123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- using System;
- using System.Collections.Generic;
- using System.Reflection;
- #if UNITY_EDITOR
- using System.Linq;
- using UnityEditor;
- #endif
- namespace UnityEngine.Rendering.Universal
- {
- /// <summary>
- /// Class <c>ScriptableRendererData</c> contains resources for a <c>ScriptableRenderer</c>.
- /// <seealso cref="ScriptableRenderer"/>
- /// </summary>
- public abstract class ScriptableRendererData : ScriptableObject
- {
- internal bool isInvalidated { get; set; }
- /// <summary>
- /// Class contains references to shader resources used by Rendering Debugger.
- /// </summary>
- [Serializable, ReloadGroup]
- public sealed class DebugShaderResources
- {
- /// <summary>
- /// Debug shader used to output interpolated vertex attributes.
- /// </summary>
- [Reload("Shaders/Debug/DebugReplacement.shader")]
- public Shader debugReplacementPS;
- }
- /// <summary>
- /// Container for shader resources used by Rendering Debugger.
- /// </summary>
- public DebugShaderResources debugShaders;
- /// <summary>
- /// Creates the instance of the ScriptableRenderer.
- /// </summary>
- /// <returns>The instance of ScriptableRenderer</returns>
- protected abstract ScriptableRenderer Create();
- [SerializeField] internal List<ScriptableRendererFeature> m_RendererFeatures = new List<ScriptableRendererFeature>(10);
- [SerializeField] internal List<long> m_RendererFeatureMap = new List<long>(10);
- [SerializeField] bool m_UseNativeRenderPass = false;
- /// <summary>
- /// List of additional render pass features for this renderer.
- /// </summary>
- public List<ScriptableRendererFeature> rendererFeatures
- {
- get => m_RendererFeatures;
- }
- /// <summary>
- /// Use SetDirty when changing seeings in the ScriptableRendererData.
- /// It will rebuild the render passes with the new data.
- /// </summary>
- public new void SetDirty()
- {
- isInvalidated = true;
- }
- internal ScriptableRenderer InternalCreateRenderer()
- {
- isInvalidated = false;
- return Create();
- }
- protected virtual void OnValidate()
- {
- SetDirty();
- #if UNITY_EDITOR
- if (m_RendererFeatures.Contains(null))
- ValidateRendererFeatures();
- #endif
- }
- protected virtual void OnEnable()
- {
- SetDirty();
- }
- public bool useNativeRenderPass
- {
- get => m_UseNativeRenderPass;
- set
- {
- SetDirty();
- m_UseNativeRenderPass = value;
- }
- }
- /// <summary>
- /// Returns true if contains renderer feature with specified type.
- /// </summary>
- /// <typeparam name="T">Renderer Feature type.</typeparam>
- /// <returns></returns>
- internal bool TryGetRendererFeature<T>(out T rendererFeature) where T : ScriptableRendererFeature
- {
- foreach (var target in rendererFeatures)
- {
- if (target.GetType() == typeof(T))
- {
- rendererFeature = target as T;
- return true;
- }
- }
- rendererFeature = null;
- return false;
- }
- #if UNITY_EDITOR
- internal virtual Material GetDefaultMaterial(DefaultMaterialType materialType)
- {
- return null;
- }
- internal virtual Shader GetDefaultShader()
- {
- return null;
- }
- internal bool ValidateRendererFeatures()
- {
- // Get all Subassets
- var subassets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(this));
- var linkedIds = new List<long>();
- var loadedAssets = new Dictionary<long, object>();
- var mapValid = m_RendererFeatureMap != null && m_RendererFeatureMap?.Count == m_RendererFeatures?.Count;
- var debugOutput = $"{name}\nValid Sub-assets:\n";
- // Collect valid, compiled sub-assets
- foreach (var asset in subassets)
- {
- if (asset == null || asset.GetType().BaseType != typeof(ScriptableRendererFeature)) continue;
- AssetDatabase.TryGetGUIDAndLocalFileIdentifier(asset, out var guid, out long localId);
- loadedAssets.Add(localId, asset);
- debugOutput += $"-{asset.name}\n--localId={localId}\n";
- }
- // Collect assets that are connected to the list
- for (var i = 0; i < m_RendererFeatures?.Count; i++)
- {
- if (!m_RendererFeatures[i]) continue;
- if (AssetDatabase.TryGetGUIDAndLocalFileIdentifier(m_RendererFeatures[i], out var guid, out long localId))
- {
- linkedIds.Add(localId);
- }
- }
- var mapDebug = mapValid ? "Linking" : "Map missing, will attempt to re-map";
- debugOutput += $"Feature List Status({mapDebug}):\n";
- // Try fix missing references
- for (var i = 0; i < m_RendererFeatures?.Count; i++)
- {
- if (m_RendererFeatures[i] == null)
- {
- if (mapValid && m_RendererFeatureMap[i] != 0)
- {
- var localId = m_RendererFeatureMap[i];
- loadedAssets.TryGetValue(localId, out var asset);
- m_RendererFeatures[i] = (ScriptableRendererFeature)asset;
- }
- else
- {
- m_RendererFeatures[i] = (ScriptableRendererFeature)GetUnusedAsset(ref linkedIds, ref loadedAssets);
- }
- }
- debugOutput += m_RendererFeatures[i] != null ? $"-{i}:Linked\n" : $"-{i}:Missing\n";
- }
- UpdateMap();
- if (!m_RendererFeatures.Contains(null))
- return true;
- Debug.LogError($"{name} is missing RendererFeatures\nThis could be due to missing scripts or compile error.", this);
- return false;
- }
- internal bool DuplicateFeatureCheck(Type type)
- {
- var isSingleFeature = type.GetCustomAttribute(typeof(DisallowMultipleRendererFeature));
- return isSingleFeature != null && m_RendererFeatures.Select(renderFeature => renderFeature.GetType()).Any(t => t == type);
- }
- private static object GetUnusedAsset(ref List<long> usedIds, ref Dictionary<long, object> assets)
- {
- foreach (var asset in assets)
- {
- var alreadyLinked = usedIds.Any(used => asset.Key == used);
- if (alreadyLinked)
- continue;
- usedIds.Add(asset.Key);
- return asset.Value;
- }
- return null;
- }
- private void UpdateMap()
- {
- if (m_RendererFeatureMap.Count != m_RendererFeatures.Count)
- {
- m_RendererFeatureMap.Clear();
- m_RendererFeatureMap.AddRange(new long[m_RendererFeatures.Count]);
- }
- for (int i = 0; i < rendererFeatures.Count; i++)
- {
- if (m_RendererFeatures[i] == null) continue;
- if (!AssetDatabase.TryGetGUIDAndLocalFileIdentifier(m_RendererFeatures[i], out var guid, out long localId)) continue;
- m_RendererFeatureMap[i] = localId;
- }
- }
- #endif
- }
- }
|