Fix new editor window resize presentation

This commit is contained in:
2026-04-13 12:20:25 +08:00
parent adb6fe4659
commit 0cc3d6da46
5 changed files with 1019 additions and 78 deletions

View File

@@ -37,6 +37,15 @@ constexpr const wchar_t* kWindowTitle = L"Main Scene * - Main.xx - XCEngine Edit
constexpr UINT kDefaultDpi = 96u;
constexpr float kBaseDpiScale = 96.0f;
bool ResolveVerboseRuntimeTraceEnabled() {
wchar_t buffer[8] = {};
const DWORD length = GetEnvironmentVariableW(
L"XCUIEDITOR_VERBOSE_TRACE",
buffer,
static_cast<DWORD>(std::size(buffer)));
return length > 0u && buffer[0] != L'0';
}
Application* GetApplicationFromWindow(HWND hwnd) {
return reinterpret_cast<Application*>(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
}
@@ -394,7 +403,6 @@ int Application::Run(HINSTANCE hInstance, int nCmdShow) {
}
RenderFrame();
Sleep(8);
}
Shutdown();
@@ -472,10 +480,17 @@ bool Application::Initialize(HINSTANCE hInstance, int nCmdShow) {
LogRuntimeTrace("app", "d3d12 window renderer initialization failed");
return false;
}
const bool hasD3D12WindowInterop = m_renderer.AttachWindowRenderer(m_windowRenderer);
if (!hasD3D12WindowInterop) {
LogRuntimeTrace(
"app",
"native renderer d3d12 interop unavailable; falling back to hwnd renderer: " +
m_renderer.GetLastRenderError());
}
m_editorContext.AttachTextMeasurer(m_renderer);
m_editorWorkspace.Initialize(repoRoot, m_renderer);
m_editorWorkspace.AttachViewportWindowRenderer(m_windowRenderer);
m_editorWorkspace.SetViewportSurfacePresentationEnabled(false);
m_editorWorkspace.SetViewportSurfacePresentationEnabled(hasD3D12WindowInterop);
if (!m_editorWorkspace.GetBuiltInIconError().empty()) {
LogRuntimeTrace("icons", m_editorWorkspace.GetBuiltInIconError());
}
@@ -544,7 +559,7 @@ void Application::RenderFrame() {
if (m_editorContext.IsValid()) {
std::vector<UIInputEvent> frameEvents = std::move(m_pendingInputEvents);
m_pendingInputEvents.clear();
if (!frameEvents.empty()) {
if (!frameEvents.empty() && IsVerboseRuntimeTraceEnabled()) {
LogRuntimeTrace(
"input",
DescribeInputEvents(frameEvents) + " | " +
@@ -552,8 +567,10 @@ void Application::RenderFrame() {
m_editorWorkspace.GetShellInteractionState()));
}
const bool d3d12FrameBegun = m_windowRenderer.BeginFrame();
if (!d3d12FrameBegun) {
const bool canUseWindowRenderer = m_renderer.HasAttachedWindowRenderer();
const bool d3d12FrameBegun =
canUseWindowRenderer && m_windowRenderer.BeginFrame();
if (canUseWindowRenderer && !d3d12FrameBegun) {
LogRuntimeTrace("viewport", "d3d12 frame begin failed");
}
@@ -562,17 +579,12 @@ void Application::RenderFrame() {
UIRect(0.0f, 0.0f, width, height),
frameEvents,
BuildCaptureStatusText());
if (d3d12FrameBegun) {
m_editorWorkspace.RenderRequestedViewports(m_windowRenderer.GetRenderContext());
if (!m_windowRenderer.SubmitFrame(false)) {
LogRuntimeTrace("viewport", "d3d12 offscreen frame submit failed");
}
}
const UIEditorShellInteractionFrame& shellFrame =
m_editorWorkspace.GetShellFrame();
if (!frameEvents.empty() ||
shellFrame.result.workspaceResult.dockHostResult.layoutChanged ||
shellFrame.result.workspaceResult.dockHostResult.commandExecuted) {
if (IsVerboseRuntimeTraceEnabled() &&
(!frameEvents.empty() ||
shellFrame.result.workspaceResult.dockHostResult.layoutChanged ||
shellFrame.result.workspaceResult.dockHostResult.commandExecuted)) {
std::ostringstream frameTrace = {};
frameTrace << "result consumed="
<< (shellFrame.result.consumed ? "true" : "false")
@@ -595,6 +607,9 @@ void Application::RenderFrame() {
ApplyHostedContentCaptureRequests();
ApplyCurrentCursor();
m_editorWorkspace.Append(drawList);
if (d3d12FrameBegun && !m_inInteractiveResize) {
m_editorWorkspace.RenderRequestedViewports(m_windowRenderer.GetRenderContext());
}
} else {
drawList.AddText(
UIPoint(28.0f, 28.0f),
@@ -610,7 +625,20 @@ void Application::RenderFrame() {
12.0f);
}
const bool framePresented = m_renderer.Render(drawData);
bool framePresented = false;
if (m_renderer.HasAttachedWindowRenderer()) {
framePresented = m_renderer.RenderToWindowRenderer(drawData);
if (!framePresented) {
LogRuntimeTrace(
"present",
"d3d12 window composition failed, falling back to hwnd renderer: " +
m_renderer.GetLastRenderError());
}
}
if (!framePresented) {
framePresented = m_renderer.Render(drawData);
}
m_autoScreenshot.CaptureIfRequested(
m_renderer,
drawData,
@@ -707,6 +735,11 @@ void Application::LogRuntimeTrace(
AppendUIEditorRuntimeTrace(channel, message);
}
bool Application::IsVerboseRuntimeTraceEnabled() {
static const bool s_enabled = ResolveVerboseRuntimeTraceEnabled();
return s_enabled;
}
std::string Application::DescribeInputEvents(
const std::vector<UIInputEvent>& events) const {
std::ostringstream stream = {};
@@ -726,13 +759,84 @@ std::string Application::DescribeInputEvents(
return stream.str();
}
void Application::OnResize(UINT width, UINT height) {
if (width == 0 || height == 0) {
void Application::OnResize() {
UINT width = 0u;
UINT height = 0u;
if (!QueryCurrentClientPixelSize(width, height)) {
return;
}
m_renderer.Resize(width, height);
m_windowRenderer.Resize(static_cast<int>(width), static_cast<int>(height));
CommitWindowResize();
if (m_inInteractiveResize) {
m_editorWorkspace.SetViewportSurfacePresentationEnabled(false);
}
}
void Application::OnEnterSizeMove() {
m_inInteractiveResize = true;
m_editorWorkspace.SetViewportSurfacePresentationEnabled(false);
}
void Application::OnExitSizeMove() {
m_inInteractiveResize = false;
CommitWindowResize();
}
bool Application::CommitWindowResize() {
UINT width = 0u;
UINT height = 0u;
if (!QueryCurrentClientPixelSize(width, height)) {
return false;
}
m_renderer.DetachWindowRenderer();
const bool resizedWindowRenderer =
m_windowRenderer.Resize(static_cast<int>(width), static_cast<int>(height));
const bool hasD3D12WindowInterop = resizedWindowRenderer &&
m_renderer.AttachWindowRenderer(m_windowRenderer);
const bool hasHealthyD3D12WindowInterop =
resizedWindowRenderer &&
hasD3D12WindowInterop;
m_editorWorkspace.SetViewportSurfacePresentationEnabled(hasHealthyD3D12WindowInterop);
if (!resizedWindowRenderer || !m_windowRenderer.GetLastError().empty()) {
LogRuntimeTrace(
"present",
"window renderer resize warning: " + m_windowRenderer.GetLastError());
}
if (!hasD3D12WindowInterop) {
LogRuntimeTrace(
"present",
"failed to rebuild d3d12 window interop after resize: " +
m_renderer.GetLastRenderError());
}
return hasHealthyD3D12WindowInterop;
}
bool Application::QueryCurrentClientPixelSize(UINT& outWidth, UINT& outHeight) const {
outWidth = 0u;
outHeight = 0u;
if (m_hwnd == nullptr || !IsWindow(m_hwnd)) {
return false;
}
RECT clientRect = {};
if (!GetClientRect(m_hwnd, &clientRect)) {
return false;
}
const LONG width = clientRect.right - clientRect.left;
const LONG height = clientRect.bottom - clientRect.top;
if (width <= 0 || height <= 0) {
return false;
}
outWidth = static_cast<UINT>(width);
outHeight = static_cast<UINT>(height);
return true;
}
void Application::OnDpiChanged(UINT dpi, const RECT& suggestedRect) {
@@ -748,6 +852,7 @@ void Application::OnDpiChanged(UINT dpi, const RECT& suggestedRect) {
suggestedRect.right - suggestedRect.left,
suggestedRect.bottom - suggestedRect.top,
SWP_NOZORDER | SWP_NOACTIVATE);
CommitWindowResize();
InvalidateRect(m_hwnd, nullptr, FALSE);
}
@@ -897,9 +1002,23 @@ LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT message, WPARAM wParam, LP
return 0;
}
break;
case WM_ENTERSIZEMOVE:
if (application != nullptr) {
application->OnEnterSizeMove();
return 0;
}
break;
case WM_EXITSIZEMOVE:
if (application != nullptr) {
application->OnExitSizeMove();
application->RenderFrame();
return 0;
}
break;
case WM_SIZE:
if (application != nullptr && wParam != SIZE_MINIMIZED) {
application->OnResize(static_cast<UINT>(LOWORD(lParam)), static_cast<UINT>(HIWORD(lParam)));
application->OnResize();
application->RenderFrame();
}
return 0;
case WM_PAINT: