160 lines
6.0 KiB
C#
160 lines
6.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using UnityEngine.VFX;
|
|
|
|
namespace UnityEditor.VFX
|
|
{
|
|
class VFXUniformMapper
|
|
{
|
|
public VFXUniformMapper(VFXExpressionMapper mapper, bool filterOutConstants)
|
|
{
|
|
m_FilterOutConstants = filterOutConstants;
|
|
Init(mapper);
|
|
}
|
|
|
|
private void CollectAndAddUniforms(VFXExpression exp, IEnumerable<string> names, HashSet<VFXExpression> processedExp)
|
|
{
|
|
if (!exp.IsAny(VFXExpression.Flags.NotCompilableOnCPU))
|
|
{
|
|
string prefix;
|
|
Dictionary<VFXExpression, List<string>> expressions;
|
|
|
|
if (VFXExpression.IsUniform(exp.valueType))
|
|
{
|
|
if (m_FilterOutConstants && exp.Is(VFXExpression.Flags.Constant)) // Filter out constant uniform that should be patched directly in shader
|
|
return;
|
|
|
|
prefix = "uniform_";
|
|
expressions = m_UniformToName;
|
|
}
|
|
else if (VFXExpression.IsTexture(exp.valueType))
|
|
{
|
|
prefix = "texture_";
|
|
expressions = m_TextureToName;
|
|
}
|
|
else if (VFXExpression.IsBufferOnGPU(exp.valueType))
|
|
{
|
|
prefix = "buffer_";
|
|
expressions = m_BufferToName;
|
|
}
|
|
else
|
|
{
|
|
if (VFXExpression.IsTypeValidOnGPU(exp.valueType))
|
|
{
|
|
throw new InvalidOperationException(string.Format("Missing handling for type: {0}", exp.valueType));
|
|
}
|
|
return;
|
|
}
|
|
|
|
List<string> previousNames;
|
|
expressions.TryGetValue(exp, out previousNames);
|
|
|
|
if (previousNames == null)
|
|
{
|
|
previousNames = new List<string>();
|
|
expressions[exp] = previousNames;
|
|
}
|
|
|
|
if (names == null)
|
|
{
|
|
if (previousNames.Count == 0) // No need to generate a name if one was already generated
|
|
previousNames.Add(prefix + VFXCodeGeneratorHelper.GeneratePrefix(m_CurrentUniformIndex++));
|
|
}
|
|
else
|
|
previousNames.AddRange(names);
|
|
}
|
|
else
|
|
{
|
|
foreach (var parent in exp.parents)
|
|
{
|
|
if (processedExp.Contains(parent))
|
|
continue;
|
|
|
|
processedExp.Add(parent);
|
|
CollectAndAddUniforms(parent, null, processedExp);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Init(VFXExpressionMapper mapper)
|
|
{
|
|
m_UniformToName = new Dictionary<VFXExpression, List<string>>();
|
|
m_TextureToName = new Dictionary<VFXExpression, List<string>>();
|
|
m_BufferToName = new Dictionary<VFXExpression, List<string>>();
|
|
|
|
m_CurrentUniformIndex = 0;
|
|
|
|
var processedExp = new HashSet<VFXExpression>();
|
|
foreach (var exp in mapper.expressions)
|
|
{
|
|
processedExp.Clear();
|
|
var initialNames = mapper.GetData(exp).Select(d => d.fullName);
|
|
CollectAndAddUniforms(exp, initialNames, processedExp);
|
|
}
|
|
}
|
|
|
|
public IEnumerable<VFXExpression> uniforms { get { return m_UniformToName.Keys; } }
|
|
public IEnumerable<VFXExpression> textures { get { return m_TextureToName.Keys; } }
|
|
public IEnumerable<VFXExpression> buffers { get { return m_BufferToName.Keys; } }
|
|
|
|
// Get only the first name of a uniform (For generated code, we collapse all uniforms using the same expression into a single one)
|
|
public string GetName(VFXExpression exp)
|
|
{
|
|
return GetNames(exp).First();
|
|
}
|
|
|
|
public List<string> GetNames(VFXExpression exp)
|
|
{
|
|
if (VFXExpression.IsTexture(exp.valueType))
|
|
return m_TextureToName[exp];
|
|
|
|
if (VFXExpression.IsBufferOnGPU(exp.valueType))
|
|
return m_BufferToName[exp];
|
|
|
|
return m_UniformToName[exp];
|
|
}
|
|
|
|
// This retrieves expression to name with additional type conversion where suitable
|
|
public Dictionary<VFXExpression, string> expressionToCode
|
|
{
|
|
get
|
|
{
|
|
return m_UniformToName.Select(s =>
|
|
{
|
|
string code = null;
|
|
string firstName = s.Value.First();
|
|
switch (s.Key.valueType)
|
|
{
|
|
case VFXValueType.Int32:
|
|
code = "asint(" + firstName + ")";
|
|
break;
|
|
case VFXValueType.Uint32:
|
|
code = "asuint(" + firstName + ")";
|
|
break;
|
|
case VFXValueType.Boolean:
|
|
code = "(bool)asuint(" + firstName + ")";
|
|
break;
|
|
default:
|
|
code = firstName;
|
|
break;
|
|
}
|
|
|
|
return new KeyValuePair<VFXExpression, string>(s.Key, code);
|
|
})
|
|
.Union(m_TextureToName.Select(s => new KeyValuePair<VFXExpression, string>(s.Key, s.Value.First())))
|
|
.Union(m_BufferToName.Select(s => new KeyValuePair<VFXExpression, string>(s.Key, s.Value.First())))
|
|
.ToDictionary(s => s.Key, s => s.Value);
|
|
}
|
|
}
|
|
|
|
private Dictionary<VFXExpression, List<string>> m_UniformToName;
|
|
private Dictionary<VFXExpression, List<string>> m_TextureToName;
|
|
private Dictionary<VFXExpression, List<string>> m_BufferToName;
|
|
private uint m_CurrentUniformIndex;
|
|
private bool m_FilterOutConstants;
|
|
}
|
|
}
|