microsoft / DirectXShaderCompiler

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

[SPIR-V] How to keep unused variable #4567

Closed SJTU-Lucy closed 1 year ago

SJTU-Lucy commented 1 year ago

For some reason, I want to reserve all the variables of a struct although some of them is not used. The hlsl code is like:

 struct PS_INPUT 
{
 float4 final_position : SV_Position;
 float4 texcoord0 : TEXCOORD0;
 float4 texcoord1 : TEXCOORD1;
 float4 world_position : TEXCOORD2;
 float4 world_normal : TEXCOORD3;
 half4 vertex_light : TEXCOORD6;
 half4 fog_info : TEXCOORD8;
 float3 world_tangent : TEXCOORD4;
 float3 world_binormal : TEXCOORD5;
 float4 pos_light : TEXCOORD9;
 half4 point_light : TEXCOORD7;
 half4 env_light : TEXCOORD10;
 float3 parallax : TEXCOORD11;
 };

The current output is like:

struct SPIRV_Cross_Input
{
    float4 in_var_TEXCOORD0 : TEXCOORD0;
    float4 in_var_TEXCOORD2 : TEXCOORD2;
    float4 in_var_TEXCOORD3 : TEXCOORD3;
    float4 in_var_TEXCOORD6 : TEXCOORD4;
    float4 in_var_TEXCOORD8 : TEXCOORD5;
    float4 in_var_TEXCOORD9 : TEXCOORD8;
    float4 in_var_TEXCOORD7 : TEXCOORD9;
    float4 in_var_TEXCOORD10 : TEXCOORD10;
};

I wonder if there is a way to keep TEXCOORD1, 4, 5, 11.

pow2clk commented 1 year ago

Hi @SJTU-Lucy!

From the output you provide, it looks like you are using https://github.com/KhronosGroup/SPIRV-Cross? If so, perhaps the bug should be filed there unless you can identify that the spirv backend of DXC is what is removing the unused inputs.

Regardless, I'm tagging this as SPIRV. @vettoreldaniele for visibility

SJTU-Lucy commented 1 year ago

Hi @pow2clk! From the .spv file that DXC generates, it could be seen that the variables are already removed.

in.var.TEXCOORD0
in.var.TEXCOORD2
in.var.TEXCOORD3
in.var.TEXCOORD6
in.var.TEXCOORD8
in.var.TEXCOORD9
in.var.TEXCOORD7
in.var.TEXCOORD10
out.var.SV_Target0
vettoreldaniele commented 1 year ago

Hi @SJTU-Lucy!

As suggested by @pow2clk, can you check whether the DXIL backend also removes the unused variables? If that's the case, the SPIR-V backend is likely not the culprit here. If you can, please provide a minimal input shader that we can use to reproduce.

SJTU-Lucy commented 1 year ago

Hi @vettoreldaniele! I have tested it in DXIL, and it's true that DXIL didn't remove the unused variables. So I think maybe that happens in SPIR-V backend.

SJTU-Lucy commented 1 year ago

A brief example can be like this:

struct VS_INPUT 
{
 float4 texcoord0 : TEXCOORD0;
 float4 texcoord1 : TEXCOORD1;
 };
struct PS_INPUT 
{
 float texcoord0 : TEXCOORD0;
 float texcoord1 : TEXCOORD1;
 };

PS_INPUT vs_main(VS_INPUT input) 
{
 PS_INPUT output = (PS_INPUT) 0;
 output.texcoord0 = 0.0;
 output.texcoord1 = 1.0;
 return output;
}
float4 ps_main(PS_INPUT input) : SV_Target0 
{
 PS_INPUT output = (PS_INPUT) 0;
 output.texcoord0 = input.texcoord0;
 return float4(output.texcoord0, output.texcoord0, output.texcoord0, output.texcoord0);
 }

When using ps as entry:

               OpCapability Shader
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %ps_main "ps_main" %in_var_TEXCOORD0 %out_var_SV_Target0
               OpExecutionMode %ps_main OriginUpperLeft
               OpSource HLSL 600
               OpName %in_var_TEXCOORD0 "in.var.TEXCOORD0"
               OpName %out_var_SV_Target0 "out.var.SV_Target0"
               OpName %ps_main "ps_main"
               OpDecorate %in_var_TEXCOORD0 Location 0
               OpDecorate %out_var_SV_Target0 Location 0

While for vs:

               OpCapability Shader
               OpMemoryModel Logical GLSL450
               OpEntryPoint Vertex %vs_main "vs_main" %out_var_TEXCOORD0 %out_var_TEXCOORD1
               OpSource HLSL 600
               OpName %out_var_TEXCOORD0 "out.var.TEXCOORD0"
               OpName %out_var_TEXCOORD1 "out.var.TEXCOORD1"
               OpName %vs_main "vs_main"
               OpDecorate %out_var_TEXCOORD0 Location 0
               OpDecorate %out_var_TEXCOORD1 Location 1
s-perron commented 1 year ago

The dead code elimination pass already has an options to preserve the interface variables. However, that options is not exposed in the legalization and optimization passes. If we want to do this we would:

s-perron commented 1 year ago

@SJTU-Lucy I will not be able to implement this myself, but I can review code if you want to contribute it.

SJTU-Lucy commented 1 year ago

omg thank you very much @s-perron ! This really helps!

kirill146 commented 1 year ago

I also have the same issue when I try to convert compiled SIPR-V back to HLSL. Recently the option for preserving interface was added to SPIRV-Tools, so now it's only a matter of creating a CLI option in DXC. I think I can make a PR for this.