我正在实现一种用于渲染体积数据的核外算法。在每个渲染过程中,应使用PBO中的glTexSubImage3D
将工作集(许多丢失的数据块,例如64 ^ 3)上传到GPU。为每个块应用glMapBuffer
非常昂贵,因此我使用了一个不变的PBO,因此映射操作仅需要执行一次。为了提高效率,我采用了乒乓更新策略。
这是我的代码
// Generating immutable PBO
GLbitfield flgs = GL_MAP_PERSISTENT_BIT |GL_MAP_COHERENT_BIT |
GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
glGenBuffers(1, &g_pingPBO);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, g_pingPBO);
glBufferStorage(GL_PIXEL_UNPACK_BUFFER, blockBytes, nullptr,flgs);
g_pboPtr[0] =
(char*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER,0,blockBytes,flgs);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glGenBuffers(1, &g_pongPBO);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, g_pongPBO);
glBufferStorage(GL_PIXEL_UNPACK_BUFFER, blockBytes, nullptr,flgs);
g_pboPtr[1] = (char*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, blockBytes,
flgs);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
// Upload
g_texCache->Bind();
unsigned int pbo[2] = { g_pingPBO,g_pongPBO };
auto curPBO = 0;
auto i = 0;
// pointer dd is the block data on cpu
memcpy(g_pboPtr[1-curPBO], dd, blockBytes);
for (; i < missedBlocks - 1;)
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo[1 - curPBO]);
// glTexSubImage3D here
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
i++;
const auto & index = g_hits[i];
// pointer d is the block data on cpu
memcpy(g_pboPtr[curPBO], d, blockBytes);
curPBO = 1 - curPBO;
}
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo[1 - curPBO]);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
g_texCache->Unbind();
根本没有OpenGL运行时错误。只是块的位置不应该在该位置。
但是以下代码获得了正确的结果:
std::shared_ptr<OpenGLBuffer> pbo[2] = { g_blockPingBuf,g_blockPongBuf };
auto curPBO = 0;
auto i = 0;
const auto & idx = g_hits[i];
const auto dd = g_largeVolumeData->ReadBlockDataFromCache(idx);
pbo[1 - curPBO]->Bind();
auto pp = pbo[1 - curPBO]->Map(OpenGLBuffer::WriteOnly);
memcpy(pp, dd, blockBytes);
pbo[1 - curPBO]->Unmap(); // copy data to pbo
pbo[1 - curPBO]->Bind();
g_texCache->Bind();
for (;i < missedBlocks-1;)
{
pbo[1 - curPBO]->Bind();
// glTexSubImage3D here
pbo[1 - curPBO]->Unbind();
i++;
pbo[curPBO]->Bind();
auto p = pbo[curPBO]->Map(OpenGLBuffer::WriteOnly);
memcpy(p, d, blockBytes);
pbo[curPBO]->Unmap(); // copy data to pbo
curPBO = 1 - curPBO;
}
pbo[1 - curPBO]->Bind();
// glTexSubImage3D here
pbo[1 - curPBO]->Unbind();