2016-02-25 139 views
4

这是(简单的)实例化着色器,我可以想出,这基本上只是变换了一堆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?如果是这样,我做错了什么?

回答

10

参考编译器用于为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,并且不一定会提供扩展。

+0

我仍然显然需要'#extension GL_ARB_shading_language_420pack:enable',否则我得到'layout(binding = ...)'的编译错误。 GL_KHR_vulkan_glsl的文档使用布局绑定,但似乎没有提到这一点)。无论如何,我的实例着色器现在编译 - 谢谢。 – MuertoExcobito

+1

@MuertoExcobito:您的#version 400声明可能会让您感到困惑。他们真的应该有他们自己的版本号:'#version 100 vulkan',这是GLSL ES拥有'#version 300 es'的方式。 –

1

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从基础实例开始计数。见

https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/xhtml/vkspec.html#interfaces-builtin-variables

有关建宏的更多信息。