Hello,
I'm currently trying out a very simple bloom solution using compute.
The idea is to recursively downsample the rendered HDR texture until this condition is met "(width ≤ 4 || height ≤ 4)".
and then start upsampling the downsampled textures in the reversed order.
Both shaders are extremely simple and really just takes a few samples around the current pixel and adds them.
The upsample also lerps between the current value and the upsampled value using a “strength” setting as factor.
Now the issue is that I'm getting severe flickering artifacts, in kind of a “tiled” looking pattern.
I've located the issue to being in the upsampling, where I actually sample the lower res texture.
But I really can't figure out what the cause would be, because all numbers looks correct when capturing.
Now for the most annoying issue, the error appears in PIX, but only if I click around the different events a bit.
For example if I look at each step in the upsample chain, the output in PIX is actually correct. However if I look at one step back in the chain the output gets “broken” and the artifacts show.
I've included some images to try to explain it further.
This is how the final Bloom texture (quarter size of full res) looks like in engine.
Notice the blocky artifacts.
Here's the output according to PIX when just traversing the events in the upsample chain.
But here's the same output from PIX, but I simply took a look at the event above and then went back.
Now I've never had this issue before, especially not that the same event in PIX gets broken depending on what you click on before. It really feels like a compute thread issue or corrupt data. But I have no idea.
Has anyone experienced anything similar before?
Does the unexpected behaviour of PIX ring a bell for anyone?
// THIS IS THE UPSAMPLE SHADER
Texture2D Source : register(t0);
// HALF-SIZED SOURCE TEXTURE
cbuffer Constants : register(b0)
{
float2 myMinUV; // Basically always 0.0
float2 myMaxUV; // Basically always 1.0
float2 myTexelSizeAndUVScale; // 1.0 / OutputTexture Size
float2 myScaleFilter; // (x: 1.75, y: 1.25)
int2 myDestOffset; // (x: 0, y: 0)
float myStrength; // 0.63
}
RWTexture2D<float3> Output : register(u0);
// CURRENT SIZED OUTPUT TEXTURE (ALREADY HAS DOWNSAMPLED DATA FROM DOWNSAMPLE PASS)
float3 SampleSource(float2 aUV)
{
// SAMPLER IS MIN_MAG_LINEAR_MIP_POINT
return SR_SampleLod0(SamplerLinearClamp, Source, clamp(aUV * myTexelSizeAndUVScale, myMinUV, myMaxUV)).xyz;
}
[numthreads(8,8,1)]
void main(uint3 threadIndex : SV_DispatchThreadId)
{
float2 uv = float2(threadIndex.xy) + float2(0.5, 0.5);
float x0 = -myScaleFilter.x;
float x1 = 0.0;
float x2 = myScaleFilter.x;
float y0 = -myScaleFilter.y;
float y1 = 0.0;
float y2 = myScaleFilter.y;
float3 sample00 = SampleSource(uv + float2(x0, y0));
float3 sample01 = SampleSource(uv + float2(x0, y1));
float3 sample02 = SampleSource(uv + float2(x0, y2));
float3 sample10 = SampleSource(uv + float2(x1, y0));
float3 sample11 = SampleSource(uv + float2(x1, y1));
float3 sample12 = SampleSource(uv + float2(x1, y2));
float3 sample20 = SampleSource(uv + float2(x2, y0));
float3 sample21 = SampleSource(uv + float2(x2, y1));
float3 sample22 = SampleSource(uv + float2(x2, y2));
float3 sampleValue = ((sample00 + sample20 + sample02 + sample22) + ((sample10 + sample01 + sample21 + sample12) * 2.0) + (sample11 * 4.0)) / 16.0;
float3 dest = Output[threadIndex.xy].xyz;
Output[threadIndex.xy] = lerp(dest, sampleValue, myStrength);
}
Worth noting is that the D3D12DebugLayer doesn't throw any errors or warnings at all during execution.
Thanks,
Baemz