opengl 缓冲区回读工作取决于绑定/Map与DSA的顺序

6gpjuf90  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(137)

我正在尝试在OpenGL中执行SSBO数据的回读。为此,我持久地MapSSBO,但以下代码实际上并没有从示例计算着色器中读回写入的数据:

std::int32_t value = 12u;
GLuint ssbo = 0u;
glCreateBuffers(1u, &ssbo);
glNamedBufferStorage(ssbo, sizeof(value), &value, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT);
const auto* ptr = reinterpret_cast<const std::int32_t*>(glMapNamedBuffer(ssbo, GL_READ_WRITE));

glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
glDispatchCompute(1, 1, 1);
glFinish();
glMemoryBarrier(GL_ALL_BARRIER_BITS);

std::memcpy(&value, ptr, sizeof(value));
printf("Value: %d\n", value);

计算着色器看起来像这样:

#version 460

layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout (std430, binding = 0) writeonly buffer resBuf { int res[]; };

void main()
{
    res[0] = 25;
}

值的预期结果应该是25,但我仍然得到初始值12。glFinishGL_ALL_BARRIER_BITS只是为了确保同步不是问题。
现在,当我切换glMapNamedBufferglBindBufferBase的顺序时,我确实得到了正确的回读结果-在AMD GPU上。在这两种情况下,回读都可以在Nvidia GPU上工作。
我注意到glBindBuffer的文档中指出,“缓冲区对象在第一次绑定后的状态是一个未Map的零大小内存缓冲区[...]"。然而,我使用的是DSA,对于大多数操作,几乎不需要显式绑定缓冲区,glCreateBuffers还声明它创建了一个新的缓冲区对象“[...],就好像它已经绑定到一个未指定的目标”。
这是AMD GL实现的错误还是我遗漏了什么?有一个简单的解决办法(简单地将缓冲区绑定到一个假目标),但我仍然希望澄清。

ffdz8vbo

ffdz8vbo1#

当你持久地Map一个缓冲区时,你必须 * 持久地Map缓冲区 *。分配带有persistent标志的缓冲区只是告诉系统您可以持久地Map它。持久Map要求Map调用 * 本身 * 声明缓冲区被持久Map。
所以glMapNamedBufferRange(这是你需要使用的函数)需要有persistent标志。

相关问题