Vulkan中的实例GLSL着色器?

Vulkan中的实例GLSL着色器?,glsl,vulkan,spir-v,Glsl,Vulkan,Spir V,这是我能想到的(最简单的)实例化着色器,它基本上只是变换一组2D基本体: #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() {

这是我能想到的(最简单的)实例化着色器,它基本上只是变换一组2D基本体:

#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)]);

}
如果我尝试使用Vulkan SDK附带的glslagvalidator将其编译为SPIR-V,我会得到:

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.

如果删除
#扩展GL_ARB_draw_instanced
行,仍然会得到
GL_InstanceID
错误。是否可以编写实例GLSL并将其编译为SPIR-V?如果是这样的话,我做得不对吗?

不需要GL_ARB_draw_实例扩展,它由核心GLSL 1.40和vulkan支持。glslang似乎无论如何都不使用扩展名:

我认为必须使用gl_InstanceIndex而不是gl_InstanceID。区别在于gl_InstanceID从0开始计数,其中gl_InstanceIndex从基本实例开始计数。看


有关内置的更多信息。

参考编译器用于为Vulkan生成SPIR-V的GLSL格式不使用普通的OpenGL扩展。它遵循GLSL 4.50的规则,但通过隐式伪扩展的指令对其进行修改/重写。请注意,您没有使用#扩展来启动它;假设它处于活动状态,因为您正在使用Vulkan GLSL-to-SPIR-V编译器

特别是,此扩展将删除
gl\u InstanceID
(和
gl\u VertexID
)。相反,它创建自己的变量,
gl\u InstanceIndex
。这是因为OpenGL是。。。愚蠢的

请参见,
gl_InstanceID
是从中的第一个实例开始的实例。但是,当添加基本实例渲染(渲染任意范围实例的能力)时,
gl_InstanceID
未更新以匹配。因此,如果从具有5个实例的2个基本实例开始,则第一个
gl_InstanceID
仍然为零(后面是1、2、3和4)。因此,基本实例只影响以下内容

自然,Vulkan不希望OpenGL在这方面的愚蠢,因此它使用了大多数人期望的实例值:用户要求渲染的实际实例索引。但这需要一个新的变量,这样用户就不会做您正在尝试的事情:在OpenGL和Vulkan中意外地使用相同的变量,而没有意识到它们具有不同的语义


您需要两个着色器,或者检查是否定义了
VULKAN
,这将适用于使用GL_KHR_VULKAN_glsl扩展的用户。如果是,则使用
gl_InstanceIndex
;如果没有,则使用
gl\u InstanceID
。此外,您的扩展声明也应该确定范围,因为Vulkan GLSL-to-SPIR-V编译器将采用GLSL 4.50,并且它不一定提供扩展。

我显然仍然需要
#扩展GL#u ARB_shading_language\u 420pack:enable
,否则我会在
布局(binding=…)
中遇到编译错误。GL_KHR_vulkan_glsl的文档使用布局绑定,但似乎没有提到这一点)。不管怎样,我的实例着色器现在可以编译了——谢谢。@MuertoExcobito:也许它被你的
#version 400
声明搞糊涂了。他们真的应该有自己的版本号:
#version 100 vulkan
,就像GLSL ES的
#version 300 ES