Serialize managed SRP asset graphs
This commit is contained in:
@@ -109,7 +109,8 @@ Unity 兼容的公开命名、对象所有权和扩展点。
|
||||
|
||||
- `GraphicsSettings.renderPipelineAsset == null` 表示 renderer 使用 engine default native pipeline selection。
|
||||
- `GraphicsSettings.renderPipelineAsset != null` 表示 renderer 使用 render-pipeline asset reference selection path。
|
||||
`AssetRef` 是长期选择身份;managed descriptor/handle 只是运行时 materialization cache 和过渡 fallback。
|
||||
`AssetRef` 是长期选择身份;managed descriptor 中的 serialized ScriptableObject graph 和 handle 只是运行时
|
||||
materialization cache 和过渡 fallback。
|
||||
- Runtime startup 不应静默指定 project default SRP asset。Project 或 editor policy 可以显式选择一个,
|
||||
但 active rendering mode 必须能通过 `GraphicsSettings.renderPipelineAsset` 观察到。
|
||||
- `GraphicsSettingsState` 同时保存 configured render-pipeline asset `AssetRef` 和
|
||||
@@ -198,11 +199,16 @@ Native passes 仍用于 backend fallback、工具和 built-in rendering。
|
||||
Managed SRP assets 通过 `GraphicsSettings.renderPipelineAsset` 选择,并通过
|
||||
`ManagedScriptableRenderPipelineAsset` bridge。
|
||||
|
||||
- `ManagedRenderPipelineAssetDescriptor` 标识 managed asset assembly、namespace、class、retained managed
|
||||
object handle 和可选 `AssetRef`。它不再是 configured pipeline 的唯一身份;`GraphicsSettingsState` 中的
|
||||
configured `AssetRef` 才是 Unity 风格 asset selection root。
|
||||
- Descriptor-only selection 仍保留给测试、legacy runtime fallback 和尚未接入 asset serialization 的路径。
|
||||
一旦已有 configured `AssetRef`,不要把 managed object handle 或 descriptor 当作长期 asset identity。
|
||||
- `ManagedRenderPipelineAssetDescriptor` 标识 managed asset assembly、namespace、class、可选 `AssetRef`、
|
||||
serialized ScriptableObject asset graph 和 retained managed object handle。它不再是 configured pipeline
|
||||
的唯一身份;`GraphicsSettingsState` 中的 configured `AssetRef` 才是 Unity 风格 asset selection root。
|
||||
- Descriptor-only selection 仍保留给测试、legacy runtime fallback 和尚未接入 asset import 的路径。没有
|
||||
`serializedAssetGraph` 时才允许按 class 默认构造 materialize;一旦 snapshot 存在,缺失或失效的
|
||||
managed object handle 必须从 snapshot 重建,不能退回 code-created default asset。
|
||||
- `GraphicsSettings.renderPipelineAsset = asset` 必须把当前 managed SRP asset graph snapshot 收进 descriptor。
|
||||
该 snapshot 覆盖 `UniversalRenderPipelineAsset -> ScriptableRendererData -> ScriptableRendererFeature`
|
||||
以及 public/`[SerializeField]` serializable settings。Runtime cache 更新可以替换 handle,但不得丢失
|
||||
snapshot 或 configured `AssetRef`。
|
||||
- `ManagedScriptableRenderPipelineAsset` 解析 `ManagedRenderPipelineAssetRuntime`,创建
|
||||
`ScriptableRenderPipelineHost`,并把 request/plan/final-color policy calls 转发给 managed code。
|
||||
- `ScriptableRenderPipelineHost` 组合 native backend asset 和可选 managed stage recorder。当 managed recorder
|
||||
@@ -339,8 +345,8 @@ Scene data 每个 camera frame 提取一次,然后由 pipeline 调整。
|
||||
authoring 还未公开。
|
||||
- `UniversalPostProcessBlock` 仍保留 post-process source promotion helper;实际 post-process stage 由
|
||||
active pass queue 中的 features/passes 声明。
|
||||
- Render-pipeline selection 已切到 `AssetRef` 作为根身份,但 `UniversalRendererData`、features 和
|
||||
`ScriptableObject` 字段/子资产仍是 code-created objects,还不是完整 Unity 风格 serialized asset pipeline。
|
||||
- Render-pipeline selection 已切到 `AssetRef` 作为根身份,并且 managed SRP descriptor 已保存
|
||||
ScriptableObject graph snapshot;完整 editor/importer `.asset` 持久化和 sub-asset authoring 仍未完成。
|
||||
- 当前 shadow support 是单个 main directional shadow path,没有 cascades。
|
||||
- Graph compiler/executor 当前没有实现 pass culling 或 transient aliasing。
|
||||
|
||||
@@ -354,6 +360,9 @@ Scene data 每个 camera frame 提取一次,然后由 pipeline 调整。
|
||||
`GraphicsSettingsState` 选择 managed SRP assets。
|
||||
- Render-pipeline asset selection 已从 descriptor/managed handle 切到 `AssetRef` 根身份;descriptor 保留为
|
||||
assembly/type/handle runtime cache,managed materialization 更新 cache 时保留 configured asset reference。
|
||||
- Managed SRP descriptor 已接入 serialized ScriptableObject graph snapshot。`GraphicsSettings` setter 保存
|
||||
当前 asset/data/features 图,getter 和 `MonoManagedRenderPipelineAssetRuntime` 在 handle 缺失或失效时按
|
||||
snapshot 重建;无 snapshot 的 descriptor-only selection 才保留 class 默认构造 fallback。
|
||||
- Managed SRP execution 由 `ScriptableRenderPipelineHost` 承载,它组合 native backend 和可选 managed
|
||||
stage recorder。
|
||||
- Mono-backed SRP assets 使用 `DefaultNativeBackend` 做 scene drawing,并把 managed stages 记录到 native
|
||||
|
||||
@@ -33,6 +33,7 @@ struct ManagedRenderPipelineAssetDescriptor {
|
||||
std::string className;
|
||||
uint32_t managedAssetHandle = 0u;
|
||||
Resources::AssetRef assetRef = {};
|
||||
std::string serializedAssetGraph;
|
||||
|
||||
bool IsValid() const {
|
||||
return !assemblyName.empty() && !className.empty();
|
||||
@@ -46,6 +47,10 @@ struct ManagedRenderPipelineAssetDescriptor {
|
||||
return assetRef.IsValid();
|
||||
}
|
||||
|
||||
bool HasSerializedAssetGraph() const {
|
||||
return !serializedAssetGraph.empty();
|
||||
}
|
||||
|
||||
std::string GetFullName() const {
|
||||
return namespaceName.empty()
|
||||
? className
|
||||
|
||||
@@ -103,6 +103,12 @@ public:
|
||||
const char* passName,
|
||||
uint64_t commandBufferHandle);
|
||||
bool IsScriptableRenderPipelineAssetObject(MonoObject* managedObject) const;
|
||||
bool TrySerializeManagedRenderPipelineAssetGraph(
|
||||
MonoObject* managedObject,
|
||||
std::string& outSerializedGraph);
|
||||
bool TryCreateManagedRenderPipelineAssetFromSerializedGraph(
|
||||
const std::string& serializedGraph,
|
||||
uint32_t& outHandle);
|
||||
bool TryEnsureManagedRenderPipelineAssetHandle(
|
||||
Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor& ioDescriptor);
|
||||
|
||||
@@ -266,6 +272,9 @@ private:
|
||||
bool CreateExternalManagedObject(
|
||||
MonoClass* monoClass,
|
||||
uint32_t& outHandle);
|
||||
bool TryDeserializeManagedRenderPipelineAssetGraph(
|
||||
const std::string& serializedGraph,
|
||||
MonoObject*& outAsset);
|
||||
uint32_t RetainExternalManagedObject(MonoObject* instance);
|
||||
void DestroyExternalManagedObject(uint32_t gcHandle);
|
||||
MonoObject* CreateManagedScriptableRenderContext(uint64_t nativeHandle);
|
||||
|
||||
@@ -2752,24 +2752,33 @@ bool MonoManagedRenderPipelineAssetRuntime::EnsureManagedAsset() const {
|
||||
? mono_object_get_class(assetObject)
|
||||
: nullptr;
|
||||
if (assetClass == nullptr) {
|
||||
m_runtime->SetError(
|
||||
"Managed render pipeline asset handle is no longer valid: " +
|
||||
m_descriptor.GetFullName() + ".");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsMonoClassOrSubclass(
|
||||
assetClass,
|
||||
m_runtime->m_scriptableRenderPipelineAssetClass)) {
|
||||
if (!m_descriptor.HasSerializedAssetGraph()) {
|
||||
m_runtime->SetError(
|
||||
"Managed render pipeline asset handle is no longer valid: " +
|
||||
m_descriptor.GetFullName() + ".");
|
||||
return false;
|
||||
}
|
||||
} else if (!IsMonoClassOrSubclass(
|
||||
assetClass,
|
||||
m_runtime->m_scriptableRenderPipelineAssetClass)) {
|
||||
m_runtime->SetError(
|
||||
"Managed render pipeline asset must derive from ScriptableRenderPipelineAsset: " +
|
||||
m_descriptor.GetFullName() + ".");
|
||||
return false;
|
||||
} else {
|
||||
m_assetHandle = m_descriptor.managedAssetHandle;
|
||||
m_ownsManagedAssetHandle = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
m_assetHandle = m_descriptor.managedAssetHandle;
|
||||
m_ownsManagedAssetHandle = false;
|
||||
return true;
|
||||
if (m_descriptor.HasSerializedAssetGraph()) {
|
||||
m_ownsManagedAssetHandle =
|
||||
m_runtime->TryCreateManagedRenderPipelineAssetFromSerializedGraph(
|
||||
m_descriptor.serializedAssetGraph,
|
||||
m_assetHandle) &&
|
||||
m_assetHandle != 0;
|
||||
return m_ownsManagedAssetHandle;
|
||||
}
|
||||
|
||||
MonoClass* assetClass = nullptr;
|
||||
@@ -4896,6 +4905,17 @@ void InternalCall_Rendering_SetRenderPipelineAsset(MonoObject* assetObject) {
|
||||
runtime != nullptr
|
||||
? runtime->RetainExternalManagedObjectReference(assetObject)
|
||||
: 0u;
|
||||
if (runtime != nullptr &&
|
||||
!runtime->TrySerializeManagedRenderPipelineAssetGraph(
|
||||
assetObject,
|
||||
descriptor.serializedAssetGraph)) {
|
||||
if (descriptor.managedAssetHandle != 0u) {
|
||||
runtime->ReleaseExternalManagedObject(
|
||||
descriptor.managedAssetHandle);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!descriptor.IsValid() ||
|
||||
descriptor.managedAssetHandle == 0u) {
|
||||
if (runtime != nullptr &&
|
||||
@@ -4930,11 +4950,13 @@ MonoObject* InternalCall_Rendering_GetRenderPipelineAsset() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (descriptor.managedAssetHandle == 0u) {
|
||||
if (!runtime->TryEnsureManagedRenderPipelineAssetHandle(descriptor)) {
|
||||
return nullptr;
|
||||
}
|
||||
const uint32_t previousManagedAssetHandle =
|
||||
descriptor.managedAssetHandle;
|
||||
if (!runtime->TryEnsureManagedRenderPipelineAssetHandle(descriptor)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (descriptor.managedAssetHandle != previousManagedAssetHandle) {
|
||||
Rendering::GetGraphicsSettingsState()
|
||||
.UpdateConfiguredRenderPipelineAssetRuntimeDescriptor(descriptor);
|
||||
}
|
||||
@@ -8531,6 +8553,127 @@ bool MonoScriptRuntime::IsScriptableRenderPipelineAssetObject(
|
||||
m_scriptableRenderPipelineAssetClass);
|
||||
}
|
||||
|
||||
bool MonoScriptRuntime::TrySerializeManagedRenderPipelineAssetGraph(
|
||||
MonoObject* managedObject,
|
||||
std::string& outSerializedGraph) {
|
||||
outSerializedGraph.clear();
|
||||
if (!m_initialized ||
|
||||
!IsScriptableRenderPipelineAssetObject(managedObject) ||
|
||||
m_scriptableRenderPipelineAssetClass == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MonoMethod* const serializeMethod =
|
||||
ResolveManagedMethod(
|
||||
m_scriptableRenderPipelineAssetClass,
|
||||
"SerializeAssetGraphInstance",
|
||||
1);
|
||||
if (serializeMethod == nullptr) {
|
||||
SetError(
|
||||
"Managed ScriptableRenderPipelineAsset.SerializeAssetGraphInstance was not found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
SetCurrentDomain();
|
||||
|
||||
void* args[1] = { managedObject };
|
||||
MonoObject* exception = nullptr;
|
||||
MonoObject* const result =
|
||||
mono_runtime_invoke(
|
||||
serializeMethod,
|
||||
nullptr,
|
||||
args,
|
||||
&exception);
|
||||
if (exception != nullptr) {
|
||||
RecordException(exception);
|
||||
return false;
|
||||
}
|
||||
|
||||
MonoString* const serializedGraph =
|
||||
reinterpret_cast<MonoString*>(result);
|
||||
outSerializedGraph = MonoStringToUtf8(serializedGraph);
|
||||
if (outSerializedGraph.empty()) {
|
||||
SetError(
|
||||
"Managed render pipeline asset graph serialization returned an empty snapshot.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MonoScriptRuntime::TryDeserializeManagedRenderPipelineAssetGraph(
|
||||
const std::string& serializedGraph,
|
||||
MonoObject*& outAsset) {
|
||||
outAsset = nullptr;
|
||||
if (!m_initialized ||
|
||||
serializedGraph.empty() ||
|
||||
m_scriptableRenderPipelineAssetClass == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MonoMethod* const deserializeMethod =
|
||||
ResolveManagedMethod(
|
||||
m_scriptableRenderPipelineAssetClass,
|
||||
"DeserializeAssetGraphInstance",
|
||||
1);
|
||||
if (deserializeMethod == nullptr) {
|
||||
SetError(
|
||||
"Managed ScriptableRenderPipelineAsset.DeserializeAssetGraphInstance was not found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
SetCurrentDomain();
|
||||
|
||||
MonoString* const managedSerializedGraph =
|
||||
mono_string_new(
|
||||
m_appDomain,
|
||||
serializedGraph.c_str());
|
||||
void* args[1] = { managedSerializedGraph };
|
||||
MonoObject* exception = nullptr;
|
||||
MonoObject* const result =
|
||||
mono_runtime_invoke(
|
||||
deserializeMethod,
|
||||
nullptr,
|
||||
args,
|
||||
&exception);
|
||||
if (exception != nullptr) {
|
||||
RecordException(exception);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsScriptableRenderPipelineAssetObject(result)) {
|
||||
SetError(
|
||||
"Managed render pipeline asset graph deserialization did not return a ScriptableRenderPipelineAsset.");
|
||||
return false;
|
||||
}
|
||||
|
||||
outAsset = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MonoScriptRuntime::TryCreateManagedRenderPipelineAssetFromSerializedGraph(
|
||||
const std::string& serializedGraph,
|
||||
uint32_t& outHandle) {
|
||||
outHandle = 0u;
|
||||
|
||||
MonoObject* assetObject = nullptr;
|
||||
if (!TryDeserializeManagedRenderPipelineAssetGraph(
|
||||
serializedGraph,
|
||||
assetObject) ||
|
||||
assetObject == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
outHandle = RetainExternalManagedObject(assetObject);
|
||||
if (outHandle == 0u) {
|
||||
SetError(
|
||||
"Managed render pipeline asset graph deserialization returned an object that could not be retained.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MonoScriptRuntime::TryEnsureManagedRenderPipelineAssetHandle(
|
||||
Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor& ioDescriptor) {
|
||||
if (!m_initialized || !ioDescriptor.IsValid()) {
|
||||
@@ -8547,6 +8690,37 @@ bool MonoScriptRuntime::TryEnsureManagedRenderPipelineAssetHandle(
|
||||
ioDescriptor.managedAssetHandle = 0u;
|
||||
}
|
||||
|
||||
if (ioDescriptor.HasSerializedAssetGraph()) {
|
||||
if (!TryCreateManagedRenderPipelineAssetFromSerializedGraph(
|
||||
ioDescriptor.serializedAssetGraph,
|
||||
ioDescriptor.managedAssetHandle) ||
|
||||
ioDescriptor.managedAssetHandle == 0u) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MonoObject* const assetObject =
|
||||
GetExternalManagedObject(ioDescriptor.managedAssetHandle);
|
||||
MonoClass* const assetClass =
|
||||
assetObject != nullptr
|
||||
? mono_object_get_class(assetObject)
|
||||
: nullptr;
|
||||
if (assetClass != nullptr) {
|
||||
MonoImage* const image =
|
||||
mono_class_get_image(assetClass);
|
||||
ioDescriptor.assemblyName =
|
||||
TrimAssemblyName(
|
||||
SafeString(
|
||||
image != nullptr
|
||||
? mono_image_get_name(image)
|
||||
: nullptr));
|
||||
ioDescriptor.namespaceName =
|
||||
SafeString(mono_class_get_namespace(assetClass));
|
||||
ioDescriptor.className =
|
||||
SafeString(mono_class_get_name(assetClass));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MonoClass* assetClass = nullptr;
|
||||
if (!ResolveManagedClass(
|
||||
ioDescriptor.assemblyName,
|
||||
|
||||
@@ -162,6 +162,7 @@ set(XCENGINE_SCRIPT_CORE_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/MonoBehaviour.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Object.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ScriptableObject.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/ScriptableObjectSerializedGraph.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Physics.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/PhysicsBodyType.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Quaternion.cs
|
||||
|
||||
@@ -3314,6 +3314,135 @@ namespace Gameplay
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class SerializedUniversalRenderPipelineAssetGraphProbe
|
||||
: MonoBehaviour
|
||||
{
|
||||
public int UpdateCount;
|
||||
public bool ObservedAssetWasNull = true;
|
||||
public int ObservedDefaultRendererIndex = -1;
|
||||
public int ObservedRendererDataCount;
|
||||
public int ObservedRendererFeatureCount;
|
||||
public bool ObservedFeatureActive = true;
|
||||
public string ObservedFeatureTypeName = string.Empty;
|
||||
public Vector4 ObservedColorScale;
|
||||
public bool ObservedShadowsSupportMainLight = true;
|
||||
public Vector4 ObservedFinalColorScale;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
UniversalRenderPipelineAsset asset =
|
||||
ScriptableObject
|
||||
.CreateInstance<UniversalRenderPipelineAsset>();
|
||||
UniversalRendererData rendererData =
|
||||
ScriptableObject
|
||||
.CreateInstance<UniversalRendererData>();
|
||||
ColorScalePostProcessRendererFeature colorScaleFeature =
|
||||
ScriptableObject
|
||||
.CreateInstance<ColorScalePostProcessRendererFeature>();
|
||||
if (asset == null ||
|
||||
rendererData == null ||
|
||||
colorScaleFeature == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
colorScaleFeature.colorScale = new Vector4(
|
||||
0.42f,
|
||||
0.51f,
|
||||
0.63f,
|
||||
1.0f);
|
||||
colorScaleFeature.SetActive(false);
|
||||
rendererData.rendererFeatures =
|
||||
new ScriptableRendererFeature[]
|
||||
{
|
||||
colorScaleFeature
|
||||
};
|
||||
asset.rendererDataList =
|
||||
new ScriptableRendererData[]
|
||||
{
|
||||
rendererData
|
||||
};
|
||||
asset.defaultRendererIndex = 0;
|
||||
asset.shadows =
|
||||
UniversalShadowSettings.CreateDefault();
|
||||
asset.shadows.supportsMainLightShadows = false;
|
||||
asset.finalColor =
|
||||
UniversalFinalColorSettings.CreateDefault();
|
||||
asset.finalColor.settings.finalColorScale =
|
||||
new Vector4(
|
||||
0.90f,
|
||||
1.10f,
|
||||
1.20f,
|
||||
1.0f);
|
||||
|
||||
GraphicsSettings.renderPipelineAsset = asset;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
++UpdateCount;
|
||||
if (UpdateCount < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UniversalRenderPipelineAsset asset =
|
||||
GraphicsSettings.renderPipelineAsset as
|
||||
UniversalRenderPipelineAsset;
|
||||
ObservedAssetWasNull = asset == null;
|
||||
if (asset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ObservedDefaultRendererIndex =
|
||||
asset.defaultRendererIndex;
|
||||
ObservedRendererDataCount =
|
||||
asset.rendererDataList != null
|
||||
? asset.rendererDataList.Length
|
||||
: 0;
|
||||
ObservedShadowsSupportMainLight =
|
||||
asset.shadows != null &&
|
||||
asset.shadows.supportsMainLightShadows;
|
||||
ObservedFinalColorScale =
|
||||
asset.finalColor != null
|
||||
? asset.finalColor.settings.finalColorScale
|
||||
: new Vector4();
|
||||
|
||||
ScriptableRendererData rendererData =
|
||||
asset.rendererDataList != null &&
|
||||
asset.rendererDataList.Length > 0
|
||||
? asset.rendererDataList[0]
|
||||
: null;
|
||||
ObservedRendererFeatureCount =
|
||||
rendererData != null &&
|
||||
rendererData.rendererFeatures != null
|
||||
? rendererData.rendererFeatures.Length
|
||||
: 0;
|
||||
|
||||
ScriptableRendererFeature feature =
|
||||
rendererData != null &&
|
||||
rendererData.rendererFeatures != null &&
|
||||
rendererData.rendererFeatures.Length > 0
|
||||
? rendererData.rendererFeatures[0]
|
||||
: null;
|
||||
ObservedFeatureTypeName =
|
||||
feature != null
|
||||
? feature.GetType().FullName ?? string.Empty
|
||||
: string.Empty;
|
||||
ObservedFeatureActive =
|
||||
feature != null &&
|
||||
feature.isActive;
|
||||
|
||||
ColorScalePostProcessRendererFeature colorScaleFeature =
|
||||
feature as ColorScalePostProcessRendererFeature;
|
||||
ObservedColorScale =
|
||||
colorScaleFeature != null
|
||||
? colorScaleFeature.colorScale
|
||||
: new Vector4();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ScriptCoreUniversalShadowlessRendererFeatureRuntimeSelectionProbe
|
||||
: MonoBehaviour
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
private bool m_disposed;
|
||||
private bool m_runtimeCreated;
|
||||
private bool m_isActive = true;
|
||||
[SerializeField] private bool m_isActive = true;
|
||||
private int m_runtimeStateVersion = 1;
|
||||
private int m_runtimeStateHash;
|
||||
private bool m_runtimeStateHashResolved;
|
||||
|
||||
@@ -10,6 +10,21 @@ namespace XCEngine.Rendering
|
||||
{
|
||||
}
|
||||
|
||||
internal static string SerializeAssetGraphInstance(
|
||||
ScriptableRenderPipelineAsset asset)
|
||||
{
|
||||
return ScriptableObjectSerializedGraph.Serialize(asset);
|
||||
}
|
||||
|
||||
internal static ScriptableRenderPipelineAsset
|
||||
DeserializeAssetGraphInstance(
|
||||
string serializedAssetGraph)
|
||||
{
|
||||
return ScriptableObjectSerializedGraph
|
||||
.Deserialize(serializedAssetGraph) as
|
||||
ScriptableRenderPipelineAsset;
|
||||
}
|
||||
|
||||
internal void ReleaseRuntimeResourcesInstance()
|
||||
{
|
||||
ReleaseRuntimeResources();
|
||||
|
||||
1051
managed/XCEngine.ScriptCore/ScriptableObjectSerializedGraph.cs
Normal file
1051
managed/XCEngine.ScriptCore/ScriptableObjectSerializedGraph.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -529,6 +529,156 @@ TEST_F(
|
||||
"Gameplay.RenderPipelineApiProbeAsset");
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
MonoScriptRuntimeTest,
|
||||
ManagedGraphicsSettingsMaterializesSerializedUniversalAssetGraphWithoutExistingHandle) {
|
||||
Scene* runtimeScene =
|
||||
CreateScene("SerializedUniversalRenderPipelineAssetGraphScene");
|
||||
GameObject* scriptObject =
|
||||
runtimeScene->CreateGameObject(
|
||||
"SerializedUniversalRenderPipelineAssetGraphProbe");
|
||||
ScriptComponent* script =
|
||||
AddScript(
|
||||
scriptObject,
|
||||
"Gameplay",
|
||||
"SerializedUniversalRenderPipelineAssetGraphProbe");
|
||||
ASSERT_NE(script, nullptr);
|
||||
|
||||
engine->OnRuntimeStart(runtimeScene);
|
||||
engine->OnUpdate(0.016f);
|
||||
|
||||
XCEngine::Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor
|
||||
descriptor =
|
||||
XCEngine::Rendering::Pipelines::
|
||||
GetConfiguredManagedRenderPipelineAssetDescriptor();
|
||||
ASSERT_TRUE(descriptor.IsValid());
|
||||
ASSERT_EQ(
|
||||
descriptor.assemblyName,
|
||||
"XCEngine.RenderPipelines.Universal");
|
||||
ASSERT_EQ(
|
||||
descriptor.namespaceName,
|
||||
"XCEngine.Rendering.Universal");
|
||||
ASSERT_EQ(
|
||||
descriptor.className,
|
||||
"UniversalRenderPipelineAsset");
|
||||
ASSERT_NE(descriptor.managedAssetHandle, 0u);
|
||||
ASSERT_FALSE(descriptor.serializedAssetGraph.empty());
|
||||
|
||||
runtime->ReleaseExternalManagedObject(descriptor.managedAssetHandle);
|
||||
descriptor.managedAssetHandle = 0u;
|
||||
XCEngine::Rendering::Pipelines::
|
||||
SetConfiguredManagedRenderPipelineAssetDescriptor(descriptor);
|
||||
|
||||
{
|
||||
const auto bridge =
|
||||
XCEngine::Rendering::Pipelines::GetManagedRenderPipelineBridge();
|
||||
ASSERT_NE(bridge, nullptr);
|
||||
|
||||
std::shared_ptr<const XCEngine::Rendering::Pipelines::
|
||||
ManagedRenderPipelineAssetRuntime>
|
||||
assetRuntime = bridge->CreateAssetRuntime(descriptor);
|
||||
ASSERT_NE(assetRuntime, nullptr);
|
||||
|
||||
XCEngine::Rendering::FinalColorSettings settings = {};
|
||||
ASSERT_TRUE(assetRuntime->TryGetDefaultFinalColorSettings(settings));
|
||||
EXPECT_FLOAT_EQ(settings.finalColorScale.x, 0.90f);
|
||||
EXPECT_FLOAT_EQ(settings.finalColorScale.y, 1.10f);
|
||||
EXPECT_FLOAT_EQ(settings.finalColorScale.z, 1.20f);
|
||||
EXPECT_FLOAT_EQ(settings.finalColorScale.w, 1.0f);
|
||||
|
||||
std::unique_ptr<XCEngine::Rendering::RenderPipelineStageRecorder>
|
||||
recorder = assetRuntime->CreateStageRecorder();
|
||||
ASSERT_NE(recorder, nullptr);
|
||||
const XCEngine::Rendering::RenderContext context = {};
|
||||
ASSERT_TRUE(recorder->Initialize(context));
|
||||
EXPECT_TRUE(
|
||||
recorder->SupportsStageRenderGraph(
|
||||
XCEngine::Rendering::CameraFrameStage::MainScene));
|
||||
EXPECT_FALSE(
|
||||
recorder->SupportsStageRenderGraph(
|
||||
XCEngine::Rendering::CameraFrameStage::PostProcess));
|
||||
recorder->Shutdown();
|
||||
}
|
||||
|
||||
engine->OnUpdate(0.016f);
|
||||
engine->OnUpdate(0.016f);
|
||||
EXPECT_TRUE(runtime->GetLastError().empty()) << runtime->GetLastError();
|
||||
|
||||
const XCEngine::Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor
|
||||
resolvedDescriptor =
|
||||
XCEngine::Rendering::Pipelines::
|
||||
GetConfiguredManagedRenderPipelineAssetDescriptor();
|
||||
EXPECT_NE(resolvedDescriptor.managedAssetHandle, 0u);
|
||||
EXPECT_FALSE(resolvedDescriptor.serializedAssetGraph.empty());
|
||||
|
||||
int updateCount = 0;
|
||||
bool observedAssetWasNull = true;
|
||||
int observedDefaultRendererIndex = -1;
|
||||
int observedRendererDataCount = 0;
|
||||
int observedRendererFeatureCount = 0;
|
||||
bool observedFeatureActive = true;
|
||||
std::string observedFeatureTypeName;
|
||||
XCEngine::Math::Vector4 observedColorScale = {};
|
||||
bool observedShadowsSupportMainLight = true;
|
||||
XCEngine::Math::Vector4 observedFinalColorScale = {};
|
||||
EXPECT_TRUE(runtime->TryGetFieldValue(script, "UpdateCount", updateCount));
|
||||
EXPECT_TRUE(runtime->TryGetFieldValue(
|
||||
script,
|
||||
"ObservedAssetWasNull",
|
||||
observedAssetWasNull));
|
||||
EXPECT_TRUE(runtime->TryGetFieldValue(
|
||||
script,
|
||||
"ObservedDefaultRendererIndex",
|
||||
observedDefaultRendererIndex));
|
||||
EXPECT_TRUE(runtime->TryGetFieldValue(
|
||||
script,
|
||||
"ObservedRendererDataCount",
|
||||
observedRendererDataCount));
|
||||
EXPECT_TRUE(runtime->TryGetFieldValue(
|
||||
script,
|
||||
"ObservedRendererFeatureCount",
|
||||
observedRendererFeatureCount));
|
||||
EXPECT_TRUE(runtime->TryGetFieldValue(
|
||||
script,
|
||||
"ObservedFeatureActive",
|
||||
observedFeatureActive));
|
||||
EXPECT_TRUE(runtime->TryGetFieldValue(
|
||||
script,
|
||||
"ObservedFeatureTypeName",
|
||||
observedFeatureTypeName));
|
||||
EXPECT_TRUE(runtime->TryGetFieldValue(
|
||||
script,
|
||||
"ObservedColorScale",
|
||||
observedColorScale));
|
||||
EXPECT_TRUE(runtime->TryGetFieldValue(
|
||||
script,
|
||||
"ObservedShadowsSupportMainLight",
|
||||
observedShadowsSupportMainLight));
|
||||
EXPECT_TRUE(runtime->TryGetFieldValue(
|
||||
script,
|
||||
"ObservedFinalColorScale",
|
||||
observedFinalColorScale));
|
||||
|
||||
EXPECT_GE(updateCount, 2);
|
||||
EXPECT_FALSE(observedAssetWasNull);
|
||||
EXPECT_EQ(observedDefaultRendererIndex, 0);
|
||||
EXPECT_EQ(observedRendererDataCount, 1);
|
||||
EXPECT_EQ(observedRendererFeatureCount, 1);
|
||||
EXPECT_FALSE(observedFeatureActive);
|
||||
EXPECT_EQ(
|
||||
observedFeatureTypeName,
|
||||
"XCEngine.Rendering.Universal.ColorScalePostProcessRendererFeature");
|
||||
EXPECT_FLOAT_EQ(observedColorScale.x, 0.42f);
|
||||
EXPECT_FLOAT_EQ(observedColorScale.y, 0.51f);
|
||||
EXPECT_FLOAT_EQ(observedColorScale.z, 0.63f);
|
||||
EXPECT_FLOAT_EQ(observedColorScale.w, 1.0f);
|
||||
EXPECT_FALSE(observedShadowsSupportMainLight);
|
||||
EXPECT_FLOAT_EQ(observedFinalColorScale.x, 0.90f);
|
||||
EXPECT_FLOAT_EQ(observedFinalColorScale.y, 1.10f);
|
||||
EXPECT_FLOAT_EQ(observedFinalColorScale.z, 1.20f);
|
||||
EXPECT_FLOAT_EQ(observedFinalColorScale.w, 1.0f);
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
MonoScriptRuntimeTest,
|
||||
RuntimeStopClearsManagedGraphicsSettingsSelection) {
|
||||
|
||||
Reference in New Issue
Block a user