diff --git a/engine/include/XCEngine/Rendering/AGENTS.md b/engine/include/XCEngine/Rendering/AGENTS.md index 836d86b5..bdc2b291 100644 --- a/engine/include/XCEngine/Rendering/AGENTS.md +++ b/engine/include/XCEngine/Rendering/AGENTS.md @@ -129,6 +129,14 @@ Guardrails: ## Past Execution +- Removed fullscreen-kernel-specific authoring from the public managed + RenderGraph / URP pass surface. Public C# pass authors now use + `AddRasterPass(...)`, resource declarations, and `SetRenderFunc(...)`; + `ColorScaleFullscreen`, `ShaderVectorFullscreen`, and `FinalColorFullscreen` + execution setters are internal implementation hooks for URP's built-in + passes. Native now records generic managed raster passes as declared callback + graph work in any stage, while true deferred managed command-buffer execution + remains the next capability gap. - Made the public managed `ScriptableRenderPass.RecordRenderGraph(RenderGraph, ContextContainer)` path receive real URP frame data. `RenderingData`, `CameraData`, `LightingData`, diff --git a/engine/src/Scripting/Mono/MonoScriptRuntime.cpp b/engine/src/Scripting/Mono/MonoScriptRuntime.cpp index 10c60c30..60c53ea8 100644 --- a/engine/src/Scripting/Mono/MonoScriptRuntime.cpp +++ b/engine/src/Scripting/Mono/MonoScriptRuntime.cpp @@ -116,6 +116,7 @@ struct ManagedScriptableRenderContextState { struct RasterPassRecordRequest { Containers::String passName = {}; Rendering::FullscreenPassDesc passDesc = {}; + bool usesManagedRenderFuncExecution = false; Rendering::RenderGraphTextureHandle sourceColorTexture = {}; std::vector readTextures = {}; std::vector readDepthTextures = {}; @@ -346,6 +347,13 @@ ResolveManagedPrimaryColorTarget( : Rendering::RenderGraphTextureHandle{}; } +bool HasManagedRasterWriteTarget( + const ManagedScriptableRenderContextState::RasterPassRecordRequest& + request) { + return ResolveManagedPrimaryColorTarget(request.colorTargets).IsValid() || + request.depthTarget.IsValid(); +} + Rendering::RenderGraphTextureHandle ResolveManagedScriptableRenderContextPrimaryColorTarget( const ManagedScriptableRenderContextState* state) { @@ -474,6 +482,58 @@ bool RecordManagedFullscreenRasterPass( std::move(textureBindings)); } +bool RecordManagedRenderFuncRasterPass( + const Rendering::RenderPipelineStageRenderGraphContext& stageContext, + Rendering::RenderGraphTextureHandle sourceColorTexture, + std::vector colorTargets, + std::vector additionalReadTextures, + std::vector additionalReadDepthTextures, + std::vector + textureBindings, + Rendering::RenderGraphTextureHandle depthTarget, + const Containers::String& passName) { + if (!ResolveManagedPrimaryColorTarget(colorTargets).IsValid() && + !depthTarget.IsValid()) { + return false; + } + + const Rendering::RenderGraphRecordingContext baseContext = + Rendering::BuildRenderGraphRecordingContext(stageContext); + Rendering::RenderGraphRecordingContextBuildParams params = {}; + if (!passName.Empty()) { + params.passName = &passName; + } + params.overrideSourceBinding = true; + if (sourceColorTexture.IsValid()) { + params.sourceBinding = + BuildManagedScriptableRenderContextSourceBinding( + stageContext, + sourceColorTexture); + } + params.overrideColorTargets = true; + params.colorTargets = std::move(colorTargets); + params.overrideDepthTarget = true; + params.depthTarget = depthTarget; + + const Rendering::RenderGraphRecordingContext recordingContext = + Rendering::BuildRenderGraphRecordingContext( + baseContext, + std::move(params)); + const Rendering::RenderPassRenderGraphContext renderGraphContext = + Rendering::BuildRenderPassRenderGraphContext(recordingContext); + const Rendering::RenderPassGraphIO io = + Rendering::BuildDeclaredRasterPassGraphIO(renderGraphContext); + return Rendering::RecordCallbackRasterRenderPass( + renderGraphContext, + io, + [](const Rendering::RenderPassContext&) { + return true; + }, + std::move(additionalReadTextures), + std::move(additionalReadDepthTextures), + std::move(textureBindings)); +} + bool RecordManagedFullscreenPassToTexture( const Rendering::RenderPipelineStageRenderGraphContext& stageContext, Rendering::RenderPass& pass, @@ -1956,9 +2016,6 @@ private: if (managedContextState.rasterPassRequests.empty()) { return true; } - if (!Rendering::IsCameraFrameFullscreenSequenceStage(context.stage)) { - return false; - } Rendering::RenderGraphTextureHandle currentSourceColor = ResolveManagedScriptableRenderContextSourceColorTexture( @@ -1966,16 +2023,50 @@ private: const Rendering::RenderGraphTextureHandle finalOutputColor = ResolveManagedScriptableRenderContextPrimaryColorTarget( &managedContextState); - if (!currentSourceColor.IsValid() || - !finalOutputColor.IsValid()) { - return false; - } for (size_t passIndex = 0u; passIndex < managedContextState.rasterPassRequests.size(); ++passIndex) { const ManagedScriptableRenderContextState::RasterPassRecordRequest& request = managedContextState.rasterPassRequests[passIndex]; + const Containers::String resolvedPassName = + !request.passName.Empty() + ? request.passName + : managedContextState.rasterPassRequests.size() == 1u + ? context.passName + : Rendering::BuildRenderGraphSequencePassName( + context.passName, + passIndex); + if (request.usesManagedRenderFuncExecution) { + if (!RecordManagedRenderFuncRasterPass( + context, + request.sourceColorTexture, + request.colorTargets, + request.readTextures, + request.readDepthTextures, + request.textureBindings, + request.depthTarget, + resolvedPassName)) { + return false; + } + + const Rendering::RenderGraphTextureHandle + resolvedOutputColor = + ResolveManagedPrimaryColorTarget( + request.colorTargets); + if (resolvedOutputColor.IsValid()) { + currentSourceColor = resolvedOutputColor; + } + continue; + } + + if (!Rendering::IsCameraFrameFullscreenSequenceStage( + context.stage) || + !currentSourceColor.IsValid() || + !finalOutputColor.IsValid()) { + return false; + } + Rendering::RenderPass* const pass = ConfigureManagedFullscreenPass( m_fullscreenPassPool, @@ -1985,14 +2076,6 @@ private: return false; } - const Containers::String resolvedPassName = - !request.passName.Empty() - ? request.passName - : managedContextState.rasterPassRequests.size() == 1u - ? context.passName - : Rendering::BuildRenderGraphSequencePassName( - context.passName, - passIndex); const Rendering::RenderGraphTextureHandle resolvedSourceColor = request.sourceColorTexture.IsValid() ? request.sourceColorTexture @@ -4717,8 +4800,7 @@ uint64_t InternalCall_Rendering_ScriptableRenderContext_BeginRasterPass( ManagedScriptableRenderContextState* const state = FindManagedScriptableRenderContextState(nativeHandle); if (state == nullptr || - state->graphContext == nullptr || - !Rendering::IsCameraFrameFullscreenSequenceStage(state->stage)) { + state->graphContext == nullptr) { return 0u; } @@ -4961,10 +5043,13 @@ InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorScaleFullscreen state, rasterPassHandle); if (request == nullptr || + state == nullptr || + !Rendering::IsCameraFrameFullscreenSequenceStage(state->stage) || vectorPayload == nullptr) { return 0; } + request->usesManagedRenderFuncExecution = false; request->passDesc = Rendering::FullscreenPassDesc::MakeColorScale( *vectorPayload); @@ -4986,6 +5071,8 @@ InternalCall_Rendering_ScriptableRenderContext_SetRasterPassShaderVectorFullscre state, rasterPassHandle); if (request == nullptr || + state == nullptr || + !Rendering::IsCameraFrameFullscreenSequenceStage(state->stage) || vectorPayload == nullptr) { return 0; } @@ -4996,6 +5083,7 @@ InternalCall_Rendering_ScriptableRenderContext_SetRasterPassShaderVectorFullscre return 0; } + request->usesManagedRenderFuncExecution = false; request->passDesc = Rendering::FullscreenPassDesc::MakeShaderVector( shaderPathString, @@ -5019,10 +5107,13 @@ InternalCall_Rendering_ScriptableRenderContext_SetRasterPassFinalColorFullscreen state, rasterPassHandle); if (request == nullptr || + state == nullptr || + !Rendering::IsCameraFrameFullscreenSequenceStage(state->stage) || settingsData == nullptr) { return 0; } + request->usesManagedRenderFuncExecution = false; request->passDesc = Rendering::FullscreenPassDesc::MakeFinalColor( BuildManagedFinalColorSettings( @@ -5032,14 +5123,33 @@ InternalCall_Rendering_ScriptableRenderContext_SetRasterPassFinalColorFullscreen : 0; } +mono_bool +InternalCall_Rendering_ScriptableRenderContext_SetRasterPassManagedRenderFuncExecution( + uint64_t nativeHandle, + uint64_t rasterPassHandle) { + ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + ManagedScriptableRenderContextState::RasterPassRecordRequest* + const request = + FindPendingManagedRasterPassRecordRequest( + state, + rasterPassHandle); + if (request == nullptr) { + return 0; + } + + request->usesManagedRenderFuncExecution = true; + request->passDesc = {}; + return 1; +} + mono_bool InternalCall_Rendering_ScriptableRenderContext_CommitRasterPass( uint64_t nativeHandle, uint64_t rasterPassHandle) { ManagedScriptableRenderContextState* const state = FindManagedScriptableRenderContextState(nativeHandle); if (state == nullptr || - state->graphContext == nullptr || - !Rendering::IsCameraFrameFullscreenSequenceStage(state->stage)) { + state->graphContext == nullptr) { return 0; } @@ -5053,9 +5163,13 @@ mono_bool InternalCall_Rendering_ScriptableRenderContext_CommitRasterPass( ManagedScriptableRenderContextState::RasterPassRecordRequest request = std::move(it->second); state->pendingRasterPassRequests.erase(it); - if (!request.passDesc.IsValid() || - !ResolveManagedPrimaryColorTarget(request.colorTargets) - .IsValid()) { + if (request.usesManagedRenderFuncExecution) { + if (!HasManagedRasterWriteTarget(request)) { + return 0; + } + } else if (!request.passDesc.IsValid() || + !ResolveManagedPrimaryColorTarget(request.colorTargets) + .IsValid()) { return 0; } @@ -6499,6 +6613,7 @@ void RegisterInternalCalls() { mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassColorScaleFullscreenExecution", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorScaleFullscreenExecution)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassShaderVectorFullscreenExecution", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassShaderVectorFullscreenExecution)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassFinalColorFullscreenExecution", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassFinalColorFullscreenExecution)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassManagedRenderFuncExecution", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassManagedRenderFuncExecution)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_CommitRasterPass", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_CommitRasterPass)); 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)); diff --git a/managed/GameScripts/RenderPipelineApiProbe.cs b/managed/GameScripts/RenderPipelineApiProbe.cs index e37c06fd..68bbee76 100644 --- a/managed/GameScripts/RenderPipelineApiProbe.cs +++ b/managed/GameScripts/RenderPipelineApiProbe.cs @@ -7,12 +7,6 @@ using XCEngine.Rendering.Universal; namespace Gameplay { - internal static class BuiltinShaderPaths - { - public const string ColorScalePostProcess = - "builtin://shaders/color-scale-post-process"; - } - internal static class ProbeFinalColorSettingsFactory { public static FinalColorSettings Create() @@ -141,12 +135,6 @@ namespace Gameplay Transparent } - internal enum FullscreenPassKind - { - ColorScale, - ShaderVector - } - internal sealed class ScenePhasePass : ScriptableRenderPass { private readonly ScenePhaseKind m_phaseKind; @@ -197,9 +185,6 @@ namespace Gameplay internal sealed class FullscreenPass : ScriptableRenderPass { - private readonly FullscreenPassKind m_passKind; - private readonly Vector4 m_vectorPayload; - private readonly string m_shaderPath; private readonly string m_passName; public FullscreenPass( @@ -207,22 +192,14 @@ namespace Gameplay Vector4 colorScale) { renderPassEvent = passEvent; - m_passKind = FullscreenPassKind.ColorScale; - m_vectorPayload = colorScale; - m_shaderPath = string.Empty; m_passName = string.Empty; } public FullscreenPass( RenderPassEvent passEvent, - string shaderPath, - Vector4 vectorPayload, - string passName = null) + string passName) { renderPassEvent = passEvent; - m_passKind = FullscreenPassKind.ShaderVector; - m_vectorPayload = vectorPayload; - m_shaderPath = shaderPath ?? string.Empty; m_passName = passName ?? string.Empty; } @@ -238,21 +215,32 @@ namespace Gameplay private bool RecordFullscreen( ScriptableRenderContext context) { - switch (m_passKind) + RenderGraphTextureHandle sourceColor = + context.sourceColorTexture; + RenderGraphTextureHandle outputColor = + context.primaryColorTarget; + if (!sourceColor.isValid || + !outputColor.isValid) { - case FullscreenPassKind.ColorScale: - return RecordColorScaleFullscreenPass( - context, - m_vectorPayload); - case FullscreenPassKind.ShaderVector: - return RecordShaderVectorFullscreenPass( - context, - m_shaderPath, - m_vectorPayload, - m_passName); - default: - return false; + return false; } + + return context + .AddRasterPass(ResolvePassName()) + .UseColorSource(sourceColor) + .SetColorAttachment(outputColor) + .SetRenderFunc( + rasterContext => + { + }) + .Commit(); + } + + private string ResolvePassName() + { + return string.IsNullOrEmpty(m_passName) + ? "Gameplay.GenericFullscreenRasterPass" + : m_passName; } } @@ -535,14 +523,10 @@ namespace Gameplay new FullscreenFeature( new FullscreenPass( RenderPassEvent.BeforeRenderingPostProcessing, - BuiltinShaderPaths.ColorScalePostProcess, - firstVectorPayload, - "ColorScale"), + "ManagedPostProcess.First"), new FullscreenPass( RenderPassEvent.AfterRenderingPostProcessing, - BuiltinShaderPaths.ColorScalePostProcess, - secondVectorPayload, - "ColorScale"))); + "ManagedPostProcess.Second"))); } } @@ -554,10 +538,10 @@ namespace Gameplay { AddFeature(new DefaultSceneFeature(onOpaqueRecorded)); AddFeature( - new FullscreenFeature( - new FullscreenPass( - RenderPassEvent.BeforeRenderingPostProcessing, - postProcessScale))); + new ColorScalePostProcessRendererFeature + { + colorScale = postProcessScale + }); } } @@ -2131,8 +2115,6 @@ namespace Gameplay new FullscreenFeature( new FullscreenPass( RenderPassEvent.BeforeRenderingPostProcessing, - BuiltinShaderPaths.ColorScalePostProcess, - new Vector4(1.05f, 1.0f, 0.95f, 1.0f), "ManagedCameraOverridePostProcess"))); } } @@ -2607,11 +2589,13 @@ namespace Gameplay return context != null && context .AddRasterPass( - "Managed.InvalidMainSceneRasterPass") + "Managed.MainSceneGenericRasterPass") .SetColorAttachment( context.primaryColorTarget) - .SetColorScaleFullscreenExecution( - new Vector4(1.0f, 1.0f, 1.0f, 1.0f)) + .SetRenderFunc( + rasterContext => + { + }) .Commit(); } } diff --git a/managed/GameScripts/ScriptableRenderContextApiSurfaceProbe.cs b/managed/GameScripts/ScriptableRenderContextApiSurfaceProbe.cs index 6b60961d..c8bdb71d 100644 --- a/managed/GameScripts/ScriptableRenderContextApiSurfaceProbe.cs +++ b/managed/GameScripts/ScriptableRenderContextApiSurfaceProbe.cs @@ -69,9 +69,13 @@ namespace Gameplay public bool HasRenderGraphRasterPassBuilderUseColorSource; public bool HasRenderGraphRasterPassBuilderUseTexture; public bool HasRenderGraphRasterPassBuilderSetColorAttachment; + public bool HasRenderGraphRasterPassBuilderSetRenderFunc; public bool HasRenderGraphRasterPassBuilderSetColorScaleFullscreenExecution; + public bool HasRenderGraphRasterPassBuilderSetShaderVectorFullscreenExecution; public bool HasRenderGraphRasterPassBuilderSetFinalColorFullscreenExecution; public bool HasRenderGraphRasterPassBuilderCommit; + public bool HasRenderGraphRasterContextType; + public bool HasRenderGraphRasterContextCommandBuffer; public bool HasSceneRenderPhaseType; public bool HasSceneRenderInjectionPointType; public bool HasRendererListType; @@ -105,6 +109,9 @@ namespace Gameplay public bool HasRenderGraphType; public bool HasRenderGraphAddRasterPass; public bool HasRenderPassPublicRecordRenderGraph; + public bool HasRenderPassProtectedRecordColorScaleFullscreenPass; + public bool HasRenderPassProtectedRecordShaderVectorFullscreenPass; + public bool HasRenderPassProtectedRecordFinalColorFullscreenPass; public bool HasRenderPassComparisonOperators; public bool HasRenderPassEventUnityNumericOrder; public bool HasRenderPassEventEngineExtensionOrder; @@ -172,6 +179,8 @@ namespace Gameplay "XCEngine.ScriptableObject"); System.Type rasterPassBuilderType = typeof(RenderGraphRasterPassBuilder); + System.Type rasterPassContextType = + typeof(RenderGraphRasterContext); System.Type rendererFeatureType = typeof(ScriptableRendererFeature); System.Type rendererDataType = @@ -476,10 +485,18 @@ namespace Gameplay rasterPassBuilderType.GetMethod( "SetColorAttachment", PublicInstanceMethodFlags) != null; + HasRenderGraphRasterPassBuilderSetRenderFunc = + rasterPassBuilderType.GetMethod( + "SetRenderFunc", + PublicInstanceMethodFlags) != null; HasRenderGraphRasterPassBuilderSetColorScaleFullscreenExecution = rasterPassBuilderType.GetMethod( "SetColorScaleFullscreenExecution", PublicInstanceMethodFlags) != null; + HasRenderGraphRasterPassBuilderSetShaderVectorFullscreenExecution = + rasterPassBuilderType.GetMethod( + "SetShaderVectorFullscreenExecution", + PublicInstanceMethodFlags) != null; HasRenderGraphRasterPassBuilderSetFinalColorFullscreenExecution = rasterPassBuilderType.GetMethod( "SetFinalColorFullscreenExecution", @@ -488,6 +505,13 @@ namespace Gameplay rasterPassBuilderType.GetMethod( "Commit", PublicInstanceMethodFlags) != null; + HasRenderGraphRasterContextType = + rasterPassContextType != null; + HasRenderGraphRasterContextCommandBuffer = + rasterPassContextType.GetProperty( + "cmd", + BindingFlags.Instance | + BindingFlags.Public) != null; HasSceneRenderPhaseType = contextType.Assembly.GetType( "XCEngine.Rendering.SceneRenderPhase") != null; @@ -640,6 +664,21 @@ namespace Gameplay typeof(ContextContainer) }, null) != null; + HasRenderPassProtectedRecordColorScaleFullscreenPass = + renderPassType.GetMethod( + "RecordColorScaleFullscreenPass", + BindingFlags.Instance | + BindingFlags.NonPublic) != null; + HasRenderPassProtectedRecordShaderVectorFullscreenPass = + renderPassType.GetMethod( + "RecordShaderVectorFullscreenPass", + BindingFlags.Instance | + BindingFlags.NonPublic) != null; + HasRenderPassProtectedRecordFinalColorFullscreenPass = + renderPassType.GetMethod( + "RecordFinalColorFullscreenPass", + BindingFlags.Instance | + BindingFlags.NonPublic) != null; HasRenderPassComparisonOperators = renderPassType.GetMethod( "op_GreaterThan", diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/BuiltinFinalColorPass.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/BuiltinFinalColorPass.cs index 6eeb628f..99803b85 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/BuiltinFinalColorPass.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/BuiltinFinalColorPass.cs @@ -20,7 +20,7 @@ namespace XCEngine.Rendering.Universal renderingData != null && renderingData.isFinalOutputStage && (!renderingData.finalColorData.requiresProcessing || - RecordFinalColorFullscreenPass( + RecordInternalFinalColorFullscreenPass( context, renderingData.finalColorData.settings, "Universal.BuiltinFinalColor")); diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessRendererFeature.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessRendererFeature.cs index 7b9d9d3e..c167d94d 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessRendererFeature.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessRendererFeature.cs @@ -35,7 +35,7 @@ namespace XCEngine.Rendering.Universal return false; } - return RecordColorScaleFullscreenPass( + return RecordInternalColorScaleFullscreenPass( context, context.sourceColorTexture, context.primaryColorTarget, diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderPass.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderPass.cs index 3621ce98..6decbaf8 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderPass.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderPass.cs @@ -170,7 +170,7 @@ namespace XCEngine.Rendering.Universal rhs) < 0; } - protected bool RecordColorScaleFullscreenPass( + internal static bool RecordInternalColorScaleFullscreenPass( ScriptableRenderContext context, Vector4 colorScale) { @@ -180,14 +180,14 @@ namespace XCEngine.Rendering.Universal context, out sourceColor, out outputColor) && - RecordColorScaleFullscreenPass( + RecordInternalColorScaleFullscreenPass( context, sourceColor, outputColor, colorScale); } - protected bool RecordColorScaleFullscreenPass( + internal static bool RecordInternalColorScaleFullscreenPass( ScriptableRenderContext context, RenderGraphTextureHandle sourceColor, RenderGraphTextureHandle outputColor, @@ -216,7 +216,7 @@ namespace XCEngine.Rendering.Universal .Commit(); } - protected bool RecordShaderVectorFullscreenPass( + internal static bool RecordInternalShaderVectorFullscreenPass( ScriptableRenderContext context, string shaderPath, Vector4 vectorPayload, @@ -235,7 +235,7 @@ namespace XCEngine.Rendering.Universal context, out sourceColor, out outputColor) && - RecordShaderVectorFullscreenPass( + RecordInternalShaderVectorFullscreenPass( context, sourceColor, outputColor, @@ -244,7 +244,7 @@ namespace XCEngine.Rendering.Universal passName: passName); } - protected bool RecordShaderVectorFullscreenPass( + internal static bool RecordInternalShaderVectorFullscreenPass( ScriptableRenderContext context, RenderGraphTextureHandle sourceColor, RenderGraphTextureHandle outputColor, @@ -285,7 +285,7 @@ namespace XCEngine.Rendering.Universal .Commit(); } - protected bool RecordFinalColorFullscreenPass( + internal static bool RecordInternalFinalColorFullscreenPass( ScriptableRenderContext context, FinalColorSettings settings, string passName = null) @@ -296,7 +296,7 @@ namespace XCEngine.Rendering.Universal context, out sourceColor, out outputColor) && - RecordFinalColorFullscreenPass( + RecordInternalFinalColorFullscreenPass( context, sourceColor, outputColor, @@ -304,7 +304,7 @@ namespace XCEngine.Rendering.Universal passName); } - protected bool RecordFinalColorFullscreenPass( + internal static bool RecordInternalFinalColorFullscreenPass( ScriptableRenderContext context, RenderGraphTextureHandle sourceColor, RenderGraphTextureHandle outputColor, diff --git a/managed/XCEngine.ScriptCore/InternalCalls.cs b/managed/XCEngine.ScriptCore/InternalCalls.cs index 1e5e1681..709e73d4 100644 --- a/managed/XCEngine.ScriptCore/InternalCalls.cs +++ b/managed/XCEngine.ScriptCore/InternalCalls.cs @@ -540,6 +540,12 @@ namespace XCEngine ulong rasterPassHandle, ref Rendering.FinalColorSettings settings); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool + Rendering_ScriptableRenderContext_SetRasterPassManagedRenderFuncExecution( + ulong nativeHandle, + ulong rasterPassHandle); + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern bool Rendering_ScriptableRenderContext_CommitRasterPass( diff --git a/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs b/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs index 27a82ba6..be00ffdc 100644 --- a/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs +++ b/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs @@ -164,9 +164,9 @@ namespace XCEngine.Rendering name)); } - // SRP v1 wrapper over managed fullscreen raster requests. Commit only - // succeeds on fullscreen sequence stages and the execution kinds remain - // limited to the built-in fullscreen pass family. + // Public RenderGraph raster authoring entry point. Built-in fullscreen + // kernels are internal URP implementation details, not public context + // shortcuts. public RenderGraphRasterPassBuilder AddRasterPass( string passName) { diff --git a/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraphRasterPassBuilder.cs b/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraphRasterPassBuilder.cs index 1461a95c..4c3d9737 100644 --- a/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraphRasterPassBuilder.cs +++ b/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraphRasterPassBuilder.cs @@ -9,12 +9,24 @@ namespace XCEngine.Rendering None = 0, ColorScaleFullscreen = 1, ShaderVectorFullscreen = 2, - FinalColorFullscreen = 3 + FinalColorFullscreen = 3, + ManagedRenderFunc = 4 } - // Managed SRP v1 raster recording is intentionally narrow: this builder - // only describes fullscreen raster passes that map onto the built-in - // ColorScale / ShaderVector / FinalColor executions. + public sealed class RenderGraphRasterContext + { + internal RenderGraphRasterContext( + CommandBuffer commandBuffer) + { + cmd = commandBuffer ?? new CommandBuffer(); + } + + public CommandBuffer cmd { get; private set; } + } + + // Public raster pass authoring follows the RenderGraph shape: declare + // resources, then provide a render func. Built-in fullscreen kernels are + // kept as internal execution details for URP. public sealed class RenderGraphRasterPassBuilder { private struct TextureBindingRequest @@ -40,6 +52,7 @@ namespace XCEngine.Rendering private string m_shaderPath = string.Empty; private string m_shaderPassName = string.Empty; private FinalColorSettings m_finalColorSettings; + private Action m_renderFunc; private RenderGraphRasterPassExecutionKind m_executionKind; private bool m_finalized; @@ -70,19 +83,6 @@ namespace XCEngine.Rendering return this; } - public RenderGraphRasterPassBuilder - SetFinalColorFullscreenExecution( - FinalColorSettings settings) - { - m_executionKind = - RenderGraphRasterPassExecutionKind - .FinalColorFullscreen; - m_finalColorSettings = settings; - m_shaderPath = string.Empty; - m_shaderPassName = string.Empty; - return this; - } - public RenderGraphRasterPassBuilder UseTexture( RenderGraphTextureHandle texture) { @@ -150,7 +150,37 @@ namespace XCEngine.Rendering return this; } - public RenderGraphRasterPassBuilder + public RenderGraphRasterPassBuilder SetRenderFunc( + Action renderFunc) + { + if (renderFunc == null) + { + throw new ArgumentNullException(nameof(renderFunc)); + } + + m_executionKind = + RenderGraphRasterPassExecutionKind.ManagedRenderFunc; + m_renderFunc = renderFunc; + m_shaderPath = string.Empty; + m_shaderPassName = string.Empty; + return this; + } + + internal RenderGraphRasterPassBuilder + SetFinalColorFullscreenExecution( + FinalColorSettings settings) + { + m_executionKind = + RenderGraphRasterPassExecutionKind + .FinalColorFullscreen; + m_finalColorSettings = settings; + m_renderFunc = null; + m_shaderPath = string.Empty; + m_shaderPassName = string.Empty; + return this; + } + + internal RenderGraphRasterPassBuilder SetColorScaleFullscreenExecution( Vector4 colorScale) { @@ -158,12 +188,13 @@ namespace XCEngine.Rendering RenderGraphRasterPassExecutionKind .ColorScaleFullscreen; m_vectorPayload = colorScale; + m_renderFunc = null; m_shaderPath = string.Empty; m_shaderPassName = string.Empty; return this; } - public RenderGraphRasterPassBuilder + internal RenderGraphRasterPassBuilder SetShaderVectorFullscreenExecution( string shaderPath, Vector4 vectorPayload, @@ -180,6 +211,7 @@ namespace XCEngine.Rendering RenderGraphRasterPassExecutionKind .ShaderVectorFullscreen; m_vectorPayload = vectorPayload; + m_renderFunc = null; m_shaderPath = shaderPath; m_shaderPassName = shaderPassName ?? string.Empty; return this; @@ -187,11 +219,9 @@ namespace XCEngine.Rendering public bool Commit() { - // Native bridge rejects raster pass recording outside the - // fullscreen sequence stages. if (m_finalized || !HasExecutionConfigured() || - !HasAnyColorAttachment()) + !HasRequiredAttachments()) { return false; } @@ -341,6 +371,20 @@ namespace XCEngine.Rendering nativePassHandle, ref m_finalColorSettings); break; + case RenderGraphRasterPassExecutionKind + .ManagedRenderFunc: + // Managed command buffers are not bridged into native + // graph execution yet, so the render func is invoked + // during recording while native records the declared IO. + m_renderFunc( + new RenderGraphRasterContext( + new CommandBuffer(m_passName))); + configuredExecution = + InternalCalls + .Rendering_ScriptableRenderContext_SetRasterPassManagedRenderFuncExecution( + m_context.nativeHandle, + nativePassHandle); + break; default: configuredExecution = false; break; @@ -359,6 +403,18 @@ namespace XCEngine.Rendering RenderGraphRasterPassExecutionKind.None; } + private bool HasRequiredAttachments() + { + if (m_executionKind == + RenderGraphRasterPassExecutionKind.ManagedRenderFunc) + { + return HasAnyColorAttachment() || + m_depthAttachment.isValid; + } + + return HasAnyColorAttachment(); + } + private void AddReadTexture( RenderGraphTextureHandle texture, bool isDepth) diff --git a/project/Assets/Scripts/ProjectRenderPipelineProbe.cs b/project/Assets/Scripts/ProjectRenderPipelineProbe.cs index ce927c85..7bafb0f2 100644 --- a/project/Assets/Scripts/ProjectRenderPipelineProbe.cs +++ b/project/Assets/Scripts/ProjectRenderPipelineProbe.cs @@ -46,12 +46,24 @@ namespace ProjectScripts ScriptableRenderContext context, RenderingData renderingData) { - return context != null && - renderingData != null && - renderingData.isPostProcessStage && - RecordColorScaleFullscreenPass( - context, - new Vector4(1.15f, 0.95f, 1.05f, 1.0f)); + if (context == null || + renderingData == null || + !renderingData.isPostProcessStage || + !context.sourceColorTexture.isValid || + !context.primaryColorTarget.isValid) + { + return false; + } + + return context + .AddRasterPass("Project.PostProcessColorScale") + .UseColorSource(context.sourceColorTexture) + .SetColorAttachment(context.primaryColorTarget) + .SetRenderFunc( + rasterContext => + { + }) + .Commit(); } } diff --git a/tests/scripting/test_mono_script_runtime.cpp b/tests/scripting/test_mono_script_runtime.cpp index 01b23b47..4ad74317 100644 --- a/tests/scripting/test_mono_script_runtime.cpp +++ b/tests/scripting/test_mono_script_runtime.cpp @@ -1457,6 +1457,20 @@ TEST_F( bool hasRendererRecordRenderer = false; bool hasPublicRendererSupportsStageRenderGraph = false; bool hasPublicRendererRecordStageRenderGraph = false; + bool hasRenderGraphRasterPassBuilderType = false; + bool hasRenderGraphRasterPassBuilderUseColorSource = false; + bool hasRenderGraphRasterPassBuilderUseTexture = false; + bool hasRenderGraphRasterPassBuilderSetColorAttachment = false; + bool hasRenderGraphRasterPassBuilderSetRenderFunc = false; + bool hasRenderGraphRasterPassBuilderSetColorScaleFullscreenExecution = false; + bool hasRenderGraphRasterPassBuilderSetShaderVectorFullscreenExecution = false; + bool hasRenderGraphRasterPassBuilderSetFinalColorFullscreenExecution = false; + bool hasRenderGraphRasterPassBuilderCommit = false; + bool hasRenderGraphRasterContextType = false; + bool hasRenderGraphRasterContextCommandBuffer = false; + bool hasRenderPassProtectedRecordColorScaleFullscreenPass = false; + bool hasRenderPassProtectedRecordShaderVectorFullscreenPass = false; + bool hasRenderPassProtectedRecordFinalColorFullscreenPass = false; EXPECT_TRUE(runtime->TryGetFieldValue( selectionScript, @@ -1606,6 +1620,62 @@ TEST_F( selectionScript, "HasPublicRendererRecordStageRenderGraph", hasPublicRendererRecordStageRenderGraph)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRenderGraphRasterPassBuilderType", + hasRenderGraphRasterPassBuilderType)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRenderGraphRasterPassBuilderUseColorSource", + hasRenderGraphRasterPassBuilderUseColorSource)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRenderGraphRasterPassBuilderUseTexture", + hasRenderGraphRasterPassBuilderUseTexture)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRenderGraphRasterPassBuilderSetColorAttachment", + hasRenderGraphRasterPassBuilderSetColorAttachment)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRenderGraphRasterPassBuilderSetRenderFunc", + hasRenderGraphRasterPassBuilderSetRenderFunc)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRenderGraphRasterPassBuilderSetColorScaleFullscreenExecution", + hasRenderGraphRasterPassBuilderSetColorScaleFullscreenExecution)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRenderGraphRasterPassBuilderSetShaderVectorFullscreenExecution", + hasRenderGraphRasterPassBuilderSetShaderVectorFullscreenExecution)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRenderGraphRasterPassBuilderSetFinalColorFullscreenExecution", + hasRenderGraphRasterPassBuilderSetFinalColorFullscreenExecution)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRenderGraphRasterPassBuilderCommit", + hasRenderGraphRasterPassBuilderCommit)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRenderGraphRasterContextType", + hasRenderGraphRasterContextType)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRenderGraphRasterContextCommandBuffer", + hasRenderGraphRasterContextCommandBuffer)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRenderPassProtectedRecordColorScaleFullscreenPass", + hasRenderPassProtectedRecordColorScaleFullscreenPass)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRenderPassProtectedRecordShaderVectorFullscreenPass", + hasRenderPassProtectedRecordShaderVectorFullscreenPass)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRenderPassProtectedRecordFinalColorFullscreenPass", + hasRenderPassProtectedRecordFinalColorFullscreenPass)); EXPECT_FALSE(hasPublicContextRecordScene); EXPECT_FALSE(hasPublicContextRecordScenePhase); @@ -1644,6 +1714,20 @@ TEST_F( EXPECT_TRUE(hasRendererRecordRenderer); EXPECT_FALSE(hasPublicRendererSupportsStageRenderGraph); EXPECT_FALSE(hasPublicRendererRecordStageRenderGraph); + EXPECT_TRUE(hasRenderGraphRasterPassBuilderType); + EXPECT_TRUE(hasRenderGraphRasterPassBuilderUseColorSource); + EXPECT_TRUE(hasRenderGraphRasterPassBuilderUseTexture); + EXPECT_TRUE(hasRenderGraphRasterPassBuilderSetColorAttachment); + EXPECT_TRUE(hasRenderGraphRasterPassBuilderSetRenderFunc); + EXPECT_FALSE(hasRenderGraphRasterPassBuilderSetColorScaleFullscreenExecution); + EXPECT_FALSE(hasRenderGraphRasterPassBuilderSetShaderVectorFullscreenExecution); + EXPECT_FALSE(hasRenderGraphRasterPassBuilderSetFinalColorFullscreenExecution); + EXPECT_TRUE(hasRenderGraphRasterPassBuilderCommit); + EXPECT_TRUE(hasRenderGraphRasterContextType); + EXPECT_TRUE(hasRenderGraphRasterContextCommandBuffer); + EXPECT_FALSE(hasRenderPassProtectedRecordColorScaleFullscreenPass); + EXPECT_FALSE(hasRenderPassProtectedRecordShaderVectorFullscreenPass); + EXPECT_FALSE(hasRenderPassProtectedRecordFinalColorFullscreenPass); } TEST_F( @@ -4315,7 +4399,7 @@ TEST_F( TEST_F( MonoScriptRuntimeTest, - ManagedStageRecorderRecordsShaderVectorPostProcessThroughScriptableRenderContext) { + ManagedStageRecorderRecordsGenericPostProcessRasterPassesThroughRenderGraph) { const auto bridge = XCEngine::Rendering::Pipelines::GetManagedRenderPipelineBridge(); ASSERT_NE(bridge, nullptr); @@ -4400,17 +4484,17 @@ TEST_F( ASSERT_EQ(compiledGraph.GetPassCount(), 2u); EXPECT_STREQ( compiledGraph.GetPassName(0).CStr(), - "ColorScale"); + "ManagedPostProcess.First"); EXPECT_STREQ( compiledGraph.GetPassName(1).CStr(), - "ColorScale"); + "ManagedPostProcess.Second"); recorder->Shutdown(); } TEST_F( MonoScriptRuntimeTest, - ManagedStageRecorderRejectsRasterPassRecordingOutsideFullscreenStages) { + ManagedStageRecorderRecordsGenericRasterPassOutsideFullscreenStages) { const auto bridge = XCEngine::Rendering::Pipelines::GetManagedRenderPipelineBridge(); ASSERT_NE(bridge, nullptr); @@ -4480,7 +4564,7 @@ TEST_F( &blackboard }; - EXPECT_FALSE(recorder->RecordStageRenderGraph(graphContext)); + EXPECT_TRUE(recorder->RecordStageRenderGraph(graphContext)); XCEngine::Rendering::CompiledRenderGraph compiledGraph = {}; XCEngine::Containers::String errorMessage; @@ -4490,7 +4574,10 @@ TEST_F( compiledGraph, &errorMessage)) << errorMessage.CStr(); - EXPECT_EQ(compiledGraph.GetPassCount(), 0u); + ASSERT_EQ(compiledGraph.GetPassCount(), 1u); + EXPECT_STREQ( + compiledGraph.GetPassName(0).CStr(), + "Managed.MainSceneGenericRasterPass"); recorder->Shutdown(); } diff --git a/tests/scripting/test_project_script_assembly.cpp b/tests/scripting/test_project_script_assembly.cpp index 9ed06fdc..0cb862cf 100644 --- a/tests/scripting/test_project_script_assembly.cpp +++ b/tests/scripting/test_project_script_assembly.cpp @@ -381,7 +381,7 @@ TEST_F( ASSERT_EQ(compiledGraph.GetPassCount(), 1u); EXPECT_STREQ( compiledGraph.GetPassName(0).CStr(), - "Universal.ColorScaleFullscreen"); + "Project.PostProcessColorScale"); recorder->Shutdown(); }