shaderc icon indicating copy to clipboard operation
shaderc copied to clipboard

Is shaderc/glslc now stripping unused inputs/outputs?

Open alecazam opened this issue 2 years ago • 6 comments

We run our GLSL shaders through glslc and then through spiv-opt. In the 6/20 and 8/20 builds of glslc and spirv-opt, the unused inputs/outputs remained, and our shaders could pass the correct data in and out. Often times, a fragment shader wouldn't use but would still declare an input to line up with the vertex output. Also I see unused vertex inputs getting stripped, and then that throws off matching those up with cpu data passed down.

As of 1.3.211.0, unused inputs/outputs are stripped. Was this a recent change, and if so, how do I disable it?

This is an example of a fragment input that is stripped away. It's easy to imagine a case where the vertex inputs are also stripped from non-use, or code that is commented out in the vertex shader. Note, this could also be a spirv-opt optimization, but I've only identified that the spriv is missing these variables.

This is mostly problematic when transpiling to HLSL SM 5.0. Our MSL transpiles look fine. Spriv running on Android is also okay.

// vs
#version 450

in vec4 a_position;
out vec3 a_worldPos;

void main()
{
   gl_position = a_position;
   a_worldPos = a_position.xyz;
}

// fs
#version 450

in vec3 a_worldPos;
layout (location = 0) out vec4 o_fragColor0;

void main()
{
    // with this commented out, the input is stripped, and vs outputs/fs inputs now have a gap
    //o_fragColor0 = float4(a_worldPos, 1.0);
    o_fragColor0 = float4(0.0);
}

alecazam avatar Apr 26 '22 22:04 alecazam

I did a diff of the old and new hlsl codegen, and the only difference I see are stripped inputs to vertex and fragment shaders. This then causes everything in the HLSL path to break that I am using. We don't even have any optimizer settings for glslc set. We let spirv-opt optimize the spirv afterwards.

I see this in Optimizer.cpp, but we're not setting this. I also don't see this in the default optimizer settings. We are very explicit about the spirv-opt settings we use.

if (pass_name == "remove-unused-interface-variables") { RegisterPass(CreateRemoveUnusedInterfaceVariablesPass()); }

We don't set -Os or -O2, but do pass these to spriv-opt

--eliminate-dead-code-aggressive --eliminate-dead-inserts --eliminate-dead-branches

alecazam avatar Apr 27 '22 16:04 alecazam

This seems to be related to --eliminate-dead-code-aggressive. If I eliminate that from our spriv-opt pass after glslc, then the inputs/outputs are not stripped.

alecazam avatar Apr 27 '22 17:04 alecazam

Of course, removing that then leaves a ton of textures/samplers which all map to the same texture/sampler register, even though only 1 out of 7 is actually in-use. I don't see a specific option to remove unused textures.

alecazam avatar Apr 27 '22 19:04 alecazam

Seems to be related to the apps passing false for "preserveInterface" field here. This is part of all the default optimizations in glslc too. And I don't see any command line option to get a ADCE and preserveInterface = true. There are some bindless calls that set this, but those aren't relevant to most shaders being generated.

Optimizer::PassToken CreateAggressiveDCEPass() {
  return MakeUnique<Optimizer::PassToken::Impl>(
      MakeUnique<opt::AggressiveDCEPass>(false));  <-
}

alecazam avatar Apr 27 '22 19:04 alecazam

Looks like this was introduced in 4b092d2 (allow ADCE to remove dead inputs) on 11/16/21, so this is a recent change. The problem is this behavior can't be disabled, and breaks shader codegen for us.

alecazam avatar Apr 27 '22 19:04 alecazam

This behaviour also breaks shader codegen for me. Is there any workaround for this?

AAstroPhysiCS avatar Jan 30 '24 18:01 AAstroPhysiCS