219 lines
7.1 KiB
C++
219 lines
7.1 KiB
C++
|
|
#include "XCUIBackend/NativeWindowUICompositor.h"
|
||
|
|
|
||
|
|
#include <XCEngine/Rendering/RenderContext.h>
|
||
|
|
#include <XCEngine/Rendering/RenderSurface.h>
|
||
|
|
#include <XCEngine/RHI/RHICommandList.h>
|
||
|
|
#include <XCEngine/RHI/RHICommandQueue.h>
|
||
|
|
#include <XCEngine/RHI/RHIResourceView.h>
|
||
|
|
#include <XCEngine/RHI/RHISwapChain.h>
|
||
|
|
|
||
|
|
namespace XCEngine {
|
||
|
|
namespace Editor {
|
||
|
|
namespace XCUIBackend {
|
||
|
|
|
||
|
|
namespace {
|
||
|
|
|
||
|
|
bool PrepareSwapChainRender(
|
||
|
|
::XCEngine::Editor::Platform::D3D12WindowRenderer& windowRenderer,
|
||
|
|
const float clearColor[4],
|
||
|
|
::XCEngine::Rendering::RenderContext& outRenderContext,
|
||
|
|
const ::XCEngine::Rendering::RenderSurface*& outRenderSurface,
|
||
|
|
::XCEngine::RHI::RHIResourceView*& outRenderTargetView) {
|
||
|
|
outRenderContext = windowRenderer.GetRenderContext();
|
||
|
|
outRenderSurface = windowRenderer.GetCurrentRenderSurface();
|
||
|
|
outRenderTargetView = nullptr;
|
||
|
|
|
||
|
|
if (!outRenderContext.IsValid() ||
|
||
|
|
outRenderSurface == nullptr ||
|
||
|
|
outRenderContext.commandList == nullptr ||
|
||
|
|
windowRenderer.GetSwapChain() == nullptr) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
const auto& colorAttachments = outRenderSurface->GetColorAttachments();
|
||
|
|
if (colorAttachments.empty() || colorAttachments[0] == nullptr) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
outRenderTargetView = colorAttachments[0];
|
||
|
|
outRenderContext.commandList->TransitionBarrier(
|
||
|
|
outRenderTargetView,
|
||
|
|
::XCEngine::RHI::ResourceStates::Present,
|
||
|
|
::XCEngine::RHI::ResourceStates::RenderTarget);
|
||
|
|
outRenderContext.commandList->SetRenderTargets(1, &outRenderTargetView, nullptr);
|
||
|
|
outRenderContext.commandList->ClearRenderTarget(outRenderTargetView, clearColor);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
void RebindSwapChainRenderTarget(
|
||
|
|
::XCEngine::Rendering::RenderContext& renderContext,
|
||
|
|
::XCEngine::RHI::RHIResourceView* renderTargetView) {
|
||
|
|
if (renderContext.commandList == nullptr || renderTargetView == nullptr) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
renderContext.commandList->SetRenderTargets(1, &renderTargetView, nullptr);
|
||
|
|
}
|
||
|
|
|
||
|
|
void PresentSwapChainRender(
|
||
|
|
::XCEngine::Editor::Platform::D3D12WindowRenderer& windowRenderer,
|
||
|
|
::XCEngine::Rendering::RenderContext& renderContext,
|
||
|
|
::XCEngine::RHI::RHIResourceView* renderTargetView) {
|
||
|
|
if (renderContext.commandList == nullptr ||
|
||
|
|
renderContext.commandQueue == nullptr ||
|
||
|
|
renderTargetView == nullptr ||
|
||
|
|
windowRenderer.GetSwapChain() == nullptr) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
renderContext.commandList->TransitionBarrier(
|
||
|
|
renderTargetView,
|
||
|
|
::XCEngine::RHI::ResourceStates::RenderTarget,
|
||
|
|
::XCEngine::RHI::ResourceStates::Present);
|
||
|
|
renderContext.commandList->Close();
|
||
|
|
|
||
|
|
void* commandLists[] = { renderContext.commandList };
|
||
|
|
renderContext.commandQueue->ExecuteCommandLists(1, commandLists);
|
||
|
|
windowRenderer.GetSwapChain()->Present(1, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace
|
||
|
|
|
||
|
|
bool NativeWindowUICompositor::Initialize(
|
||
|
|
HWND hwnd,
|
||
|
|
::XCEngine::Editor::Platform::D3D12WindowRenderer& windowRenderer,
|
||
|
|
const ConfigureFontsCallback& configureFonts) {
|
||
|
|
(void)configureFonts;
|
||
|
|
|
||
|
|
m_hwnd = hwnd;
|
||
|
|
m_windowRenderer = hwnd != nullptr ? &windowRenderer : nullptr;
|
||
|
|
m_renderBackend.Shutdown();
|
||
|
|
m_renderBackend.ResetStats();
|
||
|
|
m_pendingRenderPacket.Clear();
|
||
|
|
m_lastPresentStats = {};
|
||
|
|
return m_windowRenderer != nullptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
void NativeWindowUICompositor::Shutdown() {
|
||
|
|
m_renderBackend.Shutdown();
|
||
|
|
m_pendingRenderPacket.Clear();
|
||
|
|
m_lastPresentStats = {};
|
||
|
|
m_windowRenderer = nullptr;
|
||
|
|
m_hwnd = nullptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool NativeWindowUICompositor::HandleWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
||
|
|
(void)hwnd;
|
||
|
|
(void)message;
|
||
|
|
(void)wParam;
|
||
|
|
(void)lParam;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
void NativeWindowUICompositor::RenderFrame(
|
||
|
|
const float clearColor[4],
|
||
|
|
const UiRenderCallback& renderUi,
|
||
|
|
const RenderCallback& beforeUiRender,
|
||
|
|
const RenderCallback& afterUiRender) {
|
||
|
|
(void)renderUi;
|
||
|
|
|
||
|
|
m_lastPresentStats = {};
|
||
|
|
if (m_windowRenderer == nullptr) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
::XCEngine::Rendering::RenderContext renderContext = {};
|
||
|
|
const ::XCEngine::Rendering::RenderSurface* renderSurface = nullptr;
|
||
|
|
::XCEngine::RHI::RHIResourceView* renderTargetView = nullptr;
|
||
|
|
if (!PrepareSwapChainRender(
|
||
|
|
*m_windowRenderer,
|
||
|
|
clearColor,
|
||
|
|
renderContext,
|
||
|
|
renderSurface,
|
||
|
|
renderTargetView)) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (beforeUiRender) {
|
||
|
|
beforeUiRender(renderContext, *renderSurface);
|
||
|
|
RebindSwapChainRenderTarget(renderContext, renderTargetView);
|
||
|
|
}
|
||
|
|
|
||
|
|
m_lastPresentStats.hadPendingPacket = m_pendingRenderPacket.HasDrawData();
|
||
|
|
m_lastPresentStats.submittedDrawListCount = m_pendingRenderPacket.drawData.GetDrawListCount();
|
||
|
|
m_lastPresentStats.submittedCommandCount = m_pendingRenderPacket.drawData.GetTotalCommandCount();
|
||
|
|
|
||
|
|
if (m_pendingRenderPacket.textAtlasProvider != nullptr) {
|
||
|
|
m_renderBackend.SetTextAtlasProvider(m_pendingRenderPacket.textAtlasProvider);
|
||
|
|
} else {
|
||
|
|
m_renderBackend.SetTextAtlasProvider(nullptr);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (m_lastPresentStats.hadPendingPacket) {
|
||
|
|
m_lastPresentStats.renderedNativeOverlay =
|
||
|
|
m_renderBackend.Render(renderContext, *renderSurface, m_pendingRenderPacket.drawData);
|
||
|
|
m_lastPresentStats.overlayStats = m_renderBackend.GetLastOverlayStats();
|
||
|
|
} else {
|
||
|
|
m_renderBackend.ResetStats();
|
||
|
|
m_lastPresentStats.overlayStats = m_renderBackend.GetLastOverlayStats();
|
||
|
|
}
|
||
|
|
|
||
|
|
m_pendingRenderPacket.Clear();
|
||
|
|
|
||
|
|
if (afterUiRender) {
|
||
|
|
RebindSwapChainRenderTarget(renderContext, renderTargetView);
|
||
|
|
afterUiRender(renderContext, *renderSurface);
|
||
|
|
}
|
||
|
|
|
||
|
|
PresentSwapChainRender(*m_windowRenderer, renderContext, renderTargetView);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool NativeWindowUICompositor::CreateTextureDescriptor(
|
||
|
|
::XCEngine::RHI::RHIDevice* device,
|
||
|
|
::XCEngine::RHI::RHITexture* texture,
|
||
|
|
UITextureRegistration& outRegistration) {
|
||
|
|
(void)device;
|
||
|
|
(void)texture;
|
||
|
|
outRegistration = {};
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
void NativeWindowUICompositor::FreeTextureDescriptor(const UITextureRegistration& registration) {
|
||
|
|
(void)registration;
|
||
|
|
}
|
||
|
|
|
||
|
|
void NativeWindowUICompositor::SubmitRenderPacket(const XCUINativeWindowRenderPacket& packet) {
|
||
|
|
m_pendingRenderPacket = packet;
|
||
|
|
}
|
||
|
|
|
||
|
|
void NativeWindowUICompositor::SubmitRenderPacket(
|
||
|
|
const ::XCEngine::UI::UIDrawData& drawData,
|
||
|
|
const IXCUITextAtlasProvider* textAtlasProvider) {
|
||
|
|
m_pendingRenderPacket.drawData = drawData;
|
||
|
|
m_pendingRenderPacket.textAtlasProvider = textAtlasProvider;
|
||
|
|
}
|
||
|
|
|
||
|
|
void NativeWindowUICompositor::ClearPendingRenderPacket() {
|
||
|
|
m_pendingRenderPacket.Clear();
|
||
|
|
}
|
||
|
|
|
||
|
|
bool NativeWindowUICompositor::HasPendingRenderPacket() const {
|
||
|
|
return m_pendingRenderPacket.HasDrawData();
|
||
|
|
}
|
||
|
|
|
||
|
|
const XCUINativeWindowRenderPacket& NativeWindowUICompositor::GetPendingRenderPacket() const {
|
||
|
|
return m_pendingRenderPacket;
|
||
|
|
}
|
||
|
|
|
||
|
|
const XCUINativeWindowPresentStats& NativeWindowUICompositor::GetLastPresentStats() const {
|
||
|
|
return m_lastPresentStats;
|
||
|
|
}
|
||
|
|
|
||
|
|
std::unique_ptr<IWindowUICompositor> CreateNativeWindowUICompositor() {
|
||
|
|
return std::make_unique<NativeWindowUICompositor>();
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace XCUIBackend
|
||
|
|
} // namespace Editor
|
||
|
|
} // namespace XCEngine
|