DirectXShaderCompiler icon indicating copy to clipboard operation
DirectXShaderCompiler copied to clipboard

[SPIR-V] Specialization constants don't work if the shader uses the implicit Globals UBO

Open Dredhog opened this issue 3 years ago • 0 comments

Title

[SPIR-V] Specialization constants don't work if the shader uses the implicit Globals UBO

Functional impact

Specialization constants get placed into the $Globals UBO as regular constants when the $Globals UBO is present. This is incorrect and makes them practically unusable.

Minimal repro steps

  1. Compile the following shader with dxc.exe -T ps_6_0 -E main -spirv repro_shader.txt:
[[ vk::constant_id ( 1 )]] const int mySpecializationConstant = 0;

//cbuffer NamedCBuffer {
float myGlobal;
//};

float4 main(float4 col : COLOR) : SV_Target0
{
	if(mySpecializationConstant)
		return 0.xxxx;
	
	return myGlobal.xxxx;
}

Expected result

The SPIR-V should contain a specialization constant named mySpecializationConstant and the $Globals UBO should contain only one member named myGlobal

Actual result

The SPIR-V doesn't contain any specialization constants and it places mySpecializationConstant into the $Globals UBO (see full output in spec_constant_simple_repro.spv.txt):

               OpName %type__Globals "type.$Globals"
               OpMemberName %type__Globals 0 "mySpecializationConstant"
               OpMemberName %type__Globals 1 "myGlobal"
               OpName %_Globals "$Globals"
               OpName %out_var_SV_Target0 "out.var.SV_Target0"
               OpName %main "main"
               OpDecorate %out_var_SV_Target0 Location 0
               OpDecorate %_Globals DescriptorSet 0
               OpDecorate %_Globals Binding 0
               OpMemberDecorate %type__Globals 0 Offset 0
               OpMemberDecorate %type__Globals 1 Offset 4
               OpDecorate %type__Globals Block

Also, the compiler produces a warning pointing to the wrong name myGlobal:

spec_constant_simple_repro.txt:1:65: warning: variable 'myGlobal' will be placed in $Globals so initializer ignored
[[ vk::constant_id ( 1 )]] const int mySpecializationConstant = 0;
                                                                ^

Further technical details

  • Used DXC from the latest official built release v1.6.2112
  • Placing the constant myGlobal into a named cbuffer (as is commented out in the repro shader) instead of into the implicit $Globals cbuffer fixes the issue

Dredhog avatar Jul 05 '22 16:07 Dredhog