refactor(srp): centralize renderer data collections
This commit is contained in:
@@ -0,0 +1,283 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
internal sealed class ScriptableRendererDataCollection
|
||||
{
|
||||
private ScriptableRendererData[] m_rendererDataList;
|
||||
|
||||
public ScriptableRendererDataCollection()
|
||||
{
|
||||
m_rendererDataList =
|
||||
Array.Empty<ScriptableRendererData>();
|
||||
}
|
||||
|
||||
public ScriptableRendererData GetDefaultRendererData(
|
||||
ref ScriptableRendererData[] configuredRendererDataList,
|
||||
ref int defaultRendererIndex,
|
||||
Func<ScriptableRendererData> createDefaultRendererData)
|
||||
{
|
||||
return GetRendererData(
|
||||
ref configuredRendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
ResolveDefaultRendererIndex(
|
||||
ref configuredRendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
createDefaultRendererData),
|
||||
createDefaultRendererData);
|
||||
}
|
||||
|
||||
public ScriptableRendererData GetRendererData(
|
||||
ref ScriptableRendererData[] configuredRendererDataList,
|
||||
ref int defaultRendererIndex,
|
||||
int rendererIndex,
|
||||
Func<ScriptableRendererData> createDefaultRendererData)
|
||||
{
|
||||
int resolvedRendererIndex =
|
||||
ResolveRendererIndexWithFallback(
|
||||
ref configuredRendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
rendererIndex,
|
||||
createDefaultRendererData);
|
||||
if (resolvedRendererIndex < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return m_rendererDataList[resolvedRendererIndex];
|
||||
}
|
||||
|
||||
public int ResolveDefaultRendererIndex(
|
||||
ref ScriptableRendererData[] configuredRendererDataList,
|
||||
ref int defaultRendererIndex,
|
||||
Func<ScriptableRendererData> createDefaultRendererData)
|
||||
{
|
||||
ScriptableRendererData[] rendererDataList =
|
||||
ResolveConfiguredRendererDataList(
|
||||
ref configuredRendererDataList,
|
||||
createDefaultRendererData);
|
||||
if (rendererDataList.Length == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (defaultRendererIndex < 0 ||
|
||||
defaultRendererIndex >= rendererDataList.Length)
|
||||
{
|
||||
defaultRendererIndex = 0;
|
||||
}
|
||||
|
||||
if (rendererDataList[defaultRendererIndex] != null)
|
||||
{
|
||||
return defaultRendererIndex;
|
||||
}
|
||||
|
||||
int firstValidRendererIndex =
|
||||
FindFirstValidRendererIndex(rendererDataList);
|
||||
if (firstValidRendererIndex >= 0)
|
||||
{
|
||||
defaultRendererIndex = firstValidRendererIndex;
|
||||
return defaultRendererIndex;
|
||||
}
|
||||
|
||||
rendererDataList[defaultRendererIndex] =
|
||||
createDefaultRendererData != null
|
||||
? createDefaultRendererData()
|
||||
: null;
|
||||
return rendererDataList[defaultRendererIndex] != null
|
||||
? defaultRendererIndex
|
||||
: -1;
|
||||
}
|
||||
|
||||
public int ResolveRendererIndexWithFallback(
|
||||
ref ScriptableRendererData[] configuredRendererDataList,
|
||||
ref int defaultRendererIndex,
|
||||
int rendererIndex,
|
||||
Func<ScriptableRendererData> createDefaultRendererData)
|
||||
{
|
||||
ScriptableRendererData[] rendererDataList =
|
||||
ResolveConfiguredRendererDataList(
|
||||
ref configuredRendererDataList,
|
||||
createDefaultRendererData);
|
||||
if (rendererDataList.Length == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rendererIndex < 0 ||
|
||||
rendererIndex >= rendererDataList.Length)
|
||||
{
|
||||
return ResolveDefaultRendererIndex(
|
||||
ref configuredRendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
createDefaultRendererData);
|
||||
}
|
||||
|
||||
if (rendererDataList[rendererIndex] == null)
|
||||
{
|
||||
return ResolveDefaultRendererIndex(
|
||||
ref configuredRendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
createDefaultRendererData);
|
||||
}
|
||||
|
||||
return rendererIndex;
|
||||
}
|
||||
|
||||
public void Synchronize(
|
||||
ref ScriptableRendererData[] configuredRendererDataList,
|
||||
ref int defaultRendererIndex,
|
||||
ref int collectionHash,
|
||||
ref bool collectionHashResolved,
|
||||
Func<ScriptableRendererData> createDefaultRendererData,
|
||||
Action onChanged)
|
||||
{
|
||||
ScriptableRendererData[] rendererDataList =
|
||||
ResolveConfiguredRendererDataList(
|
||||
ref configuredRendererDataList,
|
||||
createDefaultRendererData);
|
||||
int resolvedDefaultRendererIndex =
|
||||
ResolveDefaultRendererIndex(
|
||||
ref configuredRendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
createDefaultRendererData);
|
||||
int resolvedHash =
|
||||
ComputeCollectionHash(
|
||||
rendererDataList,
|
||||
resolvedDefaultRendererIndex);
|
||||
if (!collectionHashResolved)
|
||||
{
|
||||
collectionHash = resolvedHash;
|
||||
collectionHashResolved = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (resolvedHash == collectionHash)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
collectionHash = resolvedHash;
|
||||
onChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void ReleaseRuntimeResources(
|
||||
ref ScriptableRendererData[] configuredRendererDataList,
|
||||
ref int defaultRendererIndex,
|
||||
Func<ScriptableRendererData> createDefaultRendererData)
|
||||
{
|
||||
ScriptableRendererData[] rendererDataList =
|
||||
ResolveConfiguredRendererDataList(
|
||||
ref configuredRendererDataList,
|
||||
createDefaultRendererData);
|
||||
for (int i = 0; i < rendererDataList.Length; ++i)
|
||||
{
|
||||
ScriptableRendererData rendererData =
|
||||
rendererDataList[i];
|
||||
if (rendererData == null ||
|
||||
WasRendererDataReleasedEarlier(
|
||||
rendererDataList,
|
||||
i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
rendererData.ReleaseRuntimeResourcesInstance();
|
||||
}
|
||||
}
|
||||
|
||||
private ScriptableRendererData[] ResolveConfiguredRendererDataList(
|
||||
ref ScriptableRendererData[] configuredRendererDataList,
|
||||
Func<ScriptableRendererData> createDefaultRendererData)
|
||||
{
|
||||
if (configuredRendererDataList == null ||
|
||||
configuredRendererDataList.Length == 0)
|
||||
{
|
||||
ScriptableRendererData defaultRendererData =
|
||||
createDefaultRendererData != null
|
||||
? createDefaultRendererData()
|
||||
: null;
|
||||
configuredRendererDataList =
|
||||
defaultRendererData != null
|
||||
? new ScriptableRendererData[]
|
||||
{
|
||||
defaultRendererData
|
||||
}
|
||||
: Array.Empty<ScriptableRendererData>();
|
||||
}
|
||||
|
||||
m_rendererDataList = configuredRendererDataList;
|
||||
return m_rendererDataList;
|
||||
}
|
||||
|
||||
private static int ComputeCollectionHash(
|
||||
ScriptableRendererData[] rendererDataList,
|
||||
int defaultRendererIndex)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 17;
|
||||
hash = (hash * 31) + defaultRendererIndex;
|
||||
if (rendererDataList == null)
|
||||
{
|
||||
return hash;
|
||||
}
|
||||
|
||||
hash = (hash * 31) + rendererDataList.Length;
|
||||
for (int i = 0; i < rendererDataList.Length; ++i)
|
||||
{
|
||||
ScriptableRendererData rendererData =
|
||||
rendererDataList[i];
|
||||
if (rendererData == null)
|
||||
{
|
||||
hash = (hash * 31) + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
hash =
|
||||
(hash * 31) +
|
||||
RuntimeHelpers.GetHashCode(rendererData);
|
||||
hash =
|
||||
(hash * 31) +
|
||||
rendererData.GetRuntimeStateVersionInstance();
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
private static int FindFirstValidRendererIndex(
|
||||
ScriptableRendererData[] rendererDataList)
|
||||
{
|
||||
for (int i = 0; i < rendererDataList.Length; ++i)
|
||||
{
|
||||
if (rendererDataList[i] != null)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static bool WasRendererDataReleasedEarlier(
|
||||
ScriptableRendererData[] rendererDataList,
|
||||
int rendererDataIndex)
|
||||
{
|
||||
ScriptableRendererData rendererData =
|
||||
rendererDataList[rendererDataIndex];
|
||||
for (int i = 0; i < rendererDataIndex; ++i)
|
||||
{
|
||||
if (object.ReferenceEquals(
|
||||
rendererDataList[i],
|
||||
rendererData))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user