读取和写入片段着色器中的缓冲区

Read and write to a buffer in a fragment shader

我正在尝试在片段中使用缓冲区,例如追加缓冲区:对于片段着色器的每次执行,我都会获取缓冲区的偏移量,添加数据并增加偏移量。

#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 一样 "lock" 资源来避免片段同时使用相同的资源?

不需要互斥;只需使用 atomic increment of the index value:

uint id = atomicAdd(indexCount, 1);

所有这些原子函数 return 以前的值。所以你的代码应该没问题。

如果您根本不打算压缩数据(也就是说,如果您只是编写浮点数),那么制作输出 SSBO 真的毫无意义。最好让它反映您正在编写的变量类型:

struct Vertex
{
  vec4 pos;
  vec4 color;
};

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