【发布时间】:2014-12-12 11:07:08
【问题描述】:
我很难为这个问题想出一个好标题,所以如果你能想出一个好标题,请提出一个新标题。也许我们可以在解决我的问题后做......现在开始:
我目前正在移植代码以使用 glMultiDrawElements,而不是多次调用 glDrawElements。为此,我使用了我称之为 sequenceList 的东西,它只是两个向量的 std::pair,一个 unsigned int 和一个 int。
// Sequence of vectors defining < StartIndex per primitive, Number of vertices per primitive >
using SequenceList = std::pair< std::vector< unsigned int >, std::vector< GLsizei > >;
为了能够对所有变体仅使用一个绘制函数(尽管只有一个基元可以使用一个索引列表进行绘制),我将函数调用概括为 always 使用 sequenceList 对象,但只有一个索引值。这意味着我将 glMultiDrawElements 用于所有索引绘制调用(以及 glMultiDrawArrays 用于非索引绘制调用)。
void GLVBOProbe::draw( unsigned startIndex, int numberOfIndicesToDraw ) const
{
VertexArray::SequenceList sequences = { { startIndex }, { numberOfIndicesToDraw } ) };
GLVBOLib::the().draw( name_, sequences );
}
然后,绘图调用绑定数组/法线/纹理和索引(如果需要)缓冲区。对 glMultiDrawElements 的调用看起来像
glMultiDrawElements( info.mode, sequences.second.data(), GL_UNSIGNED_INT, (const GLvoid **)sequences.first.data(), (GLsizei)sequences.second.size() );
在我的测试用例中,我从 0 开始渲染 75000 个索引。因此,sequences.second 包含 75000 个值,sequence.first 仅包含一个值:0。
现在问题来了:这会崩溃
First-chance exception at 0x000000004735E56B in Application.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
我尝试了很多不同的方法来查找问题,终于找到了一个不会崩溃的变体,而这个变体让我感到困惑。
如果我将向量复制到一个新的局部变量,它就可以工作。由于向量的大小为 1,因此仅此一点不会有问题,但是对于 3000 个索引偏移量,每帧都执行此操作感觉不那么有趣。
// Non crashing version
std::vector< unsigned int > indicesOffset = sequences.first;
// using sequence and indices
glMultiDrawElements( info.mode, sequences.second.data(), GL_UNSIGNED_INT, (const GLvoid **)indicesOffset.data(), (GLsizei)sequences.second.size() );
我的一个同事说这可能与向量的内存对齐有关,说我必须使用 boost 的 boost::aligned_allocator 才能让它工作。
【问题讨论】:
-
如果你使用参考?
std::vector< unsigned int >& indicesOffset = sequences.first; -
这可能与stackoverflow.com/questions/8719287/… 这个问题有关,并且复制向量时它不会崩溃的事实纯属巧合。这只是因为在新创建的向量之后 内存中没有任何内容。我应该有一个 int 指针向量,而不是一个整数向量。
-
你是 64 位的吗?如果是这样,那么我确实可以看到从
unsigned int*转换为GLVoid**的问题 -
是的,我使用的是 64 位。我也认为这是问题所在。