Do you know that thanks to the GL_ARB_gl_spirv, it is possible to load SPIR-V shaders (the same shaders met in a Vulkan application) in OpenGL?
Loading SPIR-V shaders in OpenGL is very easy. The only requirement is the support of OpenGL 4.6, which is usually the case on Windows with latest drivers from AMD, NVIDIA and Intel. On Linux, if I’m not wrong, proprietary drivers are required to get GL 4.6 support.
Let’s see an example with a SPIR-V vertex shader.
The first step is to produce a SPIR-V binary module compatible with OpenGL. This can be done with the glslangValidator command line utility (shipped with the Vulkan SDK):
glslangValidator -G vs.vert -o vs.spv
The -G option allows to create a binary under OpenGL semantics.
We can now load this SPIR-V module in OpenGL thanks to the following functions:
// SPIR-V binary in memory uint8_t* vs_buf = ...; size_t vs_buf_len = ...; sid = glCreateShader(GL_VERTEX_SHADER); glShaderBinary(1, &sid, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, vs_buf, vs_buf_len); glSpecializeShader(sid, "main", 0, 0, 0); int compiled = 0; glGetShaderiv(sid, GL_COMPILE_STATUS, &compiled); if (compiled) glAttachShader(program_id, sid);
where vs_buf is the SPIR-V binary buffer in memory, vs_buf_len its length in bytes and program_id an existing program created with glCreateProgram().
glShaderBinary and glSpecializeShader simply replace glShaderSource and glCompileShader.
Regular uniform variables are no longer available with SPIR-V shaders. You have to use a GPU buffer to pass data to the shaders. An uniform buffer or better a shader storage buffer is perfect.
I have no C/C++ example to give you, but if you want to play with SPIR-V shaders in OpenGL, two GeeXLab demos (a RGB triangle and a textured quad) are available HERE.
The demos work as expected on NVIDIA and Intel GPUs (tested with NVIDIA 442.19 and Intel v7755 drivers). But on AMD GPUs (tested with a Radeon RX 5500 XT and a RX 470 + Adrenalin 20.2.1), the triangle and the quad are not rendered. Nothing on the screen (except the text) and no OpenGL error. Certainly a bug in my code, but currently I have no clues…