Чтение и запись в буфер во фрагментном шейдере - PullRequest
0 голосов
/ 13 марта 2020

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

#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(location = 0) in vec2 inPosition;

layout(location = 0) out vec4 outColor;

layout(std140, binding = 0) buffer CommandDraw {
    uint indexCount;
    uint instanceCount;
    uint firstIndex;
    int vertexOffset;
    uint firstInstance;
};

layout(std430, binding = 1) buffer SSBO {
    float data[];
};

void addVertex(vec4 pos, vec4 color)
{
    uint id = indexCount++;
    uint offset = id * 8;

    data[offset] = pos.x;
    data[offset + 1] = pos.y;
    data[offset + 2] = pos.z;
    data[offset + 3] = pos.w;

    data[offset + 4] = color.x;
    data[offset + 5] = color.y;
    data[offset + 6] = color.z;
    data[offset + 7] = color.w;
}

void main() 
{
    vec3 color = vec3(0.0);
    addVertex(vec4(inPosition, 0.0, 1.0), vec4(1.0, 0.0, 0.0, 1.0));

    outColor = vec4(inPosition / 2.0 + vec2(0.5), 0.0, 1.0);
}

Я выполняю фрагментный шейдер с полноэкранным квадратором. Проблема в том, что окончательное смещение (здесь indexCount) слишком мало: оно должно быть равно width * height, но значение ниже (около 60 для экстента, равного 1280 * 720).

Я думаю, что проблема связана с параллельным выполнением фрагментного шейдера: некоторый фрагмент может использовать один и тот же буфер в одно и то же время.

Мой вопрос: возможно ли "заблокировать" ресурс, как с std::mutex чтобы избежать фрагмента, использующего один и тот же ресурс одновременно?

1 Ответ

1 голос
/ 13 марта 2020

Нет необходимости в мьютексе; просто используйте atomi c приращение значения индекса :

uint id = atomicAdd(indexCount, 1);

Все эти функции atomi c возвращают предыдущее значение. Таким образом, ваш код должен быть в порядке.

И нет никакого смысла в создании выходного SSBO, если вы вообще не собираетесь сжимать данные (то есть, если вы просто пишете числа с плавающей запятой). Лучше сделать так, чтобы он отражал типы переменных, которые вы пишете:

struct Vertex
{
  vec4 pos;
  vec4 color;
};

layout(std430, binding = 1) writeonly restrict buffer SSBO {
    Vertex vertices[];
};
...