Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
GlobalUniformVisitor.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using SiliconStudio.Shaders.Ast;
6 using SiliconStudio.Shaders.Visitor;
7 
8 namespace SiliconStudio.Shaders.Convertor
9 {
10  /// <summary>
11  /// Collect a list of global uniforms that are used as global temporary variable.
12  /// </summary>
14  {
15  private List<Variable> uniformReadList;
16 
17  private Shader shader;
18 
19  /// <summary>
20  /// Initializes a new instance of the <see cref="GlobalUniformVisitor"/> class.
21  /// </summary>
22  /// <param name="shader">The shader.</param>
24  {
25  this.shader = shader;
26  uniformReadList = new List<Variable>();
27  this.UniformUsedWriteFirstList = new List<Variable>();
28  this.UniformReadWriteList = new List<Variable>();
29  }
30 
31  /// <summary>
32  /// Gets a list of uniform that are used as "write" variable first.
33  /// </summary>
34  public List<Variable> UniformUsedWriteFirstList { get; private set; }
35 
36  /// <summary>
37  /// Gets a list of uniform that are used as "read" and "write" variable.
38  /// </summary>
39  public List<Variable> UniformReadWriteList { get; private set; }
40 
41  public bool IsVariableAsGlobalTemporary(Variable variable)
42  {
43  return UniformUsedWriteFirstList.Contains(variable);
44  }
45 
46  public bool IsVariableAsGlobalTemporary(Expression expression)
47  {
48  var variable = GetUniform(expression);
49  if (variable == null)
50  return false;
51  return IsVariableAsGlobalTemporary(variable);
52  }
53 
54  public bool IsUniformReadWrite(Variable variable)
55  {
56  return UniformReadWriteList.Contains(variable);
57  }
58 
59  public bool IsUniformReadWrite(Expression expression)
60  {
61  var variable = GetUniform(expression);
62  if (variable == null)
63  return false;
64  return IsUniformReadWrite(variable);
65  }
66 
68  protected void Visit(VariableReferenceExpression variableRef)
69  {
70  var variable = GetUniform(variableRef);
71 
72  // If the variable is a global uniform, non static/const and is not already in the list used then
73  if (variable != null && !uniformReadList.Contains(variable))
74  {
75  uniformReadList.Add(variable);
76  }
77  }
78 
79  private Variable GetUniform(Expression expression)
80  {
81  VariableReferenceExpression variableRef = null;
82  while (expression != null)
83  {
84  if (expression is MemberReferenceExpression)
85  {
86  expression = ((MemberReferenceExpression)expression).Target;
87  }
88  else if (expression is IndexerExpression)
89  {
90  expression = ((IndexerExpression)expression).Target;
91  }
92  else
93  {
94  variableRef = expression as VariableReferenceExpression;
95  break;
96  }
97  }
98 
99  if (variableRef != null)
100  {
101  var variable = variableRef.TypeInference.Declaration as Variable;
102 
103  // If the variable is a global uniform, non static/const and is not already in the list used then
104  return (variable != null && shader.Declarations.Contains(variable) && !variable.Qualifiers.Contains(Ast.Hlsl.StorageQualifier.Static)
105  && !variable.Qualifiers.Contains(Ast.StorageQualifier.Const))
106  ? variable
107  : null;
108  }
109  return null;
110  }
111 
112  private int countReadBeforeInvoke;
113 
114  protected override void Visit(MethodInvocationExpression methodInvocationExpression)
115  {
116  // Save the number of variable in read-only mode
117  countReadBeforeInvoke = uniformReadList.Count;
118  base.Visit(methodInvocationExpression);
119  }
120 
122  {
123 
124  // Handle the case where a parameter can be out
125  // If this is the case, we need to check that
126  for (int i = 0; i < invoke.Arguments.Count; i++)
127  {
128  var arg = invoke.Arguments[i];
129  var variable = this.GetUniform(arg);
130  var parameter = method.Parameters[i];
131  if (variable != null && parameter.Qualifiers.Contains(Ast.Hlsl.ParameterQualifier.Out))
132  {
133  bool isUniformWasAlreadyUsedAsRead = false;
134  for (int j = 0; j < countReadBeforeInvoke; j++)
135  {
136  if (ReferenceEquals(uniformReadList[i], variable))
137  {
138  isUniformWasAlreadyUsedAsRead = true;
139  break;
140  }
141  }
142 
143  // If this is a out parameter, and the variable was not already used as a read, then
144  // we can remove it from the uniform read list
145  if (!isUniformWasAlreadyUsedAsRead)
146  {
147  uniformReadList.Remove(variable);
148  if (!UniformUsedWriteFirstList.Contains(variable))
149  UniformUsedWriteFirstList.Add(variable);
150  }
151  }
152  }
153 
154  this.VisitDynamic(method);
155  }
156 
158  protected void Visit(AssignmentExpression assignmentExpression)
159  {
160  var variable = GetUniform(assignmentExpression.Target);
161  bool isMemberExpression = assignmentExpression.Target is MemberReferenceExpression;
162  if (variable != null)
163  {
164  // Default == operator is the only write only operators
165  if (assignmentExpression.Operator == AssignmentOperator.Default && !uniformReadList.Contains(variable) && !this.UniformUsedWriteFirstList.Contains(variable))
166  {
167  // Handle the case where the assignment operator is partial like vect.xy = 5; and later vect.zw += 6;
168  // In this case, the variable is considered as read and write (and not only write first)
169  if (isMemberExpression)
170  {
171  var variableType = variable.Type.ResolveType();
172 
173  if (variableType is VectorType || variableType is MatrixType)
174  {
175  var dim = Math.Max(TypeBase.GetDimensionSize(variableType, 0), TypeBase.GetDimensionSize(variableType, 1));
176 
177  var memberRef = assignmentExpression.Target as MemberReferenceExpression;
178  var numberOfMembers = memberRef.Member.Text.Length;
179 
180  // If the variable is a global uniform, non static/const and is not already in the list used then
181  if (numberOfMembers < dim)
182  {
183  if (!uniformReadList.Contains(variable))
184  {
185  uniformReadList.Add(variable);
186  }
187  }
188  else
189  {
190  UniformUsedWriteFirstList.Add(variable);
191  }
192  }
193  }
194  else
195  {
196  UniformUsedWriteFirstList.Add(variable);
197  }
198  }
199  if (assignmentExpression.Operator != AssignmentOperator.Default)
200  {
201  if (!UniformReadWriteList.Contains(variable))
202  UniformReadWriteList.Add(variable);
203  }
204  }
205  }
206  }
207 }
Base class for all vector types
Definition: VectorType.cs:10
override void ProcessMethodInvocation(MethodInvocationExpression invoke, MethodDefinition method)
Tag a visitable method with this attribute.
Definition: VisitorBase.cs:295
void Visit(AssignmentExpression assignmentExpression)
Expression Target
Gets or sets the target receving the assigment.
AssignmentOperator
Assignment operator used in assignment expression (a = b) or statements (a = b;)
A method definition with a body of statements.
GlobalUniformVisitor(Shader shader)
Initializes a new instance of the GlobalUniformVisitor class.
override void Visit(MethodInvocationExpression methodInvocationExpression)
A variable declaration.
Definition: Variable.cs:11
A member reference in the form {this}.{Name}
Base type for all types.
Definition: TypeBase.cs:11
Toplevel container of a shader parsing result.
Definition: Shader.cs:12
static int GetDimensionSize(TypeBase typeDeclaration, int dimension)
Definition: TypeBase.cs:139
Collect a list of global uniforms that are used as global temporary variable.
void Visit(VariableReferenceExpression variableRef)
AssignmentOperator Operator
Gets or sets the operator.