I am implementing a post-processing effect in my DirectX 11 pet renderer. The post-processing pass is implemented by rendering a full-screen quad covered with texture containing original rendered image, which works as it should, but I have problems with downscaling the texture.
The non-processed testing scene looks like this (three very bright emmissive spheres):
I see no problem at this stage, but when I run the first post-processing pass, which just down-scales the image by the factor of 8 using the texture sampler, the result is very flickery (up-scaled for clarity):
I expected a mipmap would solve or at least reduce the flickering, but it didn't change a thing. What am I doing wrong?
RenderDoc Update
After investigating the issue using RenderDoc I found that the mipmap is being generated successfully and it's third level looks like this:
However, the output of the down-scaling pass looks like this:
As if the sampler didn't use the mipmap at all. Don't get distracted by coloured object instead almost white ones. I lowered the sphere brightness a bit while investigating the bug.
Even if I choose the mipmap level explicitly
float4 vColor = s0.SampleLevel(LinearSampler, Input.Tex, 3);
it changes nothing :-/
RenderDoc also says "LOD Clamp 0-0" for the used sampler. What is it? Couldn't this be the problem?
DirectX details
Samplers
D3D11_SAMPLER_DESC descSampler;
ZeroMemory(&descSampler, sizeof(descSampler));
descSampler.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
descSampler.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
descSampler.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
descSampler.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
mDevice->CreateSamplerState(&descSampler, &mSamplerStateLinear);
descSampler.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
hr = mDevice->CreateSamplerState(&descSampler, &mSamplerStatePoint);
...are set right before rendering the screen quad
ID3D11SamplerState* aSamplers[] = { mSamplerStatePoint, mSamplerStateLinear };
mImmediateContext->PSSetSamplers(0, 2, aSamplers);
...and used within the down-scaling PS shader
SamplerState PointSampler : register (s0);
SamplerState LinearSampler : register (s1);
Texture2D s0 : register(t0);
float4 Pass1PS(QUAD_VS_OUTPUT Input) : SV_TARGET
{
return s0.Sample(LinearSampler, Input.Tex);
}
Texture
D3D11_TEXTURE2D_DESC descTex;
ZeroMemory(&descTex, sizeof(D3D11_TEXTURE2D_DESC));
descTex.ArraySize = 1;
descTex.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
descTex.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
descTex.Usage = D3D11_USAGE_DEFAULT;
descTex.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
descTex.Width = width;
descTex.Height = height;
descTex.MipLevels = 0;
descTex.SampleDesc.Count = 1;
device->CreateTexture2D(&descTex, nullptr, &tex);
...it's render target view
D3D11_RENDER_TARGET_VIEW_DESC descRTV;
descRTV.Format = descTex.Format;
descRTV.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
descRTV.Texture2D.MipSlice = 0;
device->CreateRenderTargetView(tex, &descRTV, &rtv);
...it's shader resource view
D3D11_SHADER_RESOURCE_VIEW_DESC descSRV;
ZeroMemory(&descSRV, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
descSRV.Format = descTex.Format;
descSRV.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
descSRV.Texture2D.MipLevels = (UINT)-1;
descSRV.Texture2D.MostDetailedMip = 0;
device->CreateShaderResourceView(tex, &descSRV, &srv);
Explicit generation of mipmap is called after the scene was rendered into the texture and another texture was set as a render target.
ID3D11RenderTargetView* aRTViews[1] = { mPass1Buff.GetRTV() };
mImmediateContext->OMSetRenderTargets(1, aRTViews, nullptr);
mImmediateContext->GenerateMips(mPass0Buff.GetSRV());
ID3D11ShaderResourceView* aSRViews[1] = { mPass0Buff.GetSRV() };
mImmediateContext->PSSetShaderResources(0, 1, aSRViews);
The code is compiled in debug and the D3D device was created with D3D11_CREATE_DEVICE_DEBUG
flag and I get no runtime errors on the console.