Por que barreira sincroniza a memória compartilhada quando o memoryBarrier não faz?
O seguinte sombreador de computação GLSL simplesmente copiainImage
paraoutImage
. É derivado de um passe de pós-processamento mais complexo.
Nas primeiras várias linhas demain()
, um único thread carrega 64 pixels de dados no array compartilhado. Em seguida, após a sincronização, cada um dos 64 segmentos grava um pixel na imagem de saída.
Dependendo de como sincronizo, obtenho resultados diferentes. Eu originalmente penseimemoryBarrierShared()
seria a chamada correta, mas produz o seguinte resultado:
que é o mesmo resultado de não ter sincronização ou usarmemoryBarrier()
em vez de.
Se eu usarbarrier()
, Recebo o seguinte resultado (desejado):
A distribuição tem 32 pixels de largura e, se eu alterar o tamanho do grupo de trabalho para algo menor ou igual a 32, obtenho resultados corretos.
Oque esta acontecendo aqui? Eu estou entendendo errado o propósito dememoryBarrierShared()
? Porque deveriabarrier()
trabalhos?
#version 430
#define SIZE 64
layout (local_size_x = SIZE, local_size_y = 1, local_size_z = 1) in;
layout(rgba32f) uniform readonly image2D inImage;
uniform writeonly image2D outImage;
shared vec4 shared_data[SIZE];
void main() {
ivec2 base = ivec2(gl_WorkGroupID.xy * gl_WorkGroupSize.xy);
ivec2 my_index = base + ivec2(gl_LocalInvocationID.x,0);
if (gl_LocalInvocationID.x == 0) {
for (int i = 0; i < SIZE; i++) {
shared_data[i] = imageLoad(inImage, base + ivec2(i,0));
}
}
// with no synchronization: stripes
// memoryBarrier(); // stripes
// memoryBarrierShared(); // stripes
// barrier(); // works
imageStore(outImage, my_index, shared_data[gl_LocalInvocationID.x]);
}