在64位操作系统中使用glMultiDrawElements

Using glMultiDrawElements in 64bit OS

本文关键字:glMultiDrawElements 64位 操作系统      更新时间:2023-10-16

我最近从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);
相关文章:
  • 没有找到相关文章