diff --git a/engine/include/XCEngine/Rendering/AGENTS.md b/engine/include/XCEngine/Rendering/AGENTS.md index 09e00ec0..6317bde6 100644 --- a/engine/include/XCEngine/Rendering/AGENTS.md +++ b/engine/include/XCEngine/Rendering/AGENTS.md @@ -39,7 +39,7 @@ Unity 兼容的公开命名、对象所有权和扩展点。 Opaque、skybox、transparent、depth、shadow、post 和 final-output 流程应来自 URP blocks 和 passes。 - 保持 `DrawObjectsPass` 和 `DrawSkyboxPass` 作为 managed URP pass declarations,并通过 - renderer-list/native scene-recorder backends 执行。 + RenderGraph renderer-list declarations 和 native scene draw backend 执行。 - 收紧 stage 支持规则。如果 fullscreen 或 main-scene stage 需要 managed graph recording, 必须要求所选 renderer/pipeline 支持并记录该 stage。 - 只在 Unity 形态的 API 后面扩展 managed RenderGraph:resource declarations、frame data、 @@ -216,9 +216,10 @@ Managed SRP assets 通过 `GraphicsSettings.renderPipelineAsset` 选择,并通 - Mono 创建 `MonoManagedRenderPipelineAssetRuntime` 和 `MonoManagedRenderPipelineStageRecorder`。 Scriptable context、planning context、camera request context、scene setup context 和 shadow execution context handles 都是临时 native registry entries。不要在调用之外保存 managed context objects。 -- 当前 Mono-backed SRP assets 显式使用 `DefaultNativeBackend` 做 scene drawing。Managed - `ScriptableRenderContext.DrawRenderers` 和 `DrawSkybox` 委托给 `NativeSceneRecorder` 以及 native - `SceneDrawBackend`。 +- 当前 Mono-backed SRP assets 显式使用 `DefaultNativeBackend` 做 scene drawing。URP 内置对象和 skybox + drawing 通过 managed RenderGraph 声明 renderer list、attachments 和 render func,再由 native + `SceneDrawBackend` 执行。`ScriptableRenderContext.DrawRenderers` 和 `DrawSkybox` 仍作为 SRP v1 兼容入口保留, + 并委托给 `NativeSceneRecorder`。 - Managed resource/version invalidation 是正确性的一部分。如果 managed asset、renderer data 或 feature 修改 runtime state,调用 `SetDirty` 或本地 invalidation helper,确保 native runtime caches 被释放。 当前 runtime version 也会兜底 hash `UniversalRenderPipelineAsset` 的 shadow/final-color settings,以及 @@ -279,12 +280,19 @@ Managed RenderGraph 目前有意保持较小,但应维持 Unity 的现代形 `XCEngine.Rendering.RenderGraphModule.RenderGraph.AddRasterPass` 和 `RenderGraphRasterPassBuilder` 进行。 - Public passes 应声明 reads、bindings、color attachments、depth attachment 和 render func,然后 `Commit`。 +- Renderer-list drawing 是 RenderGraph authoring 的一等声明:先用 + `RenderGraph.CreateRendererList(RendererListDesc, DrawingSettings)` 创建 `RendererListHandle`,再通过 + `RenderGraphRasterPassBuilder.UseRendererList` 声明 pass 依赖,最后在 render func 中调用 + `CommandBuffer.DrawRendererList`。URP 内置 `DrawObjectsPass` 必须走这条路径。 +- Skybox drawing 也应从 managed raster pass 的 render func 进入 `CommandBuffer.DrawSkybox`。URP 内置 + `DrawSkyboxPass` 不应再直接在 recording 阶段调用 `ScriptableRenderContext.DrawSkybox`。 - Internal fullscreen helpers,例如 color scale、shader vector 和 final color,是 URP implementation details。 不要把它们作为 public `ScriptableRenderContext` shortcuts 暴露。 - Managed `SetRenderFunc` 是 deferred RenderGraph execution callback。Mono bridge 必须 retain delegate, 在 native graph pass 执行时创建 pass-scoped `CommandBuffer`,并把已支持的 managed command stream flush 到 - 当前 `RHICommandList`。当前公开且已测试的命令子集是 `CommandBuffer.ClearRenderTarget(Color)`,写向 pass - 的 primary color attachment;没有 native command stream 和 executor 测试的命令不要暴露成 public API。 + 当前 `RHICommandList`。当前公开命令子集是 `CommandBuffer.ClearRenderTarget(Color)`、 + `CommandBuffer.DrawRendererList(RendererListHandle)` 和 `CommandBuffer.DrawSkybox()`;没有 native command stream + 和 executor 测试的命令不要暴露成 public API。 - Public RenderGraph frame data 由同一个 renderer stage 内记录的所有 passes 共享。保持 `ContextContainer` 作为 stage frame data,而不是 pass-local scratch data。 - Fullscreen internal passes 需要有效 `sourceColorTexture` 和 `primaryColorTarget`。Multi-pass fullscreen chains @@ -350,10 +358,10 @@ Scene data 每个 camera frame 提取一次,然后由 pipeline 调整。 ### 当前债务 -- Managed SRP 仍是 SRP v1 surface。Main scene drawing 通过 managed calls 记录,但由 native scene draw - backends 执行。 -- Managed `CommandBuffer` 已能随 public `SetRenderFunc` 延迟到 RenderGraph 执行期运行,但当前只收口了 - `ClearRenderTarget(Color)` 这一条受测命令。它不是完整 Unity `CommandBuffer`;新增命令必须一起补 +- Managed SRP 仍是 SRP v1 surface。Main scene drawing 现在可通过 managed RenderGraph renderer-list + declarations 记录,但实际绘制仍由 native scene draw backends 执行。 +- Managed `CommandBuffer` 已能随 public `SetRenderFunc` 延迟到 RenderGraph 执行期运行,但它不是完整 Unity + `CommandBuffer`;新增命令必须一起补 native command stream、RHI flush 和 scripting bridge tests。 - Managed RenderGraph 当前暴露 raster authoring。Native graph 有 compute pass support,但 managed compute authoring 还未公开。 @@ -401,7 +409,13 @@ Scene data 每个 camera frame 提取一次,然后由 pipeline 调整。 details。 - Public managed `SetRenderFunc` 已从 recording-time 调用改为 RenderGraph execution-time 调用; native 通过 retained managed delegate 和 pass-scoped `CommandBuffer` bridge 执行已支持的 command stream, - 当前受测命令为 `CommandBuffer.ClearRenderTarget(Color)`。 + 当前支持 `CommandBuffer.ClearRenderTarget(Color)`、`CommandBuffer.DrawRendererList(RendererListHandle)` 和 + `CommandBuffer.DrawSkybox()`。 +- Renderer-list drawing 已成为 managed RenderGraph 声明:`RenderGraph.CreateRendererList` 创建 + `RendererListHandle`,`RenderGraphRasterPassBuilder.UseRendererList` 把 renderer list 纳入 pass declaration, + `CommandBuffer.DrawRendererList` 在 RenderGraph 执行期触发 native `SceneDrawBackend`。URP 内置 + `DrawObjectsPass` 和 `DrawSkyboxPass` 已迁离 recording-time `ScriptableRenderContext.DrawRenderers/DrawSkybox` + 主路径。 - Public `ScriptableRenderPass.RecordRenderGraph(RenderGraph, ContextContainer)` 通过 `RenderingData`、 `CameraData`、`LightingData`、`ShadowData`、`EnvironmentData`、`FinalColorData` 和 `StageColorData` 接收真实 URP frame data。 diff --git a/engine/src/Scripting/Mono/MonoScriptRuntime.cpp b/engine/src/Scripting/Mono/MonoScriptRuntime.cpp index 817d16fe..9aa22c79 100644 --- a/engine/src/Scripting/Mono/MonoScriptRuntime.cpp +++ b/engine/src/Scripting/Mono/MonoScriptRuntime.cpp @@ -29,6 +29,7 @@ #include "Rendering/RenderPipeline.h" #include "Rendering/RenderPipelineAsset.h" #include "Rendering/RenderPipelineStageGraphContract.h" +#include "Rendering/SceneDrawBackend.h" #include "Resources/BuiltinResources.h" #include "Core/Asset/ResourceManager.h" #include "RHI/RHICommandList.h" @@ -54,6 +55,7 @@ #include #include #include +#include #include #include @@ -126,9 +128,11 @@ struct ManagedScriptableRenderContextState { std::vector readDepthTextures = {}; std::vector textureBindings = {}; + std::vector rendererListIndices = {}; std::vector colorTargets = {}; Rendering::RenderGraphTextureHandle depthTarget = {}; }; + std::vector rendererListRequests = {}; uint64_t nextPendingRasterPassHandle = 1u; std::unordered_map pendingRasterPassRequests = {}; @@ -169,16 +173,29 @@ struct ManagedScriptableRenderPipelinePlanningContextState { struct ManagedCommandBufferCommand { enum class Kind { - ClearRenderTarget + ClearRenderTarget, + DrawRendererList, + DrawSkybox }; Kind kind = Kind::ClearRenderTarget; float color[4] = {}; + Core::uint32 rendererListIndex = 0u; +}; + +struct ManagedSceneDrawCommandExecutionState { + bool initialized = false; + bool clearAttachments = true; }; struct ManagedCommandBufferState { uint64_t handle = 0; const Rendering::RenderPassContext* passContext = nullptr; + Rendering::SceneDrawBackend* sceneDrawBackend = nullptr; + std::shared_ptr + sceneDrawState = nullptr; + std::vector rendererLists = {}; + std::vector declaredRendererListIndices = {}; std::vector commands = {}; }; @@ -317,6 +334,59 @@ bool FlushManagedCommandBufferState( state.passContext->renderContext.commandList; const std::vector& colorAttachments = state.passContext->surface.GetColorAttachments(); + bool sceneDrawPassBegan = false; + + const auto isRendererListDeclared = + [&state](Core::uint32 rendererListIndex) { + return std::find( + state.declaredRendererListIndices.begin(), + state.declaredRendererListIndices.end(), + rendererListIndex) != + state.declaredRendererListIndices.end(); + }; + + const auto ensureSceneDrawPass = + [&state, &sceneDrawPassBegan]() -> bool { + if (state.sceneDrawBackend == nullptr || + state.sceneDrawState == nullptr) { + return false; + } + + if (!state.sceneDrawState->initialized) { + if (!state.sceneDrawBackend->Initialize( + state.passContext->renderContext)) { + return false; + } + + const Rendering::FrameExecutionContext executionContext( + state.passContext->renderContext, + state.passContext->surface, + state.passContext->sceneData, + state.passContext->sourceSurface, + state.passContext->sourceColorView, + state.passContext->sourceColorState); + if (!state.sceneDrawBackend->PrepareSceneDraw( + executionContext)) { + return false; + } + + state.sceneDrawState->initialized = true; + } + + if (sceneDrawPassBegan) { + return true; + } + + if (!state.sceneDrawBackend->BeginSceneDrawPass( + *state.passContext, + state.sceneDrawState->clearAttachments)) { + return false; + } + + state.sceneDrawState->clearAttachments = false; + sceneDrawPassBegan = true; + return true; + }; for (const ManagedCommandBufferCommand& command : state.commands) { switch (command.kind) { @@ -330,11 +400,59 @@ bool FlushManagedCommandBufferState( colorAttachments[0], command.color); break; + case ManagedCommandBufferCommand::Kind::DrawRendererList: + if (command.rendererListIndex >= state.rendererLists.size() || + !isRendererListDeclared(command.rendererListIndex) || + !ensureSceneDrawPass()) { + if (sceneDrawPassBegan && + state.sceneDrawBackend != nullptr) { + state.sceneDrawBackend->EndSceneDrawPass( + *state.passContext); + } + return false; + } + + if (!state.sceneDrawBackend->DrawSceneRenderers( + *state.passContext, + state.rendererLists[command.rendererListIndex])) { + state.sceneDrawBackend->EndSceneDrawPass( + *state.passContext); + return false; + } + break; + case ManagedCommandBufferCommand::Kind::DrawSkybox: + if (!ensureSceneDrawPass()) { + if (sceneDrawPassBegan && + state.sceneDrawBackend != nullptr) { + state.sceneDrawBackend->EndSceneDrawPass( + *state.passContext); + } + return false; + } + + if (!state.sceneDrawBackend->DrawScenePhase( + *state.passContext, + Rendering::ScenePhase::Skybox)) { + state.sceneDrawBackend->EndSceneDrawPass( + *state.passContext); + return false; + } + break; default: + if (sceneDrawPassBegan && + state.sceneDrawBackend != nullptr) { + state.sceneDrawBackend->EndSceneDrawPass( + *state.passContext); + } return false; } } + if (sceneDrawPassBegan && + state.sceneDrawBackend != nullptr) { + state.sceneDrawBackend->EndSceneDrawPass( + *state.passContext); + } return true; } @@ -1536,6 +1654,9 @@ Rendering::SortingSettings BuildManagedSortingSettings( return sortingSettings; } +Rendering::RenderStateBlock BuildManagedRenderStateBlock( + const ManagedRenderStateBlockData& renderStateBlockData); + bool TryBuildManagedRendererListDesc( const ManagedRendererListDescData& rendererListDescData, Rendering::RendererListDesc& outRendererListDesc) { @@ -1555,6 +1676,98 @@ bool TryBuildManagedRendererListDesc( return true; } +Rendering::ScenePhase ResolveManagedRendererListScenePhase( + Rendering::RendererListType rendererListType) { + switch (rendererListType) { + case Rendering::RendererListType::Transparent: + return Rendering::ScenePhase::Transparent; + case Rendering::RendererListType::Opaque: + case Rendering::RendererListType::ShadowCaster: + case Rendering::RendererListType::AllVisible: + case Rendering::RendererListType::ObjectId: + default: + return Rendering::ScenePhase::Opaque; + } +} + +bool IsManagedStandaloneScenePassStage( + Rendering::CameraFrameStage stage) { + return stage == Rendering::CameraFrameStage::ShadowCaster || + stage == Rendering::CameraFrameStage::DepthOnly; +} + +void ApplyManagedStandaloneScenePassDefaults( + Rendering::CameraFrameStage stage, + Rendering::DrawSettings& drawSettings) { + if (!IsManagedStandaloneScenePassStage(stage) || + drawSettings.HasShaderPassName()) { + return; + } + + drawSettings.shaderPassName = + stage == Rendering::CameraFrameStage::ShadowCaster + ? Containers::String("ShadowCaster") + : Containers::String("DepthOnly"); +} + +bool TryBuildManagedDrawSettings( + Rendering::CameraFrameStage stage, + const ManagedRendererListDescData& rendererListDescData, + MonoString* overrideMaterialPath, + MonoString* shaderPassName, + const ManagedRenderStateBlockData* renderStateBlockData, + Rendering::DrawSettings& outDrawSettings) { + outDrawSettings = {}; + if (!TryBuildManagedRendererListDesc( + rendererListDescData, + outDrawSettings.rendererListDesc)) { + Debug::Logger::Get().Error( + Debug::LogCategory::Rendering, + "ScriptableRenderContext received an unsupported renderer-list type"); + return false; + } + + outDrawSettings.scenePhase = + ResolveManagedRendererListScenePhase( + outDrawSettings.rendererListDesc.type); + + const std::string overrideMaterialPathUtf8 = + MonoStringToUtf8(overrideMaterialPath); + if (!overrideMaterialPathUtf8.empty()) { + outDrawSettings.overrideMaterial = + Resources::ResourceManager::Get().Load( + overrideMaterialPathUtf8.c_str()); + if (!outDrawSettings.overrideMaterial.IsValid()) { + Debug::Logger::Get().Error( + Debug::LogCategory::Rendering, + (Containers::String( + "ScriptableRenderContext failed to load override material: ") + + Containers::String(overrideMaterialPathUtf8.c_str())) + .CStr()); + return false; + } + } + + const std::string shaderPassNameUtf8 = + MonoStringToUtf8(shaderPassName); + if (!shaderPassNameUtf8.empty()) { + outDrawSettings.shaderPassName = + Containers::String(shaderPassNameUtf8.c_str()); + } + + ApplyManagedStandaloneScenePassDefaults( + stage, + outDrawSettings); + + if (renderStateBlockData != nullptr) { + outDrawSettings.renderStateBlock = + BuildManagedRenderStateBlock( + *renderStateBlockData); + } + + return true; +} + Rendering::DepthState BuildManagedDepthState( const ManagedDepthStateData& depthStateData) { Rendering::DepthState depthState = {}; @@ -2115,6 +2328,11 @@ private: assetRuntime = nullptr; uint32_t renderFuncHandle = 0u; Containers::String passName = {}; + Rendering::SceneDrawBackend* sceneDrawBackend = nullptr; + std::shared_ptr + sceneDrawState = nullptr; + std::vector rendererLists = {}; + std::vector declaredRendererListIndices = {}; ~ManagedRenderFuncExecutionState() { ReleaseRenderFunc(); @@ -2135,6 +2353,11 @@ private: ManagedCommandBufferState commandBufferState = {}; commandBufferState.passContext = &passContext; + commandBufferState.sceneDrawBackend = sceneDrawBackend; + commandBufferState.sceneDrawState = sceneDrawState; + commandBufferState.rendererLists = rendererLists; + commandBufferState.declaredRendererListIndices = + declaredRendererListIndices; const uint64_t commandBufferHandle = RegisterManagedCommandBufferState( commandBufferState); @@ -2261,6 +2484,8 @@ private: const Rendering::RenderGraphTextureHandle finalOutputColor = ResolveManagedScriptableRenderContextPrimaryColorTarget( &managedContextState); + auto sceneDrawState = + std::make_shared(); for (size_t passIndex = 0u; passIndex < managedContextState.rasterPassRequests.size(); @@ -2289,6 +2514,13 @@ private: executionState->assetRuntime = m_assetRuntime; executionState->renderFuncHandle = renderFuncHandle; executionState->passName = resolvedPassName; + executionState->sceneDrawBackend = + ResolveSceneDrawBackend(); + executionState->sceneDrawState = sceneDrawState; + executionState->rendererLists = + managedContextState.rendererListRequests; + executionState->declaredRendererListIndices = + request.rendererListIndices; Rendering::RenderPassGraphBeginCallback executeCallback = [executionState]( const Rendering::RenderPassContext& passContext) { @@ -4994,6 +5226,20 @@ uint64_t InternalCall_Rendering_ScriptableRenderContext_GetFramePlanId( : 0u; } +MonoString* InternalCall_Rendering_ScriptableRenderContext_GetPassName( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + const char* const passName = + state != nullptr && + state->graphContext != nullptr + ? state->graphContext->passName.CStr() + : ""; + return mono_string_new( + mono_domain_get(), + passName); +} + int32_t InternalCall_Rendering_ScriptableRenderContext_GetSourceColorTextureHandle( uint64_t nativeHandle) { const ManagedScriptableRenderContextState* const state = @@ -5258,6 +5504,40 @@ InternalCall_Rendering_ScriptableRenderContext_AddRasterPassTextureBinding( return 1; } +mono_bool +InternalCall_Rendering_ScriptableRenderContext_AddRasterPassRendererList( + uint64_t nativeHandle, + uint64_t rasterPassHandle, + int32_t rendererListHandle) { + ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + ManagedScriptableRenderContextState::RasterPassRecordRequest* + const request = + FindPendingManagedRasterPassRecordRequest( + state, + rasterPassHandle); + if (state == nullptr || + request == nullptr || + rendererListHandle < 0 || + static_cast(rendererListHandle) >= + state->rendererListRequests.size()) { + return 0; + } + + const Core::uint32 rendererListIndex = + static_cast(rendererListHandle); + if (std::find( + request->rendererListIndices.begin(), + request->rendererListIndices.end(), + rendererListIndex) == + request->rendererListIndices.end()) { + request->rendererListIndices.push_back( + rendererListIndex); + } + + return 1; +} + mono_bool InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorAttachment( uint64_t nativeHandle, @@ -5516,6 +5796,51 @@ mono_bool InternalCall_Rendering_CommandBuffer_ClearRenderTarget( return 1; } +mono_bool InternalCall_Rendering_CommandBuffer_DrawRendererList( + uint64_t nativeHandle, + int32_t rendererListHandle) { + ManagedCommandBufferState* const state = + FindManagedCommandBufferState(nativeHandle); + if (state == nullptr || + rendererListHandle < 0 || + static_cast(rendererListHandle) >= + state->rendererLists.size()) { + return 0; + } + + const Core::uint32 rendererListIndex = + static_cast(rendererListHandle); + if (std::find( + state->declaredRendererListIndices.begin(), + state->declaredRendererListIndices.end(), + rendererListIndex) == + state->declaredRendererListIndices.end()) { + return 0; + } + + ManagedCommandBufferCommand command = {}; + command.kind = + ManagedCommandBufferCommand::Kind::DrawRendererList; + command.rendererListIndex = rendererListIndex; + state->commands.push_back(command); + return 1; +} + +mono_bool InternalCall_Rendering_CommandBuffer_DrawSkybox( + uint64_t nativeHandle) { + ManagedCommandBufferState* const state = + FindManagedCommandBufferState(nativeHandle); + if (state == nullptr) { + return 0; + } + + ManagedCommandBufferCommand command = {}; + command.kind = + ManagedCommandBufferCommand::Kind::DrawSkybox; + state->commands.push_back(command); + return 1; +} + int32_t InternalCall_Rendering_ScriptableRenderContext_GetStageColorSource( uint64_t nativeHandle) { const ManagedScriptableRenderContextState* const state = @@ -6062,44 +6387,17 @@ InternalCall_Rendering_ScriptableRenderContext_DrawRenderersByDesc( } Rendering::DrawSettings drawSettings = {}; - drawSettings.scenePhase = - static_cast(scenePhase); - if (!TryBuildManagedRendererListDesc( + if (!TryBuildManagedDrawSettings( + state->stage, *rendererListDescData, - drawSettings.rendererListDesc)) { - Debug::Logger::Get().Error( - Debug::LogCategory::Rendering, - "ScriptableRenderContext DrawRenderers received an unsupported renderer-list type"); + overrideMaterialPath, + shaderPassName, + renderStateBlockData, + drawSettings)) { return 0; } - const std::string overrideMaterialPathUtf8 = - MonoStringToUtf8(overrideMaterialPath); - if (!overrideMaterialPathUtf8.empty()) { - drawSettings.overrideMaterial = - Resources::ResourceManager::Get().Load( - overrideMaterialPathUtf8.c_str()); - if (!drawSettings.overrideMaterial.IsValid()) { - Debug::Logger::Get().Error( - Debug::LogCategory::Rendering, - (Containers::String( - "ScriptableRenderContext DrawRenderers failed to load override material: ") + - Containers::String(overrideMaterialPathUtf8.c_str())) - .CStr()); - return 0; - } - } - - const std::string shaderPassNameUtf8 = - MonoStringToUtf8(shaderPassName); - if (!shaderPassNameUtf8.empty()) { - drawSettings.shaderPassName = - Containers::String(shaderPassNameUtf8.c_str()); - } - if (renderStateBlockData != nullptr) { - drawSettings.renderStateBlock = - BuildManagedRenderStateBlock( - *renderStateBlockData); - } + drawSettings.scenePhase = + static_cast(scenePhase); return state->sceneRecorder->RecordSceneDrawSettings( drawSettings) @@ -6107,6 +6405,45 @@ InternalCall_Rendering_ScriptableRenderContext_DrawRenderersByDesc( : 0; } +int32_t +InternalCall_Rendering_ScriptableRenderContext_CreateRendererList( + uint64_t nativeHandle, + ManagedRendererListDescData* rendererListDescData, + MonoString* overrideMaterialPath, + MonoString* shaderPassName, + ManagedRenderStateBlockData* renderStateBlockData) { + ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + if (state == nullptr || + state->graphContext == nullptr || + rendererListDescData == nullptr) { + return -1; + } + + Rendering::DrawSettings drawSettings = {}; + if (!TryBuildManagedDrawSettings( + state->stage, + *rendererListDescData, + overrideMaterialPath, + shaderPassName, + renderStateBlockData, + drawSettings)) { + return -1; + } + + const size_t rendererListIndex = + state->rendererListRequests.size(); + if (rendererListIndex > + static_cast( + std::numeric_limits::max())) { + return -1; + } + + state->rendererListRequests.push_back( + std::move(drawSettings)); + return static_cast(rendererListIndex); +} + int32_t InternalCall_Rendering_CameraRenderRequestContext_GetRenderedBaseCameraCount( uint64_t nativeHandle) { @@ -6948,6 +7285,7 @@ void RegisterInternalCalls() { mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetStage", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetStage)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetRendererIndex", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetRendererIndex)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetFramePlanId", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetFramePlanId)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetPassName", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetPassName)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetSourceColorTextureHandle", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetSourceColorTextureHandle)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetPrimaryColorTargetHandle", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetPrimaryColorTargetHandle)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetDepthTargetHandle", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetDepthTargetHandle)); @@ -6959,6 +7297,7 @@ void RegisterInternalCalls() { mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_AddRasterPassReadTexture", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_AddRasterPassReadTexture)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_AddRasterPassReadDepthTexture", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_AddRasterPassReadDepthTexture)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_AddRasterPassTextureBinding", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_AddRasterPassTextureBinding)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_AddRasterPassRendererList", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_AddRasterPassRendererList)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassColorAttachment", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorAttachment)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassDepthAttachment", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassDepthAttachment)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassColorScaleFullscreenExecution", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorScaleFullscreenExecution)); @@ -6967,6 +7306,8 @@ void RegisterInternalCalls() { 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_CommandBuffer_ClearRenderTarget", reinterpret_cast(&InternalCall_Rendering_CommandBuffer_ClearRenderTarget)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_CommandBuffer_DrawRendererList", reinterpret_cast(&InternalCall_Rendering_CommandBuffer_DrawRendererList)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_CommandBuffer_DrawSkybox", reinterpret_cast(&InternalCall_Rendering_CommandBuffer_DrawSkybox)); 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)); @@ -7019,6 +7360,7 @@ void RegisterInternalCalls() { mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetFinalColorHasCameraOverrides", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetFinalColorHasCameraOverrides)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_RecordScenePhase", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_RecordScenePhase)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_DrawRenderersByDesc", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_DrawRenderersByDesc)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_CreateRendererList", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_CreateRendererList)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_GetRendererIndex", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetRendererIndex)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_GetFramePlanId", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetFramePlanId)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_IsStageRequested", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_IsStageRequested)); diff --git a/managed/CMakeLists.txt b/managed/CMakeLists.txt index dcc6cd86..bc61ff7e 100644 --- a/managed/CMakeLists.txt +++ b/managed/CMakeLists.txt @@ -197,6 +197,7 @@ set(XCENGINE_SCRIPT_CORE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/RenderStateBlock.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/RenderStateMask.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/RendererListDesc.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/RendererListHandle.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/RendererListType.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/RendererSortMode.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/SceneRenderPhase.cs diff --git a/managed/GameScripts/ScriptableRenderContextApiSurfaceProbe.cs b/managed/GameScripts/ScriptableRenderContextApiSurfaceProbe.cs index a3e7cd46..706b5f46 100644 --- a/managed/GameScripts/ScriptableRenderContextApiSurfaceProbe.cs +++ b/managed/GameScripts/ScriptableRenderContextApiSurfaceProbe.cs @@ -71,6 +71,7 @@ namespace Gameplay public bool HasRenderGraphRasterPassBuilderType; public bool HasRenderGraphRasterPassBuilderUseColorSource; public bool HasRenderGraphRasterPassBuilderUseTexture; + public bool HasRenderGraphRasterPassBuilderUseRendererList; public bool HasRenderGraphRasterPassBuilderSetColorAttachment; public bool HasRenderGraphRasterPassBuilderSetRenderFunc; public bool HasRenderGraphRasterPassBuilderSetColorScaleFullscreenExecution; @@ -111,11 +112,15 @@ namespace Gameplay public bool HasContextContainerGetOrCreate; public bool HasRenderGraphType; public bool HasRenderGraphAddRasterPass; + public bool HasRenderGraphCreateRendererList; public bool HasRenderPassPublicRecordRenderGraph; public bool HasPublicRenderingDataFramePlanId; public bool HasRenderPassProtectedRecordColorScaleFullscreenPass; public bool HasRenderPassProtectedRecordShaderVectorFullscreenPass; public bool HasRenderPassProtectedRecordFinalColorFullscreenPass; + public bool HasRendererListHandleType; + public bool HasCommandBufferDrawRendererList; + public bool HasCommandBufferDrawSkybox; public bool HasRenderPassComparisonOperators; public bool HasRenderPassEventUnityNumericOrder; public bool HasRenderPassEventEngineExtensionOrder; @@ -201,6 +206,8 @@ namespace Gameplay typeof(ScriptableRenderPass); System.Type commandBufferType = typeof(CommandBuffer); + System.Type rendererListHandleType = + typeof(RendererListHandle); System.Type profilingSamplerType = typeof(ProfilingSampler); System.Type sceneRenderPhaseType = @@ -502,6 +509,16 @@ namespace Gameplay rasterPassBuilderType.GetMethod( "UseTexture", PublicInstanceMethodFlags) != null; + HasRenderGraphRasterPassBuilderUseRendererList = + rasterPassBuilderType.GetMethod( + "UseRendererList", + PublicInstanceMethodFlags, + null, + new System.Type[] + { + typeof(RendererListHandle) + }, + null) != null; HasRenderGraphRasterPassBuilderSetColorAttachment = rasterPassBuilderType.GetMethod( "SetColorAttachment", @@ -674,6 +691,17 @@ namespace Gameplay typeof(string) }, null) != null; + HasRenderGraphCreateRendererList = + renderGraphType.GetMethod( + "CreateRendererList", + PublicInstanceMethodFlags, + null, + new System.Type[] + { + typeof(RendererListDesc), + typeof(DrawingSettings) + }, + null) != null; HasRenderPassPublicRecordRenderGraph = renderPassType.GetMethod( "RecordRenderGraph", @@ -704,6 +732,22 @@ namespace Gameplay "RecordFinalColorFullscreenPass", BindingFlags.Instance | BindingFlags.NonPublic) != null; + HasRendererListHandleType = + rendererListHandleType != null; + HasCommandBufferDrawRendererList = + commandBufferType.GetMethod( + "DrawRendererList", + PublicInstanceMethodFlags, + null, + new System.Type[] + { + typeof(RendererListHandle) + }, + null) != null; + HasCommandBufferDrawSkybox = + commandBufferType.GetMethod( + "DrawSkybox", + PublicInstanceMethodFlags) != null; HasRenderPassComparisonOperators = renderPassType.GetMethod( "op_GreaterThan", diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DrawObjectsPass.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DrawObjectsPass.cs index 9c4f6cc2..1fa7764e 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DrawObjectsPass.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DrawObjectsPass.cs @@ -1,5 +1,6 @@ using XCEngine; using XCEngine.Rendering; +using XCEngine.Rendering.RenderGraphModule; namespace XCEngine.Rendering.Universal { @@ -52,6 +53,69 @@ namespace XCEngine.Rendering.Universal m_drawingSettings = drawingSettings; } + public override void RecordRenderGraph( + RenderGraph renderGraph, + ContextContainer frameData) + { + if (renderGraph == null || + frameData == null) + { + return; + } + + RenderingData renderingData = + frameData.Get(); + if (renderingData == null || + !renderingData.isSceneDrawStage) + { + return; + } + + RendererListHandle rendererList = + renderGraph.CreateRendererList( + m_rendererListDesc, + m_drawingSettings); + if (!rendererList.isValid) + { + return; + } + + RenderGraphTextureHandle primaryColorTarget = + renderGraph.primaryColorTarget; + RenderGraphTextureHandle depthTarget = + renderGraph.depthTarget; + if (!primaryColorTarget.isValid && + !depthTarget.isValid) + { + return; + } + + RenderGraphRasterPassBuilder passBuilder = + renderGraph.AddRasterPass( + ResolvePassName()); + if (primaryColorTarget.isValid) + { + passBuilder.SetColorAttachment( + primaryColorTarget); + } + + if (depthTarget.isValid) + { + passBuilder.SetDepthAttachment( + depthTarget); + } + + passBuilder + .UseRendererList(rendererList) + .SetRenderFunc( + rasterContext => + { + rasterContext.cmd.DrawRendererList( + rendererList); + }) + .Commit(); + } + protected override bool RecordRenderGraph( ScriptableRenderContext context, RenderingData renderingData) @@ -63,5 +127,30 @@ namespace XCEngine.Rendering.Universal m_rendererListDesc, m_drawingSettings); } + + private string ResolvePassName() + { + switch (renderPassEvent) + { + case RenderPassEvent.BeforeRenderingShadows: + case RenderPassEvent.AfterRenderingShadows: + return "Universal.DrawShadowCasterObjects"; + case RenderPassEvent.BeforeRenderingPrePasses: + case RenderPassEvent.AfterRenderingPrePasses: + return "Universal.DrawDepthOnlyObjects"; + case RenderPassEvent.BeforeRenderingTransparents: + case RenderPassEvent.RenderTransparents: + case RenderPassEvent.AfterRenderingTransparents: + return "Universal.DrawTransparentObjects"; + case RenderPassEvent.BeforeRenderingOpaques: + case RenderPassEvent.RenderOpaques: + case RenderPassEvent.AfterRenderingOpaques: + default: + return m_rendererListDesc.type == + RendererListType.Transparent + ? "Universal.DrawTransparentObjects" + : "Universal.DrawOpaqueObjects"; + } + } } } diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DrawSkyboxPass.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DrawSkyboxPass.cs index b91ef3d2..9558a053 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DrawSkyboxPass.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DrawSkyboxPass.cs @@ -1,5 +1,6 @@ using XCEngine; using XCEngine.Rendering; +using XCEngine.Rendering.RenderGraphModule; namespace XCEngine.Rendering.Universal { @@ -18,6 +19,58 @@ namespace XCEngine.Rendering.Universal renderPassEvent = passEvent; } + public override void RecordRenderGraph( + RenderGraph renderGraph, + ContextContainer frameData) + { + if (renderGraph == null || + frameData == null) + { + return; + } + + RenderingData renderingData = + frameData.Get(); + if (renderingData == null || + !renderingData.isMainSceneStage) + { + return; + } + + RenderGraphTextureHandle primaryColorTarget = + renderGraph.primaryColorTarget; + RenderGraphTextureHandle depthTarget = + renderGraph.depthTarget; + if (!primaryColorTarget.isValid && + !depthTarget.isValid) + { + return; + } + + RenderGraphRasterPassBuilder passBuilder = + renderGraph.AddRasterPass( + "Universal.DrawSkybox"); + if (primaryColorTarget.isValid) + { + passBuilder.SetColorAttachment( + primaryColorTarget); + } + + if (depthTarget.isValid) + { + passBuilder.SetDepthAttachment( + depthTarget); + } + + passBuilder + .SetRenderFunc( + rasterContext => + { + rasterContext.cmd.DrawSkybox(); + }) + .Commit(); + } + protected override bool RecordRenderGraph( ScriptableRenderContext context, RenderingData renderingData) diff --git a/managed/XCEngine.ScriptCore/InternalCalls.cs b/managed/XCEngine.ScriptCore/InternalCalls.cs index 2980ebdc..da38dc69 100644 --- a/managed/XCEngine.ScriptCore/InternalCalls.cs +++ b/managed/XCEngine.ScriptCore/InternalCalls.cs @@ -437,6 +437,11 @@ namespace XCEngine Rendering_ScriptableRenderContext_GetFramePlanId( ulong nativeHandle); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern string + Rendering_ScriptableRenderContext_GetPassName( + ulong nativeHandle); + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern int Rendering_ScriptableRenderContext_GetSourceColorTextureHandle( @@ -507,6 +512,13 @@ namespace XCEngine int textureHandle, bool isDepth); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool + Rendering_ScriptableRenderContext_AddRasterPassRendererList( + ulong nativeHandle, + ulong rasterPassHandle, + int rendererListHandle); + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern bool Rendering_ScriptableRenderContext_SetRasterPassColorAttachment( @@ -564,6 +576,17 @@ namespace XCEngine ulong nativeHandle, ref Color color); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool + Rendering_CommandBuffer_DrawRendererList( + ulong nativeHandle, + int rendererListHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool + Rendering_CommandBuffer_DrawSkybox( + ulong nativeHandle); + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern int Rendering_ScriptableRenderPipelinePlanningContext_GetRendererIndex( @@ -927,6 +950,15 @@ namespace XCEngine string shaderPassName, ref Rendering.RenderStateBlock renderStateBlock); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int + Rendering_ScriptableRenderContext_CreateRendererList( + ulong nativeHandle, + ref Rendering.RendererListDesc rendererListDesc, + string overrideMaterialPath, + string shaderPassName, + ref Rendering.RenderStateBlock renderStateBlock); + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern int Rendering_CameraRenderRequestContext_GetRenderedBaseCameraCount( diff --git a/managed/XCEngine.ScriptCore/Rendering/Core/CommandBuffer.cs b/managed/XCEngine.ScriptCore/Rendering/Core/CommandBuffer.cs index a7a0d6b3..39fdb5ef 100644 --- a/managed/XCEngine.ScriptCore/Rendering/Core/CommandBuffer.cs +++ b/managed/XCEngine.ScriptCore/Rendering/Core/CommandBuffer.cs @@ -38,6 +38,23 @@ namespace XCEngine.Rendering ref color); } + public bool DrawRendererList( + RendererListHandle rendererList) + { + return m_nativeHandle != 0ul && + rendererList.isValid && + InternalCalls.Rendering_CommandBuffer_DrawRendererList( + m_nativeHandle, + rendererList.nativeIndex); + } + + public bool DrawSkybox() + { + return m_nativeHandle != 0ul && + InternalCalls.Rendering_CommandBuffer_DrawSkybox( + m_nativeHandle); + } + private readonly ulong m_nativeHandle; } } diff --git a/managed/XCEngine.ScriptCore/Rendering/Core/RendererListHandle.cs b/managed/XCEngine.ScriptCore/Rendering/Core/RendererListHandle.cs new file mode 100644 index 00000000..f044b749 --- /dev/null +++ b/managed/XCEngine.ScriptCore/Rendering/Core/RendererListHandle.cs @@ -0,0 +1,29 @@ +namespace XCEngine.Rendering +{ + public struct RendererListHandle + { + private readonly int m_indexPlusOne; + + private RendererListHandle( + int indexPlusOne) + { + m_indexPlusOne = indexPlusOne; + } + + public bool isValid => + m_indexPlusOne > 0; + + internal int nativeIndex => + m_indexPlusOne > 0 + ? m_indexPlusOne - 1 + : -1; + + internal static RendererListHandle FromNativeIndex( + int nativeIndex) + { + return nativeIndex >= 0 + ? new RendererListHandle(nativeIndex + 1) + : default; + } + } +} diff --git a/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs b/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs index 0da99d7b..616b3f0e 100644 --- a/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs +++ b/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs @@ -28,6 +28,11 @@ namespace XCEngine.Rendering .Rendering_ScriptableRenderContext_GetFramePlanId( m_nativeHandle); + internal string passName => + InternalCalls + .Rendering_ScriptableRenderContext_GetPassName( + m_nativeHandle) ?? string.Empty; + public RenderGraphTextureHandle sourceColorTexture => RenderGraphTextureHandle.FromNativeIndex( InternalCalls @@ -171,6 +176,23 @@ namespace XCEngine.Rendering name)); } + internal RendererListHandle CreateRendererList( + RendererListDesc rendererListDesc, + DrawingSettings drawingSettings) + { + RenderStateBlock renderStateBlock = + drawingSettings.renderStateBlock; + return RendererListHandle.FromNativeIndex( + InternalCalls + .Rendering_ScriptableRenderContext_CreateRendererList( + m_nativeHandle, + ref rendererListDesc, + drawingSettings.overrideMaterialPath ?? + string.Empty, + drawingSettings.shaderPassName ?? string.Empty, + ref renderStateBlock)); + } + // Public RenderGraph raster authoring entry point. Built-in fullscreen // kernels are internal URP implementation details, not public context // shortcuts. diff --git a/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraph.cs b/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraph.cs index 436e37dc..208eb059 100644 --- a/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraph.cs +++ b/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraph.cs @@ -30,5 +30,53 @@ namespace XCEngine.Rendering.RenderGraphModule return m_context.AddRasterPass(passName); } + + public XCEngine.Rendering.RendererListHandle + CreateRendererList( + XCEngine.Rendering.RendererListDesc rendererListDesc) + { + return CreateRendererList( + rendererListDesc, + XCEngine.Rendering.DrawingSettings.CreateDefault()); + } + + public XCEngine.Rendering.RendererListHandle + CreateRendererList( + XCEngine.Rendering.RendererListDesc rendererListDesc, + XCEngine.Rendering.DrawingSettings drawingSettings) + { + if (m_context == null) + { + throw new InvalidOperationException( + "RenderGraph is not bound to a recording context."); + } + + return m_context.CreateRendererList( + rendererListDesc, + drawingSettings); + } + + internal string passName => + m_context != null + ? m_context.passName + : string.Empty; + + public XCEngine.Rendering.RenderGraphTextureHandle + sourceColorTexture => + m_context != null + ? m_context.sourceColorTexture + : default; + + public XCEngine.Rendering.RenderGraphTextureHandle + primaryColorTarget => + m_context != null + ? m_context.primaryColorTarget + : default; + + public XCEngine.Rendering.RenderGraphTextureHandle + depthTarget => + m_context != null + ? m_context.depthTarget + : default; } } diff --git a/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraphRasterPassBuilder.cs b/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraphRasterPassBuilder.cs index 584abdf5..45d25d89 100644 --- a/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraphRasterPassBuilder.cs +++ b/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraphRasterPassBuilder.cs @@ -42,6 +42,8 @@ namespace XCEngine.Rendering new List(); private readonly List m_readDepthTextures = new List(); + private readonly List m_rendererLists = + new List(); private readonly List m_textureBindings = new List(); private readonly List m_colorAttachments = @@ -123,6 +125,27 @@ namespace XCEngine.Rendering return this; } + public RenderGraphRasterPassBuilder UseRendererList( + RendererListHandle rendererList) + { + if (!rendererList.isValid) + { + return this; + } + + for (int i = 0; i < m_rendererLists.Count; ++i) + { + if (m_rendererLists[i].nativeIndex == + rendererList.nativeIndex) + { + return this; + } + } + + m_rendererLists.Add(rendererList); + return this; + } + public RenderGraphRasterPassBuilder SetColorAttachment( RenderGraphTextureHandle texture, int index = 0) @@ -309,6 +332,25 @@ namespace XCEngine.Rendering } } + for (int i = 0; i < m_rendererLists.Count; ++i) + { + RendererListHandle rendererList = + m_rendererLists[i]; + if (!rendererList.isValid) + { + continue; + } + + if (!InternalCalls + .Rendering_ScriptableRenderContext_AddRasterPassRendererList( + m_context.nativeHandle, + nativePassHandle, + rendererList.nativeIndex)) + { + return false; + } + } + for (int i = 0; i < m_colorAttachments.Count; ++i) { RenderGraphTextureHandle colorAttachment = diff --git a/tests/scripting/test_mono_script_runtime.cpp b/tests/scripting/test_mono_script_runtime.cpp index f39b2148..cae40da1 100644 --- a/tests/scripting/test_mono_script_runtime.cpp +++ b/tests/scripting/test_mono_script_runtime.cpp @@ -1277,7 +1277,104 @@ TEST_F( ASSERT_EQ(compiledGraph.GetPassCount(), 1u); EXPECT_STREQ( compiledGraph.GetPassName(0).CStr(), - "ScriptCoreUniversalMainScene.Opaque"); + "Universal.DrawOpaqueObjects"); + + host->GetStageRecorder()->Shutdown(); +} + +TEST_F( + MonoScriptRuntimeTest, + DefaultCameraRendererUsesScriptCoreUniversalPipelineAssetDefaultMainScenePasses) { + Scene* runtimeScene = + CreateScene("ScriptCoreUniversalRenderPipelineDefaultMainSceneScene"); + GameObject* selectionObject = + runtimeScene->CreateGameObject("ScriptCoreUniversalRenderPipelineSelection"); + ScriptComponent* selectionScript = + AddScript( + selectionObject, + "Gameplay", + "ScriptCoreUniversalRenderPipelineSelectionProbe"); + ASSERT_NE(selectionScript, nullptr); + + engine->OnRuntimeStart(runtimeScene); + engine->OnUpdate(0.016f); + + XCEngine::Rendering::CameraRenderer renderer; + 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( + "ScriptCoreUniversalDefaultMainSceneColor", + colorDesc); + const XCEngine::Rendering::RenderGraphTextureHandle depthTarget = + graphBuilder.CreateTransientTexture( + "ScriptCoreUniversalDefaultMainSceneDepth", + 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, + "ScriptCoreUniversalDefaultMainScene", + 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(), 3u); + EXPECT_STREQ( + compiledGraph.GetPassName(0).CStr(), + "Universal.DrawOpaqueObjects"); + EXPECT_STREQ( + compiledGraph.GetPassName(1).CStr(), + "Universal.DrawSkybox"); + EXPECT_STREQ( + compiledGraph.GetPassName(2).CStr(), + "Universal.DrawTransparentObjects"); host->GetStageRecorder()->Shutdown(); } @@ -1618,6 +1715,7 @@ TEST_F( bool hasRenderGraphRasterPassBuilderType = false; bool hasRenderGraphRasterPassBuilderUseColorSource = false; bool hasRenderGraphRasterPassBuilderUseTexture = false; + bool hasRenderGraphRasterPassBuilderUseRendererList = false; bool hasRenderGraphRasterPassBuilderSetColorAttachment = false; bool hasRenderGraphRasterPassBuilderSetRenderFunc = false; bool hasRenderGraphRasterPassBuilderSetColorScaleFullscreenExecution = false; @@ -1628,6 +1726,10 @@ TEST_F( bool hasRenderGraphRasterContextCommandBuffer = false; bool hasSceneRenderPhaseType = false; bool hasSceneRenderInjectionPointType = false; + bool hasRenderGraphCreateRendererList = false; + bool hasRendererListHandleType = false; + bool hasCommandBufferDrawRendererList = false; + bool hasCommandBufferDrawSkybox = false; bool hasPublicRenderingDataFramePlanId = false; bool hasRenderPassProtectedRecordColorScaleFullscreenPass = false; bool hasRenderPassProtectedRecordShaderVectorFullscreenPass = false; @@ -1817,6 +1919,10 @@ TEST_F( selectionScript, "HasRenderGraphRasterPassBuilderUseTexture", hasRenderGraphRasterPassBuilderUseTexture)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRenderGraphRasterPassBuilderUseRendererList", + hasRenderGraphRasterPassBuilderUseRendererList)); EXPECT_TRUE(runtime->TryGetFieldValue( selectionScript, "HasRenderGraphRasterPassBuilderSetColorAttachment", @@ -1857,6 +1963,22 @@ TEST_F( selectionScript, "HasSceneRenderInjectionPointType", hasSceneRenderInjectionPointType)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRenderGraphCreateRendererList", + hasRenderGraphCreateRendererList)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRendererListHandleType", + hasRendererListHandleType)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasCommandBufferDrawRendererList", + hasCommandBufferDrawRendererList)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasCommandBufferDrawSkybox", + hasCommandBufferDrawSkybox)); EXPECT_TRUE(runtime->TryGetFieldValue( selectionScript, "HasPublicRenderingDataFramePlanId", @@ -1920,6 +2042,7 @@ TEST_F( EXPECT_TRUE(hasRenderGraphRasterPassBuilderType); EXPECT_TRUE(hasRenderGraphRasterPassBuilderUseColorSource); EXPECT_TRUE(hasRenderGraphRasterPassBuilderUseTexture); + EXPECT_TRUE(hasRenderGraphRasterPassBuilderUseRendererList); EXPECT_TRUE(hasRenderGraphRasterPassBuilderSetColorAttachment); EXPECT_TRUE(hasRenderGraphRasterPassBuilderSetRenderFunc); EXPECT_FALSE(hasRenderGraphRasterPassBuilderSetColorScaleFullscreenExecution); @@ -1930,6 +2053,10 @@ TEST_F( EXPECT_TRUE(hasRenderGraphRasterContextCommandBuffer); EXPECT_FALSE(hasSceneRenderPhaseType); EXPECT_FALSE(hasSceneRenderInjectionPointType); + EXPECT_TRUE(hasRenderGraphCreateRendererList); + EXPECT_TRUE(hasRendererListHandleType); + EXPECT_TRUE(hasCommandBufferDrawRendererList); + EXPECT_TRUE(hasCommandBufferDrawSkybox); EXPECT_TRUE(hasPublicRenderingDataFramePlanId); EXPECT_FALSE(hasRenderPassProtectedRecordColorScaleFullscreenPass); EXPECT_FALSE(hasRenderPassProtectedRecordShaderVectorFullscreenPass);