写入索引缓冲区时崩溃
Crash when writing to an index buffer
我目前正在为Windows,Mac和Linux编写使用C++11/SDL2/OpenGL的引擎。
它在Mac和Linux上运行良好,但是我的Windows + Nvidia桌面上遇到了令人讨厌的崩溃(我唯一的其他Windows环境是虚拟机,它不支持我的OpenGL功能集)
我有两个朋友在不同的Windows + AMD设备上测试过它,所以我的问题似乎与Nvidia的驱动程序和我所处的当前状态有关,这意味着SSCCE可能无济于事。顶点缓冲区创建
良好,以下索引缓冲区的创建用于在某个未知时间点正常工作。也许在驱动程序更新之前...
作为参考,我的 Buffer 类如下所示:
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 );
}
创建索引缓冲区的代码如下所示:
static const uint16_t quadIndices[6] = { 0, 2, 1, 1, 2, 3 };
quadsIndexBuffer = new Buffer( BufferType::Index, quadIndices, sizeof(quadIndices) );
崩溃发生在glBufferData( type, size, data, GL_STREAM_DRAW );
id
是 4type
是 34963 又名GL_ELEMENT_ARRAY_BUFFER
size
是 12data
是四指数如果我尝试在不填充索引缓冲区的情况下创建索引缓冲区,则映射它并写入它,如下所示:
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();
然后崩溃发生在glMapBufferRange
内部Buffer::MapDiscard
该映射方法背后的基本原理是因为尝试映射繁忙的缓冲区可能会引入繁忙等待。
// 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.
我尝试四处寻找答案,但我找到的唯一解决方案与传递不正确的大小或glBufferData的参数顺序错误有关。没有帮助。
似乎通过禁用GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
崩溃不再表现出来,我的程序的行为是正确的。
我想我假设这是一个驱动程序错误是正确的。我会尝试将其转发给开发团队。
作为参考,这是针对 Nvidia GTX 680 驱动程序版本 350.12 上的 OpenGL 3.1
启用 glewExperiment,并设置以下 OpenGL 上下文标志:核心配置文件、向前兼容、调试
- 当回溯以零开始时,如何调试崩溃
- C++字符*缓冲区的大小
- 为什么msgrcv()将垃圾字符馈送到缓冲区
- 内联映射初始化的动态atexit析构函数崩溃
- 执行函数时导致崩溃的变量
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- ostream过载时的缓冲区冲洗
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 程序崩溃并显示"std::out_of_range"错误
- Xaudio2在更改缓冲区或循环时弹出声音
- CoInitialize()在单独的线程上崩溃而不返回
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- 使用调试/崩溃报告将应用程序部署到客户端
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- 如何在cpp.中使用协议缓冲区存储大缓冲区/数组(char/int)
- 写入索引缓冲区时崩溃
- fopen在响应不相关的char缓冲区时崩溃
- 协议缓冲区初始化期间崩溃
- 具有大数据长度的解压缩缓冲区正在崩溃
- 共享内存环形缓冲区崩溃