Estou tentando descobrir qual é a melhor maneira de gerar uma textura OpenGL usando um sombreador de computação. Até agora, eu li que os objetos de buffer de pixel são bons para transferências de CPU -> GPU sem bloqueio e que os sombreadores de computação são capazes de ler e escrever buffers, independentemente de como eles estejam vinculados. Idealmente, gostaria de evitar o maior número possível de cópias. Em outras palavras, eu gostaria de alocar um buffer na GPU, gravar dados de textura compactados e usá-lo como objeto de textura em um shader.
Atualmente, meu código é algo como isto:
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);
Isso está correto? Também li em algum lugar sobre a garantia de sincronização. O que preciso adicionar para garantir que meu sombreador de computação conclua a execução antes de copiar do objeto de buffer?
fonte
Respostas:
Depois de analisar isso por um tempo, descobri algumas coisas:
Você não pode evitar um memcpy : não é possível gravar diretamente no armazenamento de textura alocado para uma textura compactada usando apenas chamadas da API OpenGL. Isso significa que você não pode evitar a chamada
glCompressedTexImage2D
com um PBO vinculado. Dito isto, você poderá usar uma textura RGBA de 16 bits e um tipo de imagem GLSL no seu sombreador de computação.Você precisa sincronizar a memória : Para garantir que o seu sombreador de computação termine de gravar no buffer de armazenamento, verifique se todas as leituras e gravações nele terminam. Isso é feito chamando
glMemoryBarrier
comGL_SHADER_STORAGE_BARRIER_BIT
.O código completo de algo que grava em um buffer para ser usado como uma textura compactada se parece com isso:
fonte
GL_SHADER_STORAGE_BARRIER_BIT
Barreira errada. A barreira que você fornece indica como você usará a memória. Não como o shader escreveu para ele. Você está fazendo uma transferência pixel, então você precisa para usoGL_TEXTURE_UPDATE_BARRIER_BIT
GL_TEXTURE_UPDATE_BARRIER_BIT
é usado ao sincronizar chamadasglTexImage
e não tem nada a ver com a memória usada nos buffers de armazenamento. Eu acho que você quis dizerGL_PIXEL_BUFFER_BARRIER_BIT
?