lwjgl:缓冲区内存管理

x759pob2  于 2021-06-30  发布在  Java
关注(0)|答案(1)|浏览(329)

我在寻找关于哪种方法更好的内存/性能建议。
假设一个网格有4个属性

Vertex    3f
Normal    3f
TexCoords 2f
jointID   4i [Integer Joint Indices For Skeleton Animation]

我需要这些在cpu内存,因为他们可以随时修改
这样更好吗
a、 为每个组件创建4个单独的缓冲区

//3,2,4 are the strides i.e vertex is 3 floats,texCoord is 2 floats so on
FloatBuffer vertices=BufferUtils.createFloatBuffer(numOfVertices*3);
FloatBuffer normals=BufferUtils.createFloatBuffer(numOfVertices*3);
FloatBuffer texCoords=BufferUtils.createFloatBuffer(numOfVertices*2);
IntBuffer   vertexJoints=BufferUtils.createIntBuffer(numOfVertices*4);


b、 创建一个容量足够大的bytebuffer来存储所有4个属性,并为每个属性创建单独的float/int缓冲区视图

ByteBuffer  meshData=BufferUtils.createByteBuffer(((numOfVertices*3)+(numOfVertices*3)+(numOfVertices*2)+(numOfVertices*4))*4); //*4 because both float/int is 4 bytes
 FloatBuffer vertices=meshData.position(0).limit(endVertexByte).asFloatBuffer();
 FloatBuffer normals=meshData.position(endVertexByte).limit(endNormalByte).asFloatBuffer();
 FloatBuffer texCoords=meshData.position(endNormalByte).limit(endTexCoordByte).asFloatBuffer();
 IntBuffer   jointIDs=meshData.position(endTexCoordByte).limit(endJointIndexByte or end of buffer in this case).asIntBuffer();

从docs中,所有bufferutils方法都创建了一个directbuffer,它存储在本机内存中,尽管第二种方法创建的缓冲区比所有单独的属性缓冲区加起来都大[因为我们乘以4],但与第一种方法中的4个独立内存区相比,它只创建了一个较大的本机内存块。
但那只是我的意见,想法?

2admgd59

2admgd591#

当我们从cpu的Angular 来看如何将(新的)数据写入这些缓冲区时,不会有性能上的差异。在这两种情况下,更新顶点的属性数据时,只有四个连续的内存区域。只是在前一种情况下,这些内存区域的偏移量未知(因为jvm的内存分配器将分别分配每个区域),而在后一种情况下,您知道每两个连续内存区域之间的偏移量,因为您在单个jvm缓冲区内存分配中分配了这些区域。
然而,真正不同的是如何将这些客户端主机内存区域Map到服务器端opengl缓冲区对象内存。我假设,一旦您更新了主机端内存,您实际上会将其上载到服务器端opengl缓冲区对象中,而不会将客户端/主机端内存指针用于opengl顶点规范命令(仅在opengl兼容上下文中可用)。
在这种情况下,创建四个独立的连续客户端内存区域将需要执行四个opengl缓冲区内存上载命令( glBufferSubData() )opengl驱动程序通过pcie上传四个不同的直接内存访问(dma)。在只有一个连续的客户端内存区域的情况下,可以只发出一个 glBufferSubData() 将所有顶点属性的数据调用到单个缓冲区对象中,您只需在opengl顶点规范调用中使用字节偏移量(例如 glVertexAttribPointer() ).
另一种可能性是不自己分配客户端主机内存,而是让opengl为您提供主机可见、持久Map的缓冲区( glBufferStorage() + glMapBufferRange() ),然后可以对其进行写入并显式刷新,或者让它们通过opengl驱动程序隐式/一致地更新。与四个单独的客户端内存区域一样,在Map和刷新四个不同的opengl缓冲区对象区域时,您也可能需要支付“四个不同的dma传输”成本。
因此,归根结底,在客户端内存上是否有一个或四个nio缓冲区视图并不重要,而是与Map这些内存区域的服务器端opengl缓冲区对象的数量有关—越少越好。

相关问题