#include namespace XCEngine { namespace Rendering { RenderSurface CameraFramePlan::BuildGraphManagedIntermediateSurfaceTemplate( const RenderSurface& surface) { RenderSurface graphManagedSurface = surface; graphManagedSurface.SetColorAttachments({}); graphManagedSurface.SetAutoTransitionEnabled(false); graphManagedSurface.SetColorStateBefore(RHI::ResourceStates::Common); graphManagedSurface.SetColorStateAfter(RHI::ResourceStates::Common); return graphManagedSurface; } CameraFramePlan CameraFramePlan::FromRequest(const CameraRenderRequest& request) { CameraFramePlan plan = {}; plan.request = request; plan.shadowCaster = request.shadowCaster; plan.directionalShadow = request.directionalShadow; plan.postProcess = request.postProcess; plan.finalOutput = request.finalOutput; plan.finalColorPolicy = request.finalColorPolicy; plan.preScenePasses = request.preScenePasses; plan.postScenePasses = request.postScenePasses; plan.overlayPasses = request.overlayPasses; return plan; } bool CameraFramePlan::IsValid() const { return request.IsValid(); } void CameraFramePlan::ConfigureGraphManagedMainSceneSurface() { graphManagedMainSceneSurface = BuildGraphManagedIntermediateSurfaceTemplate(request.surface); } bool CameraFramePlan::UsesGraphManagedMainSceneColor() const { return colorChain.usesGraphManagedMainSceneColor; } bool CameraFramePlan::UsesGraphManagedOutputColor(CameraFrameStage stage) const { if (const CameraFrameFullscreenStagePlan* fullscreenStagePlan = GetFullscreenStagePlan(stage); fullscreenStagePlan != nullptr) { return fullscreenStagePlan->usesGraphManagedOutputColor; } return false; } CameraFrameColorSource CameraFramePlan::ResolveStageColorSource(CameraFrameStage stage) const { if (const CameraFrameFullscreenStagePlan* fullscreenStagePlan = GetFullscreenStagePlan(stage); fullscreenStagePlan != nullptr) { return fullscreenStagePlan->source; } return CameraFrameColorSource::ExplicitSurface; } bool CameraFramePlan::IsPostProcessStageValid() const { if (!postProcess.IsRequested()) { return true; } if (ResolveStageColorSource(CameraFrameStage::PostProcess) == CameraFrameColorSource::ExplicitSurface) { return postProcess.IsValid(); } const bool hasUsableDestination = UsesGraphManagedOutputColor(CameraFrameStage::PostProcess) || (HasValidColorTarget(postProcess.destinationSurface) && HasValidSurfaceSampleDescription(postProcess.destinationSurface)); return UsesGraphManagedMainSceneColor() && postProcess.passes != nullptr && HasValidSingleSampleColorSource(request.surface) && hasUsableDestination; } bool CameraFramePlan::IsFinalOutputStageValid() const { if (!finalOutput.IsRequested()) { return true; } const CameraFrameColorSource finalOutputSource = ResolveStageColorSource(CameraFrameStage::FinalOutput); if (finalOutputSource == CameraFrameColorSource::ExplicitSurface) { return finalOutput.IsValid(); } const bool hasUsableSource = finalOutputSource == CameraFrameColorSource::MainSceneColor ? UsesGraphManagedMainSceneColor() : UsesGraphManagedOutputColor(CameraFrameStage::PostProcess); return hasUsableSource && finalOutput.passes != nullptr && HasValidColorTarget(finalOutput.destinationSurface) && HasValidSurfaceSampleDescription(finalOutput.destinationSurface); } bool CameraFramePlan::HasFrameStage(CameraFrameStage stage) const { if (stage == CameraFrameStage::MainScene) { return true; } if (IsCameraFrameSequenceStage(stage)) { if (const FullscreenPassRenderRequest* fullscreenRequest = GetFullscreenPassRequest(stage); fullscreenRequest != nullptr) { return fullscreenRequest->IsRequested(); } return GetPassSequence(stage) != nullptr; } switch (GetCameraFrameStageRequestKind(stage)) { case CameraFrameStageRequestKind::ShadowCaster: return shadowCaster.IsRequested() || directionalShadow.IsValid(); case CameraFrameStageRequestKind::DepthOnly: return request.depthOnly.IsRequested(); case CameraFrameStageRequestKind::ObjectId: return request.objectId.IsRequested(); default: return false; } } RenderPassSequence* CameraFramePlan::GetPassSequence(CameraFrameStage stage) const { if (!IsCameraFrameSequenceStage(stage)) { return nullptr; } switch (stage) { case CameraFrameStage::PreScenePasses: return preScenePasses; case CameraFrameStage::PostProcess: return postProcess.passes; case CameraFrameStage::FinalOutput: return finalOutput.passes; case CameraFrameStage::PostScenePasses: return postScenePasses; case CameraFrameStage::OverlayPasses: return overlayPasses; default: return nullptr; } } const FullscreenPassRenderRequest* CameraFramePlan::GetFullscreenPassRequest( CameraFrameStage stage) const { switch (stage) { case CameraFrameStage::PostProcess: return &postProcess; case CameraFrameStage::FinalOutput: return &finalOutput; default: return nullptr; } } const CameraFrameFullscreenStagePlan* CameraFramePlan::GetFullscreenStagePlan( CameraFrameStage stage) const { switch (stage) { case CameraFrameStage::PostProcess: return &colorChain.postProcess; case CameraFrameStage::FinalOutput: return &colorChain.finalOutput; default: return nullptr; } } const ScenePassRenderRequest* CameraFramePlan::GetScenePassRequest(CameraFrameStage stage) const { switch (GetCameraFrameStageRequestKind(stage)) { case CameraFrameStageRequestKind::ShadowCaster: return &shadowCaster; case CameraFrameStageRequestKind::DepthOnly: return &request.depthOnly; default: return nullptr; } } const ObjectIdRenderRequest* CameraFramePlan::GetObjectIdRequest(CameraFrameStage stage) const { return GetCameraFrameStageRequestKind(stage) == CameraFrameStageRequestKind::ObjectId ? &request.objectId : nullptr; } const RenderSurface& CameraFramePlan::GetMainSceneSurface() const { if (UsesGraphManagedMainSceneColor() && graphManagedMainSceneSurface.GetWidth() > 0u && graphManagedMainSceneSurface.GetHeight() > 0u) { return graphManagedMainSceneSurface; } if (postProcess.IsRequested() && HasValidColorTarget(postProcess.sourceSurface)) { return postProcess.sourceSurface; } if (finalOutput.IsRequested() && HasValidColorTarget(finalOutput.sourceSurface)) { return finalOutput.sourceSurface; } return request.surface; } const RenderSurface& CameraFramePlan::GetFinalCompositedSurface() const { if (finalOutput.IsRequested() && HasValidColorTarget(finalOutput.destinationSurface)) { return finalOutput.destinationSurface; } if (postProcess.IsRequested() && HasValidColorTarget(postProcess.destinationSurface)) { return postProcess.destinationSurface; } return request.surface; } bool CameraFramePlan::RequiresIntermediateSceneColor() const { return postProcess.IsRequested() || finalOutput.IsRequested(); } } // namespace Rendering } // namespace XCEngine