I'm learning dx11 from Introduction_to_3D_Game_Programming_with_Directx_11. Everything is ok without msaa. When I enable it, my .fx and C++ codes will not work well. Do someone experienced it too and how to deal with this situation?
Before Codes:
Texture2D gTexture1;
float4 BLEND_PS(VertexOut_SV pin) :SV_TARGET
{
float4 texColor = float4(0.0f, 0.0f, 0.0f, 0.0f);
texColor = gTexture1.Sample(SamAnisotropic, pin.Tex);
return texColor;
}
because I can't bind a texture created with msaa to a texture2D,so I take msaa ON whenever.
After codes:
Texture2DMS<float4> gTexture1;
float4 BLEND_PS(VertexOut_SV pin) :SV_TARGET
{
float4 texColor = float4(0.0f, 0.0f, 0.0f, 0.0f);
texColor = gTexture1.Load(int2(pin.Tex.x*1400, pin.Tex.y*900), 0);
return texColor;
}
But the texColor is not right pixel I want.How to sample an SRV with msaa? How to convert an UAV without msaa into a SRV with msaa?
And how to enable and disable msaa in C++ game codes with corresponding hlsl codes? Do I have to keep different hlsl for each other?
For 'standard' MSAA use, you do the following:
When creating your swap chain and render traget view, set DXGI_SWAP_CHAIN_DESC.SampleDesc.Count
or DXGI_SWAP_CHAIN_DESC1.SampleDesc.Count
to 2, 4, 8, etc.
When creating your depth buffer/stencil, you need to use the same sample count for D3D11_TEXTURE2D_DESC.SampleDesc.Count
.
When creating your render target view, you need to use D3D11_RTV_DIMENSION_TEXTURE2DMS
(or pass nullptr
for the view description so it matches the resource exactly)
When creating your depth buffer/stencil view, you need to use D3D11_DSV_DIMENSION_TEXTURE2DMS
(or pass nullptr
for the view description so it matches the resource exactly)
When rendering, you need to use a rasterizer state with D3D11_RASTERIZER_DESC.MultisampleEnable
set to TRUE.
See also the Simple rendering tutorial for DirectX Tool Kit
Depending on the Direct3D feature level, some MSAA sample counts are required for particular render target formats. Use can use CheckFormatSupport
to verify render target format supports MSAA:
UINT formatSupport = 0;
if (FAILED(device->CheckFormatSupport(m_backBufferFormat, &formatSupport)))
{
throw std::exception("CheckFormatSupport");
}
UINT flags = D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE
| D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET;
if ( (formatSupport & flags) != flags )
{
// error
}
You then use CheckMultisampleQualityLevels
to verify the sample count is supported. This code finds the highest supported MSAA level count for a particular format:
for (m_sampleCount = D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT;
m_sampleCount > 1; m_sampleCount--)
{
UINT levels = 0;
if (FAILED(device->CheckMultisampleQualityLevels(m_backBufferFormat,
m_sampleCount, &levels)))
continue;
if ( levels > 0)
break;
}
if (m_sampleCount < 2)
{
// error
}
You can also validate the depth/stencil format you want to use supports
D3D11_FORMAT_SUPPORT_DEPTH_STENCIL | D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET
.
The technique above only works for the older "bit-blt" style flip modes DXGI_SWAP_EFFECT_DISCARD
or DXGI_SWAP_EFFECT_SEQUENTIAL
. For UWP and DirectX 12 you are required to use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
or DXGI_SWAP_EFFECT_FLIP_DISCARD
which will fail if you attempt to create a back buffer with a SampleCount > 1.
In this case, you create the backbuffer with a SampleCount of 1, and create your own MSAA Render Target 2D texture. You have your Render Target View point to your MSAA render target, and before you Present
you call ResolveSubresource
from your MSAA render target to the backbufffer. This is exactly the same thing that DXGI did for you 'behind the scenes' with the older flip models.
For gamma-correct rendering (aka when you use a backbuffer format ending in
_SRGB
), the newer flip styles require that you use the non-SRGB equivalent for the backbuffer format or the swapchain create will fail. You set the SRGB format on the render target view instead.