首页 > 解决方案 > 读取和写入片段着色器中的缓冲区

问题描述

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

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

我认为问题在于片段着色器的并行执行:某些片段可能同时使用相同的缓冲区。

我的问题是:是否可以像使用 a 一样“锁定”资源std::mutex以避免片段同时使用相同的资源?

标签: c++glslfragment-shadervulkan

解决方案


不需要互斥锁;只需使用索引值的原子增量

uint id = atomicAdd(indexCount, 1);

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

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

struct Vertex
{
  vec4 pos;
  vec4 color;
};

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

推荐阅读