openglspir-v

How would I set sampler2D uniforms in OpenGL in a SPIR-V Shader?


I am compiling this shader with glslangValidator, and am using OpenGL 4.3 Core Profile with the extension GL_ARB_gl_spirv, and using the GLAD webservice to generate function pointers to access the Core OpenGL API, and SDL2 to create the context, if that is of any use.

If I have a fragment shader like so:

#version 430 core

//output Fragment Color
layout (location = 0) out vec4 outFragColor;

//Texture coordinates passed from the vertex shader
layout (location = 0) in vec2 inTexCoord;

uniform sampler2D inTexture;

void main()
{
    outFragColor = texture(inTexture, inTexCoord);
}

How would I be able to set which texture unit inTexture uses?

From what I have read online through documents, I cannot use glGetUniformLocation to get the location of this uniform to use in glUniform1i, because of the fact I am using SPIR-V, instead of GLSL directly.

What would I need to do to set it in a fashion like glUniform1i? Do I need to set the location in the layout modifier? The binding? I've tried to use Uniform Buffer Objects, but apparently sampler2D can only be a uniform.


Solution

  • Since GLSL 4.20, you have the ability to set the binding point for any opaque type like samplers from GLSL code directly. This is done through the binding layout qualifier:

    layout(binding = #) uniform sampler2D inTexture;
    

    The # here is whatever binding index you want to use. This is the index you use when binding the texture: glActiveTexture(GL_TEXTURE0 + #). That is, you don't need to use glProgramUniform to set the uniform's value anymore; you already set it in the shader.

    If you want to modify the binding dynamically (and you shouldn't), GLSL 4.30 offers the ability to set the location for any non-block uniform value via the location layout qualifier:

    layout(location = #) uniform sampler2D inTexture;
    

    This makes # the uniform's location, which you can pass to any glProgramUniform call.