GLSL顶点着色器已用输入属性被编译器优化移除问题咨询
问题描述
参照Sascha Willems的点光源阴影映射示例开发时,出现着色器无法接收传入顶点属性的问题。通过RenderDoc内置着色器反编译工具核查发现,GLSL编译器已将着色器所有输入属性全部优化移除:
- location 1~3对应的color、normal、uv属性未被实际使用,被优化符合预期
- location 0的position属性已在着色器代码中被调用,却仍被优化移除
对应顶点着色器代码:
#version 450 layout(location = 0) in vec3 position; layout(location = 1) in vec3 color; layout(location = 2) in vec3 normal; layout(location = 3) in vec2 uv; layout(location = 0) out vec4 outPos; struct PointLight { vec4 position; vec4 color; }; layout(set = 0, binding = 0) uniform GlobalUbo { mat4 projection; mat4 view; mat4 inverseView; vec4 ambientLightColor; PointLight pointLights[10]; int numLights; } ubo; layout(push_constant) uniform Push { mat4 modelMatrix; mat4 viewMatrix; } push; void main() { vec4 positionWorld = push.modelMatrix * vec4(position, 1.0); gl_Position = ubo.projection * push.viewMatrix * positionWorld; outPos = vec4(position, 1.0); }
对应片段着色器代码:
#version 450 layout(location = 0) out float outFragColor; layout(location = 0) in vec4 inPos; struct PointLight { vec4 position; vec4 color; }; layout(set = 0, binding = 0) uniform GlobalUbo { mat4 projection; mat4 view; mat4 inverseView; vec4 ambientLightColor; PointLight pointLights[10]; int numLights; } ubo; void main() { vec3 lightVec = inPos.xyz - ubo.pointLights[0].xyz; outFragColor = length(lightVec); }
问题原因与解决方案
这是Vulkan开发中非常典型的管线状态与着色器不匹配触发的编译器自动优化,按概率从高到低排查即可:
- 顶点输入状态配置缺失
90%以上的同类问题都是这个原因:Vulkan驱动在编译链接管线时会做静态检查,如果你在VkPipelineVertexInputStateCreateInfo中没有为location = 0的position属性添加对应的VkVertexInputAttributeDescription,或是绑定的顶点缓冲stride、输入速率配置错误,驱动会直接判定该location没有有效顶点输入,SPIR-V优化器会直接移除这个输入变量以及所有依赖它的计算逻辑,完全不会管你在GLSL代码里有没有写调用逻辑。排查时直接核对管线创建时的顶点属性配置,确认location 0对应3分量32位浮点数格式、偏移和stride和顶点缓冲的实际内存布局匹配即可。 - 着色器编译选项触发激进优化bug
如果你使用glslangValidator、shaderc编译SPIR-V时开启了最高级别大小优化(-Osize),旧版本编译器存在错误移除已使用顶点属性的已知bug。可以尝试给编译参数加-O0关闭所有优化重新编译,若此时position属性恢复,升级着色器编译器版本即可解决。 - Push常量范围配置不匹配
检查管线中VkPushConstantRange配置的大小,你声明的Push结构体包含两个mat4,总大小为128字节,如果配置的range大小小于128字节,部分驱动会判定push常量中的矩阵为无效值,进而将依赖矩阵计算的gl_Position逻辑判定为无效,连带移除position输入。 - 着色器链接错误
检查管线创建时附着的顶点、片段着色器模块是否正确,排查是否存在错链其他着色器SPIR-V、入口点名字配置错误的低级问题。
内容的提问来源于stack exchange,提问作者Jark
相关产品推荐
相关产品推荐

