glDrawElements GL_INVALID_OPERATION on AMD GPU

Started by
6 comments, last by congard 4 years, 4 months ago

Hello! I wrote a small engine, and decided to test it on different graphics cards. And here is what turned out to be unexpected: on Nvidia and Intel everything works well on Linux and Windows, but on AMD - it gives error 1282 (GL_INVALID_OPERATION) when trying to call glDrawElements. Below are code snippets and links to the full one.

void drawModelDM(const Model &model, ShaderProgram *program, const glm::mat4 &mat = glm::mat4(1.0f)) {
    glBindVertexArray(model.shape->vaos[0]);

    if (model.shape->bonesPerVertex != 0) {
        for (int i = 0; i < model.shape->bones.size(); i++) {
            program->set(program->getLocation(AlgineNames::ShadowShader::Bones) + i, model.shape->bones[i].finalTransformation);
        }
    }

    program->set(AlgineNames::ShadowShader::BoneAttribsPerVertex, (int)(model.shape->bonesPerVertex / 4 + (model.shape->bonesPerVertex % 4 == 0 ? 0 : 1)));
    program->set(AlgineNames::ShadowShader::TransformationMatrix, mat * model.m_transform);
    
    for (size_t i = 0; i < model.shape->meshes.size(); i++) {
        int err = glGetError();
        if (err != 0)
            std::cout << "Before glDrawElements DM: " << err << "\n";
        glDrawElements(GL_TRIANGLES, model.shape->meshes[i].count, GL_UNSIGNED_INT, reinterpret_cast<void*>(model.shape->meshes[i].start * sizeof(uint))); // OK
        err = glGetError();
        if (err != 0)
            std::cout << "After glDrawElements DM: " << err << "\n";
    }
}

/**
 * Draws model
 */
void drawModel(const Model &model) {
    glBindVertexArray(model.shape->vaos[1]);

    if (model.shape->bonesPerVertex != 0) {
        for (int i = 0; i < model.shape->bones.size(); i++) {
            colorShader->set(colorShader->getLocation(AlgineNames::ColorShader::Bones) + i, model.shape->bones[i].finalTransformation);
        }
    }

    colorShader->set(AlgineNames::ColorShader::BoneAttribsPerVertex, (int)(model.shape->bonesPerVertex / 4 + (model.shape->bonesPerVertex % 4 == 0 ? 0 : 1)));
    modelMatrix = &model.m_transform;
   updateMatrices();
    for (size_t i = 0; i < model.shape->meshes.size(); i++) {
        texture2DAB(0, model.shape->meshes[i].mat.ambientTexture);
        texture2DAB(1, model.shape->meshes[i].mat.diffuseTexture);
        texture2DAB(2, model.shape->meshes[i].mat.specularTexture);
        texture2DAB(3, model.shape->meshes[i].mat.normalTexture);
        texture2DAB(4, model.shape->meshes[i].mat.reflectionTexture);
        texture2DAB(5, model.shape->meshes[i].mat.jitterTexture);

        colorShader->set(AlgineNames::ColorShader::Material::AmbientStrength, model.shape->meshes[i].mat.ambientStrength);
        colorShader->set(AlgineNames::ColorShader::Material::DiffuseStrength, model.shape->meshes[i].mat.diffuseStrength);
        colorShader->set(AlgineNames::ColorShader::Material::SpecularStrength, model.shape->meshes[i].mat.specularStrength);
        colorShader->set(AlgineNames::ColorShader::Material::Shininess, model.shape->meshes[i].mat.shininess);

        int err = glGetError();
        if (err != 0)
            std::cout << "Before glDrawElements: " << err << "\n";
        glDrawElements(GL_TRIANGLES, model.shape->meshes[i].count, GL_UNSIGNED_INT, reinterpret_cast<void*>(model.shape->meshes[i].start * sizeof(uint))); // ERROR: 1282
        err = glGetError();
        if (err != 0)
            std::cout << "After glDrawElements: " << err
                << "\nCount: " << model.shape->meshes[i].count
                << "\nStart: " << model.shape->meshes[i].start
                << "\nVAO: " << model.shape->vaos[1] << "\n";
    }
}

/**
 * Renders to depth cubemap
 */
void renderToDepthCubemap(const uint index) {
   pointLamps[index].begin();
    pointLamps[index].updateMatrix();
    lightDataSetter.setShadowShaderPos(pointLamps[index]);
   lightDataSetter.setShadowShaderMatrices(pointLamps[index]);
   glClear(GL_DEPTH_BUFFER_BIT);

   // drawing models
    for (size_t i = 0; i < MODELS_COUNT; i++)
        drawModelDM(models[i], pointShadowShader);

   // drawing lamps
   for (GLuint i = 0; i < pointLampsCount; i++) {
      if (i == index) continue;
        drawModelDM(*pointLamps[i].mptr, pointShadowShader);
   }

   pointLamps[index].end();
}

