glDrawElements在驱动程序中崩溃了调试提示

时间:2016-12-08 20:11:28

标签: c++ opengl vertex-array-object

短版本:如何调试 glDrawElements/glDrawElementsInstanced内部的崩溃(内存访问异常/ nullptr异常)

长版: 您有一个使用VAOs的OpenGL渲染代码路径,并通过调用glDrawElementsglDrawElementsInstanced提交渲染。该代码路径在大多数情况下都能正常工作。我们正在谈论“编辑器代码”,这意味着:数据可能是任何几何体,很可能经常变化。

但有时在提交可重现的数据更改后,它只会在glDrawElements*驱动程序代码中崩溃(即调用glDrawElements,函数参数正常,崩溃发生在glDrawElements内。)< / p>

你怎么能继续调试这个问题?

P.S:

  • 自我回答的问题:所有研究工作都进入了答案!
  • 这是针对编辑器代码。对于简单的演示,这种崩溃主要是由编码器无法正确理解glDrawElements的要求引起的,因此代码路径将起作用或不起作用 - 在这些情况下,请参阅:

1 个答案:

答案 0 :(得分:1)

首先应明确可能导致驱动程序崩溃的原因。在大多数情况下,内存访问不良。

什么可能导致驱动程序内部坏内存的访问?

  • GL_ELEMENT_ARRAY_BUFFER - 绑定以某种方式发生了变化(因此赋予glDrawElements的参数可能会导致超出该对象内存的访问权限)
  • GL_ELEMENT_ARRAY_BUFFER的内容已更改,可能引用未初始化/不存在的顶点数据(VBO访问超出范围)
  • 任何关联的GL_ARRAY_BUFFER对象'数据被更改,因此不再包含引用的顶点数据(VBO访问越界)
  • 甚至更多此类更改。 glDrawElements*内的访问冲突主要是指在VAO状态中绑定的任何对象都是超出界限的。

如果没有额外的调试代码,这些访问冲突很难捕获。我建议在调用glDrawElements*之前插入debug-output。 Debug输出应查询所有可用的绑定和信息,因此您可以将“工作时”和“崩溃时”的设置进行比较,然后找出要查找的内容。

我的调试功能如下:

void debugVAOState(std::string baseMessage)
{
    baseMessage.append( " ... querying VAO state:\n" );
    int vab, eabb, eabbs, mva, isOn( 1 ), vaabb;
    glGetIntegerv( GL_VERTEX_ARRAY_BINDING, &vab );
    glGetIntegerv( GL_ELEMENT_ARRAY_BUFFER_BINDING, &eabb );
    glGetBufferParameteriv( GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &eabbs );

    baseMessage.append( "  VAO: " + std::to_string( vab ) + "\n" );
    baseMessage.append( "  IBO: " + std::to_string( eabb ) + ", size=" + std::to_string( eabbs )  + "\n" );

    glGetIntegerv( GL_MAX_VERTEX_ATTRIBS, &mva );
    for ( unsigned i = 0; i < mva; ++i )
    {
        glGetVertexAttribiv( i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &isOn );
        if ( isOn )
        {
            glGetVertexAttribiv( i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &vaabb );
            baseMessage.append( "  attrib #" + std::to_string( i ) + ": VBO=" + std::to_string( vaabb ) + "\n" );
        }
    }
    OutputDebugString( baseMessage.c_str() );
}

它仍然很简单,只输出最有价值的信息,以便能够看到上述绑定是否以某种方式发生了变化。但这有助于我发现许多崩溃来自于积极的OpenGL优化。