conditional statement is not translated to SPIR-V correctly
The following glsl function:
void clip(vec4 x)
{
if (x.x < 0.0 || x.y < 0.0 || x.z < 0.0 || x.w < 0.0)
discard;
}
Yields this SPIR-V code:
%clip_vf4_ = OpFunction %void None %24
%x_0 = OpFunctionParameter %_ptr_Function_v4float
%27 = OpLabel
%119 = OpAccessChain %_ptr_Function_float %x_0 %uint_0
%120 = OpLoad %float %119
%121 = OpFOrdLessThan %bool %120 %float_0
%122 = OpLogicalNot %bool %121
OpSelectionMerge %124 None
OpBranchConditional %122 %123 %124
%123 = OpLabel
%125 = OpAccessChain %_ptr_Function_float %x_0 %uint_1
%126 = OpLoad %float %125
%127 = OpFOrdLessThan %bool %126 %float_0
OpBranch %124
%124 = OpLabel
%128 = OpPhi %bool %121 %27 %127 %123
%129 = OpLogicalNot %bool %128
OpSelectionMerge %131 None
OpBranchConditional %129 %130 %131
%130 = OpLabel
%132 = OpAccessChain %_ptr_Function_float %x_0 %uint_2
%133 = OpLoad %float %132
%134 = OpFOrdLessThan %bool %133 %float_0
OpBranch %131
%131 = OpLabel
%135 = OpPhi %bool %128 %124 %134 %130
%136 = OpLogicalNot %bool %135
OpSelectionMerge %138 None
OpBranchConditional %136 %137 %138
%137 = OpLabel
%140 = OpAccessChain %_ptr_Function_float %x_0 %uint_3
%141 = OpLoad %float %140
%142 = OpFOrdLessThan %bool %141 %float_0
OpBranch %138
%138 = OpLabel
%143 = OpPhi %bool %135 %131 %142 %137
OpSelectionMerge %145 None
OpBranchConditional %143 %144 %145
%144 = OpLabel
OpKill
%145 = OpLabel
OpReturn
OpFunctionEnd
Executing this function with the value clip(vec4(-0.5, 1, 1, 1)); results in the fragment not being discarded, even though the x value is less than zero.
If I rewrite the glsl function, to the logically equivalent:
void clip(vec4 x)
{
if (x.x < 0.0)
discard;
else if (x.y < 0.0)
discard;
else if (x.z < 0.0)
discard;
else if (x.w < 0.0)
discard;
}
It will yield this SPIR-V code:
%clip_vf4_ = OpFunction %void None %24
%x_0 = OpFunctionParameter %_ptr_Function_v4float
%27 = OpLabel
%119 = OpAccessChain %_ptr_Function_float %x_0 %uint_0
%120 = OpLoad %float %119
%121 = OpFOrdLessThan %bool %120 %float_0
OpSelectionMerge %123 None
OpBranchConditional %121 %122 %125
%122 = OpLabel
OpKill
%125 = OpLabel
%126 = OpAccessChain %_ptr_Function_float %x_0 %uint_1
%127 = OpLoad %float %126
%128 = OpFOrdLessThan %bool %127 %float_0
OpSelectionMerge %130 None
OpBranchConditional %128 %129 %132
%129 = OpLabel
OpKill
%132 = OpLabel
%133 = OpAccessChain %_ptr_Function_float %x_0 %uint_2
%134 = OpLoad %float %133
%135 = OpFOrdLessThan %bool %134 %float_0
OpSelectionMerge %137 None
OpBranchConditional %135 %136 %139
%136 = OpLabel
OpKill
%139 = OpLabel
%141 = OpAccessChain %_ptr_Function_float %x_0 %uint_3
%142 = OpLoad %float %141
%143 = OpFOrdLessThan %bool %142 %float_0
OpSelectionMerge %145 None
OpBranchConditional %143 %144 %145
%144 = OpLabel
OpKill
%145 = OpLabel
OpBranch %137
%137 = OpLabel
OpBranch %130
%130 = OpLabel
OpBranch %123
%123 = OpLabel
OpReturn
OpFunctionEnd
Executing this new version of the function with the value clip(vec4(-0.5, 1, 1, 1)); results in the fragment being discarded as expected.
Is something wrong with the first glsl function, or is this something that should be corrected ?
This is likely a SPIRV-Cross bug, not a shaderc bug, since the actual translation logic is implemented there. Unless of course this is something that we are doing wrong when invoking spirv-cross. Sending dneto0 to triage, since he owns this side of the repo more. This might a good starter bug?