#include "Rendering/Viewport/SceneViewportRenderService.h" #include #include namespace XCEngine::UI::Editor::App { namespace { ViewportRenderResult BuildFallbackResult( std::string statusText, float r, float g, float b, float a) { ViewportRenderResult result = {}; result.rendered = false; result.requiresFallbackClear = true; result.statusText = std::move(statusText); result.fallbackClearR = r; result.fallbackClearG = g; result.fallbackClearB = b; result.fallbackClearA = a; return result; } void SetStatusIfEmpty( std::string& statusText, std::string_view message) { if (statusText.empty()) { statusText = std::string(message); } } } // namespace SceneViewportRenderService::SceneViewportRenderService() = default; SceneViewportRenderService::~SceneViewportRenderService() = default; ViewportResourceRequirements SceneViewportRenderService::GetViewportResourceRequirements() { ViewportResourceRequirements requirements = {}; requirements.requiresDepthSampling = true; requirements.requiresObjectIdSurface = true; requirements.requiresSelectionMaskSurface = true; return requirements; } void SceneViewportRenderService::Shutdown() { m_renderRequest = {}; m_renderPassBundle.Shutdown(); m_sceneRenderer.reset(); m_device = nullptr; m_lastTargets = nullptr; m_lastRenderContext = {}; } void SceneViewportRenderService::SetRenderRequest( SceneViewportRenderRequest request) { m_renderRequest = std::move(request); } ViewportRenderResult SceneViewportRenderService::Render( ViewportRenderTargets& targets, ::XCEngine::RHI::RHIDevice& device, const ::XCEngine::Rendering::RenderContext& renderContext) { m_device = &device; m_lastTargets = &targets; m_lastRenderContext = renderContext; if (m_renderRequest.camera == nullptr) { return BuildFallbackResult( "Scene view camera is unavailable", 0.18f, 0.07f, 0.07f, 1.0f); } if (m_renderRequest.scene == nullptr) { return BuildFallbackResult( "No active scene", 0.07f, 0.08f, 0.10f, 1.0f); } EnsureSceneRenderer(); ::XCEngine::Rendering::RenderSurface surface = BuildViewportColorSurface(targets); std::vector<::XCEngine::Rendering::CameraFramePlan> plans = m_sceneRenderer->BuildFramePlans( *m_renderRequest.scene, m_renderRequest.camera, renderContext, surface); if (plans.empty()) { return BuildFallbackResult( "Scene renderer failed", 0.18f, 0.07f, 0.07f, 1.0f); } ViewportRenderResult result = {}; SceneViewportRenderPlanBuildResult renderPlan = m_renderPassBundle.BuildRenderPlan(targets, m_renderRequest); ApplySceneViewportRenderPlan( targets, renderPlan.plan, plans.front()); if (renderPlan.warningStatusText != nullptr) { SetStatusIfEmpty(result.statusText, renderPlan.warningStatusText); } if (!m_sceneRenderer->Render(plans)) { return BuildFallbackResult( "Scene renderer failed", 0.18f, 0.07f, 0.07f, 1.0f); } MarkSceneViewportRenderSuccess( targets, renderPlan.plan, plans.front()); result.rendered = true; return result; } ViewportObjectIdPickResult SceneViewportRenderService::PickObject( const ::XCEngine::UI::UISize& viewportSize, const ::XCEngine::UI::UIPoint& viewportMousePosition) const { if (!m_renderRequest.IsValid() || m_device == nullptr || m_lastTargets == nullptr) { return {}; } ViewportObjectIdPickContext pickContext = {}; pickContext.commandQueue = m_lastRenderContext.commandQueue; pickContext.texture = m_lastTargets->objectIdTexture; pickContext.textureState = m_lastTargets->objectIdState; pickContext.textureWidth = m_lastTargets->width; pickContext.textureHeight = m_lastTargets->height; pickContext.hasValidFrame = m_lastTargets->hasValidObjectIdFrame; pickContext.viewportSize = viewportSize; pickContext.viewportMousePosition = viewportMousePosition; return PickViewportObjectIdEntity( pickContext, [this]( const ViewportObjectIdReadbackRequest& request, std::array& outRgba) { return m_device->ReadTexturePixelRGBA8( request.commandQueue, request.texture, request.textureState, request.pixelX, request.pixelY, outRgba); }); } void SceneViewportRenderService::EnsureSceneRenderer() { if (!m_sceneRenderer) { m_sceneRenderer = std::make_unique<::XCEngine::Rendering::SceneRenderer>(); } } } // namespace XCEngine::UI::Editor::App