OpenGL 调试上下文警告 - “将使用 VIDEO 内存作为缓冲区异议的来源

OpenGL debug context warning - "Will use VIDEO memory as the source for buffer objection

我现在正在努力学习 opengl,但遇到了一个问题。在我的带有 nvidia gtx 780 opengl 的台式计算机上,通过 glDebugMessageCallback 机制打印出警告:

"Buffer object 1 (bound to _GL_ARRAY_BUFFER_ARB, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations."

我正在渲染 1 个带有顶点和索引缓冲区的立方体,因此对于我正在创建的每个缓冲区对象(其中 2 个)都会重复此消息。但是,最后还有一个最后的警告:

"Vertex shader in program 3 is being recompiled based on GL State."

我仍然能够渲染之前渲染的立方体,但我设置的颜色在白色和现在的颜色之间闪烁。我在网上搜索并找到了这个答案 - https://community.khronos.org/t/nvidia-output-debug-error-131185/66033 - 基本上说这只是一个警告,一切都应该没问题,但这不能解释为什么我的立方体现在在白色和我的颜色之间闪烁。同样的代码在我的笔记本电脑上运行良好(2019 年华硕笔记本电脑也有一个 nvidia GTX 图形芯片)。以前有人遇到过这个问题吗?这是相关代码:

const char* vertexShaderCode =
R"HereDoc(

#version 430

in layout(location=0) vec3 position;
in layout(location=1) vec3 color;
out vec3 fragColor;

uniform mat4 transformationMatrix;

void main()
{
vec4 newPos = vec4(position, 1.0) * transformationMatrix;//vector is on the left side because my matrices are row major
gl_Position = newPos;

    vec3 changedColors;
    changedColors.r += color.r + 0;
    changedColors.g += color.g + 0;
    changedColors.b += color.b + 0;
    fragColor = changedColors;
};

)HereDoc";

const char* fragmentShaderCode =
R"HereDoc(

#version 430

out vec4 color;
in vec3 fragColor;

void main()
{
    color = vec4(fragColor, 1.0f);
};

)HereDoc";

void GLAPIENTRY MyOpenGLErrorCallbackFunc(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam)
{
    BGZ_CONSOLE("%s type=0x%x %s\n", ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ), type, message);
};

void CheckCompileStatus(GLuint shaderID)
{
    GLint compileStatus;
    glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compileStatus);

    if(compileStatus != GL_TRUE)
    {
        GLint infoLogLength;
        glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &infoLogLength);

        GLchar buffer[512] = {};
        GLsizei bufferSize;
        glGetShaderInfoLog(shaderID, infoLogLength, &bufferSize, buffer);

        BGZ_CONSOLE("%s", buffer);
        InvalidCodePath;
    };
};

void CheckLinkStatus(GLuint programID)
{
    GLint linkStatus;
    glGetProgramiv(programID, GL_LINK_STATUS, &linkStatus);

    if(linkStatus != GL_TRUE)
    {
        GLint infoLogLength;
        glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength);

        GLchar buffer[512] = {};
        GLsizei bufferSize;
        glGetProgramInfoLog(programID, infoLogLength, &bufferSize, buffer);

        BGZ_CONSOLE("%s", buffer);
        InvalidCodePath;
    };
};

local_func void InstallShaders()
{
    GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

    const char* adapter[1];
    adapter[0] = vertexShaderCode;
    glShaderSource(vertexShaderID, 1, adapter, 0);
    adapter[0] = fragmentShaderCode;
    glShaderSource(fragmentShaderID, 1, adapter, 0);

    glCompileShader(vertexShaderID);
    glCompileShader(fragmentShaderID);

    CheckCompileStatus(vertexShaderID);
    CheckCompileStatus(fragmentShaderID);

    GLuint programID = glCreateProgram();
    glAttachShader(programID, vertexShaderID);
    glAttachShader(programID, fragmentShaderID);
    glLinkProgram(programID);

    CheckLinkStatus(programID);

    glUseProgram(programID);
};

