refactor(srp): move shadow caster stage selection into managed urp
- add standalone pass asset factories for camera frame stages\n- let managed pipeline assets declare stage pass asset keys\n- make universal renderer data explicitly own the builtin shadow caster stage
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
# SRP Universal Shadow Caster Stage Managed Ownership Plan 2026-04-21
|
||||
|
||||
## Goal
|
||||
|
||||
Move `CameraFrameStage::ShadowCaster` pass selection out of the native host hardcode and into managed URP ownership.
|
||||
|
||||
This stage does **not** move shadow rasterization itself into C#.
|
||||
It only makes managed URP explicitly declare which native shadow-caster pass asset it wants to use.
|
||||
|
||||
## Why This Stage
|
||||
|
||||
The current managed URP already owns:
|
||||
|
||||
1. renderer selection;
|
||||
2. main-scene builtin feature ownership;
|
||||
3. shadow enable / planning defaults.
|
||||
|
||||
But the actual `ShadowCaster` standalone stage is still installed in native host code through a hardcoded `BuiltinShadowCasterPass`.
|
||||
|
||||
That means shadow stage ownership is still not aligned with the SRP/URP boundary.
|
||||
|
||||
## Scope
|
||||
|
||||
Included:
|
||||
|
||||
1. add a native registry/factory for camera-frame standalone pass assets;
|
||||
2. let managed `ScriptableRenderPipelineAsset` expose standalone pass asset keys by stage;
|
||||
3. let `RendererBackedRenderPipelineAsset` route that decision through selected renderer data;
|
||||
4. make `UniversalRendererData` explicitly declare the builtin shadow-caster pass asset key;
|
||||
5. let `ScriptableRenderPipelineHost` resolve contextual standalone passes from managed asset runtime instead of hardcoding shadow caster;
|
||||
6. rebuild `XCEditor` and run old editor smoke.
|
||||
|
||||
Not included:
|
||||
|
||||
1. managed shadow raster pass recording;
|
||||
2. cascades;
|
||||
3. shadow atlas packing;
|
||||
4. editor UI for standalone pass selection.
|
||||
|
||||
## Acceptance
|
||||
|
||||
This stage is complete when:
|
||||
|
||||
1. managed URP explicitly owns the `ShadowCaster` standalone pass selection;
|
||||
2. native host no longer hardcodes shadow caster for managed pipelines;
|
||||
3. builtin fallback pipeline still keeps depth-only / object-id / shadow-caster working;
|
||||
4. `XCEditor` build and old editor smoke both pass.
|
||||
@@ -96,6 +96,17 @@ public:
|
||||
(void)rendererIndex;
|
||||
return GetPipelineRendererAsset();
|
||||
}
|
||||
virtual std::string GetCameraFrameStandalonePassAssetKey(
|
||||
CameraFrameStage stage) const {
|
||||
(void)stage;
|
||||
return {};
|
||||
}
|
||||
virtual std::string GetCameraFrameStandalonePassAssetKey(
|
||||
CameraFrameStage stage,
|
||||
int32_t rendererIndex) const {
|
||||
(void)rendererIndex;
|
||||
return GetCameraFrameStandalonePassAssetKey(stage);
|
||||
}
|
||||
|
||||
virtual bool TryGetDefaultFinalColorSettings(FinalColorSettings&) const {
|
||||
return false;
|
||||
|
||||
@@ -3,12 +3,17 @@
|
||||
#include <XCEngine/Rendering/RenderPipeline.h>
|
||||
#include <XCEngine/Rendering/RenderPipelineAsset.h>
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
namespace Pipelines {
|
||||
|
||||
class ManagedRenderPipelineAssetRuntime;
|
||||
|
||||
class ScriptableRenderPipelineHost final : public RenderPipeline {
|
||||
public:
|
||||
ScriptableRenderPipelineHost();
|
||||
@@ -16,6 +21,10 @@ public:
|
||||
std::unique_ptr<RenderPipelineRenderer> pipelineRenderer);
|
||||
explicit ScriptableRenderPipelineHost(
|
||||
std::shared_ptr<const RenderPipelineAsset> pipelineRendererAsset);
|
||||
ScriptableRenderPipelineHost(
|
||||
std::shared_ptr<const RenderPipelineAsset> pipelineRendererAsset,
|
||||
std::shared_ptr<const ManagedRenderPipelineAssetRuntime>
|
||||
managedAssetRuntime);
|
||||
~ScriptableRenderPipelineHost() override;
|
||||
|
||||
using RenderPipeline::Render;
|
||||
@@ -24,6 +33,9 @@ public:
|
||||
void SetPipelineRenderer(std::unique_ptr<RenderPipelineRenderer> pipelineRenderer);
|
||||
void SetPipelineRendererAsset(
|
||||
std::shared_ptr<const RenderPipelineAsset> pipelineRendererAsset);
|
||||
void SetManagedAssetRuntime(
|
||||
std::shared_ptr<const ManagedRenderPipelineAssetRuntime>
|
||||
managedAssetRuntime);
|
||||
RenderPipelineStageRecorder* GetStageRecorder() const {
|
||||
return m_stageRecorder.get();
|
||||
}
|
||||
@@ -46,19 +58,38 @@ public:
|
||||
const RenderContext& context,
|
||||
const RenderSurface& surface,
|
||||
const RenderSceneData& sceneData) override;
|
||||
RenderPass* GetCameraFrameStandalonePass(
|
||||
CameraFrameStage stage,
|
||||
int32_t rendererIndex) const override;
|
||||
|
||||
private:
|
||||
struct ContextualCameraFrameStandalonePassEntry {
|
||||
std::string assetKey = {};
|
||||
std::unique_ptr<RenderPass> pass = nullptr;
|
||||
};
|
||||
|
||||
bool EnsureInitialized(const RenderContext& context);
|
||||
void BindStageRecorderPipelineRenderer();
|
||||
void ShutdownContextualCameraFrameStandalonePasses();
|
||||
void ShutdownInitializedComponents();
|
||||
void ResetInitializationState();
|
||||
void ClearInitializationContextIfNoComponentsAreInitialized();
|
||||
void ResetStageRecorder(std::unique_ptr<RenderPipelineStageRecorder> stageRecorder);
|
||||
void ResetPipelineRenderer(std::unique_ptr<RenderPipelineRenderer> pipelineRenderer);
|
||||
RenderPass* ResolveContextualCameraFrameStandalonePass(
|
||||
CameraFrameStage stage,
|
||||
int32_t rendererIndex,
|
||||
const std::string& assetKey);
|
||||
|
||||
std::unique_ptr<RenderPipelineStageRecorder> m_stageRecorder;
|
||||
std::shared_ptr<const RenderPipelineAsset> m_pipelineRendererAsset;
|
||||
std::shared_ptr<const ManagedRenderPipelineAssetRuntime>
|
||||
m_managedAssetRuntime;
|
||||
std::unique_ptr<RenderPipelineRenderer> m_pipelineRenderer;
|
||||
std::array<
|
||||
std::unordered_map<int32_t, ContextualCameraFrameStandalonePassEntry>,
|
||||
kCameraFrameStageCount>
|
||||
m_contextualCameraFrameStandalonePasses = {};
|
||||
RHI::RHIDevice* m_initializedDevice = nullptr;
|
||||
RHI::RHIType m_initializedBackendType = RHI::RHIType::D3D12;
|
||||
bool m_pipelineRendererInitialized = false;
|
||||
@@ -70,6 +101,10 @@ public:
|
||||
ScriptableRenderPipelineHostAsset();
|
||||
explicit ScriptableRenderPipelineHostAsset(
|
||||
std::shared_ptr<const RenderPipelineAsset> pipelineRendererAsset);
|
||||
ScriptableRenderPipelineHostAsset(
|
||||
std::shared_ptr<const RenderPipelineAsset> pipelineRendererAsset,
|
||||
std::shared_ptr<const ManagedRenderPipelineAssetRuntime>
|
||||
managedAssetRuntime);
|
||||
|
||||
std::unique_ptr<RenderPipeline> CreatePipeline() const override;
|
||||
void ConfigurePipeline(RenderPipeline& pipeline) const override;
|
||||
@@ -77,6 +112,8 @@ public:
|
||||
|
||||
private:
|
||||
std::shared_ptr<const RenderPipelineAsset> m_pipelineRendererAsset;
|
||||
std::shared_ptr<const ManagedRenderPipelineAssetRuntime>
|
||||
m_managedAssetRuntime;
|
||||
};
|
||||
|
||||
} // namespace Pipelines
|
||||
|
||||
@@ -149,6 +149,13 @@ public:
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
virtual RenderPass* GetCameraFrameStandalonePass(
|
||||
CameraFrameStage stage,
|
||||
int32_t rendererIndex) const {
|
||||
(void)rendererIndex;
|
||||
return GetCameraFrameStandalonePass(stage);
|
||||
}
|
||||
|
||||
protected:
|
||||
void ShutdownCameraFrameStandalonePasses() {
|
||||
for (std::unique_ptr<RenderPass>& pass : m_cameraFrameStandalonePasses) {
|
||||
|
||||
@@ -31,7 +31,8 @@ bool TryRecordCameraFrameStageStandaloneRenderGraphPass(
|
||||
RenderPass* const standaloneStagePass =
|
||||
ResolveCameraFrameStandaloneStagePass(
|
||||
stageState.stage,
|
||||
builder.executionState);
|
||||
builder.executionState,
|
||||
context.plan.request.rendererIndex);
|
||||
if (standaloneStagePass == nullptr ||
|
||||
!standaloneStagePass->SupportsRenderGraph()) {
|
||||
handled = false;
|
||||
|
||||
@@ -217,9 +217,12 @@ RenderSceneData BuildCameraFrameStandaloneStageSceneData(
|
||||
|
||||
RenderPass* ResolveCameraFrameStandaloneStagePass(
|
||||
CameraFrameStage stage,
|
||||
CameraFrameExecutionState& executionState) {
|
||||
CameraFrameExecutionState& executionState,
|
||||
int32_t rendererIndex) {
|
||||
return executionState.pipeline != nullptr
|
||||
? executionState.pipeline->GetCameraFrameStandalonePass(stage)
|
||||
? executionState.pipeline->GetCameraFrameStandalonePass(
|
||||
stage,
|
||||
rendererIndex)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
@@ -256,7 +259,8 @@ bool ExecuteCameraFrameRecordedStagePass(
|
||||
RenderPass* const standaloneStagePass =
|
||||
ResolveCameraFrameStandaloneStagePass(
|
||||
stage,
|
||||
executionState);
|
||||
executionState,
|
||||
context.plan.request.rendererIndex);
|
||||
return ExecuteCameraFrameStandaloneStagePass(
|
||||
standaloneStagePass,
|
||||
context.plan.request.context,
|
||||
|
||||
@@ -47,7 +47,8 @@ RenderSceneData BuildCameraFrameStandaloneStageSceneData(
|
||||
|
||||
RenderPass* ResolveCameraFrameStandaloneStagePass(
|
||||
CameraFrameStage stage,
|
||||
CameraFrameExecutionState& executionState);
|
||||
CameraFrameExecutionState& executionState,
|
||||
int32_t rendererIndex);
|
||||
|
||||
bool InitializeCameraFrameStandaloneStagePass(
|
||||
RenderPass* pass,
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
#include "Rendering/Pipelines/BuiltinForwardPipeline.h"
|
||||
#include "Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h"
|
||||
#include "Rendering/Pipelines/ScriptableRenderPipelineHost.h"
|
||||
#include "Rendering/Passes/BuiltinDepthOnlyPass.h"
|
||||
#include "Rendering/Passes/BuiltinObjectIdPass.h"
|
||||
#include "Rendering/Passes/BuiltinShadowCasterPass.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
@@ -22,24 +25,53 @@ CreateBuiltinForwardPipelineRendererAsset() {
|
||||
return s_builtinForwardPipelineAsset;
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPass> CreateBuiltinDepthOnlyStandalonePass() {
|
||||
return std::make_unique<Passes::BuiltinDepthOnlyPass>();
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPass> CreateBuiltinObjectIdStandalonePass() {
|
||||
return std::make_unique<Passes::BuiltinObjectIdPass>();
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPass> CreateBuiltinShadowCasterStandalonePass() {
|
||||
return std::make_unique<Passes::BuiltinShadowCasterPass>();
|
||||
}
|
||||
|
||||
using PipelineRendererAssetRegistry =
|
||||
std::unordered_map<std::string, PipelineRendererAssetFactory>;
|
||||
using CameraFrameStandalonePassRegistry =
|
||||
std::unordered_map<std::string, CameraFrameStandalonePassFactory>;
|
||||
|
||||
PipelineRendererAssetRegistry& GetPipelineRendererAssetRegistry() {
|
||||
static PipelineRendererAssetRegistry registry = {};
|
||||
return registry;
|
||||
}
|
||||
|
||||
CameraFrameStandalonePassRegistry& GetCameraFrameStandalonePassRegistry() {
|
||||
static CameraFrameStandalonePassRegistry registry = {};
|
||||
return registry;
|
||||
}
|
||||
|
||||
std::unordered_set<std::string>& GetBuiltinPipelineRendererAssetKeys() {
|
||||
static std::unordered_set<std::string> builtinKeys = {};
|
||||
return builtinKeys;
|
||||
}
|
||||
|
||||
std::unordered_set<std::string>& GetBuiltinCameraFrameStandalonePassKeys() {
|
||||
static std::unordered_set<std::string> builtinKeys = {};
|
||||
return builtinKeys;
|
||||
}
|
||||
|
||||
std::mutex& GetPipelineRendererAssetRegistryMutex() {
|
||||
static std::mutex mutex;
|
||||
return mutex;
|
||||
}
|
||||
|
||||
std::mutex& GetCameraFrameStandalonePassRegistryMutex() {
|
||||
static std::mutex mutex;
|
||||
return mutex;
|
||||
}
|
||||
|
||||
void EnsureBuiltinPipelineRendererAssetRegistryInitialized() {
|
||||
static const bool initialized = []() {
|
||||
PipelineRendererAssetRegistry& registry =
|
||||
@@ -53,6 +85,29 @@ void EnsureBuiltinPipelineRendererAssetRegistryInitialized() {
|
||||
(void)initialized;
|
||||
}
|
||||
|
||||
void EnsureBuiltinCameraFrameStandalonePassRegistryInitialized() {
|
||||
static const bool initialized = []() {
|
||||
CameraFrameStandalonePassRegistry& registry =
|
||||
GetCameraFrameStandalonePassRegistry();
|
||||
registry.emplace(
|
||||
"BuiltinDepthOnly",
|
||||
&CreateBuiltinDepthOnlyStandalonePass);
|
||||
registry.emplace(
|
||||
"BuiltinObjectId",
|
||||
&CreateBuiltinObjectIdStandalonePass);
|
||||
registry.emplace(
|
||||
"BuiltinShadowCaster",
|
||||
&CreateBuiltinShadowCasterStandalonePass);
|
||||
std::unordered_set<std::string>& builtinKeys =
|
||||
GetBuiltinCameraFrameStandalonePassKeys();
|
||||
builtinKeys.insert("BuiltinDepthOnly");
|
||||
builtinKeys.insert("BuiltinObjectId");
|
||||
builtinKeys.insert("BuiltinShadowCaster");
|
||||
return true;
|
||||
}();
|
||||
(void)initialized;
|
||||
}
|
||||
|
||||
std::unique_ptr<NativeSceneRenderer> TryCreateNativeSceneRendererFromAsset(
|
||||
const std::shared_ptr<const RenderPipelineAsset>& asset) {
|
||||
if (asset == nullptr) {
|
||||
@@ -144,6 +199,67 @@ std::shared_ptr<const RenderPipelineAsset> CreatePipelineRendererAssetByKey(
|
||||
return it->second();
|
||||
}
|
||||
|
||||
bool RegisterCameraFrameStandalonePassFactory(
|
||||
const std::string& key,
|
||||
CameraFrameStandalonePassFactory factory) {
|
||||
if (key.empty() || !factory) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureBuiltinCameraFrameStandalonePassRegistryInitialized();
|
||||
|
||||
std::lock_guard<std::mutex> lock(
|
||||
GetCameraFrameStandalonePassRegistryMutex());
|
||||
CameraFrameStandalonePassRegistry& registry =
|
||||
GetCameraFrameStandalonePassRegistry();
|
||||
if (registry.find(key) != registry.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
registry.emplace(key, std::move(factory));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UnregisterCameraFrameStandalonePassFactory(
|
||||
const std::string& key) {
|
||||
if (key.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureBuiltinCameraFrameStandalonePassRegistryInitialized();
|
||||
|
||||
std::lock_guard<std::mutex> lock(
|
||||
GetCameraFrameStandalonePassRegistryMutex());
|
||||
if (GetBuiltinCameraFrameStandalonePassKeys().find(key) !=
|
||||
GetBuiltinCameraFrameStandalonePassKeys().end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CameraFrameStandalonePassRegistry& registry =
|
||||
GetCameraFrameStandalonePassRegistry();
|
||||
return registry.erase(key) != 0u;
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPass> CreateCameraFrameStandalonePassByKey(
|
||||
const std::string& key) {
|
||||
if (key.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EnsureBuiltinCameraFrameStandalonePassRegistryInitialized();
|
||||
|
||||
std::lock_guard<std::mutex> lock(
|
||||
GetCameraFrameStandalonePassRegistryMutex());
|
||||
const CameraFrameStandalonePassRegistry& registry =
|
||||
GetCameraFrameStandalonePassRegistry();
|
||||
const auto it = registry.find(key);
|
||||
if (it == registry.end() || !it->second) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return it->second();
|
||||
}
|
||||
|
||||
std::shared_ptr<const RenderPipelineAsset> ResolveRenderPipelineAssetOrDefault(
|
||||
std::shared_ptr<const RenderPipelineAsset> preferredAsset) {
|
||||
if (preferredAsset != nullptr) {
|
||||
|
||||
@@ -10,11 +10,14 @@ namespace Rendering {
|
||||
class NativeSceneRenderer;
|
||||
class RenderPipeline;
|
||||
class RenderPipelineAsset;
|
||||
class RenderPass;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
using PipelineRendererAssetFactory =
|
||||
std::function<std::shared_ptr<const RenderPipelineAsset>()>;
|
||||
using CameraFrameStandalonePassFactory =
|
||||
std::function<std::unique_ptr<RenderPass>()>;
|
||||
|
||||
std::shared_ptr<const RenderPipelineAsset> CreateConfiguredRenderPipelineAsset();
|
||||
std::shared_ptr<const RenderPipelineAsset> CreateFallbackRenderPipelineAsset();
|
||||
@@ -24,6 +27,13 @@ bool RegisterPipelineRendererAssetFactory(
|
||||
bool UnregisterPipelineRendererAssetFactory(const std::string& key);
|
||||
std::shared_ptr<const RenderPipelineAsset> CreatePipelineRendererAssetByKey(
|
||||
const std::string& key);
|
||||
bool RegisterCameraFrameStandalonePassFactory(
|
||||
const std::string& key,
|
||||
CameraFrameStandalonePassFactory factory);
|
||||
bool UnregisterCameraFrameStandalonePassFactory(
|
||||
const std::string& key);
|
||||
std::unique_ptr<RenderPass> CreateCameraFrameStandalonePassByKey(
|
||||
const std::string& key);
|
||||
|
||||
std::shared_ptr<const RenderPipelineAsset> ResolveRenderPipelineAssetOrDefault(
|
||||
std::shared_ptr<const RenderPipelineAsset> preferredAsset);
|
||||
|
||||
@@ -50,13 +50,19 @@ ManagedScriptableRenderPipelineAsset::ResolvePipelineRendererAsset() const {
|
||||
|
||||
ScriptableRenderPipelineHostAsset
|
||||
ManagedScriptableRenderPipelineAsset::CreateExecutionHostAsset() const {
|
||||
const std::shared_ptr<const ManagedRenderPipelineAssetRuntime> runtime =
|
||||
ResolveManagedAssetRuntime();
|
||||
if (const std::shared_ptr<const RenderPipelineAsset> pipelineRendererAsset =
|
||||
ResolvePipelineRendererAsset();
|
||||
pipelineRendererAsset != nullptr) {
|
||||
return ScriptableRenderPipelineHostAsset(pipelineRendererAsset);
|
||||
return ScriptableRenderPipelineHostAsset(
|
||||
pipelineRendererAsset,
|
||||
runtime);
|
||||
}
|
||||
|
||||
return ScriptableRenderPipelineHostAsset();
|
||||
return ScriptableRenderPipelineHostAsset(
|
||||
nullptr,
|
||||
runtime);
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPipeline> ManagedScriptableRenderPipelineAsset::CreatePipeline() const {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#include "Rendering/Pipelines/ScriptableRenderPipelineHost.h"
|
||||
|
||||
#include "Debug/Logger.h"
|
||||
#include "Rendering/Internal/RenderPipelineFactory.h"
|
||||
#include "Rendering/Pipelines/BuiltinForwardPipeline.h"
|
||||
#include "Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h"
|
||||
#include "Rendering/Passes/BuiltinDepthOnlyPass.h"
|
||||
#include "Rendering/Passes/BuiltinObjectIdPass.h"
|
||||
#include "Rendering/Passes/BuiltinShadowCasterPass.h"
|
||||
@@ -45,10 +48,20 @@ ScriptableRenderPipelineHost::ScriptableRenderPipelineHost(
|
||||
|
||||
ScriptableRenderPipelineHost::ScriptableRenderPipelineHost(
|
||||
std::shared_ptr<const RenderPipelineAsset> pipelineRendererAsset)
|
||||
: ScriptableRenderPipelineHost(
|
||||
std::move(pipelineRendererAsset),
|
||||
nullptr) {
|
||||
}
|
||||
|
||||
ScriptableRenderPipelineHost::ScriptableRenderPipelineHost(
|
||||
std::shared_ptr<const RenderPipelineAsset> pipelineRendererAsset,
|
||||
std::shared_ptr<const ManagedRenderPipelineAssetRuntime>
|
||||
managedAssetRuntime)
|
||||
: m_pipelineRendererAsset(
|
||||
pipelineRendererAsset != nullptr
|
||||
? std::move(pipelineRendererAsset)
|
||||
: CreateDefaultPipelineRendererAsset()) {
|
||||
: CreateDefaultPipelineRendererAsset())
|
||||
, m_managedAssetRuntime(std::move(managedAssetRuntime)) {
|
||||
ResetPipelineRenderer(
|
||||
CreatePipelineRendererFromAsset(m_pipelineRendererAsset));
|
||||
}
|
||||
@@ -78,6 +91,13 @@ void ScriptableRenderPipelineHost::SetPipelineRendererAsset(
|
||||
CreatePipelineRendererFromAsset(m_pipelineRendererAsset));
|
||||
}
|
||||
|
||||
void ScriptableRenderPipelineHost::SetManagedAssetRuntime(
|
||||
std::shared_ptr<const ManagedRenderPipelineAssetRuntime>
|
||||
managedAssetRuntime) {
|
||||
m_managedAssetRuntime = std::move(managedAssetRuntime);
|
||||
ShutdownContextualCameraFrameStandalonePasses();
|
||||
}
|
||||
|
||||
bool ScriptableRenderPipelineHost::Initialize(const RenderContext& context) {
|
||||
return EnsureInitialized(context);
|
||||
}
|
||||
@@ -89,6 +109,7 @@ void ScriptableRenderPipelineHost::Shutdown() {
|
||||
if (m_pipelineRenderer != nullptr) {
|
||||
m_pipelineRenderer->Shutdown();
|
||||
}
|
||||
ShutdownContextualCameraFrameStandalonePasses();
|
||||
ShutdownCameraFrameStandalonePasses();
|
||||
ResetInitializationState();
|
||||
}
|
||||
@@ -150,6 +171,32 @@ bool ScriptableRenderPipelineHost::Render(
|
||||
m_pipelineRenderer->Render(context, surface, sceneData);
|
||||
}
|
||||
|
||||
RenderPass* ScriptableRenderPipelineHost::GetCameraFrameStandalonePass(
|
||||
CameraFrameStage stage,
|
||||
int32_t rendererIndex) const {
|
||||
RenderPass* const defaultPass =
|
||||
RenderPipeline::GetCameraFrameStandalonePass(stage);
|
||||
if (m_managedAssetRuntime == nullptr ||
|
||||
!SupportsCameraFrameStandalonePass(stage)) {
|
||||
return defaultPass;
|
||||
}
|
||||
|
||||
const std::string assetKey =
|
||||
m_managedAssetRuntime
|
||||
->GetCameraFrameStandalonePassAssetKey(
|
||||
stage,
|
||||
rendererIndex);
|
||||
if (assetKey.empty()) {
|
||||
return defaultPass;
|
||||
}
|
||||
|
||||
return const_cast<ScriptableRenderPipelineHost*>(this)
|
||||
->ResolveContextualCameraFrameStandalonePass(
|
||||
stage,
|
||||
rendererIndex,
|
||||
assetKey);
|
||||
}
|
||||
|
||||
bool ScriptableRenderPipelineHost::EnsureInitialized(const RenderContext& context) {
|
||||
if (!context.IsValid() || m_pipelineRenderer == nullptr) {
|
||||
return false;
|
||||
@@ -199,6 +246,18 @@ void ScriptableRenderPipelineHost::BindStageRecorderPipelineRenderer() {
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptableRenderPipelineHost::ShutdownContextualCameraFrameStandalonePasses() {
|
||||
for (auto& stageEntries : m_contextualCameraFrameStandalonePasses) {
|
||||
for (auto& entryIt : stageEntries) {
|
||||
if (entryIt.second.pass != nullptr) {
|
||||
entryIt.second.pass->Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
stageEntries.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptableRenderPipelineHost::ShutdownInitializedComponents() {
|
||||
if (m_stageRecorderInitialized &&
|
||||
m_stageRecorder != nullptr) {
|
||||
@@ -256,26 +315,74 @@ void ScriptableRenderPipelineHost::ResetPipelineRenderer(
|
||||
}
|
||||
|
||||
m_pipelineRendererInitialized = false;
|
||||
ShutdownContextualCameraFrameStandalonePasses();
|
||||
BindStageRecorderPipelineRenderer();
|
||||
ClearInitializationContextIfNoComponentsAreInitialized();
|
||||
}
|
||||
|
||||
RenderPass*
|
||||
ScriptableRenderPipelineHost::ResolveContextualCameraFrameStandalonePass(
|
||||
CameraFrameStage stage,
|
||||
int32_t rendererIndex,
|
||||
const std::string& assetKey) {
|
||||
auto& stageEntries =
|
||||
m_contextualCameraFrameStandalonePasses[
|
||||
GetCameraFrameStageIndex(stage)];
|
||||
ContextualCameraFrameStandalonePassEntry& entry =
|
||||
stageEntries[rendererIndex];
|
||||
if (entry.assetKey == assetKey) {
|
||||
return entry.pass.get();
|
||||
}
|
||||
|
||||
if (entry.pass != nullptr) {
|
||||
entry.pass->Shutdown();
|
||||
}
|
||||
|
||||
entry = {};
|
||||
entry.assetKey = assetKey;
|
||||
entry.pass =
|
||||
Rendering::Internal::CreateCameraFrameStandalonePassByKey(
|
||||
assetKey);
|
||||
if (entry.pass == nullptr) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
Containers::String(
|
||||
"ScriptableRenderPipelineHost failed to resolve standalone pass asset key: ") +
|
||||
assetKey.c_str());
|
||||
}
|
||||
|
||||
return entry.pass.get();
|
||||
}
|
||||
|
||||
ScriptableRenderPipelineHostAsset::ScriptableRenderPipelineHostAsset()
|
||||
: ScriptableRenderPipelineHostAsset(CreateDefaultPipelineRendererAsset()) {
|
||||
: ScriptableRenderPipelineHostAsset(
|
||||
CreateDefaultPipelineRendererAsset(),
|
||||
nullptr) {
|
||||
}
|
||||
|
||||
ScriptableRenderPipelineHostAsset::ScriptableRenderPipelineHostAsset(
|
||||
std::shared_ptr<const RenderPipelineAsset> pipelineRendererAsset)
|
||||
: ScriptableRenderPipelineHostAsset(
|
||||
std::move(pipelineRendererAsset),
|
||||
nullptr) {
|
||||
}
|
||||
|
||||
ScriptableRenderPipelineHostAsset::ScriptableRenderPipelineHostAsset(
|
||||
std::shared_ptr<const RenderPipelineAsset> pipelineRendererAsset,
|
||||
std::shared_ptr<const ManagedRenderPipelineAssetRuntime>
|
||||
managedAssetRuntime)
|
||||
: m_pipelineRendererAsset(
|
||||
pipelineRendererAsset != nullptr
|
||||
? std::move(pipelineRendererAsset)
|
||||
: CreateDefaultPipelineRendererAsset()) {
|
||||
: CreateDefaultPipelineRendererAsset())
|
||||
, m_managedAssetRuntime(std::move(managedAssetRuntime)) {
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPipeline> ScriptableRenderPipelineHostAsset::CreatePipeline() const {
|
||||
std::unique_ptr<RenderPipeline> pipeline =
|
||||
std::make_unique<ScriptableRenderPipelineHost>(
|
||||
m_pipelineRendererAsset);
|
||||
m_pipelineRendererAsset,
|
||||
m_managedAssetRuntime);
|
||||
if (pipeline != nullptr) {
|
||||
ConfigurePipeline(*pipeline);
|
||||
}
|
||||
@@ -291,9 +398,11 @@ void ScriptableRenderPipelineHostAsset::ConfigurePipeline(
|
||||
pipeline.SetCameraFrameStandalonePass(
|
||||
CameraFrameStage::DepthOnly,
|
||||
std::make_unique<Passes::BuiltinDepthOnlyPass>());
|
||||
pipeline.SetCameraFrameStandalonePass(
|
||||
CameraFrameStage::ShadowCaster,
|
||||
std::make_unique<Passes::BuiltinShadowCasterPass>());
|
||||
if (m_managedAssetRuntime == nullptr) {
|
||||
pipeline.SetCameraFrameStandalonePass(
|
||||
CameraFrameStage::ShadowCaster,
|
||||
std::make_unique<Passes::BuiltinShadowCasterPass>());
|
||||
}
|
||||
}
|
||||
|
||||
FinalColorSettings ScriptableRenderPipelineHostAsset::GetDefaultFinalColorSettings() const {
|
||||
|
||||
@@ -1319,6 +1319,11 @@ public:
|
||||
GetPipelineRendererAsset() const override;
|
||||
std::shared_ptr<const Rendering::RenderPipelineAsset>
|
||||
GetPipelineRendererAsset(int32_t rendererIndex) const override;
|
||||
std::string GetCameraFrameStandalonePassAssetKey(
|
||||
Rendering::CameraFrameStage stage) const override;
|
||||
std::string GetCameraFrameStandalonePassAssetKey(
|
||||
Rendering::CameraFrameStage stage,
|
||||
int32_t rendererIndex) const override;
|
||||
|
||||
MonoScriptRuntime* GetRuntime() const {
|
||||
return m_runtime;
|
||||
@@ -1353,6 +1358,11 @@ private:
|
||||
MonoObject* assetObject) const;
|
||||
MonoMethod* ResolveGetPipelineRendererAssetKeyContextualMethod(
|
||||
MonoObject* assetObject) const;
|
||||
MonoMethod* ResolveGetCameraFrameStandalonePassAssetKeyMethod(
|
||||
MonoObject* assetObject) const;
|
||||
MonoMethod*
|
||||
ResolveGetCameraFrameStandalonePassAssetKeyContextualMethod(
|
||||
MonoObject* assetObject) const;
|
||||
MonoMethod* ResolveReleaseRuntimeResourcesMethod(
|
||||
MonoObject* assetObject) const;
|
||||
|
||||
@@ -1369,6 +1379,10 @@ private:
|
||||
mutable MonoMethod* m_getPipelineRendererAssetKeyMethod = nullptr;
|
||||
mutable MonoMethod* m_getPipelineRendererAssetKeyContextualMethod =
|
||||
nullptr;
|
||||
mutable MonoMethod* m_getCameraFrameStandalonePassAssetKeyMethod =
|
||||
nullptr;
|
||||
mutable MonoMethod*
|
||||
m_getCameraFrameStandalonePassAssetKeyContextualMethod = nullptr;
|
||||
mutable MonoMethod* m_releaseRuntimeResourcesMethod = nullptr;
|
||||
mutable bool m_ownsManagedAssetHandle = false;
|
||||
mutable bool m_assetCreationAttempted = false;
|
||||
@@ -2001,6 +2015,72 @@ MonoManagedRenderPipelineAssetRuntime::GetPipelineRendererAsset(
|
||||
return m_pipelineRendererAsset;
|
||||
}
|
||||
|
||||
std::string MonoManagedRenderPipelineAssetRuntime::
|
||||
GetCameraFrameStandalonePassAssetKey(
|
||||
Rendering::CameraFrameStage stage) const {
|
||||
return GetCameraFrameStandalonePassAssetKey(
|
||||
stage,
|
||||
-1);
|
||||
}
|
||||
|
||||
std::string MonoManagedRenderPipelineAssetRuntime::
|
||||
GetCameraFrameStandalonePassAssetKey(
|
||||
Rendering::CameraFrameStage stage,
|
||||
int32_t rendererIndex) const {
|
||||
if (!SyncManagedAssetRuntimeState()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
MonoObject* const assetObject = GetManagedAssetObject();
|
||||
if (assetObject == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
MonoMethod* const contextualMethod =
|
||||
ResolveGetCameraFrameStandalonePassAssetKeyContextualMethod(
|
||||
assetObject);
|
||||
if (contextualMethod != nullptr) {
|
||||
int32_t managedStage =
|
||||
static_cast<int32_t>(stage);
|
||||
void* args[2] = {
|
||||
&managedStage,
|
||||
&rendererIndex };
|
||||
MonoObject* managedKeyObject = nullptr;
|
||||
if (!m_runtime->InvokeManagedMethod(
|
||||
assetObject,
|
||||
contextualMethod,
|
||||
args,
|
||||
&managedKeyObject)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return MonoStringToUtf8(
|
||||
reinterpret_cast<MonoString*>(managedKeyObject));
|
||||
}
|
||||
|
||||
MonoMethod* const method =
|
||||
ResolveGetCameraFrameStandalonePassAssetKeyMethod(
|
||||
assetObject);
|
||||
if (method == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
int32_t managedStage =
|
||||
static_cast<int32_t>(stage);
|
||||
void* args[1] = { &managedStage };
|
||||
MonoObject* managedKeyObject = nullptr;
|
||||
if (!m_runtime->InvokeManagedMethod(
|
||||
assetObject,
|
||||
method,
|
||||
args,
|
||||
&managedKeyObject)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return MonoStringToUtf8(
|
||||
reinterpret_cast<MonoString*>(managedKeyObject));
|
||||
}
|
||||
|
||||
bool MonoManagedRenderPipelineAssetRuntime::AcquireManagedPipelineHandle(
|
||||
uint32_t& outPipelineHandle) const {
|
||||
if (!SyncManagedAssetRuntimeState()) {
|
||||
@@ -2208,6 +2288,8 @@ void MonoManagedRenderPipelineAssetRuntime::ReleaseManagedAsset() const {
|
||||
m_getRuntimeResourceVersionMethod = nullptr;
|
||||
m_getPipelineRendererAssetKeyMethod = nullptr;
|
||||
m_getPipelineRendererAssetKeyContextualMethod = nullptr;
|
||||
m_getCameraFrameStandalonePassAssetKeyMethod = nullptr;
|
||||
m_getCameraFrameStandalonePassAssetKeyContextualMethod = nullptr;
|
||||
m_pipelineRendererAsset.reset();
|
||||
m_pipelineRendererAssetResolved = false;
|
||||
m_contextualPipelineRendererAssets.clear();
|
||||
@@ -2356,6 +2438,37 @@ MonoManagedRenderPipelineAssetRuntime::ResolveGetPipelineRendererAssetKeyContext
|
||||
return m_getPipelineRendererAssetKeyContextualMethod;
|
||||
}
|
||||
|
||||
MonoMethod*
|
||||
MonoManagedRenderPipelineAssetRuntime::
|
||||
ResolveGetCameraFrameStandalonePassAssetKeyMethod(
|
||||
MonoObject* assetObject) const {
|
||||
if (m_getCameraFrameStandalonePassAssetKeyMethod == nullptr) {
|
||||
m_getCameraFrameStandalonePassAssetKeyMethod =
|
||||
m_runtime->ResolveManagedMethod(
|
||||
assetObject,
|
||||
"GetCameraFrameStandalonePassAssetKey",
|
||||
1);
|
||||
}
|
||||
|
||||
return m_getCameraFrameStandalonePassAssetKeyMethod;
|
||||
}
|
||||
|
||||
MonoMethod*
|
||||
MonoManagedRenderPipelineAssetRuntime::
|
||||
ResolveGetCameraFrameStandalonePassAssetKeyContextualMethod(
|
||||
MonoObject* assetObject) const {
|
||||
if (m_getCameraFrameStandalonePassAssetKeyContextualMethod ==
|
||||
nullptr) {
|
||||
m_getCameraFrameStandalonePassAssetKeyContextualMethod =
|
||||
m_runtime->ResolveManagedMethod(
|
||||
assetObject,
|
||||
"GetCameraFrameStandalonePassAssetKeyContextual",
|
||||
2);
|
||||
}
|
||||
|
||||
return m_getCameraFrameStandalonePassAssetKeyContextualMethod;
|
||||
}
|
||||
|
||||
MonoMethod*
|
||||
MonoManagedRenderPipelineAssetRuntime::ResolveReleaseRuntimeResourcesMethod(
|
||||
MonoObject* assetObject) const {
|
||||
|
||||
@@ -78,6 +78,32 @@ namespace XCEngine.Rendering.Universal
|
||||
: string.Empty;
|
||||
}
|
||||
|
||||
protected override string
|
||||
GetCameraFrameStandalonePassAssetKeyContextual(
|
||||
CameraFrameStage stage,
|
||||
int rendererIndex)
|
||||
{
|
||||
ScriptableRendererData resolvedRendererData =
|
||||
GetRendererData(rendererIndex);
|
||||
if (resolvedRendererData != null)
|
||||
{
|
||||
string standalonePassAssetKey =
|
||||
resolvedRendererData
|
||||
.GetCameraFrameStandalonePassAssetKeyInstance(
|
||||
stage);
|
||||
if (!string.IsNullOrEmpty(
|
||||
standalonePassAssetKey))
|
||||
{
|
||||
return standalonePassAssetKey;
|
||||
}
|
||||
}
|
||||
|
||||
return base
|
||||
.GetCameraFrameStandalonePassAssetKeyContextual(
|
||||
stage,
|
||||
rendererIndex);
|
||||
}
|
||||
|
||||
protected override void ReleaseRuntimeResources()
|
||||
{
|
||||
ReleaseRendererDataRuntimeResources();
|
||||
|
||||
@@ -61,6 +61,13 @@ namespace XCEngine.Rendering.Universal
|
||||
return GetPipelineRendererAssetKey();
|
||||
}
|
||||
|
||||
internal string GetCameraFrameStandalonePassAssetKeyInstance(
|
||||
CameraFrameStage stage)
|
||||
{
|
||||
return GetCameraFrameStandalonePassAssetKey(
|
||||
stage);
|
||||
}
|
||||
|
||||
internal int GetRuntimeStateVersionInstance()
|
||||
{
|
||||
return m_runtimeStateVersion;
|
||||
@@ -153,6 +160,12 @@ namespace XCEngine.Rendering.Universal
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
protected virtual string GetCameraFrameStandalonePassAssetKey(
|
||||
CameraFrameStage stage)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
protected virtual ScriptableRendererFeature[] CreateRendererFeatures()
|
||||
{
|
||||
return Array.Empty<ScriptableRendererFeature>();
|
||||
|
||||
@@ -32,6 +32,20 @@ namespace XCEngine.Rendering.Universal
|
||||
return "BuiltinForward";
|
||||
}
|
||||
|
||||
protected override string GetCameraFrameStandalonePassAssetKey(
|
||||
CameraFrameStage stage)
|
||||
{
|
||||
switch (stage)
|
||||
{
|
||||
case CameraFrameStage.ShadowCaster:
|
||||
return "BuiltinShadowCaster";
|
||||
default:
|
||||
return base
|
||||
.GetCameraFrameStandalonePassAssetKey(
|
||||
stage);
|
||||
}
|
||||
}
|
||||
|
||||
internal UniversalMainSceneData GetMainSceneInstance()
|
||||
{
|
||||
if (mainScene == null)
|
||||
|
||||
@@ -58,6 +58,21 @@ namespace XCEngine.Rendering
|
||||
return GetPipelineRendererAssetKey();
|
||||
}
|
||||
|
||||
protected virtual string GetCameraFrameStandalonePassAssetKey(
|
||||
CameraFrameStage stage)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
protected virtual string
|
||||
GetCameraFrameStandalonePassAssetKeyContextual(
|
||||
CameraFrameStage stage,
|
||||
int rendererIndex)
|
||||
{
|
||||
return GetCameraFrameStandalonePassAssetKey(
|
||||
stage);
|
||||
}
|
||||
|
||||
protected virtual void ReleaseRuntimeResources()
|
||||
{
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user