Обновление SSBO в вычислительном шейдере

В настоящее время я пытаюсь обновить SSBO, связанный/привязанный к Computeshader. Делая это таким образом, я записываю только первые 32 байта в out_picture, потому что я только memcpy столько (sizeof(pstruct)).

Вычислительный шейдер:

#version 440 core

struct Pstruct{
  float picture[1920*1080*3];
  float factor;
};

layout(std430, binding = 0) buffer Result{
  float out_picture[];
};
layout(std430, binding = 1) buffer In_p1{
  Pstruct in_p1;
};
layout(local_size_x = 1000) in;

void main() {

    out_picture[gl_GlobalInvocationID.x] = out_picture[gl_GlobalInvocationID.x]  +
                                           in_p1.picture[gl_GlobalInvocationID.x] * in_p1.factor;

}

GLSL:

struct Pstruct{
   std::vector<float> picture;
   float factor;
};

Pstruct tmp;
tmp.factor = 1.0f;
for(int i = 0; i < getNUM_PIX(); i++){
   tmp.picture.push_back(5.0f);
}

SSBO ssbo;
glGenBuffers(1, &ssbo.handle);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssbo.handle);
glBufferData(GL_SHADER_STORAGE_BUFFER, (getNUM_PIX() + 1) * sizeof(float), NULL, GL_DYNAMIC_DRAW);

...

glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo.handle);
Pstruct* ptr = (Pstruct *) glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY);
memcpy(ptr, &pstruct, sizeof(pstruct));
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);

...

glUseProgram(program);
glDispatchCompute(getNUM_PIX() / getWORK_GROUP_SIZE(), 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);

Как я могу одновременно скопировать мои picture array и мои float factor? Должен ли я разделить вызов memcpy на массив и поплавок? и если да то как? Я могу скопировать первую часть, но мне не разрешено добавлять смещение к ptr.


person Blank    schedule 23.08.2018    source источник


Ответы (1)


Прежде всего,

float picture[1920*1080*3];

явно должна быть либо текстура (вы все равно только читаете из нее), либо, по крайней мере, изображение.

Второй:

struct Pstruct{
   std::vector<float> picture;
   float factor;
};

Это определение никоим образом не соответствует определению в вашем шейдере. Объект std::vector будет просто метаобъектом, внутренне управляющим хранилищем данных, используемым вектором. memcpy это в буфер GL и передача его в GPU вообще не имеет смысла.

Правильным подходом было бы либо скопировать содержимое этого вектора отдельно в соответствующие места внутри буфера, либо просто использовать определение структуры на стороне вашего клиента, которое фактически соответствует тому, которое вы используете в шейдер (и с учетом всех правил std430). Но, как уже было сказано в моем первом замечании, правильное решение здесь, скорее всего, будет использовать вместо этого объект текстуры или изображения.

person derhass    schedule 23.08.2018
comment
не снизит ли числовая точность превращение его в image2d? image2D принимает максимум RBGA8? в противном случае это было бы абсолютно правильно, не подумал об этом. - person Blank; 23.08.2018
comment
Нет, вы можете иметь полную 32-битную текстуру и изображения с плавающей запятой на канал, см. формат GL_RGBA32F. - person derhass; 23.08.2018