local_func void
GLInit(int windowWidth, int windowHeight)
{
    glEnable(GL_DEBUG_OUTPUT);
    glDebugMessageCallback(MyOpenGLErrorCallbackFunc, 0);

    glViewport(0, 0, windowWidth, windowHeight);

    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);//Defaults to CCW ordering of indicies meaning all indicies that, from the viewers perspective, creating triangles in a CW manner repsrent visible triangles.
    glCullFace(GL_BACK);//Culls only back faces (faces facing away from viewer)
    InstallShaders();
}


void Draw(Memory_Partition* memPart, s32 id, RunTimeArr<s16> meshIndicies)
{
    glDisable(GL_TEXTURE_2D);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 2);
    glDrawElements(GL_TRIANGLES, (s32)meshIndicies.length, GL_UNSIGNED_SHORT, 0);
    glEnable(GL_TEXTURE_2D);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
};

//This implements a discriminated union for buffering render commands that my game code layer uses.
void RenderViaHardware(Rendering_Info&& renderingInfo, Memory_Partition* platformMemoryPart, int windowWidth, int windowHeight)
{
    local_persist bool glIsInitialized { false };
    if (NOT glIsInitialized)
    {
        GLInit(windowWidth, windowHeight);
        glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
        glIsInitialized = true;
    };

    u8* currentRenderBufferEntry = renderingInfo.cmdBuffer.baseAddress;
    Camera3D camera3d = renderingInfo.camera3d;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glEnable(GL_TEXTURE_2D);

    for (s32 entryNumber = 0; entryNumber < renderingInfo.cmdBuffer.entryCount; ++entryNumber)
    {
        RenderEntry_Header* entryHeader = (RenderEntry_Header*)currentRenderBufferEntry;
        switch (entryHeader->type)
        {
            case EntryType_InitBuffer:{
                RenderEntry_InitBuffer bufferData = *(RenderEntry_InitBuffer*)currentRenderBufferEntry;

                ScopedMemory scope{platformMemoryPart};

                RunTimeArr<GLfloat> verts{};
                InitArr(verts, platformMemoryPart, bufferData.verts.length * 6);
                s32 i{};
                f32 colorR{1.0f}, colorG{}, colorB{};//Im just hard coding color data right now while I'm learning
                for(s32 j{}; j < bufferData.verts.length; ++j)
                {
                    verts.Push(bufferData.verts[j].x);
                    verts.Push(bufferData.verts[j].y);
                    verts.Push(bufferData.verts[j].z);
                    verts.Push(colorR);
                    verts.Push(colorG);
                    verts.Push(colorB);
                };

                u32 vertexArrayID{};
                glGenVertexArrays(1, &vertexArrayID);
                glBindVertexArray(vertexArrayID);

                GLuint bufferID;
                glGenBuffers(1, &bufferID);
                glBindBuffer(GL_ARRAY_BUFFER, bufferID);
                glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * verts.length, verts.elements, GL_DYNAMIC_DRAW);
                glEnableVertexAttribArray(0);
                glEnableVertexAttribArray(1);
                glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, 0);
                glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (char*)(sizeof(GLfloat)*3));

                GLuint indexBufferID;
                glGenBuffers(1, &indexBufferID);
                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
                glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(s16) * bufferData.indicies.length, bufferData.indicies.elements, GL_DYNAMIC_DRAW);

                currentRenderBufferEntry += sizeof(RenderEntry_InitBuffer);
            }break;

            //...other cases for entries which are irrelevant to problem

            case EntryType_Geometry: {
                ScopedMemory scope{platformMemoryPart};

                RenderEntry_Geometry geometryEntry = *(RenderEntry_Geometry*)currentRenderBufferEntry;

                //camera transform setup
                Mat4x4 xRotMatrix = XRotation(camera3d.rotation.x);
                Mat4x4 yRotMatrix = YRotation(camera3d.rotation.y);
                Mat4x4 zRotMatrix = ZRotation(camera3d.rotation.z);
                Mat4x4 fullRotMatrix = xRotMatrix * yRotMatrix * zRotMatrix;
                v3 xAxis = GetColumn(fullRotMatrix, 0);
                v3 yAxis = GetColumn(fullRotMatrix, 1);
                v3 zAxis = GetColumn(fullRotMatrix, 2);

                //Setup full transform matrix
                Mat4x4 camTransform = ProduceCameraTransformMatrix(xAxis, yAxis, zAxis, camera3d.worldPos);
                Mat4x4 projectionTransform = ProduceProjectionTransformMatrix_UsingFOV(renderingInfo.fov, renderingInfo.aspectRatio, renderingInfo.nearPlane, renderingInfo.farPlane);
                Mat4x4 fullTransformMatrix = projectionTransform * camTransform * geometryEntry.worldTransform;

                //Send transform matrix to vertex shader
                GLint transformMatrixUniformLocation = glGetUniformLocation(3, "transformationMatrix");
                glUniformMatrix4fv(transformMatrixUniformLocation, 1, GL_FALSE, &fullTransformMatrix.elem[0][0]);

                Draw(platformMemoryPart, geometryEntry.id, geometryEntry.indicies);

                currentRenderBufferEntry += sizeof(RenderEntry_Geometry);
            }break;

            InvalidDefaultCase;
        };
    }

    renderingInfo.cmdBuffer.entryCount = 0;
};

