Trying to link an opengl program with a fragment shader that uses the GL_ARB_fragment_shader_interlock extension (or the GL_NV_fragment_shader_interlock one) leads to an internal error when the fragment shader using the extension is not the last fragment shader glAttached to the program.
The internal error is as follow:
Fragment info
-------------
Internal error: assembly compile error for fragment shader at offset 330:
-- error message --
line 13, column 1: error: invalid statement
line 15, column 1: error: invalid statement
-- internal assembly text --
!!NVfp5.0
OPTION NV_internal;
OPTION NV_bindless_texture;
# cgc version 3.4.0001, build date Jan 18 2024
# command line args:
#vendor NVIDIA Corporation
#version 3.4.0.1 COP Build Date Jan 18 2024
#profile gp5fp
#program main
#var float4 gl_FragColor : $vout.COLOR : COL0[0] : -1 : 1
TEMP T;
OUTPUT result_color0 = result.color;
FSIB;
MOV.F result_color0, {1, 0, 0, 0}.xyyx;
FSIE;
END
# 3 instructions, 0 R-regs
And here the full minimal reproducible example code
#include <QApplication>
#include <QOpenGLWidget>
#include <QOpenGLContext>
#include <QOpenGLVersionFunctionsFactory>
#include <QOpenGLFunctions_4_3_Compatibility>
#include <iostream>
const char* main_frag_src = R"glsl(
#extension GL_ARB_fragment_shader_interlock : require
vec4 ComputeColor();
void main()
{
beginInvocationInterlockARB();
gl_FragColor = ComputeColor();
endInvocationInterlockARB();
}
)glsl";
const char* color_frag_src = R"glsl(
vec4 ComputeColor()
{
return vec4(1.0, 0.0, 0.0, 1.0);
}
)glsl";
const char* main_vert_src = R"glsl(
void main()
{
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
}
)glsl";
GLuint createShader(GLenum shadertype, const char* source)
{
auto fcts_ptr = QOpenGLVersionFunctionsFactory::get<QOpenGLFunctions_4_3_Compatibility>();
if (!fcts_ptr)
throw 0;
auto& fct = *fcts_ptr;
auto shader = fct.glCreateShader(shadertype);
fct.glShaderSource(shader, 1, &source, nullptr);
fct.glCompileShader(shader);
GLint isCompiled = 0;
fct.glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
GLint maxLength = 0;
fct.glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<GLchar> errorLog(maxLength);
fct.glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]);
std::cerr << "Shader compilation failed:\n" << errorLog.data() << std::endl;
throw 0;
}
return shader;
}
struct MyWidget : QOpenGLWidget
{
void initializeGL() override {
auto ctx = context();
auto fcts_ptr = QOpenGLVersionFunctionsFactory::get<QOpenGLFunctions_4_3_Compatibility>();
if (!fcts_ptr)
throw;
auto& fct = *fcts_ptr;
std::cout << "vendor: " << fct.glGetString(GL_VENDOR) << std::endl;
std::cout << "renderer: " << fct.glGetString(GL_RENDERER) << std::endl;
auto frag_main = createShader(GL_FRAGMENT_SHADER, main_frag_src);
auto frag_color = createShader(GL_FRAGMENT_SHADER, color_frag_src);
auto vert_main = createShader(GL_VERTEX_SHADER, main_vert_src);
auto program = fct.glCreateProgram();
fct.glAttachShader(program, vert_main);
// The bug occurs when the shader using the fragment interlock functions
// is not the last fragment shader that is attached to the program
bool triggerBug = true;
if (triggerBug)
{
fct.glAttachShader(program, frag_main); // <-- shader using interlock not last
fct.glAttachShader(program, frag_color);
}
else
{
fct.glAttachShader(program, frag_color);
fct.glAttachShader(program, frag_main); // <-- shader using interlock last
}
fct.glLinkProgram(program);
GLint isLinked = 0;
fct.glGetProgramiv(program, GL_LINK_STATUS, &isLinked);
if (isLinked == GL_FALSE)
{
GLint maxLength = 0;
fct.glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<GLchar> infoLog(maxLength);
fct.glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
std::cerr << "Error during linking:\n" << infoLog.data() << std::endl;
return;
}
}
};
int main(int argc, char** argv)
{
QApplication app(argc, argv);
MyWidget widget;
widget.show();
return app.exec();
}
The bug as been observed on Windows 10 and Windows 11. At the moment I reproduce it with a driver version of 551.23 but that bug has been reproduced with older versions as well