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:
2026-04-21 02:38:56 +08:00
parent bfc4b90ce6
commit e2b2df4c8f
16 changed files with 544 additions and 14 deletions

View File

@@ -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.

View File

@@ -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;

View File

@@ -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

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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,

View File

@@ -47,7 +47,8 @@ RenderSceneData BuildCameraFrameStandaloneStageSceneData(
RenderPass* ResolveCameraFrameStandaloneStagePass(
CameraFrameStage stage,
CameraFrameExecutionState& executionState);
CameraFrameExecutionState& executionState,
int32_t rendererIndex);
bool InitializeCameraFrameStandaloneStagePass(
RenderPass* pass,

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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();

View File

@@ -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>();

View File

@@ -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)

View File

@@ -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()
{
}