checkpoint(new_editor): native d3d12 ui path
Key node 1: move main-window UI presentation onto the D3D12 render loop with native UI renderer, text system, and texture host. Key node 2: wire frame timing/FPS display, window runtime, swapchain presentation, and native screenshot capture around the new path. Key node 3: carry editor shell/workspace/viewport/panel interaction updates needed by the new renderer and detached window flow. Key node 4: pump async resource loads and scene bridge follow-up needed for scene content visibility in new_editor.
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
#include <utility>
|
||||
|
||||
namespace XCEngine::UI::Editor::App {
|
||||
@@ -18,6 +19,7 @@ using namespace EditorWindowSupport;
|
||||
namespace {
|
||||
|
||||
constexpr float kFrameTimeSmoothingFactor = 0.12f;
|
||||
constexpr float kFrameStatsDisplayRefreshIntervalSeconds = 0.25f;
|
||||
|
||||
}
|
||||
|
||||
@@ -73,14 +75,17 @@ void EditorWindowRuntimeController::ClearExternalDockHostDropPreview() {
|
||||
|
||||
void EditorWindowRuntimeController::SetDpiScale(float dpiScale) {
|
||||
m_renderer.SetDpiScale(dpiScale);
|
||||
m_textSystem.SetDpiScale(dpiScale);
|
||||
m_uiRenderer.SetDpiScale(dpiScale);
|
||||
}
|
||||
|
||||
Host::NativeRenderer& EditorWindowRuntimeController::GetRenderer() {
|
||||
return m_renderer;
|
||||
::XCEngine::UI::Editor::UIEditorTextMeasurer& EditorWindowRuntimeController::GetTextMeasurer() {
|
||||
return m_textSystem;
|
||||
}
|
||||
|
||||
const Host::NativeRenderer& EditorWindowRuntimeController::GetRenderer() const {
|
||||
return m_renderer;
|
||||
const ::XCEngine::UI::Editor::UIEditorTextMeasurer&
|
||||
EditorWindowRuntimeController::GetTextMeasurer() const {
|
||||
return m_textSystem;
|
||||
}
|
||||
|
||||
const ::XCEngine::UI::UITextureHandle& EditorWindowRuntimeController::GetTitleBarLogoIcon() const {
|
||||
@@ -98,36 +103,53 @@ bool EditorWindowRuntimeController::Initialize(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_renderer.Initialize(hwnd)) {
|
||||
LogRuntimeTrace("app", "renderer initialization failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
RECT clientRect = {};
|
||||
GetClientRect(hwnd, &clientRect);
|
||||
const int clientWidth = (std::max)(clientRect.right - clientRect.left, 1L);
|
||||
const int clientHeight = (std::max)(clientRect.bottom - clientRect.top, 1L);
|
||||
if (!m_windowRenderer.Initialize(hwnd, clientWidth, clientHeight)) {
|
||||
LogRuntimeTrace("app", "d3d12 window renderer initialization failed");
|
||||
m_renderer.Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
const Host::D3D12WindowRenderLoopAttachResult attachResult =
|
||||
m_windowRenderLoop.Attach(m_renderer, m_windowRenderer);
|
||||
if (!attachResult.interopWarning.empty()) {
|
||||
LogRuntimeTrace("app", attachResult.interopWarning);
|
||||
if (!m_textureHost.Initialize(m_windowRenderer)) {
|
||||
LogRuntimeTrace("app", "d3d12 ui texture host initialization failed");
|
||||
m_windowRenderer.Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
editorContext.AttachTextMeasurer(m_renderer);
|
||||
m_shellRuntime.Initialize(repoRoot, m_renderer, m_renderer);
|
||||
if (!m_textSystem.Initialize()) {
|
||||
LogRuntimeTrace("app", "d3d12 ui text system initialization failed");
|
||||
m_textureHost.Shutdown();
|
||||
m_windowRenderer.Shutdown();
|
||||
return false;
|
||||
}
|
||||
m_textSystem.SetDpiScale(m_renderer.GetDpiScale());
|
||||
|
||||
if (!m_uiRenderer.Initialize(m_windowRenderer, m_textureHost, m_textSystem)) {
|
||||
LogRuntimeTrace("app", "d3d12 ui renderer initialization failed");
|
||||
m_textSystem.Shutdown();
|
||||
m_textureHost.Shutdown();
|
||||
m_windowRenderer.Shutdown();
|
||||
return false;
|
||||
}
|
||||
m_uiRenderer.SetDpiScale(m_renderer.GetDpiScale());
|
||||
|
||||
const Host::D3D12WindowRenderLoopAttachResult attachResult =
|
||||
m_windowRenderLoop.Attach(m_uiRenderer, m_windowRenderer);
|
||||
if (!attachResult.warning.empty()) {
|
||||
LogRuntimeTrace("app", attachResult.warning);
|
||||
}
|
||||
|
||||
editorContext.AttachTextMeasurer(m_textSystem);
|
||||
m_shellRuntime.Initialize(repoRoot, m_textureHost, m_textSystem);
|
||||
m_shellRuntime.AttachViewportWindowRenderer(m_windowRenderer);
|
||||
m_shellRuntime.SetViewportSurfacePresentationEnabled(
|
||||
attachResult.hasViewportSurfacePresentation);
|
||||
|
||||
std::string titleBarLogoError = {};
|
||||
if (!LoadEmbeddedPngTexture(
|
||||
m_renderer,
|
||||
m_textureHost,
|
||||
IDR_PNG_LOGO_ICON,
|
||||
m_titleBarLogoIcon,
|
||||
titleBarLogoError)) {
|
||||
@@ -160,8 +182,11 @@ void EditorWindowRuntimeController::Shutdown() {
|
||||
ResetFrameTiming();
|
||||
m_autoScreenshot.Shutdown();
|
||||
m_shellRuntime.Shutdown();
|
||||
m_renderer.ReleaseTexture(m_titleBarLogoIcon);
|
||||
m_windowRenderLoop.Detach();
|
||||
m_uiRenderer.Shutdown();
|
||||
m_textSystem.Shutdown();
|
||||
m_textureHost.ReleaseTexture(m_titleBarLogoIcon);
|
||||
m_textureHost.Shutdown();
|
||||
m_windowRenderer.Shutdown();
|
||||
m_renderer.Shutdown();
|
||||
}
|
||||
@@ -185,10 +210,6 @@ bool EditorWindowRuntimeController::ApplyResize(UINT width, UINT height) {
|
||||
LogRuntimeTrace("present", resizeResult.windowRendererWarning);
|
||||
}
|
||||
|
||||
if (!resizeResult.interopWarning.empty()) {
|
||||
LogRuntimeTrace("present", resizeResult.interopWarning);
|
||||
}
|
||||
|
||||
return resizeResult.hasViewportSurfacePresentation;
|
||||
}
|
||||
|
||||
@@ -209,6 +230,7 @@ void EditorWindowRuntimeController::CaptureIfRequested(
|
||||
bool framePresented) {
|
||||
m_autoScreenshot.CaptureIfRequested(
|
||||
m_renderer,
|
||||
m_windowRenderer,
|
||||
drawData,
|
||||
pixelWidth,
|
||||
pixelHeight,
|
||||
@@ -236,26 +258,17 @@ std::string EditorWindowRuntimeController::BuildCaptureStatusText() const {
|
||||
}
|
||||
|
||||
std::string EditorWindowRuntimeController::BuildFrameRateText() const {
|
||||
if (m_displayFps <= 0.0f || m_displayFrameTimeMs <= 0.0f) {
|
||||
return {};
|
||||
}
|
||||
|
||||
char buffer[48] = {};
|
||||
std::snprintf(
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
"FPS %.1f | %.2f ms",
|
||||
m_displayFps,
|
||||
m_displayFrameTimeMs);
|
||||
return buffer;
|
||||
return m_frameRateText;
|
||||
}
|
||||
|
||||
void EditorWindowRuntimeController::ResetFrameTiming() {
|
||||
m_lastFrameTime = {};
|
||||
m_hasLastFrameTime = false;
|
||||
m_smoothedDeltaTimeSeconds = 0.0f;
|
||||
m_frameStatsDisplayAccumulatorSeconds = 0.0f;
|
||||
m_displayFps = 0.0f;
|
||||
m_displayFrameTimeMs = 0.0f;
|
||||
m_frameRateText.clear();
|
||||
}
|
||||
|
||||
void EditorWindowRuntimeController::UpdateFrameTiming() {
|
||||
@@ -283,6 +296,33 @@ void EditorWindowRuntimeController::UpdateFrameTiming() {
|
||||
m_displayFps = m_smoothedDeltaTimeSeconds > 0.0f
|
||||
? 1.0f / m_smoothedDeltaTimeSeconds
|
||||
: 0.0f;
|
||||
|
||||
m_frameStatsDisplayAccumulatorSeconds += deltaTime;
|
||||
if (m_frameRateText.empty() ||
|
||||
m_frameStatsDisplayAccumulatorSeconds >= kFrameStatsDisplayRefreshIntervalSeconds) {
|
||||
RefreshDisplayedFrameStats();
|
||||
m_frameStatsDisplayAccumulatorSeconds = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorWindowRuntimeController::RefreshDisplayedFrameStats() {
|
||||
if (m_displayFps <= 0.0f || m_displayFrameTimeMs <= 0.0f) {
|
||||
m_frameRateText.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
const int roundedFps = (std::max)(0, static_cast<int>(std::lround(m_displayFps)));
|
||||
const int roundedFrameTimeMs =
|
||||
(std::max)(0, static_cast<int>(std::lround(m_displayFrameTimeMs)));
|
||||
|
||||
char buffer[48] = {};
|
||||
std::snprintf(
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
"FPS %3d | %2d ms",
|
||||
roundedFps,
|
||||
roundedFrameTimeMs);
|
||||
m_frameRateText = buffer;
|
||||
}
|
||||
|
||||
} // namespace XCEngine::UI::Editor::App
|
||||
|
||||
Reference in New Issue
Block a user