🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

[DirectX 12] Mismatch between DepthStencilViews and RenderTargetViews

Started by
6 comments, last by charleszzx 1 year, 5 months ago

Hello everyone. I created a very simple DirectX 12 application with double buffering and a single depth stencil buffer. However, when I run the application the following error message appears:

DepthStencilViews may only be used with RenderTargetViews if the effective dimensions of the Views are equal, as well as the Resource types, multisample count, and multisample quality. 
One exception is that DepthStencil width and/or height can be larger than RenderTarget width/height.

The RenderTargetView at slot 0 has (w:800,h:600,as:2), while the Resource is a Texture2D with (mc:1,mq:0). 
The DepthStencilView has (w:800,h:600,as:1), while the Resource is a Texture2D with (mc:1,mq:0).

I am very confused. It looks like the only different is

  • RenderTargetView has as:2
  • DepthStencilView has as:1

What is as in this case? I have confirmed that they all use the same quality and count, so it has to be as. Thanks a lot!

Advertisement

I would guess that's the array size of the texture. Did you create that render target with 2 array slices? If you you would either need to create the depth buffer with 2 slices, or you would need to make an RTV that only targets a single array slice.

Thanks! But I don't remember I touch the array size of any relevant buffers. I use md3dDevice->CreateRenderTargetView(mSwapChainBuffer[i].Get(), nullptr, rtvHeapHandle); to create my render target view and use the following to create the swap chain:

	DXGI_SWAP_CHAIN_DESC1 swapChainDesc;
    swapChainDesc.Width = mClientWidth; 
    swapChainDesc.Height = mClientHeight;
    swapChainDesc.Format = mBackBufferFormat;
    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapChainDesc.BufferCount = SwapChainBufferCount;
    swapChainDesc.SampleDesc.Count = 1;
    swapChainDesc.SampleDesc.Quality = 0;
    swapChainDesc.Scaling = DXGI_SCALING_NONE;
    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
    swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
    swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

    DXGI_SWAP_CHAIN_FULLSCREEN_DESC fsSwapChainDesc = {};
    fsSwapChainDesc.Windowed = TRUE;

    ThrowIfFailed(mdxgiFactory->CreateSwapChainForHwnd(mCommandQueue.Get(), mhMainWnd, &swapChainDesc, &fsSwapChainDesc, nullptr, mSwapChain.GetAddressOf()));

. Also, if I use the following to create swap chain, the error messages disappear:

    DXGI_SWAP_CHAIN_DESC sd;
    sd.BufferDesc.Width = mClientWidth;
    sd.BufferDesc.Height = mClientHeight;
    sd.BufferDesc.RefreshRate.Numerator = 60;
    sd.BufferDesc.RefreshRate.Denominator = 1;
    sd.BufferDesc.Format = mBackBufferFormat;
    sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
    sd.SampleDesc.Count = 1;
    sd.SampleDesc.Quality = 0;
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.BufferCount = SwapChainBufferCount;
    sd.OutputWindow = mhMainWnd;
    sd.Windowed = true;
    sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
    sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

    // Note: Swap chain uses queue to perform flush.
    ThrowIfFailed(mdxgiFactory->CreateSwapChain(
        mCommandQueue.Get(),
        &sd,
        mSwapChain.GetAddressOf()));

Now, I am more confused :( . It looks like both methods we are not specifying values for array size, but one is apparently different from the other.

An educated guess (have only worked with DX11): Probably has something to do with the fact that flip-presentation model requires (at least) 2 buffers. It seems you want to create a non-fullscreen window? In this case, CreateSwapChainForHmd simply should take a “nullptr” for the DXGI_SWAP_CHAIN_FULLSCREEN_DESC, instead of setting “Windowed=true” (didn't know that parameter exists; nor do I know what it does. But I'm passing nullptr for windowed-mode).

So probably CreateSwapChain creates a windowed swap-chain, while the other creates a fullscreen. I'm guessing SwapChainBufferCount is probably “2", and the error would change if altered. And probably, in DX12 you need to create a depth-buffer with an explicit slice for each backbuffer that is created, if in fullscreen. For windowed the rules are different with the compositor-thing going on.

Again, mostly guesses. But you could try changing the SwapChainBufferCount to see if the error changes, and/or pass nullptr for fullscreen-desc to see if this changes anything.

Thanks Juliean. Unfortunately, they don't seem to fix the problem. However, I can fix the problem by explicitly passing in a D3D12_RENDER_TARGET_VIEW_DESCwith the following properties:

	D3D12_RENDER_TARGET_VIEW_DESC rtvDesc;
    rtvDesc.Format = mBackBufferFormat;
    rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
    rtvDesc.Texture2D.MipSlice = 0;
    rtvDesc.Texture2D.PlaneSlice = 0;

My guess is that passing nullptrinto CreateRenderTargetViewwill give you as:2 (array size = 2).

charleszzx said:
My guess is that passing nullptrinto CreateRenderTargetViewwill give you as:2 (array size = 2).

Well now at least this I can answer you without guessing ?

[in, optional] pDesc

Type: const D3D12_RENDER_TARGET_VIEW_DESC*

A pointer to a D3D12_RENDER_TARGET_VIEW_DESC structure that describes the render-target view.

A null pDesc is used to initialize a default descriptor, if possible. This behavior is identical to the D3D11 null descriptor behavior, where defaults are filled in. This behavior inherits the resource format and dimension (if not typeless) and RTVs target the first mip and all array slices. Not all resources support null descriptor initialization.

Which for some reason references back to D3D11:

Pointer to a D3D11_RENDER_TARGET_VIEW_DESC that represents a render-target view description. Set this parameter to NULL to create a view that accesses all of the subresources in mipmap level 0.

So this means that, when passing nullptr, you are creating a description over the entire render-target (which contains two array-elements for whatever reason), and by explicitely passing your own description, you are now creating a view of just one slice which fixes the issue. I don't know you are actually fully rendering right now (= able to confirm that outside of warnings everything is working fine), but if not, you should keep that in mind probably.

(source: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-createrendertargetview)

Ah, I did just remember one thing. IDXGIFactory::CreateSwapChain should not be compatible with DXGI_SWAP_EFFECT_FLIP_DISCARD IIRC. Not sure why you don't get a warning about it, but I remember having to port to IDXGIFactory1 to be able to use the new mode. So in your original code, by using CreateSwapChain you force flip-discard to be off, which in my intuition ought to be the source of the error - so this could explain why it “fixed” the warning. So yeah - if everything renders fine no you are probably save, but otherwise your solution probably forces stuff to render in only one of the two flip-model backbuffers, so you could expect some issues down the line.

Hello Juliean, I am using DXGI_SWAP_EFFECT_FLIP_DISCARD with CreateSwapChainForHwnd and the “fix” of explicitly passing in a D3D12_RENDER_TARGET_VIEW_DESC. Hopefully it won't cause issues down the line ?.

This topic is closed to new replies.

Advertisement