D3D11on12中无法从封装的普通ID3D12Resource查询IDXGISurface
问题:D3D11On12封装普通D3D12资源时QueryInterface获取IDXGISurface失败
在D2D结合D3D11On12的场景中,调用ID3D11On12Device::CreateWrappedResource、ID3D11Texture2D::QueryInterface<IDXGISurface>、ID2D1DeviceContext::CreateBitmapFromDxgiSurface三个函数时,封装交换链缓冲区可正常通过QueryInterface获取IDXGISurface,但封装普通ID3D12Resource时会返回错误0x80004002 : 'No such interface supported'。
官方示例代码片段
ThrowIfFailed(m_d3d11On12Device->CreateWrappedResource( m_renderTargets[n].Get(), &d3d11Flags, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT, IID_PPV_ARGS(&m_wrappedBackBuffers[n]) )); // Create a render target for D2D to draw directly to this back buffer. ComPtr<IDXGISurface> surface; ThrowIfFailed(m_wrappedBackBuffers[n].As(&surface)); ThrowIfFailed(m_d2dDeviceContext->CreateBitmapFromDxgiSurface( surface.Get(), &bitmapProperties, &m_d2dRenderTargets[n] ));
我的代码片段
winrt::com_ptr<ID2D1Bitmap1> d2dBitmap; winrt::com_ptr<ID3D11Resource> d3d11Resource; auto desc = d3dx12::CD3DX12_RESOURCE_DESC::Tex2D( DXGI_FORMAT_R8G8B8A8_UNORM, text_metrics.width, 53); desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; winrt::com_ptr<ID3D12Resource> d3d12Resource; auto heapProperties = d3dx12::CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); winrt::check_hresult(resources.D3D12Device().CreateCommittedResource( &heapProperties, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COMMON, nullptr, IID_PPV_ARGS(d3d12Resource.put()))); D3D11_RESOURCE_FLAGS d3d11Flags = { D3D11_BIND_RENDER_TARGET }; winrt::check_hresult( m_d3d11On12Device->CreateWrappedResource( d3d12Resource.get(), &d3d11Flags, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RENDER_TARGET, IID_PPV_ARGS(d3d11Resource.put()) )); auto tex2d = d3d11Resource.as<ID3D11Texture2D>(); // good! auto surface2 = tex2d.as<IDXGISurface>(); //0x80004002 : 'No such interface supported'. auto surface = d3d11Resource.as<IDXGISurface>(); //0x80004002 : 'No such interface supported'.
错误原因
- 交换链缓冲区是DXGI直接管理的资源,天然支持
IDXGISurface接口;而手动创建的普通D3D12资源并非DXGI表面类型,因此Wrapped后的D3D11纹理不会直接暴露IDXGISurface接口,直接调用QueryInterface会失败。 - 你的D3D12资源初始状态为
D3D12_RESOURCE_STATE_COMMON,但CreateWrappedResource中传入的BeforeState是D3D12_RESOURCE_STATE_RENDER_TARGET,存在状态不匹配的隐患,虽未直接导致当前错误,但可能引发后续问题。
解决方案
1. 修正IDXGISurface的获取方式
不要直接从ID3D11Texture2D查询IDXGISurface,而是先将D3D11资源转换为IDXGIResource,再通过GetSurface方法获取表面:
auto tex2d = d3d11Resource.as<ID3D11Texture2D>(); // 替换原QueryInterface逻辑 winrt::com_ptr<IDXGIResource> dxgiResource; winrt::check_hresult(tex2d.as(&dxgiResource)); winrt::com_ptr<IDXGISurface> surface; // 参数0表示获取第0个Mip层级的表面 winrt::check_hresult(dxgiResource->GetSurface(0, IID_PPV_ARGS(surface.put())));
2. 修复D3D12资源状态不匹配问题
创建D3D12资源后,先将其从COMMON状态转换为RENDER_TARGET状态,再执行CreateWrappedResource:
// 创建D3D12资源后添加状态转换屏障 D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( d3d12Resource.get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_RENDER_TARGET ); resources.CommandList()->ResourceBarrier(1, &barrier); // 提交命令列表并等待执行完成(需根据你的命令队列逻辑实现) resources.CommandList()->Close(); ID3D12CommandList* lists[] = { resources.CommandList().get() }; resources.CommandQueue()->ExecuteCommandLists(_countof(lists), lists); // 等待GPU完成状态转换 winrt::com_ptr<ID3D12Fence> fence; winrt::check_hresult(resources.D3D12Device()->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(fence.put()))); uint64_t fenceValue = 1; resources.CommandQueue()->Signal(fence.get(), fenceValue); if (fence->GetCompletedValue() < fenceValue) { HANDLE fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); winrt::check_hresult(fence->SetEventOnCompletion(fenceValue, fenceEvent)); WaitForSingleObject(fenceEvent, INFINITE); CloseHandle(fenceEvent); }
3. 确保D3D11On12设备创建时包含必要标志
创建D3D11On12设备时,必须指定D3D11_CREATE_DEVICE_BGRA_SUPPORT标志,这是D2D与D3D11互操作的前提:
D3D11_DEVICE_CREATION_FLAGS d3d11Flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; winrt::check_hresult(D3D11On12CreateDevice( d3d12Device.get(), d3d11Flags, nullptr, 0, reinterpret_cast<IUnknown**>(&d3d12CommandQueue), 1, 0, m_d3d11Device.put(), m_d3d11DeviceContext.put(), nullptr ));
内容的提问来源于stack exchange,提问作者Tom Huntington
相关产品推荐
相关产品推荐

