VFXUniformMapper.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.Linq;
  5. using UnityEngine;
  6. using UnityEngine.VFX;
  7. namespace UnityEditor.VFX
  8. {
  9. class VFXUniformMapper
  10. {
  11. public VFXUniformMapper(VFXExpressionMapper mapper, bool filterOutConstants)
  12. {
  13. m_FilterOutConstants = filterOutConstants;
  14. Init(mapper);
  15. }
  16. private void CollectAndAddUniforms(VFXExpression exp, IEnumerable<string> names, HashSet<VFXExpression> processedExp)
  17. {
  18. if (!exp.IsAny(VFXExpression.Flags.NotCompilableOnCPU))
  19. {
  20. string prefix;
  21. Dictionary<VFXExpression, List<string>> expressions;
  22. if (VFXExpression.IsUniform(exp.valueType))
  23. {
  24. if (m_FilterOutConstants && exp.Is(VFXExpression.Flags.Constant)) // Filter out constant uniform that should be patched directly in shader
  25. return;
  26. prefix = "uniform_";
  27. expressions = m_UniformToName;
  28. }
  29. else if (VFXExpression.IsTexture(exp.valueType))
  30. {
  31. prefix = "texture_";
  32. expressions = m_TextureToName;
  33. }
  34. else if (VFXExpression.IsBufferOnGPU(exp.valueType))
  35. {
  36. prefix = "buffer_";
  37. expressions = m_BufferToName;
  38. }
  39. else
  40. {
  41. if (VFXExpression.IsTypeValidOnGPU(exp.valueType))
  42. {
  43. throw new InvalidOperationException(string.Format("Missing handling for type: {0}", exp.valueType));
  44. }
  45. return;
  46. }
  47. List<string> previousNames;
  48. expressions.TryGetValue(exp, out previousNames);
  49. if (previousNames == null)
  50. {
  51. previousNames = new List<string>();
  52. expressions[exp] = previousNames;
  53. }
  54. if (names == null)
  55. {
  56. if (previousNames.Count == 0) // No need to generate a name if one was already generated
  57. previousNames.Add(prefix + VFXCodeGeneratorHelper.GeneratePrefix(m_CurrentUniformIndex++));
  58. }
  59. else
  60. previousNames.AddRange(names);
  61. }
  62. else
  63. {
  64. foreach (var parent in exp.parents)
  65. {
  66. if (processedExp.Contains(parent))
  67. continue;
  68. processedExp.Add(parent);
  69. CollectAndAddUniforms(parent, null, processedExp);
  70. }
  71. }
  72. }
  73. private void Init(VFXExpressionMapper mapper)
  74. {
  75. m_UniformToName = new Dictionary<VFXExpression, List<string>>();
  76. m_TextureToName = new Dictionary<VFXExpression, List<string>>();
  77. m_BufferToName = new Dictionary<VFXExpression, List<string>>();
  78. m_CurrentUniformIndex = 0;
  79. var processedExp = new HashSet<VFXExpression>();
  80. foreach (var exp in mapper.expressions)
  81. {
  82. processedExp.Clear();
  83. var initialNames = mapper.GetData(exp).Select(d => d.fullName);
  84. CollectAndAddUniforms(exp, initialNames, processedExp);
  85. }
  86. }
  87. public IEnumerable<VFXExpression> uniforms { get { return m_UniformToName.Keys; } }
  88. public IEnumerable<VFXExpression> textures { get { return m_TextureToName.Keys; } }
  89. public IEnumerable<VFXExpression> buffers { get { return m_BufferToName.Keys; } }
  90. // Get only the first name of a uniform (For generated code, we collapse all uniforms using the same expression into a single one)
  91. public string GetName(VFXExpression exp)
  92. {
  93. return GetNames(exp).First();
  94. }
  95. public List<string> GetNames(VFXExpression exp)
  96. {
  97. if (VFXExpression.IsTexture(exp.valueType))
  98. return m_TextureToName[exp];
  99. if (VFXExpression.IsBufferOnGPU(exp.valueType))
  100. return m_BufferToName[exp];
  101. return m_UniformToName[exp];
  102. }
  103. // This retrieves expression to name with additional type conversion where suitable
  104. public Dictionary<VFXExpression, string> expressionToCode
  105. {
  106. get
  107. {
  108. return m_UniformToName.Select(s =>
  109. {
  110. string code = null;
  111. string firstName = s.Value.First();
  112. switch (s.Key.valueType)
  113. {
  114. case VFXValueType.Int32:
  115. code = "asint(" + firstName + ")";
  116. break;
  117. case VFXValueType.Uint32:
  118. code = "asuint(" + firstName + ")";
  119. break;
  120. case VFXValueType.Boolean:
  121. code = "(bool)asuint(" + firstName + ")";
  122. break;
  123. default:
  124. code = firstName;
  125. break;
  126. }
  127. return new KeyValuePair<VFXExpression, string>(s.Key, code);
  128. })
  129. .Union(m_TextureToName.Select(s => new KeyValuePair<VFXExpression, string>(s.Key, s.Value.First())))
  130. .Union(m_BufferToName.Select(s => new KeyValuePair<VFXExpression, string>(s.Key, s.Value.First())))
  131. .ToDictionary(s => s.Key, s => s.Value);
  132. }
  133. }
  134. private Dictionary<VFXExpression, List<string>> m_UniformToName;
  135. private Dictionary<VFXExpression, List<string>> m_TextureToName;
  136. private Dictionary<VFXExpression, List<string>> m_BufferToName;
  137. private uint m_CurrentUniformIndex;
  138. private bool m_FilterOutConstants;
  139. }
  140. }