关键节点
This commit is contained in:
163
editor/app/Rendering/D3D12/D3D12WindowRenderLoop.cpp
Normal file
163
editor/app/Rendering/D3D12/D3D12WindowRenderLoop.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
#include "D3D12WindowRenderLoop.h"
|
||||
|
||||
namespace XCEngine::UI::Editor::Host {
|
||||
|
||||
D3D12WindowRenderLoopAttachResult D3D12WindowRenderLoop::Attach(
|
||||
D3D12UiRenderer& uiRenderer,
|
||||
D3D12WindowRenderer& windowRenderer) {
|
||||
m_uiRenderer = &uiRenderer;
|
||||
m_windowRenderer = &windowRenderer;
|
||||
|
||||
D3D12WindowRenderLoopAttachResult result = {};
|
||||
result.hasViewportSurfacePresentation =
|
||||
m_windowRenderer->GetSwapChain() != nullptr &&
|
||||
m_windowRenderer->GetRHIDevice() != nullptr;
|
||||
if (!result.hasViewportSurfacePresentation) {
|
||||
result.warning = "window render loop attach requires an initialized D3D12 window renderer.";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void D3D12WindowRenderLoop::Detach() {
|
||||
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.windowRendererWarning = "window render loop is detached.";
|
||||
return result;
|
||||
}
|
||||
|
||||
const bool resizedWindowRenderer =
|
||||
m_windowRenderer->Resize(static_cast<int>(width), static_cast<int>(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;
|
||||
}
|
||||
|
||||
result.hasViewportSurfacePresentation =
|
||||
resizedWindowRenderer &&
|
||||
m_windowRenderer->GetSwapChain() != nullptr &&
|
||||
m_windowRenderer->GetCurrentRenderSurface() != nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
D3D12WindowRenderLoopPresentResult D3D12WindowRenderLoop::Present(
|
||||
const ::XCEngine::UI::UIDrawData& drawData,
|
||||
const std::filesystem::path* captureOutputPath) {
|
||||
D3D12WindowRenderLoopPresentResult result = {};
|
||||
if (m_uiRenderer == nullptr) {
|
||||
result.warning = "window render loop has no ui renderer.";
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!HasViewportSurfacePresentation()) {
|
||||
result.warning = "window render loop has no active D3D12 presentation path.";
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!m_windowRenderer->PrepareCurrentBackBufferForUiRender()) {
|
||||
const std::string& error = m_windowRenderer->GetLastError();
|
||||
result.warning = error.empty()
|
||||
? "failed to prepare the current back buffer for UI rendering."
|
||||
: error;
|
||||
return result;
|
||||
}
|
||||
|
||||
const ::XCEngine::Rendering::RenderContext renderContext =
|
||||
m_windowRenderer->GetRenderContext();
|
||||
const ::XCEngine::Rendering::RenderSurface* surface =
|
||||
m_windowRenderer->GetCurrentRenderSurface();
|
||||
if (surface == nullptr) {
|
||||
result.warning = "window render loop could not resolve the current back buffer surface.";
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!m_uiRenderer->Render(drawData, renderContext, *surface)) {
|
||||
const std::string& error = m_uiRenderer->GetLastError();
|
||||
result.warning = error.empty()
|
||||
? "d3d12 ui renderer failed to render the current frame."
|
||||
: error;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!m_windowRenderer->FinalizeCurrentBackBufferForPresent()) {
|
||||
const std::string& error = m_windowRenderer->GetLastError();
|
||||
result.warning = error.empty()
|
||||
? "failed to finalize the current back buffer for present."
|
||||
: error;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!m_windowRenderer->SubmitFrame()) {
|
||||
const std::string& error = m_windowRenderer->GetLastError();
|
||||
result.warning = error.empty()
|
||||
? "failed to submit the current D3D12 frame."
|
||||
: error;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (captureOutputPath != nullptr) {
|
||||
std::string captureError = {};
|
||||
if (!m_windowRenderer->CaptureCurrentBackBufferToPng(*captureOutputPath, captureError)) {
|
||||
result.captureError = captureError.empty()
|
||||
? "failed to capture the current D3D12 back buffer."
|
||||
: std::move(captureError);
|
||||
} else {
|
||||
result.captureSucceeded = true;
|
||||
}
|
||||
}
|
||||
|
||||
const bool presented = m_windowRenderer->PresentFrame();
|
||||
const std::string presentError = m_windowRenderer->GetLastError();
|
||||
|
||||
if (!m_windowRenderer->SignalFrameCompletion()) {
|
||||
const std::string& error = m_windowRenderer->GetLastError();
|
||||
result.warning = error.empty()
|
||||
? "failed to signal current frame completion."
|
||||
: error;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!presented) {
|
||||
result.warning = presentError.empty()
|
||||
? "failed to present the swap chain."
|
||||
: presentError;
|
||||
return result;
|
||||
}
|
||||
|
||||
result.framePresented = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool D3D12WindowRenderLoop::HasViewportSurfacePresentation() const {
|
||||
return m_uiRenderer != nullptr &&
|
||||
m_windowRenderer != nullptr &&
|
||||
m_windowRenderer->GetSwapChain() != nullptr &&
|
||||
m_windowRenderer->GetCurrentRenderSurface() != nullptr;
|
||||
}
|
||||
|
||||
} // namespace XCEngine::UI::Editor::Host
|
||||
Reference in New Issue
Block a user