Неверный результат при использовании glTexSubimage3D для загрузки данных из неизменяемого pbo - PullRequest
0 голосов
/ 07 января 2019

Я реализую внешний алгоритм для рендеринга объемных данных. На каждом этапе рендеринга рабочие наборы (много пропущенных блоков данных, например, 64 ^ 3) должны загружаться в GPU с использованием glTexSubImage3D из PBO. Применение 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();
...