ScriptableRendererData.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. using System.Collections.Generic;
  2. using UnityEngine.Scripting.APIUpdating;
  3. #if UNITY_EDITOR
  4. using System.Linq;
  5. using UnityEditor;
  6. #endif
  7. namespace UnityEngine.Rendering.Universal
  8. {
  9. /// <summary>
  10. /// Class <c>ScriptableRendererData</c> contains resources for a <c>ScriptableRenderer</c>.
  11. /// <seealso cref="ScriptableRenderer"/>
  12. /// </summary>
  13. [MovedFrom("UnityEngine.Rendering.LWRP")] public abstract class ScriptableRendererData : ScriptableObject
  14. {
  15. internal bool isInvalidated { get; set; }
  16. /// <summary>
  17. /// Creates the instance of the ScriptableRenderer.
  18. /// </summary>
  19. /// <returns>The instance of ScriptableRenderer</returns>
  20. protected abstract ScriptableRenderer Create();
  21. [SerializeField] internal List<ScriptableRendererFeature> m_RendererFeatures = new List<ScriptableRendererFeature>(10);
  22. [SerializeField] internal List<long> m_RendererFeatureMap = new List<long>(10);
  23. /// <summary>
  24. /// List of additional render pass features for this renderer.
  25. /// </summary>
  26. public List<ScriptableRendererFeature> rendererFeatures
  27. {
  28. get => m_RendererFeatures;
  29. }
  30. /// <summary>
  31. /// Use SetDirty when changing seeings in the ScriptableRendererData.
  32. /// It will rebuild the render passes with the new data.
  33. /// </summary>
  34. public new void SetDirty()
  35. {
  36. isInvalidated = true;
  37. }
  38. internal ScriptableRenderer InternalCreateRenderer()
  39. {
  40. isInvalidated = false;
  41. return Create();
  42. }
  43. protected virtual void OnValidate()
  44. {
  45. SetDirty();
  46. #if UNITY_EDITOR
  47. if (m_RendererFeatures.Contains(null))
  48. ValidateRendererFeatures();
  49. #endif
  50. }
  51. protected virtual void OnEnable()
  52. {
  53. SetDirty();
  54. }
  55. #if UNITY_EDITOR
  56. internal virtual Material GetDefaultMaterial(DefaultMaterialType materialType)
  57. {
  58. return null;
  59. }
  60. internal virtual Shader GetDefaultShader()
  61. {
  62. return null;
  63. }
  64. internal bool ValidateRendererFeatures()
  65. {
  66. // Get all Subassets
  67. var subassets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(this));
  68. var linkedIds = new List<long>();
  69. var loadedAssets = new Dictionary<long, object>();
  70. var mapValid = m_RendererFeatureMap != null && m_RendererFeatureMap?.Count == m_RendererFeatures?.Count;
  71. var debugOutput = $"{name}\nValid Sub-assets:\n";
  72. // Collect valid, compiled sub-assets
  73. foreach (var asset in subassets)
  74. {
  75. if (asset == null || asset.GetType().BaseType != typeof(ScriptableRendererFeature)) continue;
  76. AssetDatabase.TryGetGUIDAndLocalFileIdentifier(asset, out var guid, out long localId);
  77. loadedAssets.Add(localId, asset);
  78. debugOutput += $"-{asset.name}\n--localId={localId}\n";
  79. }
  80. // Collect assets that are connected to the list
  81. for (var i = 0; i < m_RendererFeatures?.Count; i++)
  82. {
  83. if(!m_RendererFeatures[i]) continue;
  84. if (AssetDatabase.TryGetGUIDAndLocalFileIdentifier(m_RendererFeatures[i], out var guid, out long localId))
  85. {
  86. linkedIds.Add(localId);
  87. }
  88. }
  89. var mapDebug = mapValid ? "Linking" : "Map missing, will attempt to re-map";
  90. debugOutput += $"Feature List Status({mapDebug}):\n";
  91. // Try fix missing references
  92. for (var i = 0; i < m_RendererFeatures?.Count; i++)
  93. {
  94. if (m_RendererFeatures[i] == null)
  95. {
  96. if (mapValid && m_RendererFeatureMap[i] != 0)
  97. {
  98. var localId = m_RendererFeatureMap[i];
  99. loadedAssets.TryGetValue(localId, out var asset);
  100. m_RendererFeatures[i] = (ScriptableRendererFeature)asset;
  101. }
  102. else
  103. {
  104. m_RendererFeatures[i] = (ScriptableRendererFeature)GetUnusedAsset(ref linkedIds, ref loadedAssets);
  105. }
  106. }
  107. debugOutput += m_RendererFeatures[i] != null ? $"-{i}:Linked\n" : $"-{i}:Missing\n";
  108. }
  109. if(UniversalRenderPipeline.asset.debugLevel != PipelineDebugLevel.Disabled)
  110. Debug.LogWarning(debugOutput);
  111. UpdateMap();
  112. if (!m_RendererFeatures.Contains(null)) return true;
  113. Debug.LogError($"{name} is missing RendererFeatures\nThis could be due to missing scripts or compile error.", this);
  114. return false;
  115. }
  116. private static object GetUnusedAsset(ref List<long> usedIds, ref Dictionary<long, object> assets)
  117. {
  118. foreach (var asset in assets)
  119. {
  120. var alreadyLinked = usedIds.Any(used => asset.Key == used);
  121. if (alreadyLinked) continue;
  122. usedIds.Add(asset.Key);
  123. return asset.Value;
  124. }
  125. return null;
  126. }
  127. private void UpdateMap()
  128. {
  129. if (m_RendererFeatureMap.Count != m_RendererFeatures.Count)
  130. {
  131. m_RendererFeatureMap.Clear();
  132. m_RendererFeatureMap.AddRange(new long[m_RendererFeatures.Count]);
  133. }
  134. for (var i = 0; i < rendererFeatures.Count; i++)
  135. {
  136. if(m_RendererFeatures[i] == null) continue;
  137. if (!AssetDatabase.TryGetGUIDAndLocalFileIdentifier(m_RendererFeatures[i], out var guid,
  138. out long localId)) continue;
  139. m_RendererFeatureMap[i] = localId;
  140. }
  141. }
  142. #endif
  143. }
  144. }