diff --git a/engine/include/XCEngine/Rendering/Execution/CameraFrameColorSource.h b/engine/include/XCEngine/Rendering/Execution/CameraFrameColorSource.h new file mode 100644 index 00000000..28351a15 --- /dev/null +++ b/engine/include/XCEngine/Rendering/Execution/CameraFrameColorSource.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace XCEngine { +namespace Rendering { + +enum class CameraFrameColorSource : uint8_t { + ExplicitSurface = 0, + MainSceneColor, + PostProcessColor +}; + +} // namespace Rendering +} // namespace XCEngine diff --git a/engine/include/XCEngine/Rendering/Execution/CameraFramePlan.h b/engine/include/XCEngine/Rendering/Execution/CameraFramePlan.h index 5af08519..f3b9f700 100644 --- a/engine/include/XCEngine/Rendering/Execution/CameraFramePlan.h +++ b/engine/include/XCEngine/Rendering/Execution/CameraFramePlan.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -8,12 +9,6 @@ namespace XCEngine { namespace Rendering { -enum class CameraFrameColorSource { - ExplicitSurface = 0, - MainSceneColor, - PostProcessColor -}; - struct CameraFrameFullscreenStagePlan { bool requested = false; bool usesGraphManagedOutputColor = false; diff --git a/engine/include/XCEngine/Rendering/Graph/RenderGraphRecordingContext.h b/engine/include/XCEngine/Rendering/Graph/RenderGraphRecordingContext.h index 356e9fde..61e08e81 100644 --- a/engine/include/XCEngine/Rendering/Graph/RenderGraphRecordingContext.h +++ b/engine/include/XCEngine/Rendering/Graph/RenderGraphRecordingContext.h @@ -273,7 +273,7 @@ inline SceneRenderFeaturePassRenderGraphContext BuildSceneRenderFeaturePassRende inline RenderPipelineStageRenderGraphContext BuildRenderPipelineStageRenderGraphContext( const RenderGraphRecordingContext& common, CameraFrameStage stage) { - return { + RenderPipelineStageRenderGraphContext context = { common.graphBuilder, common.passName, stage, @@ -286,9 +286,11 @@ inline RenderPipelineStageRenderGraphContext BuildRenderPipelineStageRenderGraph common.sourceColorTexture, common.colorTargets, common.depthTarget, + {}, common.executionSucceeded, common.blackboard }; + return context; } inline SceneRenderFeaturePassRenderGraphContext CloneSceneRenderFeaturePassRenderGraphContext( diff --git a/engine/include/XCEngine/Rendering/RenderPipeline.h b/engine/include/XCEngine/Rendering/RenderPipeline.h index dbf4d55e..73cc20c2 100644 --- a/engine/include/XCEngine/Rendering/RenderPipeline.h +++ b/engine/include/XCEngine/Rendering/RenderPipeline.h @@ -1,14 +1,17 @@ #pragma once #include +#include #include #include #include #include #include +#include #include #include #include +#include #include #include @@ -40,8 +43,13 @@ struct RenderPipelineStageRenderGraphContext { RenderGraphTextureHandle sourceColorTexture = {}; std::vector colorTargets = {}; RenderGraphTextureHandle depthTarget = {}; + ResolvedFinalColorPolicy finalColorPolicy = {}; bool* executionSucceeded = nullptr; RenderGraphBlackboard* blackboard = nullptr; + CameraFrameColorSource stageColorSource = + CameraFrameColorSource::ExplicitSurface; + bool usesGraphManagedOutputColor = false; + DirectionalShadowRenderPlan directionalShadowPlan = {}; }; class RenderPipelineStageRecorder { diff --git a/engine/include/XCEngine/Scripting/IScriptRuntime.h b/engine/include/XCEngine/Scripting/IScriptRuntime.h index ba077585..e7cba842 100644 --- a/engine/include/XCEngine/Scripting/IScriptRuntime.h +++ b/engine/include/XCEngine/Scripting/IScriptRuntime.h @@ -74,6 +74,8 @@ public: virtual bool TryGetAvailableScriptClasses( std::vector& outClasses) const = 0; + virtual bool TryGetAvailableRenderPipelineAssetClasses( + std::vector& outClasses) const = 0; virtual bool TryGetClassFieldMetadata( const std::string& assemblyName, diff --git a/engine/include/XCEngine/Scripting/Mono/MonoScriptRuntime.h b/engine/include/XCEngine/Scripting/Mono/MonoScriptRuntime.h index 4aeafcf2..3789d511 100644 --- a/engine/include/XCEngine/Scripting/Mono/MonoScriptRuntime.h +++ b/engine/include/XCEngine/Scripting/Mono/MonoScriptRuntime.h @@ -19,6 +19,12 @@ typedef struct _MonoMethod MonoMethod; typedef struct _MonoClassField MonoClassField; namespace XCEngine { +namespace Rendering { +namespace Pipelines { +struct ManagedRenderPipelineAssetDescriptor; +} // namespace Pipelines +} // namespace Rendering + namespace Scripting { class ScriptComponent; @@ -56,6 +62,8 @@ public: std::vector GetScriptClassNames(const std::string& assemblyName = std::string()) const; bool TryGetAvailableScriptClasses( std::vector& outClasses) const override; + bool TryGetAvailableRenderPipelineAssetClasses( + std::vector& outClasses) const override; bool TryGetClassFieldMetadata( const std::string& assemblyName, const std::string& namespaceName, @@ -76,6 +84,8 @@ public: uint32_t RetainExternalManagedObjectReference(MonoObject* managedObject); void ReleaseExternalManagedObject(uint32_t gcHandle); bool IsScriptableRenderPipelineAssetObject(MonoObject* managedObject) const; + bool TryEnsureManagedRenderPipelineAssetHandle( + Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor& ioDescriptor); bool TryGetFieldValue( const ScriptComponent* component, @@ -178,6 +188,9 @@ private: bool LoadAssemblies(); bool DiscoverScriptClasses(); void DiscoverScriptClassesInImage(const std::string& assemblyName, MonoImage* image); + void DiscoverRenderPipelineAssetClassesInImage( + const std::string& assemblyName, + MonoImage* image); bool IsMonoBehaviourSubclass(MonoClass* monoClass) const; bool IsSupportedComponentFieldClass(MonoClass* monoClass) const; bool IsScriptComponentFieldClass(MonoClass* monoClass) const; @@ -282,6 +295,7 @@ private: MonoClassField* m_scriptComponentUUIDField = nullptr; std::unordered_map m_classes; + std::vector m_renderPipelineAssetClasses; std::unordered_map m_instances; std::unordered_map m_externalManagedObjects; std::shared_ptr m_runtimeLifetimeToken; diff --git a/engine/include/XCEngine/Scripting/NullScriptRuntime.h b/engine/include/XCEngine/Scripting/NullScriptRuntime.h index dee2ed93..77aa2738 100644 --- a/engine/include/XCEngine/Scripting/NullScriptRuntime.h +++ b/engine/include/XCEngine/Scripting/NullScriptRuntime.h @@ -11,6 +11,8 @@ public: void OnRuntimeStop(Components::Scene* scene) override; bool TryGetAvailableScriptClasses( std::vector& outClasses) const override; + bool TryGetAvailableRenderPipelineAssetClasses( + std::vector& outClasses) const override; bool TryGetClassFieldMetadata( const std::string& assemblyName, const std::string& namespaceName, diff --git a/engine/include/XCEngine/Scripting/ScriptEngine.h b/engine/include/XCEngine/Scripting/ScriptEngine.h index 13fca0bb..7eb23341 100644 --- a/engine/include/XCEngine/Scripting/ScriptEngine.h +++ b/engine/include/XCEngine/Scripting/ScriptEngine.h @@ -60,6 +60,9 @@ public: bool TryGetAvailableScriptClasses( std::vector& outClasses, const std::string& assemblyName = std::string()) const; + bool TryGetAvailableRenderPipelineAssetClasses( + std::vector& outClasses, + const std::string& assemblyName = std::string()) const; bool TrySetScriptFieldValue( ScriptComponent* component, const std::string& fieldName, diff --git a/engine/src/Rendering/Execution/CameraRenderer.cpp b/engine/src/Rendering/Execution/CameraRenderer.cpp index b71618b4..4ad58be7 100644 --- a/engine/src/Rendering/Execution/CameraRenderer.cpp +++ b/engine/src/Rendering/Execution/CameraRenderer.cpp @@ -3,6 +3,7 @@ #include "Components/CameraComponent.h" #include "Rendering/Execution/DirectionalShadowExecutionState.h" #include "Rendering/Execution/Internal/CameraFrameGraph/Executor.h" +#include "Rendering/GraphicsSettingsState.h" #include "Rendering/Internal/RenderPipelineFactory.h" #include "Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h" #include "Rendering/RenderPipelineAsset.h" @@ -88,7 +89,7 @@ void CameraRenderer::RefreshManagedPipelineBindingIfNeeded() { } const size_t currentGeneration = - Pipelines::GetManagedRenderPipelineEnvironmentGeneration(); + GetGraphicsSettingsState().GetEnvironmentGeneration(); if (currentGeneration == m_managedPipelineEnvironmentGeneration) { return; } @@ -117,7 +118,7 @@ void CameraRenderer::ResetPipeline(std::unique_ptr pipeline) { m_managedPipelineEnvironmentGeneration = UsesManagedPipelineBinding() - ? Pipelines::GetManagedRenderPipelineEnvironmentGeneration() + ? GetGraphicsSettingsState().GetEnvironmentGeneration() : 0u; } diff --git a/engine/src/Rendering/Execution/Internal/CameraFrameGraph/StageContract.cpp b/engine/src/Rendering/Execution/Internal/CameraFrameGraph/StageContract.cpp index 0043825d..12229260 100644 --- a/engine/src/Rendering/Execution/Internal/CameraFrameGraph/StageContract.cpp +++ b/engine/src/Rendering/Execution/Internal/CameraFrameGraph/StageContract.cpp @@ -582,12 +582,22 @@ RenderPassContext BuildCameraFrameStageFallbackPassContext( RenderPipelineStageRenderGraphContext BuildCameraFramePipelineStageRenderGraphContext( const CameraFrameRenderGraphStageContext& context, const CameraFrameStageGraphBuildState& stageState) { - return BuildRenderPipelineStageRenderGraphContext( + RenderPipelineStageRenderGraphContext pipelineContext = + BuildRenderPipelineStageRenderGraphContext( BuildCameraFrameStageGraphRecordingContext( context, stageState, context.sceneData), stageState.stage); + pipelineContext.finalColorPolicy = + context.plan.finalColorPolicy; + pipelineContext.stageColorSource = + context.plan.ResolveStageColorSource(stageState.stage); + pipelineContext.usesGraphManagedOutputColor = + context.plan.UsesGraphManagedOutputColor(stageState.stage); + pipelineContext.directionalShadowPlan = + context.plan.directionalShadow; + return pipelineContext; } bool RecordCameraFramePipelineStageGraphPass( diff --git a/engine/src/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.cpp b/engine/src/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.cpp index f60a0f77..9c090735 100644 --- a/engine/src/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.cpp +++ b/engine/src/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.cpp @@ -1,35 +1,13 @@ #include "Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h" +#include "Rendering/GraphicsSettingsState.h" + #include namespace XCEngine { namespace Rendering { namespace Pipelines { -namespace { - -ManagedRenderPipelineAssetDescriptor& GetManagedRenderPipelineAssetDescriptorStorage() { - static ManagedRenderPipelineAssetDescriptor s_descriptor = {}; - return s_descriptor; -} - -std::shared_ptr& GetManagedRenderPipelineBridgeStorage() { - static std::shared_ptr s_bridge = nullptr; - return s_bridge; -} - -size_t& GetManagedRenderPipelineBridgeGenerationStorage() { - static size_t s_generation = 1u; - return s_generation; -} - -size_t& GetManagedRenderPipelineEnvironmentGenerationStorage() { - static size_t s_generation = 1u; - return s_generation; -} - -} // namespace - ManagedScriptableRenderPipelineAsset::ManagedScriptableRenderPipelineAsset( ManagedRenderPipelineAssetDescriptor descriptor) : m_descriptor(std::move(descriptor)) { @@ -37,8 +15,10 @@ ManagedScriptableRenderPipelineAsset::ManagedScriptableRenderPipelineAsset( std::shared_ptr ManagedScriptableRenderPipelineAsset::ResolveManagedAssetRuntime() const { + const GraphicsSettingsState& graphicsSettings = + GetGraphicsSettingsState(); const size_t bridgeGeneration = - GetManagedRenderPipelineBridgeGenerationStorage(); + graphicsSettings.GetManagedRenderPipelineBridgeGeneration(); if (m_managedAssetRuntime != nullptr && m_managedAssetRuntimeBridgeGeneration == bridgeGeneration) { return m_managedAssetRuntime; @@ -48,7 +28,7 @@ ManagedScriptableRenderPipelineAsset::ResolveManagedAssetRuntime() const { m_managedAssetRuntimeBridgeGeneration = bridgeGeneration; const std::shared_ptr bridge = - GetManagedRenderPipelineBridgeStorage(); + graphicsSettings.GetManagedRenderPipelineBridge(); if (bridge == nullptr) { return nullptr; } @@ -121,45 +101,41 @@ void ManagedScriptableRenderPipelineAsset::ConfigureCameraFramePlan( void SetManagedRenderPipelineBridge( std::shared_ptr bridge) { - GetManagedRenderPipelineBridgeStorage() = std::move(bridge); - ++GetManagedRenderPipelineBridgeGenerationStorage(); - ++GetManagedRenderPipelineEnvironmentGenerationStorage(); + GetGraphicsSettingsState().SetManagedRenderPipelineBridge( + std::move(bridge)); } void ClearManagedRenderPipelineBridge() { - GetManagedRenderPipelineBridgeStorage().reset(); - ++GetManagedRenderPipelineBridgeGenerationStorage(); - ++GetManagedRenderPipelineEnvironmentGenerationStorage(); + GetGraphicsSettingsState().ClearManagedRenderPipelineBridge(); } std::shared_ptr GetManagedRenderPipelineBridge() { - return GetManagedRenderPipelineBridgeStorage(); + return GetGraphicsSettingsState().GetManagedRenderPipelineBridge(); } size_t GetManagedRenderPipelineEnvironmentGeneration() { - return GetManagedRenderPipelineEnvironmentGenerationStorage(); + return GetGraphicsSettingsState().GetEnvironmentGeneration(); } void SetManagedRenderPipelineAssetDescriptor( const ManagedRenderPipelineAssetDescriptor& descriptor) { - GetManagedRenderPipelineAssetDescriptorStorage() = descriptor; - ++GetManagedRenderPipelineEnvironmentGenerationStorage(); + GetGraphicsSettingsState().SetRenderPipelineAssetDescriptor( + descriptor); } void ClearManagedRenderPipelineAssetDescriptor() { - GetManagedRenderPipelineAssetDescriptorStorage() = {}; - ++GetManagedRenderPipelineEnvironmentGenerationStorage(); + GetGraphicsSettingsState().ClearRenderPipelineAssetDescriptor(); } ManagedRenderPipelineAssetDescriptor GetManagedRenderPipelineAssetDescriptor() { - return GetManagedRenderPipelineAssetDescriptorStorage(); + return GetGraphicsSettingsState().GetRenderPipelineAssetDescriptor(); } std::shared_ptr CreateManagedOrDefaultScriptableRenderPipelineAsset() { const ManagedRenderPipelineAssetDescriptor descriptor = - GetManagedRenderPipelineAssetDescriptor(); + GetGraphicsSettingsState().GetRenderPipelineAssetDescriptor(); if (descriptor.IsValid()) { return std::make_shared(descriptor); } diff --git a/engine/src/Rendering/Pipelines/NativeSceneRecorder.cpp b/engine/src/Rendering/Pipelines/NativeSceneRecorder.cpp index ab6b7aa3..e16a36e5 100644 --- a/engine/src/Rendering/Pipelines/NativeSceneRecorder.cpp +++ b/engine/src/Rendering/Pipelines/NativeSceneRecorder.cpp @@ -227,9 +227,19 @@ NativeSceneRecorder::BuildGraphContext() const { BuildRenderGraphRecordingContext( baseRecordingContext, std::move(recordingParams)); - return BuildRenderPipelineStageRenderGraphContext( + RenderPipelineStageRenderGraphContext context = + BuildRenderPipelineStageRenderGraphContext( recordingContext, m_context.stage); + context.finalColorPolicy = + m_context.finalColorPolicy; + context.stageColorSource = + m_context.stageColorSource; + context.usesGraphManagedOutputColor = + m_context.usesGraphManagedOutputColor; + context.directionalShadowPlan = + m_context.directionalShadowPlan; + return context; } } // namespace Pipelines diff --git a/engine/src/Scripting/Mono/MonoScriptRuntime.cpp b/engine/src/Scripting/Mono/MonoScriptRuntime.cpp index c57a1b8f..5a4ab4e9 100644 --- a/engine/src/Scripting/Mono/MonoScriptRuntime.cpp +++ b/engine/src/Scripting/Mono/MonoScriptRuntime.cpp @@ -11,6 +11,7 @@ #include "Input/InputManager.h" #include "Physics/PhysicsWorld.h" #include "Rendering/Execution/CameraFramePlan.h" +#include "Rendering/GraphicsSettingsState.h" #include "Rendering/Internal/RenderPipelineFactory.h" #include "Rendering/Passes/BuiltinVectorFullscreenPass.h" #include "Rendering/Planning/FullscreenPassDesc.h" @@ -149,6 +150,84 @@ void UnregisterManagedScriptableRenderContextState(uint64_t handle) { GetManagedScriptableRenderContextRegistry().erase(handle); } +const Rendering::RenderCameraData& ResolveManagedScriptableRenderContextCameraData( + const ManagedScriptableRenderContextState* state) { + if (state != nullptr && + state->graphContext != nullptr) { + return state->graphContext->sceneData.cameraData; + } + + static const Rendering::RenderCameraData kDefaultCameraData = {}; + return kDefaultCameraData; +} + +const Rendering::RenderLightingData& ResolveManagedScriptableRenderContextLightingData( + const ManagedScriptableRenderContextState* state) { + if (state != nullptr && + state->graphContext != nullptr) { + return state->graphContext->sceneData.lighting; + } + + static const Rendering::RenderLightingData kDefaultLightingData = {}; + return kDefaultLightingData; +} + +const Rendering::RenderEnvironmentData& +ResolveManagedScriptableRenderContextEnvironmentData( + const ManagedScriptableRenderContextState* state) { + if (state != nullptr && + state->graphContext != nullptr) { + return state->graphContext->sceneData.environment; + } + + static const Rendering::RenderEnvironmentData kDefaultEnvironmentData = {}; + return kDefaultEnvironmentData; +} + +const Rendering::ResolvedFinalColorPolicy& +ResolveManagedScriptableRenderContextFinalColorPolicy( + const ManagedScriptableRenderContextState* state) { + if (state != nullptr && + state->graphContext != nullptr) { + return state->graphContext->finalColorPolicy; + } + + static const Rendering::ResolvedFinalColorPolicy + kDefaultFinalColorPolicy = {}; + return kDefaultFinalColorPolicy; +} + +Rendering::CameraFrameColorSource +ResolveManagedScriptableRenderContextStageColorSource( + const ManagedScriptableRenderContextState* state) { + if (state != nullptr && + state->graphContext != nullptr) { + return state->graphContext->stageColorSource; + } + + return Rendering::CameraFrameColorSource::ExplicitSurface; +} + +bool ResolveManagedScriptableRenderContextUsesGraphManagedOutputColor( + const ManagedScriptableRenderContextState* state) { + return state != nullptr && + state->graphContext != nullptr && + state->graphContext->usesGraphManagedOutputColor; +} + +const Rendering::DirectionalShadowRenderPlan& +ResolveManagedScriptableRenderContextDirectionalShadowPlan( + const ManagedScriptableRenderContextState* state) { + if (state != nullptr && + state->graphContext != nullptr) { + return state->graphContext->directionalShadowPlan; + } + + static const Rendering::DirectionalShadowRenderPlan + kDefaultDirectionalShadowPlan = {}; + return kDefaultDirectionalShadowPlan; +} + uint64_t& GetManagedScriptableRenderPipelineCameraRequestContextNextHandle() { static uint64_t nextHandle = 1; return nextHandle; @@ -305,12 +384,12 @@ MonoScriptRuntime* GetActiveMonoScriptRuntime() { void ClearManagedRenderPipelineSelection(MonoScriptRuntime* runtime) { const Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor descriptor = - Rendering::Pipelines::GetManagedRenderPipelineAssetDescriptor(); + Rendering::GetGraphicsSettingsState().GetRenderPipelineAssetDescriptor(); if (runtime != nullptr && descriptor.managedAssetHandle != 0u) { runtime->ReleaseExternalManagedObject(descriptor.managedAssetHandle); } - Rendering::Pipelines::ClearManagedRenderPipelineAssetDescriptor(); + Rendering::GetGraphicsSettingsState().ClearRenderPipelineAssetDescriptor(); } bool TryUnboxManagedBoolean(MonoObject* boxedValue, bool& outValue) { @@ -2731,7 +2810,7 @@ mono_bool InternalCall_Physics_Raycast( void InternalCall_Rendering_SetRenderPipelineAsset(MonoObject* assetObject) { MonoScriptRuntime* const runtime = GetActiveMonoScriptRuntime(); const Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor currentDescriptor = - Rendering::Pipelines::GetManagedRenderPipelineAssetDescriptor(); + Rendering::GetGraphicsSettingsState().GetRenderPipelineAssetDescriptor(); if (assetObject == nullptr) { ClearManagedRenderPipelineSelection(runtime); @@ -2775,7 +2854,8 @@ void InternalCall_Rendering_SetRenderPipelineAsset(MonoObject* assetObject) { currentDescriptor.managedAssetHandle); } - Rendering::Pipelines::SetManagedRenderPipelineAssetDescriptor(descriptor); + Rendering::GetGraphicsSettingsState().SetRenderPipelineAssetDescriptor( + descriptor); } MonoObject* InternalCall_Rendering_GetRenderPipelineAsset() { @@ -2784,13 +2864,21 @@ MonoObject* InternalCall_Rendering_GetRenderPipelineAsset() { return nullptr; } - const Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor descriptor = - Rendering::Pipelines::GetManagedRenderPipelineAssetDescriptor(); - if (!descriptor.IsValid() || - descriptor.managedAssetHandle == 0u) { + Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor descriptor = + Rendering::GetGraphicsSettingsState().GetRenderPipelineAssetDescriptor(); + if (!descriptor.IsValid()) { return nullptr; } + if (descriptor.managedAssetHandle == 0u) { + if (!runtime->TryEnsureManagedRenderPipelineAssetHandle(descriptor)) { + return nullptr; + } + + Rendering::GetGraphicsSettingsState().SetRenderPipelineAssetDescriptor( + descriptor); + } + return runtime->GetExternalManagedObject( descriptor.managedAssetHandle); } @@ -2804,6 +2892,512 @@ int32_t InternalCall_Rendering_ScriptableRenderContext_GetStage( : static_cast(Rendering::CameraFrameStage::MainScene); } +int32_t InternalCall_Rendering_ScriptableRenderContext_GetStageColorSource( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return static_cast( + ResolveManagedScriptableRenderContextStageColorSource(state)); +} + +mono_bool +InternalCall_Rendering_ScriptableRenderContext_GetStageUsesGraphManagedOutputColor( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextUsesGraphManagedOutputColor( + state) + ? 1 + : 0; +} + +mono_bool +InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowEnabled( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state) + .enabled + ? 1 + : 0; +} + +void InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowViewProjection( + uint64_t nativeHandle, + XCEngine::Math::Matrix4x4* outViewProjection) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + *outViewProjection = + ResolveManagedScriptableRenderContextDirectionalShadowPlan(state) + .cameraData.viewProjection; +} + +float InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowOrthographicHalfExtent( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state) + .orthographicHalfExtent; +} + +float InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowNearClipPlane( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state) + .nearClipPlane; +} + +float InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowFarClipPlane( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state) + .farClipPlane; +} + +int32_t InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowMapWidth( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return static_cast( + ResolveManagedScriptableRenderContextDirectionalShadowPlan(state) + .mapWidth); +} + +int32_t InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowMapHeight( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return static_cast( + ResolveManagedScriptableRenderContextDirectionalShadowPlan(state) + .mapHeight); +} + +float InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowWorldTexelSize( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state) + .texelWorldSize; +} + +float InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowReceiverDepthBias( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state) + .sampling.receiverDepthBias; +} + +float InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowNormalBiasScale( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state) + .sampling.normalBiasScale; +} + +float InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowStrength( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state) + .sampling.shadowStrength; +} + +float InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowDepthBiasFactor( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state) + .casterBias.depthBiasFactor; +} + +int32_t InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowDepthBiasUnits( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextDirectionalShadowPlan(state) + .casterBias.depthBiasUnits; +} + +void InternalCall_Rendering_ScriptableRenderContext_GetCameraView( + uint64_t nativeHandle, + XCEngine::Math::Matrix4x4* outView) { + if (outView == nullptr) { + return; + } + + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + *outView = + ResolveManagedScriptableRenderContextCameraData(state).view; +} + +void InternalCall_Rendering_ScriptableRenderContext_GetCameraProjection( + uint64_t nativeHandle, + XCEngine::Math::Matrix4x4* outProjection) { + if (outProjection == nullptr) { + return; + } + + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + *outProjection = + ResolveManagedScriptableRenderContextCameraData(state).projection; +} + +void InternalCall_Rendering_ScriptableRenderContext_GetCameraViewProjection( + uint64_t nativeHandle, + XCEngine::Math::Matrix4x4* outViewProjection) { + if (outViewProjection == nullptr) { + return; + } + + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + *outViewProjection = + ResolveManagedScriptableRenderContextCameraData(state).viewProjection; +} + +void InternalCall_Rendering_ScriptableRenderContext_GetCameraWorldPosition( + uint64_t nativeHandle, + XCEngine::Math::Vector3* outWorldPosition) { + if (outWorldPosition == nullptr) { + return; + } + + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + *outWorldPosition = + ResolveManagedScriptableRenderContextCameraData(state).worldPosition; +} + +void InternalCall_Rendering_ScriptableRenderContext_GetCameraWorldRight( + uint64_t nativeHandle, + XCEngine::Math::Vector3* outWorldRight) { + if (outWorldRight == nullptr) { + return; + } + + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + *outWorldRight = + ResolveManagedScriptableRenderContextCameraData(state).worldRight; +} + +void InternalCall_Rendering_ScriptableRenderContext_GetCameraWorldUp( + uint64_t nativeHandle, + XCEngine::Math::Vector3* outWorldUp) { + if (outWorldUp == nullptr) { + return; + } + + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + *outWorldUp = + ResolveManagedScriptableRenderContextCameraData(state).worldUp; +} + +void InternalCall_Rendering_ScriptableRenderContext_GetCameraWorldForward( + uint64_t nativeHandle, + XCEngine::Math::Vector3* outWorldForward) { + if (outWorldForward == nullptr) { + return; + } + + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + *outWorldForward = + ResolveManagedScriptableRenderContextCameraData(state).worldForward; +} + +void InternalCall_Rendering_ScriptableRenderContext_GetCameraClearColor( + uint64_t nativeHandle, + XCEngine::Math::Color* outClearColor) { + if (outClearColor == nullptr) { + return; + } + + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + *outClearColor = + ResolveManagedScriptableRenderContextCameraData(state).clearColor; +} + +int32_t InternalCall_Rendering_ScriptableRenderContext_GetCameraClearFlags( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return static_cast( + ResolveManagedScriptableRenderContextCameraData(state).clearFlags); +} + +mono_bool +InternalCall_Rendering_ScriptableRenderContext_GetCameraPerspectiveProjection( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextCameraData(state) + .perspectiveProjection + ? 1 + : 0; +} + +float InternalCall_Rendering_ScriptableRenderContext_GetCameraVerticalFovRadians( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextCameraData(state) + .verticalFovRadians; +} + +float InternalCall_Rendering_ScriptableRenderContext_GetCameraOrthographicSize( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextCameraData(state) + .orthographicSize; +} + +float InternalCall_Rendering_ScriptableRenderContext_GetCameraAspectRatio( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextCameraData(state) + .aspectRatio; +} + +float InternalCall_Rendering_ScriptableRenderContext_GetCameraNearClipPlane( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextCameraData(state) + .nearClipPlane; +} + +float InternalCall_Rendering_ScriptableRenderContext_GetCameraFarClipPlane( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextCameraData(state) + .farClipPlane; +} + +int32_t InternalCall_Rendering_ScriptableRenderContext_GetCameraViewportWidth( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return static_cast( + ResolveManagedScriptableRenderContextCameraData(state).viewportWidth); +} + +int32_t InternalCall_Rendering_ScriptableRenderContext_GetCameraViewportHeight( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return static_cast( + ResolveManagedScriptableRenderContextCameraData(state).viewportHeight); +} + +mono_bool +InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightEnabled( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextLightingData(state) + .mainDirectionalLight.enabled + ? 1 + : 0; +} + +mono_bool +InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightCastsShadows( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextLightingData(state) + .mainDirectionalLight.castsShadows + ? 1 + : 0; +} + +void InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightDirection( + uint64_t nativeHandle, + XCEngine::Math::Vector3* outDirection) { + if (outDirection == nullptr) { + return; + } + + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + *outDirection = ResolveManagedScriptableRenderContextLightingData(state) + .mainDirectionalLight.direction; +} + +void InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightColor( + uint64_t nativeHandle, + XCEngine::Math::Color* outColor) { + if (outColor == nullptr) { + return; + } + + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + *outColor = ResolveManagedScriptableRenderContextLightingData(state) + .mainDirectionalLight.color; +} + +float +InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightIntensity( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextLightingData(state) + .mainDirectionalLight.intensity; +} + +mono_bool +InternalCall_Rendering_ScriptableRenderContext_GetHasMainDirectionalShadow( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextLightingData(state) + .HasMainDirectionalShadow() + ? 1 + : 0; +} + +int32_t InternalCall_Rendering_ScriptableRenderContext_GetAdditionalLightCount( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return static_cast( + ResolveManagedScriptableRenderContextLightingData(state) + .additionalLightCount); +} + +int32_t InternalCall_Rendering_ScriptableRenderContext_GetEnvironmentMode( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return static_cast( + ResolveManagedScriptableRenderContextEnvironmentData(state).mode); +} + +void InternalCall_Rendering_ScriptableRenderContext_GetEnvironmentSkyboxTopColor( + uint64_t nativeHandle, + XCEngine::Math::Color* outColor) { + if (outColor == nullptr) { + return; + } + + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + *outColor = ResolveManagedScriptableRenderContextEnvironmentData(state) + .skybox.topColor; +} + +void InternalCall_Rendering_ScriptableRenderContext_GetEnvironmentSkyboxHorizonColor( + uint64_t nativeHandle, + XCEngine::Math::Color* outColor) { + if (outColor == nullptr) { + return; + } + + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + *outColor = ResolveManagedScriptableRenderContextEnvironmentData(state) + .skybox.horizonColor; +} + +void InternalCall_Rendering_ScriptableRenderContext_GetEnvironmentSkyboxBottomColor( + uint64_t nativeHandle, + XCEngine::Math::Color* outColor) { + if (outColor == nullptr) { + return; + } + + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + *outColor = ResolveManagedScriptableRenderContextEnvironmentData(state) + .skybox.bottomColor; +} + +int32_t +InternalCall_Rendering_ScriptableRenderContext_GetFinalColorOutputTransferMode( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return static_cast( + ResolveManagedScriptableRenderContextFinalColorPolicy(state) + .outputTransferMode); +} + +int32_t +InternalCall_Rendering_ScriptableRenderContext_GetFinalColorExposureMode( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return static_cast( + ResolveManagedScriptableRenderContextFinalColorPolicy(state) + .exposureMode); +} + +float InternalCall_Rendering_ScriptableRenderContext_GetFinalColorExposureValue( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextFinalColorPolicy(state) + .exposureValue; +} + +int32_t +InternalCall_Rendering_ScriptableRenderContext_GetFinalColorToneMappingMode( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return static_cast( + ResolveManagedScriptableRenderContextFinalColorPolicy(state) + .toneMappingMode); +} + +void InternalCall_Rendering_ScriptableRenderContext_GetFinalColorScale( + uint64_t nativeHandle, + XCEngine::Math::Vector4* outScale) { + if (outScale == nullptr) { + return; + } + + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + *outScale = ResolveManagedScriptableRenderContextFinalColorPolicy(state) + .finalColorScale; +} + +mono_bool +InternalCall_Rendering_ScriptableRenderContext_GetFinalColorHasPipelineDefaults( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextFinalColorPolicy(state) + .hasPipelineDefaults + ? 1 + : 0; +} + +mono_bool +InternalCall_Rendering_ScriptableRenderContext_GetFinalColorHasCameraOverrides( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return ResolveManagedScriptableRenderContextFinalColorPolicy(state) + .hasCameraOverrides + ? 1 + : 0; +} + mono_bool InternalCall_Rendering_ScriptableRenderContext_RecordScene( uint64_t nativeHandle) { ManagedScriptableRenderContextState* const state = @@ -3115,6 +3709,56 @@ void RegisterInternalCalls() { mono_add_internal_call("XCEngine.InternalCalls::Rendering_SetRenderPipelineAsset", reinterpret_cast(&InternalCall_Rendering_SetRenderPipelineAsset)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_GetRenderPipelineAsset", reinterpret_cast(&InternalCall_Rendering_GetRenderPipelineAsset)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetStage", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetStage)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetStageColorSource", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetStageColorSource)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetStageUsesGraphManagedOutputColor", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetStageUsesGraphManagedOutputColor)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowEnabled", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowEnabled)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowViewProjection", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowViewProjection)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowOrthographicHalfExtent", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowOrthographicHalfExtent)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowNearClipPlane", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowNearClipPlane)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowFarClipPlane", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowFarClipPlane)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowMapWidth", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowMapWidth)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowMapHeight", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowMapHeight)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowWorldTexelSize", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowWorldTexelSize)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowReceiverDepthBias", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowReceiverDepthBias)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowNormalBiasScale", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowNormalBiasScale)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowStrength", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowStrength)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowDepthBiasFactor", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowDepthBiasFactor)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalShadowDepthBiasUnits", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalShadowDepthBiasUnits)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraView", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetCameraView)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraProjection", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetCameraProjection)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraViewProjection", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetCameraViewProjection)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraWorldPosition", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetCameraWorldPosition)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraWorldRight", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetCameraWorldRight)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraWorldUp", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetCameraWorldUp)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraWorldForward", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetCameraWorldForward)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraClearColor", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetCameraClearColor)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraClearFlags", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetCameraClearFlags)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraPerspectiveProjection", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetCameraPerspectiveProjection)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraVerticalFovRadians", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetCameraVerticalFovRadians)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraOrthographicSize", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetCameraOrthographicSize)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraAspectRatio", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetCameraAspectRatio)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraNearClipPlane", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetCameraNearClipPlane)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraFarClipPlane", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetCameraFarClipPlane)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraViewportWidth", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetCameraViewportWidth)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetCameraViewportHeight", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetCameraViewportHeight)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalLightEnabled", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightEnabled)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalLightCastsShadows", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightCastsShadows)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalLightDirection", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightDirection)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalLightColor", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightColor)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetMainDirectionalLightIntensity", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetMainDirectionalLightIntensity)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetHasMainDirectionalShadow", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetHasMainDirectionalShadow)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetAdditionalLightCount", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetAdditionalLightCount)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetEnvironmentMode", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetEnvironmentMode)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetEnvironmentSkyboxTopColor", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetEnvironmentSkyboxTopColor)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetEnvironmentSkyboxHorizonColor", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetEnvironmentSkyboxHorizonColor)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetEnvironmentSkyboxBottomColor", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetEnvironmentSkyboxBottomColor)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetFinalColorOutputTransferMode", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetFinalColorOutputTransferMode)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetFinalColorExposureMode", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetFinalColorExposureMode)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetFinalColorExposureValue", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetFinalColorExposureValue)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetFinalColorToneMappingMode", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetFinalColorToneMappingMode)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetFinalColorScale", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetFinalColorScale)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetFinalColorHasPipelineDefaults", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetFinalColorHasPipelineDefaults)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetFinalColorHasCameraOverrides", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetFinalColorHasCameraOverrides)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_RecordScene", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_RecordScene)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_RecordScenePhase", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_RecordScenePhase)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_RecordSceneInjectionPoint", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_RecordSceneInjectionPoint)); @@ -3260,6 +3904,30 @@ bool MonoScriptRuntime::TryGetAvailableScriptClasses( return true; } +bool MonoScriptRuntime::TryGetAvailableRenderPipelineAssetClasses( + std::vector& outClasses) const { + outClasses.clear(); + if (!m_initialized) { + return false; + } + + outClasses = m_renderPipelineAssetClasses; + std::sort( + outClasses.begin(), + outClasses.end(), + [](const ScriptClassDescriptor& lhs, const ScriptClassDescriptor& rhs) { + if (lhs.assemblyName != rhs.assemblyName) { + return lhs.assemblyName < rhs.assemblyName; + } + if (lhs.namespaceName != rhs.namespaceName) { + return lhs.namespaceName < rhs.namespaceName; + } + return lhs.className < rhs.className; + }); + + return true; +} + std::vector MonoScriptRuntime::GetScriptClassNames(const std::string& assemblyName) const { std::vector classes; if (!TryGetAvailableScriptClasses(classes)) { @@ -3898,6 +4566,9 @@ bool MonoScriptRuntime::DiscoverScriptClasses() { } DiscoverScriptClassesInImage(m_settings.appAssemblyName, m_appImage); + DiscoverRenderPipelineAssetClassesInImage( + m_settings.appAssemblyName, + m_appImage); return true; } @@ -3972,6 +4643,38 @@ void MonoScriptRuntime::DiscoverScriptClassesInImage(const std::string& assembly } } +void MonoScriptRuntime::DiscoverRenderPipelineAssetClassesInImage( + const std::string& assemblyName, + MonoImage* image) { + if (!image || m_scriptableRenderPipelineAssetClass == nullptr) { + return; + } + + const int typeCount = mono_image_get_table_rows(image, MONO_TABLE_TYPEDEF); + for (int index = 1; index <= typeCount; ++index) { + const uint32_t typeToken = + mono_metadata_make_token(MONO_TABLE_TYPEDEF, index); + MonoClass* monoClass = mono_class_get(image, typeToken); + if (monoClass == nullptr || + monoClass == m_scriptableRenderPipelineAssetClass || + !IsMonoClassOrSubclass( + monoClass, + m_scriptableRenderPipelineAssetClass)) { + continue; + } + + if ((mono_class_get_flags(monoClass) & MONO_TYPE_ATTR_ABSTRACT) != 0) { + continue; + } + + m_renderPipelineAssetClasses.push_back( + ScriptClassDescriptor{ + assemblyName, + SafeString(mono_class_get_namespace(monoClass)), + SafeString(mono_class_get_name(monoClass))}); + } +} + bool MonoScriptRuntime::IsMonoBehaviourSubclass(MonoClass* monoClass) const { if (!monoClass || !m_monoBehaviourClass || monoClass == m_monoBehaviourClass) { return false; @@ -4302,6 +5005,45 @@ bool MonoScriptRuntime::IsScriptableRenderPipelineAssetObject( m_scriptableRenderPipelineAssetClass); } +bool MonoScriptRuntime::TryEnsureManagedRenderPipelineAssetHandle( + Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor& ioDescriptor) { + if (!m_initialized || !ioDescriptor.IsValid()) { + return false; + } + + if (ioDescriptor.managedAssetHandle != 0u) { + MonoObject* const assetObject = + GetExternalManagedObject(ioDescriptor.managedAssetHandle); + if (IsScriptableRenderPipelineAssetObject(assetObject)) { + return true; + } + + ioDescriptor.managedAssetHandle = 0u; + } + + MonoClass* assetClass = nullptr; + if (!ResolveManagedClass( + ioDescriptor.assemblyName, + ioDescriptor.namespaceName, + ioDescriptor.className, + assetClass) || + assetClass == nullptr) { + return false; + } + + if (!IsMonoClassOrSubclass( + assetClass, + m_scriptableRenderPipelineAssetClass)) { + SetError( + "Managed render pipeline asset must derive from ScriptableRenderPipelineAsset: " + + ioDescriptor.GetFullName() + "."); + return false; + } + + return CreateExternalManagedObject(assetClass, ioDescriptor.managedAssetHandle) && + ioDescriptor.managedAssetHandle != 0u; +} + void MonoScriptRuntime::DestroyExternalManagedObject(uint32_t gcHandle) { if (gcHandle == 0) { return; @@ -4483,10 +5225,20 @@ MonoMethod* MonoScriptRuntime::ResolveManagedMethod( } SetCurrentDomain(); - return mono_class_get_method_from_name( - monoClass, - methodName, - parameterCount); + for (MonoClass* currentClass = monoClass; + currentClass != nullptr; + currentClass = mono_class_get_parent(currentClass)) { + if (MonoMethod* const method = + mono_class_get_method_from_name( + currentClass, + methodName, + parameterCount); + method != nullptr) { + return method; + } + } + + return nullptr; } MonoMethod* MonoScriptRuntime::ResolveManagedMethod( @@ -5118,6 +5870,7 @@ void MonoScriptRuntime::ClearExternalManagedObjects() { void MonoScriptRuntime::ClearClassCache() { m_classes.clear(); + m_renderPipelineAssetClasses.clear(); } bool MonoScriptRuntime::InvokeManagedMethod( diff --git a/engine/src/Scripting/NullScriptRuntime.cpp b/engine/src/Scripting/NullScriptRuntime.cpp index c07c9ab5..72fe35c9 100644 --- a/engine/src/Scripting/NullScriptRuntime.cpp +++ b/engine/src/Scripting/NullScriptRuntime.cpp @@ -17,6 +17,12 @@ bool NullScriptRuntime::TryGetAvailableScriptClasses( return false; } +bool NullScriptRuntime::TryGetAvailableRenderPipelineAssetClasses( + std::vector& outClasses) const { + outClasses.clear(); + return false; +} + bool NullScriptRuntime::TryGetClassFieldMetadata( const std::string& assemblyName, const std::string& namespaceName, diff --git a/engine/src/Scripting/ScriptEngine.cpp b/engine/src/Scripting/ScriptEngine.cpp index 4d38745d..2d55211d 100644 --- a/engine/src/Scripting/ScriptEngine.cpp +++ b/engine/src/Scripting/ScriptEngine.cpp @@ -11,6 +11,38 @@ namespace Scripting { namespace { +void FilterAndSortScriptClasses( + const std::vector& runtimeClasses, + std::vector& outClasses, + const std::string& assemblyName) { + outClasses.clear(); + outClasses.reserve(runtimeClasses.size()); + for (const ScriptClassDescriptor& descriptor : runtimeClasses) { + if (!assemblyName.empty() && descriptor.assemblyName != assemblyName) { + continue; + } + + if (descriptor.className.empty()) { + continue; + } + + outClasses.push_back(descriptor); + } + + std::sort( + outClasses.begin(), + outClasses.end(), + [](const ScriptClassDescriptor& lhs, const ScriptClassDescriptor& rhs) { + if (lhs.assemblyName != rhs.assemblyName) { + return lhs.assemblyName < rhs.assemblyName; + } + if (lhs.namespaceName != rhs.namespaceName) { + return lhs.namespaceName < rhs.namespaceName; + } + return lhs.className < rhs.className; + }); +} + std::unordered_map CollectClassDefaultValues( const IScriptRuntime* runtime, const ScriptComponent* component, @@ -371,39 +403,26 @@ bool ScriptEngine::HasRuntimeInstance(const ScriptComponent* component) const { bool ScriptEngine::TryGetAvailableScriptClasses( std::vector& outClasses, const std::string& assemblyName) const { - outClasses.clear(); - std::vector runtimeClasses; if (!m_runtime->TryGetAvailableScriptClasses(runtimeClasses)) { + outClasses.clear(); return false; } - outClasses.reserve(runtimeClasses.size()); - for (const ScriptClassDescriptor& descriptor : runtimeClasses) { - if (!assemblyName.empty() && descriptor.assemblyName != assemblyName) { - continue; - } + FilterAndSortScriptClasses(runtimeClasses, outClasses, assemblyName); + return true; +} - if (descriptor.className.empty()) { - continue; - } - - outClasses.push_back(descriptor); +bool ScriptEngine::TryGetAvailableRenderPipelineAssetClasses( + std::vector& outClasses, + const std::string& assemblyName) const { + std::vector runtimeClasses; + if (!m_runtime->TryGetAvailableRenderPipelineAssetClasses(runtimeClasses)) { + outClasses.clear(); + return false; } - std::sort( - outClasses.begin(), - outClasses.end(), - [](const ScriptClassDescriptor& lhs, const ScriptClassDescriptor& rhs) { - if (lhs.assemblyName != rhs.assemblyName) { - return lhs.assemblyName < rhs.assemblyName; - } - if (lhs.namespaceName != rhs.namespaceName) { - return lhs.namespaceName < rhs.namespaceName; - } - return lhs.className < rhs.className; - }); - + FilterAndSortScriptClasses(runtimeClasses, outClasses, assemblyName); return true; } diff --git a/managed/CMakeLists.txt b/managed/CMakeLists.txt index 57e7215d..81578a32 100644 --- a/managed/CMakeLists.txt +++ b/managed/CMakeLists.txt @@ -101,41 +101,65 @@ endforeach() set(XCENGINE_SCRIPT_CORE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Behaviour.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Camera.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/CameraData.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/CameraFrameColorSource.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/CameraFrameStage.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Color.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ColorScalePostProcessRendererFeature.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Component.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Debug.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/DisableDirectionalShadowRendererFeature.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/DirectionalLightData.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/DirectionalShadowData.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/FinalColorExposureMode.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/FinalColorData.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/FinalColorOutputTransferMode.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/FinalColorSettings.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/FinalColorToneMappingMode.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ForceMode.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ForwardRenderer.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ForwardRendererData.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ForwardRenderPipelineAsset.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/FullscreenPassDescriptor.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/EnvironmentData.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/GraphicsSettings.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/GameObject.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Input.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/InternalCalls.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/KeyCode.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Light.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/LightingData.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/MeshFilter.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/MeshRenderer.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Matrix4x4.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/MonoBehaviour.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Object.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Physics.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/PhysicsBodyType.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Quaternion.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/RaycastHit.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/RenderPassEvent.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/RenderPipelineAsset.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/RenderClearFlags.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/RenderEnvironmentMode.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/RendererDrivenRenderPipeline.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/RenderingData.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ScenePhase.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/SceneRenderInjectionPoint.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ShadowData.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ScriptableRenderPass.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ScriptableRenderPipeline.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ScriptableRenderPipelineAsset.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ScriptableRenderPipelineCameraRequestContext.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ScriptableRenderPipelinePlanningContext.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ScriptableRenderContext.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ScriptableRenderer.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ScriptableRendererData.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ScriptableRendererFeature.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rigidbody.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/SerializeField.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Space.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/StageColorData.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Time.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Transform.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Vector2.cs diff --git a/managed/GameScripts/RenderPipelineApiProbe.cs b/managed/GameScripts/RenderPipelineApiProbe.cs index 4d679763..ffc835fe 100644 --- a/managed/GameScripts/RenderPipelineApiProbe.cs +++ b/managed/GameScripts/RenderPipelineApiProbe.cs @@ -1,3 +1,4 @@ +using System; using XCEngine; namespace Gameplay @@ -8,6 +9,712 @@ namespace Gameplay "builtin://shaders/color-scale-post-process"; } + internal static class ProbeFinalColorSettingsFactory + { + public static FinalColorSettings Create() + { + FinalColorSettings settings = + FinalColorSettings.CreateDefault(); + settings.outputTransferMode = + FinalColorOutputTransferMode.LinearToSRGB; + settings.exposureMode = + FinalColorExposureMode.Fixed; + settings.exposureValue = 1.75f; + settings.toneMappingMode = + FinalColorToneMappingMode.ACES; + settings.finalColorScale = + new Vector4(0.90f, 1.10f, 1.20f, 1.0f); + return settings; + } + } + + internal sealed class SceneInjectionPass : ScriptableRenderPass + { + private readonly SceneRenderInjectionPoint m_injectionPoint; + + public SceneInjectionPass( + RenderPassEvent passEvent, + SceneRenderInjectionPoint injectionPoint) + { + renderPassEvent = passEvent; + m_injectionPoint = injectionPoint; + } + + protected override bool RecordRenderGraph( + ScriptableRenderContext context, + RenderingData renderingData) + { + return context != null && + renderingData != null && + renderingData.isMainSceneStage && + context.RecordSceneInjectionPoint(m_injectionPoint); + } + } + + internal sealed class ScenePhasePass : ScriptableRenderPass + { + private readonly ScenePhase m_scenePhase; + private readonly Action m_onRecorded; + + public ScenePhasePass( + RenderPassEvent passEvent, + ScenePhase scenePhase, + Action onRecorded = null) + { + renderPassEvent = passEvent; + m_scenePhase = scenePhase; + m_onRecorded = onRecorded; + } + + protected override bool RecordRenderGraph( + ScriptableRenderContext context, + RenderingData renderingData) + { + bool recorded = context != null && + renderingData != null && + renderingData.isMainSceneStage && + context.RecordScenePhase(m_scenePhase); + if (recorded && m_onRecorded != null) + { + m_onRecorded(); + } + + return recorded; + } + } + + internal sealed class FullscreenPass : ScriptableRenderPass + { + private readonly FullscreenPassDescriptor m_descriptor; + + public FullscreenPass( + RenderPassEvent passEvent, + FullscreenPassDescriptor descriptor) + { + renderPassEvent = passEvent; + m_descriptor = descriptor; + } + + protected override bool RecordRenderGraph( + ScriptableRenderContext context, + RenderingData renderingData) + { + return context != null && + renderingData != null && + context.RecordFullscreenPass(m_descriptor); + } + } + + internal sealed class DefaultSceneFeature : ScriptableRendererFeature + { + private readonly SceneInjectionPass m_beforeOpaquePass; + private readonly ScenePhasePass m_opaquePass; + private readonly SceneInjectionPass m_afterOpaquePass; + private readonly SceneInjectionPass m_beforeSkyboxPass; + private readonly ScenePhasePass m_skyboxPass; + private readonly SceneInjectionPass m_afterSkyboxPass; + private readonly SceneInjectionPass m_beforeTransparentPass; + private readonly ScenePhasePass m_transparentPass; + private readonly SceneInjectionPass m_afterTransparentPass; + + public DefaultSceneFeature( + Action onOpaqueRecorded = null) + { + m_beforeOpaquePass = + new SceneInjectionPass( + RenderPassEvent.BeforeRenderingOpaques, + SceneRenderInjectionPoint.BeforeOpaque); + m_opaquePass = + new ScenePhasePass( + RenderPassEvent.RenderOpaques, + ScenePhase.Opaque, + onOpaqueRecorded); + m_afterOpaquePass = + new SceneInjectionPass( + RenderPassEvent.AfterRenderingOpaques, + SceneRenderInjectionPoint.AfterOpaque); + m_beforeSkyboxPass = + new SceneInjectionPass( + RenderPassEvent.BeforeRenderingSkybox, + SceneRenderInjectionPoint.BeforeSkybox); + m_skyboxPass = + new ScenePhasePass( + RenderPassEvent.RenderSkybox, + ScenePhase.Skybox); + m_afterSkyboxPass = + new SceneInjectionPass( + RenderPassEvent.AfterRenderingSkybox, + SceneRenderInjectionPoint.AfterSkybox); + m_beforeTransparentPass = + new SceneInjectionPass( + RenderPassEvent.BeforeRenderingTransparents, + SceneRenderInjectionPoint.BeforeTransparent); + m_transparentPass = + new ScenePhasePass( + RenderPassEvent.RenderTransparents, + ScenePhase.Transparent); + m_afterTransparentPass = + new SceneInjectionPass( + RenderPassEvent.AfterRenderingTransparents, + SceneRenderInjectionPoint.AfterTransparent); + } + + public override void AddRenderPasses( + ScriptableRenderer renderer, + RenderingData renderingData) + { + if (renderer == null || + renderingData == null || + !renderingData.isMainSceneStage) + { + return; + } + + renderer.EnqueuePass(m_beforeOpaquePass); + renderer.EnqueuePass(m_opaquePass); + renderer.EnqueuePass(m_afterOpaquePass); + renderer.EnqueuePass(m_beforeSkyboxPass); + renderer.EnqueuePass(m_skyboxPass); + renderer.EnqueuePass(m_afterSkyboxPass); + renderer.EnqueuePass(m_beforeTransparentPass); + renderer.EnqueuePass(m_transparentPass); + renderer.EnqueuePass(m_afterTransparentPass); + } + } + + internal sealed class FullscreenFeature : ScriptableRendererFeature + { + private readonly ScriptableRenderPass[] m_passes; + + public FullscreenFeature( + params ScriptableRenderPass[] passes) + { + m_passes = passes ?? Array.Empty(); + } + + public override void AddRenderPasses( + ScriptableRenderer renderer, + RenderingData renderingData) + { + if (renderer == null || + renderingData == null) + { + return; + } + + for (int i = 0; i < m_passes.Length; ++i) + { + ScriptableRenderPass renderPass = m_passes[i]; + if (renderPass == null || + !renderPass.SupportsStage(renderingData.stage)) + { + continue; + } + + renderer.EnqueuePass(renderPass); + } + } + } + + internal sealed class ProbeSceneRenderer : ScriptableRenderer + { + public ProbeSceneRenderer( + Action onOpaqueRecorded = null) + { + AddFeature(new DefaultSceneFeature(onOpaqueRecorded)); + } + } + + internal sealed class ProbePostProcessRenderer : ScriptableRenderer + { + public ProbePostProcessRenderer( + FullscreenPassDescriptor firstPass, + FullscreenPassDescriptor secondPass) + { + AddFeature( + new FullscreenFeature( + new FullscreenPass( + RenderPassEvent.BeforeRenderingPostProcessing, + firstPass), + new FullscreenPass( + RenderPassEvent.AfterRenderingPostProcessing, + secondPass))); + } + } + + internal sealed class ProbeForwardRenderer : ScriptableRenderer + { + public ProbeForwardRenderer( + Vector4 postProcessScale, + Action onOpaqueRecorded) + { + AddFeature(new DefaultSceneFeature(onOpaqueRecorded)); + AddFeature( + new FullscreenFeature( + new FullscreenPass( + RenderPassEvent.BeforeRenderingPostProcessing, + FullscreenPassDescriptor.CreateColorScale( + postProcessScale)))); + } + } + + internal sealed class ProbePlannedFullscreenRenderer : ScriptableRenderer + { + public ProbePlannedFullscreenRenderer() + { + FullscreenPassDescriptor descriptor = + FullscreenPassDescriptor.CreateColorScale( + new Vector4(1.05f, 1.0f, 0.95f, 1.0f)); + AddFeature( + new FullscreenFeature( + new FullscreenPass( + RenderPassEvent.BeforeRenderingPostProcessing, + descriptor), + new FullscreenPass( + RenderPassEvent.BeforeRenderingFinalOutput, + descriptor))); + } + } + + internal sealed class CameraDataObservationPass + : ScriptableRenderPass + { + public static Vector4 ObservedViewRow0; + public static Vector4 ObservedViewRow1; + public static Vector4 ObservedViewRow2; + public static Vector4 ObservedViewRow3; + public static Vector4 ObservedProjectionRow0; + public static Vector4 ObservedProjectionRow1; + public static Vector4 ObservedProjectionRow2; + public static Vector4 ObservedProjectionRow3; + public static Vector4 ObservedViewProjectionRow0; + public static Vector4 ObservedViewProjectionRow1; + public static Vector4 ObservedViewProjectionRow2; + public static Vector4 ObservedViewProjectionRow3; + public static Vector3 ObservedWorldPosition; + public static Vector4 ObservedClearColor; + public static int ObservedClearFlags; + public static bool ObservedPerspectiveProjection; + public static float ObservedVerticalFovRadians; + public static float ObservedOrthographicSize; + public static float ObservedAspectRatio; + public static float ObservedNearClipPlane; + public static float ObservedFarClipPlane; + public static int ObservedViewportWidth; + public static int ObservedViewportHeight; + public static bool ObservedMainDirectionalLightEnabled; + public static bool ObservedMainDirectionalLightCastsShadows; + public static Vector3 ObservedMainDirectionalLightDirection; + public static Vector4 ObservedMainDirectionalLightColor; + public static float ObservedMainDirectionalLightIntensity; + public static bool ObservedHasMainDirectionalShadow; + public static int ObservedAdditionalLightCount; + public static bool ObservedShadowEnabled; + public static Vector4 ObservedShadowViewProjectionRow0; + public static Vector4 ObservedShadowViewProjectionRow1; + public static Vector4 ObservedShadowViewProjectionRow2; + public static Vector4 ObservedShadowViewProjectionRow3; + public static float ObservedShadowOrthographicHalfExtent; + public static float ObservedShadowNearClipPlane; + public static float ObservedShadowFarClipPlane; + public static int ObservedShadowMapWidth; + public static int ObservedShadowMapHeight; + public static float ObservedShadowWorldTexelSize; + public static float ObservedShadowReceiverDepthBias; + public static float ObservedShadowNormalBiasScale; + public static float ObservedShadowStrength; + public static float ObservedShadowDepthBiasFactor; + public static int ObservedShadowDepthBiasUnits; + public static int ObservedEnvironmentMode; + public static Vector4 ObservedSkyboxTopColor; + public static Vector4 ObservedSkyboxHorizonColor; + public static Vector4 ObservedSkyboxBottomColor; + public static int ObservedFinalColorOutputTransferMode; + public static int ObservedFinalColorExposureMode; + public static float ObservedFinalColorExposureValue; + public static int ObservedFinalColorToneMappingMode; + public static Vector4 ObservedFinalColorScale; + public static bool ObservedFinalColorHasPipelineDefaults; + public static bool ObservedFinalColorHasCameraOverrides; + public static bool ObservedFinalColorRequiresProcessing; + public static int RecordCallCount; + + public CameraDataObservationPass() + { + renderPassEvent = RenderPassEvent.RenderOpaques; + } + + public static void Reset() + { + ObservedViewRow0 = new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedViewRow1 = new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedViewRow2 = new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedViewRow3 = new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedProjectionRow0 = new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedProjectionRow1 = new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedProjectionRow2 = new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedProjectionRow3 = new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedViewProjectionRow0 = new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedViewProjectionRow1 = new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedViewProjectionRow2 = new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedViewProjectionRow3 = new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedWorldPosition = new Vector3(0.0f, 0.0f, 0.0f); + ObservedClearColor = new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedClearFlags = 0; + ObservedPerspectiveProjection = true; + ObservedVerticalFovRadians = 0.0f; + ObservedOrthographicSize = 0.0f; + ObservedAspectRatio = 0.0f; + ObservedNearClipPlane = 0.0f; + ObservedFarClipPlane = 0.0f; + ObservedViewportWidth = 0; + ObservedViewportHeight = 0; + ObservedMainDirectionalLightEnabled = false; + ObservedMainDirectionalLightCastsShadows = false; + ObservedMainDirectionalLightDirection = + new Vector3(0.0f, 0.0f, 0.0f); + ObservedMainDirectionalLightColor = + new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedMainDirectionalLightIntensity = 0.0f; + ObservedHasMainDirectionalShadow = false; + ObservedAdditionalLightCount = 0; + ObservedShadowEnabled = false; + ObservedShadowViewProjectionRow0 = + new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedShadowViewProjectionRow1 = + new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedShadowViewProjectionRow2 = + new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedShadowViewProjectionRow3 = + new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedShadowOrthographicHalfExtent = 0.0f; + ObservedShadowNearClipPlane = 0.0f; + ObservedShadowFarClipPlane = 0.0f; + ObservedShadowMapWidth = 0; + ObservedShadowMapHeight = 0; + ObservedShadowWorldTexelSize = 0.0f; + ObservedShadowReceiverDepthBias = 0.0f; + ObservedShadowNormalBiasScale = 0.0f; + ObservedShadowStrength = 0.0f; + ObservedShadowDepthBiasFactor = 0.0f; + ObservedShadowDepthBiasUnits = 0; + ObservedEnvironmentMode = 0; + ObservedSkyboxTopColor = + new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedSkyboxHorizonColor = + new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedSkyboxBottomColor = + new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedFinalColorOutputTransferMode = 0; + ObservedFinalColorExposureMode = 0; + ObservedFinalColorExposureValue = 0.0f; + ObservedFinalColorToneMappingMode = 0; + ObservedFinalColorScale = + new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + ObservedFinalColorHasPipelineDefaults = false; + ObservedFinalColorHasCameraOverrides = false; + ObservedFinalColorRequiresProcessing = false; + RecordCallCount = 0; + } + + protected override bool RecordRenderGraph( + ScriptableRenderContext context, + RenderingData renderingData) + { + if (context == null || + renderingData == null || + !renderingData.isMainSceneStage) + { + return false; + } + + CameraData cameraData = renderingData.cameraData; + LightingData lightingData = renderingData.lightingData; + ShadowData shadowData = renderingData.shadowData; + EnvironmentData environmentData = + renderingData.environmentData; + FinalColorData finalColorData = + renderingData.finalColorData; + if (cameraData == null) + { + return false; + } + + ObservedViewRow0 = cameraData.view.GetRow(0); + ObservedViewRow1 = cameraData.view.GetRow(1); + ObservedViewRow2 = cameraData.view.GetRow(2); + ObservedViewRow3 = cameraData.view.GetRow(3); + ObservedProjectionRow0 = + cameraData.projection.GetRow(0); + ObservedProjectionRow1 = + cameraData.projection.GetRow(1); + ObservedProjectionRow2 = + cameraData.projection.GetRow(2); + ObservedProjectionRow3 = + cameraData.projection.GetRow(3); + ObservedViewProjectionRow0 = + cameraData.viewProjection.GetRow(0); + ObservedViewProjectionRow1 = + cameraData.viewProjection.GetRow(1); + ObservedViewProjectionRow2 = + cameraData.viewProjection.GetRow(2); + ObservedViewProjectionRow3 = + cameraData.viewProjection.GetRow(3); + ObservedWorldPosition = cameraData.worldPosition; + ObservedClearColor = new Vector4( + cameraData.clearColor.r, + cameraData.clearColor.g, + cameraData.clearColor.b, + cameraData.clearColor.a); + ObservedClearFlags = (int)cameraData.clearFlags; + ObservedPerspectiveProjection = + cameraData.perspectiveProjection; + ObservedVerticalFovRadians = + cameraData.verticalFovRadians; + ObservedOrthographicSize = + cameraData.orthographicSize; + ObservedAspectRatio = + cameraData.aspectRatio; + ObservedNearClipPlane = + cameraData.nearClipPlane; + ObservedFarClipPlane = + cameraData.farClipPlane; + ObservedViewportWidth = + cameraData.viewportWidth; + ObservedViewportHeight = + cameraData.viewportHeight; + if (lightingData != null && + lightingData.mainDirectionalLight != null) + { + ObservedMainDirectionalLightEnabled = + lightingData.mainDirectionalLight.enabled; + ObservedMainDirectionalLightCastsShadows = + lightingData.mainDirectionalLight.castsShadows; + ObservedMainDirectionalLightDirection = + lightingData.mainDirectionalLight.direction; + ObservedMainDirectionalLightColor = new Vector4( + lightingData.mainDirectionalLight.color.r, + lightingData.mainDirectionalLight.color.g, + lightingData.mainDirectionalLight.color.b, + lightingData.mainDirectionalLight.color.a); + ObservedMainDirectionalLightIntensity = + lightingData.mainDirectionalLight.intensity; + ObservedHasMainDirectionalShadow = + lightingData.hasMainDirectionalShadow; + ObservedAdditionalLightCount = + lightingData.additionalLightCount; + } + if (shadowData != null && + shadowData.mainDirectionalShadow != null) + { + DirectionalShadowData mainDirectionalShadow = + shadowData.mainDirectionalShadow; + ObservedShadowEnabled = + mainDirectionalShadow.enabled; + ObservedShadowViewProjectionRow0 = + mainDirectionalShadow.viewProjection.GetRow(0); + ObservedShadowViewProjectionRow1 = + mainDirectionalShadow.viewProjection.GetRow(1); + ObservedShadowViewProjectionRow2 = + mainDirectionalShadow.viewProjection.GetRow(2); + ObservedShadowViewProjectionRow3 = + mainDirectionalShadow.viewProjection.GetRow(3); + ObservedShadowOrthographicHalfExtent = + mainDirectionalShadow.orthographicHalfExtent; + ObservedShadowNearClipPlane = + mainDirectionalShadow.nearClipPlane; + ObservedShadowFarClipPlane = + mainDirectionalShadow.farClipPlane; + ObservedShadowMapWidth = + mainDirectionalShadow.mapWidth; + ObservedShadowMapHeight = + mainDirectionalShadow.mapHeight; + ObservedShadowWorldTexelSize = + mainDirectionalShadow.worldTexelSize; + ObservedShadowReceiverDepthBias = + mainDirectionalShadow.receiverDepthBias; + ObservedShadowNormalBiasScale = + mainDirectionalShadow.normalBiasScale; + ObservedShadowStrength = + mainDirectionalShadow.shadowStrength; + ObservedShadowDepthBiasFactor = + mainDirectionalShadow.depthBiasFactor; + ObservedShadowDepthBiasUnits = + mainDirectionalShadow.depthBiasUnits; + } + if (environmentData != null) + { + ObservedEnvironmentMode = + (int)environmentData.mode; + ObservedSkyboxTopColor = new Vector4( + environmentData.skyboxTopColor.r, + environmentData.skyboxTopColor.g, + environmentData.skyboxTopColor.b, + environmentData.skyboxTopColor.a); + ObservedSkyboxHorizonColor = new Vector4( + environmentData.skyboxHorizonColor.r, + environmentData.skyboxHorizonColor.g, + environmentData.skyboxHorizonColor.b, + environmentData.skyboxHorizonColor.a); + ObservedSkyboxBottomColor = new Vector4( + environmentData.skyboxBottomColor.r, + environmentData.skyboxBottomColor.g, + environmentData.skyboxBottomColor.b, + environmentData.skyboxBottomColor.a); + } + if (finalColorData != null) + { + ObservedFinalColorOutputTransferMode = + (int)finalColorData.settings.outputTransferMode; + ObservedFinalColorExposureMode = + (int)finalColorData.settings.exposureMode; + ObservedFinalColorExposureValue = + finalColorData.settings.exposureValue; + ObservedFinalColorToneMappingMode = + (int)finalColorData.settings.toneMappingMode; + ObservedFinalColorScale = + finalColorData.settings.finalColorScale; + ObservedFinalColorHasPipelineDefaults = + finalColorData.hasPipelineDefaults; + ObservedFinalColorHasCameraOverrides = + finalColorData.hasCameraOverrides; + ObservedFinalColorRequiresProcessing = + finalColorData.requiresProcessing; + } + RecordCallCount++; + return context.RecordScene(); + } + } + + internal sealed class CameraDataObservationFeature + : ScriptableRendererFeature + { + private readonly CameraDataObservationPass m_pass = + new CameraDataObservationPass(); + + public override void AddRenderPasses( + ScriptableRenderer renderer, + RenderingData renderingData) + { + if (renderer == null || + renderingData == null || + !renderingData.isMainSceneStage) + { + return; + } + + renderer.EnqueuePass(m_pass); + } + } + + internal sealed class CameraDataObservationRenderer + : ScriptableRenderer + { + public CameraDataObservationRenderer() + { + AddFeature(new CameraDataObservationFeature()); + } + } + + internal sealed class StageColorObservationPass + : ScriptableRenderPass + { + public static int ObservedMainSceneSource; + public static bool ObservedMainSceneUsesGraphManagedOutputColor; + public static int ObservedPostProcessSource; + public static bool ObservedPostProcessUsesGraphManagedOutputColor; + public static int ObservedFinalOutputSource; + public static bool ObservedFinalOutputUsesGraphManagedOutputColor; + public static int MainSceneRecordCallCount; + public static int PostProcessRecordCallCount; + public static int FinalOutputRecordCallCount; + + public StageColorObservationPass( + RenderPassEvent passEvent) + { + renderPassEvent = passEvent; + } + + public static void Reset() + { + ObservedMainSceneSource = 0; + ObservedMainSceneUsesGraphManagedOutputColor = false; + ObservedPostProcessSource = 0; + ObservedPostProcessUsesGraphManagedOutputColor = false; + ObservedFinalOutputSource = 0; + ObservedFinalOutputUsesGraphManagedOutputColor = false; + MainSceneRecordCallCount = 0; + PostProcessRecordCallCount = 0; + FinalOutputRecordCallCount = 0; + } + + protected override bool RecordRenderGraph( + ScriptableRenderContext context, + RenderingData renderingData) + { + if (context == null || + renderingData == null) + { + return false; + } + + StageColorData stageColorData = + renderingData.stageColorData; + if (stageColorData == null) + { + return false; + } + + if (renderingData.isMainSceneStage) + { + ObservedMainSceneSource = + (int)stageColorData.source; + ObservedMainSceneUsesGraphManagedOutputColor = + stageColorData.usesGraphManagedOutputColor; + MainSceneRecordCallCount++; + return true; + } + + if (renderingData.isPostProcessStage) + { + ObservedPostProcessSource = + (int)stageColorData.source; + ObservedPostProcessUsesGraphManagedOutputColor = + stageColorData.usesGraphManagedOutputColor; + PostProcessRecordCallCount++; + return true; + } + + if (renderingData.isFinalOutputStage) + { + ObservedFinalOutputSource = + (int)stageColorData.source; + ObservedFinalOutputUsesGraphManagedOutputColor = + stageColorData.usesGraphManagedOutputColor; + FinalOutputRecordCallCount++; + return true; + } + + return false; + } + } + + internal sealed class StageColorObservationRenderer + : ScriptableRenderer + { + public StageColorObservationRenderer() + { + AddFeature( + new FullscreenFeature( + new StageColorObservationPass( + RenderPassEvent.RenderOpaques), + new StageColorObservationPass( + RenderPassEvent.BeforeRenderingPostProcessing), + new StageColorObservationPass( + RenderPassEvent.BeforeRenderingFinalOutput))); + } + } + public sealed class LegacyRenderPipelineApiProbeAsset : RenderPipelineAsset { } @@ -100,6 +807,15 @@ namespace Gameplay } } + public sealed class ManagedRenderContextCameraDataProbeAsset + : ScriptableRenderPipelineAsset + { + protected override ScriptableRenderPipeline CreatePipeline() + { + return new ManagedRenderContextCameraDataProbe(); + } + } + public sealed class ManagedFinalColorRenderPipelineProbeAsset : ScriptableRenderPipelineAsset { @@ -110,13 +826,44 @@ namespace Gameplay protected override FinalColorSettings GetDefaultFinalColorSettings() { - FinalColorSettings settings = FinalColorSettings.CreateDefault(); - settings.outputTransferMode = FinalColorOutputTransferMode.LinearToSRGB; - settings.exposureMode = FinalColorExposureMode.Fixed; - settings.exposureValue = 1.75f; - settings.toneMappingMode = FinalColorToneMappingMode.ACES; - settings.finalColorScale = new Vector4(0.90f, 1.10f, 1.20f, 1.0f); - return settings; + return ProbeFinalColorSettingsFactory.Create(); + } + } + + public sealed class ManagedRenderContextFinalColorDataProbeAsset + : ScriptableRenderPipelineAsset + { + protected override ScriptableRenderPipeline CreatePipeline() + { + return new ManagedRenderContextCameraDataProbe(); + } + + protected override FinalColorSettings GetDefaultFinalColorSettings() + { + return ProbeFinalColorSettingsFactory.Create(); + } + } + + public sealed class ManagedRenderContextStageColorDataProbeAsset + : ScriptableRenderPipelineAsset + { + protected override ScriptableRenderPipeline CreatePipeline() + { + return new ManagedRenderContextStageColorDataProbe(); + } + + protected override void ConfigureCameraFramePlan( + ScriptableRenderPipelinePlanningContext context) + { + context.ClearFullscreenStage(CameraFrameStage.PostProcess); + context.ClearFullscreenStage(CameraFrameStage.FinalOutput); + context.RequestFullscreenStage( + CameraFrameStage.PostProcess, + CameraFrameColorSource.MainSceneColor, + true); + context.RequestFullscreenStage( + CameraFrameStage.FinalOutput, + CameraFrameColorSource.PostProcessColor); } } @@ -125,60 +872,39 @@ namespace Gameplay public static int SupportsStageCallCount; public static int RecordStageCallCount; + protected override ScriptableRenderer CreateRenderer() + { + return new ProbeSceneRenderer(); + } + protected override bool SupportsStageRenderGraph( CameraFrameStage stage) { SupportsStageCallCount++; - return stage == CameraFrameStage.MainScene; + return base.SupportsStageRenderGraph(stage); } protected override bool RecordStageRenderGraph( ScriptableRenderContext context) { RecordStageCallCount++; - return context != null && - context.stage == CameraFrameStage.MainScene && - context.RecordSceneInjectionPoint( - SceneRenderInjectionPoint.BeforeOpaque) && - context.RecordScenePhase(ScenePhase.Opaque) && - context.RecordSceneInjectionPoint( - SceneRenderInjectionPoint.AfterOpaque) && - context.RecordSceneInjectionPoint( - SceneRenderInjectionPoint.BeforeSkybox) && - context.RecordScenePhase(ScenePhase.Skybox) && - context.RecordSceneInjectionPoint( - SceneRenderInjectionPoint.AfterSkybox) && - context.RecordSceneInjectionPoint( - SceneRenderInjectionPoint.BeforeTransparent) && - context.RecordScenePhase(ScenePhase.Transparent) && - context.RecordSceneInjectionPoint( - SceneRenderInjectionPoint.AfterTransparent); + return base.RecordStageRenderGraph(context); } } public sealed class ManagedPostProcessRenderPipelineProbe : ScriptableRenderPipeline { - protected override bool SupportsStageRenderGraph( - CameraFrameStage stage) + protected override ScriptableRenderer CreateRenderer() { - return stage == CameraFrameStage.PostProcess; - } - - protected override bool RecordStageRenderGraph( - ScriptableRenderContext context) - { - return context != null && - context.stage == CameraFrameStage.PostProcess && - context.RecordFullscreenPass( - FullscreenPassDescriptor.CreateShaderVector( - BuiltinShaderPaths.ColorScalePostProcess, - new Vector4(1.10f, 0.95f, 0.90f, 1.0f), - "ColorScale")) && - context.RecordFullscreenPass( - FullscreenPassDescriptor.CreateShaderVector( - BuiltinShaderPaths.ColorScalePostProcess, - new Vector4(0.95f, 1.05f, 1.10f, 1.0f), - "ColorScale")); + return new ProbePostProcessRenderer( + FullscreenPassDescriptor.CreateShaderVector( + BuiltinShaderPaths.ColorScalePostProcess, + new Vector4(1.10f, 0.95f, 0.90f, 1.0f), + "ColorScale"), + FullscreenPassDescriptor.CreateShaderVector( + BuiltinShaderPaths.ColorScalePostProcess, + new Vector4(0.95f, 1.05f, 1.10f, 1.0f), + "ColorScale")); } } @@ -200,22 +926,26 @@ namespace Gameplay m_postProcessScale = postProcessScale; } + protected override ScriptableRenderer CreateRenderer() + { + return new ProbeForwardRenderer( + m_postProcessScale, + OnOpaqueRecorded); + } + protected override bool SupportsStageRenderGraph( CameraFrameStage stage) { if (stage == CameraFrameStage.MainScene) { SupportsMainSceneCallCount++; - return true; } - - if (stage == CameraFrameStage.PostProcess) + else if (stage == CameraFrameStage.PostProcess) { SupportsPostProcessCallCount++; - return true; } - return false; + return base.SupportsStageRenderGraph(stage); } protected override bool RecordStageRenderGraph( @@ -229,47 +959,46 @@ namespace Gameplay if (context.stage == CameraFrameStage.MainScene) { RecordMainSceneCallCount++; - bool recorded = context.RecordScene(); - if (recorded) - { - RecordSceneCallCount++; - } - - return recorded; } - - if (context.stage == CameraFrameStage.PostProcess) + else if (context.stage == CameraFrameStage.PostProcess) { RecordPostProcessCallCount++; LastPostProcessScale = m_postProcessScale; - return context.RecordFullscreenPass( - FullscreenPassDescriptor.CreateColorScale( - m_postProcessScale)); } - return false; + return base.RecordStageRenderGraph(context); + } + + private void OnOpaqueRecorded() + { + RecordSceneCallCount++; } } public sealed class ManagedPlannedFullscreenRenderPipelineProbe : ScriptableRenderPipeline { - protected override bool SupportsStageRenderGraph( - CameraFrameStage stage) + protected override ScriptableRenderer CreateRenderer() { - return stage == CameraFrameStage.PostProcess || - stage == CameraFrameStage.FinalOutput; + return new ProbePlannedFullscreenRenderer(); } + } - protected override bool RecordStageRenderGraph( - ScriptableRenderContext context) + public sealed class ManagedRenderContextCameraDataProbe + : ScriptableRenderPipeline + { + protected override ScriptableRenderer CreateRenderer() { - return context != null && - (context.stage == CameraFrameStage.PostProcess || - context.stage == CameraFrameStage.FinalOutput) && - context.RecordFullscreenPass( - FullscreenPassDescriptor.CreateColorScale( - new Vector4(1.05f, 1.0f, 0.95f, 1.0f))); + return new CameraDataObservationRenderer(); + } + } + + public sealed class ManagedRenderContextStageColorDataProbe + : ScriptableRenderPipeline + { + protected override ScriptableRenderer CreateRenderer() + { + return new StageColorObservationRenderer(); } } @@ -313,6 +1042,133 @@ namespace Gameplay } } + public sealed class ScriptCoreForwardRenderPipelineSelectionProbe + : MonoBehaviour + { + public bool SelectionRoundTripSucceeded; + public string SelectedPipelineAssetTypeName = string.Empty; + public string SelectedRendererDataTypeName = string.Empty; + + public void Start() + { + ForwardRenderPipelineAsset asset = + new ForwardRenderPipelineAsset + { + rendererData = new ForwardRendererData() + }; + GraphicsSettings.renderPipelineAsset = asset; + + ForwardRenderPipelineAsset selectedAsset = + GraphicsSettings.renderPipelineAsset as ForwardRenderPipelineAsset; + SelectionRoundTripSucceeded = + selectedAsset != null; + SelectedPipelineAssetTypeName = + selectedAsset != null + ? selectedAsset.GetType().FullName ?? string.Empty + : string.Empty; + SelectedRendererDataTypeName = + selectedAsset != null && + selectedAsset.rendererData != null + ? selectedAsset.rendererData.GetType().FullName ?? string.Empty + : string.Empty; + } + } + + public sealed class ScriptCoreForwardRenderPipelineRuntimeSelectionProbe + : MonoBehaviour + { + public void Start() + { + GraphicsSettings.renderPipelineAsset = + new ForwardRenderPipelineAsset + { + rendererData = new ForwardRendererData() + }; + } + } + + public sealed class ScriptCoreConfiguredForwardRenderPipelineRuntimeSelectionProbe + : MonoBehaviour + { + public void Start() + { + GraphicsSettings.renderPipelineAsset = + new ForwardRenderPipelineAsset + { + rendererData = new ForwardRendererData + { + renderOpaque = true, + renderSkybox = false, + renderTransparent = false + } + }; + } + } + + public sealed class ScriptCoreForwardPostProcessRendererFeatureRuntimeSelectionProbe + : MonoBehaviour + { + public void Start() + { + GraphicsSettings.renderPipelineAsset = + new ForwardRenderPipelineAsset + { + rendererData = new ForwardRendererData + { + rendererFeatures = + new ScriptableRendererFeature[] + { + new ColorScalePostProcessRendererFeature + { + colorScale = new Vector4( + 1.08f, + 0.96f, + 0.92f, + 1.0f) + } + } + } + }; + } + } + + public sealed class ScriptCoreForwardShadowlessRendererFeatureRuntimeSelectionProbe + : MonoBehaviour + { + public void Start() + { + GraphicsSettings.renderPipelineAsset = + new ForwardRenderPipelineAsset + { + rendererData = new ForwardRendererData + { + rendererFeatures = + new ScriptableRendererFeature[] + { + new DisableDirectionalShadowRendererFeature() + } + } + }; + } + } + + public sealed class ProjectConfiguredRenderPipelineGetterProbe + : MonoBehaviour + { + public bool ObservedAssetWasNull = true; + public string ObservedPipelineAssetTypeName = string.Empty; + + public void Start() + { + ScriptableRenderPipelineAsset asset = + GraphicsSettings.renderPipelineAsset; + ObservedAssetWasNull = asset == null; + ObservedPipelineAssetTypeName = asset != null + ? asset.GetType().FullName ?? string.Empty + : string.Empty; + } + } + public sealed class ManagedForwardRenderPipelineRuntimeSelectionProbe : MonoBehaviour { @@ -359,4 +1215,349 @@ namespace Gameplay ManagedForwardRenderPipelineProbe.LastPostProcessScale; } } + + public sealed class ManagedRenderContextCameraDataRuntimeSelectionProbe + : MonoBehaviour + { + public Vector4 ObservedViewRow0; + public Vector4 ObservedViewRow1; + public Vector4 ObservedViewRow2; + public Vector4 ObservedViewRow3; + public Vector4 ObservedProjectionRow0; + public Vector4 ObservedProjectionRow1; + public Vector4 ObservedProjectionRow2; + public Vector4 ObservedProjectionRow3; + public Vector4 ObservedViewProjectionRow0; + public Vector4 ObservedViewProjectionRow1; + public Vector4 ObservedViewProjectionRow2; + public Vector4 ObservedViewProjectionRow3; + public Vector3 ObservedWorldPosition; + public Vector4 ObservedClearColor; + public int ObservedClearFlags; + public bool ObservedPerspectiveProjection; + public float ObservedVerticalFovRadians; + public float ObservedOrthographicSize; + public float ObservedAspectRatio; + public float ObservedNearClipPlane; + public float ObservedFarClipPlane; + public int ObservedViewportWidth; + public int ObservedViewportHeight; + public int ObservedRecordCallCount; + + public void Start() + { + CameraDataObservationPass.Reset(); + GraphicsSettings.renderPipelineAsset = + new ManagedRenderContextCameraDataProbeAsset(); + } + + public void Update() + { + ObservedViewRow0 = + CameraDataObservationPass.ObservedViewRow0; + ObservedViewRow1 = + CameraDataObservationPass.ObservedViewRow1; + ObservedViewRow2 = + CameraDataObservationPass.ObservedViewRow2; + ObservedViewRow3 = + CameraDataObservationPass.ObservedViewRow3; + ObservedProjectionRow0 = + CameraDataObservationPass.ObservedProjectionRow0; + ObservedProjectionRow1 = + CameraDataObservationPass.ObservedProjectionRow1; + ObservedProjectionRow2 = + CameraDataObservationPass.ObservedProjectionRow2; + ObservedProjectionRow3 = + CameraDataObservationPass.ObservedProjectionRow3; + ObservedViewProjectionRow0 = + CameraDataObservationPass.ObservedViewProjectionRow0; + ObservedViewProjectionRow1 = + CameraDataObservationPass.ObservedViewProjectionRow1; + ObservedViewProjectionRow2 = + CameraDataObservationPass.ObservedViewProjectionRow2; + ObservedViewProjectionRow3 = + CameraDataObservationPass.ObservedViewProjectionRow3; + ObservedWorldPosition = + CameraDataObservationPass.ObservedWorldPosition; + ObservedClearColor = + CameraDataObservationPass.ObservedClearColor; + ObservedClearFlags = + CameraDataObservationPass.ObservedClearFlags; + ObservedPerspectiveProjection = + CameraDataObservationPass.ObservedPerspectiveProjection; + ObservedVerticalFovRadians = + CameraDataObservationPass.ObservedVerticalFovRadians; + ObservedOrthographicSize = + CameraDataObservationPass.ObservedOrthographicSize; + ObservedAspectRatio = + CameraDataObservationPass.ObservedAspectRatio; + ObservedNearClipPlane = + CameraDataObservationPass.ObservedNearClipPlane; + ObservedFarClipPlane = + CameraDataObservationPass.ObservedFarClipPlane; + ObservedViewportWidth = + CameraDataObservationPass.ObservedViewportWidth; + ObservedViewportHeight = + CameraDataObservationPass.ObservedViewportHeight; + ObservedRecordCallCount = + CameraDataObservationPass.RecordCallCount; + } + } + + public sealed class ManagedRenderContextLightingDataRuntimeSelectionProbe + : MonoBehaviour + { + public bool ObservedMainDirectionalLightEnabled; + public bool ObservedMainDirectionalLightCastsShadows; + public Vector3 ObservedMainDirectionalLightDirection; + public Vector4 ObservedMainDirectionalLightColor; + public float ObservedMainDirectionalLightIntensity; + public bool ObservedHasMainDirectionalShadow; + public int ObservedAdditionalLightCount; + public int ObservedRecordCallCount; + + public void Start() + { + CameraDataObservationPass.Reset(); + GraphicsSettings.renderPipelineAsset = + new ManagedRenderContextCameraDataProbeAsset(); + } + + public void Update() + { + ObservedMainDirectionalLightEnabled = + CameraDataObservationPass + .ObservedMainDirectionalLightEnabled; + ObservedMainDirectionalLightCastsShadows = + CameraDataObservationPass + .ObservedMainDirectionalLightCastsShadows; + ObservedMainDirectionalLightDirection = + CameraDataObservationPass + .ObservedMainDirectionalLightDirection; + ObservedMainDirectionalLightColor = + CameraDataObservationPass + .ObservedMainDirectionalLightColor; + ObservedMainDirectionalLightIntensity = + CameraDataObservationPass + .ObservedMainDirectionalLightIntensity; + ObservedHasMainDirectionalShadow = + CameraDataObservationPass + .ObservedHasMainDirectionalShadow; + ObservedAdditionalLightCount = + CameraDataObservationPass + .ObservedAdditionalLightCount; + ObservedRecordCallCount = + CameraDataObservationPass.RecordCallCount; + } + } + + public sealed class ManagedRenderContextEnvironmentDataRuntimeSelectionProbe + : MonoBehaviour + { + public int ObservedEnvironmentMode; + public Vector4 ObservedSkyboxTopColor; + public Vector4 ObservedSkyboxHorizonColor; + public Vector4 ObservedSkyboxBottomColor; + public int ObservedRecordCallCount; + + public void Start() + { + CameraDataObservationPass.Reset(); + GraphicsSettings.renderPipelineAsset = + new ManagedRenderContextCameraDataProbeAsset(); + } + + public void Update() + { + ObservedEnvironmentMode = + CameraDataObservationPass.ObservedEnvironmentMode; + ObservedSkyboxTopColor = + CameraDataObservationPass.ObservedSkyboxTopColor; + ObservedSkyboxHorizonColor = + CameraDataObservationPass.ObservedSkyboxHorizonColor; + ObservedSkyboxBottomColor = + CameraDataObservationPass.ObservedSkyboxBottomColor; + ObservedRecordCallCount = + CameraDataObservationPass.RecordCallCount; + } + } + + public sealed class ManagedRenderContextShadowDataRuntimeSelectionProbe + : MonoBehaviour + { + public bool ObservedShadowEnabled; + public Vector4 ObservedShadowViewProjectionRow0; + public Vector4 ObservedShadowViewProjectionRow1; + public Vector4 ObservedShadowViewProjectionRow2; + public Vector4 ObservedShadowViewProjectionRow3; + public float ObservedShadowOrthographicHalfExtent; + public float ObservedShadowNearClipPlane; + public float ObservedShadowFarClipPlane; + public int ObservedShadowMapWidth; + public int ObservedShadowMapHeight; + public float ObservedShadowWorldTexelSize; + public float ObservedShadowReceiverDepthBias; + public float ObservedShadowNormalBiasScale; + public float ObservedShadowStrength; + public float ObservedShadowDepthBiasFactor; + public int ObservedShadowDepthBiasUnits; + public int ObservedRecordCallCount; + + public void Start() + { + CameraDataObservationPass.Reset(); + GraphicsSettings.renderPipelineAsset = + new ManagedRenderContextCameraDataProbeAsset(); + } + + public void Update() + { + ObservedShadowEnabled = + CameraDataObservationPass.ObservedShadowEnabled; + ObservedShadowViewProjectionRow0 = + CameraDataObservationPass + .ObservedShadowViewProjectionRow0; + ObservedShadowViewProjectionRow1 = + CameraDataObservationPass + .ObservedShadowViewProjectionRow1; + ObservedShadowViewProjectionRow2 = + CameraDataObservationPass + .ObservedShadowViewProjectionRow2; + ObservedShadowViewProjectionRow3 = + CameraDataObservationPass + .ObservedShadowViewProjectionRow3; + ObservedShadowOrthographicHalfExtent = + CameraDataObservationPass + .ObservedShadowOrthographicHalfExtent; + ObservedShadowNearClipPlane = + CameraDataObservationPass + .ObservedShadowNearClipPlane; + ObservedShadowFarClipPlane = + CameraDataObservationPass + .ObservedShadowFarClipPlane; + ObservedShadowMapWidth = + CameraDataObservationPass + .ObservedShadowMapWidth; + ObservedShadowMapHeight = + CameraDataObservationPass + .ObservedShadowMapHeight; + ObservedShadowWorldTexelSize = + CameraDataObservationPass + .ObservedShadowWorldTexelSize; + ObservedShadowReceiverDepthBias = + CameraDataObservationPass + .ObservedShadowReceiverDepthBias; + ObservedShadowNormalBiasScale = + CameraDataObservationPass + .ObservedShadowNormalBiasScale; + ObservedShadowStrength = + CameraDataObservationPass + .ObservedShadowStrength; + ObservedShadowDepthBiasFactor = + CameraDataObservationPass + .ObservedShadowDepthBiasFactor; + ObservedShadowDepthBiasUnits = + CameraDataObservationPass + .ObservedShadowDepthBiasUnits; + ObservedRecordCallCount = + CameraDataObservationPass.RecordCallCount; + } + } + + public sealed class ManagedRenderContextFinalColorDataRuntimeSelectionProbe + : MonoBehaviour + { + public int ObservedFinalColorOutputTransferMode; + public int ObservedFinalColorExposureMode; + public float ObservedFinalColorExposureValue; + public int ObservedFinalColorToneMappingMode; + public Vector4 ObservedFinalColorScale; + public bool ObservedFinalColorHasPipelineDefaults; + public bool ObservedFinalColorHasCameraOverrides; + public bool ObservedFinalColorRequiresProcessing; + public int ObservedRecordCallCount; + + public void Start() + { + CameraDataObservationPass.Reset(); + GraphicsSettings.renderPipelineAsset = + new ManagedRenderContextFinalColorDataProbeAsset(); + } + + public void Update() + { + ObservedFinalColorOutputTransferMode = + CameraDataObservationPass + .ObservedFinalColorOutputTransferMode; + ObservedFinalColorExposureMode = + CameraDataObservationPass + .ObservedFinalColorExposureMode; + ObservedFinalColorExposureValue = + CameraDataObservationPass + .ObservedFinalColorExposureValue; + ObservedFinalColorToneMappingMode = + CameraDataObservationPass + .ObservedFinalColorToneMappingMode; + ObservedFinalColorScale = + CameraDataObservationPass + .ObservedFinalColorScale; + ObservedFinalColorHasPipelineDefaults = + CameraDataObservationPass + .ObservedFinalColorHasPipelineDefaults; + ObservedFinalColorHasCameraOverrides = + CameraDataObservationPass + .ObservedFinalColorHasCameraOverrides; + ObservedFinalColorRequiresProcessing = + CameraDataObservationPass + .ObservedFinalColorRequiresProcessing; + ObservedRecordCallCount = + CameraDataObservationPass.RecordCallCount; + } + } + + public sealed class ManagedRenderContextStageColorDataRuntimeSelectionProbe + : MonoBehaviour + { + public int ObservedMainSceneSource; + public bool ObservedMainSceneUsesGraphManagedOutputColor; + public int ObservedPostProcessSource; + public bool ObservedPostProcessUsesGraphManagedOutputColor; + public int ObservedFinalOutputSource; + public bool ObservedFinalOutputUsesGraphManagedOutputColor; + public int ObservedMainSceneRecordCallCount; + public int ObservedPostProcessRecordCallCount; + public int ObservedFinalOutputRecordCallCount; + + public void Start() + { + StageColorObservationPass.Reset(); + GraphicsSettings.renderPipelineAsset = + new ManagedRenderContextStageColorDataProbeAsset(); + } + + public void Update() + { + ObservedMainSceneSource = + StageColorObservationPass.ObservedMainSceneSource; + ObservedMainSceneUsesGraphManagedOutputColor = + StageColorObservationPass + .ObservedMainSceneUsesGraphManagedOutputColor; + ObservedPostProcessSource = + StageColorObservationPass.ObservedPostProcessSource; + ObservedPostProcessUsesGraphManagedOutputColor = + StageColorObservationPass + .ObservedPostProcessUsesGraphManagedOutputColor; + ObservedFinalOutputSource = + StageColorObservationPass.ObservedFinalOutputSource; + ObservedFinalOutputUsesGraphManagedOutputColor = + StageColorObservationPass + .ObservedFinalOutputUsesGraphManagedOutputColor; + ObservedMainSceneRecordCallCount = + StageColorObservationPass.MainSceneRecordCallCount; + ObservedPostProcessRecordCallCount = + StageColorObservationPass.PostProcessRecordCallCount; + ObservedFinalOutputRecordCallCount = + StageColorObservationPass.FinalOutputRecordCallCount; + } + } } diff --git a/managed/XCEngine.ScriptCore/CameraData.cs b/managed/XCEngine.ScriptCore/CameraData.cs new file mode 100644 index 00000000..aa7f308a --- /dev/null +++ b/managed/XCEngine.ScriptCore/CameraData.cs @@ -0,0 +1,109 @@ +namespace XCEngine +{ + public sealed class CameraData + { + internal static readonly CameraData Default = + new CameraData( + Matrix4x4.Identity, + Matrix4x4.Identity, + Matrix4x4.Identity, + new Vector3(0.0f, 0.0f, 0.0f), + new Vector3(1.0f, 0.0f, 0.0f), + new Vector3(0.0f, 1.0f, 0.0f), + new Vector3(0.0f, 0.0f, 1.0f), + new Color(0.0f, 0.0f, 0.0f, 1.0f), + RenderClearFlags.All, + true, + 60.0f * 0.017453292519943295f, + 5.0f, + 1.0f, + 0.1f, + 1000.0f, + 0, + 0); + + internal CameraData( + Matrix4x4 view, + Matrix4x4 projection, + Matrix4x4 viewProjection, + Vector3 worldPosition, + Vector3 worldRight, + Vector3 worldUp, + Vector3 worldForward, + Color clearColor, + RenderClearFlags clearFlags, + bool perspectiveProjection, + float verticalFovRadians, + float orthographicSize, + float aspectRatio, + float nearClipPlane, + float farClipPlane, + int viewportWidth, + int viewportHeight) + { + this.view = view; + this.projection = projection; + this.viewProjection = viewProjection; + this.worldPosition = worldPosition; + this.worldRight = worldRight; + this.worldUp = worldUp; + this.worldForward = worldForward; + this.clearColor = clearColor; + this.clearFlags = clearFlags; + this.perspectiveProjection = perspectiveProjection; + this.verticalFovRadians = verticalFovRadians; + this.orthographicSize = orthographicSize; + this.aspectRatio = aspectRatio; + this.nearClipPlane = nearClipPlane; + this.farClipPlane = farClipPlane; + this.viewportWidth = viewportWidth; + this.viewportHeight = viewportHeight; + } + + public Matrix4x4 view { get; } + + public Matrix4x4 projection { get; } + + public Matrix4x4 viewProjection { get; } + + public Vector3 worldPosition { get; } + + public Vector3 worldRight { get; } + + public Vector3 worldUp { get; } + + public Vector3 worldForward { get; } + + public Color clearColor { get; } + + public RenderClearFlags clearFlags { get; } + + public bool perspectiveProjection { get; } + + public bool isPerspectiveProjection => + perspectiveProjection; + + public bool isOrthographicProjection => + !perspectiveProjection; + + public bool clearsColor => + (clearFlags & RenderClearFlags.Color) != 0; + + public bool clearsDepth => + (clearFlags & RenderClearFlags.Depth) != 0; + + public float verticalFovRadians { get; } + + public float orthographicSize { get; } + + public float aspectRatio { get; } + + public float nearClipPlane { get; } + + public float farClipPlane { get; } + + public int viewportWidth { get; } + + public int viewportHeight { get; } + } +} diff --git a/managed/XCEngine.ScriptCore/Color.cs b/managed/XCEngine.ScriptCore/Color.cs new file mode 100644 index 00000000..c3c4cef4 --- /dev/null +++ b/managed/XCEngine.ScriptCore/Color.cs @@ -0,0 +1,49 @@ +using System.Runtime.InteropServices; + +namespace XCEngine +{ + [StructLayout(LayoutKind.Sequential)] + public struct Color + { + public float R; + public float G; + public float B; + public float A; + + public float r + { + get => R; + set => R = value; + } + + public float g + { + get => G; + set => G = value; + } + + public float b + { + get => B; + set => B = value; + } + + public float a + { + get => A; + set => A = value; + } + + public Color( + float r, + float g, + float b, + float a = 1.0f) + { + R = r; + G = g; + B = b; + A = a; + } + } +} diff --git a/managed/XCEngine.ScriptCore/ColorScalePostProcessRendererFeature.cs b/managed/XCEngine.ScriptCore/ColorScalePostProcessRendererFeature.cs new file mode 100644 index 00000000..f417d90e --- /dev/null +++ b/managed/XCEngine.ScriptCore/ColorScalePostProcessRendererFeature.cs @@ -0,0 +1,79 @@ +namespace XCEngine +{ + internal sealed class ColorScalePostProcessPass + : ScriptableRenderPass + { + private readonly ColorScalePostProcessRendererFeature m_feature; + + public ColorScalePostProcessPass( + ColorScalePostProcessRendererFeature feature) + { + m_feature = feature; + renderPassEvent = + RenderPassEvent.BeforeRenderingPostProcessing; + } + + protected override bool RecordRenderGraph( + ScriptableRenderContext context, + RenderingData renderingData) + { + return context != null && + renderingData != null && + renderingData.isPostProcessStage && + m_feature != null && + context.RecordFullscreenPass( + FullscreenPassDescriptor.CreateColorScale( + m_feature.colorScale)); + } + } + + public sealed class ColorScalePostProcessRendererFeature + : ScriptableRendererFeature + { + private ColorScalePostProcessPass m_pass; + + public Vector4 colorScale = new Vector4( + 1.0f, + 1.0f, + 1.0f, + 1.0f); + + public override void Create() + { + m_pass = + new ColorScalePostProcessPass(this); + } + + public override void ConfigureCameraFramePlan( + ScriptableRenderPipelinePlanningContext context) + { + if (context == null) + { + return; + } + + context.RequestFullscreenStage( + CameraFrameStage.PostProcess, + CameraFrameColorSource.MainSceneColor); + } + + public override void AddRenderPasses( + ScriptableRenderer renderer, + RenderingData renderingData) + { + if (renderer == null || + renderingData == null || + !renderingData.isPostProcessStage) + { + return; + } + + if (m_pass == null) + { + Create(); + } + + renderer.EnqueuePass(m_pass); + } + } +} diff --git a/managed/XCEngine.ScriptCore/DirectionalLightData.cs b/managed/XCEngine.ScriptCore/DirectionalLightData.cs new file mode 100644 index 00000000..9dada2a8 --- /dev/null +++ b/managed/XCEngine.ScriptCore/DirectionalLightData.cs @@ -0,0 +1,40 @@ +namespace XCEngine +{ + public sealed class DirectionalLightData + { + internal static readonly DirectionalLightData Default = + new DirectionalLightData( + false, + false, + new Vector3(0.0f, 0.0f, -1.0f), + new Color(1.0f, 1.0f, 1.0f, 1.0f), + 1.0f); + + internal DirectionalLightData( + bool enabled, + bool castsShadows, + Vector3 direction, + Color color, + float intensity) + { + this.enabled = enabled; + this.castsShadows = castsShadows; + this.direction = direction; + this.color = color; + this.intensity = intensity; + } + + public bool enabled { get; } + + public bool castsShadows { get; } + + public Vector3 direction { get; } + + public Color color { get; } + + public float intensity { get; } + + public bool isValid => + enabled; + } +} diff --git a/managed/XCEngine.ScriptCore/DirectionalShadowData.cs b/managed/XCEngine.ScriptCore/DirectionalShadowData.cs new file mode 100644 index 00000000..35e96004 --- /dev/null +++ b/managed/XCEngine.ScriptCore/DirectionalShadowData.cs @@ -0,0 +1,83 @@ +namespace XCEngine +{ + public sealed class DirectionalShadowData + { + internal static readonly DirectionalShadowData Default = + new DirectionalShadowData( + false, + Matrix4x4.Identity, + 0.0f, + 0.1f, + 0.0f, + 0, + 0, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0); + + internal DirectionalShadowData( + bool enabled, + Matrix4x4 viewProjection, + float orthographicHalfExtent, + float nearClipPlane, + float farClipPlane, + int mapWidth, + int mapHeight, + float worldTexelSize, + float receiverDepthBias, + float normalBiasScale, + float shadowStrength, + float depthBiasFactor, + int depthBiasUnits) + { + this.enabled = enabled; + this.viewProjection = viewProjection; + this.orthographicHalfExtent = + orthographicHalfExtent; + this.nearClipPlane = nearClipPlane; + this.farClipPlane = farClipPlane; + this.mapWidth = mapWidth; + this.mapHeight = mapHeight; + this.worldTexelSize = worldTexelSize; + this.receiverDepthBias = receiverDepthBias; + this.normalBiasScale = normalBiasScale; + this.shadowStrength = shadowStrength; + this.depthBiasFactor = depthBiasFactor; + this.depthBiasUnits = depthBiasUnits; + } + + public bool enabled { get; } + + public Matrix4x4 viewProjection { get; } + + public float orthographicHalfExtent { get; } + + public float nearClipPlane { get; } + + public float farClipPlane { get; } + + public int mapWidth { get; } + + public int mapHeight { get; } + + public float worldTexelSize { get; } + + public float receiverDepthBias { get; } + + public float normalBiasScale { get; } + + public float shadowStrength { get; } + + public float depthBiasFactor { get; } + + public int depthBiasUnits { get; } + + public bool hasShadowMap => + enabled && + mapWidth > 0 && + mapHeight > 0; + } +} diff --git a/managed/XCEngine.ScriptCore/DisableDirectionalShadowRendererFeature.cs b/managed/XCEngine.ScriptCore/DisableDirectionalShadowRendererFeature.cs new file mode 100644 index 00000000..62806969 --- /dev/null +++ b/managed/XCEngine.ScriptCore/DisableDirectionalShadowRendererFeature.cs @@ -0,0 +1,16 @@ +namespace XCEngine +{ + public sealed class DisableDirectionalShadowRendererFeature + : ScriptableRendererFeature + { + public override void ConfigureCameraRenderRequest( + ScriptableRenderPipelineCameraRequestContext context) + { + if (context != null && + context.hasDirectionalShadow) + { + context.ClearDirectionalShadow(); + } + } + } +} diff --git a/managed/XCEngine.ScriptCore/EnvironmentData.cs b/managed/XCEngine.ScriptCore/EnvironmentData.cs new file mode 100644 index 00000000..4968c65a --- /dev/null +++ b/managed/XCEngine.ScriptCore/EnvironmentData.cs @@ -0,0 +1,41 @@ +namespace XCEngine +{ + public sealed class EnvironmentData + { + internal static readonly EnvironmentData Default = + new EnvironmentData( + RenderEnvironmentMode.None, + new Color(0.18f, 0.36f, 0.74f, 1.0f), + new Color(0.78f, 0.84f, 0.92f, 1.0f), + new Color(0.92f, 0.93f, 0.95f, 1.0f)); + + internal EnvironmentData( + RenderEnvironmentMode mode, + Color skyboxTopColor, + Color skyboxHorizonColor, + Color skyboxBottomColor) + { + this.mode = mode; + this.skyboxTopColor = skyboxTopColor; + this.skyboxHorizonColor = skyboxHorizonColor; + this.skyboxBottomColor = skyboxBottomColor; + } + + public RenderEnvironmentMode mode { get; } + + public Color skyboxTopColor { get; } + + public Color skyboxHorizonColor { get; } + + public Color skyboxBottomColor { get; } + + public bool hasProceduralSkybox => + mode == RenderEnvironmentMode.ProceduralSkybox; + + public bool hasMaterialSkybox => + mode == RenderEnvironmentMode.MaterialSkybox; + + public bool hasSkybox => + hasProceduralSkybox || hasMaterialSkybox; + } +} diff --git a/managed/XCEngine.ScriptCore/FinalColorData.cs b/managed/XCEngine.ScriptCore/FinalColorData.cs new file mode 100644 index 00000000..1a595412 --- /dev/null +++ b/managed/XCEngine.ScriptCore/FinalColorData.cs @@ -0,0 +1,39 @@ +namespace XCEngine +{ + public sealed class FinalColorData + { + internal static readonly FinalColorData Default = + new FinalColorData( + FinalColorSettings.CreateDefault(), + false, + false); + + internal FinalColorData( + FinalColorSettings settings, + bool hasPipelineDefaults, + bool hasCameraOverrides) + { + this.settings = settings; + this.hasPipelineDefaults = hasPipelineDefaults; + this.hasCameraOverrides = hasCameraOverrides; + } + + public FinalColorSettings settings { get; } + + public bool hasPipelineDefaults { get; } + + public bool hasCameraOverrides { get; } + + public bool requiresProcessing => + settings.outputTransferMode != + FinalColorOutputTransferMode.Disabled || + settings.exposureMode != + FinalColorExposureMode.Disabled || + settings.toneMappingMode != + FinalColorToneMappingMode.Disabled || + settings.finalColorScale.x != 1.0f || + settings.finalColorScale.y != 1.0f || + settings.finalColorScale.z != 1.0f || + settings.finalColorScale.w != 1.0f; + } +} diff --git a/managed/XCEngine.ScriptCore/ForwardRenderPipelineAsset.cs b/managed/XCEngine.ScriptCore/ForwardRenderPipelineAsset.cs new file mode 100644 index 00000000..2aa8d65e --- /dev/null +++ b/managed/XCEngine.ScriptCore/ForwardRenderPipelineAsset.cs @@ -0,0 +1,18 @@ +namespace XCEngine +{ + public class ForwardRenderPipelineAsset : ScriptableRenderPipelineAsset + { + public ForwardRendererData rendererData = + new ForwardRendererData(); + + protected override ScriptableRendererData GetDefaultRendererData() + { + if (rendererData == null) + { + rendererData = new ForwardRendererData(); + } + + return rendererData; + } + } +} diff --git a/managed/XCEngine.ScriptCore/ForwardRenderer.cs b/managed/XCEngine.ScriptCore/ForwardRenderer.cs new file mode 100644 index 00000000..294d59bb --- /dev/null +++ b/managed/XCEngine.ScriptCore/ForwardRenderer.cs @@ -0,0 +1,147 @@ +namespace XCEngine +{ + internal sealed class ForwardSceneInjectionPass : ScriptableRenderPass + { + private readonly SceneRenderInjectionPoint m_injectionPoint; + + public ForwardSceneInjectionPass( + RenderPassEvent passEvent, + SceneRenderInjectionPoint injectionPoint) + { + renderPassEvent = passEvent; + m_injectionPoint = injectionPoint; + } + + protected override bool RecordRenderGraph( + ScriptableRenderContext context, + RenderingData renderingData) + { + return context != null && + renderingData != null && + renderingData.isMainSceneStage && + context.RecordSceneInjectionPoint(m_injectionPoint); + } + } + + internal sealed class ForwardScenePhasePass : ScriptableRenderPass + { + private readonly ScenePhase m_scenePhase; + + public ForwardScenePhasePass( + RenderPassEvent passEvent, + ScenePhase scenePhase) + { + renderPassEvent = passEvent; + m_scenePhase = scenePhase; + } + + protected override bool RecordRenderGraph( + ScriptableRenderContext context, + RenderingData renderingData) + { + return context != null && + renderingData != null && + renderingData.isMainSceneStage && + context.RecordScenePhase(m_scenePhase); + } + } + + internal sealed class ForwardSceneFeature : ScriptableRendererFeature + { + private readonly ForwardRendererData m_rendererData; + private readonly ForwardSceneInjectionPass m_beforeOpaquePass = + new ForwardSceneInjectionPass( + RenderPassEvent.BeforeRenderingOpaques, + SceneRenderInjectionPoint.BeforeOpaque); + private readonly ForwardScenePhasePass m_opaquePass = + new ForwardScenePhasePass( + RenderPassEvent.RenderOpaques, + ScenePhase.Opaque); + private readonly ForwardSceneInjectionPass m_afterOpaquePass = + new ForwardSceneInjectionPass( + RenderPassEvent.AfterRenderingOpaques, + SceneRenderInjectionPoint.AfterOpaque); + private readonly ForwardSceneInjectionPass m_beforeSkyboxPass = + new ForwardSceneInjectionPass( + RenderPassEvent.BeforeRenderingSkybox, + SceneRenderInjectionPoint.BeforeSkybox); + private readonly ForwardScenePhasePass m_skyboxPass = + new ForwardScenePhasePass( + RenderPassEvent.RenderSkybox, + ScenePhase.Skybox); + private readonly ForwardSceneInjectionPass m_afterSkyboxPass = + new ForwardSceneInjectionPass( + RenderPassEvent.AfterRenderingSkybox, + SceneRenderInjectionPoint.AfterSkybox); + private readonly ForwardSceneInjectionPass m_beforeTransparentPass = + new ForwardSceneInjectionPass( + RenderPassEvent.BeforeRenderingTransparents, + SceneRenderInjectionPoint.BeforeTransparent); + private readonly ForwardScenePhasePass m_transparentPass = + new ForwardScenePhasePass( + RenderPassEvent.RenderTransparents, + ScenePhase.Transparent); + private readonly ForwardSceneInjectionPass m_afterTransparentPass = + new ForwardSceneInjectionPass( + RenderPassEvent.AfterRenderingTransparents, + SceneRenderInjectionPoint.AfterTransparent); + + public ForwardSceneFeature( + ForwardRendererData rendererData) + { + m_rendererData = rendererData; + } + + public override void AddRenderPasses( + ScriptableRenderer renderer, + RenderingData renderingData) + { + if (renderer == null || + renderingData == null || + !renderingData.isMainSceneStage || + m_rendererData == null) + { + return; + } + + if (m_rendererData.renderOpaque) + { + renderer.EnqueuePass(m_beforeOpaquePass); + renderer.EnqueuePass(m_opaquePass); + renderer.EnqueuePass(m_afterOpaquePass); + } + + if (m_rendererData.renderSkybox) + { + renderer.EnqueuePass(m_beforeSkyboxPass); + renderer.EnqueuePass(m_skyboxPass); + renderer.EnqueuePass(m_afterSkyboxPass); + } + + if (m_rendererData.renderTransparent) + { + renderer.EnqueuePass(m_beforeTransparentPass); + renderer.EnqueuePass(m_transparentPass); + renderer.EnqueuePass(m_afterTransparentPass); + } + } + } + + public sealed class ForwardRenderer : ScriptableRenderer + { + public ForwardRenderer( + ForwardRendererData rendererData) + { + ForwardRendererData resolvedData = + rendererData ?? new ForwardRendererData(); + AddFeature(new ForwardSceneFeature(resolvedData)); + + ScriptableRendererFeature[] rendererFeatures = + resolvedData.CreateRendererFeaturesInstance(); + for (int i = 0; i < rendererFeatures.Length; ++i) + { + AddFeature(rendererFeatures[i]); + } + } + } +} diff --git a/managed/XCEngine.ScriptCore/ForwardRendererData.cs b/managed/XCEngine.ScriptCore/ForwardRendererData.cs new file mode 100644 index 00000000..7e8b0c88 --- /dev/null +++ b/managed/XCEngine.ScriptCore/ForwardRendererData.cs @@ -0,0 +1,24 @@ +using System; + +namespace XCEngine +{ + public class ForwardRendererData : ScriptableRendererData + { + public bool renderOpaque = true; + public bool renderSkybox = true; + public bool renderTransparent = true; + public ScriptableRendererFeature[] rendererFeatures = + Array.Empty(); + + protected override ScriptableRenderer CreateRenderer() + { + return new ForwardRenderer(this); + } + + protected override ScriptableRendererFeature[] CreateRendererFeatures() + { + return rendererFeatures ?? + Array.Empty(); + } + } +} diff --git a/managed/XCEngine.ScriptCore/InternalCalls.cs b/managed/XCEngine.ScriptCore/InternalCalls.cs index 3f3c4a77..59a1d5a4 100644 --- a/managed/XCEngine.ScriptCore/InternalCalls.cs +++ b/managed/XCEngine.ScriptCore/InternalCalls.cs @@ -388,11 +388,276 @@ namespace XCEngine internal static extern int Rendering_ScriptableRenderContext_GetStage( ulong nativeHandle); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int + Rendering_ScriptableRenderContext_GetStageColorSource( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool + Rendering_ScriptableRenderContext_GetStageUsesGraphManagedOutputColor( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool + Rendering_ScriptableRenderContext_GetMainDirectionalShadowEnabled( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void + Rendering_ScriptableRenderContext_GetMainDirectionalShadowViewProjection( + ulong nativeHandle, + out Matrix4x4 viewProjection); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern float + Rendering_ScriptableRenderContext_GetMainDirectionalShadowOrthographicHalfExtent( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern float + Rendering_ScriptableRenderContext_GetMainDirectionalShadowNearClipPlane( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern float + Rendering_ScriptableRenderContext_GetMainDirectionalShadowFarClipPlane( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int + Rendering_ScriptableRenderContext_GetMainDirectionalShadowMapWidth( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int + Rendering_ScriptableRenderContext_GetMainDirectionalShadowMapHeight( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern float + Rendering_ScriptableRenderContext_GetMainDirectionalShadowWorldTexelSize( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern float + Rendering_ScriptableRenderContext_GetMainDirectionalShadowReceiverDepthBias( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern float + Rendering_ScriptableRenderContext_GetMainDirectionalShadowNormalBiasScale( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern float + Rendering_ScriptableRenderContext_GetMainDirectionalShadowStrength( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern float + Rendering_ScriptableRenderContext_GetMainDirectionalShadowDepthBiasFactor( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int + Rendering_ScriptableRenderContext_GetMainDirectionalShadowDepthBiasUnits( + ulong nativeHandle); + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern bool Rendering_ScriptableRenderContext_RecordScene( ulong nativeHandle); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void + Rendering_ScriptableRenderContext_GetCameraView( + ulong nativeHandle, + out Matrix4x4 view); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void + Rendering_ScriptableRenderContext_GetCameraProjection( + ulong nativeHandle, + out Matrix4x4 projection); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void + Rendering_ScriptableRenderContext_GetCameraViewProjection( + ulong nativeHandle, + out Matrix4x4 viewProjection); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void + Rendering_ScriptableRenderContext_GetCameraWorldPosition( + ulong nativeHandle, + out Vector3 worldPosition); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void + Rendering_ScriptableRenderContext_GetCameraWorldRight( + ulong nativeHandle, + out Vector3 worldRight); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void + Rendering_ScriptableRenderContext_GetCameraWorldUp( + ulong nativeHandle, + out Vector3 worldUp); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void + Rendering_ScriptableRenderContext_GetCameraWorldForward( + ulong nativeHandle, + out Vector3 worldForward); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void + Rendering_ScriptableRenderContext_GetCameraClearColor( + ulong nativeHandle, + out Color clearColor); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int + Rendering_ScriptableRenderContext_GetCameraClearFlags( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool + Rendering_ScriptableRenderContext_GetCameraPerspectiveProjection( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern float + Rendering_ScriptableRenderContext_GetCameraVerticalFovRadians( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern float + Rendering_ScriptableRenderContext_GetCameraOrthographicSize( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern float + Rendering_ScriptableRenderContext_GetCameraAspectRatio( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern float + Rendering_ScriptableRenderContext_GetCameraNearClipPlane( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern float + Rendering_ScriptableRenderContext_GetCameraFarClipPlane( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int + Rendering_ScriptableRenderContext_GetCameraViewportWidth( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int + Rendering_ScriptableRenderContext_GetCameraViewportHeight( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool + Rendering_ScriptableRenderContext_GetMainDirectionalLightEnabled( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool + Rendering_ScriptableRenderContext_GetMainDirectionalLightCastsShadows( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void + Rendering_ScriptableRenderContext_GetMainDirectionalLightDirection( + ulong nativeHandle, + out Vector3 direction); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void + Rendering_ScriptableRenderContext_GetMainDirectionalLightColor( + ulong nativeHandle, + out Color color); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern float + Rendering_ScriptableRenderContext_GetMainDirectionalLightIntensity( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool + Rendering_ScriptableRenderContext_GetHasMainDirectionalShadow( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int + Rendering_ScriptableRenderContext_GetAdditionalLightCount( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int + Rendering_ScriptableRenderContext_GetEnvironmentMode( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void + Rendering_ScriptableRenderContext_GetEnvironmentSkyboxTopColor( + ulong nativeHandle, + out Color color); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void + Rendering_ScriptableRenderContext_GetEnvironmentSkyboxHorizonColor( + ulong nativeHandle, + out Color color); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void + Rendering_ScriptableRenderContext_GetEnvironmentSkyboxBottomColor( + ulong nativeHandle, + out Color color); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int + Rendering_ScriptableRenderContext_GetFinalColorOutputTransferMode( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int + Rendering_ScriptableRenderContext_GetFinalColorExposureMode( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern float + Rendering_ScriptableRenderContext_GetFinalColorExposureValue( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int + Rendering_ScriptableRenderContext_GetFinalColorToneMappingMode( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void + Rendering_ScriptableRenderContext_GetFinalColorScale( + ulong nativeHandle, + out Vector4 scale); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool + Rendering_ScriptableRenderContext_GetFinalColorHasPipelineDefaults( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool + Rendering_ScriptableRenderContext_GetFinalColorHasCameraOverrides( + ulong nativeHandle); + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern bool Rendering_ScriptableRenderContext_RecordScenePhase( diff --git a/managed/XCEngine.ScriptCore/LightingData.cs b/managed/XCEngine.ScriptCore/LightingData.cs new file mode 100644 index 00000000..e9aff57b --- /dev/null +++ b/managed/XCEngine.ScriptCore/LightingData.cs @@ -0,0 +1,35 @@ +namespace XCEngine +{ + public sealed class LightingData + { + internal static readonly LightingData Default = + new LightingData( + DirectionalLightData.Default, + false, + 0); + + internal LightingData( + DirectionalLightData mainDirectionalLight, + bool hasMainDirectionalShadow, + int additionalLightCount) + { + this.mainDirectionalLight = + mainDirectionalLight ?? DirectionalLightData.Default; + this.hasMainDirectionalShadow = + hasMainDirectionalShadow; + this.additionalLightCount = additionalLightCount; + } + + public DirectionalLightData mainDirectionalLight { get; } + + public bool hasMainDirectionalShadow { get; } + + public int additionalLightCount { get; } + + public bool hasMainDirectionalLight => + mainDirectionalLight.enabled; + + public bool hasAdditionalLights => + additionalLightCount > 0; + } +} diff --git a/managed/XCEngine.ScriptCore/Matrix4x4.cs b/managed/XCEngine.ScriptCore/Matrix4x4.cs new file mode 100644 index 00000000..6940ab41 --- /dev/null +++ b/managed/XCEngine.ScriptCore/Matrix4x4.cs @@ -0,0 +1,221 @@ +using System; +using System.Runtime.InteropServices; + +namespace XCEngine +{ + [StructLayout(LayoutKind.Sequential)] + public struct Matrix4x4 + { + public float M00; + public float M01; + public float M02; + public float M03; + public float M10; + public float M11; + public float M12; + public float M13; + public float M20; + public float M21; + public float M22; + public float M23; + public float M30; + public float M31; + public float M32; + public float M33; + + public static Matrix4x4 Identity => + new Matrix4x4 + { + M00 = 1.0f, + M11 = 1.0f, + M22 = 1.0f, + M33 = 1.0f + }; + + public float this[int row, int column] + { + get + { + switch (row) + { + case 0: + switch (column) + { + case 0: + return M00; + case 1: + return M01; + case 2: + return M02; + case 3: + return M03; + default: + throw new ArgumentOutOfRangeException( + nameof(column)); + } + case 1: + switch (column) + { + case 0: + return M10; + case 1: + return M11; + case 2: + return M12; + case 3: + return M13; + default: + throw new ArgumentOutOfRangeException( + nameof(column)); + } + case 2: + switch (column) + { + case 0: + return M20; + case 1: + return M21; + case 2: + return M22; + case 3: + return M23; + default: + throw new ArgumentOutOfRangeException( + nameof(column)); + } + case 3: + switch (column) + { + case 0: + return M30; + case 1: + return M31; + case 2: + return M32; + case 3: + return M33; + default: + throw new ArgumentOutOfRangeException( + nameof(column)); + } + default: + throw new ArgumentOutOfRangeException(nameof(row)); + } + } + set + { + switch (row) + { + case 0: + switch (column) + { + case 0: + M00 = value; + return; + case 1: + M01 = value; + return; + case 2: + M02 = value; + return; + case 3: + M03 = value; + return; + } + break; + case 1: + switch (column) + { + case 0: + M10 = value; + return; + case 1: + M11 = value; + return; + case 2: + M12 = value; + return; + case 3: + M13 = value; + return; + } + break; + case 2: + switch (column) + { + case 0: + M20 = value; + return; + case 1: + M21 = value; + return; + case 2: + M22 = value; + return; + case 3: + M23 = value; + return; + } + break; + case 3: + switch (column) + { + case 0: + M30 = value; + return; + case 1: + M31 = value; + return; + case 2: + M32 = value; + return; + case 3: + M33 = value; + return; + } + break; + } + + throw new ArgumentOutOfRangeException( + row < 0 || row > 3 + ? nameof(row) + : nameof(column)); + } + } + + public Vector4 GetRow(int row) + { + switch (row) + { + case 0: + return new Vector4(M00, M01, M02, M03); + case 1: + return new Vector4(M10, M11, M12, M13); + case 2: + return new Vector4(M20, M21, M22, M23); + case 3: + return new Vector4(M30, M31, M32, M33); + default: + throw new ArgumentOutOfRangeException(nameof(row)); + } + } + + public Vector4 GetColumn(int column) + { + switch (column) + { + case 0: + return new Vector4(M00, M10, M20, M30); + case 1: + return new Vector4(M01, M11, M21, M31); + case 2: + return new Vector4(M02, M12, M22, M32); + case 3: + return new Vector4(M03, M13, M23, M33); + default: + throw new ArgumentOutOfRangeException( + nameof(column)); + } + } + } +} diff --git a/managed/XCEngine.ScriptCore/RenderClearFlags.cs b/managed/XCEngine.ScriptCore/RenderClearFlags.cs new file mode 100644 index 00000000..f8cb26ec --- /dev/null +++ b/managed/XCEngine.ScriptCore/RenderClearFlags.cs @@ -0,0 +1,13 @@ +using System; + +namespace XCEngine +{ + [Flags] + public enum RenderClearFlags + { + None = 0, + Color = 1 << 0, + Depth = 1 << 1, + All = Color | Depth + } +} diff --git a/managed/XCEngine.ScriptCore/RenderEnvironmentMode.cs b/managed/XCEngine.ScriptCore/RenderEnvironmentMode.cs new file mode 100644 index 00000000..21bc6d41 --- /dev/null +++ b/managed/XCEngine.ScriptCore/RenderEnvironmentMode.cs @@ -0,0 +1,9 @@ +namespace XCEngine +{ + public enum RenderEnvironmentMode + { + None = 0, + ProceduralSkybox = 1, + MaterialSkybox = 2 + } +} diff --git a/managed/XCEngine.ScriptCore/RenderPassEvent.cs b/managed/XCEngine.ScriptCore/RenderPassEvent.cs new file mode 100644 index 00000000..f4287382 --- /dev/null +++ b/managed/XCEngine.ScriptCore/RenderPassEvent.cs @@ -0,0 +1,19 @@ +namespace XCEngine +{ + public enum RenderPassEvent + { + BeforeRenderingOpaques = 100, + RenderOpaques = 110, + AfterRenderingOpaques = 120, + BeforeRenderingSkybox = 200, + RenderSkybox = 210, + AfterRenderingSkybox = 220, + BeforeRenderingTransparents = 300, + RenderTransparents = 310, + AfterRenderingTransparents = 320, + BeforeRenderingPostProcessing = 400, + AfterRenderingPostProcessing = 420, + BeforeRenderingFinalOutput = 500, + AfterRenderingFinalOutput = 520 + } +} diff --git a/managed/XCEngine.ScriptCore/RendererDrivenRenderPipeline.cs b/managed/XCEngine.ScriptCore/RendererDrivenRenderPipeline.cs new file mode 100644 index 00000000..9aae4517 --- /dev/null +++ b/managed/XCEngine.ScriptCore/RendererDrivenRenderPipeline.cs @@ -0,0 +1,20 @@ +namespace XCEngine +{ + public class RendererDrivenRenderPipeline : ScriptableRenderPipeline + { + private readonly ScriptableRendererData m_rendererData; + + public RendererDrivenRenderPipeline( + ScriptableRendererData rendererData) + { + m_rendererData = rendererData; + } + + protected internal override ScriptableRenderer CreateRenderer() + { + return m_rendererData != null + ? m_rendererData.CreateRendererInstance() + : null; + } + } +} diff --git a/managed/XCEngine.ScriptCore/RenderingData.cs b/managed/XCEngine.ScriptCore/RenderingData.cs new file mode 100644 index 00000000..537025cc --- /dev/null +++ b/managed/XCEngine.ScriptCore/RenderingData.cs @@ -0,0 +1,89 @@ +namespace XCEngine +{ + public sealed class RenderingData + { + internal RenderingData(CameraFrameStage stage) + : this( + stage, + CameraData.Default, + LightingData.Default, + ShadowData.Default, + EnvironmentData.Default, + FinalColorData.Default, + StageColorData.Default) + { + } + + internal RenderingData(ScriptableRenderContext context) + : this( + context != null + ? context.stage + : CameraFrameStage.MainScene, + context != null + ? context.cameraData + : CameraData.Default, + context != null + ? context.lightingData + : LightingData.Default, + context != null + ? context.shadowData + : ShadowData.Default, + context != null + ? context.environmentData + : EnvironmentData.Default, + context != null + ? context.finalColorData + : FinalColorData.Default, + context != null + ? context.stageColorData + : StageColorData.Default) + { + } + + private RenderingData( + CameraFrameStage stage, + CameraData cameraData, + LightingData lightingData, + ShadowData shadowData, + EnvironmentData environmentData, + FinalColorData finalColorData, + StageColorData stageColorData) + { + this.stage = stage; + this.cameraData = cameraData ?? CameraData.Default; + this.lightingData = + lightingData ?? LightingData.Default; + this.shadowData = + shadowData ?? ShadowData.Default; + this.environmentData = + environmentData ?? EnvironmentData.Default; + this.finalColorData = + finalColorData ?? FinalColorData.Default; + this.stageColorData = + stageColorData ?? StageColorData.Default; + } + + public CameraFrameStage stage { get; } + + public CameraData cameraData { get; } + + public LightingData lightingData { get; } + + public ShadowData shadowData { get; } + + public EnvironmentData environmentData { get; } + + public FinalColorData finalColorData { get; } + + public StageColorData stageColorData { get; } + + public bool isMainSceneStage => + stage == CameraFrameStage.MainScene; + + public bool isPostProcessStage => + stage == CameraFrameStage.PostProcess; + + public bool isFinalOutputStage => + stage == CameraFrameStage.FinalOutput; + } +} diff --git a/managed/XCEngine.ScriptCore/ScriptableRenderContext.cs b/managed/XCEngine.ScriptCore/ScriptableRenderContext.cs index 2f28d3c9..9e17cc5a 100644 --- a/managed/XCEngine.ScriptCore/ScriptableRenderContext.cs +++ b/managed/XCEngine.ScriptCore/ScriptableRenderContext.cs @@ -5,6 +5,12 @@ namespace XCEngine public sealed class ScriptableRenderContext { private readonly ulong m_nativeHandle; + private CameraData m_cameraData; + private LightingData m_lightingData; + private ShadowData m_shadowData; + private EnvironmentData m_environmentData; + private FinalColorData m_finalColorData; + private StageColorData m_stageColorData; internal ScriptableRenderContext(ulong nativeHandle) { @@ -15,6 +21,27 @@ namespace XCEngine (CameraFrameStage)InternalCalls.Rendering_ScriptableRenderContext_GetStage( m_nativeHandle); + public CameraData cameraData => + m_cameraData ?? (m_cameraData = ResolveCameraData()); + + public LightingData lightingData => + m_lightingData ?? (m_lightingData = ResolveLightingData()); + + public ShadowData shadowData => + m_shadowData ?? (m_shadowData = ResolveShadowData()); + + public EnvironmentData environmentData => + m_environmentData ?? + (m_environmentData = ResolveEnvironmentData()); + + public FinalColorData finalColorData => + m_finalColorData ?? + (m_finalColorData = ResolveFinalColorData()); + + public StageColorData stageColorData => + m_stageColorData ?? + (m_stageColorData = ResolveStageColorData()); + public bool RecordScene() { return InternalCalls @@ -65,5 +92,251 @@ namespace XCEngine passName, ref vectorPayload); } + + private CameraData ResolveCameraData() + { + Matrix4x4 view; + Matrix4x4 projection; + Matrix4x4 viewProjection; + Vector3 worldPosition; + Vector3 worldRight; + Vector3 worldUp; + Vector3 worldForward; + Color clearColor; + + InternalCalls + .Rendering_ScriptableRenderContext_GetCameraView( + m_nativeHandle, + out view); + InternalCalls + .Rendering_ScriptableRenderContext_GetCameraProjection( + m_nativeHandle, + out projection); + InternalCalls + .Rendering_ScriptableRenderContext_GetCameraViewProjection( + m_nativeHandle, + out viewProjection); + InternalCalls + .Rendering_ScriptableRenderContext_GetCameraWorldPosition( + m_nativeHandle, + out worldPosition); + InternalCalls + .Rendering_ScriptableRenderContext_GetCameraWorldRight( + m_nativeHandle, + out worldRight); + InternalCalls + .Rendering_ScriptableRenderContext_GetCameraWorldUp( + m_nativeHandle, + out worldUp); + InternalCalls + .Rendering_ScriptableRenderContext_GetCameraWorldForward( + m_nativeHandle, + out worldForward); + InternalCalls + .Rendering_ScriptableRenderContext_GetCameraClearColor( + m_nativeHandle, + out clearColor); + + return new CameraData( + view, + projection, + viewProjection, + worldPosition, + worldRight, + worldUp, + worldForward, + clearColor, + (RenderClearFlags)InternalCalls + .Rendering_ScriptableRenderContext_GetCameraClearFlags( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetCameraPerspectiveProjection( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetCameraVerticalFovRadians( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetCameraOrthographicSize( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetCameraAspectRatio( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetCameraNearClipPlane( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetCameraFarClipPlane( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetCameraViewportWidth( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetCameraViewportHeight( + m_nativeHandle)); + } + + private LightingData ResolveLightingData() + { + Vector3 mainDirectionalLightDirection; + Color mainDirectionalLightColor; + + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalLightDirection( + m_nativeHandle, + out mainDirectionalLightDirection); + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalLightColor( + m_nativeHandle, + out mainDirectionalLightColor); + + return new LightingData( + new DirectionalLightData( + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalLightEnabled( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalLightCastsShadows( + m_nativeHandle), + mainDirectionalLightDirection, + mainDirectionalLightColor, + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalLightIntensity( + m_nativeHandle)), + InternalCalls + .Rendering_ScriptableRenderContext_GetHasMainDirectionalShadow( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetAdditionalLightCount( + m_nativeHandle)); + } + + private EnvironmentData ResolveEnvironmentData() + { + Color skyboxTopColor; + Color skyboxHorizonColor; + Color skyboxBottomColor; + + InternalCalls + .Rendering_ScriptableRenderContext_GetEnvironmentSkyboxTopColor( + m_nativeHandle, + out skyboxTopColor); + InternalCalls + .Rendering_ScriptableRenderContext_GetEnvironmentSkyboxHorizonColor( + m_nativeHandle, + out skyboxHorizonColor); + InternalCalls + .Rendering_ScriptableRenderContext_GetEnvironmentSkyboxBottomColor( + m_nativeHandle, + out skyboxBottomColor); + + return new EnvironmentData( + (RenderEnvironmentMode)InternalCalls + .Rendering_ScriptableRenderContext_GetEnvironmentMode( + m_nativeHandle), + skyboxTopColor, + skyboxHorizonColor, + skyboxBottomColor); + } + + private ShadowData ResolveShadowData() + { + Matrix4x4 viewProjection; + + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalShadowViewProjection( + m_nativeHandle, + out viewProjection); + + return new ShadowData( + new DirectionalShadowData( + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalShadowEnabled( + m_nativeHandle), + viewProjection, + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalShadowOrthographicHalfExtent( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalShadowNearClipPlane( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalShadowFarClipPlane( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalShadowMapWidth( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalShadowMapHeight( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalShadowWorldTexelSize( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalShadowReceiverDepthBias( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalShadowNormalBiasScale( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalShadowStrength( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalShadowDepthBiasFactor( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetMainDirectionalShadowDepthBiasUnits( + m_nativeHandle))); + } + + private FinalColorData ResolveFinalColorData() + { + Vector4 finalColorScale; + + InternalCalls + .Rendering_ScriptableRenderContext_GetFinalColorScale( + m_nativeHandle, + out finalColorScale); + + FinalColorSettings settings = + FinalColorSettings.CreateDefault(); + settings.outputTransferMode = + (FinalColorOutputTransferMode)InternalCalls + .Rendering_ScriptableRenderContext_GetFinalColorOutputTransferMode( + m_nativeHandle); + settings.exposureMode = + (FinalColorExposureMode)InternalCalls + .Rendering_ScriptableRenderContext_GetFinalColorExposureMode( + m_nativeHandle); + settings.exposureValue = + InternalCalls + .Rendering_ScriptableRenderContext_GetFinalColorExposureValue( + m_nativeHandle); + settings.toneMappingMode = + (FinalColorToneMappingMode)InternalCalls + .Rendering_ScriptableRenderContext_GetFinalColorToneMappingMode( + m_nativeHandle); + settings.finalColorScale = + finalColorScale; + + return new FinalColorData( + settings, + InternalCalls + .Rendering_ScriptableRenderContext_GetFinalColorHasPipelineDefaults( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetFinalColorHasCameraOverrides( + m_nativeHandle)); + } + + private StageColorData ResolveStageColorData() + { + return new StageColorData( + (CameraFrameColorSource)InternalCalls + .Rendering_ScriptableRenderContext_GetStageColorSource( + m_nativeHandle), + InternalCalls + .Rendering_ScriptableRenderContext_GetStageUsesGraphManagedOutputColor( + m_nativeHandle)); + } } } diff --git a/managed/XCEngine.ScriptCore/ScriptableRenderPass.cs b/managed/XCEngine.ScriptCore/ScriptableRenderPass.cs new file mode 100644 index 00000000..684cfde6 --- /dev/null +++ b/managed/XCEngine.ScriptCore/ScriptableRenderPass.cs @@ -0,0 +1,66 @@ +namespace XCEngine +{ + public abstract class ScriptableRenderPass + { + protected ScriptableRenderPass() + { + } + + public RenderPassEvent renderPassEvent { get; protected set; } = + RenderPassEvent.BeforeRenderingOpaques; + + public virtual bool SupportsStage( + CameraFrameStage stage) + { + CameraFrameStage resolvedStage; + return TryResolveStage( + renderPassEvent, + out resolvedStage) && + resolvedStage == stage; + } + + internal bool Record( + ScriptableRenderContext context, + RenderingData renderingData) + { + return RecordRenderGraph( + context, + renderingData); + } + + protected abstract bool RecordRenderGraph( + ScriptableRenderContext context, + RenderingData renderingData); + + internal static bool TryResolveStage( + RenderPassEvent passEvent, + out CameraFrameStage stage) + { + switch (passEvent) + { + case RenderPassEvent.BeforeRenderingOpaques: + case RenderPassEvent.RenderOpaques: + case RenderPassEvent.AfterRenderingOpaques: + case RenderPassEvent.BeforeRenderingSkybox: + case RenderPassEvent.RenderSkybox: + case RenderPassEvent.AfterRenderingSkybox: + case RenderPassEvent.BeforeRenderingTransparents: + case RenderPassEvent.RenderTransparents: + case RenderPassEvent.AfterRenderingTransparents: + stage = CameraFrameStage.MainScene; + return true; + case RenderPassEvent.BeforeRenderingPostProcessing: + case RenderPassEvent.AfterRenderingPostProcessing: + stage = CameraFrameStage.PostProcess; + return true; + case RenderPassEvent.BeforeRenderingFinalOutput: + case RenderPassEvent.AfterRenderingFinalOutput: + stage = CameraFrameStage.FinalOutput; + return true; + default: + stage = CameraFrameStage.MainScene; + return false; + } + } + } +} diff --git a/managed/XCEngine.ScriptCore/ScriptableRenderPipeline.cs b/managed/XCEngine.ScriptCore/ScriptableRenderPipeline.cs index c7f9f59a..03c47d7c 100644 --- a/managed/XCEngine.ScriptCore/ScriptableRenderPipeline.cs +++ b/managed/XCEngine.ScriptCore/ScriptableRenderPipeline.cs @@ -2,20 +2,44 @@ namespace XCEngine { public abstract class ScriptableRenderPipeline : Object { + private ScriptableRenderer m_renderer; + protected ScriptableRenderPipeline() { } + protected internal virtual ScriptableRenderer CreateRenderer() + { + return null; + } + protected internal virtual bool SupportsStageRenderGraph( CameraFrameStage stage) { - return false; + ScriptableRenderer renderer = GetOrCreateRenderer(); + return renderer != null && + renderer.SupportsStageRenderGraph(stage); } protected internal virtual bool RecordStageRenderGraph( ScriptableRenderContext context) { - return false; + ScriptableRenderer renderer = GetOrCreateRenderer(); + return renderer != null && + renderer.RecordStageRenderGraph(context); + } + + protected ScriptableRenderer renderer => + GetOrCreateRenderer(); + + private ScriptableRenderer GetOrCreateRenderer() + { + if (m_renderer == null) + { + m_renderer = CreateRenderer(); + } + + return m_renderer; } } } diff --git a/managed/XCEngine.ScriptCore/ScriptableRenderPipelineAsset.cs b/managed/XCEngine.ScriptCore/ScriptableRenderPipelineAsset.cs index 9ef076f7..bd699fba 100644 --- a/managed/XCEngine.ScriptCore/ScriptableRenderPipelineAsset.cs +++ b/managed/XCEngine.ScriptCore/ScriptableRenderPipelineAsset.cs @@ -8,22 +8,50 @@ namespace XCEngine protected internal virtual ScriptableRenderPipeline CreatePipeline() { - return null; + ScriptableRendererData rendererData = + ResolveDefaultRendererData(); + return rendererData != null + ? new RendererDrivenRenderPipeline(rendererData) + : null; } protected internal virtual void ConfigureCameraRenderRequest( ScriptableRenderPipelineCameraRequestContext context) { + ScriptableRendererData rendererData = + ResolveDefaultRendererData(); + if (rendererData != null) + { + rendererData.ConfigureCameraRenderRequestInstance( + context); + } } protected internal virtual void ConfigureCameraFramePlan( ScriptableRenderPipelinePlanningContext context) { + ScriptableRendererData rendererData = + ResolveDefaultRendererData(); + if (rendererData != null) + { + rendererData.ConfigureCameraFramePlanInstance( + context); + } } protected internal virtual FinalColorSettings GetDefaultFinalColorSettings() { return FinalColorSettings.CreateDefault(); } + + internal ScriptableRendererData ResolveDefaultRendererData() + { + return GetDefaultRendererData(); + } + + protected virtual ScriptableRendererData GetDefaultRendererData() + { + return null; + } } } diff --git a/managed/XCEngine.ScriptCore/ScriptableRenderer.cs b/managed/XCEngine.ScriptCore/ScriptableRenderer.cs new file mode 100644 index 00000000..c102db5d --- /dev/null +++ b/managed/XCEngine.ScriptCore/ScriptableRenderer.cs @@ -0,0 +1,128 @@ +using System.Collections.Generic; + +namespace XCEngine +{ + public abstract class ScriptableRenderer + { + private readonly List m_features = + new List(); + private readonly List m_activePassQueue = + new List(); + + protected ScriptableRenderer() + { + } + + public void EnqueuePass( + ScriptableRenderPass renderPass) + { + if (renderPass == null) + { + return; + } + + int insertIndex = m_activePassQueue.Count; + while (insertIndex > 0 && + m_activePassQueue[insertIndex - 1].renderPassEvent > + renderPass.renderPassEvent) + { + insertIndex--; + } + + m_activePassQueue.Insert( + insertIndex, + renderPass); + } + + protected void AddFeature( + ScriptableRendererFeature feature) + { + if (feature == null) + { + return; + } + + m_features.Add(feature); + feature.Create(); + } + + protected virtual void AddRenderPasses( + RenderingData renderingData) + { + } + + internal bool SupportsStageRenderGraph( + CameraFrameStage stage) + { + RenderingData renderingData = new RenderingData(stage); + BuildPassQueue(renderingData); + for (int i = 0; i < m_activePassQueue.Count; ++i) + { + ScriptableRenderPass renderPass = m_activePassQueue[i]; + if (renderPass != null && + renderPass.SupportsStage(stage)) + { + return true; + } + } + + return false; + } + + internal bool RecordStageRenderGraph( + ScriptableRenderContext context) + { + if (context == null) + { + return false; + } + + RenderingData renderingData = + new RenderingData(context); + BuildPassQueue(renderingData); + + bool recordedAnyPass = false; + for (int i = 0; i < m_activePassQueue.Count; ++i) + { + ScriptableRenderPass renderPass = m_activePassQueue[i]; + if (renderPass == null || + !renderPass.SupportsStage(renderingData.stage)) + { + continue; + } + + if (!renderPass.Record( + context, + renderingData)) + { + return false; + } + + recordedAnyPass = true; + } + + return recordedAnyPass; + } + + private void BuildPassQueue( + RenderingData renderingData) + { + m_activePassQueue.Clear(); + + for (int i = 0; i < m_features.Count; ++i) + { + ScriptableRendererFeature feature = m_features[i]; + if (feature == null || !feature.isActive) + { + continue; + } + + feature.AddRenderPasses( + this, + renderingData); + } + + AddRenderPasses(renderingData); + } + } +} diff --git a/managed/XCEngine.ScriptCore/ScriptableRendererData.cs b/managed/XCEngine.ScriptCore/ScriptableRendererData.cs new file mode 100644 index 00000000..867ebca6 --- /dev/null +++ b/managed/XCEngine.ScriptCore/ScriptableRendererData.cs @@ -0,0 +1,99 @@ +using System; + +namespace XCEngine +{ + public abstract class ScriptableRendererData : Object + { + private ScriptableRendererFeature[] m_rendererFeatures; + + protected ScriptableRendererData() + { + } + + internal ScriptableRenderer CreateRendererInstance() + { + return CreateRenderer(); + } + + internal ScriptableRendererFeature[] CreateRendererFeaturesInstance() + { + return GetRendererFeatures(); + } + + internal void ConfigureCameraRenderRequestInstance( + ScriptableRenderPipelineCameraRequestContext context) + { + ConfigureCameraRenderRequest(context); + + ScriptableRendererFeature[] rendererFeatures = + GetRendererFeatures(); + for (int i = 0; i < rendererFeatures.Length; ++i) + { + ScriptableRendererFeature rendererFeature = + rendererFeatures[i]; + if (rendererFeature == null || + !rendererFeature.isActive) + { + continue; + } + + rendererFeature.ConfigureCameraRenderRequest( + context); + } + } + + internal void ConfigureCameraFramePlanInstance( + ScriptableRenderPipelinePlanningContext context) + { + ConfigureCameraFramePlan(context); + + ScriptableRendererFeature[] rendererFeatures = + GetRendererFeatures(); + for (int i = 0; i < rendererFeatures.Length; ++i) + { + ScriptableRendererFeature rendererFeature = + rendererFeatures[i]; + if (rendererFeature == null || + !rendererFeature.isActive) + { + continue; + } + + rendererFeature.ConfigureCameraFramePlan( + context); + } + } + + protected virtual ScriptableRenderer CreateRenderer() + { + return null; + } + + protected virtual void ConfigureCameraRenderRequest( + ScriptableRenderPipelineCameraRequestContext context) + { + } + + protected virtual void ConfigureCameraFramePlan( + ScriptableRenderPipelinePlanningContext context) + { + } + + protected virtual ScriptableRendererFeature[] CreateRendererFeatures() + { + return Array.Empty(); + } + + private ScriptableRendererFeature[] GetRendererFeatures() + { + if (m_rendererFeatures == null) + { + m_rendererFeatures = + CreateRendererFeatures() ?? + Array.Empty(); + } + + return m_rendererFeatures; + } + } +} diff --git a/managed/XCEngine.ScriptCore/ScriptableRendererFeature.cs b/managed/XCEngine.ScriptCore/ScriptableRendererFeature.cs new file mode 100644 index 00000000..8db647ce --- /dev/null +++ b/managed/XCEngine.ScriptCore/ScriptableRendererFeature.cs @@ -0,0 +1,31 @@ +namespace XCEngine +{ + public abstract class ScriptableRendererFeature + { + protected ScriptableRendererFeature() + { + } + + public bool isActive { get; set; } = true; + + public virtual void Create() + { + } + + public virtual void ConfigureCameraRenderRequest( + ScriptableRenderPipelineCameraRequestContext context) + { + } + + public virtual void ConfigureCameraFramePlan( + ScriptableRenderPipelinePlanningContext context) + { + } + + public virtual void AddRenderPasses( + ScriptableRenderer renderer, + RenderingData renderingData) + { + } + } +} diff --git a/managed/XCEngine.ScriptCore/ShadowData.cs b/managed/XCEngine.ScriptCore/ShadowData.cs new file mode 100644 index 00000000..a16046c6 --- /dev/null +++ b/managed/XCEngine.ScriptCore/ShadowData.cs @@ -0,0 +1,22 @@ +namespace XCEngine +{ + public sealed class ShadowData + { + internal static readonly ShadowData Default = + new ShadowData( + DirectionalShadowData.Default); + + internal ShadowData( + DirectionalShadowData mainDirectionalShadow) + { + this.mainDirectionalShadow = + mainDirectionalShadow ?? + DirectionalShadowData.Default; + } + + public DirectionalShadowData mainDirectionalShadow { get; } + + public bool hasMainDirectionalShadow => + mainDirectionalShadow.enabled; + } +} diff --git a/managed/XCEngine.ScriptCore/StageColorData.cs b/managed/XCEngine.ScriptCore/StageColorData.cs new file mode 100644 index 00000000..6122b777 --- /dev/null +++ b/managed/XCEngine.ScriptCore/StageColorData.cs @@ -0,0 +1,26 @@ +namespace XCEngine +{ + public sealed class StageColorData + { + internal static readonly StageColorData Default = + new StageColorData( + CameraFrameColorSource.ExplicitSurface, + false); + + internal StageColorData( + CameraFrameColorSource source, + bool usesGraphManagedOutputColor) + { + this.source = source; + this.usesGraphManagedOutputColor = + usesGraphManagedOutputColor; + } + + public CameraFrameColorSource source { get; } + + public bool usesGraphManagedSourceColor => + source != CameraFrameColorSource.ExplicitSurface; + + public bool usesGraphManagedOutputColor { get; } + } +} diff --git a/tests/Rendering/integration/object_id_scene/main.cpp b/tests/Rendering/integration/object_id_scene/main.cpp index c51b9638..721e081b 100644 --- a/tests/Rendering/integration/object_id_scene/main.cpp +++ b/tests/Rendering/integration/object_id_scene/main.cpp @@ -528,7 +528,7 @@ void ObjectIdSceneTest::RenderFrame() { request.surface = mainSurface; request.objectId.surface = objectIdSurface; - ASSERT_TRUE(mCameraRenderer->Render(request)); + ASSERT_TRUE(mCameraRenderer->Render(CameraFramePlan::FromRequest(request))); commandList->TransitionBarrier(backBufferView, mBackBufferState, ResourceStates::CopyDst); commandList->CopyResource(backBufferView, mObjectIdColorView); diff --git a/tests/Rendering/integration/post_process_scene/main.cpp b/tests/Rendering/integration/post_process_scene/main.cpp index a997dc8e..bb8c14c3 100644 --- a/tests/Rendering/integration/post_process_scene/main.cpp +++ b/tests/Rendering/integration/post_process_scene/main.cpp @@ -368,7 +368,7 @@ void PostProcessSceneTest::RenderFrame() { request.postProcess.destinationSurface = finalSurface; request.postProcess.passes = &mPostProcessPasses; - ASSERT_TRUE(mCameraRenderer->Render(request)); + ASSERT_TRUE(mCameraRenderer->Render(CameraFramePlan::FromRequest(request))); commandList->Close(); void* commandLists[] = { commandList }; diff --git a/tests/Scene/test_scene_runtime.cpp b/tests/Scene/test_scene_runtime.cpp index 9fa7b851..346e65b8 100644 --- a/tests/Scene/test_scene_runtime.cpp +++ b/tests/Scene/test_scene_runtime.cpp @@ -230,6 +230,12 @@ public: return false; } + bool TryGetAvailableRenderPipelineAssetClasses( + std::vector& outClasses) const override { + outClasses.clear(); + return false; + } + bool TryGetClassFieldMetadata( const std::string& assemblyName, const std::string& namespaceName, diff --git a/tests/scripting/test_mono_script_runtime.cpp b/tests/scripting/test_mono_script_runtime.cpp index c9234de0..c7475953 100644 --- a/tests/scripting/test_mono_script_runtime.cpp +++ b/tests/scripting/test_mono_script_runtime.cpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -65,6 +67,13 @@ void ExpectVector3Near(const XCEngine::Math::Vector3& actual, const XCEngine::Ma EXPECT_NEAR(actual.z, expected.z, tolerance); } +void ExpectVector4Near(const XCEngine::Math::Vector4& actual, const XCEngine::Math::Vector4& expected, float tolerance = 0.001f) { + EXPECT_NEAR(actual.x, expected.x, tolerance); + EXPECT_NEAR(actual.y, expected.y, tolerance); + EXPECT_NEAR(actual.z, expected.z, tolerance); + EXPECT_NEAR(actual.w, expected.w, tolerance); +} + class CapturingLogSink final : public XCEngine::Debug::ILogSink { public: void Log(const XCEngine::Debug::LogEntry& entry) override { @@ -206,6 +215,64 @@ TEST_F(MonoScriptRuntimeTest, ScriptClassDescriptorApiReturnsConcreteManagedType classes.end()); } +TEST_F( + MonoScriptRuntimeTest, + RenderPipelineAssetClassDescriptorApiReturnsConcretePipelineAssets) { + std::vector classes; + ASSERT_TRUE(runtime->TryGetAvailableRenderPipelineAssetClasses(classes)); + ASSERT_FALSE(classes.empty()); + + EXPECT_TRUE(std::is_sorted( + classes.begin(), + classes.end(), + [](const ScriptClassDescriptor& lhs, const ScriptClassDescriptor& rhs) { + if (lhs.assemblyName != rhs.assemblyName) { + return lhs.assemblyName < rhs.assemblyName; + } + if (lhs.namespaceName != rhs.namespaceName) { + return lhs.namespaceName < rhs.namespaceName; + } + return lhs.className < rhs.className; + })); + + EXPECT_NE( + std::find( + classes.begin(), + classes.end(), + ScriptClassDescriptor{ + "GameScripts", + "Gameplay", + "RenderPipelineApiProbeAsset"}), + classes.end()); + EXPECT_NE( + std::find( + classes.begin(), + classes.end(), + ScriptClassDescriptor{ + "GameScripts", + "Gameplay", + "ManagedRenderPipelineProbeAsset"}), + classes.end()); + EXPECT_NE( + std::find( + classes.begin(), + classes.end(), + ScriptClassDescriptor{ + "GameScripts", + "Gameplay", + "ManagedForwardRenderPipelineProbeAsset"}), + classes.end()); + EXPECT_EQ( + std::find( + classes.begin(), + classes.end(), + ScriptClassDescriptor{ + "GameScripts", + "Gameplay", + "LegacyRenderPipelineApiProbeAsset"}), + classes.end()); +} + TEST_F(MonoScriptRuntimeTest, ClassFieldMetadataListsSupportedPublicInstanceFields) { std::vector fields; @@ -343,6 +410,107 @@ TEST_F(MonoScriptRuntimeTest, ManagedGraphicsSettingsRoundTripsRenderPipelineAss "Gameplay.RenderPipelineApiProbeAsset"); } +TEST_F( + MonoScriptRuntimeTest, + ManagedGraphicsSettingsRoundTripsScriptCoreForwardRenderPipelineAssetSelection) { + Scene* runtimeScene = + CreateScene("ScriptCoreForwardRenderPipelineSelectionScene"); + GameObject* scriptObject = + runtimeScene->CreateGameObject("ScriptCoreForwardRenderPipelineProbe"); + ScriptComponent* script = + AddScript( + scriptObject, + "Gameplay", + "ScriptCoreForwardRenderPipelineSelectionProbe"); + ASSERT_NE(script, nullptr); + + engine->OnRuntimeStart(runtimeScene); + engine->OnUpdate(0.016f); + + const XCEngine::Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor descriptor = + XCEngine::Rendering::Pipelines::GetManagedRenderPipelineAssetDescriptor(); + EXPECT_EQ(descriptor.assemblyName, "XCEngine.ScriptCore"); + EXPECT_EQ(descriptor.namespaceName, "XCEngine"); + EXPECT_EQ(descriptor.className, "ForwardRenderPipelineAsset"); + EXPECT_NE(descriptor.managedAssetHandle, 0u); + + bool selectionRoundTripSucceeded = false; + std::string selectedPipelineAssetTypeName; + std::string selectedRendererDataTypeName; + EXPECT_TRUE(runtime->TryGetFieldValue( + script, + "SelectionRoundTripSucceeded", + selectionRoundTripSucceeded)); + EXPECT_TRUE(selectionRoundTripSucceeded); + EXPECT_TRUE(runtime->TryGetFieldValue( + script, + "SelectedPipelineAssetTypeName", + selectedPipelineAssetTypeName)); + EXPECT_EQ( + selectedPipelineAssetTypeName, + "XCEngine.ForwardRenderPipelineAsset"); + EXPECT_TRUE(runtime->TryGetFieldValue( + script, + "SelectedRendererDataTypeName", + selectedRendererDataTypeName)); + EXPECT_EQ( + selectedRendererDataTypeName, + "XCEngine.ForwardRendererData"); +} + +TEST_F( + MonoScriptRuntimeTest, + ManagedGraphicsSettingsGetterMaterializesConfiguredAssetWithoutExistingHandle) { + Scene* runtimeScene = + CreateScene("ManagedRenderPipelineGetterMaterializationScene"); + GameObject* scriptObject = + runtimeScene->CreateGameObject("RenderPipelineGetterProbe"); + ScriptComponent* script = + AddScript( + scriptObject, + "Gameplay", + "ProjectConfiguredRenderPipelineGetterProbe"); + ASSERT_NE(script, nullptr); + + XCEngine::Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor + configuredDescriptor = {}; + configuredDescriptor.assemblyName = "GameScripts"; + configuredDescriptor.namespaceName = "Gameplay"; + configuredDescriptor.className = "RenderPipelineApiProbeAsset"; + XCEngine::Rendering::Pipelines::SetManagedRenderPipelineAssetDescriptor( + configuredDescriptor); + + engine->OnRuntimeStart(runtimeScene); + engine->OnUpdate(0.016f); + + const XCEngine::Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor + resolvedDescriptor = + XCEngine::Rendering::Pipelines::GetManagedRenderPipelineAssetDescriptor(); + EXPECT_EQ(resolvedDescriptor.assemblyName, configuredDescriptor.assemblyName); + EXPECT_EQ(resolvedDescriptor.namespaceName, configuredDescriptor.namespaceName); + EXPECT_EQ(resolvedDescriptor.className, configuredDescriptor.className); + EXPECT_NE(resolvedDescriptor.managedAssetHandle, 0u); + EXPECT_NE( + runtime->GetExternalManagedObject( + resolvedDescriptor.managedAssetHandle), + nullptr); + + bool observedAssetWasNull = true; + std::string observedPipelineAssetTypeName; + EXPECT_TRUE(runtime->TryGetFieldValue( + script, + "ObservedAssetWasNull", + observedAssetWasNull)); + EXPECT_FALSE(observedAssetWasNull); + EXPECT_TRUE(runtime->TryGetFieldValue( + script, + "ObservedPipelineAssetTypeName", + observedPipelineAssetTypeName)); + EXPECT_EQ( + observedPipelineAssetTypeName, + "Gameplay.RenderPipelineApiProbeAsset"); +} + TEST_F( MonoScriptRuntimeTest, RuntimeStopClearsManagedGraphicsSettingsSelection) { @@ -502,10 +670,12 @@ TEST_F( ASSERT_NE(host->GetStageRecorder(), nullptr); EXPECT_TRUE( host->GetStageRecorder()->Initialize( - XCEngine::Rendering::RenderContext{})); + XCEngine::Rendering::RenderContext{})) + << runtime->GetLastError(); EXPECT_TRUE( host->SupportsStageRenderGraph( - XCEngine::Rendering::CameraFrameStage::MainScene)); + XCEngine::Rendering::CameraFrameStage::MainScene)) + << runtime->GetLastError(); XCEngine::Rendering::RenderGraph graph; XCEngine::Rendering::RenderGraphBuilder graphBuilder(graph); @@ -541,11 +711,13 @@ TEST_F( {}, { colorTarget }, depthTarget, + {}, &executionSucceeded, &blackboard }; - EXPECT_TRUE(host->GetStageRecorder()->RecordStageRenderGraph(graphContext)); + EXPECT_TRUE(host->GetStageRecorder()->RecordStageRenderGraph(graphContext)) + << runtime->GetLastError(); XCEngine::Rendering::CompiledRenderGraph compiledGraph = {}; XCEngine::Containers::String errorMessage; @@ -569,6 +741,106 @@ TEST_F( host->GetStageRecorder()->Shutdown(); } +TEST_F( + MonoScriptRuntimeTest, + DefaultCameraRendererUsesScriptCoreForwardPipelineAssetAndRespectsRendererData) { + Scene* runtimeScene = + CreateScene("ScriptCoreForwardRenderPipelineDefaultRendererScene"); + GameObject* selectionObject = + runtimeScene->CreateGameObject("ScriptCoreForwardRenderPipelineSelection"); + ScriptComponent* selectionScript = + AddScript( + selectionObject, + "Gameplay", + "ScriptCoreConfiguredForwardRenderPipelineRuntimeSelectionProbe"); + ASSERT_NE(selectionScript, nullptr); + + engine->OnRuntimeStart(runtimeScene); + engine->OnUpdate(0.016f); + + XCEngine::Rendering::CameraRenderer renderer; + const auto* asset = + dynamic_cast< + const XCEngine::Rendering::Pipelines::ManagedScriptableRenderPipelineAsset*>( + renderer.GetPipelineAsset()); + ASSERT_NE(asset, nullptr); + EXPECT_EQ(asset->GetDescriptor().assemblyName, "XCEngine.ScriptCore"); + EXPECT_EQ(asset->GetDescriptor().namespaceName, "XCEngine"); + EXPECT_EQ(asset->GetDescriptor().className, "ForwardRenderPipelineAsset"); + + auto* host = + dynamic_cast( + renderer.GetPipeline()); + ASSERT_NE(host, nullptr); + ASSERT_NE(host->GetStageRecorder(), nullptr); + EXPECT_TRUE( + host->GetStageRecorder()->Initialize( + XCEngine::Rendering::RenderContext{})); + EXPECT_TRUE( + host->SupportsStageRenderGraph( + XCEngine::Rendering::CameraFrameStage::MainScene)); + + XCEngine::Rendering::RenderGraph graph; + XCEngine::Rendering::RenderGraphBuilder graphBuilder(graph); + XCEngine::Rendering::RenderGraphTextureDesc colorDesc = {}; + colorDesc.width = 64u; + colorDesc.height = 64u; + colorDesc.format = + static_cast( + XCEngine::RHI::Format::R8G8B8A8_UNorm); + XCEngine::Rendering::RenderGraphTextureDesc depthDesc = colorDesc; + depthDesc.format = + static_cast( + XCEngine::RHI::Format::D32_Float); + const XCEngine::Rendering::RenderGraphTextureHandle colorTarget = + graphBuilder.CreateTransientTexture( + "ScriptCoreForwardMainSceneColor", + colorDesc); + const XCEngine::Rendering::RenderGraphTextureHandle depthTarget = + graphBuilder.CreateTransientTexture( + "ScriptCoreForwardMainSceneDepth", + depthDesc); + + const XCEngine::Rendering::RenderSceneData sceneData = {}; + const XCEngine::Rendering::RenderSurface surface(64u, 64u); + bool executionSucceeded = true; + XCEngine::Rendering::RenderGraphBlackboard blackboard = {}; + const XCEngine::Rendering::RenderPipelineStageRenderGraphContext graphContext = { + graphBuilder, + "ScriptCoreForwardMainScene", + XCEngine::Rendering::CameraFrameStage::MainScene, + {}, + sceneData, + surface, + nullptr, + nullptr, + XCEngine::RHI::ResourceStates::Common, + {}, + { colorTarget }, + depthTarget, + {}, + &executionSucceeded, + &blackboard + }; + + EXPECT_TRUE(host->GetStageRecorder()->RecordStageRenderGraph(graphContext)); + + XCEngine::Rendering::CompiledRenderGraph compiledGraph = {}; + XCEngine::Containers::String errorMessage; + ASSERT_TRUE( + XCEngine::Rendering::RenderGraphCompiler::Compile( + graph, + compiledGraph, + &errorMessage)) + << errorMessage.CStr(); + ASSERT_EQ(compiledGraph.GetPassCount(), 1u); + EXPECT_STREQ( + compiledGraph.GetPassName(0).CStr(), + "ScriptCoreForwardMainScene.Opaque"); + + host->GetStageRecorder()->Shutdown(); +} + TEST_F( MonoScriptRuntimeTest, DefaultSceneRendererUsesManagedForwardPipelineForPlannedMainSceneAndPostProcessRender) { @@ -693,6 +965,1226 @@ TEST_F( EXPECT_FLOAT_EQ(observedPostProcessScale.w, 1.0f); } +TEST_F( + MonoScriptRuntimeTest, + DefaultSceneRendererUsesScriptCoreForwardRendererFeatureForPlannedPostProcessRender) { + Scene* runtimeScene = + CreateScene("ScriptCoreForwardRendererFeatureSceneRendererScene"); + GameObject* selectionObject = + runtimeScene->CreateGameObject("ScriptCoreForwardRendererFeatureSelection"); + ScriptComponent* selectionScript = + AddScript( + selectionObject, + "Gameplay", + "ScriptCoreForwardPostProcessRendererFeatureRuntimeSelectionProbe"); + ASSERT_NE(selectionScript, nullptr); + + GameObject* cameraObject = runtimeScene->CreateGameObject("Camera"); + auto* camera = cameraObject->AddComponent(); + ASSERT_NE(camera, nullptr); + camera->SetPrimary(true); + + engine->OnRuntimeStart(runtimeScene); + engine->OnUpdate(0.016f); + + TestRenderDevice device; + TestRenderCommandList commandList; + TestRenderCommandQueue commandQueue; + TestRenderResourceView colorView( + XCEngine::RHI::ResourceViewType::RenderTarget, + XCEngine::RHI::ResourceViewDimension::Texture2D, + XCEngine::RHI::Format::R8G8B8A8_UNorm); + TestRenderResourceView depthView( + XCEngine::RHI::ResourceViewType::DepthStencil, + XCEngine::RHI::ResourceViewDimension::Texture2D, + XCEngine::RHI::Format::D32_Float); + + const XCEngine::Rendering::RenderContext context = + CreateRenderContext( + device, + commandList, + commandQueue); + XCEngine::Rendering::RenderSurface surface(64u, 64u); + surface.SetColorAttachment(&colorView); + surface.SetDepthAttachment(&depthView); + + XCEngine::Rendering::SceneRenderer renderer; + const auto* pipelineAsset = + dynamic_cast< + const XCEngine::Rendering::Pipelines::ManagedScriptableRenderPipelineAsset*>( + renderer.GetPipelineAsset()); + ASSERT_NE(pipelineAsset, nullptr); + EXPECT_EQ(pipelineAsset->GetDescriptor().assemblyName, "XCEngine.ScriptCore"); + EXPECT_EQ(pipelineAsset->GetDescriptor().namespaceName, "XCEngine"); + EXPECT_EQ( + pipelineAsset->GetDescriptor().className, + "ForwardRenderPipelineAsset"); + + const std::vector plans = + renderer.BuildFramePlans( + *runtimeScene, + nullptr, + context, + surface); + ASSERT_EQ(plans.size(), 1u); + EXPECT_TRUE(plans[0].UsesGraphManagedSceneColor()); + EXPECT_TRUE( + plans[0].IsFullscreenStageRequested( + XCEngine::Rendering::CameraFrameStage::PostProcess)); + EXPECT_TRUE(plans[0].IsPostProcessStageValid()); + EXPECT_EQ( + plans[0].ResolveStageColorSource( + XCEngine::Rendering::CameraFrameStage::PostProcess), + XCEngine::Rendering::CameraFrameColorSource::MainSceneColor); + + ASSERT_TRUE(renderer.Render(plans)); + EXPECT_EQ(commandList.drawCalls, 1u); + EXPECT_GT(device.createTextureCalls, 0u); + EXPECT_GT(device.createPipelineLayoutCalls, 0u); + EXPECT_GT(device.createPipelineStateCalls, 0u); +} + +TEST_F( + MonoScriptRuntimeTest, + ScriptCoreForwardRendererFeatureConfiguresCameraRequestPolicy) { + Scene* runtimeScene = + CreateScene("ScriptCoreForwardRendererFeatureCameraRequestScene"); + + GameObject* selectionObject = + runtimeScene->CreateGameObject("ScriptCoreForwardCameraRequestSelection"); + ScriptComponent* selectionScript = + AddScript( + selectionObject, + "Gameplay", + "ScriptCoreForwardShadowlessRendererFeatureRuntimeSelectionProbe"); + ASSERT_NE(selectionScript, nullptr); + + GameObject* cameraObject = runtimeScene->CreateGameObject("Camera"); + auto* camera = cameraObject->AddComponent(); + ASSERT_NE(camera, nullptr); + camera->SetPrimary(true); + + GameObject* lightObject = runtimeScene->CreateGameObject("Light"); + auto* light = lightObject->AddComponent(); + ASSERT_NE(light, nullptr); + light->SetLightType(LightType::Directional); + light->SetCastsShadows(true); + + engine->OnRuntimeStart(runtimeScene); + engine->OnUpdate(0.016f); + + XCEngine::Rendering::CameraRenderRequest baselineRequest = {}; + baselineRequest.scene = runtimeScene; + baselineRequest.camera = camera; + baselineRequest.surface = XCEngine::Rendering::RenderSurface(64u, 64u); + XCEngine::Rendering::ApplyDefaultRenderPipelineAssetCameraRenderRequestPolicy( + baselineRequest, + 0u, + 0u, + XCEngine::Rendering::DirectionalShadowPlanningSettings{}); + ASSERT_TRUE(baselineRequest.directionalShadow.IsValid()); + + XCEngine::Rendering::CameraRenderer renderer; + const auto* pipelineAsset = + dynamic_cast< + const XCEngine::Rendering::Pipelines::ManagedScriptableRenderPipelineAsset*>( + renderer.GetPipelineAsset()); + ASSERT_NE(pipelineAsset, nullptr); + EXPECT_EQ(pipelineAsset->GetDescriptor().assemblyName, "XCEngine.ScriptCore"); + EXPECT_EQ(pipelineAsset->GetDescriptor().namespaceName, "XCEngine"); + EXPECT_EQ( + pipelineAsset->GetDescriptor().className, + "ForwardRenderPipelineAsset"); + + XCEngine::Rendering::CameraRenderRequest request = {}; + request.scene = runtimeScene; + request.camera = camera; + request.surface = XCEngine::Rendering::RenderSurface(64u, 64u); + pipelineAsset->ConfigureCameraRenderRequest( + request, + 0u, + 0u, + XCEngine::Rendering::DirectionalShadowPlanningSettings{}); + + EXPECT_FALSE(request.directionalShadow.IsValid()); +} + +TEST_F( + MonoScriptRuntimeTest, + ManagedRenderContextExposesCameraDataThroughRenderingData) { + Scene* runtimeScene = + CreateScene("ManagedRenderContextCameraDataScene"); + GameObject* selectionObject = + runtimeScene->CreateGameObject("ManagedRenderContextCameraDataSelection"); + ScriptComponent* selectionScript = + AddScript( + selectionObject, + "Gameplay", + "ManagedRenderContextCameraDataRuntimeSelectionProbe"); + ASSERT_NE(selectionScript, nullptr); + + GameObject* cameraObject = runtimeScene->CreateGameObject("Camera"); + auto* camera = cameraObject->AddComponent(); + ASSERT_NE(camera, nullptr); + camera->SetPrimary(true); + camera->SetProjectionType(CameraProjectionType::Orthographic); + camera->SetFieldOfView(75.0f); + camera->SetOrthographicSize(7.5f); + camera->SetNearClipPlane(0.25f); + camera->SetFarClipPlane(512.0f); + camera->SetClearMode(CameraClearMode::DepthOnly); + camera->SetClearColor( + XCEngine::Math::Color(0.12f, 0.34f, 0.56f, 0.78f)); + cameraObject->GetTransform()->SetLocalPosition( + XCEngine::Math::Vector3(2.0f, 4.0f, 6.0f)); + + engine->OnRuntimeStart(runtimeScene); + engine->OnUpdate(0.016f); + + TestRenderDevice device; + TestRenderCommandList commandList; + TestRenderCommandQueue commandQueue; + TestRenderResourceView colorView( + XCEngine::RHI::ResourceViewType::RenderTarget, + XCEngine::RHI::ResourceViewDimension::Texture2D, + XCEngine::RHI::Format::R8G8B8A8_UNorm); + TestRenderResourceView depthView( + XCEngine::RHI::ResourceViewType::DepthStencil, + XCEngine::RHI::ResourceViewDimension::Texture2D, + XCEngine::RHI::Format::D32_Float); + + const XCEngine::Rendering::RenderContext context = + CreateRenderContext( + device, + commandList, + commandQueue); + XCEngine::Rendering::RenderSurface surface(160u, 90u); + surface.SetColorAttachment(&colorView); + surface.SetDepthAttachment(&depthView); + + XCEngine::Rendering::SceneRenderer renderer; + const auto* pipelineAsset = + dynamic_cast< + const XCEngine::Rendering::Pipelines::ManagedScriptableRenderPipelineAsset*>( + renderer.GetPipelineAsset()); + ASSERT_NE(pipelineAsset, nullptr); + EXPECT_EQ(pipelineAsset->GetDescriptor().assemblyName, "GameScripts"); + EXPECT_EQ(pipelineAsset->GetDescriptor().namespaceName, "Gameplay"); + EXPECT_EQ( + pipelineAsset->GetDescriptor().className, + "ManagedRenderContextCameraDataProbeAsset"); + + const std::vector plans = + renderer.BuildFramePlans( + *runtimeScene, + nullptr, + context, + surface); + ASSERT_EQ(plans.size(), 1u); + ASSERT_TRUE(renderer.Render(plans)); + + engine->OnUpdate(0.016f); + + const XCEngine::Rendering::RenderCameraData expectedCameraData = + XCEngine::Rendering::BuildRenderCameraData( + *camera, + 160u, + 90u); + + XCEngine::Math::Vector4 observedViewRow0 = {}; + XCEngine::Math::Vector4 observedViewRow1 = {}; + XCEngine::Math::Vector4 observedViewRow2 = {}; + XCEngine::Math::Vector4 observedViewRow3 = {}; + XCEngine::Math::Vector4 observedProjectionRow0 = {}; + XCEngine::Math::Vector4 observedProjectionRow1 = {}; + XCEngine::Math::Vector4 observedProjectionRow2 = {}; + XCEngine::Math::Vector4 observedProjectionRow3 = {}; + XCEngine::Math::Vector4 observedViewProjectionRow0 = {}; + XCEngine::Math::Vector4 observedViewProjectionRow1 = {}; + XCEngine::Math::Vector4 observedViewProjectionRow2 = {}; + XCEngine::Math::Vector4 observedViewProjectionRow3 = {}; + XCEngine::Math::Vector3 observedWorldPosition = {}; + XCEngine::Math::Vector4 observedClearColor = {}; + int observedClearFlags = 0; + bool observedPerspectiveProjection = true; + float observedVerticalFovRadians = 0.0f; + float observedOrthographicSize = 0.0f; + float observedAspectRatio = 0.0f; + float observedNearClipPlane = 0.0f; + float observedFarClipPlane = 0.0f; + int observedViewportWidth = 0; + int observedViewportHeight = 0; + int observedRecordCallCount = 0; + + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedViewRow0", + observedViewRow0)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedViewRow1", + observedViewRow1)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedViewRow2", + observedViewRow2)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedViewRow3", + observedViewRow3)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedProjectionRow0", + observedProjectionRow0)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedProjectionRow1", + observedProjectionRow1)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedProjectionRow2", + observedProjectionRow2)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedProjectionRow3", + observedProjectionRow3)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedViewProjectionRow0", + observedViewProjectionRow0)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedViewProjectionRow1", + observedViewProjectionRow1)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedViewProjectionRow2", + observedViewProjectionRow2)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedViewProjectionRow3", + observedViewProjectionRow3)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedWorldPosition", + observedWorldPosition)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedClearColor", + observedClearColor)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedClearFlags", + observedClearFlags)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedPerspectiveProjection", + observedPerspectiveProjection)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedVerticalFovRadians", + observedVerticalFovRadians)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedOrthographicSize", + observedOrthographicSize)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedAspectRatio", + observedAspectRatio)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedNearClipPlane", + observedNearClipPlane)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedFarClipPlane", + observedFarClipPlane)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedViewportWidth", + observedViewportWidth)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedViewportHeight", + observedViewportHeight)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedRecordCallCount", + observedRecordCallCount)); + + const auto expectObservedRowMatchesMatrix = []( + const XCEngine::Math::Vector4& observedRow, + const XCEngine::Math::Matrix4x4& expectedMatrix, + int rowIndex) { + ExpectVector4Near( + observedRow, + XCEngine::Math::Vector4( + expectedMatrix.m[rowIndex][0], + expectedMatrix.m[rowIndex][1], + expectedMatrix.m[rowIndex][2], + expectedMatrix.m[rowIndex][3])); + }; + + EXPECT_EQ(observedRecordCallCount, 1); + expectObservedRowMatchesMatrix( + observedViewRow0, + expectedCameraData.view, + 0); + expectObservedRowMatchesMatrix( + observedViewRow1, + expectedCameraData.view, + 1); + expectObservedRowMatchesMatrix( + observedViewRow2, + expectedCameraData.view, + 2); + expectObservedRowMatchesMatrix( + observedViewRow3, + expectedCameraData.view, + 3); + expectObservedRowMatchesMatrix( + observedProjectionRow0, + expectedCameraData.projection, + 0); + expectObservedRowMatchesMatrix( + observedProjectionRow1, + expectedCameraData.projection, + 1); + expectObservedRowMatchesMatrix( + observedProjectionRow2, + expectedCameraData.projection, + 2); + expectObservedRowMatchesMatrix( + observedProjectionRow3, + expectedCameraData.projection, + 3); + expectObservedRowMatchesMatrix( + observedViewProjectionRow0, + expectedCameraData.viewProjection, + 0); + expectObservedRowMatchesMatrix( + observedViewProjectionRow1, + expectedCameraData.viewProjection, + 1); + expectObservedRowMatchesMatrix( + observedViewProjectionRow2, + expectedCameraData.viewProjection, + 2); + expectObservedRowMatchesMatrix( + observedViewProjectionRow3, + expectedCameraData.viewProjection, + 3); + EXPECT_FLOAT_EQ(observedWorldPosition.x, 2.0f); + EXPECT_FLOAT_EQ(observedWorldPosition.y, 4.0f); + EXPECT_FLOAT_EQ(observedWorldPosition.z, 6.0f); + EXPECT_FLOAT_EQ(observedClearColor.x, 0.12f); + EXPECT_FLOAT_EQ(observedClearColor.y, 0.34f); + EXPECT_FLOAT_EQ(observedClearColor.z, 0.56f); + EXPECT_FLOAT_EQ(observedClearColor.w, 0.78f); + EXPECT_EQ( + observedClearFlags, + static_cast(XCEngine::Rendering::RenderClearFlags::Depth)); + EXPECT_FALSE(observedPerspectiveProjection); + EXPECT_FLOAT_EQ( + observedVerticalFovRadians, + 75.0f * XCEngine::Math::DEG_TO_RAD); + EXPECT_FLOAT_EQ(observedOrthographicSize, 7.5f); + EXPECT_FLOAT_EQ(observedAspectRatio, 160.0f / 90.0f); + EXPECT_FLOAT_EQ(observedNearClipPlane, 0.25f); + EXPECT_FLOAT_EQ(observedFarClipPlane, 512.0f); + EXPECT_EQ(observedViewportWidth, 160); + EXPECT_EQ(observedViewportHeight, 90); +} + +TEST_F( + MonoScriptRuntimeTest, + ManagedRenderContextExposesLightingDataThroughRenderingData) { + Scene* runtimeScene = + CreateScene("ManagedRenderContextLightingDataScene"); + GameObject* selectionObject = + runtimeScene->CreateGameObject( + "ManagedRenderContextLightingDataSelection"); + ScriptComponent* selectionScript = + AddScript( + selectionObject, + "Gameplay", + "ManagedRenderContextLightingDataRuntimeSelectionProbe"); + ASSERT_NE(selectionScript, nullptr); + + GameObject* cameraObject = runtimeScene->CreateGameObject("Camera"); + auto* camera = cameraObject->AddComponent(); + ASSERT_NE(camera, nullptr); + camera->SetPrimary(true); + + GameObject* directionalLightObject = + runtimeScene->CreateGameObject("DirectionalLight"); + auto* directionalLight = + directionalLightObject->AddComponent(); + ASSERT_NE(directionalLight, nullptr); + directionalLight->SetLightType(LightType::Directional); + directionalLight->SetColor( + XCEngine::Math::Color(0.25f, 0.50f, 0.75f, 1.0f)); + directionalLight->SetIntensity(2.75f); + directionalLight->SetCastsShadows(true); + directionalLightObject->GetTransform()->SetLocalEulerAngles( + XCEngine::Math::Vector3(25.0f, -40.0f, 0.0f)); + + GameObject* pointLightObject = + runtimeScene->CreateGameObject("PointLight"); + auto* pointLight = + pointLightObject->AddComponent(); + ASSERT_NE(pointLight, nullptr); + pointLight->SetLightType(LightType::Point); + pointLight->SetColor( + XCEngine::Math::Color(0.9f, 0.3f, 0.2f, 1.0f)); + pointLight->SetIntensity(1.25f); + pointLight->SetRange(15.0f); + pointLight->SetCastsShadows(false); + pointLightObject->GetTransform()->SetLocalPosition( + XCEngine::Math::Vector3(3.0f, 2.0f, -1.0f)); + + engine->OnRuntimeStart(runtimeScene); + engine->OnUpdate(0.016f); + + TestRenderDevice device; + TestRenderCommandList commandList; + TestRenderCommandQueue commandQueue; + TestRenderResourceView colorView( + XCEngine::RHI::ResourceViewType::RenderTarget, + XCEngine::RHI::ResourceViewDimension::Texture2D, + XCEngine::RHI::Format::R8G8B8A8_UNorm); + TestRenderResourceView depthView( + XCEngine::RHI::ResourceViewType::DepthStencil, + XCEngine::RHI::ResourceViewDimension::Texture2D, + XCEngine::RHI::Format::D32_Float); + + const XCEngine::Rendering::RenderContext context = + CreateRenderContext( + device, + commandList, + commandQueue); + XCEngine::Rendering::RenderSurface surface(192u, 108u); + surface.SetColorAttachment(&colorView); + surface.SetDepthAttachment(&depthView); + + XCEngine::Rendering::SceneRenderer renderer; + const auto* pipelineAsset = + dynamic_cast< + const XCEngine::Rendering::Pipelines::ManagedScriptableRenderPipelineAsset*>( + renderer.GetPipelineAsset()); + ASSERT_NE(pipelineAsset, nullptr); + EXPECT_EQ(pipelineAsset->GetDescriptor().assemblyName, "GameScripts"); + EXPECT_EQ(pipelineAsset->GetDescriptor().namespaceName, "Gameplay"); + EXPECT_EQ( + pipelineAsset->GetDescriptor().className, + "ManagedRenderContextCameraDataProbeAsset"); + + const std::vector plans = + renderer.BuildFramePlans( + *runtimeScene, + nullptr, + context, + surface); + ASSERT_EQ(plans.size(), 1u); + ASSERT_TRUE(renderer.Render(plans)); + + engine->OnUpdate(0.016f); + + XCEngine::Rendering::RenderSceneExtractor extractor; + const XCEngine::Rendering::RenderSceneData expectedSceneData = + extractor.ExtractForCamera( + *runtimeScene, + *camera, + 192u, + 108u); + ASSERT_TRUE(expectedSceneData.HasCamera()); + + bool observedMainDirectionalLightEnabled = false; + bool observedMainDirectionalLightCastsShadows = false; + XCEngine::Math::Vector3 observedMainDirectionalLightDirection = {}; + XCEngine::Math::Vector4 observedMainDirectionalLightColor = {}; + float observedMainDirectionalLightIntensity = 0.0f; + bool observedHasMainDirectionalShadow = false; + int observedAdditionalLightCount = 0; + int observedRecordCallCount = 0; + + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedMainDirectionalLightEnabled", + observedMainDirectionalLightEnabled)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedMainDirectionalLightCastsShadows", + observedMainDirectionalLightCastsShadows)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedMainDirectionalLightDirection", + observedMainDirectionalLightDirection)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedMainDirectionalLightColor", + observedMainDirectionalLightColor)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedMainDirectionalLightIntensity", + observedMainDirectionalLightIntensity)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedHasMainDirectionalShadow", + observedHasMainDirectionalShadow)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedAdditionalLightCount", + observedAdditionalLightCount)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedRecordCallCount", + observedRecordCallCount)); + + EXPECT_EQ(observedRecordCallCount, 1); + EXPECT_EQ( + observedMainDirectionalLightEnabled, + expectedSceneData.lighting.mainDirectionalLight.enabled); + EXPECT_EQ( + observedMainDirectionalLightCastsShadows, + expectedSceneData.lighting.mainDirectionalLight.castsShadows); + ExpectVector3Near( + observedMainDirectionalLightDirection, + expectedSceneData.lighting.mainDirectionalLight.direction); + ExpectVector4Near( + observedMainDirectionalLightColor, + XCEngine::Math::Vector4( + expectedSceneData.lighting.mainDirectionalLight.color.r, + expectedSceneData.lighting.mainDirectionalLight.color.g, + expectedSceneData.lighting.mainDirectionalLight.color.b, + expectedSceneData.lighting.mainDirectionalLight.color.a)); + EXPECT_FLOAT_EQ( + observedMainDirectionalLightIntensity, + expectedSceneData.lighting.mainDirectionalLight.intensity); + EXPECT_EQ( + observedHasMainDirectionalShadow, + plans[0].directionalShadow.IsValid()); + EXPECT_EQ( + observedAdditionalLightCount, + static_cast(expectedSceneData.lighting.additionalLightCount)); +} + +TEST_F( + MonoScriptRuntimeTest, + ManagedRenderContextExposesShadowDataThroughRenderingData) { + Scene* runtimeScene = + CreateScene("ManagedRenderContextShadowDataScene"); + GameObject* selectionObject = + runtimeScene->CreateGameObject( + "ManagedRenderContextShadowDataSelection"); + ScriptComponent* selectionScript = + AddScript( + selectionObject, + "Gameplay", + "ManagedRenderContextShadowDataRuntimeSelectionProbe"); + ASSERT_NE(selectionScript, nullptr); + + GameObject* cameraObject = runtimeScene->CreateGameObject("Camera"); + auto* camera = cameraObject->AddComponent(); + ASSERT_NE(camera, nullptr); + camera->SetPrimary(true); + + GameObject* directionalLightObject = + runtimeScene->CreateGameObject("DirectionalLight"); + auto* directionalLight = + directionalLightObject->AddComponent(); + ASSERT_NE(directionalLight, nullptr); + directionalLight->SetLightType(LightType::Directional); + directionalLight->SetColor( + XCEngine::Math::Color(0.25f, 0.50f, 0.75f, 1.0f)); + directionalLight->SetIntensity(2.75f); + directionalLight->SetCastsShadows(true); + directionalLightObject->GetTransform()->SetLocalEulerAngles( + XCEngine::Math::Vector3(25.0f, -40.0f, 0.0f)); + + engine->OnRuntimeStart(runtimeScene); + engine->OnUpdate(0.016f); + + TestRenderDevice device; + TestRenderCommandList commandList; + TestRenderCommandQueue commandQueue; + TestRenderResourceView colorView( + XCEngine::RHI::ResourceViewType::RenderTarget, + XCEngine::RHI::ResourceViewDimension::Texture2D, + XCEngine::RHI::Format::R8G8B8A8_UNorm); + TestRenderResourceView depthView( + XCEngine::RHI::ResourceViewType::DepthStencil, + XCEngine::RHI::ResourceViewDimension::Texture2D, + XCEngine::RHI::Format::D32_Float); + + const XCEngine::Rendering::RenderContext context = + CreateRenderContext( + device, + commandList, + commandQueue); + XCEngine::Rendering::RenderSurface surface(192u, 108u); + surface.SetColorAttachment(&colorView); + surface.SetDepthAttachment(&depthView); + + XCEngine::Rendering::SceneRenderer renderer; + const std::vector plans = + renderer.BuildFramePlans( + *runtimeScene, + nullptr, + context, + surface); + ASSERT_EQ(plans.size(), 1u); + ASSERT_TRUE(plans[0].directionalShadow.IsValid()); + ASSERT_TRUE(renderer.Render(plans)); + + engine->OnUpdate(0.016f); + + bool observedShadowEnabled = false; + XCEngine::Math::Vector4 observedShadowViewProjectionRow0 = {}; + XCEngine::Math::Vector4 observedShadowViewProjectionRow1 = {}; + XCEngine::Math::Vector4 observedShadowViewProjectionRow2 = {}; + XCEngine::Math::Vector4 observedShadowViewProjectionRow3 = {}; + float observedShadowOrthographicHalfExtent = 0.0f; + float observedShadowNearClipPlane = 0.0f; + float observedShadowFarClipPlane = 0.0f; + int observedShadowMapWidth = 0; + int observedShadowMapHeight = 0; + float observedShadowWorldTexelSize = 0.0f; + float observedShadowReceiverDepthBias = 0.0f; + float observedShadowNormalBiasScale = 0.0f; + float observedShadowStrength = 0.0f; + float observedShadowDepthBiasFactor = 0.0f; + int observedShadowDepthBiasUnits = 0; + int observedRecordCallCount = 0; + + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedShadowEnabled", + observedShadowEnabled)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedShadowViewProjectionRow0", + observedShadowViewProjectionRow0)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedShadowViewProjectionRow1", + observedShadowViewProjectionRow1)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedShadowViewProjectionRow2", + observedShadowViewProjectionRow2)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedShadowViewProjectionRow3", + observedShadowViewProjectionRow3)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedShadowOrthographicHalfExtent", + observedShadowOrthographicHalfExtent)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedShadowNearClipPlane", + observedShadowNearClipPlane)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedShadowFarClipPlane", + observedShadowFarClipPlane)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedShadowMapWidth", + observedShadowMapWidth)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedShadowMapHeight", + observedShadowMapHeight)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedShadowWorldTexelSize", + observedShadowWorldTexelSize)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedShadowReceiverDepthBias", + observedShadowReceiverDepthBias)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedShadowNormalBiasScale", + observedShadowNormalBiasScale)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedShadowStrength", + observedShadowStrength)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedShadowDepthBiasFactor", + observedShadowDepthBiasFactor)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedShadowDepthBiasUnits", + observedShadowDepthBiasUnits)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedRecordCallCount", + observedRecordCallCount)); + + const XCEngine::Rendering::DirectionalShadowRenderPlan& + expectedShadowPlan = plans[0].directionalShadow; + + const auto expectObservedRowMatchesMatrix = []( + const XCEngine::Math::Vector4& observedRow, + const XCEngine::Math::Matrix4x4& expectedMatrix, + int rowIndex) { + ExpectVector4Near( + observedRow, + XCEngine::Math::Vector4( + expectedMatrix.m[rowIndex][0], + expectedMatrix.m[rowIndex][1], + expectedMatrix.m[rowIndex][2], + expectedMatrix.m[rowIndex][3])); + }; + + EXPECT_EQ(observedRecordCallCount, 1); + EXPECT_EQ(observedShadowEnabled, expectedShadowPlan.enabled); + expectObservedRowMatchesMatrix( + observedShadowViewProjectionRow0, + expectedShadowPlan.cameraData.viewProjection, + 0); + expectObservedRowMatchesMatrix( + observedShadowViewProjectionRow1, + expectedShadowPlan.cameraData.viewProjection, + 1); + expectObservedRowMatchesMatrix( + observedShadowViewProjectionRow2, + expectedShadowPlan.cameraData.viewProjection, + 2); + expectObservedRowMatchesMatrix( + observedShadowViewProjectionRow3, + expectedShadowPlan.cameraData.viewProjection, + 3); + EXPECT_FLOAT_EQ( + observedShadowOrthographicHalfExtent, + expectedShadowPlan.orthographicHalfExtent); + EXPECT_FLOAT_EQ( + observedShadowNearClipPlane, + expectedShadowPlan.nearClipPlane); + EXPECT_FLOAT_EQ( + observedShadowFarClipPlane, + expectedShadowPlan.farClipPlane); + EXPECT_EQ(observedShadowMapWidth, static_cast(expectedShadowPlan.mapWidth)); + EXPECT_EQ(observedShadowMapHeight, static_cast(expectedShadowPlan.mapHeight)); + EXPECT_FLOAT_EQ( + observedShadowWorldTexelSize, + expectedShadowPlan.texelWorldSize); + EXPECT_FLOAT_EQ( + observedShadowReceiverDepthBias, + expectedShadowPlan.sampling.receiverDepthBias); + EXPECT_FLOAT_EQ( + observedShadowNormalBiasScale, + expectedShadowPlan.sampling.normalBiasScale); + EXPECT_FLOAT_EQ( + observedShadowStrength, + expectedShadowPlan.sampling.shadowStrength); + EXPECT_FLOAT_EQ( + observedShadowDepthBiasFactor, + expectedShadowPlan.casterBias.depthBiasFactor); + EXPECT_EQ( + observedShadowDepthBiasUnits, + expectedShadowPlan.casterBias.depthBiasUnits); +} + +TEST_F( + MonoScriptRuntimeTest, + ManagedRenderContextExposesEnvironmentDataThroughRenderingData) { + Scene* runtimeScene = + CreateScene("ManagedRenderContextEnvironmentDataScene"); + GameObject* selectionObject = + runtimeScene->CreateGameObject( + "ManagedRenderContextEnvironmentDataSelection"); + ScriptComponent* selectionScript = + AddScript( + selectionObject, + "Gameplay", + "ManagedRenderContextEnvironmentDataRuntimeSelectionProbe"); + ASSERT_NE(selectionScript, nullptr); + + GameObject* cameraObject = runtimeScene->CreateGameObject("Camera"); + auto* camera = cameraObject->AddComponent(); + ASSERT_NE(camera, nullptr); + camera->SetPrimary(true); + camera->SetProjectionType(CameraProjectionType::Perspective); + camera->SetClearMode(CameraClearMode::ColorAndDepth); + camera->SetSkyboxEnabled(true); + camera->SetSkyboxTopColor( + XCEngine::Math::Color(0.11f, 0.22f, 0.33f, 1.0f)); + camera->SetSkyboxHorizonColor( + XCEngine::Math::Color(0.44f, 0.55f, 0.66f, 1.0f)); + camera->SetSkyboxBottomColor( + XCEngine::Math::Color(0.77f, 0.88f, 0.99f, 1.0f)); + + engine->OnRuntimeStart(runtimeScene); + engine->OnUpdate(0.016f); + + TestRenderDevice device; + TestRenderCommandList commandList; + TestRenderCommandQueue commandQueue; + TestRenderResourceView colorView( + XCEngine::RHI::ResourceViewType::RenderTarget, + XCEngine::RHI::ResourceViewDimension::Texture2D, + XCEngine::RHI::Format::R8G8B8A8_UNorm); + TestRenderResourceView depthView( + XCEngine::RHI::ResourceViewType::DepthStencil, + XCEngine::RHI::ResourceViewDimension::Texture2D, + XCEngine::RHI::Format::D32_Float); + + const XCEngine::Rendering::RenderContext context = + CreateRenderContext( + device, + commandList, + commandQueue); + XCEngine::Rendering::RenderSurface surface(200u, 120u); + surface.SetColorAttachment(&colorView); + surface.SetDepthAttachment(&depthView); + + XCEngine::Rendering::SceneRenderer renderer; + const std::vector plans = + renderer.BuildFramePlans( + *runtimeScene, + nullptr, + context, + surface); + ASSERT_EQ(plans.size(), 1u); + ASSERT_TRUE(renderer.Render(plans)); + + engine->OnUpdate(0.016f); + + int observedEnvironmentMode = 0; + XCEngine::Math::Vector4 observedSkyboxTopColor = {}; + XCEngine::Math::Vector4 observedSkyboxHorizonColor = {}; + XCEngine::Math::Vector4 observedSkyboxBottomColor = {}; + int observedRecordCallCount = 0; + + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedEnvironmentMode", + observedEnvironmentMode)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedSkyboxTopColor", + observedSkyboxTopColor)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedSkyboxHorizonColor", + observedSkyboxHorizonColor)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedSkyboxBottomColor", + observedSkyboxBottomColor)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedRecordCallCount", + observedRecordCallCount)); + + EXPECT_EQ(observedRecordCallCount, 1); + EXPECT_EQ( + observedEnvironmentMode, + static_cast( + XCEngine::Rendering::RenderEnvironmentMode::ProceduralSkybox)); + ExpectVector4Near( + observedSkyboxTopColor, + XCEngine::Math::Vector4(0.11f, 0.22f, 0.33f, 1.0f)); + ExpectVector4Near( + observedSkyboxHorizonColor, + XCEngine::Math::Vector4(0.44f, 0.55f, 0.66f, 1.0f)); + ExpectVector4Near( + observedSkyboxBottomColor, + XCEngine::Math::Vector4(0.77f, 0.88f, 0.99f, 1.0f)); +} + +TEST_F( + MonoScriptRuntimeTest, + ManagedRenderContextExposesFinalColorDataThroughRenderingData) { + Scene* runtimeScene = + CreateScene("ManagedRenderContextFinalColorDataScene"); + GameObject* selectionObject = + runtimeScene->CreateGameObject( + "ManagedRenderContextFinalColorDataSelection"); + ScriptComponent* selectionScript = + AddScript( + selectionObject, + "Gameplay", + "ManagedRenderContextFinalColorDataRuntimeSelectionProbe"); + ASSERT_NE(selectionScript, nullptr); + + GameObject* cameraObject = runtimeScene->CreateGameObject("Camera"); + auto* camera = cameraObject->AddComponent(); + ASSERT_NE(camera, nullptr); + camera->SetPrimary(true); + + XCEngine::Rendering::FinalColorOverrideSettings finalColorOverrides = {}; + finalColorOverrides.overrideExposureValue = true; + finalColorOverrides.exposureValue = 2.5f; + finalColorOverrides.overrideToneMappingMode = true; + finalColorOverrides.toneMappingMode = + XCEngine::Rendering::FinalColorToneMappingMode::Neutral; + finalColorOverrides.overrideFinalColorScale = true; + finalColorOverrides.finalColorScale = + XCEngine::Math::Vector4(0.80f, 0.95f, 1.05f, 1.0f); + camera->SetFinalColorOverrides(finalColorOverrides); + + engine->OnRuntimeStart(runtimeScene); + engine->OnUpdate(0.016f); + + TestRenderDevice device; + TestRenderCommandList commandList; + TestRenderCommandQueue commandQueue; + TestRenderResourceView colorView( + XCEngine::RHI::ResourceViewType::RenderTarget, + XCEngine::RHI::ResourceViewDimension::Texture2D, + XCEngine::RHI::Format::R8G8B8A8_UNorm); + TestRenderResourceView depthView( + XCEngine::RHI::ResourceViewType::DepthStencil, + XCEngine::RHI::ResourceViewDimension::Texture2D, + XCEngine::RHI::Format::D32_Float); + + const XCEngine::Rendering::RenderContext context = + CreateRenderContext( + device, + commandList, + commandQueue); + XCEngine::Rendering::RenderSurface surface(160u, 90u); + surface.SetColorAttachment(&colorView); + surface.SetDepthAttachment(&depthView); + + XCEngine::Rendering::SceneRenderer renderer; + const std::vector plans = + renderer.BuildFramePlans( + *runtimeScene, + nullptr, + context, + surface); + ASSERT_EQ(plans.size(), 1u); + ASSERT_TRUE(renderer.Render(plans)); + + engine->OnUpdate(0.016f); + + const XCEngine::Rendering::ResolvedFinalColorPolicy& + expectedFinalColorPolicy = plans[0].finalColorPolicy; + + int observedFinalColorOutputTransferMode = 0; + int observedFinalColorExposureMode = 0; + float observedFinalColorExposureValue = 0.0f; + int observedFinalColorToneMappingMode = 0; + XCEngine::Math::Vector4 observedFinalColorScale = {}; + bool observedFinalColorHasPipelineDefaults = false; + bool observedFinalColorHasCameraOverrides = false; + bool observedFinalColorRequiresProcessing = false; + int observedRecordCallCount = 0; + + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedFinalColorOutputTransferMode", + observedFinalColorOutputTransferMode)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedFinalColorExposureMode", + observedFinalColorExposureMode)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedFinalColorExposureValue", + observedFinalColorExposureValue)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedFinalColorToneMappingMode", + observedFinalColorToneMappingMode)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedFinalColorScale", + observedFinalColorScale)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedFinalColorHasPipelineDefaults", + observedFinalColorHasPipelineDefaults)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedFinalColorHasCameraOverrides", + observedFinalColorHasCameraOverrides)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedFinalColorRequiresProcessing", + observedFinalColorRequiresProcessing)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedRecordCallCount", + observedRecordCallCount)); + + EXPECT_EQ(observedRecordCallCount, 1); + EXPECT_EQ( + observedFinalColorOutputTransferMode, + static_cast(expectedFinalColorPolicy.outputTransferMode)); + EXPECT_EQ( + observedFinalColorExposureMode, + static_cast(expectedFinalColorPolicy.exposureMode)); + EXPECT_FLOAT_EQ( + observedFinalColorExposureValue, + expectedFinalColorPolicy.exposureValue); + EXPECT_EQ( + observedFinalColorToneMappingMode, + static_cast(expectedFinalColorPolicy.toneMappingMode)); + ExpectVector4Near( + observedFinalColorScale, + expectedFinalColorPolicy.finalColorScale); + EXPECT_EQ( + observedFinalColorHasPipelineDefaults, + expectedFinalColorPolicy.hasPipelineDefaults); + EXPECT_EQ( + observedFinalColorHasCameraOverrides, + expectedFinalColorPolicy.hasCameraOverrides); + EXPECT_EQ( + observedFinalColorRequiresProcessing, + expectedFinalColorPolicy.RequiresProcessing()); +} + +TEST_F( + MonoScriptRuntimeTest, + ManagedRenderContextExposesStageColorDataThroughRenderingData) { + Scene* runtimeScene = + CreateScene("ManagedRenderContextStageColorDataScene"); + GameObject* selectionObject = + runtimeScene->CreateGameObject( + "ManagedRenderContextStageColorDataSelection"); + ScriptComponent* selectionScript = + AddScript( + selectionObject, + "Gameplay", + "ManagedRenderContextStageColorDataRuntimeSelectionProbe"); + ASSERT_NE(selectionScript, nullptr); + + GameObject* cameraObject = runtimeScene->CreateGameObject("Camera"); + auto* camera = cameraObject->AddComponent(); + ASSERT_NE(camera, nullptr); + camera->SetPrimary(true); + + engine->OnRuntimeStart(runtimeScene); + engine->OnUpdate(0.016f); + + TestRenderDevice device; + TestRenderCommandList commandList; + TestRenderCommandQueue commandQueue; + TestRenderResourceView colorView( + XCEngine::RHI::ResourceViewType::RenderTarget, + XCEngine::RHI::ResourceViewDimension::Texture2D, + XCEngine::RHI::Format::R8G8B8A8_UNorm); + TestRenderResourceView depthView( + XCEngine::RHI::ResourceViewType::DepthStencil, + XCEngine::RHI::ResourceViewDimension::Texture2D, + XCEngine::RHI::Format::D32_Float); + + const XCEngine::Rendering::RenderContext context = + CreateRenderContext( + device, + commandList, + commandQueue); + XCEngine::Rendering::RenderSurface surface(160u, 90u); + surface.SetColorAttachment(&colorView); + surface.SetDepthAttachment(&depthView); + + XCEngine::Rendering::SceneRenderer renderer; + const std::vector plans = + renderer.BuildFramePlans( + *runtimeScene, + nullptr, + context, + surface); + ASSERT_EQ(plans.size(), 1u); + EXPECT_TRUE( + plans[0].IsFullscreenStageRequested( + XCEngine::Rendering::CameraFrameStage::PostProcess)); + EXPECT_TRUE( + plans[0].IsFullscreenStageRequested( + XCEngine::Rendering::CameraFrameStage::FinalOutput)); + ASSERT_TRUE(renderer.Render(plans)); + + engine->OnUpdate(0.016f); + + int observedMainSceneSource = 0; + bool observedMainSceneUsesGraphManagedOutputColor = false; + int observedPostProcessSource = 0; + bool observedPostProcessUsesGraphManagedOutputColor = false; + int observedFinalOutputSource = 0; + bool observedFinalOutputUsesGraphManagedOutputColor = false; + int observedMainSceneRecordCallCount = 0; + int observedPostProcessRecordCallCount = 0; + int observedFinalOutputRecordCallCount = 0; + + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedMainSceneSource", + observedMainSceneSource)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedMainSceneUsesGraphManagedOutputColor", + observedMainSceneUsesGraphManagedOutputColor)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedPostProcessSource", + observedPostProcessSource)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedPostProcessUsesGraphManagedOutputColor", + observedPostProcessUsesGraphManagedOutputColor)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedFinalOutputSource", + observedFinalOutputSource)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedFinalOutputUsesGraphManagedOutputColor", + observedFinalOutputUsesGraphManagedOutputColor)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedMainSceneRecordCallCount", + observedMainSceneRecordCallCount)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedPostProcessRecordCallCount", + observedPostProcessRecordCallCount)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "ObservedFinalOutputRecordCallCount", + observedFinalOutputRecordCallCount)); + + EXPECT_EQ(observedMainSceneRecordCallCount, 1); + EXPECT_EQ(observedPostProcessRecordCallCount, 1); + EXPECT_EQ(observedFinalOutputRecordCallCount, 1); + EXPECT_EQ( + observedMainSceneSource, + static_cast( + plans[0].ResolveStageColorSource( + XCEngine::Rendering::CameraFrameStage::MainScene))); + EXPECT_EQ( + observedMainSceneUsesGraphManagedOutputColor, + plans[0].UsesGraphManagedOutputColor( + XCEngine::Rendering::CameraFrameStage::MainScene)); + EXPECT_EQ( + observedPostProcessSource, + static_cast( + plans[0].ResolveStageColorSource( + XCEngine::Rendering::CameraFrameStage::PostProcess))); + EXPECT_EQ( + observedPostProcessUsesGraphManagedOutputColor, + plans[0].UsesGraphManagedOutputColor( + XCEngine::Rendering::CameraFrameStage::PostProcess)); + EXPECT_EQ( + observedFinalOutputSource, + static_cast( + plans[0].ResolveStageColorSource( + XCEngine::Rendering::CameraFrameStage::FinalOutput))); + EXPECT_EQ( + observedFinalOutputUsesGraphManagedOutputColor, + plans[0].UsesGraphManagedOutputColor( + XCEngine::Rendering::CameraFrameStage::FinalOutput)); +} + TEST_F( MonoScriptRuntimeTest, RegistersManagedRenderPipelineBridgeThatCreatesManagedStageRecorders) { @@ -785,6 +2277,7 @@ TEST_F( {}, { colorTarget }, depthTarget, + {}, &executionSucceeded, &blackboard }; @@ -878,6 +2371,7 @@ TEST_F( {}, { outputColor }, {}, + {}, &executionSucceeded, &blackboard }; diff --git a/tests/scripting/test_script_engine.cpp b/tests/scripting/test_script_engine.cpp index 3e183681..e8a0a300 100644 --- a/tests/scripting/test_script_engine.cpp +++ b/tests/scripting/test_script_engine.cpp @@ -61,6 +61,12 @@ public: return true; } + bool TryGetAvailableRenderPipelineAssetClasses( + std::vector& outClasses) const override { + outClasses = renderPipelineAssetClasses; + return true; + } + bool TryGetClassFieldMetadata( const std::string& assemblyName, const std::string& namespaceName, @@ -149,6 +155,7 @@ public: std::vector events; std::vector scriptClasses; + std::vector renderPipelineAssetClasses; std::vector fieldMetadata; std::vector fieldDefaultValues; std::unordered_map managedFieldValues;