microsoft / microsoft/DirectXShaderCompiler

[SPIR-V] Not all unnecessary bindings are eliminated using SPIR-V backend

Open
#3,927 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

spirv
Dominant language
C++
Stars
3.7k
Forks
900
Avg merge
2d 11h
Merged PRs (30d)
44

Description

Consider following HLSL

struct PixelInput
{
	float4 pos : SV_Position0;
	float2 texCoord : TEXCOORD0;
};

Texture2D Tex0;
SamplerState SS0;
Texture2D Tex1;
SamplerState SS1;

float4 main(in PixelInput In) : SV_Target0
{
	const float2 val = Tex0.Sample(SS0, In.texCoord).xy;
	if (((val.x == 0.0f) && (val.y == 0.0f)))
	{
		clip(-1.0f);
	}
	clip(-0.5f);
	return Tex1.Sample(SS1, In.texCoord);
}

and following compilation command: dxc -T ps_6_0 -spirv test.hlsl -Fo test.spv
Output of the spirv-dis test.spv will be

; SPIR-V
; Version: 1.0
; Generator: Google spiregg; 0
; Bound: 35
; Schema: 0
               OpCapability Shader
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %main "main" %gl_FragCoord %in_var_TEXCOORD0 %out_var_SV_Target0
               OpExecutionMode %main OriginUpperLeft
               OpSource HLSL 600
               OpName %type_2d_image "type.2d.image"
               OpName %Tex0 "Tex0"
               OpName %type_sampler "type.sampler"
               OpName %SS0 "SS0"
               OpName %in_var_TEXCOORD0 "in.var.TEXCOORD0"
               OpName %out_var_SV_Target0 "out.var.SV_Target0"
               OpName %main "main"
               OpName %type_sampled_image "type.sampled.image"
               OpDecorate %gl_FragCoord BuiltIn FragCoord
               OpDecorate %in_var_TEXCOORD0 Location 0
               OpDecorate %out_var_SV_Target0 Location 0
               OpDecorate %Tex0 DescriptorSet 0
               OpDecorate %Tex0 Binding 0
               OpDecorate %SS0 DescriptorSet 0
               OpDecorate %SS0 Binding 1
      %float = OpTypeFloat 32
    %float_0 = OpConstant %float 0
%type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
%type_sampler = OpTypeSampler
%_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
    %v4float = OpTypeVector %float 4
%_ptr_Input_v4float = OpTypePointer Input %v4float
    %v2float = OpTypeVector %float 2
%_ptr_Input_v2float = OpTypePointer Input %v2float
%_ptr_Output_v4float = OpTypePointer Output %v4float
       %void = OpTypeVoid
         %20 = OpTypeFunction %void
%type_sampled_image = OpTypeSampledImage %type_2d_image
       %bool = OpTypeBool
       %Tex0 = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
        %SS0 = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
%in_var_TEXCOORD0 = OpVariable %_ptr_Input_v2float Input
%out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
       %main = OpFunction %void None %20
         %22 = OpLabel
         %23 = OpLoad %v2float %in_var_TEXCOORD0
         %24 = OpLoad %type_2d_image %Tex0
         %25 = OpLoad %type_sampler %SS0
         %26 = OpSampledImage %type_sampled_image %24 %25
         %27 = OpImageSampleImplicitLod %v4float %26 %23 None
         %28 = OpCompositeExtract %float %27 0
         %29 = OpFOrdEqual %bool %28 %float_0
         %30 = OpCompositeExtract %float %27 1
         %31 = OpFOrdEqual %bool %30 %float_0
         %32 = OpLogicalAnd %bool %29 %31
               OpSelectionMerge %33 None
               OpBranchConditional %32 %34 %33
         %34 = OpLabel
               OpKill
         %33 = OpLabel
               OpKill
               OpFunctionEnd

Tex1 and SS1 were eliminated (as unreachable I guess) but Tex0 and SS0 are still here while results of the sampling are not really used -- both branches end up in OpKill, so sampling could be removed and so Tex0 and SS0 could be removed too... ...and whole shader could be collapsed to the single OpKill 😄

Tested on dxc_2021_07_01.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the issue with dxc -T ps_6_0 -spirv test.hlsl -Fo test.spv, then inspect the SPIR-V backend's handling of dead code and resource elimination. Use spirv-dis on the output to verify that the unused sampling and bindings are removed and that the shader is reduced to the terminating operation.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.