2016-02-25 92 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

有關建宏的更多信息。