Align rendering orchestration with camera stack plans
This commit is contained in:
89
engine/src/Rendering/Execution/CameraStackFramePlan.cpp
Normal file
89
engine/src/Rendering/Execution/CameraStackFramePlan.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#include <XCEngine/Rendering/Execution/CameraStackFramePlan.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <utility>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
namespace {
|
||||
|
||||
uint64_t AllocateCameraStackFramePlanId() {
|
||||
static std::atomic<uint64_t> s_nextStackPlanId{ 1u };
|
||||
uint64_t stackPlanId =
|
||||
s_nextStackPlanId.fetch_add(
|
||||
1u,
|
||||
std::memory_order_relaxed);
|
||||
if (stackPlanId == 0u) {
|
||||
stackPlanId =
|
||||
s_nextStackPlanId.fetch_add(
|
||||
1u,
|
||||
std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
return stackPlanId;
|
||||
}
|
||||
|
||||
bool IsBaseCameraPlan(const CameraFramePlan& plan) {
|
||||
return plan.request.cameraStackOrder == 0u;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
CameraStackFramePlan CameraStackFramePlan::FromCameraPlans(
|
||||
uint64_t cameraStackId,
|
||||
std::vector<CameraFramePlan> cameraPlans) {
|
||||
CameraStackFramePlan stackPlan = {};
|
||||
stackPlan.stackPlanId = AllocateCameraStackFramePlanId();
|
||||
stackPlan.cameraStackId = cameraStackId;
|
||||
stackPlan.cameraPlans = std::move(cameraPlans);
|
||||
return stackPlan;
|
||||
}
|
||||
|
||||
bool CameraStackFramePlan::IsValid() const {
|
||||
if (stackPlanId == 0u ||
|
||||
cameraPlans.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const CameraFramePlan& plan : cameraPlans) {
|
||||
if (!plan.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CameraStackFramePlan::HasBaseCamera() const {
|
||||
return GetBaseCameraPlan() != nullptr;
|
||||
}
|
||||
|
||||
bool CameraStackFramePlan::IsOverlayOnly() const {
|
||||
return !cameraPlans.empty() &&
|
||||
!HasBaseCamera();
|
||||
}
|
||||
|
||||
const CameraFramePlan* CameraStackFramePlan::GetBaseCameraPlan() const {
|
||||
for (const CameraFramePlan& plan : cameraPlans) {
|
||||
if (IsBaseCameraPlan(plan)) {
|
||||
return &plan;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const CameraFramePlan* CameraStackFramePlan::GetSortKeyPlan() const {
|
||||
if (const CameraFramePlan* const basePlan = GetBaseCameraPlan();
|
||||
basePlan != nullptr) {
|
||||
return basePlan;
|
||||
}
|
||||
|
||||
return cameraPlans.empty()
|
||||
? nullptr
|
||||
: &cameraPlans.front();
|
||||
}
|
||||
|
||||
} // namespace Rendering
|
||||
} // namespace XCEngine
|
||||
@@ -3,6 +3,9 @@
|
||||
#include "Rendering/Planning/CameraFramePlanBuilder.h"
|
||||
#include "Rendering/Planning/SceneRenderRequestUtils.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
@@ -16,6 +19,23 @@ bool CompareCameraFramePlans(
|
||||
rhs.request);
|
||||
}
|
||||
|
||||
bool CompareCameraStackFramePlans(
|
||||
const CameraStackFramePlan& lhs,
|
||||
const CameraStackFramePlan& rhs) {
|
||||
const CameraFramePlan* const lhsSortKeyPlan =
|
||||
lhs.GetSortKeyPlan();
|
||||
const CameraFramePlan* const rhsSortKeyPlan =
|
||||
rhs.GetSortKeyPlan();
|
||||
if (lhsSortKeyPlan == nullptr ||
|
||||
rhsSortKeyPlan == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return CompareCameraFramePlans(
|
||||
*lhsSortKeyPlan,
|
||||
*rhsSortKeyPlan);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
RenderPipelineHost::RenderPipelineHost()
|
||||
@@ -42,8 +62,22 @@ std::vector<CameraFramePlan> RenderPipelineHost::BuildFramePlans(
|
||||
: std::vector<CameraFramePlan>();
|
||||
}
|
||||
|
||||
std::vector<CameraStackFramePlan> RenderPipelineHost::BuildStackFramePlans(
|
||||
const std::vector<CameraRenderRequest>& requests) {
|
||||
return m_framePlanBuilder != nullptr
|
||||
? m_framePlanBuilder->BuildStackPlans(
|
||||
requests,
|
||||
GetPipelineAsset())
|
||||
: std::vector<CameraStackFramePlan>();
|
||||
}
|
||||
|
||||
bool RenderPipelineHost::Render(const CameraFramePlan& plan) {
|
||||
return m_cameraRenderer.Render(plan);
|
||||
std::vector<CameraFramePlan> plans = {};
|
||||
plans.push_back(plan);
|
||||
return Render(
|
||||
CameraStackFramePlan::FromCameraPlans(
|
||||
plan.request.cameraStackId,
|
||||
std::move(plans)));
|
||||
}
|
||||
|
||||
bool RenderPipelineHost::Render(const std::vector<CameraFramePlan>& plans) {
|
||||
@@ -63,8 +97,20 @@ bool RenderPipelineHost::Render(const std::vector<CameraFramePlan>& plans) {
|
||||
sortedPlans.end(),
|
||||
CompareCameraFramePlans);
|
||||
|
||||
return Render(
|
||||
m_framePlanBuilder != nullptr
|
||||
? m_framePlanBuilder->BuildStackPlansFromFramePlans(
|
||||
std::move(sortedPlans))
|
||||
: std::vector<CameraStackFramePlan>());
|
||||
}
|
||||
|
||||
bool RenderPipelineHost::Render(const CameraStackFramePlan& stackPlan) {
|
||||
if (!stackPlan.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool rendered = false;
|
||||
for (const CameraFramePlan& plan : sortedPlans) {
|
||||
for (const CameraFramePlan& plan : stackPlan.cameraPlans) {
|
||||
if (!m_cameraRenderer.Render(plan)) {
|
||||
return false;
|
||||
}
|
||||
@@ -72,6 +118,44 @@ bool RenderPipelineHost::Render(const std::vector<CameraFramePlan>& plans) {
|
||||
rendered = true;
|
||||
}
|
||||
|
||||
if (rendered) {
|
||||
if (RenderPipeline* const pipeline = GetPipeline();
|
||||
pipeline != nullptr) {
|
||||
pipeline->FinishCameraStackRendering(stackPlan);
|
||||
}
|
||||
}
|
||||
|
||||
return rendered;
|
||||
}
|
||||
|
||||
bool RenderPipelineHost::Render(const std::vector<CameraStackFramePlan>& stackPlans) {
|
||||
if (stackPlans.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const CameraStackFramePlan& stackPlan : stackPlans) {
|
||||
if (!stackPlan.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<CameraStackFramePlan> sortedStackPlans =
|
||||
stackPlans;
|
||||
std::stable_sort(
|
||||
sortedStackPlans.begin(),
|
||||
sortedStackPlans.end(),
|
||||
CompareCameraStackFramePlans);
|
||||
|
||||
bool rendered = false;
|
||||
for (const CameraStackFramePlan& stackPlan :
|
||||
sortedStackPlans) {
|
||||
if (!Render(stackPlan)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rendered = true;
|
||||
}
|
||||
|
||||
return rendered;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,21 @@ std::vector<CameraFramePlan> SceneRenderer::BuildFramePlans(
|
||||
return m_pipelineHost.BuildFramePlans(requests);
|
||||
}
|
||||
|
||||
std::vector<CameraStackFramePlan> SceneRenderer::BuildStackFramePlans(
|
||||
const Components::Scene& scene,
|
||||
Components::CameraComponent* overrideCamera,
|
||||
const RenderContext& context,
|
||||
const RenderSurface& surface) {
|
||||
const std::vector<CameraRenderRequest> requests =
|
||||
m_requestPlanner.BuildRequests(
|
||||
scene,
|
||||
overrideCamera,
|
||||
context,
|
||||
surface,
|
||||
m_pipelineHost.GetPipelineAsset());
|
||||
return m_pipelineHost.BuildStackFramePlans(requests);
|
||||
}
|
||||
|
||||
bool SceneRenderer::Render(const CameraFramePlan& plan) {
|
||||
return m_pipelineHost.Render(plan);
|
||||
}
|
||||
@@ -42,12 +57,20 @@ bool SceneRenderer::Render(const std::vector<CameraFramePlan>& plans) {
|
||||
return m_pipelineHost.Render(plans);
|
||||
}
|
||||
|
||||
bool SceneRenderer::Render(const CameraStackFramePlan& stackPlan) {
|
||||
return m_pipelineHost.Render(stackPlan);
|
||||
}
|
||||
|
||||
bool SceneRenderer::Render(const std::vector<CameraStackFramePlan>& stackPlans) {
|
||||
return m_pipelineHost.Render(stackPlans);
|
||||
}
|
||||
|
||||
bool SceneRenderer::Render(
|
||||
const Components::Scene& scene,
|
||||
Components::CameraComponent* overrideCamera,
|
||||
const RenderContext& context,
|
||||
const RenderSurface& surface) {
|
||||
return Render(BuildFramePlans(scene, overrideCamera, context, surface));
|
||||
return Render(BuildStackFramePlans(scene, overrideCamera, context, surface));
|
||||
}
|
||||
|
||||
} // namespace Rendering
|
||||
|
||||
@@ -193,6 +193,13 @@ bool ScriptableRenderPipelineHost::Render(
|
||||
m_pipelineBackend->Render(context, surface, sceneData);
|
||||
}
|
||||
|
||||
void ScriptableRenderPipelineHost::FinishCameraStackRendering(
|
||||
const CameraStackFramePlan& stackPlan) {
|
||||
if (m_stageRecorder != nullptr) {
|
||||
m_stageRecorder->FinishCameraStackRendering(stackPlan);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptableRenderPipelineHost::ConfigureRenderSceneData(
|
||||
const CameraFramePlan& plan,
|
||||
RenderSceneData& sceneData) const {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "Rendering/RenderPipelineAsset.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
@@ -13,6 +15,19 @@ std::vector<CameraFramePlan> CameraFramePlanBuilder::BuildPlans(
|
||||
return plans;
|
||||
}
|
||||
|
||||
std::vector<CameraStackFramePlan> CameraFramePlanBuilder::BuildStackPlans(
|
||||
const std::vector<CameraRenderRequest>& requests,
|
||||
const RenderPipelineAsset* pipelineAsset) {
|
||||
std::vector<CameraFramePlan> plans = CreatePlansFromRequests(requests);
|
||||
ConfigurePlans(plans, pipelineAsset);
|
||||
return CreateStackPlansFromPlans(std::move(plans));
|
||||
}
|
||||
|
||||
std::vector<CameraStackFramePlan> CameraFramePlanBuilder::BuildStackPlansFromFramePlans(
|
||||
std::vector<CameraFramePlan> plans) const {
|
||||
return CreateStackPlansFromPlans(std::move(plans));
|
||||
}
|
||||
|
||||
std::vector<CameraFramePlan> CameraFramePlanBuilder::CreatePlansFromRequests(
|
||||
const std::vector<CameraRenderRequest>& requests) const {
|
||||
std::vector<CameraFramePlan> plans = {};
|
||||
@@ -24,6 +39,43 @@ std::vector<CameraFramePlan> CameraFramePlanBuilder::CreatePlansFromRequests(
|
||||
return plans;
|
||||
}
|
||||
|
||||
std::vector<CameraStackFramePlan> CameraFramePlanBuilder::CreateStackPlansFromPlans(
|
||||
std::vector<CameraFramePlan> plans) const {
|
||||
std::vector<CameraStackFramePlan> stackPlans = {};
|
||||
if (plans.empty()) {
|
||||
return stackPlans;
|
||||
}
|
||||
|
||||
stackPlans.reserve(plans.size());
|
||||
|
||||
for (CameraFramePlan& plan : plans) {
|
||||
const uint64_t cameraStackId = plan.request.cameraStackId;
|
||||
if (cameraStackId != 0u) {
|
||||
bool appendedToExistingStack = false;
|
||||
for (CameraStackFramePlan& stackPlan : stackPlans) {
|
||||
if (stackPlan.cameraStackId == cameraStackId) {
|
||||
stackPlan.cameraPlans.push_back(std::move(plan));
|
||||
appendedToExistingStack = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (appendedToExistingStack) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<CameraFramePlan> stackCameraPlans = {};
|
||||
stackCameraPlans.push_back(std::move(plan));
|
||||
stackPlans.push_back(
|
||||
CameraStackFramePlan::FromCameraPlans(
|
||||
cameraStackId,
|
||||
std::move(stackCameraPlans)));
|
||||
}
|
||||
|
||||
return stackPlans;
|
||||
}
|
||||
|
||||
void CameraFramePlanBuilder::ConfigurePlans(
|
||||
std::vector<CameraFramePlan>& plans,
|
||||
const RenderPipelineAsset* pipelineAsset) const {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Rendering/Execution/CameraFramePlan.h>
|
||||
#include <XCEngine/Rendering/Execution/CameraStackFramePlan.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -19,10 +20,17 @@ public:
|
||||
std::vector<CameraFramePlan> BuildPlans(
|
||||
const std::vector<CameraRenderRequest>& requests,
|
||||
const RenderPipelineAsset* pipelineAsset);
|
||||
std::vector<CameraStackFramePlan> BuildStackPlans(
|
||||
const std::vector<CameraRenderRequest>& requests,
|
||||
const RenderPipelineAsset* pipelineAsset);
|
||||
std::vector<CameraStackFramePlan> BuildStackPlansFromFramePlans(
|
||||
std::vector<CameraFramePlan> plans) const;
|
||||
|
||||
private:
|
||||
std::vector<CameraFramePlan> CreatePlansFromRequests(
|
||||
const std::vector<CameraRenderRequest>& requests) const;
|
||||
std::vector<CameraStackFramePlan> CreateStackPlansFromPlans(
|
||||
std::vector<CameraFramePlan> plans) const;
|
||||
void ConfigurePlans(
|
||||
std::vector<CameraFramePlan>& plans,
|
||||
const RenderPipelineAsset* pipelineAsset) const;
|
||||
|
||||
@@ -56,6 +56,8 @@ std::vector<CameraRenderRequest> SceneRenderRequestPlanner::BuildRequests(
|
||||
CollectCameras(scene, overrideCamera);
|
||||
|
||||
size_t renderedBaseCameraCount = 0;
|
||||
uint64_t nextCameraStackId = 1u;
|
||||
uint64_t activeCameraStackId = 0u;
|
||||
for (Components::CameraComponent* camera : cameras) {
|
||||
CameraRenderRequest request;
|
||||
if (!SceneRenderRequestUtils::BuildCameraRenderRequest(
|
||||
@@ -69,6 +71,12 @@ std::vector<CameraRenderRequest> SceneRenderRequestPlanner::BuildRequests(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (camera->GetStackType() == Components::CameraStackType::Base ||
|
||||
activeCameraStackId == 0u) {
|
||||
activeCameraStackId = nextCameraStackId++;
|
||||
}
|
||||
request.cameraStackId = activeCameraStackId;
|
||||
|
||||
if (pipelineAsset != nullptr) {
|
||||
pipelineAsset->ConfigureCameraRenderRequest(
|
||||
request,
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "Physics/PhysicsWorld.h"
|
||||
#include "Rendering/Caches/DirectionalShadowSurfaceCache.h"
|
||||
#include "Rendering/Execution/CameraFramePlan.h"
|
||||
#include "Rendering/Execution/CameraStackFramePlan.h"
|
||||
#include "Rendering/Execution/DirectionalShadowExecutionState.h"
|
||||
#include "Rendering/Execution/CameraFrameRenderGraphFrameData.h"
|
||||
#include "Rendering/Execution/Internal/CameraFrameGraph/SurfaceUtils.h"
|
||||
@@ -2134,6 +2135,7 @@ public:
|
||||
m_supportsStageContextualMethod = nullptr;
|
||||
m_supportsStageMethod = nullptr;
|
||||
m_recordStageMethod = nullptr;
|
||||
m_finishCameraStackRenderingMethod = nullptr;
|
||||
m_resolvedPipelineHandle = 0;
|
||||
m_boundSceneDrawBackend = nullptr;
|
||||
}
|
||||
@@ -2322,6 +2324,35 @@ public:
|
||||
return flushed;
|
||||
}
|
||||
|
||||
void FinishCameraStackRendering(
|
||||
const Rendering::CameraStackFramePlan& stackPlan) override {
|
||||
if (!IsRuntimeAlive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MonoObject* const pipelineObject = GetManagedPipelineObject();
|
||||
MonoMethod* const method =
|
||||
ResolveFinishCameraStackRenderingMethod(pipelineObject);
|
||||
if (pipelineObject == nullptr ||
|
||||
method == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const Rendering::CameraFramePlan& plan :
|
||||
stackPlan.cameraPlans) {
|
||||
int32_t rendererIndex = plan.request.rendererIndex;
|
||||
uint64_t framePlanId = plan.framePlanId;
|
||||
void* args[2] = {
|
||||
&rendererIndex,
|
||||
&framePlanId };
|
||||
m_runtime->InvokeManagedMethod(
|
||||
pipelineObject,
|
||||
method,
|
||||
args,
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct ManagedRenderFuncExecutionState {
|
||||
std::shared_ptr<const MonoManagedRenderPipelineAssetRuntime>
|
||||
@@ -2415,6 +2446,7 @@ private:
|
||||
m_supportsStageContextualMethod = nullptr;
|
||||
m_supportsStageMethod = nullptr;
|
||||
m_recordStageMethod = nullptr;
|
||||
m_finishCameraStackRenderingMethod = nullptr;
|
||||
m_resolvedPipelineHandle = pipelineHandle;
|
||||
}
|
||||
|
||||
@@ -2471,6 +2503,19 @@ private:
|
||||
return m_recordStageMethod;
|
||||
}
|
||||
|
||||
MonoMethod* ResolveFinishCameraStackRenderingMethod(
|
||||
MonoObject* pipelineObject) const {
|
||||
if (m_finishCameraStackRenderingMethod == nullptr) {
|
||||
m_finishCameraStackRenderingMethod =
|
||||
m_runtime->ResolveManagedMethod(
|
||||
pipelineObject,
|
||||
"FinishCameraStackRenderingInstance",
|
||||
2);
|
||||
}
|
||||
|
||||
return m_finishCameraStackRenderingMethod;
|
||||
}
|
||||
|
||||
bool FlushManagedRasterPasses(
|
||||
const Rendering::RenderPipelineStageRenderGraphContext& context,
|
||||
ManagedScriptableRenderContextState& managedContextState) {
|
||||
@@ -2653,6 +2698,7 @@ private:
|
||||
mutable MonoMethod* m_supportsStageContextualMethod = nullptr;
|
||||
mutable MonoMethod* m_supportsStageMethod = nullptr;
|
||||
mutable MonoMethod* m_recordStageMethod = nullptr;
|
||||
mutable MonoMethod* m_finishCameraStackRenderingMethod = nullptr;
|
||||
mutable uint32_t m_resolvedPipelineHandle = 0;
|
||||
std::vector<std::unique_ptr<Rendering::RenderPass>> m_fullscreenPassPool = {};
|
||||
Rendering::SceneDrawBackend* m_boundSceneDrawBackend = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user