我正在尝试在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。glFinish
和GL_ALL_BARRIER_BITS
只是为了确保同步不是问题。
现在,当我切换glMapNamedBuffer
和glBindBufferBase
的顺序时,我确实得到了正确的回读结果-在AMD GPU上。在这两种情况下,回读都可以在Nvidia GPU上工作。
我注意到glBindBuffer
的文档中指出,“缓冲区对象在第一次绑定后的状态是一个未Map的零大小内存缓冲区[...]"。然而,我使用的是DSA,对于大多数操作,几乎不需要显式绑定缓冲区,glCreateBuffers
还声明它创建了一个新的缓冲区对象“[...],就好像它已经绑定到一个未指定的目标”。
这是AMD GL实现的错误还是我遗漏了什么?有一个简单的解决办法(简单地将缓冲区绑定到一个假目标),但我仍然希望澄清。
1条答案
按热度按时间ffdz8vbo1#
当你持久地Map一个缓冲区时,你必须 * 持久地Map缓冲区 *。分配带有persistent标志的缓冲区只是告诉系统您可以持久地Map它。持久Map要求Map调用 * 本身 * 声明缓冲区被持久Map。
所以
glMapNamedBufferRange
(这是你需要使用的函数)需要有persistent标志。