编辑:

我发现了颜色不起作用的问题,在下面的评论中得到了解答。但是,我仍然不知道这些警告试图告诉我什么,如果它们是我应该寻求解决的问题。

您的变量 vec3 changedColors; 未初始化。用 vec3 changedColors = vec3(0); 初始化它。它在您的笔记本电脑上工作的原因可能是它的图形驱动程序默认将其初始化为零,而您的其他图形驱动程序则不会。

关于警告(不是错误)。它只是警告您,您的缓冲区将被放入视频内存中,因为您正在使用 GL_STATIC_DRAW 作为缓冲区。它实际上更像是一个日志,您可以安全地忽略它。如果你想摆脱它,你必须在你的回调中过滤掉它(你传递给 glDebugMessageCallback)。您的回调将有一个 severity 参数,可让您过滤具有特定严重性的消息。

或者,如果您只想删除该特定消息,请过滤其 id 值。

这是一个取自 blog.nobel-joergensen.com 的例子:

void APIENTRY openglCallbackFunction(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
{
    cout << "---------------------opengl-callback-start------------" << endl;
    cout << "message: "<< message << endl;
    cout << "type: ";
    switch (type) {
    case GL_DEBUG_TYPE_ERROR:
        cout << "ERROR";
        break;
    case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
        cout << "DEPRECATED_BEHAVIOR";
        break;
    case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
        cout << "UNDEFINED_BEHAVIOR";
        break;
    case GL_DEBUG_TYPE_PORTABILITY:
        cout << "PORTABILITY";
        break;
    case GL_DEBUG_TYPE_PERFORMANCE:
        cout << "PERFORMANCE";
        break;
    case GL_DEBUG_TYPE_OTHER:
        cout << "OTHER";
        break;
    }
    cout << endl;

    cout << "id: " << id << endl;
    cout << "severity: ";
    switch (severity){
    case GL_DEBUG_SEVERITY_LOW:
        cout << "LOW";
        break;
    case GL_DEBUG_SEVERITY_MEDIUM:
        cout << "MEDIUM";
        break;
    case GL_DEBUG_SEVERITY_HIGH:
        cout << "HIGH";
        break;
    }
    cout << endl;
    cout << "---------------------opengl-callback-end--------------" << endl;
}