From c17fcd450f4fca542466b06fa27eb890b0a12002 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Tue, 31 Mar 2026 22:10:27 +0800 Subject: [PATCH] refactor: split viewport host rendering paths --- editor/src/Viewport/ViewportHostService.h | 378 ++++++++++++---------- 1 file changed, 212 insertions(+), 166 deletions(-) diff --git a/editor/src/Viewport/ViewportHostService.h b/editor/src/Viewport/ViewportHostService.h index 78facc9b..5233c718 100644 --- a/editor/src/Viewport/ViewportHostService.h +++ b/editor/src/Viewport/ViewportHostService.h @@ -300,6 +300,13 @@ private: SceneViewportCameraController controller; }; + struct SceneViewportRenderState { + SceneViewportOverlayData overlay = {}; + Rendering::RenderPassSequence postPasses; + Rendering::RenderCameraData cameraData = {}; + std::vector selectionRenderables; + }; + ViewportEntry& GetEntry(EditorViewportKind kind) { const size_t index = kind == EditorViewportKind::Scene ? 0u : 1u; m_entries[index].kind = kind; @@ -378,6 +385,100 @@ private: m_sceneViewCamera.controller.Focus(center); } + RHI::TextureDesc BuildViewportTextureDesc(uint32_t width, uint32_t height, RHI::Format format) const { + RHI::TextureDesc desc = {}; + desc.width = width; + desc.height = height; + desc.depth = 1; + desc.mipLevels = 1; + desc.arraySize = 1; + desc.format = static_cast(format); + desc.textureType = static_cast(RHI::TextureType::Texture2D); + desc.sampleCount = 1; + desc.sampleQuality = 0; + desc.flags = 0; + return desc; + } + + RHI::ResourceViewDesc BuildViewportTextureViewDesc(RHI::Format format) const { + RHI::ResourceViewDesc desc = {}; + desc.format = static_cast(format); + desc.dimension = RHI::ResourceViewDimension::Texture2D; + return desc; + } + + bool CreateViewportColorResources(ViewportEntry& entry) { + const RHI::TextureDesc colorDesc = + BuildViewportTextureDesc(entry.width, entry.height, RHI::Format::R8G8B8A8_UNorm); + entry.colorTexture = m_device->CreateTexture(colorDesc); + if (entry.colorTexture == nullptr) { + return false; + } + + const RHI::ResourceViewDesc colorViewDesc = + BuildViewportTextureViewDesc(RHI::Format::R8G8B8A8_UNorm); + entry.colorView = m_device->CreateRenderTargetView(entry.colorTexture, colorViewDesc); + return entry.colorView != nullptr; + } + + bool CreateViewportDepthResources(ViewportEntry& entry) { + const RHI::TextureDesc depthDesc = + BuildViewportTextureDesc(entry.width, entry.height, RHI::Format::D24_UNorm_S8_UInt); + entry.depthTexture = m_device->CreateTexture(depthDesc); + if (entry.depthTexture == nullptr) { + return false; + } + + const RHI::ResourceViewDesc depthViewDesc = + BuildViewportTextureViewDesc(RHI::Format::D24_UNorm_S8_UInt); + entry.depthView = m_device->CreateDepthStencilView(entry.depthTexture, depthViewDesc); + return entry.depthView != nullptr; + } + + bool CreateSceneViewportSelectionMaskResources(ViewportEntry& entry) { + const RHI::TextureDesc selectionMaskDesc = + BuildViewportTextureDesc(entry.width, entry.height, RHI::Format::R8G8B8A8_UNorm); + entry.selectionMaskTexture = m_device->CreateTexture(selectionMaskDesc); + if (entry.selectionMaskTexture == nullptr) { + return false; + } + + const RHI::ResourceViewDesc selectionMaskViewDesc = + BuildViewportTextureViewDesc(RHI::Format::R8G8B8A8_UNorm); + entry.selectionMaskView = m_device->CreateRenderTargetView( + entry.selectionMaskTexture, + selectionMaskViewDesc); + if (entry.selectionMaskView == nullptr) { + return false; + } + + entry.selectionMaskShaderView = m_device->CreateShaderResourceView( + entry.selectionMaskTexture, + selectionMaskViewDesc); + return entry.selectionMaskShaderView != nullptr; + } + + bool CreateViewportTextureDescriptor(ViewportEntry& entry) { + m_backend->AllocateTextureDescriptor(&entry.imguiCpuHandle, &entry.imguiGpuHandle); + if (entry.imguiCpuHandle.ptr == 0 || entry.imguiGpuHandle.ptr == 0) { + return false; + } + + auto* nativeTexture = static_cast(entry.colorTexture); + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = 1; + m_device->GetDevice()->CreateShaderResourceView( + nativeTexture->GetResource(), + &srvDesc, + entry.imguiCpuHandle); + + entry.textureId = static_cast(entry.imguiGpuHandle.ptr); + return true; + } + bool EnsureViewportResources(ViewportEntry& entry) { if (entry.requestedWidth == 0 || entry.requestedHeight == 0) { return false; @@ -402,110 +503,26 @@ private: entry.width = entry.requestedWidth; entry.height = entry.requestedHeight; - RHI::TextureDesc colorDesc = {}; - colorDesc.width = entry.width; - colorDesc.height = entry.height; - colorDesc.depth = 1; - colorDesc.mipLevels = 1; - colorDesc.arraySize = 1; - colorDesc.format = static_cast(RHI::Format::R8G8B8A8_UNorm); - colorDesc.textureType = static_cast(RHI::TextureType::Texture2D); - colorDesc.sampleCount = 1; - colorDesc.sampleQuality = 0; - colorDesc.flags = 0; - entry.colorTexture = m_device->CreateTexture(colorDesc); - if (entry.colorTexture == nullptr) { + if (!CreateViewportColorResources(entry)) { DestroyViewportResources(entry); return false; } - RHI::ResourceViewDesc colorViewDesc = {}; - colorViewDesc.format = static_cast(RHI::Format::R8G8B8A8_UNorm); - colorViewDesc.dimension = RHI::ResourceViewDimension::Texture2D; - entry.colorView = m_device->CreateRenderTargetView(entry.colorTexture, colorViewDesc); - if (entry.colorView == nullptr) { + if (!CreateViewportDepthResources(entry)) { DestroyViewportResources(entry); return false; } - RHI::TextureDesc depthDesc = {}; - depthDesc.width = entry.width; - depthDesc.height = entry.height; - depthDesc.depth = 1; - depthDesc.mipLevels = 1; - depthDesc.arraySize = 1; - depthDesc.format = static_cast(RHI::Format::D24_UNorm_S8_UInt); - depthDesc.textureType = static_cast(RHI::TextureType::Texture2D); - depthDesc.sampleCount = 1; - depthDesc.sampleQuality = 0; - depthDesc.flags = 0; - entry.depthTexture = m_device->CreateTexture(depthDesc); - if (entry.depthTexture == nullptr) { - DestroyViewportResources(entry); - return false; - } - - RHI::ResourceViewDesc depthViewDesc = {}; - depthViewDesc.format = static_cast(RHI::Format::D24_UNorm_S8_UInt); - depthViewDesc.dimension = RHI::ResourceViewDimension::Texture2D; - entry.depthView = m_device->CreateDepthStencilView(entry.depthTexture, depthViewDesc); - if (entry.depthView == nullptr) { - DestroyViewportResources(entry); - return false; - } - - if (entry.kind == EditorViewportKind::Scene) { - RHI::TextureDesc selectionMaskDesc = {}; - selectionMaskDesc.width = entry.width; - selectionMaskDesc.height = entry.height; - selectionMaskDesc.depth = 1; - selectionMaskDesc.mipLevels = 1; - selectionMaskDesc.arraySize = 1; - selectionMaskDesc.format = static_cast(RHI::Format::R8G8B8A8_UNorm); - selectionMaskDesc.textureType = static_cast(RHI::TextureType::Texture2D); - selectionMaskDesc.sampleCount = 1; - selectionMaskDesc.sampleQuality = 0; - selectionMaskDesc.flags = 0; - entry.selectionMaskTexture = m_device->CreateTexture(selectionMaskDesc); - if (entry.selectionMaskTexture == nullptr) { + if (entry.kind == EditorViewportKind::Scene && + !CreateSceneViewportSelectionMaskResources(entry)) { DestroyViewportResources(entry); return false; - } - - RHI::ResourceViewDesc selectionMaskViewDesc = {}; - selectionMaskViewDesc.format = static_cast(RHI::Format::R8G8B8A8_UNorm); - selectionMaskViewDesc.dimension = RHI::ResourceViewDimension::Texture2D; - entry.selectionMaskView = m_device->CreateRenderTargetView(entry.selectionMaskTexture, selectionMaskViewDesc); - if (entry.selectionMaskView == nullptr) { - DestroyViewportResources(entry); - return false; - } - - entry.selectionMaskShaderView = m_device->CreateShaderResourceView(entry.selectionMaskTexture, selectionMaskViewDesc); - if (entry.selectionMaskShaderView == nullptr) { - DestroyViewportResources(entry); - return false; - } } - m_backend->AllocateTextureDescriptor(&entry.imguiCpuHandle, &entry.imguiGpuHandle); - if (entry.imguiCpuHandle.ptr == 0 || entry.imguiGpuHandle.ptr == 0) { + if (!CreateViewportTextureDescriptor(entry)) { DestroyViewportResources(entry); return false; } - - auto* nativeTexture = static_cast(entry.colorTexture); - D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; - srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = 1; - m_device->GetDevice()->CreateShaderResourceView( - nativeTexture->GetResource(), - &srvDesc, - entry.imguiCpuHandle); - - entry.textureId = static_cast(entry.imguiGpuHandle.ptr); entry.colorState = RHI::ResourceStates::Common; entry.selectionMaskState = RHI::ResourceStates::Common; return true; @@ -746,6 +763,110 @@ private: return true; } + void BuildSceneViewportRenderState( + ViewportEntry& entry, + IEditorContext& context, + const Components::Scene& scene, + SceneViewportRenderState& outState) { + outState.overlay = GetSceneViewOverlayData(); + if (!outState.overlay.valid) { + return; + } + + outState.selectionRenderables = CollectSceneViewportSelectionRenderables( + scene, + context.GetSelectionManager().GetSelectedEntities(), + outState.overlay.cameraPosition); + if (!outState.selectionRenderables.empty()) { + outState.cameraData = BuildSceneViewportCameraData( + *m_sceneViewCamera.camera, + entry.width, + entry.height); + } + + BuildSceneViewPostPassSequence( + entry, + outState.overlay, + outState.cameraData, + outState.selectionRenderables, + outState.postPasses); + } + + bool RenderSceneViewportEntry( + ViewportEntry& entry, + IEditorContext& context, + const Components::Scene* scene, + const Rendering::RenderContext& renderContext, + Rendering::RenderSurface& surface) { + surface.SetClearColorOverride(Math::Color(0.27f, 0.27f, 0.27f, 1.0f)); + if (!EnsureSceneViewCamera()) { + entry.statusText = "Scene view camera is unavailable"; + ClearViewport(entry, renderContext, 0.18f, 0.07f, 0.07f, 1.0f); + return false; + } + + ApplySceneViewCameraController(); + entry.statusText.clear(); + if (scene == nullptr) { + entry.statusText = "No active scene"; + ClearViewport(entry, renderContext, 0.07f, 0.08f, 0.10f, 1.0f); + return false; + } + + SceneViewportRenderState sceneState = {}; + BuildSceneViewportRenderState(entry, context, *scene, sceneState); + + std::vector requests = + m_sceneRenderer->BuildRenderRequests(*scene, m_sceneViewCamera.camera, renderContext, surface); + if (requests.empty()) { + SetViewportStatusIfEmpty(entry.statusText, "Scene renderer failed"); + ClearViewport(entry, renderContext, 0.18f, 0.07f, 0.07f, 1.0f); + return false; + } + + if (sceneState.postPasses.GetPassCount() > 0) { + requests[0].postScenePasses = &sceneState.postPasses; + } + + if (!m_sceneRenderer->Render(requests)) { + SetViewportStatusIfEmpty(entry.statusText, "Scene renderer failed"); + ClearViewport(entry, renderContext, 0.18f, 0.07f, 0.07f, 1.0f); + return false; + } + + entry.colorState = RHI::ResourceStates::PixelShaderResource; + return true; + } + + bool RenderGameViewportEntry( + ViewportEntry& entry, + const Components::Scene* scene, + const Rendering::RenderContext& renderContext, + const Rendering::RenderSurface& surface) { + if (scene == nullptr) { + entry.statusText = "No active scene"; + ClearViewport(entry, renderContext, 0.07f, 0.08f, 0.10f, 1.0f); + return false; + } + + const auto cameras = scene->FindObjectsOfType(); + if (cameras.empty()) { + entry.statusText = "No camera in scene"; + ClearViewport(entry, renderContext, 0.10f, 0.09f, 0.08f, 1.0f); + return false; + } + + if (!m_sceneRenderer->Render(*scene, nullptr, renderContext, surface)) { + entry.statusText = "Scene renderer failed"; + ClearViewport(entry, renderContext, 0.18f, 0.07f, 0.07f, 1.0f); + return false; + } + + entry.colorState = RHI::ResourceStates::PixelShaderResource; + entry.statusText.clear(); + return true; + } + void RenderViewportEntry( ViewportEntry& entry, IEditorContext& context, @@ -759,86 +880,11 @@ private: Rendering::RenderSurface surface = BuildSurface(entry); if (entry.kind == EditorViewportKind::Scene) { - surface.SetClearColorOverride(Math::Color(0.27f, 0.27f, 0.27f, 1.0f)); - if (!EnsureSceneViewCamera()) { - entry.statusText = "Scene view camera is unavailable"; - ClearViewport(entry, renderContext, 0.18f, 0.07f, 0.07f, 1.0f); - return; - } - - ApplySceneViewCameraController(); - entry.statusText.clear(); - if (scene == nullptr) { - entry.statusText = "No active scene"; - ClearViewport(entry, renderContext, 0.07f, 0.08f, 0.10f, 1.0f); - return; - } - - const SceneViewportOverlayData overlay = GetSceneViewOverlayData(); - Rendering::RenderPassSequence sceneViewPostPasses; - Rendering::RenderCameraData cameraData = {}; - std::vector selectionRenderables; - if (overlay.valid) { - selectionRenderables = CollectSceneViewportSelectionRenderables( - *scene, - context.GetSelectionManager().GetSelectedEntities(), - overlay.cameraPosition); - if (!selectionRenderables.empty()) { - cameraData = BuildSceneViewportCameraData( - *m_sceneViewCamera.camera, - entry.width, - entry.height); - } - BuildSceneViewPostPassSequence( - entry, - overlay, - cameraData, - selectionRenderables, - sceneViewPostPasses); - } - - std::vector requests = - m_sceneRenderer->BuildRenderRequests(*scene, m_sceneViewCamera.camera, renderContext, surface); - if (requests.empty()) { - SetViewportStatusIfEmpty(entry.statusText, "Scene renderer failed"); - ClearViewport(entry, renderContext, 0.18f, 0.07f, 0.07f, 1.0f); - return; - } - - if (sceneViewPostPasses.GetPassCount() > 0) { - requests[0].postScenePasses = &sceneViewPostPasses; - } - - if (!m_sceneRenderer->Render(requests)) { - SetViewportStatusIfEmpty(entry.statusText, "Scene renderer failed"); - ClearViewport(entry, renderContext, 0.18f, 0.07f, 0.07f, 1.0f); - return; - } - entry.colorState = RHI::ResourceStates::PixelShaderResource; + RenderSceneViewportEntry(entry, context, scene, renderContext, surface); return; } - if (scene == nullptr) { - entry.statusText = "No active scene"; - ClearViewport(entry, renderContext, 0.07f, 0.08f, 0.10f, 1.0f); - return; - } - - const auto cameras = scene->FindObjectsOfType(); - if (cameras.empty()) { - entry.statusText = "No camera in scene"; - ClearViewport(entry, renderContext, 0.10f, 0.09f, 0.08f, 1.0f); - return; - } - - if (!m_sceneRenderer->Render(*scene, nullptr, renderContext, surface)) { - entry.statusText = "Scene renderer failed"; - ClearViewport(entry, renderContext, 0.18f, 0.07f, 0.07f, 1.0f); - return; - } - - entry.colorState = RHI::ResourceStates::PixelShaderResource; - entry.statusText.clear(); + RenderGameViewportEntry(entry, scene, renderContext, surface); } void ClearViewport(