diff --git a/new_editor/CMakeLists.txt b/new_editor/CMakeLists.txt index 83fd3903..8414f187 100644 --- a/new_editor/CMakeLists.txt +++ b/new_editor/CMakeLists.txt @@ -141,6 +141,7 @@ xcui_editor_apply_common_target_settings(XCUIEditorHost PUBLIC) target_link_libraries(XCUIEditorHost PUBLIC XCEngine d2d1.lib + d3d11.lib d3d12.lib d3dcompiler.lib dwrite.lib diff --git a/new_editor/app/Application.cpp b/new_editor/app/Application.cpp index 8be4f23a..aac5f746 100644 --- a/new_editor/app/Application.cpp +++ b/new_editor/app/Application.cpp @@ -36,6 +36,7 @@ constexpr const wchar_t* kWindowClassName = L"XCEditorShellHost"; constexpr const wchar_t* kWindowTitle = L"Main Scene * - Main.xx - XCEngine Editor"; constexpr UINT kDefaultDpi = 96u; constexpr float kBaseDpiScale = 96.0f; +constexpr UINT kDeferredRenderMessage = WM_APP + 1u; bool ResolveVerboseRuntimeTraceEnabled() { wchar_t buffer[8] = {}; @@ -541,6 +542,8 @@ void Application::RenderFrame() { return; } + ApplyPendingWindowResize(); + RECT clientRect = {}; GetClientRect(m_hwnd, &clientRect); const unsigned int pixelWidth = @@ -607,7 +610,7 @@ void Application::RenderFrame() { ApplyHostedContentCaptureRequests(); ApplyCurrentCursor(); m_editorWorkspace.Append(drawList); - if (d3d12FrameBegun && !m_inInteractiveResize) { + if (d3d12FrameBegun) { m_editorWorkspace.RenderRequestedViewports(m_windowRenderer.GetRenderContext()); } } else { @@ -760,36 +763,51 @@ std::string Application::DescribeInputEvents( } void Application::OnResize() { + QueueCurrentClientResize(); +} + +void Application::OnEnterSizeMove() { + m_inInteractiveResize = true; +} + +void Application::OnExitSizeMove() { + m_inInteractiveResize = false; + QueueCurrentClientResize(); +} + +void Application::QueueWindowResize(UINT width, UINT height) { + if (width == 0u || height == 0u) { + return; + } + + m_pendingWindowResizeWidth = width; + m_pendingWindowResizeHeight = height; + m_hasPendingWindowResize = true; +} + +void Application::QueueCurrentClientResize() { UINT width = 0u; UINT height = 0u; if (!QueryCurrentClientPixelSize(width, height)) { return; } - m_renderer.Resize(width, height); - CommitWindowResize(); - if (m_inInteractiveResize) { - m_editorWorkspace.SetViewportSurfacePresentationEnabled(false); + QueueWindowResize(width, height); +} + +bool Application::ApplyPendingWindowResize() { + if (!m_hasPendingWindowResize) { + return true; } -} -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)) { + const UINT width = m_pendingWindowResizeWidth; + const UINT height = m_pendingWindowResizeHeight; + m_hasPendingWindowResize = false; + if (width == 0u || height == 0u) { return false; } + m_renderer.Resize(width, height); m_renderer.DetachWindowRenderer(); const bool resizedWindowRenderer = m_windowRenderer.Resize(static_cast(width), static_cast(height)); @@ -816,6 +834,15 @@ bool Application::CommitWindowResize() { return hasHealthyD3D12WindowInterop; } +void Application::RequestDeferredRenderFrame() { + if (m_hwnd == nullptr || !IsWindow(m_hwnd) || m_renderFrameQueued) { + return; + } + + m_renderFrameQueued = true; + PostMessageW(m_hwnd, kDeferredRenderMessage, 0, 0); +} + bool Application::QueryCurrentClientPixelSize(UINT& outWidth, UINT& outHeight) const { outWidth = 0u; outHeight = 0u; @@ -844,16 +871,18 @@ void Application::OnDpiChanged(UINT dpi, const RECT& suggestedRect) { m_dpiScale = GetDpiScale(); m_renderer.SetDpiScale(m_dpiScale); if (m_hwnd != nullptr) { + const LONG windowWidth = suggestedRect.right - suggestedRect.left; + const LONG windowHeight = suggestedRect.bottom - suggestedRect.top; SetWindowPos( m_hwnd, nullptr, suggestedRect.left, suggestedRect.top, - suggestedRect.right - suggestedRect.left, - suggestedRect.bottom - suggestedRect.top, + windowWidth, + windowHeight, SWP_NOZORDER | SWP_NOACTIVATE); - CommitWindowResize(); - InvalidateRect(m_hwnd, nullptr, FALSE); + QueueCurrentClientResize(); + RequestDeferredRenderFrame(); } std::ostringstream trace = {}; @@ -1011,16 +1040,23 @@ LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT message, WPARAM wParam, LP case WM_EXITSIZEMOVE: if (application != nullptr) { application->OnExitSizeMove(); - application->RenderFrame(); + application->RequestDeferredRenderFrame(); return 0; } break; case WM_SIZE: if (application != nullptr && wParam != SIZE_MINIMIZED) { application->OnResize(); - application->RenderFrame(); + application->RequestDeferredRenderFrame(); } return 0; + case kDeferredRenderMessage: + if (application != nullptr) { + application->m_renderFrameQueued = false; + application->RenderFrame(); + return 0; + } + break; case WM_PAINT: if (application != nullptr) { PAINTSTRUCT paintStruct = {}; diff --git a/new_editor/app/Application.h b/new_editor/app/Application.h index fe29a522..c5183079 100644 --- a/new_editor/app/Application.h +++ b/new_editor/app/Application.h @@ -37,8 +37,15 @@ private: bool Initialize(HINSTANCE hInstance, int nCmdShow); void Shutdown(); void RenderFrame(); - void OnResize(UINT width, UINT height); + void OnResize(); + void OnEnterSizeMove(); + void OnExitSizeMove(); void OnDpiChanged(UINT dpi, const RECT& suggestedRect); + void QueueWindowResize(UINT width, UINT height); + void QueueCurrentClientResize(); + bool ApplyPendingWindowResize(); + void RequestDeferredRenderFrame(); + bool QueryCurrentClientPixelSize(UINT& outWidth, UINT& outHeight) const; bool IsPointerInsideClientArea() const; bool ApplyCurrentCursor() const; LPCWSTR ResolveCurrentCursorResource() const; @@ -64,6 +71,7 @@ private: void QueueWindowFocusEvent(::XCEngine::UI::UIInputEventType type); static std::filesystem::path ResolveRepoRootPath(); static LONG WINAPI HandleUnhandledException(EXCEPTION_POINTERS* exceptionInfo); + static bool IsVerboseRuntimeTraceEnabled(); HWND m_hwnd = nullptr; HINSTANCE m_hInstance = nullptr; @@ -78,6 +86,11 @@ private: bool m_trackingMouseLeave = false; UINT m_windowDpi = 96u; float m_dpiScale = 1.0f; + bool m_inInteractiveResize = false; + bool m_renderFrameQueued = false; + bool m_hasPendingWindowResize = false; + UINT m_pendingWindowResizeWidth = 0u; + UINT m_pendingWindowResizeHeight = 0u; }; int RunXCUIEditorApp(HINSTANCE hInstance, int nCmdShow); diff --git a/new_editor/app/Host/D3D12WindowRenderer.h b/new_editor/app/Host/D3D12WindowRenderer.h index 7ae7acba..666f4f81 100644 --- a/new_editor/app/Host/D3D12WindowRenderer.h +++ b/new_editor/app/Host/D3D12WindowRenderer.h @@ -22,7 +22,10 @@ #include #include +#include +#include +#include #include namespace XCEngine::UI::Editor::Host { @@ -34,13 +37,17 @@ public: bool Initialize(HWND hwnd, int width, int height); void Shutdown(); - void Resize(int width, int height); + bool Resize(int width, int height); bool BeginFrame(); + bool PreparePresentSurface(); bool SubmitFrame(bool presentSwapChain); + bool SignalFrameCompletion(); + bool PresentFrame(); ID3D12Device* GetDevice() const; ID3D12DescriptorHeap* GetSrvHeap() const; ID3D12CommandQueue* GetCommandQueue() const; + const std::string& GetLastError() const; void AllocateShaderResourceDescriptor( D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle, D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle); @@ -57,6 +64,9 @@ public: ::XCEngine::RHI::RHIDevice* GetRHIDevice() const; ::XCEngine::RHI::RHISwapChain* GetSwapChain() const; const ::XCEngine::Rendering::RenderSurface* GetCurrentRenderSurface() const; + const ::XCEngine::RHI::D3D12Texture* GetCurrentBackBufferTexture() const; + const ::XCEngine::RHI::D3D12Texture* GetBackBufferTexture(std::uint32_t index) const; + std::uint32_t GetBackBufferCount() const; ::XCEngine::Rendering::RenderContext GetRenderContext() const; private: @@ -64,13 +74,18 @@ private: ::XCEngine::RHI::D3D12CommandQueue* GetD3D12CommandQueue() const; ::XCEngine::RHI::D3D12CommandList* GetD3D12CommandList() const; ::XCEngine::RHI::D3D12SwapChain* GetD3D12SwapChain() const; + ::XCEngine::RHI::RHICommandList* GetCurrentCommandList() const; void AllocateShaderResourceDescriptorInternal( D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle, D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle); void FreeShaderResourceDescriptorInternal( D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle, D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle); + bool InitializeFrameCompletionFence(); + void ReleaseFrameCompletionFence(); + void WaitForBackBufferFrame(std::uint32_t backBufferIndex); void WaitForGpuIdle(); + void ReleaseBackBufferCommandReferences(); void ReleaseBackBufferViews(); bool RecreateBackBufferViews(); @@ -80,13 +95,19 @@ private: ::XCEngine::RHI::RHIDevice* m_device = nullptr; ::XCEngine::RHI::RHICommandQueue* m_commandQueue = nullptr; - ::XCEngine::RHI::RHICommandList* m_commandList = nullptr; + std::array<::XCEngine::RHI::RHICommandList*, kSwapChainBufferCount> m_commandLists = {}; ::XCEngine::RHI::RHISwapChain* m_swapChain = nullptr; ::XCEngine::RHI::RHIDescriptorPool* m_srvPool = nullptr; ::XCEngine::RHI::D3D12DescriptorHeap* m_srvHeap = nullptr; std::vector m_srvUsage = {}; std::vector<::XCEngine::RHI::RHIResourceView*> m_backBufferViews = {}; std::vector<::XCEngine::Rendering::RenderSurface> m_backBufferSurfaces = {}; + Microsoft::WRL::ComPtr m_frameCompletionFence = {}; + HANDLE m_frameCompletionEvent = nullptr; + std::array m_backBufferFenceValues = {}; + std::uint32_t m_activeBackBufferIndex = 0u; + std::uint64_t m_lastSubmittedFrameValue = 0; + std::string m_lastError = {}; UINT m_srvDescriptorSize = 0; }; diff --git a/new_editor/app/Host/NativeRenderer.h b/new_editor/app/Host/NativeRenderer.h index 5c5a7970..0594d625 100644 --- a/new_editor/app/Host/NativeRenderer.h +++ b/new_editor/app/Host/NativeRenderer.h @@ -4,12 +4,17 @@ #define NOMINMAX #endif +#include "D3D12WindowRenderer.h" + #include #include -#include +#include +#include +#include #include +#include #include #include #include @@ -30,7 +35,13 @@ public: void SetDpiScale(float dpiScale); float GetDpiScale() const; void Resize(UINT width, UINT height); + bool AttachWindowRenderer(D3D12WindowRenderer& windowRenderer); + void DetachWindowRenderer(); + void ReleaseWindowRendererBackBufferTargets(); + bool RebuildWindowRendererBackBufferTargets(); + bool HasAttachedWindowRenderer() const; bool Render(const ::XCEngine::UI::UIDrawData& drawData); + bool RenderToWindowRenderer(const ::XCEngine::UI::UIDrawData& drawData); const std::string& GetLastRenderError() const; bool LoadTextureFromFile( const std::filesystem::path& path, @@ -47,15 +58,6 @@ public: std::string& outError); private: - bool EnsureRenderTarget(); - bool EnsureWicFactory(std::string& outError); - void DiscardRenderTarget(); - bool CreateDeviceResources(); - void InvalidateCachedTextureBitmaps(const ID2D1RenderTarget* renderTarget); - bool RenderToTarget( - ID2D1RenderTarget& renderTarget, - ID2D1SolidColorBrush& solidBrush, - const ::XCEngine::UI::UIDrawData& drawData); struct NativeTextureResource { std::vector pixels = {}; Microsoft::WRL::ComPtr cachedBitmap = {}; @@ -63,6 +65,30 @@ private: UINT width = 0u; UINT height = 0u; }; + struct D3D12BackBufferInteropTarget { + Microsoft::WRL::ComPtr wrappedResource = {}; + Microsoft::WRL::ComPtr targetBitmap = {}; + }; + struct D3D12SourceTextureInteropResource { + std::uintptr_t key = 0u; + Microsoft::WRL::ComPtr wrappedResource = {}; + Microsoft::WRL::ComPtr bitmap = {}; + }; + + bool EnsureRenderTarget(); + bool EnsureWindowRendererInterop(); + bool EnsureWicFactory(std::string& outError); + void DiscardRenderTarget(); + bool CreateDeviceResources(); + void ReleaseWindowRendererInterop(); + bool RebuildBackBufferInteropTargets(); + void ClearActiveInteropSourceTextures(); + bool PrepareActiveInteropSourceTextures(const ::XCEngine::UI::UIDrawData& drawData); + void InvalidateCachedTextureBitmaps(const ID2D1RenderTarget* renderTarget); + bool RenderToTarget( + ID2D1RenderTarget& renderTarget, + ID2D1SolidColorBrush& solidBrush, + const ::XCEngine::UI::UIDrawData& drawData); bool DecodeTextureFile( const std::filesystem::path& path, NativeTextureResource& outTexture, @@ -71,6 +97,9 @@ private: ID2D1RenderTarget& renderTarget, NativeTextureResource& texture, Microsoft::WRL::ComPtr& outBitmap); + bool ResolveInteropBitmap( + const ::XCEngine::UI::UITextureHandle& texture, + Microsoft::WRL::ComPtr& outBitmap) const; void RenderCommand( ID2D1RenderTarget& renderTarget, ID2D1SolidColorBrush& solidBrush, @@ -82,11 +111,21 @@ private: static std::wstring Utf8ToWide(std::string_view text); HWND m_hwnd = nullptr; - Microsoft::WRL::ComPtr m_d2dFactory; + D3D12WindowRenderer* m_windowRenderer = nullptr; + Microsoft::WRL::ComPtr m_d2dFactory; Microsoft::WRL::ComPtr m_dwriteFactory; Microsoft::WRL::ComPtr m_wicFactory; + Microsoft::WRL::ComPtr m_d3d11Device; + Microsoft::WRL::ComPtr m_d3d11DeviceContext; + Microsoft::WRL::ComPtr m_d3d11On12Device; + Microsoft::WRL::ComPtr m_d2dDevice; + Microsoft::WRL::ComPtr m_d2dDeviceContext; Microsoft::WRL::ComPtr m_renderTarget; Microsoft::WRL::ComPtr m_solidBrush; + Microsoft::WRL::ComPtr m_interopBrush; + std::vector m_backBufferInteropTargets = {}; + std::vector m_activeInteropSourceTextures = {}; + std::unordered_map> m_activeInteropBitmaps; mutable std::unordered_map> m_textFormats; std::unordered_set m_liveTextures; std::string m_lastRenderError = {}; diff --git a/new_editor/app/Shell/ProductShellAsset.cpp b/new_editor/app/Shell/ProductShellAsset.cpp index e8e08e1e..018ab0c5 100644 --- a/new_editor/app/Shell/ProductShellAsset.cpp +++ b/new_editor/app/Shell/ProductShellAsset.cpp @@ -429,11 +429,10 @@ UIEditorWorkspacePanelPresentationModel BuildViewportPresentation( presentation.panelId = std::move(panelId); presentation.kind = UIEditorPanelPresentationKind::ViewportShell; presentation.viewportShellModel.spec.chrome.title = std::move(title); - presentation.viewportShellModel.spec.chrome.subtitle = std::move(subtitle); - presentation.viewportShellModel.spec.chrome.showTopBar = true; - presentation.viewportShellModel.spec.chrome.showBottomBar = true; - presentation.viewportShellModel.frame.statusText = - "Viewport request chain is active."; + presentation.viewportShellModel.spec.chrome.subtitle = {}; + presentation.viewportShellModel.spec.chrome.showTopBar = false; + presentation.viewportShellModel.spec.chrome.showBottomBar = false; + presentation.viewportShellModel.frame.statusText.clear(); return presentation; } @@ -448,8 +447,8 @@ UIEditorShellInteractionDefinition BuildBaseShellDefinition() { definition.statusSegments = {}; definition.workspacePresentations = { BuildHostedContentPresentation("hierarchy"), - BuildViewportPresentation("scene", "Scene", "New Editor viewport shell"), - BuildViewportPresentation("game", "Game", "New Editor viewport shell"), + BuildViewportPresentation("scene", "Scene", {}), + BuildViewportPresentation("game", "Game", {}), BuildHostedContentPresentation("inspector"), BuildHostedContentPresentation("console"), BuildHostedContentPresentation("project") diff --git a/new_editor/app/Viewport/ProductViewportHostService.cpp b/new_editor/app/Viewport/ProductViewportHostService.cpp index 71019c71..e9bd29ac 100644 --- a/new_editor/app/Viewport/ProductViewportHostService.cpp +++ b/new_editor/app/Viewport/ProductViewportHostService.cpp @@ -8,24 +8,6 @@ namespace { using ::XCEngine::RHI::ResourceStates; -std::string BuildViewportPendingStatus(ProductViewportKind kind) { - return kind == ProductViewportKind::Scene - ? "Scene viewport host pending D3D12 presenter integration." - : "Game viewport host pending D3D12 presenter integration."; -} - -std::string BuildViewportReadyStatus(ProductViewportKind kind) { - return kind == ProductViewportKind::Scene - ? "Scene viewport render target ready; presenter still uses NativeRenderer." - : "Game viewport render target ready; presenter still uses NativeRenderer."; -} - -std::string BuildViewportPresentedStatus(ProductViewportKind kind) { - return kind == ProductViewportKind::Scene - ? "Scene viewport frame ready." - : "Game viewport frame ready."; -} - } // namespace void ProductViewportHostService::AttachWindowRenderer( @@ -81,23 +63,17 @@ ProductViewportFrame ProductViewportHostService::RequestViewport( : 0u; if (!entry.requestedThisFrame) { - entry.statusText = "Viewport is waiting for a visible surface."; return BuildFrame(entry, requestedSize); } if (m_windowRenderer == nullptr || m_device == nullptr) { - entry.statusText = BuildViewportPendingStatus(kind); return BuildFrame(entry, requestedSize); } if (!EnsureViewportResources(entry)) { - entry.statusText = "Failed to create viewport render targets."; return BuildFrame(entry, requestedSize); } - entry.statusText = m_surfacePresentationEnabled - ? BuildViewportPresentedStatus(kind) - : BuildViewportReadyStatus(kind); return BuildFrame(entry, requestedSize); } @@ -119,9 +95,6 @@ void ProductViewportHostService::RenderRequestedViewports( } entry.renderedThisFrame = true; - entry.statusText = m_surfacePresentationEnabled - ? BuildViewportPresentedStatus(entry.kind) - : BuildViewportReadyStatus(entry.kind); } } diff --git a/new_editor/app/Workspace/ProductEditorWorkspace.cpp b/new_editor/app/Workspace/ProductEditorWorkspace.cpp index 670d16a4..e770e67d 100644 --- a/new_editor/app/Workspace/ProductEditorWorkspace.cpp +++ b/new_editor/app/Workspace/ProductEditorWorkspace.cpp @@ -36,33 +36,62 @@ void ApplyViewportFrameToPresentation( presentation.viewportShellModel.frame.statusText = viewportFrame.statusText; } -std::vector BuildWorkspacePresentations( - const UIEditorShellInteractionDefinition& definition, - const UIEditorShellInteractionRequest& shellRequest, - ProductViewportHostService& viewportHostService) { - std::vector presentations = - definition.workspacePresentations; - for (UIEditorWorkspacePanelPresentationModel& presentation : presentations) { - if (presentation.kind != UIEditorPanelPresentationKind::ViewportShell || - !IsProductViewportPanel(presentation.panelId)) { - continue; - } +void ApplyViewportFrameToShellModel( + const ProductViewportFrame& viewportFrame, + UIEditorViewportShellModel& shellModel) { + shellModel.frame.texture = viewportFrame.texture; + shellModel.frame.requestedSize = viewportFrame.requestedSize; + shellModel.frame.presentedSize = viewportFrame.renderSize; + shellModel.frame.hasTexture = viewportFrame.hasTexture; + shellModel.frame.statusText = viewportFrame.statusText; +} - const UIEditorWorkspaceViewportComposeRequest* viewportRequest = - FindUIEditorWorkspaceViewportPresentationRequest( - shellRequest.shellRequest.workspaceRequest, - presentation.panelId); - const ::XCEngine::UI::UISize requestedSize = - viewportRequest != nullptr - ? viewportRequest->viewportShellRequest.requestedViewportSize - : ::XCEngine::UI::UISize(); - ApplyViewportFrameToPresentation( - viewportHostService.RequestViewport( - ResolveProductViewportKind(presentation.panelId), - requestedSize), - presentation); +UIEditorWorkspacePanelPresentationModel* FindMutableWorkspacePresentation( + std::vector& presentations, + std::string_view panelId) { + for (UIEditorWorkspacePanelPresentationModel& presentation : presentations) { + if (presentation.panelId == panelId) { + return &presentation; + } } - return presentations; + + return nullptr; +} + +void ApplyViewportFramesToShellFrame( + UIEditorShellInteractionFrame& shellFrame, + ProductViewportHostService& viewportHostService) { + auto applyToViewportFrames = + [&](std::vector& viewportFrames) { + for (UIEditorWorkspaceViewportComposeFrame& viewportComposeFrame : viewportFrames) { + if (!IsProductViewportPanel(viewportComposeFrame.panelId)) { + continue; + } + + const ProductViewportFrame viewportFrame = + viewportHostService.RequestViewport( + ResolveProductViewportKind(viewportComposeFrame.panelId), + viewportComposeFrame.viewportShellFrame.requestedViewportSize); + ApplyViewportFrameToShellModel( + viewportFrame, + viewportComposeFrame.viewportShellModel); + if (UIEditorWorkspacePanelPresentationModel* presentation = + FindMutableWorkspacePresentation( + shellFrame.model.workspacePresentations, + viewportComposeFrame.panelId); + presentation != nullptr) { + ApplyViewportFrameToPresentation(viewportFrame, *presentation); + } + } + }; + + applyToViewportFrames(shellFrame.workspaceInteractionFrame.composeFrame.viewportFrames); + applyToViewportFrames(shellFrame.shellFrame.workspaceFrame.viewportFrames); +} + +std::vector BuildWorkspacePresentations( + const UIEditorShellInteractionDefinition& definition) { + return definition.workspacePresentations; } UIEditorShellComposeModel BuildShellComposeModelFromFrame( @@ -168,18 +197,7 @@ void ProductEditorWorkspace::Update( UIEditorShellInteractionDefinition definition = context.BuildShellDefinition(captureText); m_viewportHostService.BeginFrame(); - const UIEditorShellInteractionRequest shellRequest = - ResolveUIEditorShellInteractionRequest( - bounds, - context.GetWorkspaceController(), - definition, - m_shellInteractionState, - metrics, - context.GetShellServices()); - definition.workspacePresentations = BuildWorkspacePresentations( - definition, - shellRequest, - m_viewportHostService); + definition.workspacePresentations = BuildWorkspacePresentations(definition); const std::vector hostedContentEvents = inputEvents; const std::vector shellEvents = HasHostedContentCapture() @@ -194,6 +212,7 @@ void ProductEditorWorkspace::Update( shellEvents, context.GetShellServices(), metrics); + ApplyViewportFramesToShellFrame(m_shellFrame, m_viewportHostService); context.SyncSessionFromWorkspace(); context.UpdateStatusFromShellResult(m_shellFrame.result); diff --git a/new_editor/include/XCEditor/Foundation/UIEditorRuntimeTrace.h b/new_editor/include/XCEditor/Foundation/UIEditorRuntimeTrace.h index 1839db21..b2832c88 100644 --- a/new_editor/include/XCEditor/Foundation/UIEditorRuntimeTrace.h +++ b/new_editor/include/XCEditor/Foundation/UIEditorRuntimeTrace.h @@ -19,5 +19,6 @@ void AppendUIEditorCrashTrace( std::filesystem::path GetUIEditorRuntimeTracePath(); std::filesystem::path GetUIEditorCrashTracePath(); +bool IsUIEditorRuntimeTraceInitialized(); } // namespace XCEngine::UI::Editor diff --git a/new_editor/src/Foundation/UIEditorRuntimeTrace.cpp b/new_editor/src/Foundation/UIEditorRuntimeTrace.cpp index 630e7182..42ff5a59 100644 --- a/new_editor/src/Foundation/UIEditorRuntimeTrace.cpp +++ b/new_editor/src/Foundation/UIEditorRuntimeTrace.cpp @@ -17,6 +17,8 @@ std::mutex g_traceMutex = {}; std::filesystem::path g_logRoot = {}; std::filesystem::path g_runtimeTracePath = {}; std::filesystem::path g_crashTracePath = {}; +std::ofstream g_runtimeTraceStream = {}; +std::ofstream g_crashTraceStream = {}; bool g_traceInitialized = false; std::string BuildTimestampString() { @@ -40,16 +42,9 @@ std::string BuildTimestampString() { } void AppendTraceLine( - const std::filesystem::path& path, + std::ofstream& stream, std::string_view channel, std::string_view message) { - if (path.empty()) { - return; - } - - std::error_code errorCode = {}; - std::filesystem::create_directories(path.parent_path(), errorCode); - std::ofstream stream(path, std::ios::out | std::ios::app); if (!stream.is_open()) { return; } @@ -70,11 +65,20 @@ void InitializeUIEditorRuntimeTrace(const std::filesystem::path& logRoot) { g_logRoot = logRoot.lexically_normal(); g_runtimeTracePath = (g_logRoot / "runtime.log").lexically_normal(); g_crashTracePath = (g_logRoot / "crash.log").lexically_normal(); - g_traceInitialized = true; std::error_code errorCode = {}; std::filesystem::create_directories(g_logRoot, errorCode); - AppendTraceLine(g_runtimeTracePath, "trace", "trace session started"); + g_runtimeTraceStream.close(); + g_crashTraceStream.close(); + g_runtimeTraceStream.open(g_runtimeTracePath, std::ios::out | std::ios::app); + g_crashTraceStream.open(g_crashTracePath, std::ios::out | std::ios::app); + g_traceInitialized = g_runtimeTraceStream.is_open() && g_crashTraceStream.is_open(); + if (!g_traceInitialized) { + return; + } + + AppendTraceLine(g_runtimeTraceStream, "trace", "trace session started"); + g_runtimeTraceStream.flush(); } void ShutdownUIEditorRuntimeTrace() { @@ -83,7 +87,11 @@ void ShutdownUIEditorRuntimeTrace() { return; } - AppendTraceLine(g_runtimeTracePath, "trace", "trace session ended"); + AppendTraceLine(g_runtimeTraceStream, "trace", "trace session ended"); + g_runtimeTraceStream.flush(); + g_crashTraceStream.flush(); + g_runtimeTraceStream.close(); + g_crashTraceStream.close(); g_traceInitialized = false; } @@ -95,7 +103,7 @@ void AppendUIEditorRuntimeTrace( return; } - AppendTraceLine(g_runtimeTracePath, channel, message); + AppendTraceLine(g_runtimeTraceStream, channel, message); } void AppendUIEditorCrashTrace( @@ -113,8 +121,10 @@ void AppendUIEditorCrashTrace( "Unhandled exception code=0x%08X address=%p", exceptionCode, exceptionAddress); - AppendTraceLine(g_crashTracePath, "crash", buffer); - AppendTraceLine(g_runtimeTracePath, "crash", buffer); + AppendTraceLine(g_crashTraceStream, "crash", buffer); + AppendTraceLine(g_runtimeTraceStream, "crash", buffer); + g_crashTraceStream.flush(); + g_runtimeTraceStream.flush(); } std::filesystem::path GetUIEditorRuntimeTracePath() { @@ -127,4 +137,9 @@ std::filesystem::path GetUIEditorCrashTracePath() { return g_crashTracePath; } +bool IsUIEditorRuntimeTraceInitialized() { + std::lock_guard lock(g_traceMutex); + return g_traceInitialized; +} + } // namespace XCEngine::UI::Editor diff --git a/new_editor/src/Shell/UIEditorViewportSlot.cpp b/new_editor/src/Shell/UIEditorViewportSlot.cpp index 78d7e5d0..5f0b9ec9 100644 --- a/new_editor/src/Shell/UIEditorViewportSlot.cpp +++ b/new_editor/src/Shell/UIEditorViewportSlot.cpp @@ -55,34 +55,6 @@ UISize ResolveFrameAspectSize(const UIEditorViewportSlotFrame& frame, const UISi return fallback; } -UIRect FitRectToAspect(const UIRect& container, const UISize& size) { - if (!HasArea(container) || size.width <= 0.0f || size.height <= 0.0f) { - return container; - } - - const float containerAspect = container.width / container.height; - const float frameAspect = size.width / size.height; - if (frameAspect <= 0.0f) { - return container; - } - - if (frameAspect >= containerAspect) { - const float fittedHeight = container.width / frameAspect; - return UIRect( - container.x, - container.y + (container.height - fittedHeight) * 0.5f, - container.width, - fittedHeight); - } - - const float fittedWidth = container.height * frameAspect; - return UIRect( - container.x + (container.width - fittedWidth) * 0.5f, - container.y, - fittedWidth, - container.height); -} - UIColor ResolveToolFillColor( const UIEditorViewportSlotToolItem& item, bool hovered, @@ -199,11 +171,7 @@ UIEditorViewportSlotLayout BuildUIEditorViewportSlotLayout( layout.inputRect = InsetRect(layout.surfaceRect, metrics.surfaceInset); layout.requestedSurfaceSize = UISize(layout.inputRect.width, layout.inputRect.height); - layout.textureRect = frame.hasTexture - ? FitRectToAspect( - layout.inputRect, - ResolveFrameAspectSize(frame, layout.requestedSurfaceSize)) - : layout.inputRect; + layout.textureRect = layout.inputRect; if (!layout.hasTopBar) { return layout; @@ -437,34 +405,8 @@ void AppendUIEditorViewportSlotForeground( } } - const UISize frameSize = ResolveFrameAspectSize(frame, layout.requestedSurfaceSize); if (frame.hasTexture && frame.texture.IsValid()) { drawList.AddImage(layout.textureRect, frame.texture, palette.imageTint); - drawList.AddText( - UIPoint(layout.inputRect.x + 14.0f, layout.inputRect.y + 14.0f), - "Texture " + - std::to_string(static_cast(frameSize.width)) + - "x" + - std::to_string(static_cast(frameSize.height)), - palette.textMuted, - 12.0f); - } else { - const std::string statusText = frame.statusText.empty() - ? std::string("Viewport is waiting for frame") - : frame.statusText; - drawList.AddText( - UIPoint(layout.inputRect.x + 16.0f, layout.inputRect.y + 18.0f), - statusText, - palette.textPrimary, - 14.0f); - drawList.AddText( - UIPoint(layout.inputRect.x + 16.0f, layout.inputRect.y + 42.0f), - "Requested surface: " + - std::to_string(static_cast(layout.requestedSurfaceSize.width)) + - "x" + - std::to_string(static_cast(layout.requestedSurfaceSize.height)), - palette.textMuted, - 12.0f); } if (layout.hasBottomBar) {