2016-02-26 121 views
0

我有一个使用6 GL计算着色器序列的Marching Cubes的GPU实现,每个读取缓冲区之前写入的缓冲区都有相应的内存屏障。早期阶段中使用的缓冲区保存临时标记变量,并且在不再需要时将其大小调整为0,但不会删除,因为我将在稍后的运行中再次使用它们。从GL计算着色器读取缓冲区后释放缓冲区

在某些阶段,我需要从着色器中的缓冲区中读取数据,然后在着色器完成之后立即释放它,然后为下一个着色器阶段分配缓冲区。我的问题是如何安全地做到这一点。内存屏障文档讲述了如何在允许其他着色器读取之前确保完成所有写入操作,但在第一个着色器中没有提到读取操作。

如果我做的:

glUseProgram(firstShader); 
glDispatchCompute(size,1,1); 
glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 
glNamedBufferData(firstBuffer,0,NULL,GL_DYNAMIC_DRAW); 
glNamedBufferData(secondBuffer,1000000,&data,GL_DYNAMIC_DRAW); 
glUseProgram(secondShader); 
glDispatchCompute(size,1,1); 

firstBuffer不能保证被调整,直至firstShader完成从中读取?如果不是,我该如何做到这一点?

+0

请注意,在您的主要性能循环中分配/释放内存不会在性能方面为您带来任何收益。事实上,如果重构计算着色器以使用共享变量而不是多次通过并读取/写入GPU内存,则可能会从算法中获得更多。 –

+0

感谢您的评论Nicol。我正在建模非常大的网格,所以问题是内存使用而不是性能。我使用第一对通道来收集样本,并找到生成几何图形的立方体,以便从那时起可以减少大量的调用次数。有几点我必须将整个样本空间保留在内存中,这可能需要几百MB,所以我希望在完成后立即摆脱它。不知道如何去使用共享变量,因为它们非常小并且仅限于单个工作组? – russ

回答

0

并且在不再需要时应将其调整为0,但不会删除,因为我会再次希望它们用于以后的运行。

调整缓冲区大小等效于删除缓冲区,并在同一个ID上分配新的缓冲区。

在某些阶段,我需要从着色器中的缓冲区中读取数据,然后在着色器完成之后立即释放它,然后为下一个着色阶段分配缓冲区。我的问题是如何安全地做到这一点。

只要删除它即可。在第一阶段删除缓冲区只会删除该ID。该id只是对实际缓冲区对象的另一个引用。当调整大小或删除缓冲区时,只有id和实际缓冲区之间的关联被切断。调整大小实际上会创建一个新的缓冲区,并将其重新与其关联。实际上调用glBufferData将做同样的事情(与glBufferSubData相反)。这被称为“孤儿”。

实际的缓冲区被释放,一旦它的最后一个引用,无论是通过使用或从一个ID,下降。

+0

谢谢,这就是我需要知道的一切:) – russ