#include "D3D12WindowRenderLoop.h" namespace XCEngine::UI::Editor::Host { D3D12WindowRenderLoopAttachResult D3D12WindowRenderLoop::Attach( NativeRenderer& uiRenderer, D3D12WindowRenderer& windowRenderer) { m_uiRenderer = &uiRenderer; m_windowRenderer = &windowRenderer; D3D12WindowRenderLoopAttachResult result = {}; result.hasViewportSurfacePresentation = m_uiRenderer->AttachWindowRenderer(*m_windowRenderer); if (!result.hasViewportSurfacePresentation) { const std::string& interopError = m_uiRenderer->GetLastRenderError(); result.interopWarning = interopError.empty() ? "native renderer d3d12 interop unavailable; falling back to hwnd renderer." : "native renderer d3d12 interop unavailable; falling back to hwnd renderer: " + interopError; } return result; } void D3D12WindowRenderLoop::Detach() { if (m_uiRenderer != nullptr) { m_uiRenderer->DetachWindowRenderer(); } m_uiRenderer = nullptr; m_windowRenderer = nullptr; } D3D12WindowRenderLoopFrameContext D3D12WindowRenderLoop::BeginFrame() const { D3D12WindowRenderLoopFrameContext context = {}; if (!HasViewportSurfacePresentation()) { return context; } if (!m_windowRenderer->BeginFrame()) { const std::string& frameError = m_windowRenderer->GetLastError(); context.warning = frameError.empty() ? "d3d12 frame begin failed" : "d3d12 frame begin failed: " + frameError; return context; } context.canRenderViewports = true; context.renderContext = m_windowRenderer->GetRenderContext(); return context; } D3D12WindowRenderLoopResizeResult D3D12WindowRenderLoop::ApplyResize(UINT width, UINT height) { D3D12WindowRenderLoopResizeResult result = {}; if (m_uiRenderer == nullptr || m_windowRenderer == nullptr) { result.interopWarning = "window render loop is detached."; return result; } m_uiRenderer->Resize(width, height); const bool hadViewportSurfacePresentation = m_uiRenderer->HasAttachedWindowRenderer(); if (hadViewportSurfacePresentation) { m_uiRenderer->ReleaseWindowRendererBackBufferTargets(); } const bool resizedWindowRenderer = m_windowRenderer->Resize(static_cast(width), static_cast(height)); if (!resizedWindowRenderer || !m_windowRenderer->GetLastError().empty()) { const std::string& resizeError = m_windowRenderer->GetLastError(); result.windowRendererWarning = resizeError.empty() ? "window renderer resize warning." : "window renderer resize warning: " + resizeError; } if (!resizedWindowRenderer) { if (hadViewportSurfacePresentation) { result.hasViewportSurfacePresentation = m_uiRenderer->RebuildWindowRendererBackBufferTargets(); if (!result.hasViewportSurfacePresentation) { const D3D12WindowRenderLoopAttachResult attachResult = Attach(*m_uiRenderer, *m_windowRenderer); result.hasViewportSurfacePresentation = attachResult.hasViewportSurfacePresentation; result.interopWarning = attachResult.interopWarning; } } return result; } if (hadViewportSurfacePresentation) { result.hasViewportSurfacePresentation = m_uiRenderer->RebuildWindowRendererBackBufferTargets(); if (!result.hasViewportSurfacePresentation) { const D3D12WindowRenderLoopAttachResult attachResult = Attach(*m_uiRenderer, *m_windowRenderer); result.hasViewportSurfacePresentation = attachResult.hasViewportSurfacePresentation; result.interopWarning = attachResult.interopWarning; } return result; } const D3D12WindowRenderLoopAttachResult attachResult = Attach(*m_uiRenderer, *m_windowRenderer); result.hasViewportSurfacePresentation = attachResult.hasViewportSurfacePresentation; result.interopWarning = attachResult.interopWarning; return result; } D3D12WindowRenderLoopPresentResult D3D12WindowRenderLoop::Present( const ::XCEngine::UI::UIDrawData& drawData) const { D3D12WindowRenderLoopPresentResult result = {}; if (m_uiRenderer == nullptr) { result.warning = "window render loop has no ui renderer."; return result; } if (HasViewportSurfacePresentation()) { result.framePresented = m_uiRenderer->RenderToWindowRenderer(drawData); if (!result.framePresented) { const std::string& composeError = m_uiRenderer->GetLastRenderError(); result.warning = composeError.empty() ? "d3d12 window composition failed, falling back to hwnd renderer." : "d3d12 window composition failed, falling back to hwnd renderer: " + composeError; } } if (!result.framePresented) { result.framePresented = m_uiRenderer->Render(drawData); if (!result.framePresented && result.warning.empty()) { result.warning = m_uiRenderer->GetLastRenderError(); } } return result; } bool D3D12WindowRenderLoop::HasViewportSurfacePresentation() const { return m_uiRenderer != nullptr && m_windowRenderer != nullptr && m_uiRenderer->HasAttachedWindowRenderer(); } } // namespace XCEngine::UI::Editor::Host