refactor(srp): move recording helpers into universal extensions

This commit is contained in:
2026-04-19 14:42:57 +08:00
parent f4d4112e2f
commit 8edc68f02b
9 changed files with 309 additions and 167 deletions

View File

@@ -205,9 +205,11 @@ set(XCENGINE_RENDER_PIPELINES_UNIVERSAL_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/RenderingDataResolver.cs
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/ShadowData.cs
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/ScriptableRenderPass.cs
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/ScriptableRenderContextExtensions.cs
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/ScriptableRenderer.cs
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/ScriptableRendererData.cs
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/ScriptableRendererFeature.cs
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/ScriptableRenderPipelineCameraRequestContextExtensions.cs
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/StageColorData.cs
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/UniversalRenderer.cs
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/UniversalRendererData.cs

View File

@@ -789,7 +789,7 @@ namespace Gameplay
ScriptableRenderPipelineCameraRequestContext context)
{
if (context != null &&
context.hasDirectionalShadow)
context.HasDirectionalShadow())
{
context.ClearDirectionalShadow();
}

View File

@@ -20,6 +20,12 @@ namespace Gameplay
public bool HasPublicContextStageColorData;
public bool HasPublicCameraRequestContextHasDirectionalShadow;
public bool HasPublicCameraRequestContextClearDirectionalShadow;
public bool HasUniversalContextRecordSceneExtension;
public bool HasUniversalContextRecordOpaqueScenePhaseExtension;
public bool HasUniversalContextRecordBeforeOpaqueInjectionExtension;
public bool HasUniversalContextRecordShaderVectorFullscreenPassExtension;
public bool HasUniversalCameraRequestContextHasDirectionalShadowExtension;
public bool HasUniversalCameraRequestContextClearDirectionalShadowExtension;
public bool HasPublicPipelineAssetConfigureCameraFramePlan;
public bool HasPlanningContextType;
public bool HasRendererFeatureConfigureCameraFramePlan;
@@ -38,6 +44,16 @@ namespace Gameplay
typeof(ScriptableRenderPipelineAsset);
System.Type rendererFeatureType =
typeof(ScriptableRendererFeature);
System.Type universalAssemblyType =
typeof(ScriptableRendererFeature);
System.Reflection.Assembly universalAssembly =
universalAssemblyType.Assembly;
System.Type renderContextExtensionsType =
universalAssembly.GetType(
"XCEngine.Rendering.Universal.ScriptableRenderContextExtensions");
System.Type cameraRequestContextExtensionsType =
universalAssembly.GetType(
"XCEngine.Rendering.Universal.ScriptableRenderPipelineCameraRequestContextExtensions");
HasPublicContextRecordScene =
contextType.GetMethod(
@@ -87,6 +103,36 @@ namespace Gameplay
cameraRequestContextType.GetMethod(
"ClearDirectionalShadow",
PublicInstanceMethodFlags) != null;
HasUniversalContextRecordSceneExtension =
renderContextExtensionsType != null &&
renderContextExtensionsType.GetMethod(
"RecordScene",
BindingFlags.Static | BindingFlags.Public) != null;
HasUniversalContextRecordOpaqueScenePhaseExtension =
renderContextExtensionsType != null &&
renderContextExtensionsType.GetMethod(
"RecordOpaqueScenePhase",
BindingFlags.Static | BindingFlags.Public) != null;
HasUniversalContextRecordBeforeOpaqueInjectionExtension =
renderContextExtensionsType != null &&
renderContextExtensionsType.GetMethod(
"RecordBeforeOpaqueInjection",
BindingFlags.Static | BindingFlags.Public) != null;
HasUniversalContextRecordShaderVectorFullscreenPassExtension =
renderContextExtensionsType != null &&
renderContextExtensionsType.GetMethod(
"RecordShaderVectorFullscreenPass",
BindingFlags.Static | BindingFlags.Public) != null;
HasUniversalCameraRequestContextHasDirectionalShadowExtension =
cameraRequestContextExtensionsType != null &&
cameraRequestContextExtensionsType.GetMethod(
"HasDirectionalShadow",
BindingFlags.Static | BindingFlags.Public) != null;
HasUniversalCameraRequestContextClearDirectionalShadowExtension =
cameraRequestContextExtensionsType != null &&
cameraRequestContextExtensionsType.GetMethod(
"ClearDirectionalShadow",
BindingFlags.Static | BindingFlags.Public) != null;
HasPublicPipelineAssetConfigureCameraFramePlan =
pipelineAssetType.GetMethod(
"ConfigureCameraFramePlan",

View File

@@ -1,33 +1,9 @@
using System;
using XCEngine;
namespace XCEngine.Rendering
{
public sealed class ScriptableRenderContext
{
private enum RecordedScenePhase
{
Opaque = 0,
Skybox = 1,
Transparent = 3
}
private enum RecordedSceneInjectionPoint
{
BeforeOpaque = 0,
AfterOpaque = 1,
BeforeSkybox = 2,
AfterSkybox = 3,
BeforeTransparent = 4,
AfterTransparent = 5
}
private enum RecordedFullscreenPassType
{
ColorScale = 0,
ShaderVector = 1
}
private readonly ulong m_nativeHandle;
internal ScriptableRenderContext(ulong nativeHandle)
@@ -41,130 +17,6 @@ namespace XCEngine.Rendering
internal ulong nativeHandle =>
m_nativeHandle;
public bool RecordScene()
{
return InternalCalls
.Rendering_ScriptableRenderContext_RecordScene(
m_nativeHandle);
}
public bool RecordOpaqueScenePhase()
{
return RecordScenePhaseInternal(
RecordedScenePhase.Opaque);
}
public bool RecordSkyboxScenePhase()
{
return RecordScenePhaseInternal(
RecordedScenePhase.Skybox);
}
public bool RecordTransparentScenePhase()
{
return RecordScenePhaseInternal(
RecordedScenePhase.Transparent);
}
public bool RecordBeforeOpaqueInjection()
{
return RecordSceneInjectionPointInternal(
RecordedSceneInjectionPoint.BeforeOpaque);
}
public bool RecordAfterOpaqueInjection()
{
return RecordSceneInjectionPointInternal(
RecordedSceneInjectionPoint.AfterOpaque);
}
public bool RecordBeforeSkyboxInjection()
{
return RecordSceneInjectionPointInternal(
RecordedSceneInjectionPoint.BeforeSkybox);
}
public bool RecordAfterSkyboxInjection()
{
return RecordSceneInjectionPointInternal(
RecordedSceneInjectionPoint.AfterSkybox);
}
public bool RecordBeforeTransparentInjection()
{
return RecordSceneInjectionPointInternal(
RecordedSceneInjectionPoint.BeforeTransparent);
}
public bool RecordAfterTransparentInjection()
{
return RecordSceneInjectionPointInternal(
RecordedSceneInjectionPoint.AfterTransparent);
}
public bool RecordColorScaleFullscreenPass(
Vector4 colorScale)
{
return RecordFullscreenPassInternal(
RecordedFullscreenPassType.ColorScale,
string.Empty,
string.Empty,
colorScale);
}
public bool RecordShaderVectorFullscreenPass(
string shaderPath,
Vector4 vectorPayload,
string passName = null)
{
if (string.IsNullOrEmpty(shaderPath))
{
throw new ArgumentException(
"Fullscreen shader path cannot be null or empty.",
nameof(shaderPath));
}
return RecordFullscreenPassInternal(
RecordedFullscreenPassType.ShaderVector,
shaderPath,
passName ?? string.Empty,
vectorPayload);
}
private bool RecordScenePhaseInternal(
RecordedScenePhase scenePhase)
{
return InternalCalls
.Rendering_ScriptableRenderContext_RecordScenePhase(
m_nativeHandle,
(int)scenePhase);
}
private bool RecordSceneInjectionPointInternal(
RecordedSceneInjectionPoint injectionPoint)
{
return InternalCalls
.Rendering_ScriptableRenderContext_RecordSceneInjectionPoint(
m_nativeHandle,
(int)injectionPoint);
}
private bool RecordFullscreenPassInternal(
RecordedFullscreenPassType passType,
string shaderPath,
string passName,
Vector4 vectorPayload)
{
return InternalCalls
.Rendering_ScriptableRenderContext_RecordFullscreenPass(
m_nativeHandle,
(int)passType,
shaderPath,
passName,
ref vectorPayload);
}
}
}

View File

@@ -21,17 +21,8 @@ namespace XCEngine.Rendering
.Rendering_ScriptableRenderPipelineCameraRequestContext_GetRenderedRequestCount(
m_nativeHandle);
public bool hasDirectionalShadow =>
InternalCalls
.Rendering_ScriptableRenderPipelineCameraRequestContext_GetHasDirectionalShadow(
m_nativeHandle);
public void ClearDirectionalShadow()
{
InternalCalls
.Rendering_ScriptableRenderPipelineCameraRequestContext_ClearDirectionalShadow(
m_nativeHandle);
}
internal ulong nativeHandle =>
m_nativeHandle;
}
}

