I'm currently writing an vulkan application and got in some trouble when using specialization constants. An array of vec4 is not visible in Renderdoc, which i use to debug my application, as long I'm using specialization constants as size of that array instead of other constant values. Renderdoc shows me, that te current value of the specialication constant is 1;
I'm using an Nvidea GTX 880M and compiled my code with the LunarG glaslangvalidator. When I directly insert the specialization constant as array size no error occures, but when I apply mathematical operations, i.e. add 0, the constant becomes 0.
Here the code in GLSL like it was generated from compiled code by renderdoc:
#version 450
layout(constant_id = 2) const int TEXTURE_COORDS_COUNT = 1;
const int _61 = (0 + TEXTURE_COORDS_COUNT);
const int _63 = (TEXTURE_COORDS_COUNT / 4);
const int _64 = (_61 - _63);
const int specialSize = (0 + TEXTURE_COORDS_COUNT);
layout(set = 0, binding = 0, std140) uniform cameraUniform
{
mat4 perspectiveView;
} cu;
layout(location = 0) in mat4 instanceTransformation;
layout(location = 4) in vec3 inPosition;
layout(location = 0) out vec4 fragNormals;
layout(location = 5) in vec3 inNormals;
layout(location = 1) out vec4 fragSpecial[specialSize];
layout(location = 6) in vec4 inSpecial[specialSize];
void main()
{
gl_Position = (cu.perspectiveView * instanceTransformation) * vec4(inPosition, 1.0);
fragNormals = (cu.perspectiveView * instanceTransformation) * vec4(inNormals, 0.0);
for (int i = 0; i < _64; i++)
{
fragSpecial[i] = inSpecial[i];
}
}
Here spir-v code generated by Renderdoc:
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 7
; Bound: 82
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %main "main" %_ %instanceTransformation %inPosition %fragNormals %inNormals %fragSpecial %inSpecial
OpSource GLSL 450
OpSourceExtension "GL_ARB_separate_shader_objects"
OpName %main "main"
OpName %gl_PerVertex "gl_PerVertex"
OpMemberName %gl_PerVertex 0 "gl_Position"
OpMemberName %gl_PerVertex 1 "gl_PointSize"
OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
OpMemberName %gl_PerVertex 3 "gl_CullDistance"
OpName %_ ""
OpName %cameraUniform "cameraUniform"
OpMemberName %cameraUniform 0 "perspectiveView"
OpName %cu "cu"
OpName %instanceTransformation "instanceTransformation"
OpName %inPosition "inPosition"
OpName %fragNormals "fragNormals"
OpName %inNormals "inNormals"
OpName %i "i"
OpName %TEXTURE_COORDS_COUNT "TEXTURE_COORDS_COUNT"
OpName %specialSize "specialSize"
OpName %fragSpecial "fragSpecial"
OpName %inSpecial "inSpecial"
OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
OpDecorate %gl_PerVertex Block
OpMemberDecorate %cameraUniform 0 ColMajor
OpMemberDecorate %cameraUniform 0 Offset 0
OpMemberDecorate %cameraUniform 0 MatrixStride 16
OpDecorate %cameraUniform Block
OpDecorate %cu DescriptorSet 0
OpDecorate %cu Binding 0
OpDecorate %instanceTransformation Location 0
OpDecorate %inPosition Location 4
OpDecorate %fragNormals Location 0
OpDecorate %inNormals Location 5
OpDecorate %TEXTURE_COORDS_COUNT SpecId 2
OpDecorate %fragSpecial Location 1
OpDecorate %inSpecial Location 6
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%uint = OpTypeInt 32 0
%uint_1 = OpConstant %uint 1
%_arr_float_uint_1 = OpTypeArray %float %uint_1
%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
%_ = OpVariable %_ptr_Output_gl_PerVertex Output
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%mat4v4float = OpTypeMatrix %v4float 4
%cameraUniform = OpTypeStruct %mat4v4float
%_ptr_Uniform_cameraUniform = OpTypePointer Uniform %cameraUniform
%cu = OpVariable %_ptr_Uniform_cameraUniform Uniform
%_ptr_Uniform_mat4v4float = OpTypePointer Uniform %mat4v4float
%_ptr_Input_mat4v4float = OpTypePointer Input %mat4v4float
%instanceTransformation = OpVariable %_ptr_Input_mat4v4float Input
%v3float = OpTypeVector %float 3
%_ptr_Input_v3float = OpTypePointer Input %v3float
%inPosition = OpVariable %_ptr_Input_v3float Input
%float_1 = OpConstant %float 1
%_ptr_Output_v4float = OpTypePointer Output %v4float
%fragNormals = OpVariable %_ptr_Output_v4float Output
%inNormals = OpVariable %_ptr_Input_v3float Input
%float_0 = OpConstant %float 0
%_ptr_Function_int = OpTypePointer Function %int
%TEXTURE_COORDS_COUNT = OpSpecConstant %int 1
%61 = OpSpecConstantOp %int IAdd %int_0 %TEXTURE_COORDS_COUNT
%int_4 = OpConstant %int 4
%63 = OpSpecConstantOp %int SDiv %TEXTURE_COORDS_COUNT %int_4
%64 = OpSpecConstantOp %int ISub %61 %63
%bool = OpTypeBool
%specialSize = OpSpecConstantOp %int IAdd %int_0 %TEXTURE_COORDS_COUNT
%_arr_v4float_specialSize = OpTypeArray %v4float %specialSize
%_ptr_Output__arr_v4float_specialSize = OpTypePointer Output %_arr_v4float_specialSize
%fragSpecial = OpVariable %_ptr_Output__arr_v4float_specialSize Output
%_ptr_Input__arr_v4float_specialSize = OpTypePointer Input %_arr_v4float_specialSize
%inSpecial = OpVariable %_ptr_Input__arr_v4float_specialSize Input
%_ptr_Input_v4float = OpTypePointer Input %v4float
%int_1 = OpConstant %int 1
%main = OpFunction %void None %3
%5 = OpLabel
%i = OpVariable %_ptr_Function_int Function
%21 = OpAccessChain %_ptr_Uniform_mat4v4float %cu %int_0
%22 = OpLoad %mat4v4float %21
%25 = OpLoad %mat4v4float %instanceTransformation
%26 = OpMatrixTimesMatrix %mat4v4float %22 %25
%30 = OpLoad %v3float %inPosition
%32 = OpCompositeExtract %float %30 0
%33 = OpCompositeExtract %float %30 1
%34 = OpCompositeExtract %float %30 2
%35 = OpCompositeConstruct %v4float %32 %33 %34 %float_1
%36 = OpMatrixTimesVector %v4float %26 %35
%38 = OpAccessChain %_ptr_Output_v4float %_ %int_0
OpStore %38 %36
%40 = OpAccessChain %_ptr_Uniform_mat4v4float %cu %int_0
%41 = OpLoad %mat4v4float %40
%42 = OpLoad %mat4v4float %instanceTransformation
%43 = OpMatrixTimesMatrix %mat4v4float %41 %42
%45 = OpLoad %v3float %inNormals
%47 = OpCompositeExtract %float %45 0
%48 = OpCompositeExtract %float %45 1
%49 = OpCompositeExtract %float %45 2
%50 = OpCompositeConstruct %v4float %47 %48 %49 %float_0
%51 = OpMatrixTimesVector %v4float %43 %50
OpStore %fragNormals %51
OpStore %i %int_0
OpBranch %54
%54 = OpLabel
OpLoopMerge %56 %57 None
OpBranch %58
%58 = OpLabel
%59 = OpLoad %int %i
%66 = OpSLessThan %bool %59 %64
OpBranchConditional %66 %55 %56
%55 = OpLabel
%71 = OpLoad %int %i
%74 = OpLoad %int %i
%76 = OpAccessChain %_ptr_Input_v4float %inSpecial %74
%77 = OpLoad %v4float %76
%78 = OpAccessChain %_ptr_Output_v4float %fragSpecial %71
OpStore %78 %77
OpBranch %57
%57 = OpLabel
%79 = OpLoad %int %i
%81 = OpIAdd %int %79 %int_1
OpStore %i %81
OpBranch %54
%56 = OpLabel
OpReturn
OpFunctionEnd
Here the working code:
#version 450
layout(constant_id = 2) const int specialSize = 1;
const int _61 = (0 + specialSize);
const int _63 = (specialSize / 4);
const int _64 = (_61 - _63);
layout(set = 0, binding = 0, std140) uniform cameraUniform
{
mat4 perspectiveView;
} cu;
layout(location = 0) in mat4 instanceTransformation;
layout(location = 4) in vec3 inPosition;
layout(location = 0) out vec4 fragNormals;
layout(location = 5) in vec3 inNormals;
layout(location = 1) out vec4 fragSpecial[specialSize];
layout(location = 6) in vec4 inSpecial[specialSize];
void main()
{
gl_Position = (cu.perspectiveView * instanceTransformation) * vec4(inPosition, 1.0);
fragNormals = (cu.perspectiveView * instanceTransformation) * vec4(inNormals, 0.0);
for (int i = 0; i < _64; i++)
{
fragSpecial[i] = inSpecial[i];
}
}
And its spir-v code:
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 7
; Bound: 81
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %main "main" %_ %instanceTransformation %inPosition %fragNormals %inNormals %fragSpecial %inSpecial
OpSource GLSL 450
OpSourceExtension "GL_ARB_separate_shader_objects"
OpName %main "main"
OpName %gl_PerVertex "gl_PerVertex"
OpMemberName %gl_PerVertex 0 "gl_Position"
OpMemberName %gl_PerVertex 1 "gl_PointSize"
OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
OpMemberName %gl_PerVertex 3 "gl_CullDistance"
OpName %_ ""
OpName %cameraUniform "cameraUniform"
OpMemberName %cameraUniform 0 "perspectiveView"
OpName %cu "cu"
OpName %instanceTransformation "instanceTransformation"
OpName %inPosition "inPosition"
OpName %fragNormals "fragNormals"
OpName %inNormals "inNormals"
OpName %i "i"
OpName %TEXTURE_COORDS_COUNT "TEXTURE_COORDS_COUNT"
OpName %TEXTURE_COORDS_COUNT "specialSize"
OpName %fragSpecial "fragSpecial"
OpName %inSpecial "inSpecial"
OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
OpDecorate %gl_PerVertex Block
OpMemberDecorate %cameraUniform 0 ColMajor
OpMemberDecorate %cameraUniform 0 Offset 0
OpMemberDecorate %cameraUniform 0 MatrixStride 16
OpDecorate %cameraUniform Block
OpDecorate %cu DescriptorSet 0
OpDecorate %cu Binding 0
OpDecorate %instanceTransformation Location 0
OpDecorate %inPosition Location 4
OpDecorate %fragNormals Location 0
OpDecorate %inNormals Location 5
OpDecorate %TEXTURE_COORDS_COUNT SpecId 2
OpDecorate %fragSpecial Location 1
OpDecorate %inSpecial Location 6
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%uint = OpTypeInt 32 0
%uint_1 = OpConstant %uint 1
%_arr_float_uint_1 = OpTypeArray %float %uint_1
%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
%_ = OpVariable %_ptr_Output_gl_PerVertex Output
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%mat4v4float = OpTypeMatrix %v4float 4
%cameraUniform = OpTypeStruct %mat4v4float
%_ptr_Uniform_cameraUniform = OpTypePointer Uniform %cameraUniform
%cu = OpVariable %_ptr_Uniform_cameraUniform Uniform
%_ptr_Uniform_mat4v4float = OpTypePointer Uniform %mat4v4float
%_ptr_Input_mat4v4float = OpTypePointer Input %mat4v4float
%instanceTransformation = OpVariable %_ptr_Input_mat4v4float Input
%v3float = OpTypeVector %float 3
%_ptr_Input_v3float = OpTypePointer Input %v3float
%inPosition = OpVariable %_ptr_Input_v3float Input
%float_1 = OpConstant %float 1
%_ptr_Output_v4float = OpTypePointer Output %v4float
%fragNormals = OpVariable %_ptr_Output_v4float Output
%inNormals = OpVariable %_ptr_Input_v3float Input
%float_0 = OpConstant %float 0
%_ptr_Function_int = OpTypePointer Function %int
%TEXTURE_COORDS_COUNT = OpSpecConstant %int 1
%61 = OpSpecConstantOp %int IAdd %int_0 %TEXTURE_COORDS_COUNT
%int_4 = OpConstant %int 4
%63 = OpSpecConstantOp %int SDiv %TEXTURE_COORDS_COUNT %int_4
%64 = OpSpecConstantOp %int ISub %61 %63
%bool = OpTypeBool
%_arr_v4float_TEXTURE_COORDS_COUNT = OpTypeArray %v4float %TEXTURE_COORDS_COUNT
%_ptr_Output__arr_v4float_TEXTURE_COORDS_COUNT = OpTypePointer Output %_arr_v4float_TEXTURE_COORDS_COUNT
%fragSpecial = OpVariable %_ptr_Output__arr_v4float_TEXTURE_COORDS_COUNT Output
%_ptr_Input__arr_v4float_TEXTURE_COORDS_COUNT = OpTypePointer Input %_arr_v4float_TEXTURE_COORDS_COUNT
%inSpecial = OpVariable %_ptr_Input__arr_v4float_TEXTURE_COORDS_COUNT Input
%_ptr_Input_v4float = OpTypePointer Input %v4float
%int_1 = OpConstant %int 1
%main = OpFunction %void None %3
%5 = OpLabel
%i = OpVariable %_ptr_Function_int Function
%21 = OpAccessChain %_ptr_Uniform_mat4v4float %cu %int_0
%22 = OpLoad %mat4v4float %21
%25 = OpLoad %mat4v4float %instanceTransformation
%26 = OpMatrixTimesMatrix %mat4v4float %22 %25
%30 = OpLoad %v3float %inPosition
%32 = OpCompositeExtract %float %30 0
%33 = OpCompositeExtract %float %30 1
%34 = OpCompositeExtract %float %30 2
%35 = OpCompositeConstruct %v4float %32 %33 %34 %float_1
%36 = OpMatrixTimesVector %v4float %26 %35
%38 = OpAccessChain %_ptr_Output_v4float %_ %int_0
OpStore %38 %36
%40 = OpAccessChain %_ptr_Uniform_mat4v4float %cu %int_0
%41 = OpLoad %mat4v4float %40
%42 = OpLoad %mat4v4float %instanceTransformation
%43 = OpMatrixTimesMatrix %mat4v4float %41 %42
%45 = OpLoad %v3float %inNormals
%47 = OpCompositeExtract %float %45 0
%48 = OpCompositeExtract %float %45 1
%49 = OpCompositeExtract %float %45 2
%50 = OpCompositeConstruct %v4float %47 %48 %49 %float_0
%51 = OpMatrixTimesVector %v4float %43 %50
OpStore %fragNormals %51
OpStore %i %int_0
OpBranch %54
%54 = OpLabel
OpLoopMerge %56 %57 None
OpBranch %58
%58 = OpLabel
%59 = OpLoad %int %i
%66 = OpSLessThan %bool %59 %64
OpBranchConditional %66 %55 %56
%55 = OpLabel
%70 = OpLoad %int %i
%73 = OpLoad %int %i
%75 = OpAccessChain %_ptr_Input_v4float %inSpecial %73
%76 = OpLoad %v4float %75
%77 = OpAccessChain %_ptr_Output_v4float %fragSpecial %70
OpStore %77 %76
OpBranch %57
%57 = OpLabel
%78 = OpLoad %int %i
%80 = OpIAdd %int %78 %int_1
OpStore %i %80
OpBranch %54
%56 = OpLabel
OpReturn
OpFunctionEnd
specialSize should be 1 (like it is in the working example), but is 0. Thanks for your help!
EDIT:
If noone can figure out the problem, maybe someone can tell me if this is a bug and where I have to report it so that it will be fixed.
EDIT:
Seems like Renderdoc contains a bug which did not calculate some values at the right time.