How to Load SPIR-V Shaders in OpenGL

GL_ARB_gl_spirv demo with GeeXLab

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.

GL_ARB_gl_spirv demo with GeeXLab

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…

One thought on “How to Load SPIR-V Shaders in OpenGL”

  1. Tim

    Soo. I’m trying to get this up and running on an RX 580.
    Even with an OpenGL 4.6 context, GL_NUM_PROGRAM_BINARY_FORMATS returns a big fat zero.

    Despite that… it seems to work regardless.
    The relevant function pointers exist, I can load and link SPIR-V shaders into a program object.

    Wether or not they work as expected remains to be seen.. Did you get much further with this?

Comments are closed.