以下情景:
我在系统内存中有一个顶点缓冲区,其地址我每帧都通过glVertexAttribPointer提交给glDrawArrays。渲染API是OpenGL ES 3.0。
现在我的问题:
我可以假设,glDrawArrays会在每次绘制调用时创建缓冲区的完整副本吗?或者,如果我在共享内存平台上,它是否可能直接从缓冲区中提取?
此致
答案 0 :(得分:0)
对于所有海豚,您需要将其视为“它将直接从缓冲区中吸取”。
当设置指针时,你没有告诉openGL有关缓冲区的任何大小,所以在那一点上除了GPU上的一些指针之外根本没有设置或者更确切地说是一个整数值,因为当使用GPU顶点时使用相同的过程缓冲区。
因此,只有在调用draw时才会确定数据大小,您可以在此处说明缓冲区中使用了多少个顶点。在这一点上,我不希望openGL将数据复制到其内部存储器中,但即便如此,它更像是临时数据缓存,仅此而已。这些数据不会通过渲染调用重用,必须再次访问数据。
您需要将数据保留在内存中,并且必须可以访问这些数据。如果它们不再拥有,您可以进行绘制调用以绘制垃圾,如果您无法访问所插入的内存,则甚至会收到崩溃。因此,例如,从在堆栈中分配数据的方法/函数设置指针通常是禁止的。
答案 1 :(得分:0)
我可以假设,glDrawArrays将创建缓冲区的完整副本 每次抽奖?
图形驱动程序非常努力地不复制批量数据缓冲区 - 它非常缓慢且耗能。使用缓冲区而不是客户端阵列的全部意义在于它们可以上传到图形服务器一次,然后只需通过绘图调用引用而无需复制或(在桌面上)通过PCIe传输到图形RAM中。
渲染的行为就像缓冲区已被复制一样(例如,输出必须反映绘制调用时的缓冲区状态,即使它随后被修改)。但是,在大多数情况下,实际上不需要复制。
写得不好的申请可以强制复制;例如,如果您在使用它提交绘图后立即修改缓冲区(例如调用glBufferSubData
),则驱动程序可能需要创建新版本的缓冲区,因为原始数据可能仍然被绘制引用排队。编写良好的应用程序尝试管理其资源更新,因此这不会发生,因为它通常对应用程序呈现性能而言是致命的......