View File

@@ -10,7 +10,7 @@ namespace XCEngine.Rendering.Universal
ScriptableRenderPipelineCameraRequestContext context)
{
if (context != null &&
context.hasDirectionalShadow)
context.HasDirectionalShadow())
{
context.ClearDirectionalShadow();
}

View File

@@ -0,0 +1,185 @@
using System;
using XCEngine;
using XCEngine.Rendering;
namespace XCEngine.Rendering.Universal
{
public static class ScriptableRenderContextExtensions
{
private enum RecordedScenePhase
{
Opaque = 0,
Skybox = 1,
Transparent = 3
}
private enum RecordedSceneInjectionPoint
{
BeforeOpaque = 0,
AfterOpaque = 1,
BeforeSkybox = 2,
AfterSkybox = 3,
BeforeTransparent = 4,
AfterTransparent = 5
}
private enum RecordedFullscreenPassType
{
ColorScale = 0,
ShaderVector = 1
}
public static bool RecordScene(
this ScriptableRenderContext context)
{
return context != null &&
InternalCalls
.Rendering_ScriptableRenderContext_RecordScene(
context.nativeHandle);
}
public static bool RecordOpaqueScenePhase(
this ScriptableRenderContext context)
{
return RecordScenePhaseInternal(
context,
RecordedScenePhase.Opaque);
}
public static bool RecordSkyboxScenePhase(
this ScriptableRenderContext context)
{
return RecordScenePhaseInternal(
context,
RecordedScenePhase.Skybox);
}
public static bool RecordTransparentScenePhase(
this ScriptableRenderContext context)
{
return RecordScenePhaseInternal(
context,
RecordedScenePhase.Transparent);
}
public static bool RecordBeforeOpaqueInjection(
this ScriptableRenderContext context)
{
return RecordSceneInjectionPointInternal(
context,
RecordedSceneInjectionPoint.BeforeOpaque);
}
public static bool RecordAfterOpaqueInjection(
this ScriptableRenderContext context)
{
return RecordSceneInjectionPointInternal(
context,
RecordedSceneInjectionPoint.AfterOpaque);
}
public static bool RecordBeforeSkyboxInjection(
this ScriptableRenderContext context)
{
return RecordSceneInjectionPointInternal(
context,
RecordedSceneInjectionPoint.BeforeSkybox);
}
public static bool RecordAfterSkyboxInjection(
this ScriptableRenderContext context)
{
return RecordSceneInjectionPointInternal(
context,
RecordedSceneInjectionPoint.AfterSkybox);
}
public static bool RecordBeforeTransparentInjection(
this ScriptableRenderContext context)
{
return RecordSceneInjectionPointInternal(
context,
RecordedSceneInjectionPoint.BeforeTransparent);
}
public static bool RecordAfterTransparentInjection(
this ScriptableRenderContext context)
{
return RecordSceneInjectionPointInternal(
context,
RecordedSceneInjectionPoint.AfterTransparent);
}
public static bool RecordColorScaleFullscreenPass(
this ScriptableRenderContext context,
Vector4 colorScale)
{
return RecordFullscreenPassInternal(
context,
RecordedFullscreenPassType.ColorScale,
string.Empty,
string.Empty,
colorScale);
}
public static bool RecordShaderVectorFullscreenPass(
this ScriptableRenderContext context,
string shaderPath,
Vector4 vectorPayload,
string passName = null)
{
if (string.IsNullOrEmpty(shaderPath))
{
throw new ArgumentException(
"Fullscreen shader path cannot be null or empty.",
nameof(shaderPath));
}
return RecordFullscreenPassInternal(
context,
RecordedFullscreenPassType.ShaderVector,
shaderPath,
passName ?? string.Empty,
vectorPayload);
}
private static bool RecordScenePhaseInternal(
ScriptableRenderContext context,
RecordedScenePhase scenePhase)
{
return context != null &&
InternalCalls
.Rendering_ScriptableRenderContext_RecordScenePhase(
context.nativeHandle,
(int)scenePhase);
}
private static bool RecordSceneInjectionPointInternal(
ScriptableRenderContext context,
RecordedSceneInjectionPoint injectionPoint)
{
return context != null &&
InternalCalls
.Rendering_ScriptableRenderContext_RecordSceneInjectionPoint(
context.nativeHandle,
(int)injectionPoint);
}
private static bool RecordFullscreenPassInternal(
ScriptableRenderContext context,
RecordedFullscreenPassType passType,
string shaderPath,
string passName,
Vector4 vectorPayload)
{
return context != null &&
InternalCalls
.Rendering_ScriptableRenderContext_RecordFullscreenPass(
context.nativeHandle,
(int)passType,
shaderPath,
passName,
ref vectorPayload);
}
}
}

