在64位操作系统中使用glMultiDrawElements
Using glMultiDrawElements in 64bit OS
我最近从32位环境迁移到64位环境,除了一个问题之外进展顺利:glMultiDrawElements
使用一些数组在64位操作系统下不进行一些调整就无法工作。
glMultiDrawElements( GL_LINE_LOOP, fCount_, GL_UNSIGNED_INT,
reinterpret_cast< const GLvoid** >( iOffset_ ),
mesh().faces().size() );
我对顶点和顶点索引都使用VBOs。fCount_
和iOffset_
是GLsizei
的阵列。由于缓冲区被绑定到GL_ELEMENT_ARRAY_BUFFER
, iOffset_
的元素被用作VBO开始的字节偏移量。这在32位操作系统下运行良好。
如果我将glMultiDrawElements
更改为glDrawElements
并将其放入循环中,它在两个平台上都能正常工作:
int offset = 0;
for ( Sy_meshData::Faces::ConstIterator i = mesh().faces().constBegin();
i != mesh().faces().constEnd(); ++i ) {
glDrawElements( GL_LINE_LOOP, i->vertexIndices.size(), GL_UNSIGNED_INT,
reinterpret_cast< const GLvoid* >( sizeof( GLsizei ) * offset ) );
offset += i->vertexIndices.size();
}
我认为我所看到的是OpenGL读取iOffset_
的64位块导致大量数字,但glMultiDrawElements
不支持任何大于32位(GL_UNSIGNED_INT
)的类型,所以我不确定如何纠正它。
有其他人遇到过这种情况并解决了吗?或者我完全错误地处理了这个问题,只是幸运地使用了32位操作系统?
更新将我现有的代码替换为:
typedef void ( *testPtr )( GLenum mode, const GLsizei* count, GLenum type,
const GLuint* indices, GLsizei primcount );
testPtr ptr = (testPtr)glMultiDrawElements;
ptr( GL_LINE_LOOP, fCount_, GL_UNSIGNED_INT, iOffset_, mesh().faces().size() );
结果完全相同。
原因很简单,glMultiDrawElements
不期望一个整数偏移量数组(在您的平台上是32位),而是一个指针数组(在您的平台上是64位),解释为缓冲区偏移量。
但是您只是将整数数组(或指针指向)转换为指针数组(或指针指向),这将不起作用,因为该函数现在只是将您的n个连续32位值重新解释为n个连续64位值。当然它适用于glDrawElements
,因为你只是将单个整数转换为单个指针,这实际上是将32位值转换为64位值。
你需要做的不是强制转换你的指针/数组,而是在这个偏移数组中的每个单独的值:
std::vector<void*> pointers(mesh().faces().size());
for(size_t i=0; i<pointers.size(); ++i)
pointers[i] = static_cast<void*>(iOffset_[i]);
glMultiDrawElements( GL_LINE_LOOP, fCount_, GL_UNSIGNED_INT,
&pointers.front(), mesh().faces().size() );
或者更好的做法是,从一开始就将偏移量存储为指针而不是整数。
您遇到了我在https://stackoverflow.com/a/8284829/524368
中详细剖析的问题。我建议你遵循我在答案最后的建议,不要试图将你的数字转换成编译器认为是指针的东西,而是将函数签名转换成接受数字的东西。
注意,在glMultiDrawElements的情况下,第一个间接不会进入VBO,而是进入客户端内存。因此要强制转换的签名是eg.
void myglMultiDrawElementsOffset(GLenum mode,
const GLsizei * count,
GLenum type,
const uintptr_t * indices,
GLsizei primcount);
- 没有找到相关文章