OpenGL Compute Shader Invocations

У меня вопрос, связанный с новыми вычислительными шейдерами. В настоящее время я работаю над системой частиц. Я храню все свои частицы в буфере хранения шейдеров для доступа к ним в вычислительном шейдере. Затем я отправляю одномерную рабочую группу.

#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);

Так какой бит будет уместно использовать в этом случае?

6

Решение

У вас есть барьеры назад. Это общая проблема.

Биты, которые вы даете барьеру, описывают, как вы собираетесь использовать записанные данные, не так, как данные были написаны. GL_SHADER_STORAGE_BARRIER_BIT было бы уместно, только если у вас был какой-то процесс, который записывал в буферный объект через загрузку / хранение изображения (или буфер хранения / атомарные счетчики), а затем использовал буфер хранения для чтения данных этого объекта буфера.

Так как вы читаете буфер как буфер массива атрибутов вершин, вы должны использовать умный заголовок, GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT,

8

Другие решения

Я решил проблему. Проблема была только в количестве рабочих групп, которые я отправил.
Значение 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);

И теперь каждая частица движется. 🙂

1

По вопросам рекламы [email protected]