Запись в сжатую текстуру с использованием вычислительного шейдера без лишних копий

8

Я пытаюсь выяснить, как лучше всего создать текстуру OpenGL с помощью вычислительного шейдера. До сих пор я читал, что объекты пиксельного буфера хороши для неблокирующей передачи CPU -> GPU, и что вычислительные шейдеры способны читать и записывать буферы независимо от того, как они связаны. В идеале я хотел бы избежать как можно большего количества копий. Другими словами, я хотел бы выделить буфер на GPU, записать сжатые данные текстуры в него, а затем использовать этот буфер в качестве объекта текстуры в шейдере.

В настоящее время мой код выглядит примерно так:

GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
glBufferStorage(GL_SHADER_STORAGE_BUFFER, tex_size_in_bytes, 0, 0);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);

// Bind buffer to resource in compute shader
// execute compute shader

glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, fmt, w, h, 0, tex_size_in_bytes, 0);

Это правильно? Я тоже где-то читал о гарантии синхронизации. Что мне нужно добавить, чтобы убедиться, что мой вычислительный шейдер завершает выполнение до копирования из объекта буфера?

Mokosha
источник
Вы хотите указать, какой формат сжатия текстур вы предпочитаете? Я предполагаю, но ваш ответ, вероятно, будет включать в себя процедуру сжатия текстур в вычислительном режиме.
ap_

Ответы:

3

Посмотрев на это некоторое время, я обнаружил пару вещей:

  1. Вы не можете избежать использования memcpy : вы не можете писать напрямую в хранилище текстур, выделенное для сжатой текстуры, используя только вызовы API OpenGL. Это означает, что вы не можете избежать вызова glCompressedTexImage2Dс привязанным PBO. При этом вы можете использовать 16-битную текстуру RGBA и тип изображения GLSL в своем вычислительном шейдере.

  2. Вам необходимо синхронизировать память : чтобы убедиться, что ваш вычислительный шейдер завершает запись в буфер хранения, вы должны убедиться, что все операции чтения и записи в него завершены. Это делается по телефону glMemoryBarrierс GL_SHADER_STORAGE_BARRIER_BIT.

Полный код для чего-то, что записывает в буфер для использования в качестве сжатой текстуры, выглядит следующим образом:

GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
glBufferStorage(GL_SHADER_STORAGE_BUFFER, tex_size_in_bytes, 0, 0);

glUseProgram(compute_shader_prog);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, compute_shader_bind_point, buffer);
glDispatchCompute(wg_x, wg_y, wg_z);
glMemoryBarrier(GL_SHADER_STORAGE_BUFFER_BIT);

glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, fmt, w, h, 0, tex_size_in_bytes, 0);
Mokosha
источник
"Вы можете использовать 16-битную RGBA-текстуру и" И ЧТО ??? :)
Натан Рид
2
Ха-ха, это то, что происходит, когда вы оставляете вкладку открытой, чтобы закончить позже. Ред.
Мокоша
1
GL_SHADER_STORAGE_BARRIER_BITНеправильный барьер. Предоставляемый вами барьер указывает, как вы будете использовать память. Не так, как шейдер написал в него. Вы делаете передачу пикселей, поэтому вам нужно использоватьGL_TEXTURE_UPDATE_BARRIER_BIT
Николь Болас
1
Ты уверен? Согласно документации , GL_TEXTURE_UPDATE_BARRIER_BITиспользуется при синхронизации вызовов glTexImageи не имеет ничего общего с памятью, используемой в буферах хранения. Я думаю ты имел ввиду GL_PIXEL_BUFFER_BARRIER_BIT?
Мокоша