【问题标题】:glDrawElements crashes in the driver | debugging hints [closed]glDrawElements 在驱动程序中崩溃 |调试提示[关闭]
【发布时间】:2016-12-11 05:17:57
【问题描述】:

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

加长版: 您有一条使用VAOs 的OpenGL 渲染代码路径,并通过调用glDrawElementsglDrawElementsInstanced 提交渲染。该代码路径在大多数情况下都能正常工作。我们说的是“编辑器代码”,这意味着:数据可能是任何几何图形,并且很可能会频繁更改。

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

如何继续调试这个问题?

附注:

  • 自我回答的问题:所有的研究努力都在寻找答案!
  • 这是针对编辑器代码。对于简单的演示,此类崩溃主要是由于编码人员没有正确理解 glDrawElements 的要求造成的,因此代码路径要么工作要么不工作 - 在这些情况下,请参阅:

【问题讨论】:

  • 我不明白为什么这个问题一直被否决。也许它旁边应该有一个通知,它是自我回答的?我知道这个问题没有显示出研究工作——因为所有的研究工作都投入到了答案中!不过应该还是很清楚的,确实对大家创建OpenGL编辑器很有用。
  • 自我回答问题以分享知识很好。但这个问题必须仍然是一个好问题。这不是。 不是你的任何人都无法回答。
  • 那么,有多少人创建了集成的 OpenGL 图形开发环境?我知道这个问题和答案对很多人没有用。但是少数人在谷歌上搜索可能会发现它很有帮助。是的,这是一个黑匣子魔术“它是否会在驱动程序内部崩溃”问题,这很难描述。我只是想让它更清楚一点,但我认为它并没有变得更好。
  • P.S.:关于它大部分时间都可以正常工作,但在特定数据修改时崩溃的事实,应该清楚不能有一个“最小、完整和可验证的例子”。

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


【解决方案1】:

首先应该清楚可能导致驱动程序崩溃的原因。在大多数情况下,这是错误的内存访问。

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

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

如果没有额外的调试代码,这些访问违规将很难被发现。我建议在调用glDrawElements* 之前插入调试输出。 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 优化的崩溃。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-08
    • 2011-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-15
    • 2021-05-15
    相关资源
    最近更新 更多