2016-12-16 5 views
4

Я пытаюсь написать общую реализацию гауссово-размытия общего вычислительного шейдера.Вычислительная шейдерная общая память содержит артефакты

В основном он работает, однако он содержит артефакты, которые меняют каждый кадр, даже когда сцена статична. Я провел последние несколько часов, пытаясь отладить это. Я дошел до того, что границы не превышены, разворачиваются все петли, заменяются униформы постоянными, но артефакты сохраняются.

Я тестировал исходный код с артефактами на трех разных машинах/графических процессорах (2 nvidia, 1 intel), и все они дают одинаковые результаты. Имитация развернутой/постоянной версии выполнения кодов с рабочими группами, выполненными вперед и назад с помощью простого кода на C++, не вызывает этих ошибок.

enter image description here

При выделении общего массива [96] [96] вместо [16] [48] можно устранить большинство из артефактов.

Это привело меня к мысли о том, что мне не хватает логической ошибки, поэтому мне удалось создать очень простой шейдер, который все еще производит ошибку в меньших масштабах, я был бы признателен, если бы кто-нибудь мог указать на причину , Я проверил много документации и не нашел ничего неправильного.

Предоставлен общий массив с поплавками 16x48, это 3072 байта, примерно 10% от минимального предела общей памяти.

Затенение запускаются в 16x16 рабочих группах, так что каждый поток будет написать 3 уникальных места, и считывается из одного уникального местоположения

текстуры затем рендерера, как ВПГ в результате чего между Vals 0-1 будет отображаться на оттенок 0-360 (красный-голубой-красный), а значения из границ будут красными.

#version 430 
//Execute in 16x16 sized thread blocks 
layout(local_size_x=16,local_size_y=16) in; 
uniform layout (r32f) restrict writeonly image2D _imageOut; 
shared float hoz[16][48]; 
void main() 
{ 
    //Init shared memory with a big out of bounds value we can identify 
    hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y] = 20000.0f; 
    hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y+16] = 20000.0f; 
    hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y+32] = 20000.0f; 
    //Sync shared memory 
    memoryBarrierShared(); 
    //Write the values we want to actually read back 
    hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y] = 0.5f; 
    hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y+16] = 0.5f; 
    hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y+32] = 0.5f; 
    //Sync shared memory 
    memoryBarrierShared(); 
    //i=0,8,16 work 
    //i=1-7,9-5,17 don't work (haven't bothered testing further 
    const int i = 17; 
    imageStore(_imageOut, ivec2(gl_GlobalInvocationID.xy), vec4(hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y+i])); 
    //Sync shared memory (can't hurt) 
    memoryBarrierShared(); 
} 

Запуск этого шейдера с размерами запуска больше, чем 8х8 производит артефакты в пораженной области изображения.

glDispatchCompute(9, 9, 0); glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);

мне пришлось останова и шаг кадров, чтобы захватить это, занимает около 14 кадров enter image description here

glDispatchCompute(512/16, 512/16, 0);//Full image is 512x512 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);

Снова пришлось останова и шаг кадров, чтобы захватить это, при работе с 60FPS (vsync) артефакты появлялись чаще/одновременно.

enter image description here

ответ

5
memoryBarrierShared(); 

Нет, это только делает пишет видимую других вызовов. Вы должны убедиться, что все записи на самом деле произошло, если вы хотите быть в состоянии читать из других данных invocations.

То, что сделано с the barrier function. Который следует назвать послеmemoryBarrierShared.

+0

Спасибо, это исправлено. Тем не менее, слишком быстро снимать документы. – Robadob

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