[英]Instanced GLSL shaders in Vulkan?
這是我能想出的(最簡單的)實例化着色器,它基本上只是轉換了一堆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附帶的glslangValidator將其編譯為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.
如果我刪除#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繪圖命令中的第一個實例開始的實例 。 但是,當添加了基礎實例化渲染(渲染任意范圍的實例的能力)時, gl_InstanceID
未更新為匹配。 因此,如果從具有5個實例的2的基本實例開始,則第一個gl_InstanceID
仍將為零 (后跟1,2,3和4)。 因此,基本實例唯一影響的是實例化數組 。
當然,Vulkan在這方面不希望OpenGL愚蠢,因此它使用了大多數人期望的實例值:用戶要求呈現的實際實例索引。 但是這需要一個新變量,因此用戶不會做你正在嘗試的事情:在OpenGL和Vulkan中意外地使用相同的變量而不會意識到它們具有不同的語義。
您將需要兩個着色器或檢查是否已定義VULKAN
,這將適用於使用GL_KHR_vulkan_glsl擴展名的人。 如果是,則使用gl_InstanceIndex
; 如果沒有,你使用gl_InstanceID
。 此外,您的#extension聲明也應該作為范圍,因為Vulkan GLSL-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從基本實例計數。 看到
有關內置函數的更多信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.