Escribir en una textura comprimida usando un sombreador de cómputo, sin copias adicionales

8

Estoy tratando de descubrir cuál es la mejor manera de generar una textura OpenGL usando un sombreador de cómputo. Hasta ahora, he leído que los objetos de búfer de píxeles son buenos para CPU sin bloqueo -> transferencias de GPU, y que los sombreadores de cómputo son capaces de leer y escribir búferes independientemente de cómo estén vinculados. Idealmente, me gustaría evitar tantas copias como sea posible. En otras palabras, me gustaría asignar un búfer en la GPU, escribir datos de textura comprimidos y luego usar ese búfer como un objeto de textura en un sombreador.

Actualmente, mi código se parece a esto:

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);

¿Es esto correcto? También leí en alguna parte sobre garantizar la sincronización. ¿Qué necesito agregar para asegurarme de que mi sombreador de cómputo complete la ejecución antes de copiar desde el objeto de búfer?

Mokosha
fuente
¿Desea especificar qué formato de compresión de textura prefiere? Supongo que su respuesta probablemente involucrará una rutina de compresión de texturas en modo de cómputo.
ap_

Respuestas:

3

Después de investigar esto por un tiempo, descubrí un par de cosas:

  1. No puede evitar una memoria : no puede escribir directamente en el almacenamiento de texturas asignado para una textura comprimida utilizando solo llamadas de API OpenGL. Esto significa que no puede evitar la llamada glCompressedTexImage2Dcon un PBO vinculado. Dicho esto, es posible que pueda usar una textura RGBA de 16 bits y un tipo de imagen GLSL en su sombreador de cómputo.

  2. Debe sincronizar la memoria : para asegurarse de que su sombreador de cómputo termine de escribir en su búfer de almacenamiento, debe asegurarse de que todas las lecturas y escrituras terminen. Esto se hace llamando glMemoryBarriera GL_SHADER_STORAGE_BARRIER_BIT.

El código completo de algo que se escribe en un búfer para ser usado como una textura comprimida se ve así:

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
fuente
"es posible que pueda usar una textura RGBA de 16 bits y un" ¿Y QUÉ? :)
Nathan Reed
2
Jaja, esto es lo que sucede cuando dejas la pestaña abierta para terminar más tarde. Editado
Mokosha
1
GL_SHADER_STORAGE_BARRIER_BITBarrera equivocada. La barrera que proporciona establece cómo utilizará la memoria. No cómo le escribió el sombreador. Estás haciendo una transferencia de píxeles, por lo que debes usarloGL_TEXTURE_UPDATE_BARRIER_BIT
Nicol Bolas
1
¿Estás seguro? Según los documentos , GL_TEXTURE_UPDATE_BARRIER_BITse utiliza al sincronizar llamadas glTexImagey no tiene nada que ver con la memoria utilizada en las memorias intermedias de almacenamiento. Creo que quisiste decir GL_PIXEL_BUFFER_BARRIER_BIT?
Mokosha