6

我有一个与新计算着色器相关的问题。我目前正在研究粒子系统。我将所有粒子存储在着色器存储缓冲区中,以便在计算着色器中访问它们。然后我派出一个一维工作组。

#define WORK_GROUP_SIZE 128
_shaderManager->useProgram("computeProg");
glDispatchCompute((_numParticles/WORK_GROUP_SIZE), 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);

我的计算着色器:

#version 430
struct particle{
         vec4 currentPos;
         vec4 oldPos;
};

layout(std430, binding=0) buffer particles{
         struct particle p[];
};

layout (local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
void main(){
         uint gid = gl_GlobalInvocationID.x;

         p[gid].currentPos.x += 100;
}

但不知何故,并非所有粒子都受到影响。我正在以与此示例中相同的方式执行此操作,但它不起作用。http://education.siggraph.org/media/conference/S2012_Materials/ComputeShader_6pp.pdf

编辑:

在我调用 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT) 之后,我继续这样:

_shaderManager->useProgram("shaderProg"); 
glBindBuffer(GL_ARRAY_BUFFER, shaderStorageBufferID); 
glVertexPointer(4,GL_FLOAT,sizeof(glm::vec4), (void*)0);
glEnableClientState(GL_VERTEX_ARRAY); 
glDrawArrays(GL_POINTS, 0, _numParticles); 
glDisableClientState(GL_VERTEX_ARRAY);

那么在这种情况下哪个位适合使用?

4

2 回答 2

8

你有你的障碍。这是一个常见的问题。

您提供给屏障的位描述了您打算如何使用写入的数据,而不是如何写入数据。GL_SHADER_STORAGE_BARRIER_BIT仅当您有一些进程通过图像加载/存储(或存储缓冲区/原子计数器)写入缓冲区对象,然后使用存储缓冲区读取该缓冲区对象数据时才适用。

由于您将缓冲区作为顶点属性数组缓冲区读取,因此您应该使用巧妙的标题GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT.

于 2012-10-05T08:56:21.763 回答
2

我解决了这个问题。问题只是我派出的工作组的数量。numParticles/WORK_GROUP_SIZE 将被四舍五入,因为这两个变量都是整数。这导致具有不同数量粒子的分派工作组太少。

当我得到 1000 个粒子时,只有 1000/128 = 7 个工作组被调度。每个工作组的大小为 128。这意味着我得到 7*128 = 896 个线程,因此 104 个粒子根本不会移动。由于 numParticles%128 的范围可能在 0...128 之间,我刚刚又派出了一个工作组:

glDispatchCompute((_numParticles/WORK_GROUP_SIZE)+1, 1, 1);

从现在开始,每一个粒子都会移动。:)

于 2012-10-05T18:57:41.090 回答