diff --git a/docs/used/SRP_URP_ManagedShadowExecutionPlan_完成归档_2026-04-21.md b/docs/used/SRP_URP_ManagedShadowExecutionPlan_完成归档_2026-04-21.md new file mode 100644 index 00000000..7816e1a0 --- /dev/null +++ b/docs/used/SRP_URP_ManagedShadowExecutionPlan_完成归档_2026-04-21.md @@ -0,0 +1,72 @@ +# SRP URP Managed Shadow Execution Plan + +Date: 2026-04-21 + +## Goal + +Continue moving URP renderer ownership upward by replacing the URP-specific native directional-shadow execution policy key with an explicit managed shadow execution callback. + +After the previous stages: + +- `UniversalRenderer` owns default shadow-stage planning +- `UniversalRenderer` owns default shadow-caster pass composition +- renderer slots now behave like authored renderer entries + +But the bridge between the planned shadow stage and the final runtime shadow state is still routed through the native `"BuiltinDirectionalShadow"` execution policy key. This stage removes that URP-specific indirection. + +## Current Problems + +1. `UniversalRendererData` still exposes directional-shadow execution through a native asset-key fallback instead of a managed renderer callback. +2. `ScriptableRenderPipelineHost` can only ask managed URP for a directional-shadow execution policy key, not for an explicit renderer-owned shadow execution decision. +3. The current design leaves shadow execution ownership split awkwardly: + - managed URP decides stage existence + - native policy key decides how the planned main-light shadow becomes executable runtime state + +## Scope + +### 1. Add an explicit managed directional shadow execution context + +Required work: + +- add a native-to-managed context wrapper for directional shadow execution +- let managed code opt into the default native shadow execution wiring without exposing raw native resource internals +- allow managed code to explicitly clear shadow execution state when needed + +### 2. Add managed shadow execution hooks across the SRP stack + +Required work: + +- add a directional-shadow execution hook to `ScriptableRenderPipelineAsset` +- route renderer-backed assets through `ScriptableRendererData` +- let `ScriptableRenderer` and renderer features participate, mirroring existing camera-request / frame-plan ownership layering where useful + +### 3. Make URP use the new callback instead of the native execution policy key + +Required work: + +- make `UniversalRenderer` explicitly request the default main directional shadow execution when its shadow block is enabled +- remove the URP reliance on `"BuiltinDirectionalShadow"` as the primary renderer ownership seam +- keep native fallback behavior only as generic substrate, not as the URP default ownership path + +## Out Of Scope + +- cascaded shadows +- soft-shadow algorithm changes +- deferred renderer +- moving all lighting/shadow sampling shader setup into managed code +- editor-side URP renderer UI + +## Done Criteria + +1. Managed URP can explicitly configure directional shadow execution through a callback context. +2. `UniversalRendererData` no longer depends on a native directional-shadow execution policy key as its primary default path. +3. The old `XCEditor` builds in Debug. +4. The old editor smoke passes for at least about 10 seconds and a fresh `SceneReady` appears in `editor/bin/Debug/editor.log`. + +## Follow-Up + +Once this stage closes, the remaining renderer-core seams become smaller and cleaner: + +- render scene setup ownership +- richer renderer variants +- eventual managed SRP package composition above the current C++ render-graph substrate diff --git a/engine/include/XCEngine/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h b/engine/include/XCEngine/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h index fcc10543..86cbf539 100644 --- a/engine/include/XCEngine/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h +++ b/engine/include/XCEngine/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h @@ -12,7 +12,9 @@ namespace Rendering { struct CameraFramePlan; struct CameraRenderRequest; +struct DirectionalShadowExecutionState; struct DirectionalShadowPlanningSettings; +struct DirectionalShadowSurfaceAllocation; namespace Pipelines { @@ -86,6 +88,12 @@ public: } virtual void ConfigureCameraFramePlan(CameraFramePlan&) const { } + virtual bool ConfigureDirectionalShadowExecutionState( + const CameraFramePlan&, + const DirectionalShadowSurfaceAllocation&, + DirectionalShadowExecutionState&) const { + return false; + } virtual std::shared_ptr GetPipelineRendererAsset() const { @@ -127,15 +135,6 @@ public: const { return {}; } - virtual std::string GetDirectionalShadowExecutionPolicyAssetKey() - const { - return {}; - } - virtual std::string GetDirectionalShadowExecutionPolicyAssetKey( - int32_t rendererIndex) const { - (void)rendererIndex; - return GetDirectionalShadowExecutionPolicyAssetKey(); - } virtual bool TryGetDefaultFinalColorSettings(FinalColorSettings&) const { return false; diff --git a/engine/include/XCEngine/Scripting/Mono/MonoScriptRuntime.h b/engine/include/XCEngine/Scripting/Mono/MonoScriptRuntime.h index 0799788d..96e054ee 100644 --- a/engine/include/XCEngine/Scripting/Mono/MonoScriptRuntime.h +++ b/engine/include/XCEngine/Scripting/Mono/MonoScriptRuntime.h @@ -266,6 +266,8 @@ private: MonoObject* CreateManagedScriptableRenderContext(uint64_t nativeHandle); MonoObject* CreateManagedCameraRenderRequestContext( uint64_t nativeHandle); + MonoObject* CreateManagedDirectionalShadowExecutionContext( + uint64_t nativeHandle); MonoObject* CreateManagedScriptableRenderPipelinePlanningContext( uint64_t nativeHandle); MonoObject* GetManagedObject(uint32_t gcHandle) const; @@ -308,12 +310,15 @@ private: MonoClass* m_scriptableRenderPipelineClass = nullptr; MonoClass* m_scriptableRenderContextClass = nullptr; MonoClass* m_cameraRenderRequestContextClass = nullptr; + MonoClass* m_directionalShadowExecutionContextClass = nullptr; MonoClass* m_scriptableRenderPipelinePlanningContextClass = nullptr; MonoClass* m_serializeFieldAttributeClass = nullptr; MonoMethod* m_gameObjectConstructor = nullptr; MonoMethod* m_scriptableRenderContextConstructor = nullptr; MonoMethod* m_cameraRenderRequestContextConstructor = nullptr; + MonoMethod* m_directionalShadowExecutionContextConstructor = + nullptr; MonoMethod* m_scriptableRenderPipelinePlanningContextConstructor = nullptr; MonoClassField* m_managedGameObjectUUIDField = nullptr; diff --git a/engine/src/Rendering/Pipelines/ScriptableRenderPipelineHost.cpp b/engine/src/Rendering/Pipelines/ScriptableRenderPipelineHost.cpp index a96c89b0..1783f975 100644 --- a/engine/src/Rendering/Pipelines/ScriptableRenderPipelineHost.cpp +++ b/engine/src/Rendering/Pipelines/ScriptableRenderPipelineHost.cpp @@ -1,6 +1,7 @@ #include "Rendering/Pipelines/ScriptableRenderPipelineHost.h" #include "Debug/Logger.h" +#include "Rendering/Execution/DirectionalShadowExecutionState.h" #include "Rendering/Internal/RenderPipelineFactory.h" #include "Rendering/Pipelines/BuiltinForwardPipeline.h" #include "Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h" @@ -211,38 +212,20 @@ bool ScriptableRenderPipelineHost::ConfigureDirectionalShadowExecutionState( const CameraFramePlan& plan, const DirectionalShadowSurfaceAllocation& shadowAllocation, DirectionalShadowExecutionState& shadowState) const { - if (m_managedAssetRuntime == nullptr) { - return RenderPipeline::ConfigureDirectionalShadowExecutionState( - plan, - shadowAllocation, - shadowState); - } - - const std::string assetKey = + if (m_managedAssetRuntime != nullptr && m_managedAssetRuntime - ->GetDirectionalShadowExecutionPolicyAssetKey( - plan.request.rendererIndex); - if (assetKey.empty()) { - return RenderPipeline::ConfigureDirectionalShadowExecutionState( - plan, - shadowAllocation, - shadowState); + ->ConfigureDirectionalShadowExecutionState( + plan, + shadowAllocation, + shadowState)) { + return shadowState.shadowCasterRequest.IsValid() && + shadowState.shadowData.IsValid(); } - if (!Rendering::Internal::ConfigureDirectionalShadowExecutionStateByKey( - assetKey, - plan, - shadowAllocation, - shadowState)) { - Debug::Logger::Get().Error( - Debug::LogCategory::Rendering, - Containers::String( - "ScriptableRenderPipelineHost failed to resolve directional shadow execution policy asset key: ") + - assetKey.c_str()); - return false; - } - - return true; + return RenderPipeline::ConfigureDirectionalShadowExecutionState( + plan, + shadowAllocation, + shadowState); } RenderPass* ScriptableRenderPipelineHost::GetCameraFrameStandalonePass( diff --git a/engine/src/Scripting/Mono/MonoScriptRuntime.cpp b/engine/src/Scripting/Mono/MonoScriptRuntime.cpp index 5d19ec84..09e6c31d 100644 --- a/engine/src/Scripting/Mono/MonoScriptRuntime.cpp +++ b/engine/src/Scripting/Mono/MonoScriptRuntime.cpp @@ -10,7 +10,9 @@ #include "Debug/Logger.h" #include "Input/InputManager.h" #include "Physics/PhysicsWorld.h" +#include "Rendering/Caches/DirectionalShadowSurfaceCache.h" #include "Rendering/Execution/CameraFramePlan.h" +#include "Rendering/Execution/DirectionalShadowExecutionState.h" #include "Rendering/Execution/CameraFrameRenderGraphFrameData.h" #include "Rendering/Execution/Internal/CameraFrameGraph/SurfaceUtils.h" #include "Rendering/Graph/RenderGraph.h" @@ -24,6 +26,7 @@ #include "Rendering/Pipelines/NativeSceneRecorder.h" #include "Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h" #include "Rendering/RenderPassGraphContract.h" +#include "Rendering/RenderPipeline.h" #include "Rendering/RenderPipelineAsset.h" #include "Rendering/RenderPipelineStageGraphContract.h" #include "Resources/BuiltinResources.h" @@ -134,6 +137,16 @@ struct ManagedCameraRenderRequestContextState { bool suppressDirectionalShadow = false; }; +struct ManagedDirectionalShadowExecutionContextState { + uint64_t handle = 0; + const Rendering::CameraFramePlan* plan = nullptr; + const Rendering::DirectionalShadowSurfaceAllocation* + shadowAllocation = nullptr; + Rendering::DirectionalShadowExecutionState* shadowState = + nullptr; + bool explicitlyConfigured = false; +}; + struct ManagedScriptableRenderPipelinePlanningContextState { uint64_t handle = 0; Rendering::CameraFramePlan* plan = nullptr; @@ -516,6 +529,60 @@ void UnregisterManagedCameraRenderRequestContextState( GetManagedCameraRenderRequestContextRegistry().erase(handle); } +uint64_t& GetManagedDirectionalShadowExecutionContextNextHandle() { + static uint64_t nextHandle = 1; + return nextHandle; +} + +std::unordered_map< + uint64_t, + ManagedDirectionalShadowExecutionContextState*>& +GetManagedDirectionalShadowExecutionContextRegistry() { + static std::unordered_map< + uint64_t, + ManagedDirectionalShadowExecutionContextState*> + registry; + return registry; +} + +ManagedDirectionalShadowExecutionContextState* +FindManagedDirectionalShadowExecutionContextState( + uint64_t handle) { + const auto it = + GetManagedDirectionalShadowExecutionContextRegistry().find( + handle); + return it != + GetManagedDirectionalShadowExecutionContextRegistry() + .end() + ? it->second + : nullptr; +} + +uint64_t RegisterManagedDirectionalShadowExecutionContextState( + ManagedDirectionalShadowExecutionContextState& state) { + uint64_t handle = + GetManagedDirectionalShadowExecutionContextNextHandle()++; + if (handle == 0) { + handle = + GetManagedDirectionalShadowExecutionContextNextHandle()++; + } + + state.handle = handle; + GetManagedDirectionalShadowExecutionContextRegistry()[handle] = + &state; + return handle; +} + +void UnregisterManagedDirectionalShadowExecutionContextState( + uint64_t handle) { + if (handle == 0) { + return; + } + + GetManagedDirectionalShadowExecutionContextRegistry().erase( + handle); +} + uint64_t& GetManagedScriptableRenderPipelinePlanningContextNextHandle() { static uint64_t nextHandle = 1; return nextHandle; @@ -1366,6 +1433,12 @@ public: directionalShadowSettings) const override; void ConfigureCameraFramePlan( Rendering::CameraFramePlan& plan) const override; + bool ConfigureDirectionalShadowExecutionState( + const Rendering::CameraFramePlan& plan, + const Rendering::DirectionalShadowSurfaceAllocation& + shadowAllocation, + Rendering::DirectionalShadowExecutionState& shadowState) + const override; bool TryGetDefaultFinalColorSettings( Rendering::FinalColorSettings& settings) const override; @@ -1382,10 +1455,6 @@ public: int32_t rendererIndex) const override; std::string GetDirectionalShadowPlanningPolicyAssetKey() const override; - std::string GetDirectionalShadowExecutionPolicyAssetKey() const - override; - std::string GetDirectionalShadowExecutionPolicyAssetKey( - int32_t rendererIndex) const override; std::string GetCameraFrameStandalonePassAssetKey( Rendering::CameraFrameStage stage) const override; std::string GetCameraFrameStandalonePassAssetKey( @@ -1433,13 +1502,10 @@ private: MonoObject* assetObject) const; MonoMethod* ResolveGetRenderSceneSetupPolicyAssetKeyContextualMethod( MonoObject* assetObject) const; + MonoMethod* ResolveConfigureDirectionalShadowExecutionStateMethod( + MonoObject* assetObject) const; MonoMethod* ResolveGetDirectionalShadowPlanningPolicyAssetKeyMethod( MonoObject* assetObject) const; - MonoMethod* ResolveGetDirectionalShadowExecutionPolicyAssetKeyMethod( - MonoObject* assetObject) const; - MonoMethod* - ResolveGetDirectionalShadowExecutionPolicyAssetKeyContextualMethod( - MonoObject* assetObject) const; MonoMethod* ResolveGetCameraFrameStandalonePassAssetKeyMethod( MonoObject* assetObject) const; MonoMethod* @@ -1471,13 +1537,10 @@ private: mutable MonoMethod* m_getRenderSceneSetupPolicyAssetKeyContextualMethod = nullptr; + mutable MonoMethod* + m_configureDirectionalShadowExecutionStateMethod = nullptr; mutable MonoMethod* m_getDirectionalShadowPlanningPolicyAssetKeyMethod = nullptr; - mutable MonoMethod* - m_getDirectionalShadowExecutionPolicyAssetKeyMethod = nullptr; - mutable MonoMethod* - m_getDirectionalShadowExecutionPolicyAssetKeyContextualMethod = - nullptr; mutable MonoMethod* m_getCameraFrameStandalonePassAssetKeyMethod = nullptr; mutable MonoMethod* @@ -1998,6 +2061,52 @@ void MonoManagedRenderPipelineAssetRuntime::ConfigureCameraFramePlan( planningContextHandle); } +bool MonoManagedRenderPipelineAssetRuntime:: + ConfigureDirectionalShadowExecutionState( + const Rendering::CameraFramePlan& plan, + const Rendering::DirectionalShadowSurfaceAllocation& + shadowAllocation, + Rendering::DirectionalShadowExecutionState& shadowState) const { + if (!EnsureManagedAsset()) { + return false; + } + + MonoObject* const assetObject = GetManagedAssetObject(); + MonoMethod* const method = + ResolveConfigureDirectionalShadowExecutionStateMethod( + assetObject); + if (assetObject == nullptr || method == nullptr) { + return false; + } + + ManagedDirectionalShadowExecutionContextState executionState = + {}; + executionState.plan = &plan; + executionState.shadowAllocation = &shadowAllocation; + executionState.shadowState = &shadowState; + const uint64_t executionContextHandle = + RegisterManagedDirectionalShadowExecutionContextState( + executionState); + MonoObject* const executionContextObject = + m_runtime->CreateManagedDirectionalShadowExecutionContext( + executionContextHandle); + if (executionContextObject == nullptr) { + UnregisterManagedDirectionalShadowExecutionContextState( + executionContextHandle); + return false; + } + + void* args[1] = { executionContextObject }; + m_runtime->InvokeManagedMethod( + assetObject, + method, + args, + nullptr); + UnregisterManagedDirectionalShadowExecutionContextState( + executionContextHandle); + return executionState.explicitlyConfigured; +} + bool MonoManagedRenderPipelineAssetRuntime::TryGetDefaultFinalColorSettings( Rendering::FinalColorSettings& settings) const { settings = {}; @@ -2275,61 +2384,6 @@ std::string MonoManagedRenderPipelineAssetRuntime:: reinterpret_cast(managedKeyObject)); } -std::string MonoManagedRenderPipelineAssetRuntime:: - GetDirectionalShadowExecutionPolicyAssetKey() const { - return GetDirectionalShadowExecutionPolicyAssetKey(-1); -} - -std::string MonoManagedRenderPipelineAssetRuntime:: - GetDirectionalShadowExecutionPolicyAssetKey( - int32_t rendererIndex) const { - if (!SyncManagedAssetRuntimeState()) { - return {}; - } - - MonoObject* const assetObject = GetManagedAssetObject(); - if (assetObject == nullptr) { - return {}; - } - - MonoMethod* const contextualMethod = - ResolveGetDirectionalShadowExecutionPolicyAssetKeyContextualMethod( - assetObject); - if (contextualMethod != nullptr) { - void* args[1] = { &rendererIndex }; - MonoObject* managedKeyObject = nullptr; - if (!m_runtime->InvokeManagedMethod( - assetObject, - contextualMethod, - args, - &managedKeyObject)) { - return {}; - } - - return MonoStringToUtf8( - reinterpret_cast(managedKeyObject)); - } - - MonoMethod* const method = - ResolveGetDirectionalShadowExecutionPolicyAssetKeyMethod( - assetObject); - if (method == nullptr) { - return {}; - } - - MonoObject* managedKeyObject = nullptr; - if (!m_runtime->InvokeManagedMethod( - assetObject, - method, - nullptr, - &managedKeyObject)) { - return {}; - } - - return MonoStringToUtf8( - reinterpret_cast(managedKeyObject)); -} - std::string MonoManagedRenderPipelineAssetRuntime:: GetCameraFrameStandalonePassAssetKey( Rendering::CameraFrameStage stage) const { @@ -2607,10 +2661,8 @@ void MonoManagedRenderPipelineAssetRuntime::ReleaseManagedAsset() const { m_usesNativeCameraFramePlanBaselineContextualMethod = nullptr; m_getRenderSceneSetupPolicyAssetKeyMethod = nullptr; m_getRenderSceneSetupPolicyAssetKeyContextualMethod = nullptr; + m_configureDirectionalShadowExecutionStateMethod = nullptr; m_getDirectionalShadowPlanningPolicyAssetKeyMethod = nullptr; - m_getDirectionalShadowExecutionPolicyAssetKeyMethod = nullptr; - m_getDirectionalShadowExecutionPolicyAssetKeyContextualMethod = - nullptr; m_getCameraFrameStandalonePassAssetKeyMethod = nullptr; m_getCameraFrameStandalonePassAssetKeyContextualMethod = nullptr; m_pipelineRendererAsset.reset(); @@ -2823,6 +2875,22 @@ MonoManagedRenderPipelineAssetRuntime:: return m_getRenderSceneSetupPolicyAssetKeyContextualMethod; } +MonoMethod* +MonoManagedRenderPipelineAssetRuntime:: + ResolveConfigureDirectionalShadowExecutionStateMethod( + MonoObject* assetObject) const { + if (m_configureDirectionalShadowExecutionStateMethod == + nullptr) { + m_configureDirectionalShadowExecutionStateMethod = + m_runtime->ResolveManagedMethod( + assetObject, + "ConfigureDirectionalShadowExecutionStateInstance", + 1); + } + + return m_configureDirectionalShadowExecutionStateMethod; +} + MonoMethod* MonoManagedRenderPipelineAssetRuntime:: ResolveGetDirectionalShadowPlanningPolicyAssetKeyMethod( @@ -2839,39 +2907,6 @@ MonoManagedRenderPipelineAssetRuntime:: return m_getDirectionalShadowPlanningPolicyAssetKeyMethod; } -MonoMethod* -MonoManagedRenderPipelineAssetRuntime:: - ResolveGetDirectionalShadowExecutionPolicyAssetKeyMethod( - MonoObject* assetObject) const { - if (m_getDirectionalShadowExecutionPolicyAssetKeyMethod == - nullptr) { - m_getDirectionalShadowExecutionPolicyAssetKeyMethod = - m_runtime->ResolveManagedMethod( - assetObject, - "GetDirectionalShadowExecutionPolicyAssetKey", - 0); - } - - return m_getDirectionalShadowExecutionPolicyAssetKeyMethod; -} - -MonoMethod* -MonoManagedRenderPipelineAssetRuntime:: - ResolveGetDirectionalShadowExecutionPolicyAssetKeyContextualMethod( - MonoObject* assetObject) const { - if (m_getDirectionalShadowExecutionPolicyAssetKeyContextualMethod == - nullptr) { - m_getDirectionalShadowExecutionPolicyAssetKeyContextualMethod = - m_runtime->ResolveManagedMethod( - assetObject, - "GetDirectionalShadowExecutionPolicyAssetKeyContextual", - 1); - } - - return - m_getDirectionalShadowExecutionPolicyAssetKeyContextualMethod; -} - MonoMethod* MonoManagedRenderPipelineAssetRuntime:: ResolveGetCameraFrameStandalonePassAssetKeyMethod( @@ -5771,6 +5806,80 @@ void InternalCall_Rendering_CameraRenderRequestContext_ClearDirectionalShadow( state->suppressDirectionalShadow = true; } +mono_bool +InternalCall_Rendering_DirectionalShadowExecutionContext_GetHasPlannedMainDirectionalShadow( + uint64_t nativeHandle) { + const ManagedDirectionalShadowExecutionContextState* const state = + FindManagedDirectionalShadowExecutionContextState( + nativeHandle); + return state != nullptr && + state->plan != nullptr && + state->plan->directionalShadow.IsValid() + ? 1 + : 0; +} + +int32_t +InternalCall_Rendering_DirectionalShadowExecutionContext_GetRendererIndex( + uint64_t nativeHandle) { + const ManagedDirectionalShadowExecutionContextState* const state = + FindManagedDirectionalShadowExecutionContextState( + nativeHandle); + return state != nullptr && + state->plan != nullptr + ? state->plan->request.rendererIndex + : -1; +} + +mono_bool +InternalCall_Rendering_DirectionalShadowExecutionContext_GetIsConfigured( + uint64_t nativeHandle) { + const ManagedDirectionalShadowExecutionContextState* const state = + FindManagedDirectionalShadowExecutionContextState( + nativeHandle); + return state != nullptr && + state->explicitlyConfigured + ? 1 + : 0; +} + +mono_bool +InternalCall_Rendering_DirectionalShadowExecutionContext_UseDefaultMainDirectionalShadowExecution( + uint64_t nativeHandle) { + ManagedDirectionalShadowExecutionContextState* const state = + FindManagedDirectionalShadowExecutionContextState( + nativeHandle); + if (state == nullptr || + state->plan == nullptr || + state->shadowAllocation == nullptr || + state->shadowState == nullptr) { + return 0; + } + + Rendering::ApplyDefaultRenderPipelineDirectionalShadowExecutionPolicy( + *state->plan, + *state->shadowAllocation, + *state->shadowState); + state->explicitlyConfigured = true; + return state->shadowState->shadowCasterRequest.IsValid() && + state->shadowState->shadowData.IsValid() + ? 1 + : 0; +} + +void InternalCall_Rendering_DirectionalShadowExecutionContext_ClearDirectionalShadowExecution( + uint64_t nativeHandle) { + ManagedDirectionalShadowExecutionContextState* const state = + FindManagedDirectionalShadowExecutionContextState( + nativeHandle); + if (state == nullptr || state->shadowState == nullptr) { + return; + } + + *state->shadowState = {}; + state->explicitlyConfigured = true; +} + int32_t InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetRendererIndex( uint64_t nativeHandle) { @@ -6223,6 +6332,11 @@ void RegisterInternalCalls() { mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_GetDirectionalShadowPlanningSettings", reinterpret_cast(&InternalCall_Rendering_CameraRenderRequestContext_GetDirectionalShadowPlanningSettings)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_SetDirectionalShadowPlanningSettings", reinterpret_cast(&InternalCall_Rendering_CameraRenderRequestContext_SetDirectionalShadowPlanningSettings)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_ClearDirectionalShadow", reinterpret_cast(&InternalCall_Rendering_CameraRenderRequestContext_ClearDirectionalShadow)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_DirectionalShadowExecutionContext_GetHasPlannedMainDirectionalShadow", reinterpret_cast(&InternalCall_Rendering_DirectionalShadowExecutionContext_GetHasPlannedMainDirectionalShadow)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_DirectionalShadowExecutionContext_GetRendererIndex", reinterpret_cast(&InternalCall_Rendering_DirectionalShadowExecutionContext_GetRendererIndex)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_DirectionalShadowExecutionContext_GetIsConfigured", reinterpret_cast(&InternalCall_Rendering_DirectionalShadowExecutionContext_GetIsConfigured)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_DirectionalShadowExecutionContext_UseDefaultMainDirectionalShadowExecution", reinterpret_cast(&InternalCall_Rendering_DirectionalShadowExecutionContext_UseDefaultMainDirectionalShadowExecution)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_DirectionalShadowExecutionContext_ClearDirectionalShadowExecution", reinterpret_cast(&InternalCall_Rendering_DirectionalShadowExecutionContext_ClearDirectionalShadowExecution)); GetInternalCallRegistrationState() = true; } @@ -6301,11 +6415,13 @@ void MonoScriptRuntime::Shutdown() { m_scriptableRenderPipelineClass = nullptr; m_scriptableRenderContextClass = nullptr; m_cameraRenderRequestContextClass = nullptr; + m_directionalShadowExecutionContextClass = nullptr; m_scriptableRenderPipelinePlanningContextClass = nullptr; m_serializeFieldAttributeClass = nullptr; m_gameObjectConstructor = nullptr; m_scriptableRenderContextConstructor = nullptr; m_cameraRenderRequestContextConstructor = nullptr; + m_directionalShadowExecutionContextConstructor = nullptr; m_scriptableRenderPipelinePlanningContextConstructor = nullptr; m_managedGameObjectUUIDField = nullptr; m_gameObjectUUIDField = nullptr; @@ -7100,6 +7216,27 @@ bool MonoScriptRuntime::DiscoverScriptClasses() { return false; } + m_directionalShadowExecutionContextClass = mono_class_from_name( + m_coreImage, + kManagedRenderingNamespace, + "DirectionalShadowExecutionContext"); + if (!m_directionalShadowExecutionContextClass) { + SetError( + "Failed to locate the managed DirectionalShadowExecutionContext type."); + return false; + } + + m_directionalShadowExecutionContextConstructor = + mono_class_get_method_from_name( + m_directionalShadowExecutionContextClass, + ".ctor", + 1); + if (!m_directionalShadowExecutionContextConstructor) { + SetError( + "Failed to locate the managed DirectionalShadowExecutionContext constructor."); + return false; + } + m_scriptableRenderPipelinePlanningContextClass = mono_class_from_name( m_coreImage, kManagedRenderingNamespace, @@ -7716,6 +7853,46 @@ MonoScriptRuntime::CreateManagedCameraRenderRequestContext( return contextObject; } +MonoObject* +MonoScriptRuntime::CreateManagedDirectionalShadowExecutionContext( + uint64_t nativeHandle) { + if (!m_initialized || + nativeHandle == 0 || + m_directionalShadowExecutionContextClass == nullptr || + m_directionalShadowExecutionContextConstructor == nullptr) { + return nullptr; + } + + SetCurrentDomain(); + + MonoObject* const contextObject = + mono_object_new( + m_appDomain, + m_directionalShadowExecutionContextClass); + if (contextObject == nullptr) { + SetError( + "Mono failed to allocate a managed DirectionalShadowExecutionContext."); + return nullptr; + } + + void* args[1]; + uint64_t nativeHandleArgument = nativeHandle; + args[0] = &nativeHandleArgument; + + MonoObject* exception = nullptr; + mono_runtime_invoke( + m_directionalShadowExecutionContextConstructor, + contextObject, + args, + &exception); + if (exception != nullptr) { + RecordException(exception); + return nullptr; + } + + return contextObject; +} + MonoObject* MonoScriptRuntime::CreateManagedScriptableRenderPipelinePlanningContext( uint64_t nativeHandle) { diff --git a/managed/CMakeLists.txt b/managed/CMakeLists.txt index 41fae5a8..595bd566 100644 --- a/managed/CMakeLists.txt +++ b/managed/CMakeLists.txt @@ -175,6 +175,7 @@ set(XCENGINE_SCRIPT_CORE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/CameraFrameStage.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/CompareFunction.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/DepthState.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/DirectionalShadowExecutionContext.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/DirectionalShadowPlanningSettings.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/DrawingSettings.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/FinalColorExposureMode.cs diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipelineAsset.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipelineAsset.cs index ea281281..111d803c 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipelineAsset.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipelineAsset.cs @@ -71,6 +71,17 @@ namespace XCEngine.Rendering.Universal } } + protected override bool ConfigureDirectionalShadowExecutionState( + DirectionalShadowExecutionContext context) + { + ScriptableRendererData resolvedRendererData = + ResolveRendererData(context); + return resolvedRendererData != null && + resolvedRendererData + .ConfigureDirectionalShadowExecutionStateInstance( + context); + } + private protected string GetPipelineRendererAssetKey() { return GetPipelineRendererAssetKeyContextual( @@ -149,33 +160,6 @@ namespace XCEngine.Rendering.Universal return string.Empty; } - private protected virtual string - GetDirectionalShadowExecutionPolicyAssetKey() - { - return string.Empty; - } - - private protected virtual string - GetDirectionalShadowExecutionPolicyAssetKeyContextual( - int rendererIndex) - { - ScriptableRendererData resolvedRendererData = - GetRendererData(rendererIndex); - if (resolvedRendererData != null) - { - string executionPolicyAssetKey = - resolvedRendererData - .GetDirectionalShadowExecutionPolicyAssetKeyInstance(); - if (!string.IsNullOrEmpty( - executionPolicyAssetKey)) - { - return executionPolicyAssetKey; - } - } - - return GetDirectionalShadowExecutionPolicyAssetKey(); - } - protected override void ReleaseRuntimeResources() { ReleaseRendererDataRuntimeResources(); @@ -404,6 +388,15 @@ namespace XCEngine.Rendering.Universal : -1); } + private ScriptableRendererData ResolveRendererData( + DirectionalShadowExecutionContext context) + { + return GetRendererData( + context != null + ? context.rendererIndex + : -1); + } + private void ApplyResolvedRendererIndex( CameraRenderRequestContext context, int rendererIndex) diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderer.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderer.cs index a27b59c2..736966fb 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderer.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderer.cs @@ -101,6 +101,12 @@ namespace XCEngine.Rendering.Universal FinalizeCameraFramePlan(context); } + internal void ConfigureDirectionalShadowExecutionStateInstance( + DirectionalShadowExecutionContext context) + { + ConfigureDirectionalShadowExecutionState(context); + } + internal bool RecordRendererInstance( RendererRecordingContext context) { @@ -199,6 +205,11 @@ namespace XCEngine.Rendering.Universal context); } + protected virtual void ConfigureDirectionalShadowExecutionState( + DirectionalShadowExecutionContext context) + { + } + private void BuildPassQueue( RenderingData renderingData) { diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs index 01b51782..8e0e2925 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs @@ -76,12 +76,6 @@ namespace XCEngine.Rendering.Universal stage); } - internal string - GetDirectionalShadowExecutionPolicyAssetKeyInstance() - { - return GetDirectionalShadowExecutionPolicyAssetKey(); - } - internal int GetRuntimeStateVersionInstance() { return m_runtimeStateVersion; @@ -152,6 +146,42 @@ namespace XCEngine.Rendering.Universal } } + internal bool ConfigureDirectionalShadowExecutionStateInstance( + DirectionalShadowExecutionContext context) + { + ConfigureDirectionalShadowExecutionState( + context); + + ScriptableRenderer renderer = + GetRendererInstance(); + if (renderer != null) + { + renderer + .ConfigureDirectionalShadowExecutionStateInstance( + context); + } + + ScriptableRendererFeature[] rendererFeatures = + GetRendererFeatures(); + for (int i = 0; i < rendererFeatures.Length; ++i) + { + ScriptableRendererFeature rendererFeature = + rendererFeatures[i]; + if (rendererFeature == null || + !rendererFeature.isActive) + { + continue; + } + + rendererFeature + .ConfigureDirectionalShadowExecutionState( + context); + } + + return context != null && + context.isConfigured; + } + protected virtual ScriptableRenderer CreateRenderer() { return null; @@ -175,6 +205,11 @@ namespace XCEngine.Rendering.Universal { } + protected virtual void ConfigureDirectionalShadowExecutionState( + DirectionalShadowExecutionContext context) + { + } + private protected virtual string GetPipelineRendererAssetKey() { return string.Empty; @@ -191,12 +226,6 @@ namespace XCEngine.Rendering.Universal return string.Empty; } - private protected virtual string - GetDirectionalShadowExecutionPolicyAssetKey() - { - return string.Empty; - } - protected virtual ScriptableRendererFeature[] CreateRendererFeatures() { return rendererFeatures ?? diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererFeature.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererFeature.cs index 9b1bdca4..7a7a08c7 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererFeature.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererFeature.cs @@ -52,6 +52,11 @@ namespace XCEngine.Rendering.Universal { } + public virtual void ConfigureDirectionalShadowExecutionState( + DirectionalShadowExecutionContext context) + { + } + public virtual void AddRenderPasses( ScriptableRenderer renderer, RenderingData renderingData) diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs index 65c5665f..255d6486 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs @@ -70,6 +70,26 @@ namespace XCEngine.Rendering.Universal ConfigureFinalOutputStage(context); } + protected override void ConfigureDirectionalShadowExecutionState( + DirectionalShadowExecutionContext context) + { + if (context == null || + !context.hasPlannedMainDirectionalShadow) + { + return; + } + + ShadowCasterBlockData shadowCaster = + m_rendererData.GetShadowCasterBlockInstance(); + if (shadowCaster == null || + !shadowCaster.enabled) + { + return; + } + + context.UseDefaultMainDirectionalShadowExecution(); + } + protected override void AddRenderPasses( RenderingData renderingData) { diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs index 227502d7..bdd698da 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs @@ -43,12 +43,6 @@ namespace XCEngine.Rendering.Universal return "BuiltinDefaultSceneSetup"; } - private protected override string - GetDirectionalShadowExecutionPolicyAssetKey() - { - return "BuiltinDirectionalShadow"; - } - internal UniversalMainSceneData GetMainSceneInstance() { if (mainScene == null) diff --git a/managed/XCEngine.ScriptCore/InternalCalls.cs b/managed/XCEngine.ScriptCore/InternalCalls.cs index a41936b7..7c5f53a2 100644 --- a/managed/XCEngine.ScriptCore/InternalCalls.cs +++ b/managed/XCEngine.ScriptCore/InternalCalls.cs @@ -903,6 +903,31 @@ namespace XCEngine Rendering_CameraRenderRequestContext_ClearDirectionalShadow( ulong nativeHandle); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool + Rendering_DirectionalShadowExecutionContext_GetHasPlannedMainDirectionalShadow( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int + Rendering_DirectionalShadowExecutionContext_GetRendererIndex( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool + Rendering_DirectionalShadowExecutionContext_GetIsConfigured( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool + Rendering_DirectionalShadowExecutionContext_UseDefaultMainDirectionalShadowExecution( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void + Rendering_DirectionalShadowExecutionContext_ClearDirectionalShadowExecution( + ulong nativeHandle); + } } diff --git a/managed/XCEngine.ScriptCore/Rendering/Core/DirectionalShadowExecutionContext.cs b/managed/XCEngine.ScriptCore/Rendering/Core/DirectionalShadowExecutionContext.cs new file mode 100644 index 00000000..9eb9de9f --- /dev/null +++ b/managed/XCEngine.ScriptCore/Rendering/Core/DirectionalShadowExecutionContext.cs @@ -0,0 +1,45 @@ +namespace XCEngine.Rendering +{ + public sealed class DirectionalShadowExecutionContext + { + private readonly ulong m_nativeHandle; + + internal DirectionalShadowExecutionContext( + ulong nativeHandle) + { + m_nativeHandle = nativeHandle; + } + + public bool hasPlannedMainDirectionalShadow => + InternalCalls + .Rendering_DirectionalShadowExecutionContext_GetHasPlannedMainDirectionalShadow( + m_nativeHandle); + + public int rendererIndex => + InternalCalls + .Rendering_DirectionalShadowExecutionContext_GetRendererIndex( + m_nativeHandle); + + public bool isConfigured => + InternalCalls + .Rendering_DirectionalShadowExecutionContext_GetIsConfigured( + m_nativeHandle); + + public bool UseDefaultMainDirectionalShadowExecution() + { + return InternalCalls + .Rendering_DirectionalShadowExecutionContext_UseDefaultMainDirectionalShadowExecution( + m_nativeHandle); + } + + public void ClearDirectionalShadowExecution() + { + InternalCalls + .Rendering_DirectionalShadowExecutionContext_ClearDirectionalShadowExecution( + m_nativeHandle); + } + + internal ulong nativeHandle => + m_nativeHandle; + } +} diff --git a/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderPipelineAsset.cs b/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderPipelineAsset.cs index a750dea2..397d14a1 100644 --- a/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderPipelineAsset.cs +++ b/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderPipelineAsset.cs @@ -21,6 +21,13 @@ namespace XCEngine.Rendering ConfigureCameraFramePlan(context); } + internal bool ConfigureDirectionalShadowExecutionStateInstance( + DirectionalShadowExecutionContext context) + { + return ConfigureDirectionalShadowExecutionState( + context); + } + internal int GetRuntimeResourceVersionInstance() { SynchronizeRuntimeResourceVersion(); @@ -42,6 +49,12 @@ namespace XCEngine.Rendering { } + protected virtual bool ConfigureDirectionalShadowExecutionState( + DirectionalShadowExecutionContext context) + { + return false; + } + protected virtual FinalColorSettings GetDefaultFinalColorSettings() { return FinalColorSettings.CreateDefault();