#include "D3D12WindowInteropInternal.h" namespace XCEngine::UI::Editor::Host { using namespace D3D12WindowInteropInternal; void D3D12WindowInteropContext::ReleaseBackBufferTargets() { ClearSourceTextures(); if (m_d2dDeviceContext != nullptr) { m_d2dDeviceContext->SetTarget(nullptr); } if (m_d3d11DeviceContext != nullptr) { m_d3d11DeviceContext->ClearState(); } m_backBufferTargets.clear(); if (m_d2dDeviceContext != nullptr) { D2D1_TAG firstTag = 0u; D2D1_TAG secondTag = 0u; m_d2dDeviceContext->Flush(&firstTag, &secondTag); } if (m_d3d11DeviceContext != nullptr) { m_d3d11DeviceContext->Flush(); } } bool D3D12WindowInteropContext::RebuildBackBufferTargets() { m_backBufferTargets.clear(); if (m_windowRenderer == nullptr || m_d3d11On12Device == nullptr || m_d2dDeviceContext == nullptr) { return false; } const std::uint32_t backBufferCount = m_windowRenderer->GetBackBufferCount(); m_backBufferTargets.resize(backBufferCount); for (std::uint32_t index = 0u; index < backBufferCount; ++index) { const ::XCEngine::RHI::D3D12Texture* backBufferTexture = m_windowRenderer->GetBackBufferTexture(index); if (backBufferTexture == nullptr || backBufferTexture->GetResource() == nullptr) { m_lastError = "Failed to resolve a D3D12 swap chain back buffer."; m_backBufferTargets.clear(); return false; } D3D11_RESOURCE_FLAGS resourceFlags = {}; resourceFlags.BindFlags = D3D11_BIND_RENDER_TARGET; HRESULT hr = m_d3d11On12Device->CreateWrappedResource( backBufferTexture->GetResource(), &resourceFlags, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT, IID_PPV_ARGS(m_backBufferTargets[index].wrappedResource.ReleaseAndGetAddressOf())); if (FAILED(hr) || m_backBufferTargets[index].wrappedResource == nullptr) { m_lastError = HrToInteropString("ID3D11On12Device::CreateWrappedResource(backbuffer)", hr); m_backBufferTargets.clear(); return false; } Microsoft::WRL::ComPtr dxgiSurface = {}; hr = m_backBufferTargets[index].wrappedResource.As(&dxgiSurface); if (FAILED(hr) || dxgiSurface == nullptr) { m_lastError = HrToInteropString("ID3D11Resource::QueryInterface(IDXGISurface)", hr); m_backBufferTargets.clear(); return false; } const D2D1_BITMAP_PROPERTIES1 bitmapProperties = BuildD2DBitmapProperties( backBufferTexture->GetDesc().Format, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW); hr = m_d2dDeviceContext->CreateBitmapFromDxgiSurface( dxgiSurface.Get(), &bitmapProperties, m_backBufferTargets[index].targetBitmap.ReleaseAndGetAddressOf()); if (FAILED(hr) || m_backBufferTargets[index].targetBitmap == nullptr) { m_lastError = HrToInteropString( "ID2D1DeviceContext::CreateBitmapFromDxgiSurface(backbuffer)", hr); m_backBufferTargets.clear(); return false; } } m_lastError.clear(); return true; } bool D3D12WindowInteropContext::HasAttachedWindowRenderer() const { return m_windowRenderer != nullptr && m_d3d11On12Device != nullptr && m_d2dDeviceContext != nullptr && !m_backBufferTargets.empty(); } bool D3D12WindowInteropContext::HasBackBufferTargets() const { return !m_backBufferTargets.empty(); } void D3D12WindowInteropContext::BuildAcquiredResources( std::uint32_t backBufferIndex, std::vector& outResources) const { outResources.clear(); ID3D11Resource* backBufferResource = GetWrappedBackBufferResource(backBufferIndex); if (backBufferResource != nullptr) { outResources.push_back(backBufferResource); } for (const SourceTextureResource& resource : m_activeSourceTextures) { if (resource.wrappedResource != nullptr) { outResources.push_back(resource.wrappedResource.Get()); } } } ID3D11Resource* D3D12WindowInteropContext::GetWrappedBackBufferResource(std::uint32_t index) const { return index < m_backBufferTargets.size() ? m_backBufferTargets[index].wrappedResource.Get() : nullptr; } ID2D1Bitmap1* D3D12WindowInteropContext::GetBackBufferTargetBitmap(std::uint32_t index) const { return index < m_backBufferTargets.size() ? m_backBufferTargets[index].targetBitmap.Get() : nullptr; } std::uint32_t D3D12WindowInteropContext::GetCurrentBackBufferIndex() const { return m_windowRenderer != nullptr && m_windowRenderer->GetSwapChain() != nullptr ? m_windowRenderer->GetSwapChain()->GetCurrentBackBufferIndex() : 0u; } } // namespace XCEngine::UI::Editor::Host