View File

@@ -0,0 +1,30 @@
using XCEngine;
using XCEngine.Rendering;
namespace XCEngine.Rendering.Universal
{
public static class ScriptableRenderPipelineCameraRequestContextExtensions
{
public static bool HasDirectionalShadow(
this ScriptableRenderPipelineCameraRequestContext context)
{
return context != null &&
InternalCalls
.Rendering_ScriptableRenderPipelineCameraRequestContext_GetHasDirectionalShadow(
context.nativeHandle);
}
public static void ClearDirectionalShadow(
this ScriptableRenderPipelineCameraRequestContext context)
{
if (context == null)
{
return;
}
InternalCalls
.Rendering_ScriptableRenderPipelineCameraRequestContext_ClearDirectionalShadow(
context.nativeHandle);
}
}
}

View File

@@ -1163,6 +1163,12 @@ TEST_F(
bool hasPublicContextStageColorData = false;
bool hasPublicCameraRequestContextHasDirectionalShadow = false;
bool hasPublicCameraRequestContextClearDirectionalShadow = false;
bool hasUniversalContextRecordSceneExtension = false;
bool hasUniversalContextRecordOpaqueScenePhaseExtension = false;
bool hasUniversalContextRecordBeforeOpaqueInjectionExtension = false;
bool hasUniversalContextRecordShaderVectorFullscreenPassExtension = false;
bool hasUniversalCameraRequestContextHasDirectionalShadowExtension = false;
bool hasUniversalCameraRequestContextClearDirectionalShadowExtension = false;
bool hasPublicPipelineAssetConfigureCameraFramePlan = false;
bool hasPlanningContextType = false;
bool hasRendererFeatureConfigureCameraFramePlan = false;
@@ -1217,6 +1223,30 @@ TEST_F(
selectionScript,
"HasPublicCameraRequestContextClearDirectionalShadow",
hasPublicCameraRequestContextClearDirectionalShadow));
EXPECT_TRUE(runtime->TryGetFieldValue(
selectionScript,
"HasUniversalContextRecordSceneExtension",
hasUniversalContextRecordSceneExtension));
EXPECT_TRUE(runtime->TryGetFieldValue(
selectionScript,
"HasUniversalContextRecordOpaqueScenePhaseExtension",
hasUniversalContextRecordOpaqueScenePhaseExtension));
EXPECT_TRUE(runtime->TryGetFieldValue(
selectionScript,
"HasUniversalContextRecordBeforeOpaqueInjectionExtension",
hasUniversalContextRecordBeforeOpaqueInjectionExtension));
EXPECT_TRUE(runtime->TryGetFieldValue(
selectionScript,
"HasUniversalContextRecordShaderVectorFullscreenPassExtension",
hasUniversalContextRecordShaderVectorFullscreenPassExtension));
EXPECT_TRUE(runtime->TryGetFieldValue(
selectionScript,
"HasUniversalCameraRequestContextHasDirectionalShadowExtension",
hasUniversalCameraRequestContextHasDirectionalShadowExtension));
EXPECT_TRUE(runtime->TryGetFieldValue(
selectionScript,
"HasUniversalCameraRequestContextClearDirectionalShadowExtension",
hasUniversalCameraRequestContextClearDirectionalShadowExtension));
EXPECT_TRUE(runtime->TryGetFieldValue(
selectionScript,
"HasPublicPipelineAssetConfigureCameraFramePlan",
@@ -1238,18 +1268,24 @@ TEST_F(
"HasRendererCameraRequestContextType",
hasRendererCameraRequestContextType));
EXPECT_TRUE(hasPublicContextRecordScene);
EXPECT_TRUE(hasPublicContextRecordOpaqueScenePhase);
EXPECT_TRUE(hasPublicContextRecordBeforeOpaqueInjection);
EXPECT_TRUE(hasPublicContextRecordShaderVectorFullscreenPass);
EXPECT_FALSE(hasPublicContextRecordScene);
EXPECT_FALSE(hasPublicContextRecordOpaqueScenePhase);
EXPECT_FALSE(hasPublicContextRecordBeforeOpaqueInjection);
EXPECT_FALSE(hasPublicContextRecordShaderVectorFullscreenPass);
EXPECT_FALSE(hasPublicContextCameraData);
EXPECT_FALSE(hasPublicContextLightingData);
EXPECT_FALSE(hasPublicContextShadowData);
EXPECT_FALSE(hasPublicContextEnvironmentData);
EXPECT_FALSE(hasPublicContextFinalColorData);
EXPECT_FALSE(hasPublicContextStageColorData);
EXPECT_TRUE(hasPublicCameraRequestContextHasDirectionalShadow);
EXPECT_TRUE(hasPublicCameraRequestContextClearDirectionalShadow);
EXPECT_FALSE(hasPublicCameraRequestContextHasDirectionalShadow);
EXPECT_FALSE(hasPublicCameraRequestContextClearDirectionalShadow);
EXPECT_TRUE(hasUniversalContextRecordSceneExtension);
EXPECT_TRUE(hasUniversalContextRecordOpaqueScenePhaseExtension);
EXPECT_TRUE(hasUniversalContextRecordBeforeOpaqueInjectionExtension);
EXPECT_TRUE(hasUniversalContextRecordShaderVectorFullscreenPassExtension);
EXPECT_TRUE(hasUniversalCameraRequestContextHasDirectionalShadowExtension);
EXPECT_TRUE(hasUniversalCameraRequestContextClearDirectionalShadowExtension);
EXPECT_FALSE(hasPublicPipelineAssetConfigureCameraFramePlan);
EXPECT_FALSE(hasPlanningContextType);
EXPECT_FALSE(hasRendererFeatureConfigureCameraFramePlan);