如何在 directx 11 中使用多个帧缓冲区在交换链上创建渲染目标视图

How to create render target views on swap chain with multiple frame buffers in directx 11

我正在尝试实现具有 1 个以上后台缓冲区的交换链,但我在为第 0 个缓冲区之后的任何缓冲区创建渲染目标视图时遇到问题。

我这样创建交换链:

IDXGIFactory1* idxgiFactory;
// D3D_CALL is just a macro that throws exception with info on error
D3D_CALL(CreateDXGIFactory1(__uuidof(IDXGIFactory1), &idxgiFactory));

DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = BUFFER_COUNT; // currently 2
sd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 0;
sd.BufferDesc.RefreshRate.Denominator = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | D3D11_BIND_RENDER_TARGET;
sd.OutputWindow = window.GetHandle(); // wrapper for my window
sd.SampleDesc.Count = 4;
sd.SampleDesc.Quality = 1;
sd.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
sd.Windowed = TRUE;

D3D_CALL(idxgiFactory->CreateSwapChain(
    m_HWDevice, // ptr to ID3D11Device
    &sd,
    &m_HWSwapChain));

到目前为止,它一直在使用具有交换效果 DISCARD 的单帧缓冲区,根据 MSDN,它已过时且性能不佳。

创建交换链后,我得到后台缓冲区并创建视图,如下所示:

// this is called with buffer index from 0 till BUFFER_COUNT - 1
// 'm_RenderTarget' is simply an array of ID3D11Texture2D, where the size matches BUFFER_COUNT
D3D_CALL(m_HWSwapChain->GetBuffer(bufferIndex, __uuidof(ID3D11Texture2D), (LPVOID*)&m_RenderTarget[bufferIndex]));

// I then attempt to create the RTV like so:
ID3D11RenderTargetView* rtv = NULL;
D3D_CALL(m_HWDevice->CreateRenderTargetView(m_RenderTarget[bufferIndex], NULL, &rtv));

关于创建渲染目标视图的代码适用于 'bufferIndex' 0,但在索引 1 上出现以下错误:

D3D11 ERROR: ID3D11Device::CreateRenderTargetView: A render-target view cannot be made on a read-only resource. (Perhaps a DXGI_SWAP_CHAIN buffer other than buffer 0?) [ STATE_CREATION ERROR #135: CREATERENDERTARGETVIEW_INVALIDDESC]

我假设我必须使用 D3D11_RENDER_TARGET_VIEW_DESC 并在里面填充 D3D11_BUFFER_RTV 结构?虽然不知道如何设置,但找不到任何示例。

我试着用这样的描述符创建 RTV:

D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
ZeroMemory(&rtvDesc, sizeof(rtvDesc));
rtvDesc.Buffer.NumElements = BUFFER_COUNT;
rtvDesc.Buffer.FirstElement = 0;
rtvDesc.Buffer.ElementOffset = size.x * size.y * 4; // dimensions of my back buffer * 4 bytes per pixel
rtvDesc.Buffer.ElementWidth = 4; // 4 bytes per pixel in DXGI_FORMAT_B8G8R8A8_UNORM

这给出了错误:

D3D11 ERROR: ID3D11Device::CreateRenderTargetView: The ViewDimension in the View Desc incompatible with the type of the Resource. [ STATE_CREATION ERROR #129: CREATESHADERRESOURCEVIEW_INVALIDRESOURCE]

不确定我在这里遗漏了什么。

我对它的工作原理有点误解。我遗漏了一些关键信息:

*

If the swap chain's swap effect is either DXGI_SWAP_EFFECT_SEQUENTIAL or DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, only the swap chain's zero-index buffer can be read from and written to. The swap chain's buffers with indexes greater than zero can only be read from; so if you call the IDXGIResource::GetUsage method for such buffers, they have the DXGI_USAGE_READ_ONLY flag set.

来源:https://docs.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgiswapchain-getbuffer

另一个关键点是 dx11 自动管理帧缓冲区。我试图获取所有帧缓冲区并相应地写入它们。显然我只需要第 0 个帧缓冲区一次,为它创建一个视图并且只关心它。其余的将由 dx11 在幕后自动管理。 dx12 不是这种情况。

相关问题: