2014-02-06 5 views
1

My other post собирается собирать общую информацию о видах шлейфов GLSL, но, к сожалению, ничего из этого не случилось, и проблема не решена. Поэтому конкретный вопрос. Я уменьшил свою проблему до минимального примера, представленного ниже:Доступ к атомным изображениям GLSL

Тривиальная проблема создает текстуру замков и текстуру цвета размером с экран. В проходе 1 все цвета установлены на ноль (шейдер 1). В проходе два нарисованы два треугольника, которые геометрические шейдеры округляются и слегка смещаются (шейдер 2). Фрагментный шейдер атомарно увеличивает цвет текстуры. В проходе три, цвет визуализируется (шейдер 3).

шейдер 1:

//Vertex 
#version 440 
uniform mat4 mat_P; 
in vec4 _vec_vert_a; 
void main(void) { 
    gl_Position = mat_P*_vec_vert_a; 
} 

//Fragment 
#version 440 
layout(rgba32f) coherent uniform image2D img0; 
void main(void) { 
    imageStore(img0,ivec2(gl_FragCoord.xy),vec4(0.0,0.0,0.0,1.0)); 
    discard; 
} 

шейдер 2:

//Vertex 
#version 440 
in vec4 _vec_vert_a; 
out vec4 vert_vg; 
void main(void) { 
    vert_vg = _vec_vert_a; 
} 

//Geometry 
#version 440 
#define REPS 4 
layout(triangles) in; 
layout(triangle_strip,max_vertices=3*REPS) out; 
uniform mat4 mat_P; 
in vec4 vert_vg[3]; 
void main(void) { 
    for (int rep=0;rep<REPS;++rep) { 
     for (int i=0;i<3;++i) { 
      vec4 vert = vert_vg[i]; 
      vert.xy += vec2(5.0*rep); 
      gl_Position = mat_P*vert; EmitVertex(); 
     } 
     EndPrimitive(); 
    } 
} 

//Fragment 
#version 440 
layout(rgba32f) coherent uniform image2D img0; 
layout(r32ui) coherent uniform uimage2D img1; 
void main(void) { 
    ivec2 coord = ivec2(gl_FragCoord.xy); 
    bool have_written = false; 
    do { 
     bool can_write = (imageAtomicExchange(img1,coord,1u)!=1u); 
     if (can_write) { 
      vec4 data = imageLoad(img0,coord); 
      data.xyz += vec3(1.0,0.0,0.0); 
      imageStore(img0,coord,data); 
      memoryBarrier(); 
      imageAtomicExchange(img1,coord,0); 
      have_written = true; 
     } 
    } while (!have_written); 
    discard; 
} 

шейдер 3:

//Vertex 
#version 440 
uniform mat4 mat_P; 
in vec4 _vec_vert_a; 
void main(void) { 
    gl_Position = mat_P*_vec_vert_a; 
} 

#version 440 
layout(rgba32f) coherent uniform image2D img0; 
void main(void) { 
    vec4 data = imageLoad(img0,ivec2(gl_FragCoord.xy)); 
    gl_FragData[0] = vec4(data.rgb/4.0, 1.0); //tonemap 
} 

Главный цикл:

  1. Enable шейдер 1
  2. визуализации Полноэкранный Quad
  3. glMemoryBarrier (GL_ALL_BARRIER_BITS);

  4. Enable шейдер 2

  5. Рендер два небольших треугольников
  6. glMemoryBarrier (GL_ALL_BARRIER_BITS);

  7. Включить Shader 3

  8. делают Fullscreen квадроциклов

Обратите внимание, что в пунктах 3 и 6 Я [думаю, что я] мог бы использовать GL_SHADER_IMAGE_ACCESS_BARRIER_BIT. На всякий случай, я консервативен.

Визуализированный джиттер цвета со временем и в основном довольно мал. Это показывает, что атомарности не происходит. Может ли кто-то здравомыслие проверить эту процедуру? Я что-то пропустил?

EDIT: From this page, я обнаружил, что использование discard может сделать загрузку/сохранение изображения неопределенным во фрагменте. Я удалил сброс, но проблема все еще возникает. Я также нашел layout(early_fragment_tests) in;, что заставляет ранние фрагментные тесты (это тоже не помогло).

ответ

0

Другой связанный ссылка:
https://www.opengl.org/discussion_boards/showthread.php/182715-Image-load-store-mutex-problem?p=1255935#post1255935

Некоторые спин код блокировки, который работал в прошлый раз, когда я тестировал его (предоставляется несколько лет назад):
http://blog.icare3d.org/2010/07/opengl-40-abuffer-v20-linked-lists-of.html

Другая реализация того же приложения:
https://github.com/OpenGLInsights/OpenGLInsightsCode/blob/master/Chapter%2020%20Efficient%20Layered%20Fragment%20Buffer%20Techniques/lfbPages.glsl

В приведенных выше ссылках используется канарейка, которая определенно была важна и, возможно, все еще есть. coherent важен, но у вас это есть. Несколько лет назад memoryBarrier() просто не был реализован и ничего не сделал. Надеюсь, это не так, однако, возможно, спин-блокировка работает нормально, а записи в img0 не происходят в следующем порядке.

Компиляторы GLSL могут быть немного ошибочными несколько раз. Вот несколько примеров, показывающих, насколько странным может быть кодирование GLSL. Точка, много попыток написания одного и того же кода, может помочь. Я видел проблемы с functions as conditionals inside while loops simply failing. Все, что я знаю, делает ... тогда компилируется совершенно по-другому в типичное время. Иногда может помогать объединение условий в состояние цикла. Иногда else break не так, как ожидалось или позволить компилятор раскатать определенные циклы, и вы должны использовать следующее:

for (...) 
{ 
    if (...) 
    { 
     ... 
     continue; 
    } 
    break; 
} 
+0

Аналого буфера кода не работает (первая версия дает ошибку GL перед визуализацией ничего , о котором я сообщил, и связанный с ним просто сбой). При поиске другого примера кода я также нашел http://soconne.blogspot.com/p/demos.html, некоторые из которых произошли из-за внутренних ошибок компилятора. Я тоже пробовал цикл for. Должен быть лучший способ, чем пытаться перепрограммировать код производителя в рекламе. – imallett

Смежные вопросы