/**
 * Renders to depth map
 */
void renderToDepthMap(uint index) {
   dirLamps[index].begin();
   glClear(GL_DEPTH_BUFFER_BIT);

   // drawing models
    for (size_t i = 0; i < MODELS_COUNT; i++)
        drawModelDM(models[i], dirShadowShader, dirLamps[index].m_lightSpace);

   // drawing lamps
   for (GLuint i = 0; i < dirLampsCount; i++) {
      if (i == index) continue;
        drawModelDM(*dirLamps[i].mptr, dirShadowShader, dirLamps[index].m_lightSpace);
   }

   dirLamps[index].end();
}

/**
 * Color rendering
 */
uint colorAttachment02[3] = { GL_COLOR_ATTACHMENT0, GL_NONE, GL_COLOR_ATTACHMENT2 };
uint colorAttachment0123[4] = {
    GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3
};
void render() {
    renderer.mainPass(displayFb->getId());
    
   // view port to window size
   glViewport(0, 0, winWidth, winHeight);

    glDrawBuffers(4, colorAttachment0123);
    colorShader->use();

    // sending lamps parameters to fragment shader
   sendLampsData();

    // drawing
    for (size_t i = 0; i < MODELS_COUNT; i++)
        drawModel(models[i]);
   for (size_t i = 0; i < pointLampsCount + dirLampsCount; i++)
       drawModel(lamps[i]);

    // [...]
}

void display() {
    // animate
    for (usize i = 0; i < MODELS_COUNT; i++)
        if (models[i].shape->bonesPerVertex != 0)
            models[i].animator->animate(glfwGetTime());

    // shadow rendering
    // point lights
    pointShadowShader->use();
   for (uint i = 0; i < pointLampsCount; i++) {
       lightDataSetter.setShadowShaderFarPlane(pointLamps[i]);
        renderToDepthCubemap(i);
    }

    // dir lights
    dirShadowShader->use();
    for (uint i = 0; i < dirLampsCount; i++)
        renderToDepthMap(i);
   
    ssrShader->use();
    ssrShader->set(AlgineNames::SSRShader::ProjectionMatrix, camera.getProjectionMatrix());
    ssrShader->set(AlgineNames::SSRShader::ViewMatrix, camera.getViewMatrix());

   /* --- color rendering --- */
    glClear(GL_DEPTH_BUFFER_BIT); // color will cleared by quad rendering
   render();
   glUseProgram(0);
}

Everything is perfectly drawn in the depth map, but not in the "color map"... And such a problem is ONLY on AMD.

Full code: https://github.com/congard/algine/blob/master/src/main.cpp#L802
Shaders: vertex shader, fragment shader
Repository link: https://github.com/congard/algine

Please help... I've already spent about 5 hours trying to figure out what I'm doing wrong

Advertisement

Thanks for the link! As a result, I received such errors:

Message: glDrawElements has generated an error (GL_INVALID_OPERATION)
Source: API
Type: Error
ID: 1000
Severity: High


Message: glDrawElements failed because the currently active shader combination is invalid (GL_INVALID_OPERATION)
Source: API
Type: Error
ID: 2003
Severity: High

But when compiling the shader, no errors were received. How to understand what the problem is with?

Hi. From the documentation of glDrawElements():

GL_INVALID_OPERATION is generated if a geometry shader is active and mode is incompatible with the input primitive type of the geometry shader in the currently installed program object.

GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to an enabled array or the element array and the buffer object's data store is currently mapped.

Also, glDrawElements() expects a const void * as the last parameter. Not sure if a reinterpret_cast fulfills that. I use (const void *) to offset into an element array for drawing ...

Hope that helps a bit.

Immediately after launching the application on Nvidia, this warning appeared:

Message: Framebuffer detailed info: The driver allocated storage for renderbuffer 1.
Source: API
Type: Other
ID: 131169
Severity: Low

Then after each call to glDrawElements (which is called NOT for drawing in the depth map, but in the "color map") I get the following messages:

Message: Texture state usage warning: Texture 0 is base level inconsistent. Check texture size.
Source: API
Type: Other
ID: 131204
Severity: Low

What are these warnings related to?

Nvidia Nsight didn’t show anything that could cause this problem

Precompiled binaries for Windows: with debug context enabled / debug output and without debug output

Thanks for your reply!

fleabay said:
Are you stepping through your code to find where the error occurs?

Nvidia warning occurs when called

glDrawElements(GL_TRIANGLES, model.shape->meshes[i].count, GL_UNSIGNED_INT, reinterpret_cast<void*>(model.shape->meshes[i].start * sizeof(uint)))

On AMD, error 1282 (invalid operation) occurs on the same line;
There are no errors/warnings on Intel.
Could the warning that Nvidia gives out be related to the error that AMD is giving?

Later I will post AMD RenderDoc captures and the debug output in AMD CodeXL

This topic is closed to new replies.

Advertisement