我对使用“Direct 3D 11 on 12”库很感兴趣,但是在调整窗口大小时遇到了麻烦。特别是,我正在修改 Visual Studio“DirectX 12 App”示例。
在示例创建 ID3D12CommandQueue 之后,我正在创建 ID3D11On12Device:
ComPtr<ID3D11Device> d3d11Device;
IUnknown* queues[] = { m_commandQueue.Get() };
DX::ThrowIfFailed(D3D11On12CreateDevice(m_d3dDevice.Get(), D3D11_CREATE_DEVICE_BGRA_SUPPORT, nullptr, 0, queues, 1, 0, d3d11Device.GetAddressOf(), m_d3d11DeviceContext.GetAddressOf(), nullptr));
DX::ThrowIfFailed(d3d11Device.As(&m_d3d11On12Device));
然后,当示例创建其渲染目标视图时,我添加了包装 ID3D11Resource 的创建:
for (UINT n = 0; n < c_frameCount; n++)
{
// Visual studio template calls m_swapChain->GetBuffer() and m_d3dDevice->CreateRenderTargetView() here
D3D11_RESOURCE_FLAGS d3d11Flags = { D3D11_BIND_RENDER_TARGET };
DX::ThrowIfFailed(m_d3d11On12Device->CreateWrappedResource(m_renderTargets[n].Get(), &d3d11Flags, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT, IID_PPV_ARGS(&m_wrappedBackBuffers[n])));
rtvDescriptor.Offset(m_rtvDescriptorSize);
...
// m_renderTargets[n]->SetName(), etc.
}
然后,在创建了其余的 D3D12 资源之后,我正在测试 ID3D11On12Device::AcquireWrappedResources() 和 ID3D11On12Device::ReleaseWrappedResources() (只是作为测试,尽量使代码尽可能简单)
ID3D11Resource* resources[] = { m_wrappedBackBuffers[0].Get() };
m_d3d11On12Device->AcquireWrappedResources(resources, 1);
m_d3d11On12Device->ReleaseWrappedResources(resources, 1);
到目前为止,一切似乎都按预期工作。但是,在调整窗口大小时会出现问题。特别是,调整大小调用 IDXGISwapChain3::ResizeBuffers()。发生这种情况时,ResizeBuffers() 返回失败,并且控制台上显示以下消息:
DXGI ERROR: IDXGISwapChain::ResizeBuffers: Swapchain cannot be resized unless all outstanding buffer references have been released. [ MISCELLANEOUS ERROR #19: ]
我尝试在 ResizeBuffers() 之前清除 m_wrappedBackBuffers 引用:
for (UINT n = 0; n < c_frameCount; n++)
{
m_renderTargets[n] = nullptr;
m_wrappedBackBuffers[n] = nullptr;
}
但这似乎没有效果。我还尝试过对 ID3D11DeviceContext 进行 Flush()ing 和 ClearState()ing,但这些似乎没有效果或产生以下错误:
D3D12 ERROR: ID3D12CommandQueue::ExecuteCommandLists: A command list, which writes to a swapchain back buffer, may only be executed when that back buffer is the back buffer will be presented during the next call to Present*. Such a back buffer is also referred to as the "current back buffer". [ STATE_SETTING ERROR #907: EXECUTECOMMANDLISTS_WRONGSWAPCHAINBUFFERREFERENCE]
D3D12: Removing Device.
注释掉 ID3D11On12Device::AcquireWrappedResources() 和 ID3D11On12Device::ReleaseWrappedResources() 调用使 ResizeBuffers() 成功返回;但似乎需要调用这两个函数才能完全使用该库。
似乎在某个地方,ID3D11On12Device 或 ID3D11DeviceContext 保留了对交换链缓冲区的引用,但我无法找到任何有关如何在不破坏整个设备的情况下重置此引用的文档。
GitHub 上的这个问题似乎与我遇到的问题相同;但是,响应涉及“在 D2D 上下文中调用 SetTarget(nullptr)”,但我在这个项目中根本没有接触过 Direct2D(并且 Visual Studio 模板已经在 IDXGISwapChain3::ResizeBuffers() 之前调用了 WaitForGpu())。
Microsoft 的示例根本不包括交换链缓冲区大小调整。运行示例会导致交换链被拉伸以适应窗口。
我在 Microsoft 的文档中没有找到任何关于调整大小的信息。