Scrivere su una trama compressa usando uno shader di calcolo, senza copie extra


8

Sto cercando di capire quale sia il modo migliore per generare una trama OpenGL usando uno shader di calcolo. Finora, ho letto che gli oggetti pixel buffer sono buoni per CPU non bloccanti -> trasferimenti GPU e che gli shader di calcolo sono in grado di leggere e scrivere buffer indipendentemente da come sono associati. Idealmente, vorrei evitare quante più copie possibile. In altre parole, vorrei allocare un buffer sulla GPU, scrivere dati di trama compressi su di esso e quindi utilizzare quel buffer come oggetto trama in uno shader.

Attualmente, il mio codice è simile al seguente:

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

È corretto? Ho letto da qualche parte anche su come garantire la sincronizzazione. Cosa devo aggiungere per assicurarmi che il mio shader di calcolo completi l'esecuzione prima di copiare dall'oggetto buffer?


Vorresti specificare quale formato di compressione delle trame preferisci? Immagino, ma la tua risposta probabilmente coinvolgerà una routine di compressione delle trame in modalità di calcolo.
ap_

Risposte:


3

Dopo aver esaminato questo per un po ', ho scoperto un paio di cose:

  1. Non è possibile evitare un memcpy : non è possibile scrivere direttamente nella memoria delle trame allocata per una trama compressa usando solo chiamate API OpenGL. Ciò significa che non è possibile evitare la chiamata glCompressedTexImage2Dcon un PBO associato. Detto questo, potresti essere in grado di utilizzare una trama RGBA a 16 bit e un tipo di immagine GLSL nel tuo shader di calcolo.

  2. È necessario sincronizzare la memoria : per assicurarsi che lo shader di elaborazione finisca di scrivere sul buffer di archiviazione, è necessario assicurarsi che tutte le letture e le scritture vengano completate. Questo viene fatto chiamando glMemoryBarriercon GL_SHADER_STORAGE_BARRIER_BIT.

Il codice completo per qualcosa che scrive in un buffer da utilizzare come texture compressa è simile al seguente:

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

"potresti essere in grado di usare una trama RGBA a 16 bit e un" AND A WHAT ??? :)
Nathan Reed,

2
Haha, questo è ciò che accade quando lasci la scheda aperta per terminare in seguito. Modificato.
Mokosha,

1
GL_SHADER_STORAGE_BARRIER_BITBarriera sbagliata. La barriera fornita indica come verrà utilizzata la memoria. Non come lo shader gli ha scritto. Stai effettuando un trasferimento di pixel, quindi devi usarloGL_TEXTURE_UPDATE_BARRIER_BIT
Nicol Bolas il

1
Sei sicuro? Secondo i documenti , GL_TEXTURE_UPDATE_BARRIER_BITviene utilizzato durante la sincronizzazione delle chiamate glTexImagee non ha nulla a che fare con la memoria utilizzata nei buffer di archiviazione. Penso che volevi dire GL_PIXEL_BUFFER_BARRIER_BIT?
Mokosha,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.