MSL: Support unordered relational operators.
The SPIR-V spec says that these check if the operands either are unordered or satisfy the given condition. So that's just what we'll do, using Metal's `isunordered()` stdlib function. Apple's optimizers ought to be able to collapse that to a single unordered compare.
This commit is contained in:
parent
e14bf77b1a
commit
d3233690cb
30
reference/shaders-msl/asm/frag/unord-relational-op.asm.frag
Normal file
30
reference/shaders-msl/asm/frag/unord-relational-op.asm.frag
Normal file
@ -0,0 +1,30 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
constant float a_tmp [[function_constant(1)]];
|
||||
constant float a = is_function_constant_defined(a_tmp) ? a_tmp : 1.0;
|
||||
constant float b_tmp [[function_constant(2)]];
|
||||
constant float b = is_function_constant_defined(b_tmp) ? b_tmp : 2.0;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0()
|
||||
{
|
||||
main0_out out = {};
|
||||
float t0 = a;
|
||||
float t1 = b;
|
||||
bool c21 = (isunordered(a, b) || a == b);
|
||||
bool c22 = (isunordered(a, b) || a != b);
|
||||
bool c23 = (isunordered(a, b) || a < b);
|
||||
bool c25 = (isunordered(a, b) || a > b);
|
||||
bool c27 = (isunordered(a, b) || a <= b);
|
||||
bool c29 = (isunordered(a, b) || a >= b);
|
||||
out.FragColor = float4(t0 + t1);
|
||||
return out;
|
||||
}
|
||||
|
77
shaders-msl/asm/frag/unord-relational-op.asm.frag
Normal file
77
shaders-msl/asm/frag/unord-relational-op.asm.frag
Normal file
@ -0,0 +1,77 @@
|
||||
; SPIR-V
|
||||
; Version: 1.3
|
||||
; Generator: Khronos Glslang Reference Front End; 7
|
||||
; Bound: 33
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %FragColor
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource ESSL 310
|
||||
OpName %main "main"
|
||||
OpName %t0 "t0"
|
||||
OpName %a "a"
|
||||
OpName %t1 "t1"
|
||||
OpName %b "b"
|
||||
OpName %c21 "c21"
|
||||
OpName %c22 "c22"
|
||||
OpName %c23 "c23"
|
||||
OpName %c25 "c25"
|
||||
OpName %c27 "c27"
|
||||
OpName %c29 "c29"
|
||||
OpName %FragColor "FragColor"
|
||||
OpDecorate %t0 RelaxedPrecision
|
||||
OpDecorate %a RelaxedPrecision
|
||||
OpDecorate %a SpecId 1
|
||||
OpDecorate %t1 RelaxedPrecision
|
||||
OpDecorate %b RelaxedPrecision
|
||||
OpDecorate %b SpecId 2
|
||||
OpDecorate %FragColor RelaxedPrecision
|
||||
OpDecorate %FragColor Location 0
|
||||
OpDecorate %29 RelaxedPrecision
|
||||
OpDecorate %30 RelaxedPrecision
|
||||
OpDecorate %31 RelaxedPrecision
|
||||
OpDecorate %32 RelaxedPrecision
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%_ptr_Function_float = OpTypePointer Function %float
|
||||
%a = OpSpecConstant %float 1
|
||||
%b = OpSpecConstant %float 2
|
||||
%bool = OpTypeBool
|
||||
%_ptr_Function_bool = OpTypePointer Function %bool
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%t0 = OpVariable %_ptr_Function_float Function
|
||||
%t1 = OpVariable %_ptr_Function_float Function
|
||||
%c21 = OpVariable %_ptr_Function_bool Function
|
||||
%c22 = OpVariable %_ptr_Function_bool Function
|
||||
%c23 = OpVariable %_ptr_Function_bool Function
|
||||
%c25 = OpVariable %_ptr_Function_bool Function
|
||||
%c27 = OpVariable %_ptr_Function_bool Function
|
||||
%c29 = OpVariable %_ptr_Function_bool Function
|
||||
OpStore %t0 %a
|
||||
OpStore %t1 %b
|
||||
%15 = OpFUnordEqual %bool %a %b
|
||||
OpStore %c21 %15
|
||||
%17 = OpFUnordNotEqual %bool %a %b
|
||||
OpStore %c22 %17
|
||||
%19 = OpFUnordLessThan %bool %a %b
|
||||
OpStore %c23 %19
|
||||
%21 = OpFUnordGreaterThan %bool %a %b
|
||||
OpStore %c25 %21
|
||||
%23 = OpFUnordLessThanEqual %bool %a %b
|
||||
OpStore %c27 %23
|
||||
%25 = OpFUnordGreaterThanEqual %bool %a %b
|
||||
OpStore %c29 %25
|
||||
%29 = OpLoad %float %t0
|
||||
%30 = OpLoad %float %t1
|
||||
%31 = OpFAdd %float %29 %30
|
||||
%32 = OpCompositeConstruct %v4float %31 %31 %31 %31
|
||||
OpStore %FragColor %32
|
||||
OpReturn
|
||||
OpFunctionEnd
|
@ -1562,6 +1562,20 @@ void CompilerMSL::emit_specialization_constants()
|
||||
statement("");
|
||||
}
|
||||
|
||||
void CompilerMSL::emit_binary_unord_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1,
|
||||
const char *op)
|
||||
{
|
||||
bool forward = should_forward(op0) && should_forward(op1);
|
||||
emit_op(result_type, result_id,
|
||||
join("(isunordered(", to_enclosed_unpacked_expression(op0), ", ", to_enclosed_unpacked_expression(op1),
|
||||
") || ", to_enclosed_unpacked_expression(op0), " ", op, " ", to_enclosed_unpacked_expression(op1),
|
||||
")"),
|
||||
forward);
|
||||
|
||||
inherit_expression_dependencies(result_id, op0);
|
||||
inherit_expression_dependencies(result_id, op1);
|
||||
}
|
||||
|
||||
// Override for MSL-specific syntax instructions
|
||||
void CompilerMSL::emit_instruction(const Instruction &instruction)
|
||||
{
|
||||
@ -1576,6 +1590,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
|
||||
#define MSL_BFOP_CAST(op, type) \
|
||||
emit_binary_func_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, opcode_is_sign_invariant(opcode))
|
||||
#define MSL_UFOP(op) emit_unary_func_op(ops[0], ops[1], ops[2], #op)
|
||||
#define MSL_UNORD_BOP(op) emit_binary_unord_op(ops[0], ops[1], ops[2], ops[3], #op)
|
||||
|
||||
auto ops = stream(instruction);
|
||||
auto opcode = static_cast<Op>(instruction.op);
|
||||
@ -1620,6 +1635,30 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
|
||||
MSL_BOP(<=);
|
||||
break;
|
||||
|
||||
case OpFUnordEqual:
|
||||
MSL_UNORD_BOP(==);
|
||||
break;
|
||||
|
||||
case OpFUnordNotEqual:
|
||||
MSL_UNORD_BOP(!=);
|
||||
break;
|
||||
|
||||
case OpFUnordGreaterThan:
|
||||
MSL_UNORD_BOP(>);
|
||||
break;
|
||||
|
||||
case OpFUnordGreaterThanEqual:
|
||||
MSL_UNORD_BOP(>=);
|
||||
break;
|
||||
|
||||
case OpFUnordLessThan:
|
||||
MSL_UNORD_BOP(<);
|
||||
break;
|
||||
|
||||
case OpFUnordLessThanEqual:
|
||||
MSL_UNORD_BOP(<=);
|
||||
break;
|
||||
|
||||
// Derivatives
|
||||
case OpDPdx:
|
||||
case OpDPdxFine:
|
||||
|
@ -276,6 +276,7 @@ public:
|
||||
void remap_constexpr_sampler(uint32_t id, const MSLConstexprSampler &sampler);
|
||||
|
||||
protected:
|
||||
void emit_binary_unord_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op);
|
||||
void emit_instruction(const Instruction &instr) override;
|
||||
void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args,
|
||||
uint32_t count) override;
|
||||
|
Loading…
Reference in New Issue
Block a user