Vulkan中的实例化GLSL着色器?
这是(简单的)实例化着色器,我可以想出,这基本上只是变换了一堆2D原语:Vulkan中的实例化GLSL着色器?
#version 400
#extension GL_ARB_draw_instanced : enable
#extension GL_ARB_shading_language_420pack : enable
layout(std140, binding = 0) uniform VConstants {
vec4 vfuniforms[48];
};
in vec4 pos;
void main() {
gl_Position = vec4(0.0,0,0.0,1);
gl_Position.x = dot(pos, vfuniforms[int(float(gl_InstanceID) * 2.0)]);
gl_Position.y = dot(pos, vfuniforms[int(float(gl_InstanceID) * 2.0 + 1.0)]);
}
如果我尝试用自带的glslangValidator编译这SPIR-V福尔康SDK,我得到:
WARNING: 0:2: '#extension' : extension not supported: GL_ARB_draw_instanced
ERROR: 0:14: 'gl_InstanceID' : undeclared identifier
ERROR: 1 compilation errors. No code generated.
如果我删除#extension GL_ARB_draw_instanced
线,我仍然得到gl_InstanceID
错误。是否可以编写实例化GLSL并将其编译为SPIR-V?如果是这样,我做错了什么?
参考编译器用于为Vulkan生成SPIR-V的GLSL格式不使用普通的OpenGL扩展。它遵循GLSL 4.50的规则,但它通过隐式伪延伸GL_KHR_vulkan_glsl的指示修改/覆盖它们。请注意,您不使用#extension来启动它;假设为,因为您使用的是Vulkan GLSL-to-SPIR-V编译器。
特别是,该扩展删除了gl_InstanceID
(和gl_VertexID
)。相反,它创建了自己的变量,gl_InstanceIndex
。原因是因为OpenGL是愚蠢的。
请参阅:gl_InstanceID
是从instanced drawing command中的第一个实例开始的实例。但是,添加基本实例渲染(可渲染任意范围的实例)时,gl_InstanceID
未更新为匹配。因此,如果从具有5个实例的2的基本实例开始,则第一个gl_InstanceID
将仍为零(后面跟着1,2,3和4)。所以基础实例唯一影响的是instanced arrays。当然,Vulkan在这方面不需要OpenGL愚蠢的一部分,所以它使用了大多数人所期望的实例值:用户要求渲染的实际实例索引。但是这需要一个新的变量,以便用户不会做你想做的事情:意外地在OpenGL和Vulkan中使用相同的变量,却没有意识到它们具有不同的语义。
您将需要两个着色器或检查是否定义了VULKAN
,这将用于那些使用GL_KHR_vulkan_glsl扩展名的用户。如果是,则使用gl_InstanceIndex
;如果没有,则使用gl_InstanceID
。此外,您的#extension声明也应该作为范围,因为Vulkan GLSL-to-SPIR-V编译器将采用GLSL 4.50,并且不一定会提供扩展。
GL_ARB_draw_instanced扩展名不是必需的,它由核心GLSL 1.40和vulkan支持。 glslang似乎并没有使用扩展:https://github.com/KhronosGroup/glslang/blob/master/glslang/MachineIndependent/Initialize.cpp#L1707
而不是gl_InstanceID,我认为gl_InstanceIndex必须使用。所不同的是,gl_InstanceID从0开始计数,其中gl_InstanceIndex从基础实例开始计数。见
有关建宏的更多信息。
我仍然显然需要'#extension GL_ARB_shading_language_420pack:enable',否则我得到'layout(binding = ...)'的编译错误。 GL_KHR_vulkan_glsl的文档使用布局绑定,但似乎没有提到这一点)。无论如何,我的实例着色器现在编译 - 谢谢。 – MuertoExcobito
@MuertoExcobito:您的#version 400声明可能会让您感到困惑。他们真的应该有他们自己的版本号:'#version 100 vulkan',这是GLSL ES拥有'#version 300 es'的方式。 –