Support ternary expressions in OpSpecConstantOp.
This commit is contained in:
Родитель
7607eb6923
Коммит
ffa9133d77
|
@ -0,0 +1,23 @@
|
|||
static const uint s = 10u;
|
||||
static const bool _13 = (s > 20u);
|
||||
static const uint _16 = _13 ? 30u : 50u;
|
||||
|
||||
static float FragColor;
|
||||
|
||||
struct SPIRV_Cross_Output
|
||||
{
|
||||
float FragColor : SV_Target0;
|
||||
};
|
||||
|
||||
void frag_main()
|
||||
{
|
||||
FragColor = float(_16);
|
||||
}
|
||||
|
||||
SPIRV_Cross_Output main()
|
||||
{
|
||||
frag_main();
|
||||
SPIRV_Cross_Output stage_output;
|
||||
stage_output.FragColor = FragColor;
|
||||
return stage_output;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
constant uint s_tmp [[function_constant(0)]];
|
||||
constant uint s = is_function_constant_defined(s_tmp) ? s_tmp : 10u;
|
||||
constant bool _13 = (s > 20u);
|
||||
constant uint _16 = _13 ? 30u : 50u;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0()
|
||||
{
|
||||
main0_out out = {};
|
||||
out.FragColor = float(_16);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) out float FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = float((10u > 20u) ? 30u : 50u);
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#version 450
|
||||
|
||||
layout(constant_id = 0) const uint s = 10u;
|
||||
const bool _13 = (s > 20u);
|
||||
const uint _16 = _13 ? 30u : 50u;
|
||||
|
||||
layout(location = 0) out float FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = float(_16);
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
static const uint s = 10u;
|
||||
static const bool _13 = (s > 20u);
|
||||
static const uint _16 = _13 ? 30u : 50u;
|
||||
|
||||
static float FragColor;
|
||||
|
||||
struct SPIRV_Cross_Output
|
||||
{
|
||||
float FragColor : SV_Target0;
|
||||
};
|
||||
|
||||
void frag_main()
|
||||
{
|
||||
FragColor = float(_16);
|
||||
}
|
||||
|
||||
SPIRV_Cross_Output main()
|
||||
{
|
||||
frag_main();
|
||||
SPIRV_Cross_Output stage_output;
|
||||
stage_output.FragColor = FragColor;
|
||||
return stage_output;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
constant uint s_tmp [[function_constant(0)]];
|
||||
constant uint s = is_function_constant_defined(s_tmp) ? s_tmp : 10u;
|
||||
constant bool _13 = (s > 20u);
|
||||
constant uint _16 = _13 ? 30u : 50u;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0()
|
||||
{
|
||||
main0_out out = {};
|
||||
out.FragColor = float(_16);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) out float FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = float((10u > 20u) ? 30u : 50u);
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#version 450
|
||||
|
||||
layout(constant_id = 0) const uint s = 10u;
|
||||
const bool _13 = (s > 20u);
|
||||
const uint _16 = _13 ? 30u : 50u;
|
||||
|
||||
layout(location = 0) out float FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = float(_16);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#version 450
|
||||
layout(location = 0) out float FragColor;
|
||||
layout(constant_id = 0) const uint s = 10u;
|
||||
const uint f = s > 20u ? 30u : 50u;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = float(f);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#version 450
|
||||
layout(location = 0) out float FragColor;
|
||||
layout(constant_id = 0) const uint s = 10u;
|
||||
const uint f = s > 20u ? 30u : 50u;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = float(f);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#version 450
|
||||
layout(location = 0) out float FragColor;
|
||||
layout(constant_id = 0) const uint s = 10u;
|
||||
const uint f = s > 20u ? 30u : 50u;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = float(f);
|
||||
}
|
|
@ -2553,11 +2553,14 @@ string CompilerGLSL::constant_op_expression(const SPIRConstantOp &cop)
|
|||
// In order to preserve its compile-time constness in Vulkan GLSL,
|
||||
// we need to reduce the OpSelect expression back to this simplified model.
|
||||
// If we cannot, fail.
|
||||
if (!to_trivial_mix_op(type, op, cop.arguments[2], cop.arguments[1], cop.arguments[0]))
|
||||
if (to_trivial_mix_op(type, op, cop.arguments[2], cop.arguments[1], cop.arguments[0]))
|
||||
{
|
||||
SPIRV_CROSS_THROW(
|
||||
"Cannot implement specialization constant op OpSelect. "
|
||||
"Need trivial select implementation which can be resolved to a simple cast from boolean.");
|
||||
// Implement as a simple cast down below.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Implement a ternary and pray the compiler understands it :)
|
||||
return to_ternary_expression(type, cop.arguments[0], cop.arguments[1], cop.arguments[2]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3578,6 +3581,37 @@ bool CompilerGLSL::to_trivial_mix_op(const SPIRType &type, string &op, uint32_t
|
|||
return ret;
|
||||
}
|
||||
|
||||
string CompilerGLSL::to_ternary_expression(const SPIRType &restype, uint32_t select, uint32_t true_value,
|
||||
uint32_t false_value)
|
||||
{
|
||||
string expr;
|
||||
auto &lerptype = expression_type(select);
|
||||
|
||||
if (lerptype.vecsize == 1)
|
||||
expr = join(to_enclosed_expression(select), " ? ", to_enclosed_expression(true_value), " : ",
|
||||
to_enclosed_expression(false_value));
|
||||
else
|
||||
{
|
||||
auto swiz = [this](uint32_t expression, uint32_t i) { return to_extract_component_expression(expression, i); };
|
||||
|
||||
expr = type_to_glsl_constructor(restype);
|
||||
expr += "(";
|
||||
for (uint32_t i = 0; i < restype.vecsize; i++)
|
||||
{
|
||||
expr += swiz(select, i);
|
||||
expr += " ? ";
|
||||
expr += swiz(true_value, i);
|
||||
expr += " : ";
|
||||
expr += swiz(false_value, i);
|
||||
if (i + 1 < restype.vecsize)
|
||||
expr += ", ";
|
||||
}
|
||||
expr += ")";
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
void CompilerGLSL::emit_mix_op(uint32_t result_type, uint32_t id, uint32_t left, uint32_t right, uint32_t lerp)
|
||||
{
|
||||
auto &lerptype = expression_type(lerp);
|
||||
|
@ -3608,31 +3642,7 @@ void CompilerGLSL::emit_mix_op(uint32_t result_type, uint32_t id, uint32_t left,
|
|||
// Could use GL_EXT_shader_integer_mix on desktop at least,
|
||||
// but Apple doesn't support it. :(
|
||||
// Just implement it as ternary expressions.
|
||||
string expr;
|
||||
if (lerptype.vecsize == 1)
|
||||
expr = join(to_enclosed_expression(lerp), " ? ", to_enclosed_expression(right), " : ",
|
||||
to_enclosed_expression(left));
|
||||
else
|
||||
{
|
||||
auto swiz = [this](uint32_t expression, uint32_t i) {
|
||||
return to_extract_component_expression(expression, i);
|
||||
};
|
||||
|
||||
expr = type_to_glsl_constructor(restype);
|
||||
expr += "(";
|
||||
for (uint32_t i = 0; i < restype.vecsize; i++)
|
||||
{
|
||||
expr += swiz(lerp, i);
|
||||
expr += " ? ";
|
||||
expr += swiz(right, i);
|
||||
expr += " : ";
|
||||
expr += swiz(left, i);
|
||||
if (i + 1 < restype.vecsize)
|
||||
expr += ", ";
|
||||
}
|
||||
expr += ")";
|
||||
}
|
||||
|
||||
auto expr = to_ternary_expression(get<SPIRType>(result_type), lerp, right, left);
|
||||
emit_op(result_type, id, expr, should_forward(left) && should_forward(right) && should_forward(lerp));
|
||||
inherit_expression_dependencies(id, left);
|
||||
inherit_expression_dependencies(id, right);
|
||||
|
|
|
@ -408,6 +408,9 @@ protected:
|
|||
SPIRType binary_op_bitcast_helper(std::string &cast_op0, std::string &cast_op1, SPIRType::BaseType &input_type,
|
||||
uint32_t op0, uint32_t op1, bool skip_cast_if_equal_type);
|
||||
|
||||
std::string to_ternary_expression(const SPIRType &result_type, uint32_t select, uint32_t true_value,
|
||||
uint32_t false_value);
|
||||
|
||||
void emit_unary_op(uint32_t result_type, uint32_t result_id, uint32_t op0, const char *op);
|
||||
bool expression_is_forwarded(uint32_t id);
|
||||
SPIRExpression &emit_op(uint32_t result_type, uint32_t result_id, const std::string &rhs, bool forward_rhs,
|
||||
|
|
Загрузка…
Ссылка в новой задаче