I created a single pass gaussian blur using HLSL compute shader. I also want it to be separable, which means, that first I perform blur along the horizontal direction, write out the result to the texture, then perform the vertical blur with the horizontally blurred data.
I do this by creating DeviceMemoryBarriers before and after writing out the blur results to the globallycoherent Texture2D.
This is my shader:
Texture2D<float4> input:register(t0);
globallycoherent RWTexture2D<float4> input_output:register(u0);
// Note: Shader requires feature: Typed UAV additional format loads!
[numthreads(16, 16, 1)]
void main(uint3 DTid : SV_DispatchThreadID)
{
// Query the texture dimensions (width, height):
uint2 dim;
input_output.GetDimensions(dim.x, dim.y);
// Determine if the thread is alive (it is alive when the dispatchthreadID can directly index a pixel)
if (DTid.x < dim.x && DTid.y < dim.y)
{
// Do bilinear downsampling first and write it out:
input_output[DTid.xy] = input.SampleLevel(sampler_linear_clamp, ((float2)DTid + 0.5f) / (float2)dim, 0);
DeviceMemoryBarrier();
uint i = 0;
float4 sum = 0;
// Gather samples in the X (horizontal) direction:
[unroll]
for (i = 0; i < 9; ++i)
{
sum += input_output[DTid.xy + uint2(gaussianOffsets[i], 0)] * gaussianWeightsNormalized[i];
}
// Write out the result of the horizontal blur:
DeviceMemoryBarrier();
input_output[DTid.xy] = sum;
DeviceMemoryBarrier();
sum = 0;
// Gather samples in the Y (vertical) direction:
[unroll]
for (i = 0; i < 9; ++i)
{
sum += input_output[DTid.xy + uint2(0, gaussianOffsets[i])] * gaussianWeightsNormalized[i];
}
// Write out the result of the vertical blur:
DeviceMemoryBarrier();
input_output[DTid.xy] = sum;
}
}
The problem is that the result flickers a bit, and has some errors in the image, too. Seems a bit like a thread group can't see writes by other groups.
But there is a globallycoherent modifier before the RWTexture2D which should flush the entire resource so that writes are visible in every thread group (MSDN). Indeed, if I remove that modifier, then the flickering becomes a whole lot worse than if I leave it there.
Here is a screenshot of the problem:
(Notice the lines on the windmill, and it also flickers on the whole image from time to time which is not visible on a still shot)
Anyone here has an idea what I can do about it? (PS. the blur is performed when creating mipmaps, so I very much want to avoid multiple passes because it is already one pass for each mip)