0

I am working on a Qt6 application which features a QOpenGLWidget where I render using some GLSL shaders.

I try to use the Qt6 helpers and primitives for OpenGL as much as possible.

I set up my context to use OpenGL version 4.6 core and log the result with this code:

// Print OpenGL version information
qDebug().nospace().noquote() << "OpenGL actual version: " << context->format().version().first << "." << context->format().version().second;
qDebug().nospace().noquote() << "OpenGL vendor:" << QString(reinterpret_cast<const char*>(functions->glGetString(GL_VENDOR)));
qDebug().nospace().noquote() << "OpenGL renderer:" << QString(reinterpret_cast<const char*>(functions->glGetString(GL_RENDERER)));

The corresponding output looks like this:

OpenGL actual version: 4.6
OpenGL vendor:NVIDIA Corporation
OpenGL renderer:Quadro P400/PCIe/SSE2

I also log the number of available uniform locations with the following code:

// Retrieve the maximum uniform locations
GLint maxUniformLocations;
functions->glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &maxUniformLocations);
qDebug().nospace().noquote() << "Maximum uniform locations:" << maxUniformLocations;

and it outputs:

Maximum uniform locations:65536

The code that sets uniforms run on every frame and looks like this:

//program.setUniformValue("last_draw_down", lastButtonsPressed[DRAW_BUTTON_INDEX]);
//program.setUniformValue("last_now", lastNow);
program.setUniformValue("bits_per_channel", bits_per_channel);
program.setUniformValue("brightness", brightness.value().toFloat());
program.setUniformValue("clock", static_cast<GLfloat>(now%1000)/1000.0f);
program.setUniformValue("contrast", contrast.value().toFloat());
program.setUniformValue("dithering", dithering.value().toFloat());
program.setUniformValue("is_dragging", is_dragging);
program.setUniformValue("is_draw_down", buttonsPressed[DRAW_BUTTON_INDEX]);
program.setUniformValue("is_navigation_down", buttonsPressed[NAVIGATION_BUTTON_INDEX]);
program.setUniformValue("last_dragged", last_dragged);
program.setUniformValue("last_navigation_down", lastButtonsPressed[NAVIGATION_BUTTON_INDEX]);
program.setUniformValue("modelMat", modelMat);
program.setUniformValue("now", now);
program.setUniformValue("projectionMat", projectionMat);
program.setUniformValue("resolution", size());
program.setUniformValue("texture_array", textureUnit);
program.setUniformValue("viewMat", viewMat);

As you can see there are exactly 16 uniforms set. If I add just one more uniform (for example by uncommenting one of the lines at the top), the program starts to spit the following in error output:

OpenGL Message: "GL_INVALID_OPERATION error generated. Wrong component type or count."

(I have debug enabled in my OpenGL context) It does not really matter which uniforms are enabled, just the number.

So my question is, how come I can't set more than 16 uniforms when my context clearly claims there is room for 65536 (4096 times as many)?

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Mr. Developerdude
  • 9,118
  • 10
  • 57
  • 95
  • Could you please add the shader code? – BDL Jul 15 '23 at 09:58
  • @BDL The shader is a big mess but it compiles, links and runs. – Mr. Developerdude Jul 16 '23 at 00:05
  • I don't think the error you're seeing has anything to do with the number of uniforms being set. Rather it suggests a mismatch between the declared type of the uniform in the shader code and the type of data being assigned to it. Without seeing the full code I'd guess the `setUniformValue` overload being invoked is not the one you expect/need -- hence the error message. – G.M. Jul 16 '23 at 08:30

1 Answers1

0

I don't know exactly what's wrong with your code, but I have some ideas that might help.

  • Updating the driver is always a good idea.
  • If you're in Compatibility mode, I think your limits might be lower than normal, so it's worth checking it.
  • I'm not sure what the setUniformValue method does, but I guess it calls one of the glUniform* functions. According to the docs, this function won't give you an error if you use too many uniform locations. It gives you errors for example when you want to put a vec4 where there is only a float in the shader. You should check these errors: https://docs.gl/gl4/glUniform#errors
  • There are other limitations to uniforms, not just the number of locations. For example MAX_VERTEX_UNIFORM_COMPONENTS (which has to be at least 1024). A vec4 has 4 components a mat3 has 9 etc. and in a vertex shader you can only use MAX_VERTEX_UNIFORM_COMPONENTS many uniform components. So you should check these other limits as well.
  • If you use glGetError, you should set up a debug message callback to get more information about the error. Here is a good tutorial: https://learnopengl.com/In-Practice/Debugging
  • If none of these work, as a workaround, you could use a uniform buffer object instead of individual uniforms. It only uses 1 location and it might be more performant. And if you later want to use this shader with Vulkan, you'll be able to do it (Vulkan only supports uniform buffers and not individual uniforms).
racz16
  • 198
  • 2
  • 8