Align URP render graph frame data scope
This commit is contained in:
@@ -6,63 +6,123 @@ already made. It is intentionally not a full map of the current implementation.
|
||||
If this file conflicts with the current code, trust the code and update this
|
||||
file in the same change.
|
||||
|
||||
## Long-Term Goal
|
||||
## Next-Stage Goal
|
||||
|
||||
The rendering module is moving toward a Unity SRP / URP style model:
|
||||
The rendering module's next stage is to close the SRP / URP architecture around
|
||||
Unity's public rendering model. The goal is not merely to have similar class
|
||||
names; pipeline authors should be able to reason about XCEngine rendering with
|
||||
the same mental model they use for Unity SRP and URP.
|
||||
|
||||
Unity alignment is the primary design constraint:
|
||||
|
||||
- Treat `GraphicsSettings.renderPipelineAsset`, `RenderPipelineAsset`,
|
||||
`ScriptableRenderPipelineAsset`, `ScriptableRenderPipeline`,
|
||||
`ScriptableRenderContext`, `ScriptableRendererData`,
|
||||
`ScriptableRenderer`, `ScriptableRendererFeature`,
|
||||
`ScriptableRenderPass`, `RenderPassEvent`, `RenderingData`, and
|
||||
`UniversalAdditionalCameraData` as the product-facing spine.
|
||||
- Keep the managed API close to Unity semantics wherever the engine can support
|
||||
it. If XCEngine must diverge, the divergence should be explicit, documented,
|
||||
and caused by a real engine constraint rather than native convenience.
|
||||
- Prefer Unity-style authoring concepts over native implementation concepts.
|
||||
Public C# code should feel like URP pipeline authoring, not like remote
|
||||
control over a native built-in renderer.
|
||||
|
||||
The pipeline selection contract must stay explicit and Unity-like:
|
||||
|
||||
- `GraphicsSettings.renderPipelineAsset == null` selects the built-in pipeline.
|
||||
- `GraphicsSettings.renderPipelineAsset != null` selects the programmable SRP
|
||||
path.
|
||||
- The managed product shape should stay close to:
|
||||
`ScriptableRenderPipelineAsset -> ScriptableRendererData ->
|
||||
ScriptableRenderer -> ScriptableRendererFeature/ScriptableRenderPass`.
|
||||
- `ScriptableRenderPipelineHost` is the native host for managed SRP execution;
|
||||
it must not become a hidden fallback renderer when managed SRP planning or
|
||||
recording fails.
|
||||
- Managed SRP / URP owns renderer selection, stage planning, feature/pass
|
||||
organization, camera policy, and optional stage requests such as shadow,
|
||||
depth, post-process, and final output.
|
||||
- Native rendering owns scene extraction, renderer-list drawing, render graph
|
||||
execution, fullscreen primitive execution, and built-in private draw kernels.
|
||||
- Public managed scene drawing should expose drawing capability, not native
|
||||
built-in injection order. Keep the public surface centered on
|
||||
`DrawRenderers(...)`, `DrawSkybox()`, `DrawOpaqueRenderers()`, and
|
||||
- `GraphicsSettings.renderPipelineAsset != null` selects the managed SRP path.
|
||||
- Runtime startup must not silently assign a project default SRP asset. A
|
||||
project default can be loaded by project/editor policy, but rendering mode
|
||||
changes must remain visible through `GraphicsSettings.renderPipelineAsset`.
|
||||
- If a managed SRP asset cannot create a valid pipeline, recorder, or backend
|
||||
bridge, creation should fail visibly and let the top-level factory choose the
|
||||
built-in pipeline. `ScriptableRenderPipelineHost` must not impersonate a
|
||||
successful managed SRP by drawing through a hidden fallback renderer.
|
||||
|
||||
The URP object model should be the center of future work:
|
||||
|
||||
- `ScriptableRenderPipelineAsset` owns pipeline defaults, renderer-data lists,
|
||||
default renderer selection, camera policy, final-color policy, shadow policy,
|
||||
and managed pipeline lifetime.
|
||||
- `ScriptableRendererData` is the serialized renderer configuration. It owns
|
||||
renderer feature lists, default feature creation, runtime invalidation, and
|
||||
renderer instance rebuilds.
|
||||
- `ScriptableRenderer` owns per-camera pass queue construction. It should
|
||||
enqueue passes from renderer features, sort by `RenderPassEvent`, partition
|
||||
work into URP-like renderer blocks, and record only the stage requested by
|
||||
the native frame plan.
|
||||
- `ScriptableRendererFeature` owns reusable renderer extensions. Features
|
||||
should configure camera/frame policy and enqueue `ScriptableRenderPass`
|
||||
instances without reaching into native private pass order.
|
||||
- `ScriptableRenderPass` owns pass lifecycle and recording. The long-term pass
|
||||
surface should be `RecordRenderGraph(...)`, renderer-list drawing, public
|
||||
texture/resource declarations, and explicit pass data.
|
||||
|
||||
The native/managed boundary should remain strict:
|
||||
|
||||
- Managed SRP / URP owns renderer selection, feature/pass organization,
|
||||
optional stage planning, camera clear policy, shadow/depth requests,
|
||||
post-process and final-output policy, and public frame data exposed to user
|
||||
passes.
|
||||
- Native rendering owns scene extraction, culling and renderer-list
|
||||
realization, render graph compilation/execution, RHI resource lifetime,
|
||||
fullscreen primitive execution, and private built-in draw kernels.
|
||||
- Managed scene drawing should expose draw capabilities, not native injection
|
||||
points. Keep the public scene surface centered on `DrawRenderers(...)`,
|
||||
`DrawSkybox()`, `DrawOpaqueRenderers()`, and
|
||||
`DrawTransparentRenderers()`.
|
||||
- Do not reintroduce implicit project-default SRP activation, hidden
|
||||
`ScriptableRenderPipelineHost` fallback, or public managed wrappers for
|
||||
built-in private scene injection points.
|
||||
- Future URP alignment should add managed-side renderer/pass/render-graph
|
||||
capability. It should not reopen native private fallback paths just to make a
|
||||
feature appear to work.
|
||||
- Main-scene, shadow, and depth work should be renderer-driven. Managed passes
|
||||
may request those stages and call public draw APIs, while native continues to
|
||||
execute renderer lists and low-level draw kernels.
|
||||
|
||||
Managed RenderGraph is the key capability gap for the next stage:
|
||||
|
||||
- Grow the current fullscreen-pass bridge into a URP-style render-graph
|
||||
authoring surface with explicit texture creation/imports, read/write
|
||||
declarations, pass data, frame-data/context-container access, and scheduled
|
||||
renderer-list drawing.
|
||||
- Post-process and final-output should become ordinary URP feature/pass work
|
||||
where possible. Native fullscreen kernels may remain execution primitives,
|
||||
but they should not appear as feature-specific public shortcuts.
|
||||
- Prefer data-driven frame state (`CameraData`, `LightingData`, `ShadowData`,
|
||||
`EnvironmentData`, `FinalColorData`, `StageColorData`) over direct scene
|
||||
object inspection during pass recording.
|
||||
|
||||
Tests should protect Unity-facing semantics while the architecture closes:
|
||||
|
||||
- Prioritize contract tests for null-vs-SRP selection, managed SRP creation
|
||||
failure, no hidden fallback rendering, renderer-data/default-renderer
|
||||
selection, camera renderer override, feature/pass enqueue order, stage
|
||||
planning, render-graph recording, and forbidden public API surface.
|
||||
- Add URP integration scenes after the API and responsibility boundaries are
|
||||
stable: default Universal renderer, `RenderObjectsRendererFeature`,
|
||||
post-process/final-output, shadow/depth, camera override, and camera stack.
|
||||
- Avoid overfitting tests to temporary native bridge details. Tests should lock
|
||||
Unity SRP / URP semantics first, implementation mechanics second.
|
||||
|
||||
Guardrails:
|
||||
|
||||
- Do not reintroduce public managed wrappers for native private scene injection
|
||||
points.
|
||||
- Do not make `RenderPassEvent` or renderer blocks a thin alias for native
|
||||
built-in pass order. They should describe URP scheduling semantics.
|
||||
- Do not add managed APIs that only work by reaching into one built-in native
|
||||
renderer path. Add a public renderer-list, render-graph, or pass abstraction
|
||||
instead.
|
||||
- A managed SRP stage that declares support and then fails to record should
|
||||
fail visibly. It should not silently continue by drawing the default native
|
||||
scene.
|
||||
|
||||
## Past Execution
|
||||
|
||||
- Established the top-level selection rule: explicit null means built-in,
|
||||
explicit managed asset means SRP, and runtime startup must not silently assign
|
||||
`ProjectDefaultRenderPipelineAsset`.
|
||||
- Removed public managed native scene injection APIs such as
|
||||
`ScriptableRenderContext.RecordSceneInjectionPoint(...)`,
|
||||
`RecordBefore/After*Injection(...)`, and
|
||||
`RecordOpaque/Skybox/TransparentScenePhase(...)`.
|
||||
- Kept `RecordScene()` / `RecordScenePhase(...)` internal and made the public
|
||||
managed scene surface express draw operations through `DrawRenderers(...)`,
|
||||
`DrawSkybox()`, `DrawOpaqueRenderers()`, and
|
||||
`DrawTransparentRenderers()`.
|
||||
- Moved renderer-backed SRP stage ownership into `ScriptableRenderer`,
|
||||
`ScriptableRendererFeature`, and `ScriptableRenderPass`; renderer-backed
|
||||
assets clear native optional stage defaults before managed renderer/features
|
||||
explicitly request the stages they need.
|
||||
- Removed `CameraRenderRequestContext.hasDirectionalShadow` and
|
||||
`ClearDirectionalShadow()` from the ScriptCore public surface. Core keeps only
|
||||
internal bridge access, while URP policy belongs in renderer asset, renderer
|
||||
data, and feature code.
|
||||
- Reordered managed camera request policy so managed / URP first observes the
|
||||
native directional-shadow baseline, then the final managed policy recomputes
|
||||
or clears the request without native planning adding it back afterward.
|
||||
- Prevented URP default renderer feature factories from auto-injecting built-in
|
||||
private feature wrappers.
|
||||
- Tightened SRP creation failure semantics:
|
||||
`ManagedScriptableRenderPipelineAsset::CreatePipeline()` fails when managed
|
||||
runtime, backend asset, or stage recorder is unavailable; factory fallback
|
||||
then returns the built-in pipeline instead of letting
|
||||
`ScriptableRenderPipelineHost` impersonate a successful managed SRP.
|
||||
- Made the public managed
|
||||
`ScriptableRenderPass.RecordRenderGraph(RenderGraph, ContextContainer)` path
|
||||
receive real URP frame data. `RenderingData`, `CameraData`, `LightingData`,
|
||||
`ShadowData`, `EnvironmentData`, `FinalColorData`, and `StageColorData` are
|
||||
now `ContextItem`s populated before public render-graph recording.
|
||||
- Moved managed public render-graph frame data ownership from individual
|
||||
`ScriptableRenderPass` calls to the `ScriptableRenderer` stage recording
|
||||
scope. Public `ContextContainer` state is now shared across renderer passes
|
||||
for the same stage, matching URP's frame-data mental model instead of
|
||||
pass-local scratch data.
|
||||
|
||||
@@ -1173,6 +1173,297 @@ namespace Gameplay
|
||||
}
|
||||
}
|
||||
|
||||
internal static class PublicRenderGraphFrameDataProbeState
|
||||
{
|
||||
public static bool HasRenderingData;
|
||||
public static bool HasCameraData;
|
||||
public static bool HasLightingData;
|
||||
public static bool HasShadowData;
|
||||
public static bool HasEnvironmentData;
|
||||
public static bool HasFinalColorData;
|
||||
public static bool HasStageColorData;
|
||||
public static bool RenderingDataMatchesItems;
|
||||
public static int ObservedStage;
|
||||
public static int ObservedRendererIndex;
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
HasRenderingData = false;
|
||||
HasCameraData = false;
|
||||
HasLightingData = false;
|
||||
HasShadowData = false;
|
||||
HasEnvironmentData = false;
|
||||
HasFinalColorData = false;
|
||||
HasStageColorData = false;
|
||||
RenderingDataMatchesItems = false;
|
||||
ObservedStage = -1;
|
||||
ObservedRendererIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class PublicRenderGraphFrameDataProbePass
|
||||
: ScriptableRenderPass
|
||||
{
|
||||
public PublicRenderGraphFrameDataProbePass()
|
||||
{
|
||||
renderPassEvent = RenderPassEvent.RenderOpaques;
|
||||
}
|
||||
|
||||
public override void RecordRenderGraph(
|
||||
RenderGraph renderGraph,
|
||||
ContextContainer frameData)
|
||||
{
|
||||
PublicRenderGraphFrameDataProbeState.HasRenderingData =
|
||||
frameData != null &&
|
||||
frameData.Contains<RenderingData>();
|
||||
PublicRenderGraphFrameDataProbeState.HasCameraData =
|
||||
frameData != null &&
|
||||
frameData.Contains<CameraData>();
|
||||
PublicRenderGraphFrameDataProbeState.HasLightingData =
|
||||
frameData != null &&
|
||||
frameData.Contains<LightingData>();
|
||||
PublicRenderGraphFrameDataProbeState.HasShadowData =
|
||||
frameData != null &&
|
||||
frameData.Contains<ShadowData>();
|
||||
PublicRenderGraphFrameDataProbeState.HasEnvironmentData =
|
||||
frameData != null &&
|
||||
frameData.Contains<EnvironmentData>();
|
||||
PublicRenderGraphFrameDataProbeState.HasFinalColorData =
|
||||
frameData != null &&
|
||||
frameData.Contains<FinalColorData>();
|
||||
PublicRenderGraphFrameDataProbeState.HasStageColorData =
|
||||
frameData != null &&
|
||||
frameData.Contains<StageColorData>();
|
||||
|
||||
if (!PublicRenderGraphFrameDataProbeState.HasRenderingData)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RenderingData renderingData =
|
||||
frameData.Get<RenderingData>();
|
||||
PublicRenderGraphFrameDataProbeState.ObservedStage =
|
||||
(int)renderingData.stage;
|
||||
PublicRenderGraphFrameDataProbeState.ObservedRendererIndex =
|
||||
renderingData.rendererIndex;
|
||||
PublicRenderGraphFrameDataProbeState
|
||||
.RenderingDataMatchesItems =
|
||||
object.ReferenceEquals(
|
||||
renderingData.cameraData,
|
||||
frameData.Get<CameraData>()) &&
|
||||
object.ReferenceEquals(
|
||||
renderingData.lightingData,
|
||||
frameData.Get<LightingData>()) &&
|
||||
object.ReferenceEquals(
|
||||
renderingData.shadowData,
|
||||
frameData.Get<ShadowData>()) &&
|
||||
object.ReferenceEquals(
|
||||
renderingData.environmentData,
|
||||
frameData.Get<EnvironmentData>()) &&
|
||||
object.ReferenceEquals(
|
||||
renderingData.finalColorData,
|
||||
frameData.Get<FinalColorData>()) &&
|
||||
object.ReferenceEquals(
|
||||
renderingData.stageColorData,
|
||||
frameData.Get<StageColorData>());
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class PublicRenderGraphFrameDataProbeFeature
|
||||
: ScriptableRendererFeature
|
||||
{
|
||||
private readonly PublicRenderGraphFrameDataProbePass m_pass =
|
||||
new PublicRenderGraphFrameDataProbePass();
|
||||
|
||||
public override void AddRenderPasses(
|
||||
ScriptableRenderer renderer,
|
||||
RenderingData renderingData)
|
||||
{
|
||||
if (renderer == null ||
|
||||
renderingData == null ||
|
||||
!renderingData.isMainSceneStage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
renderer.EnqueuePass(m_pass);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class PublicRenderGraphFrameDataProbeRenderer
|
||||
: ScriptableRenderer
|
||||
{
|
||||
public PublicRenderGraphFrameDataProbeRenderer()
|
||||
{
|
||||
AddFeature(new PublicRenderGraphFrameDataProbeFeature());
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class PublicRenderGraphSharedFrameDataProbeItem
|
||||
: ContextItem
|
||||
{
|
||||
public int Value;
|
||||
public int WriterOrder;
|
||||
public RenderingData RenderingData;
|
||||
|
||||
public PublicRenderGraphSharedFrameDataProbeItem()
|
||||
{
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
Value = 0;
|
||||
WriterOrder = 0;
|
||||
RenderingData = null;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class PublicRenderGraphSharedFrameDataProbeState
|
||||
{
|
||||
public static bool WriterVisited;
|
||||
public static bool ReaderVisited;
|
||||
public static bool ReaderObservedWriterItem;
|
||||
public static bool ReaderObservedSameFrameData;
|
||||
public static bool ReaderObservedSameRenderingData;
|
||||
public static int ReaderObservedValue;
|
||||
public static int ReaderOrder;
|
||||
public static ContextContainer WriterFrameData;
|
||||
public static int NextOrder;
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
WriterVisited = false;
|
||||
ReaderVisited = false;
|
||||
ReaderObservedWriterItem = false;
|
||||
ReaderObservedSameFrameData = false;
|
||||
ReaderObservedSameRenderingData = false;
|
||||
ReaderObservedValue = 0;
|
||||
ReaderOrder = 0;
|
||||
WriterFrameData = null;
|
||||
NextOrder = 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class PublicRenderGraphSharedFrameDataWriterPass
|
||||
: ScriptableRenderPass
|
||||
{
|
||||
public PublicRenderGraphSharedFrameDataWriterPass()
|
||||
{
|
||||
renderPassEvent = RenderPassEvent.RenderOpaques;
|
||||
}
|
||||
|
||||
public override void RecordRenderGraph(
|
||||
RenderGraph renderGraph,
|
||||
ContextContainer frameData)
|
||||
{
|
||||
PublicRenderGraphSharedFrameDataProbeState.WriterVisited =
|
||||
frameData != null;
|
||||
PublicRenderGraphSharedFrameDataProbeState.WriterFrameData =
|
||||
frameData;
|
||||
if (frameData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PublicRenderGraphSharedFrameDataProbeItem item =
|
||||
frameData
|
||||
.GetOrCreate<PublicRenderGraphSharedFrameDataProbeItem>();
|
||||
item.Value = 73;
|
||||
item.WriterOrder =
|
||||
++PublicRenderGraphSharedFrameDataProbeState.NextOrder;
|
||||
item.RenderingData =
|
||||
frameData.Contains<RenderingData>()
|
||||
? frameData.Get<RenderingData>()
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class PublicRenderGraphSharedFrameDataReaderPass
|
||||
: ScriptableRenderPass
|
||||
{
|
||||
public PublicRenderGraphSharedFrameDataReaderPass()
|
||||
{
|
||||
renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
|
||||
}
|
||||
|
||||
public override void RecordRenderGraph(
|
||||
RenderGraph renderGraph,
|
||||
ContextContainer frameData)
|
||||
{
|
||||
PublicRenderGraphSharedFrameDataProbeState.ReaderVisited =
|
||||
frameData != null;
|
||||
PublicRenderGraphSharedFrameDataProbeState.ReaderOrder =
|
||||
++PublicRenderGraphSharedFrameDataProbeState.NextOrder;
|
||||
PublicRenderGraphSharedFrameDataProbeState
|
||||
.ReaderObservedSameFrameData =
|
||||
object.ReferenceEquals(
|
||||
PublicRenderGraphSharedFrameDataProbeState
|
||||
.WriterFrameData,
|
||||
frameData);
|
||||
|
||||
if (frameData == null ||
|
||||
!frameData
|
||||
.Contains<PublicRenderGraphSharedFrameDataProbeItem>())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PublicRenderGraphSharedFrameDataProbeItem item =
|
||||
frameData
|
||||
.Get<PublicRenderGraphSharedFrameDataProbeItem>();
|
||||
PublicRenderGraphSharedFrameDataProbeState
|
||||
.ReaderObservedWriterItem =
|
||||
item.WriterOrder > 0 &&
|
||||
item.WriterOrder <
|
||||
PublicRenderGraphSharedFrameDataProbeState.ReaderOrder;
|
||||
PublicRenderGraphSharedFrameDataProbeState
|
||||
.ReaderObservedValue =
|
||||
item.Value;
|
||||
PublicRenderGraphSharedFrameDataProbeState
|
||||
.ReaderObservedSameRenderingData =
|
||||
frameData.Contains<RenderingData>() &&
|
||||
object.ReferenceEquals(
|
||||
item.RenderingData,
|
||||
frameData.Get<RenderingData>());
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class PublicRenderGraphSharedFrameDataProbeFeature
|
||||
: ScriptableRendererFeature
|
||||
{
|
||||
private readonly PublicRenderGraphSharedFrameDataWriterPass
|
||||
m_writerPass =
|
||||
new PublicRenderGraphSharedFrameDataWriterPass();
|
||||
private readonly PublicRenderGraphSharedFrameDataReaderPass
|
||||
m_readerPass =
|
||||
new PublicRenderGraphSharedFrameDataReaderPass();
|
||||
|
||||
public override void AddRenderPasses(
|
||||
ScriptableRenderer renderer,
|
||||
RenderingData renderingData)
|
||||
{
|
||||
if (renderer == null ||
|
||||
renderingData == null ||
|
||||
!renderingData.isMainSceneStage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
renderer.EnqueuePass(m_writerPass);
|
||||
renderer.EnqueuePass(m_readerPass);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class PublicRenderGraphSharedFrameDataProbeRenderer
|
||||
: ScriptableRenderer
|
||||
{
|
||||
public PublicRenderGraphSharedFrameDataProbeRenderer()
|
||||
{
|
||||
AddFeature(
|
||||
new PublicRenderGraphSharedFrameDataProbeFeature());
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class ProbeRendererData
|
||||
: UniversalRendererData
|
||||
{
|
||||
@@ -1532,6 +1823,24 @@ namespace Gameplay
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class PublicRenderGraphFrameDataProbeRendererData
|
||||
: ProbeRendererData
|
||||
{
|
||||
protected override ScriptableRenderer CreateProbeRenderer()
|
||||
{
|
||||
return new PublicRenderGraphFrameDataProbeRenderer();
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class PublicRenderGraphSharedFrameDataProbeRendererData
|
||||
: ProbeRendererData
|
||||
{
|
||||
protected override ScriptableRenderer CreateProbeRenderer()
|
||||
{
|
||||
return new PublicRenderGraphSharedFrameDataProbeRenderer();
|
||||
}
|
||||
}
|
||||
|
||||
internal static class ManagedLifecycleProbeState
|
||||
{
|
||||
public static int CreatePipelineCallCount;
|
||||
@@ -2230,6 +2539,32 @@ namespace Gameplay
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ManagedPublicRenderGraphFrameDataProbeAsset
|
||||
: UniversalRenderPipelineAsset
|
||||
{
|
||||
public ManagedPublicRenderGraphFrameDataProbeAsset()
|
||||
{
|
||||
rendererDataList =
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<PublicRenderGraphFrameDataProbeRendererData>());
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ManagedPublicRenderGraphSharedFrameDataProbeAsset
|
||||
: UniversalRenderPipelineAsset
|
||||
{
|
||||
public ManagedPublicRenderGraphSharedFrameDataProbeAsset()
|
||||
{
|
||||
rendererDataList =
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<PublicRenderGraphSharedFrameDataProbeRendererData>());
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ManagedMainSceneRasterPassProbePipeline
|
||||
: ScriptableRenderPipeline
|
||||
{
|
||||
@@ -3372,5 +3707,106 @@ namespace Gameplay
|
||||
StageColorObservationPass.FinalOutputRecordCallCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ManagedPublicRenderGraphFrameDataRuntimeSelectionProbe
|
||||
: MonoBehaviour
|
||||
{
|
||||
public bool ObservedHasRenderingData;
|
||||
public bool ObservedHasCameraData;
|
||||
public bool ObservedHasLightingData;
|
||||
public bool ObservedHasShadowData;
|
||||
public bool ObservedHasEnvironmentData;
|
||||
public bool ObservedHasFinalColorData;
|
||||
public bool ObservedHasStageColorData;
|
||||
public bool ObservedRenderingDataMatchesItems;
|
||||
public int ObservedStage;
|
||||
public int ObservedRendererIndex;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
PublicRenderGraphFrameDataProbeState.Reset();
|
||||
GraphicsSettings.renderPipelineAsset =
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedPublicRenderGraphFrameDataProbeAsset>();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
ObservedHasRenderingData =
|
||||
PublicRenderGraphFrameDataProbeState
|
||||
.HasRenderingData;
|
||||
ObservedHasCameraData =
|
||||
PublicRenderGraphFrameDataProbeState
|
||||
.HasCameraData;
|
||||
ObservedHasLightingData =
|
||||
PublicRenderGraphFrameDataProbeState
|
||||
.HasLightingData;
|
||||
ObservedHasShadowData =
|
||||
PublicRenderGraphFrameDataProbeState
|
||||
.HasShadowData;
|
||||
ObservedHasEnvironmentData =
|
||||
PublicRenderGraphFrameDataProbeState
|
||||
.HasEnvironmentData;
|
||||
ObservedHasFinalColorData =
|
||||
PublicRenderGraphFrameDataProbeState
|
||||
.HasFinalColorData;
|
||||
ObservedHasStageColorData =
|
||||
PublicRenderGraphFrameDataProbeState
|
||||
.HasStageColorData;
|
||||
ObservedRenderingDataMatchesItems =
|
||||
PublicRenderGraphFrameDataProbeState
|
||||
.RenderingDataMatchesItems;
|
||||
ObservedStage =
|
||||
PublicRenderGraphFrameDataProbeState
|
||||
.ObservedStage;
|
||||
ObservedRendererIndex =
|
||||
PublicRenderGraphFrameDataProbeState
|
||||
.ObservedRendererIndex;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ManagedPublicRenderGraphSharedFrameDataRuntimeSelectionProbe
|
||||
: MonoBehaviour
|
||||
{
|
||||
public bool ObservedWriterVisited;
|
||||
public bool ObservedReaderVisited;
|
||||
public bool ObservedReaderSawWriterItem;
|
||||
public bool ObservedSameFrameData;
|
||||
public bool ObservedSameRenderingData;
|
||||
public int ObservedValue;
|
||||
public int ObservedReaderOrder;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
PublicRenderGraphSharedFrameDataProbeState.Reset();
|
||||
GraphicsSettings.renderPipelineAsset =
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedPublicRenderGraphSharedFrameDataProbeAsset>();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
ObservedWriterVisited =
|
||||
PublicRenderGraphSharedFrameDataProbeState
|
||||
.WriterVisited;
|
||||
ObservedReaderVisited =
|
||||
PublicRenderGraphSharedFrameDataProbeState
|
||||
.ReaderVisited;
|
||||
ObservedReaderSawWriterItem =
|
||||
PublicRenderGraphSharedFrameDataProbeState
|
||||
.ReaderObservedWriterItem;
|
||||
ObservedSameFrameData =
|
||||
PublicRenderGraphSharedFrameDataProbeState
|
||||
.ReaderObservedSameFrameData;
|
||||
ObservedSameRenderingData =
|
||||
PublicRenderGraphSharedFrameDataProbeState
|
||||
.ReaderObservedSameRenderingData;
|
||||
ObservedValue =
|
||||
PublicRenderGraphSharedFrameDataProbeState
|
||||
.ReaderObservedValue;
|
||||
ObservedReaderOrder =
|
||||
PublicRenderGraphSharedFrameDataProbeState
|
||||
.ReaderOrder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
public sealed class CameraData
|
||||
public sealed class CameraData : ContextItem
|
||||
{
|
||||
internal static readonly CameraData Default =
|
||||
new CameraData(
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
public sealed class EnvironmentData
|
||||
public sealed class EnvironmentData : ContextItem
|
||||
{
|
||||
internal static readonly EnvironmentData Default =
|
||||
new EnvironmentData(
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
public sealed class FinalColorData
|
||||
public sealed class FinalColorData : ContextItem
|
||||
{
|
||||
internal static readonly FinalColorData Default =
|
||||
new FinalColorData(
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
public sealed class LightingData
|
||||
public sealed class LightingData : ContextItem
|
||||
{
|
||||
internal static readonly LightingData Default =
|
||||
new LightingData(
|
||||
|
||||
@@ -3,7 +3,7 @@ using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
public sealed class RenderingData
|
||||
public sealed class RenderingData : ContextItem
|
||||
{
|
||||
internal RenderingData(CameraFrameStage stage)
|
||||
: this(
|
||||
|
||||
@@ -73,7 +73,9 @@ namespace XCEngine.Rendering.Universal
|
||||
|
||||
internal bool Record(
|
||||
ScriptableRenderContext context,
|
||||
RenderingData renderingData)
|
||||
RenderingData renderingData,
|
||||
RenderGraph renderGraph,
|
||||
ContextContainer frameData)
|
||||
{
|
||||
RenderingData passRenderingData =
|
||||
renderingData;
|
||||
@@ -85,13 +87,12 @@ namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
if (HasPublicRenderGraphOverride())
|
||||
{
|
||||
using (ContextContainer frameData =
|
||||
new ContextContainer())
|
||||
{
|
||||
RecordRenderGraph(
|
||||
new RenderGraph(context),
|
||||
frameData);
|
||||
}
|
||||
PopulateRenderGraphFrameData(
|
||||
frameData,
|
||||
passRenderingData);
|
||||
RecordRenderGraph(
|
||||
renderGraph,
|
||||
frameData);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -441,6 +442,40 @@ namespace XCEngine.Rendering.Universal
|
||||
typeof(ScriptableRenderPass);
|
||||
}
|
||||
|
||||
internal static ContextContainer BuildRenderGraphFrameData(
|
||||
RenderingData renderingData)
|
||||
{
|
||||
ContextContainer frameData =
|
||||
new ContextContainer();
|
||||
PopulateRenderGraphFrameData(
|
||||
frameData,
|
||||
renderingData);
|
||||
return frameData;
|
||||
}
|
||||
|
||||
internal static void PopulateRenderGraphFrameData(
|
||||
ContextContainer frameData,
|
||||
RenderingData renderingData)
|
||||
{
|
||||
if (frameData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (renderingData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
frameData.Set(renderingData);
|
||||
frameData.Set(renderingData.cameraData);
|
||||
frameData.Set(renderingData.lightingData);
|
||||
frameData.Set(renderingData.shadowData);
|
||||
frameData.Set(renderingData.environmentData);
|
||||
frameData.Set(renderingData.finalColorData);
|
||||
frameData.Set(renderingData.stageColorData);
|
||||
}
|
||||
|
||||
private static bool TryResolveDefaultFullscreenTargets(
|
||||
ScriptableRenderContext context,
|
||||
out RenderGraphTextureHandle sourceColor,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
using XCEngine.Rendering.RenderGraphModule;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
@@ -170,8 +171,17 @@ namespace XCEngine.Rendering.Universal
|
||||
RenderingData renderingData =
|
||||
context.renderingData;
|
||||
BuildPassQueue(renderingData);
|
||||
bool recorded =
|
||||
RecordRendererStage(context);
|
||||
bool recorded;
|
||||
using (ContextContainer frameData =
|
||||
ScriptableRenderPass.BuildRenderGraphFrameData(
|
||||
renderingData))
|
||||
{
|
||||
recorded =
|
||||
RecordRendererStage(
|
||||
context,
|
||||
new RenderGraph(context.renderContext),
|
||||
frameData);
|
||||
}
|
||||
if (recorded)
|
||||
{
|
||||
FinishCameraStackRendering();
|
||||
@@ -299,7 +309,9 @@ namespace XCEngine.Rendering.Universal
|
||||
}
|
||||
|
||||
protected virtual bool RecordRendererStage(
|
||||
RendererRecordingContext context)
|
||||
RendererRecordingContext context,
|
||||
RenderGraph renderGraph,
|
||||
ContextContainer frameData)
|
||||
{
|
||||
if (context == null ||
|
||||
context.renderContext == null)
|
||||
@@ -314,38 +326,52 @@ namespace XCEngine.Rendering.Universal
|
||||
return RecordRendererBlock(
|
||||
RendererBlock.ShadowCaster,
|
||||
context,
|
||||
renderGraph,
|
||||
frameData,
|
||||
ref recordedAnyPass) &&
|
||||
recordedAnyPass;
|
||||
case CameraFrameStage.DepthOnly:
|
||||
return RecordRendererBlock(
|
||||
RendererBlock.DepthPrepass,
|
||||
context,
|
||||
renderGraph,
|
||||
frameData,
|
||||
ref recordedAnyPass) &&
|
||||
recordedAnyPass;
|
||||
case CameraFrameStage.MainScene:
|
||||
return RecordRendererBlock(
|
||||
RendererBlock.MainOpaque,
|
||||
context,
|
||||
renderGraph,
|
||||
frameData,
|
||||
ref recordedAnyPass) &&
|
||||
RecordRendererBlock(
|
||||
RendererBlock.MainSkybox,
|
||||
context,
|
||||
renderGraph,
|
||||
frameData,
|
||||
ref recordedAnyPass) &&
|
||||
RecordRendererBlock(
|
||||
RendererBlock.MainTransparent,
|
||||
context,
|
||||
renderGraph,
|
||||
frameData,
|
||||
ref recordedAnyPass) &&
|
||||
recordedAnyPass;
|
||||
case CameraFrameStage.PostProcess:
|
||||
return RecordRendererBlock(
|
||||
RendererBlock.PostProcess,
|
||||
context,
|
||||
renderGraph,
|
||||
frameData,
|
||||
ref recordedAnyPass) &&
|
||||
recordedAnyPass;
|
||||
case CameraFrameStage.FinalOutput:
|
||||
return RecordRendererBlock(
|
||||
RendererBlock.FinalOutput,
|
||||
context,
|
||||
renderGraph,
|
||||
frameData,
|
||||
ref recordedAnyPass) &&
|
||||
recordedAnyPass;
|
||||
default:
|
||||
@@ -356,6 +382,8 @@ namespace XCEngine.Rendering.Universal
|
||||
private bool RecordRendererBlock(
|
||||
RendererBlock block,
|
||||
RendererRecordingContext context,
|
||||
RenderGraph renderGraph,
|
||||
ContextContainer frameData,
|
||||
ref bool recordedAnyPass)
|
||||
{
|
||||
if (context == null ||
|
||||
@@ -388,7 +416,9 @@ namespace XCEngine.Rendering.Universal
|
||||
|
||||
if (!renderPass.Record(
|
||||
context.renderContext,
|
||||
context.renderingData))
|
||||
context.renderingData,
|
||||
renderGraph,
|
||||
frameData))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
public sealed class ShadowData
|
||||
public sealed class ShadowData : ContextItem
|
||||
{
|
||||
internal static readonly ShadowData Default =
|
||||
new ShadowData(
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
public sealed class StageColorData
|
||||
public sealed class StageColorData : ContextItem
|
||||
{
|
||||
internal static readonly StageColorData Default =
|
||||
new StageColorData(
|
||||
|
||||
@@ -56,6 +56,20 @@ namespace XCEngine.Rendering
|
||||
return Create<T>();
|
||||
}
|
||||
|
||||
internal void Set<T>(
|
||||
T item)
|
||||
where T : ContextItem
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (item == null)
|
||||
{
|
||||
m_items.Remove(typeof(T));
|
||||
return;
|
||||
}
|
||||
|
||||
m_items[typeof(T)] = item;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (m_disposed)
|
||||
|
||||
@@ -758,6 +758,271 @@ TEST_F(
|
||||
host->GetStageRecorder()->Shutdown();
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
MonoScriptRuntimeTest,
|
||||
PublicRecordRenderGraphReceivesUniversalFrameDataContextItems) {
|
||||
Scene* runtimeScene =
|
||||
CreateScene("ManagedPublicRenderGraphFrameDataScene");
|
||||
GameObject* selectionObject =
|
||||
runtimeScene->CreateGameObject(
|
||||
"ManagedPublicRenderGraphFrameDataSelection");
|
||||
ScriptComponent* selectionScript =
|
||||
AddScript(
|
||||
selectionObject,
|
||||
"Gameplay",
|
||||
"ManagedPublicRenderGraphFrameDataRuntimeSelectionProbe");
|
||||
ASSERT_NE(selectionScript, nullptr);
|
||||
|
||||
engine->OnRuntimeStart(runtimeScene);
|
||||
engine->OnUpdate(0.016f);
|
||||
|
||||
XCEngine::Rendering::CameraRenderer renderer;
|
||||
const auto* asset =
|
||||
dynamic_cast<
|
||||
const XCEngine::Rendering::Pipelines::ManagedScriptableRenderPipelineAsset*>(
|
||||
renderer.GetPipelineAsset());
|
||||
ASSERT_NE(asset, nullptr);
|
||||
EXPECT_EQ(asset->GetDescriptor().assemblyName, "GameScripts");
|
||||
EXPECT_EQ(asset->GetDescriptor().namespaceName, "Gameplay");
|
||||
EXPECT_EQ(
|
||||
asset->GetDescriptor().className,
|
||||
"ManagedPublicRenderGraphFrameDataProbeAsset");
|
||||
|
||||
auto* host =
|
||||
dynamic_cast<XCEngine::Rendering::Pipelines::ScriptableRenderPipelineHost*>(
|
||||
renderer.GetPipeline());
|
||||
ASSERT_NE(host, nullptr);
|
||||
ASSERT_NE(host->GetStageRecorder(), nullptr);
|
||||
ASSERT_TRUE(
|
||||
host->GetStageRecorder()->Initialize(
|
||||
XCEngine::Rendering::RenderContext{}))
|
||||
<< runtime->GetLastError();
|
||||
ASSERT_TRUE(
|
||||
host->SupportsStageRenderGraph(
|
||||
XCEngine::Rendering::RenderPipelineStageSupportContext{
|
||||
XCEngine::Rendering::CameraFrameStage::MainScene,
|
||||
0 }))
|
||||
<< runtime->GetLastError();
|
||||
|
||||
XCEngine::Rendering::RenderGraph graph;
|
||||
XCEngine::Rendering::RenderGraphBuilder graphBuilder(graph);
|
||||
XCEngine::Rendering::RenderGraphTextureDesc colorDesc = {};
|
||||
colorDesc.width = 16u;
|
||||
colorDesc.height = 16u;
|
||||
colorDesc.format =
|
||||
static_cast<XCEngine::Core::uint32>(
|
||||
XCEngine::RHI::Format::R8G8B8A8_UNorm);
|
||||
XCEngine::Rendering::RenderGraphTextureDesc depthDesc = colorDesc;
|
||||
depthDesc.format =
|
||||
static_cast<XCEngine::Core::uint32>(
|
||||
XCEngine::RHI::Format::D32_Float);
|
||||
const XCEngine::Rendering::RenderGraphTextureHandle colorTarget =
|
||||
graphBuilder.CreateTransientTexture(
|
||||
"ManagedPublicFrameDataColor",
|
||||
colorDesc);
|
||||
const XCEngine::Rendering::RenderGraphTextureHandle depthTarget =
|
||||
graphBuilder.CreateTransientTexture(
|
||||
"ManagedPublicFrameDataDepth",
|
||||
depthDesc);
|
||||
|
||||
const XCEngine::Rendering::RenderSceneData sceneData = {};
|
||||
const XCEngine::Rendering::RenderSurface surface(16u, 16u);
|
||||
bool executionSucceeded = true;
|
||||
XCEngine::Rendering::RenderGraphBlackboard blackboard = {};
|
||||
const XCEngine::Rendering::RenderPipelineStageRenderGraphContext graphContext = {
|
||||
graphBuilder,
|
||||
"ManagedPublicFrameData",
|
||||
XCEngine::Rendering::CameraFrameStage::MainScene,
|
||||
{},
|
||||
sceneData,
|
||||
surface,
|
||||
nullptr,
|
||||
nullptr,
|
||||
XCEngine::RHI::ResourceStates::Common,
|
||||
{},
|
||||
{ colorTarget },
|
||||
depthTarget,
|
||||
{},
|
||||
&executionSucceeded,
|
||||
&blackboard,
|
||||
XCEngine::Rendering::CameraFrameColorSource::ExplicitSurface,
|
||||
false,
|
||||
{},
|
||||
0
|
||||
};
|
||||
|
||||
EXPECT_TRUE(
|
||||
host->GetStageRecorder()->RecordStageRenderGraph(graphContext))
|
||||
<< runtime->GetLastError();
|
||||
engine->OnUpdate(0.016f);
|
||||
|
||||
const auto expectBoolField =
|
||||
[&](const char* fieldName) {
|
||||
bool value = false;
|
||||
EXPECT_TRUE(runtime->TryGetFieldValue(
|
||||
selectionScript,
|
||||
fieldName,
|
||||
value));
|
||||
EXPECT_TRUE(value) << fieldName;
|
||||
};
|
||||
expectBoolField("ObservedHasRenderingData");
|
||||
expectBoolField("ObservedHasCameraData");
|
||||
expectBoolField("ObservedHasLightingData");
|
||||
expectBoolField("ObservedHasShadowData");
|
||||
expectBoolField("ObservedHasEnvironmentData");
|
||||
expectBoolField("ObservedHasFinalColorData");
|
||||
expectBoolField("ObservedHasStageColorData");
|
||||
expectBoolField("ObservedRenderingDataMatchesItems");
|
||||
|
||||
int observedStage = -1;
|
||||
int observedRendererIndex = -1;
|
||||
EXPECT_TRUE(runtime->TryGetFieldValue(
|
||||
selectionScript,
|
||||
"ObservedStage",
|
||||
observedStage));
|
||||
EXPECT_TRUE(runtime->TryGetFieldValue(
|
||||
selectionScript,
|
||||
"ObservedRendererIndex",
|
||||
observedRendererIndex));
|
||||
EXPECT_EQ(
|
||||
observedStage,
|
||||
static_cast<int>(
|
||||
XCEngine::Rendering::CameraFrameStage::MainScene));
|
||||
EXPECT_EQ(observedRendererIndex, 0);
|
||||
|
||||
host->GetStageRecorder()->Shutdown();
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
MonoScriptRuntimeTest,
|
||||
PublicRecordRenderGraphSharesFrameDataAcrossRendererPasses) {
|
||||
Scene* runtimeScene =
|
||||
CreateScene("ManagedPublicRenderGraphSharedFrameDataScene");
|
||||
GameObject* selectionObject =
|
||||
runtimeScene->CreateGameObject(
|
||||
"ManagedPublicRenderGraphSharedFrameDataSelection");
|
||||
ScriptComponent* selectionScript =
|
||||
AddScript(
|
||||
selectionObject,
|
||||
"Gameplay",
|
||||
"ManagedPublicRenderGraphSharedFrameDataRuntimeSelectionProbe");
|
||||
ASSERT_NE(selectionScript, nullptr);
|
||||
|
||||
engine->OnRuntimeStart(runtimeScene);
|
||||
engine->OnUpdate(0.016f);
|
||||
|
||||
XCEngine::Rendering::CameraRenderer renderer;
|
||||
const auto* asset =
|
||||
dynamic_cast<
|
||||
const XCEngine::Rendering::Pipelines::ManagedScriptableRenderPipelineAsset*>(
|
||||
renderer.GetPipelineAsset());
|
||||
ASSERT_NE(asset, nullptr);
|
||||
EXPECT_EQ(asset->GetDescriptor().assemblyName, "GameScripts");
|
||||
EXPECT_EQ(asset->GetDescriptor().namespaceName, "Gameplay");
|
||||
EXPECT_EQ(
|
||||
asset->GetDescriptor().className,
|
||||
"ManagedPublicRenderGraphSharedFrameDataProbeAsset");
|
||||
|
||||
auto* host =
|
||||
dynamic_cast<XCEngine::Rendering::Pipelines::ScriptableRenderPipelineHost*>(
|
||||
renderer.GetPipeline());
|
||||
ASSERT_NE(host, nullptr);
|
||||
ASSERT_NE(host->GetStageRecorder(), nullptr);
|
||||
ASSERT_TRUE(
|
||||
host->GetStageRecorder()->Initialize(
|
||||
XCEngine::Rendering::RenderContext{}))
|
||||
<< runtime->GetLastError();
|
||||
ASSERT_TRUE(
|
||||
host->SupportsStageRenderGraph(
|
||||
XCEngine::Rendering::RenderPipelineStageSupportContext{
|
||||
XCEngine::Rendering::CameraFrameStage::MainScene,
|
||||
0 }))
|
||||
<< runtime->GetLastError();
|
||||
|
||||
XCEngine::Rendering::RenderGraph graph;
|
||||
XCEngine::Rendering::RenderGraphBuilder graphBuilder(graph);
|
||||
XCEngine::Rendering::RenderGraphTextureDesc colorDesc = {};
|
||||
colorDesc.width = 16u;
|
||||
colorDesc.height = 16u;
|
||||
colorDesc.format =
|
||||
static_cast<XCEngine::Core::uint32>(
|
||||
XCEngine::RHI::Format::R8G8B8A8_UNorm);
|
||||
XCEngine::Rendering::RenderGraphTextureDesc depthDesc = colorDesc;
|
||||
depthDesc.format =
|
||||
static_cast<XCEngine::Core::uint32>(
|
||||
XCEngine::RHI::Format::D32_Float);
|
||||
const XCEngine::Rendering::RenderGraphTextureHandle colorTarget =
|
||||
graphBuilder.CreateTransientTexture(
|
||||
"ManagedPublicSharedFrameDataColor",
|
||||
colorDesc);
|
||||
const XCEngine::Rendering::RenderGraphTextureHandle depthTarget =
|
||||
graphBuilder.CreateTransientTexture(
|
||||
"ManagedPublicSharedFrameDataDepth",
|
||||
depthDesc);
|
||||
|
||||
const XCEngine::Rendering::RenderSceneData sceneData = {};
|
||||
const XCEngine::Rendering::RenderSurface surface(16u, 16u);
|
||||
bool executionSucceeded = true;
|
||||
XCEngine::Rendering::RenderGraphBlackboard blackboard = {};
|
||||
const XCEngine::Rendering::RenderPipelineStageRenderGraphContext graphContext = {
|
||||
graphBuilder,
|
||||
"ManagedPublicSharedFrameData",
|
||||
XCEngine::Rendering::CameraFrameStage::MainScene,
|
||||
{},
|
||||
sceneData,
|
||||
surface,
|
||||
nullptr,
|
||||
nullptr,
|
||||
XCEngine::RHI::ResourceStates::Common,
|
||||
{},
|
||||
{ colorTarget },
|
||||
depthTarget,
|
||||
{},
|
||||
&executionSucceeded,
|
||||
&blackboard,
|
||||
XCEngine::Rendering::CameraFrameColorSource::ExplicitSurface,
|
||||
false,
|
||||
{},
|
||||
0
|
||||
};
|
||||
|
||||
EXPECT_TRUE(
|
||||
host->GetStageRecorder()->RecordStageRenderGraph(graphContext))
|
||||
<< runtime->GetLastError();
|
||||
engine->OnUpdate(0.016f);
|
||||
|
||||
const auto expectBoolField =
|
||||
[&](const char* fieldName) {
|
||||
bool value = false;
|
||||
EXPECT_TRUE(runtime->TryGetFieldValue(
|
||||
selectionScript,
|
||||
fieldName,
|
||||
value));
|
||||
EXPECT_TRUE(value) << fieldName;
|
||||
};
|
||||
expectBoolField("ObservedWriterVisited");
|
||||
expectBoolField("ObservedReaderVisited");
|
||||
expectBoolField("ObservedReaderSawWriterItem");
|
||||
expectBoolField("ObservedSameFrameData");
|
||||
expectBoolField("ObservedSameRenderingData");
|
||||
|
||||
int observedValue = 0;
|
||||
EXPECT_TRUE(runtime->TryGetFieldValue(
|
||||
selectionScript,
|
||||
"ObservedValue",
|
||||
observedValue));
|
||||
EXPECT_EQ(observedValue, 73);
|
||||
|
||||
int observedReaderOrder = 0;
|
||||
EXPECT_TRUE(runtime->TryGetFieldValue(
|
||||
selectionScript,
|
||||
"ObservedReaderOrder",
|
||||
observedReaderOrder));
|
||||
EXPECT_GT(observedReaderOrder, 1);
|
||||
|
||||
host->GetStageRecorder()->Shutdown();
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
MonoScriptRuntimeTest,
|
||||
DefaultCameraRendererUsesScriptCoreUniversalPipelineAssetAndRespectsRendererData) {
|
||||
|
||||
Reference in New Issue
Block a user