microsoft / DirectXShaderCompiler

This repo hosts the source for the DirectX Shader Compiler which is based on LLVM/Clang.
Other
3.04k stars 677 forks source link

[SPIR-V] Potential invalid OpKill when using HLSL clip api #6743

Closed farzonl closed 2 months ago

farzonl commented 2 months ago

There was an issue that fixed this for vulkan 1.3 here: https://github.com/microsoft/DirectXShaderCompiler/issues/5937.

Should the same fix be applied to universal 1.5?

Example code:

[numthreads(1, 1, 1)]
[shader("pixel")]
void fn( ) : SV_Target {
    float4 p1;
     clip(p1.a);
}

## Universal invocation: 
dxc clip_test.hlsl -T lib_6_8  -enable-16bit-types -spirv -fspv-target-env=universal1.5 -fcgl -O0

generates OpKill

; SPIR-V
; Version: 1.5
; Generator: Google spiregg; 0
; Bound: 22
; Schema: 0
               OpCapability MinLod
               OpCapability FragmentShaderSampleInterlockEXT
               OpCapability FragmentShaderPixelInterlockEXT
               OpCapability FragmentShaderShadingRateInterlockEXT
               OpCapability ComputeDerivativeGroupQuadsNV
               OpCapability ComputeDerivativeGroupLinearNV
               OpCapability RayQueryKHR
               OpCapability VulkanMemoryModelDeviceScope
               OpCapability GroupNonUniformPartitionedNV
               OpCapability Shader
               OpExtension "SPV_EXT_fragment_shader_interlock"
               OpExtension "SPV_NV_compute_shader_derivatives"
               OpExtension "SPV_KHR_ray_query"
               OpExtension "SPV_KHR_vulkan_memory_model"
               OpExtension "SPV_NV_shader_subgroup_partitioned"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %fn "fn"
               OpExecutionMode %fn OriginUpperLeft
               OpSource HLSL 680
               OpName %fn "fn"
               OpName %src_fn "src.fn"
               OpName %bb_entry "bb.entry"
               OpName %p1 "p1"
               OpName %if_true "if.true"
               OpName %if_merge "if.merge"
        %int = OpTypeInt 32 1
      %int_3 = OpConstant %int 3
      %float = OpTypeFloat 32
    %float_0 = OpConstant %float 0
       %void = OpTypeVoid
          %7 = OpTypeFunction %void
    %v4float = OpTypeVector %float 4
%_ptr_Function_v4float = OpTypePointer Function %v4float
%_ptr_Function_float = OpTypePointer Function %float
       %bool = OpTypeBool
         %fn = OpFunction %void None %7
          %8 = OpLabel
          %9 = OpFunctionCall %void %src_fn
               OpReturn
               OpFunctionEnd
     %src_fn = OpFunction %void None %7
   %bb_entry = OpLabel
         %p1 = OpVariable %_ptr_Function_v4float Function
         %16 = OpAccessChain %_ptr_Function_float %p1 %int_3
         %17 = OpLoad %float %16
         %19 = OpFOrdLessThan %bool %17 %float_0
               OpSelectionMerge %if_merge None
               OpBranchConditional %19 %if_true %if_merge
    %if_true = OpLabel
               OpKill
   %if_merge = OpLabel
               OpReturn
               OpFunctionEnd

However using 1.3 produces OpDemoteToHelperInvocation

SPIRV invocation:

dxc scratch/clip_test.hlsl  -T lib_6_8 -enable-16bit-types -spirv -fspv-target-env=vulkan1.3 -fcgl -O0
; SPIR-V
; Version: 1.6
; Generator: Google spiregg; 0
; Bound: 22
; Schema: 0
               OpCapability MinLod
               OpCapability FragmentShaderSampleInterlockEXT
               OpCapability FragmentShaderPixelInterlockEXT
               OpCapability FragmentShaderShadingRateInterlockEXT
               OpCapability ComputeDerivativeGroupQuadsNV
               OpCapability ComputeDerivativeGroupLinearNV
               OpCapability RayQueryKHR
               OpCapability VulkanMemoryModelDeviceScope
               OpCapability GroupNonUniformPartitionedNV
               OpCapability Shader
               OpCapability DemoteToHelperInvocation
               OpExtension "SPV_EXT_fragment_shader_interlock"
               OpExtension "SPV_NV_compute_shader_derivatives"
               OpExtension "SPV_KHR_ray_query"
               OpExtension "SPV_KHR_vulkan_memory_model"
               OpExtension "SPV_NV_shader_subgroup_partitioned"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %fn "fn"
               OpExecutionMode %fn OriginUpperLeft
               OpSource HLSL 680
               OpName %fn "fn"
               OpName %src_fn "src.fn"
               OpName %bb_entry "bb.entry"
               OpName %p1 "p1"
               OpName %if_true "if.true"
               OpName %if_merge "if.merge"
        %int = OpTypeInt 32 1
      %int_3 = OpConstant %int 3
      %float = OpTypeFloat 32
    %float_0 = OpConstant %float 0
       %void = OpTypeVoid
          %7 = OpTypeFunction %void
    %v4float = OpTypeVector %float 4
%_ptr_Function_v4float = OpTypePointer Function %v4float
%_ptr_Function_float = OpTypePointer Function %float
       %bool = OpTypeBool
         %fn = OpFunction %void None %7
          %8 = OpLabel
          %9 = OpFunctionCall %void %src_fn
               OpReturn
               OpFunctionEnd
     %src_fn = OpFunction %void None %7
   %bb_entry = OpLabel
         %p1 = OpVariable %_ptr_Function_v4float Function
         %16 = OpAccessChain %_ptr_Function_float %p1 %int_3
         %17 = OpLoad %float %16
         %19 = OpFOrdLessThan %bool %17 %float_0
               OpSelectionMerge %if_merge None
               OpBranchConditional %19 %if_true %if_merge
    %if_true = OpLabel
               OpDemoteToHelperInvocation
               OpBranch %if_merge
   %if_merge = OpLabel
               OpReturn
               OpFunctionEnd
s-perron commented 2 months ago

This is unfortunate, but no. The demote to helper function are missing before SPIR-V version 1.6, so we cannot use them in universal1.5. I would recommend adding -fspv-extension=SPV_EXT_demote_to_helper_invocation.

See https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpDemoteToHelperInvocation.