C++ 写入索引缓冲区时崩溃

C++ 写入索引缓冲区时崩溃,c++,opengl,vbo,C++,Opengl,Vbo,我目前正在使用C++11/SDL2/OpenGL为Windows、Mac和Linux编写代码 它在Mac和Linux上运行良好,但我的Windows+Nvidia桌面(我唯一的其他Windows环境是虚拟机,它不支持我的OpenGL功能集)出现了严重的崩溃 我有两个朋友在不同的Windows+AMD设备上测试过它,所以我的问题似乎与Nvidia的驱动程序和我的当前状态有关,这意味着SSCCE可能不会有帮助。 顶点缓冲区创建得很好,以下索引缓冲区的创建用于在某个未知时间点正常工作。也许在驱动程序更

我目前正在使用C++11/SDL2/OpenGL为Windows、Mac和Linux编写代码

它在Mac和Linux上运行良好,但我的Windows+Nvidia桌面(我唯一的其他Windows环境是虚拟机,它不支持我的OpenGL功能集)出现了严重的崩溃

我有两个朋友在不同的Windows+AMD设备上测试过它,所以我的问题似乎与Nvidia的驱动程序和我的当前状态有关,这意味着SSCCE可能不会有帮助。
顶点缓冲区创建得很好,以下索引缓冲区的创建用于在某个未知时间点正常工作。也许在驱动程序更新之前

作为参考,我的缓冲区类如下:

static GLenum GetGLBufferType( BufferType bufferType ) {
    switch ( bufferType ) {
    case BufferType::Vertex: {
        return GL_ARRAY_BUFFER;
    } break;

    case BufferType::Index: {
        return GL_ELEMENT_ARRAY_BUFFER;
    } break;

    case BufferType::Uniform: {
        return GL_UNIFORM_BUFFER;
    } break;

    default: {
        return GL_NONE;
    } break;
    }
}

GLuint Buffer::GetID( void ) const {
    return id;
}

Buffer::Buffer( BufferType bufferType, const void *data, size_t size )
: type( GetGLBufferType( bufferType ) ), offset( 0 ), size( size )
{
    glGenBuffers( 1, &id );
    glBindBuffer( type, id );
    glBufferData( type, size, data, GL_STREAM_DRAW );

    if ( bufferType == BufferType::Uniform ) {
        glGetIntegerv( GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, reinterpret_cast<GLint *>( &alignment ) );
    }
    else {
        alignment = 16;
    }
}

Buffer::~Buffer() {
    glDeleteBuffers( 1, &id );
}

void *Buffer::Map( void ) {
    Bind();
    return glMapBufferRange( type, 0, size, GL_MAP_WRITE_BIT );
}

BufferMemory Buffer::MapDiscard( size_t allocSize ) {
    Bind();

    allocSize = (allocSize + alignment - 1) & ~(alignment - 1);
    if ( (offset + allocSize) > size ) {
        // We've run out of memory. Orphan the buffer and allocate some more memory
        glBufferData( type, size, nullptr, GL_STREAM_DRAW );
        offset = 0;
    }

    BufferMemory result;
    result.devicePtr = glMapBufferRange(
        type,
        offset,
        allocSize,
        GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_RANGE_BIT
    );
    result.offset = offset;
    result.size = allocSize;
    offset += allocSize;
    return result;
}

void Buffer::Unmap( void ) {
    glUnmapBuffer( type );
}

void Buffer::BindRange( int index, size_t rangeOffset, size_t rangeSize ) const {
    if ( !rangeSize ) {
        rangeSize = size - rangeOffset;
    }

    glBindBufferRange( type, index, id, rangeOffset, rangeSize );
}

void Buffer::Bind( void ) const {
    glBindBuffer( type, id );
}
崩溃发生在
glBufferData(类型、大小、数据、GL\u流\u绘制)
id
is 4
类型
是34963 aka
GL\u元素\u数组\u缓冲区

大小
为12
数据
为四位索引

如果我尝试在不填充索引缓冲区的情况下创建索引缓冲区,则将其映射并写入,如下所示:

quadsIndexBuffer = new Buffer( BufferType::Index, nullptr, sizeof(quadIndices) );
BufferMemory bufferMem = quadsIndexBuffer->MapDiscard( 6 * sizeof(uint16_t) );
uint16_t *indexBuffer = static_cast<uint16_t *>( bufferMem.devicePtr );
for ( size_t i = 0u; i < 6; i++ ) {
    *indexBuffer++ = quadIndices[i];
}
quadsIndexBuffer->Unmap();

我试着四处搜索答案,但我找到的唯一解决方案是传递错误的大小,或者glBufferData的参数顺序错误。没有帮助。

似乎通过禁用
GL\u DEBUG\u OUTPUT\u SYNCHRONOUS\u ARB
崩溃不再出现,我的程序的行为是正确的

我想我是对的,我认为这是一个驱动程序错误。我会试着把它转发给开发团队

作为参考,这是针对Nvidia GTX 680驱动程序版本350.12上的OpenGL 3.1的

glewExperimental已启用,并设置了以下OpenGL上下文标志:核心配置文件、前向兼容、调试

您的问题是什么?它为什么会崩溃,我如何修复它?它是什么类型的崩溃?您收到的消息是什么?0xC0000005处的访问冲突,调用堆栈显示垃圾,但这可能是由于我使用/Z7进行的编译器配置造成的-我预计它在nvoglv32.dll中崩溃,因为这是最近传递执行控制的地方。这可能是一个愚蠢的建议,但尝试将缓冲区内容复制到动态分配的(使用新的)内存块,然后将其传递给glBufferData。
quadsIndexBuffer = new Buffer( BufferType::Index, nullptr, sizeof(quadIndices) );
BufferMemory bufferMem = quadsIndexBuffer->MapDiscard( 6 * sizeof(uint16_t) );
uint16_t *indexBuffer = static_cast<uint16_t *>( bufferMem.devicePtr );
for ( size_t i = 0u; i < 6; i++ ) {
    *indexBuffer++ = quadIndices[i];
}
quadsIndexBuffer->Unmap();
// Usage strategy is map-discard. In other words, keep appending to the buffer
// until we run out of memory. At this point, orphan the buffer by re-allocating
// a buffer of the same size and access bits.