Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instanced GLSL shaders in Vulkan?

This is the (simplest) instancing shader I can come up with, which basically just transforms a bunch of 2D primitives:

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

}

If I try to compile this to SPIR-V with the glslangValidator that comes with the Vulkan SDK, I get:

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.

If I remove the #extension GL_ARB_draw_instanced line, I still get the gl_InstanceID error. Is it possible to write instancing GLSL and compile them to SPIR-V? If so, what I am doing incorrectly?

like image 653
MuertoExcobito Avatar asked Feb 25 '16 21:02

MuertoExcobito


People also ask

Can Vulkan use GLSL?

Vulkan does not directly consume shaders in a human-readable text format, but instead uses SPIR-V as an intermediate representation. This opens the option to use shader languages other than e.g. GLSL, as long as they can target the Vulkan SPIR-V environment.

What shader language does Vulkan use?

GLSL. OpenGL Shading Language (GLSL) is the standard shader programming language for Khronos APIs such as Vulkan, OpenGL 4.

How do you compile shaders in Vulkan?

Double click the file to run it. Replace the path to glslc with the path to where you installed the Vulkan SDK. Make the script executable with chmod +x compile.sh and run it. These two commands tell the compiler to read the GLSL source file and output a SPIR-V bytecode file using the -o (output) flag.

Does OpenGL support HLSL?

The GLSL that is referred to herein is compatible with OpenGL ES 2.0; the HLSL is compatible with Direct3D 11.


1 Answers

The form of GLSL that the reference compiler uses to generate SPIR-V for Vulkan doesn't use normal OpenGL extensions. It follows the rules of GLSL 4.50, but it amends/overrides them by the dictates of the implicit pseudo-extension GL_KHR_vulkan_glsl. Note that you don't use #extension to initiate it; it is assumed to be active because you're using the Vulkan GLSL-to-SPIR-V compiler.

In particular, this extension removes gl_InstanceID (and gl_VertexID). Instead, it creates its own variable, gl_InstanceIndex. The reason for this is because OpenGL was... stupid.

See, gl_InstanceID is the instance starting from the first instance in the instanced drawing command. However, when base-instanced rendering was added (the ability to render an arbitrary range of instances), gl_InstanceID was not updated to match. So if you start from a base instance of 2 with 5 instances, the first gl_InstanceID will still be zero (followed by 1, 2, 3, and 4). So the only things the base instance affects are instanced arrays.

Naturally, Vulkan wanted no part of OpenGL's stupidity in this regard, so it uses what most people would expect the instance value to be: the actual instance index the user asked to render. But this required a new variable, so that users wouldn't do what you're attempting: to accidentally use the same variable across both OpenGL and Vulkan without realizing that they have different semantics.

You'll either need two shaders or to check if VULKAN is defined, which is will be for those using the GL_KHR_vulkan_glsl extension. If it is, you use gl_InstanceIndex; if not, you use gl_InstanceID. Also, your #extension declarations should be scoped as well, since the Vulkan GLSL-to-SPIR-V compiler will assume GLSL 4.50, and it won't necessarily offer up extensions.

like image 158
Nicol Bolas Avatar answered Sep 20 '22 05:09

Nicol Bolas