A game about forced loneliness, made by TACStudios
at master 12 kB view raw
1using System; 2using System.Collections.Generic; 3using UnityEngine; 4 5namespace UnityEditor.ShaderGraph.Internal 6{ 7 [Serializable] 8 public abstract class AbstractShaderProperty : ShaderInput 9 { 10 public abstract PropertyType propertyType { get; } 11 12 internal override ConcreteSlotValueType concreteShaderValueType => propertyType.ToConcreteShaderValueType(); 13 14 // user selected precision setting 15 [SerializeField] 16 Precision m_Precision = Precision.Inherit; 17 18 [Obsolete("AbstractShaderProperty.gpuInstanced is no longer used")] 19 public bool gpuInstanced 20 { 21 get { return false; } 22 set { } 23 } 24 25 internal virtual string GetHLSLVariableName(bool isSubgraphProperty, GenerationMode mode) 26 { 27 if (mode == GenerationMode.VFX) 28 { 29 // Per-element exposed properties are provided by the properties structure filled by VFX. 30 if (overrideHLSLDeclaration && hlslDeclarationOverride != HLSLDeclaration.Global) 31 return $"PROP.{referenceName}"; 32 // For un-exposed global properties, just read from the cbuffer. 33 else 34 return referenceName; 35 } 36 37 return referenceName; 38 } 39 40 internal string GetConnectionStateHLSLVariableName() 41 { 42 return GetConnectionStateVariableName(referenceName + "_" + objectId); 43 } 44 45 // NOTE: this does not tell you the HLSLDeclaration of the entire property... 46 // instead, it tells you what the DEFAULT HLSL Declaration would be, IF the property makes use of the default 47 // to check ACTUAL HLSL Declaration types, enumerate the HLSL Properties and check their HLSLDeclarations... 48 internal virtual HLSLDeclaration GetDefaultHLSLDeclaration() 49 { 50 if (overrideHLSLDeclaration) 51 return hlslDeclarationOverride; 52 // default Behavior switches between UnityPerMaterial and Global based on Exposed checkbox 53 if (generatePropertyBlock) 54 return HLSLDeclaration.UnityPerMaterial; 55 else 56 return HLSLDeclaration.Global; 57 } 58 59 // by default we disallow UI from choosing "DoNotDeclare" 60 // it needs a bit more UI support to disable property node output slots before we make it public 61 internal virtual bool AllowHLSLDeclaration(HLSLDeclaration decl) => (decl != HLSLDeclaration.DoNotDeclare); 62 63 [SerializeField] 64 internal bool overrideHLSLDeclaration = false; 65 66 [SerializeField] 67 internal HLSLDeclaration hlslDeclarationOverride; 68 69 override internal bool isExposed => base.isExposed && shouldForceExposed; 70 71 internal bool shouldForceExposed => (hlslDeclarationOverride == HLSLDeclaration.HybridPerInstance || GetDefaultHLSLDeclaration() == HLSLDeclaration.UnityPerMaterial) && isExposable; 72 73 internal Precision precision 74 { 75 get => m_Precision; 76 set => m_Precision = value; 77 } 78 79 ConcretePrecision m_ConcretePrecision = ConcretePrecision.Single; 80 public ConcretePrecision concretePrecision => m_ConcretePrecision; 81 internal void SetupConcretePrecision(ConcretePrecision defaultPrecision) 82 { 83 m_ConcretePrecision = precision.ToConcrete(defaultPrecision, defaultPrecision); 84 } 85 86 [SerializeField] 87 bool m_Hidden = false; 88 public bool hidden 89 { 90 get => m_Hidden; 91 set => m_Hidden = value; 92 } 93 94 internal string hideTagString => hidden || (shouldForceExposed && !isExposed) ? "[HideInInspector]" : ""; 95 96 // reference names are the HLSL declaration name / property block ref name 97 internal virtual void GetPropertyReferenceNames(List<string> result) 98 { 99 result.Add(referenceName); 100 } 101 102 // display names are used as the UI name in the property block / show up in the Material Inspector 103 internal virtual void GetPropertyDisplayNames(List<string> result) 104 { 105 result.Add(displayName); 106 } 107 108 // the simple interface for simple properties 109 internal virtual string GetPropertyBlockString() 110 { 111 return string.Empty; 112 } 113 114 internal bool shouldGeneratePropertyBlock => (generatePropertyBlock || shouldForceExposed) 115 && GetDefaultHLSLDeclaration() != HLSLDeclaration.Global; 116 117 // the more complex interface for complex properties (defaulted for simple properties) 118 internal virtual void AppendPropertyBlockStrings(ShaderStringBuilder builder) 119 { 120 builder.AppendLine(GetPropertyBlockString()); 121 } 122 123 internal abstract void ForeachHLSLProperty(Action<HLSLProperty> action); 124 125 internal virtual string GetPropertyAsArgumentStringForVFX(string precisionString) 126 { 127 return GetPropertyAsArgumentString(precisionString); 128 } 129 130 internal abstract string GetPropertyAsArgumentString(string precisionString); 131 internal abstract AbstractMaterialNode ToConcreteNode(); 132 internal abstract PreviewProperty GetPreviewMaterialProperty(); 133 134 public virtual string GetPropertyTypeString() 135 { 136 var typeString = propertyType.ToString(); 137 if (sgVersion < latestVersion) 138 typeString = $"{typeString} (Legacy v{sgVersion})"; 139 return typeString; 140 } 141 } 142 143 [Serializable] 144 public abstract class AbstractShaderProperty<T> : AbstractShaderProperty 145 { 146 [SerializeField] 147 T m_Value; 148 149 public virtual T value 150 { 151 get => m_Value; 152 set => m_Value = value; 153 } 154 } 155 156 // class for extracting deprecated data from older versions of AbstractShaderProperty 157 class LegacyShaderPropertyData 158 { 159 // indicates user wishes to support the HYBRID renderer GPU instanced path 160 [SerializeField] 161 public bool m_GPUInstanced = false; 162 163 // converts the old m_GPUInstanced data into the new override HLSLDeclaration system. 164 public static void UpgradeToHLSLDeclarationOverride(string json, AbstractShaderProperty property) 165 { 166 // this maintains the old behavior for versioned properties: 167 // old exposed GPUInstanced properties are declared hybrid (becomes override in new system) 168 // old unexposed GPUInstanced properties are declared global (becomes override in new system) 169 // old exposed properties are declared UnityPerMaterial (default behavior, no override necessary) 170 // old unexposed properties are declared Global (default behavior, no override necessary) 171 // moving forward, users can use the overrides directly to control what it does 172 173 var legacyShaderPropertyData = new LegacyShaderPropertyData(); 174 JsonUtility.FromJsonOverwrite(json, legacyShaderPropertyData); 175 if (legacyShaderPropertyData.m_GPUInstanced) 176 { 177 property.overrideHLSLDeclaration = true; 178 if (property.generatePropertyBlock) 179 property.hlslDeclarationOverride = HLSLDeclaration.HybridPerInstance; 180 else 181 property.hlslDeclarationOverride = HLSLDeclaration.Global; 182 } 183 } 184 } 185 186 public enum HLSLType 187 { 188 // value types 189 _float, 190 _float2, 191 _float3, 192 _float4, 193 _matrix4x4, 194 195 // object types 196 FirstObjectType, 197 _Texture2D = FirstObjectType, 198 _Texture3D, 199 _TextureCube, 200 _Texture2DArray, 201 _SamplerState, 202 203 // custom type 204 _CUSTOM 205 } 206 207 // describes the different ways we can generate HLSL declarations 208 [Flags] 209 internal enum HLSLDeclaration 210 { 211 DoNotDeclare, // NOT declared in HLSL 212 Global, // declared in the global scope, mainly for use with state coming from Shader.SetGlobal*() 213 UnityPerMaterial, // declared in the UnityPerMaterial cbuffer, populated by Material or MaterialPropertyBlock 214 HybridPerInstance, // declared using HybridRenderer path (v1 or v2) to get DOTS GPU instancing 215 } 216 217 internal struct HLSLProperty 218 { 219 public string name; 220 public HLSLType type; 221 public ConcretePrecision precision; 222 public HLSLDeclaration declaration; 223 public Action<ShaderStringBuilder> customDeclaration; 224 225 public HLSLProperty(HLSLType type, string name, HLSLDeclaration declaration, ConcretePrecision precision = ConcretePrecision.Single) 226 { 227 this.type = type; 228 this.name = name; 229 this.declaration = declaration; 230 this.precision = precision; 231 this.customDeclaration = null; 232 } 233 234 public bool ValueEquals(HLSLProperty other) 235 { 236 if ((name != other.name) || 237 (type != other.type) || 238 (precision != other.precision) || 239 (declaration != other.declaration) || 240 ((customDeclaration == null) != (other.customDeclaration == null))) 241 { 242 return false; 243 } 244 else if (customDeclaration != null) 245 { 246 var ssb = new ShaderStringBuilder(); 247 var ssbother = new ShaderStringBuilder(); 248 customDeclaration(ssb); 249 other.customDeclaration(ssbother); 250 if (ssb.ToCodeBlock() != ssbother.ToCodeBlock()) 251 return false; 252 } 253 return true; 254 } 255 256 static string[,] kValueTypeStrings = new string[(int)HLSLType.FirstObjectType, 2] 257 { 258 {"float", "half"}, 259 {"float2", "half2"}, 260 {"float3", "half3"}, 261 {"float4", "half4"}, 262 {"float4x4", "half4x4"} 263 }; 264 265 static string[] kObjectTypeStrings = new string[(int)HLSLType._CUSTOM - (int)HLSLType.FirstObjectType] 266 { 267 "TEXTURE2D", 268 "TEXTURE3D", 269 "TEXTURECUBE", 270 "TEXTURE2D_ARRAY", 271 "SAMPLER", 272 }; 273 274 public bool IsObjectType() 275 { 276 return type == HLSLType._SamplerState || 277 type == HLSLType._Texture2D || 278 type == HLSLType._Texture3D || 279 type == HLSLType._TextureCube || 280 type == HLSLType._Texture2DArray || 281 type == HLSLType._CUSTOM; 282 } 283 284 public string GetValueTypeString() 285 { 286 if (type < HLSLType.FirstObjectType) 287 return kValueTypeStrings[(int)type, (int)precision]; 288 return null; 289 } 290 291 public void AppendTo(ShaderStringBuilder ssb, Func<string, string> nameModifier = null) 292 { 293 var mName = nameModifier?.Invoke(name) ?? name; 294 295 if (type < HLSLType.FirstObjectType) 296 { 297 ssb.Append(kValueTypeStrings[(int)type, (int)precision]); 298 ssb.Append(" "); 299 ssb.Append(mName); 300 ssb.Append(";"); 301 } 302 else if (type < HLSLType._CUSTOM) 303 { 304 ssb.Append(kObjectTypeStrings[type - HLSLType.FirstObjectType]); 305 ssb.Append("("); 306 ssb.Append(mName); 307 ssb.Append(");"); 308 } 309 else 310 { 311 customDeclaration(ssb); 312 } 313 //ssb.Append(" // "); 314 //ssb.Append(declaration.ToString()); 315 ssb.AppendNewLine(); 316 } 317 } 318}