4 using System.Collections.Generic;
5 using System.Globalization;
8 using SiliconStudio.Shaders.Analysis;
9 using SiliconStudio.Shaders.Analysis.Hlsl;
10 using SiliconStudio.Shaders.Ast;
11 using SiliconStudio.Shaders.Ast.Glsl;
12 using SiliconStudio.Shaders.Ast.Hlsl;
13 using SiliconStudio.Shaders.Parser;
14 using SiliconStudio.Shaders.Utility;
15 using SiliconStudio.Shaders.Visitor;
16 using SiliconStudio.Shaders.Writer.Hlsl;
21 namespace SiliconStudio.Shaders.Convertor
36 #region Constants and Fields
38 private const string TagLayoutKey =
"LAYOUT";
39 private const string VertexIOInterfaceName =
"_VertexIO_";
41 private const string gl_FrontFacing =
"gl_FrontFacing";
43 private static readonly List<string> SemanticModifiers =
new List<string> {
"_centroid",
"_pp",
"_sat" };
45 private readonly
bool[] allocatedRegistersForSamplers =
new bool[16];
47 private readonly
bool[] allocatedRegistersForUniforms =
new bool[256];
49 private readonly Dictionary<string, string> builtinGeometryInputs;
51 private readonly Dictionary<string, string> builtinGeometryOutputs;
53 private readonly Dictionary<string, string> builtinPixelInputs;
55 private readonly Dictionary<string, string> builtinPixelOutputs;
57 private readonly Dictionary<string, string> builtinVertexInputs;
59 private readonly Dictionary<string, string> builtinVertexOutputs;
61 private readonly Dictionary<string, TypeBase> builtinGlslTypes;
63 private readonly List<Variable> declarationListToRemove =
new List<Variable>();
65 private readonly
string entryPointName;
67 private readonly Dictionary<string, string> functionMapping;
69 private readonly Dictionary<Variable, Variable> inputAssignment =
new Dictionary<Variable, Variable>(
new ReferenceEqualityComparer<Variable>());
71 private readonly List<Variable> listOfMultidimensionArrayVariable =
new List<Variable>();
73 private readonly Dictionary<MethodInvocationExpression, bool> methodInvocationHandled =
new Dictionary<MethodInvocationExpression, bool>(
new ReferenceEqualityComparer<MethodInvocationExpression>());
79 private readonly Dictionary<SamplerTextureKey, Variable> samplerMapping =
new Dictionary<SamplerTextureKey, Variable>();
83 private string geometryLayoutInput;
87 private string geometryLayoutOutput;
89 private List<Variable> inputs =
new List<Variable>();
91 private bool isAssignmentTarget;
93 private List<Variable> outputs =
new List<Variable>();
101 private bool isPixelShaderOutputFragDataMuliType =
false;
103 private int breakIndex = 0;
107 #region Constructors and Destructors
119 this.entryPointName = entryPointName;
120 this.pipelineStage = pipelineStage;
121 this.shaderModel = shaderModel;
122 this.VariableLayouts =
new Dictionary<string, VariableLayoutRule>();
123 this.ConstantBufferLayouts =
new Dictionary<string, ConstantBufferLayoutRule>();
124 this.MapRules =
new Dictionary<string, MapRule>();
125 this.KeepConstantBuffer =
true;
127 if (useBuiltinSemantic)
129 builtinVertexInputs =
new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase) { {
"SV_VertexID",
"gl_VertexID" }, {
"SV_InstanceID",
"gl_InstanceID" }, };
131 builtinVertexOutputs =
new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
132 builtinGeometryInputs =
new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
133 builtinGeometryOutputs =
new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
134 builtinPixelInputs =
new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
135 builtinPixelOutputs =
new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
140 builtinVertexOutputs.Add(
"POSITION",
"gl_Position");
141 builtinVertexOutputs.Add(
"PSIZE",
"gl_PointSize");
143 builtinGeometryInputs.Add(
"PSIZE",
"gl_PointSize");
145 builtinGeometryOutputs.Add(
"PSIZE",
"gl_PointSize");
147 builtinPixelInputs.Add(
"VPOS",
"gl_FragCoord");
148 builtinPixelInputs.Add(
"VFACE", gl_FrontFacing);
149 builtinPixelInputs.Add(
"POSITION",
"gl_FragCoord");
151 builtinPixelOutputs.Add(
"DEPTH",
"gl_FragDepth");
152 builtinPixelOutputs.Add(
"COLOR",
"gl_FragData[]");
156 builtinVertexOutputs.Add(
"SV_Position",
"gl_Position");
157 builtinVertexOutputs.Add(
"SV_ClipDistance",
"gl_ClipDistance[]");
159 builtinGeometryInputs.Add(
"SV_POSITION",
"gl_Position");
160 builtinGeometryInputs.Add(
"SV_ClipDistance",
"gl_ClipDistance[]");
161 builtinGeometryInputs.Add(
"SV_PrimitiveID",
"gl_PrimitiveIDIn");
163 builtinGeometryOutputs.Add(
"SV_POSITION",
"gl_Position");
164 builtinGeometryOutputs.Add(
"SV_ClipDistance",
"gl_ClipDistance[]");
165 builtinGeometryOutputs.Add(
"SV_RenderTargetArrayIndex",
"gl_Layer");
167 builtinPixelInputs.Add(
"SV_Position",
"gl_FragCoord");
168 builtinPixelInputs.Add(
"SV_IsFrontFace",
"gl_FrontFacing");
169 builtinPixelInputs.Add(
"SV_ClipDistance",
"gl_ClipDistance[]");
171 builtinPixelOutputs.Add(
"SV_Depth",
"gl_FragDepth");
172 builtinPixelOutputs.Add(
"SV_Target",
"gl_FragData[]");
175 builtinGlslTypes =
new Dictionary<string, TypeBase>(StringComparer.CurrentCultureIgnoreCase)
177 {
"gl_ClipDistance", ScalarType.Float},
178 {
"gl_FragCoord", VectorType.Float4},
179 {
"gl_FragDepth", ScalarType.Float},
180 {
"gl_FragColor", VectorType.Float4},
181 {
"gl_FragData", VectorType.Float4},
182 {
"gl_FrontFacing", ScalarType.Bool},
183 {
"gl_InstanceID", ScalarType.Int },
184 {
"gl_InvocationID", ScalarType.Int},
185 {
"gl_Layer", ScalarType.Int},
186 {
"gl_NumSamples", ScalarType.Int},
187 {
"gl_PatchVerticesIn", ScalarType.Int},
188 {
"gl_PointCoord", VectorType.Float2},
189 {
"gl_PointSize", ScalarType.Float},
190 {
"gl_Position", VectorType.Float4},
191 {
"gl_PrimitiveID", ScalarType.Int},
192 {
"gl_PrimitiveIDIn", ScalarType.Int},
193 {
"gl_SampleID", ScalarType.Int},
194 {
"gl_SampleMask", ScalarType.Int},
195 {
"gl_SampleMaskIn", ScalarType.Int},
196 {
"gl_SamplePosition", VectorType.Float2},
197 {
"gl_TessCoord", VectorType.Float3},
198 {
"gl_VertexID", ScalarType.Int},
199 {
"gl_ViewportIndex", ScalarType.Int},
203 functionMapping =
new Dictionary<string, string> {
209 {
"rsqrt",
"inversesqrt" },
211 {
"saturate",
"clamp" },
218 #region Public Properties
223 public bool ViewFrustumRemap {
get; set; }
231 public bool IsPointSpriteShader {
get; set; }
239 public bool NoSwapForBinaryMatrixOperation {
get; set; }
247 public bool UseBindingLayout {
get; set; }
255 public bool UseBuiltinSemantic {
get; set; }
263 public bool UseLocationLayout {
get; set; }
268 public bool UseOnlyTextureName {
get; set; }
276 public bool UseSemanticForVariable {
get; set; }
284 public bool UseSemanticForLocation {
get; set; }
290 public bool UseInterfaceForInOut {
get; set; }
298 public Dictionary<string, VariableLayoutRule> VariableLayouts {
get;
private set; }
306 public Dictionary<string, ConstantBufferLayoutRule> ConstantBufferLayouts {
get;
private set; }
314 public Dictionary<string, MapRule> MapRules {
get;
private set; }
322 public bool KeepUniformArrayInitializers {
get; set; }
331 public bool TextureFunctionsCompatibilityProfile {
get; set; }
336 public bool KeepConstantBuffer {
get; set; }
341 public bool KeepNonUniformArrayInitializers {
get; set; }
346 public bool UnrollForLoops {
get; set; }
366 private bool IsInEntryPoint {
get {
return CurrentFunction != null && CurrentFunction.Name.Text == entryPointName; } }
370 #region Public Methods and Operators
391 if (typeBase != null)
393 var vectorType = typeBase.ResolveType() as
VectorType;
394 if (vectorType != null)
396 var subType = vectorType.Type.ResolveType();
398 typeBase.TypeInference.TargetType = TypeBase.CreateWithBaseType(vectorType, ScalarType.Float);
412 parserResult = parserResultIn;
413 shader = parserResultIn.Shader;
420 entryPoint = shader.Declarations.OfType<
MethodDefinition>().FirstOrDefault(x => x.Name.Text == entryPointName);
422 if (entryPoint == null)
423 throw new ArgumentException(
string.Format(
"Could not find entry point named {0}", entryPointName));
426 TransformGlobalMultipleVariableToSingleVariable();
430 this.GenerateSamplerMappingAndStrip();
434 globalUniformVisitor.Run((MethodDefinition)entryPoint);
437 writer.Visit(shader);
438 var text = writer.Text;
447 RemoveDefaultParametersForMethods();
450 TranformToGlslTypes();
453 RenameGlslKeywords();
456 RebindVariableReferenceExpressions();
459 var declarations = shader.Declarations.Where(declaration => !(declaration is
MethodDeclaration)).ToList();
461 shader.Declarations = declarations;
478 var isInMethod = !shader.Declarations.Contains(variable);
483 if (CurrentFunction != null && variable.
Qualifiers.
Contains(Ast.Hlsl.StorageQualifier.Static))
491 Visit((
Node)variable);
494 if (variable.Type.TypeInference.Declaration is
Typedef)
496 var typeDefType = variable.Type.ResolveType();
503 variable.Type = typeDefType;
519 for (
int i = 0; i < arrayInit.Arguments.Count; ++i)
522 statements.Add(statement);
526 variable.InitialValue = null;
531 else if (!isInMethod && !IsUniformLike(variable))
533 variable.InitialValue = null;
549 CurrentFunction =
function;
553 foreach (var arg
in function.Parameters)
555 if (arg.Qualifiers.Contains(Ast.ParameterQualifier.Out) && arg.Qualifiers.Contains(Ast.ParameterQualifier.In))
557 arg.Qualifiers.Values.Remove(Ast.ParameterQualifier.Out);
558 arg.Qualifiers.Values.Remove(Ast.ParameterQualifier.In);
559 arg.Qualifiers.Values.Add(Ast.ParameterQualifier.InOut);
563 if (
function == entryPoint)
564 PrepareVisitEntryPoint(
function);
566 function.Qualifiers.Values.Clear();
570 Visit((
Node)
function);
573 if (
function == entryPoint)
574 PostVisitEntryPoint(
function);
577 foreach (var modifier
in function.Parameters.Select(variable => variable.Qualifiers).Where(modifier => modifier.Contains(Ast.StorageQualifier.Uniform)))
578 modifier.Values.Remove(Ast.StorageQualifier.Uniform);
581 RemoveStreamTypeFromMethodDefinition(
function);
584 CurrentFunction = null;
598 foreach (var arg
in function.Parameters)
600 if (arg.Qualifiers.Contains(Ast.ParameterQualifier.Out) || arg.Qualifiers.Contains(Ast.ParameterQualifier.InOut))
609 foreach (var qualifier
in arg.Qualifiers.OfType<Ast.ParameterQualifier>())
611 switch ((
string)qualifier.Key)
614 geometryLayoutInput =
"triangles_adjacency";
617 geometryLayoutInput =
"triangles";
620 geometryLayoutInput =
"lines_adjacency";
623 geometryLayoutInput =
"lines";
626 geometryLayoutInput =
"points";
630 if (geometryLayoutInput != null)
632 geometryInputParameter = arg;
647 int countDifferentType = 0;
649 foreach (var output
in outputs)
651 var outputType = output.Type.ResolveType();
652 if (outputType is StructType)
654 countDifferentType += GetMembers((StructType)outputType).Select(fieldRef => fieldRef.Field).Count(field => this.CheckFragDataOutputType(field.Semantic(), field.Type.ResolveType()));
658 if (CheckFragDataOutputType(output.Semantic(), outputType))
659 countDifferentType++;
663 var returnType = function.ReturnType.ResolveType();
664 var returnStructType = returnType as StructType;
665 if (returnStructType != null)
667 countDifferentType += GetMembers(returnStructType).Select(fieldRef => fieldRef.Field).Count(field => this.CheckFragDataOutputType(field.Semantic(), field.Type.ResolveType()));
669 else if (
function.
Semantic() != null)
671 if (CheckFragDataOutputType(
function.
Semantic(), returnType))
672 countDifferentType++;
675 isPixelShaderOutputFragDataMuliType = countDifferentType > 0;
681 if (inputSemantic == null)
685 int semanticIndex = 0;
686 var semantic = ResolveSemantic(inputSemantic, type,
false,
"tmptmp", out newFieldType, out semanticIndex, inputSemantic.
Span);
687 if (semantic.Name.Text.StartsWith(
"gl_fragdata", StringComparison.InvariantCultureIgnoreCase) && (newFieldType != type || type is
ArrayType))
710 int inputSemanticLocation = 0;
711 int outputSemanticLocation = 0;
714 foreach (var variable
in this.inputs)
716 var structType = variable.Type.ResolveType() as StructType;
717 if (structType != null)
719 bool semanticFound =
false;
720 foreach (var fieldRef
in GetMembers(structType))
722 var field = fieldRef.Field;
724 var semantic = field.Semantic();
725 if (semantic != null)
727 var fieldType = field.Type.ResolveType();
728 var variableFromSemantic = this.BindLocation(semantic, fieldType,
true, fieldRef.FieldNamePath, ref inputSemanticLocation, variable.Span);
733 function.Body.Insert(
738 this.CastSemanticToReferenceType(variableFromSemantic.Name, fieldType, variableFromSemantic))) { Span = variable.Span });
739 semanticFound =
true;
746 variable.Qualifiers = Qualifier.None;
747 function.Body.Statements.Insert(0,
new DeclarationStatement(variable) { Span = variable.Span });
752 var semantic = variable.Semantic();
753 if (semantic != null)
754 this.BindLocation(semantic, variable.Type.ResolveType(),
true, variable.Name, ref inputSemanticLocation, variable.Span);
759 foreach (var variable
in this.outputs)
761 var structType = variable.Type.ResolveType() as StructType;
762 if (structType != null)
765 variable.Qualifiers = Qualifier.None;
770 var lastStatement = function.Body.Statements.LastOrDefault();
772 ReturnStruct(structType,
new VariableReferenceExpression(variable.Name) { Span = lastStatement != null ? lastStatement.Span : new SourceSpan() }, statementList);
774 function.Body.Statements.Add(statementList);
779 var returnType = function.ReturnType.ResolveType();
780 var returnStructType = returnType as StructType;
781 if (returnStructType != null)
783 foreach (var fieldRef
in GetMembers(returnStructType))
785 var field = fieldRef.Field;
786 BindLocation(field.Semantic(), field.Type.ResolveType(),
false, field.Name, ref outputSemanticLocation,
function.ReturnType.Span);
789 else if (
function.
Semantic() != null)
791 var semantic = function.Semantic();
792 BindLocation(semantic, returnType,
false, null, ref outputSemanticLocation, semantic.Span);
798 foreach (var variable
in shader.Declarations.OfType<
Variable>())
800 if (variable.Qualifiers.Contains(Ast.ParameterQualifier.Out))
802 BindLocation(variable.Semantic(), variable.Type.ResolveType(),
false, variable.Name, ref outputSemanticLocation, variable.Span);
808 foreach (var outputVariable
in outputs)
810 BindLocation(outputVariable.Semantic(), outputVariable.Type.ResolveType(),
false, outputVariable.Name, ref outputSemanticLocation, outputVariable.Span);
815 for (
int i = 0; i < function.Parameters.Count; ++i)
817 var variable = function.Parameters[i];
818 var modifier = variable.Qualifiers;
819 if (modifier.Contains(Ast.StorageQualifier.Uniform))
821 function.Parameters.RemoveAt(i--);
822 ScopeStack.Peek().RemoveDeclaration(variable);
824 if (!shader.Declarations.Contains(variable))
827 var variableNameBase = variable.Name;
828 variable.Name.Text +=
"_uniform";
829 int variableNameIndex = 1;
830 while (FindDeclaration(variable.Name) != null)
831 variable.Name.Text = variableNameBase +
"_" + variableNameIndex++;
833 AddGlobalDeclaration(variable);
851 if (varRefExpr != null)
853 var variable = FindDeclaration(varRefExpr.Name) as
Variable;
854 if (variable != null)
856 Variable newVariable;
857 inputAssignment.TryGetValue(variable, out newVariable);
859 if (newVariable != null)
861 return new VariableReferenceExpression(newVariable);
878 Visit((
Node)castExpression);
880 var targetType = castExpression.Target.TypeInference.TargetType;
885 var literalExpression = (LiteralExpression)castExpression.From;
886 if (literalExpression.Value != null)
888 var toStringValue = literalExpression.Value.ToString().Trim();
889 if (toStringValue ==
"0")
895 if (targetType ==
ScalarType.
Float && castExpression.From is LiteralExpression)
897 var literalExpression = (LiteralExpression)castExpression.From;
898 literalExpression.Value =
Convert.ChangeType(literalExpression.Value, typeof(
float));
899 return literalExpression;
904 targetType = castExpression.TypeInference.TargetType;
905 if (targetType != null)
906 castByMethod.TypeInference.TargetType = targetType;
908 CheckCastMethod(castByMethod);
924 if (expressionStatement != null)
927 if (methodInvocationExpression != null)
930 if (methodVar != null)
932 newStatement = VisitStatementAsFunctionInvocation(statement, methodInvocationExpression, methodVar);
937 if (memberReferenceExpression != null)
939 newStatement = VisitStatementAsMemberInvocation(statement, methodInvocationExpression, memberReferenceExpression);
946 if (assignExpression != null)
948 newStatement = VisitStatementAsAssignExpression(statement, assignExpression);
953 return newStatement ?? (
Statement)this.Visit((
Node)statement);
965 var methodName = methodVar.Name;
970 if (methodInvocationExpression.
Arguments.Count == 1)
974 if (!methodInvocationHandled.ContainsKey(methodInvocationExpression))
975 methodInvocationHandled.Add(methodInvocationExpression,
true);
977 Visit((
Node)statement);
979 var clipArgType = methodInvocationExpression.Arguments[0].TypeInference.TargetType;
981 bool isSingleValue = clipArgType is
ScalarType;
990 conditionExpression = methodAll;
999 if (methodInvocationExpression.
Arguments.Count == 3)
1001 if (!methodInvocationHandled.ContainsKey(methodInvocationExpression))
1002 methodInvocationHandled.Add(methodInvocationExpression,
true);
1003 Visit((
Node)statement);
1033 if (memberReferenceExpression.
Member ==
"GetDimensions")
1036 var variableTexture = this.FindGlobalVariableFromExpression(textureRef);
1038 if (variableTexture == null)
1040 parserResult.Error(
"Unable to find target variable for expression [{0}]", methodInvocationExpression.Span, methodInvocationExpression);
1044 var glslSampler = GetGLSampler(null, variableTexture,
false);
1046 if (glslSampler == null)
1048 parserResult.Error(
"Unable to find matching sampler for GetDimensions() for expression [{0}]", methodInvocationExpression.Span, methodInvocationExpression);
1061 textureSizeCall.Arguments.Add(
new VariableReferenceExpression(glslSampler.Name));
1067 resultBlock.Statements.Add(
1071 methodInvocationExpression.
Arguments[0],
1073 resultBlock.Statements.Add(
1077 methodInvocationExpression.
Arguments[1],
1089 if (NoSwapForBinaryMatrixOperation && indexerExpression != null)
1092 var targetIterator = indexerExpression.Target;
1093 var indices =
new List<Expression> { indexerExpression.Index };
1094 while (targetIterator is IndexerExpression)
1096 indices.Add(((IndexerExpression)targetIterator).Index);
1097 targetIterator = ((IndexerExpression)targetIterator).Target;
1102 if (variableReferenceExpression != null)
1104 var variable = FindDeclaration(variableReferenceExpression.Name) as
Variable;
1107 var variableType = variable != null ? variable.Type.ResolveType() : null;
1110 if (matrixType != null)
1112 if (indices.Count == 2)
1114 IndexerExpression nextExpression = null;
1117 for (
int i = 0; i < indices.Count; i++)
1119 nextExpression = nextExpression == null ?
new IndexerExpression(variableReferenceExpression, indices[i]) :
new IndexerExpression(nextExpression, indices[i]);
1122 assignmentExpression.Target = nextExpression;
1127 var matrixElementType = matrixType.Type.ResolveType() as
ScalarType;
1128 var matrixRowType =
new VectorType(matrixElementType, matrixType.ColumnCount);
1141 assignmentExpression.Value = (
Expression)VisitDynamic(assignmentExpression.
Value);
1143 var localResult =
new Variable(matrixRowType,
"_localmat_", assignmentExpression.
Value);
1146 for (
int i = 0; i < matrixType.ColumnCount; i++)
1148 var targetExpression =
new IndexerExpression(
new IndexerExpression(indexerExpression.Target,
new LiteralExpression(i)), indexerExpression.Index);
1149 var valueExpression =
new IndexerExpression(
new VariableReferenceExpression(
"_localmat_"),
new LiteralExpression(i));
1174 Visit((
Node)methodInvocationExpression);
1177 if (methodInvocationHandled.ContainsKey(methodInvocationExpression))
1178 return methodInvocationExpression;
1184 if (methodVar != null)
1186 var methodName = methodVar.Name;
1190 if (methodInvocationExpression.TypeInference.Declaration is Typedef)
1192 methodInvocationExpression.Target =
new TypeReferenceExpression(methodInvocationExpression.TypeInference.TargetType);
1193 return methodInvocationExpression;
1196 if (methodName ==
"mul")
1199 var leftParameter = ConvertToSafeExpressionForBinary(methodInvocationExpression.Arguments[NoSwapForBinaryMatrixOperation ? 0 : 1]);
1200 var rightParameter = ConvertToSafeExpressionForBinary(methodInvocationExpression.Arguments[NoSwapForBinaryMatrixOperation ? 1 : 0]);
1204 if (methodName ==
"lit")
1219 methodInvocationExpression.Arguments[0]);
1221 methodLit.Arguments.Add(diffuseArg);
1232 methodLit.Arguments.Add(specularArg);
1239 if (methodName ==
"isfinite")
1241 methodVar.Name =
"isinf";
1246 if (methodName ==
"log10")
1248 methodVar.Name =
"log";
1253 if (methodName ==
"saturate")
1255 methodVar.Name =
"saturate";
1261 if (methodName ==
"all" || methodName ==
"any")
1263 var argType = methodInvocationExpression.Arguments[0].TypeInference.TargetType;
1268 methodInvocationExpression.Arguments[0] = notEqual;
1272 if (
string.Compare(methodName,
"D3DCOLORtoUBYTE4", StringComparison.OrdinalIgnoreCase) == 0)
1277 string methodNameGl;
1278 if (functionMapping.TryGetValue(methodName, out methodNameGl))
1279 methodVar.Name = methodNameGl;
1284 if (memberReferenceExpression != null)
1286 var targetVariable = FindGlobalVariableFromExpression(memberReferenceExpression.Target);
1287 if (targetVariable == null)
1289 parserResult.Error(
"Unable to find target variable for expression [{0}]", methodInvocationExpression.Span, methodInvocationExpression);
1290 return methodInvocationExpression;
1292 var targetVariableType = targetVariable.Type.ResolveType();
1293 if (targetVariableType.IsBuiltIn && targetVariableType.Name.Text.StartsWith(
"Buffer"))
1295 parserResult.Error(
"Unable to convert Buffer<> variable access [{0}]. Features not supported in GLSL", methodInvocationExpression.Span, methodInvocationExpression);
1296 return methodInvocationExpression;
1298 methodDeclaration = memberReferenceExpression.TypeInference.Declaration as
MethodDeclaration;
1300 switch (memberReferenceExpression.Member)
1303 case "RestartStrip":
1304 methodInvocationExpression.Target =
new VariableReferenceExpression(
"EndPrimitive");
1308 case "GetDimensions":
1310 parserResult.Error(
"GetDimensions should have been already preprocessed for expression [{0}]", methodInvocationExpression.Span, methodInvocationExpression);
1318 string methodName =
"texture";
1320 bool isLoad = memberReferenceExpression.Member ==
"Load";
1321 int baseParameterCount = isLoad ? 1 : 2;
1328 sampler = this.FindGlobalVariableFromExpression(methodInvocationExpression.Arguments[0]);
1330 var glslSampler = GetGLSampler(sampler, targetVariable,
true);
1332 if (TextureFunctionsCompatibilityProfile)
1341 methodName +=
"Cube";
1343 parserResult.Error(
"Unable to find texture profile in compatibility mode [{0}]", methodInvocationExpression.Span, methodInvocationExpression);
1346 if (glslSampler == null)
1348 parserResult.Error(
"Unable to find matching texture/sampler expression [{0}]", methodInvocationExpression.Span, methodInvocationExpression);
1349 return methodInvocationExpression;
1352 bool hasBias = memberReferenceExpression.Member ==
"SampleBias";
1354 baseParameterCount++;
1356 if (memberReferenceExpression.Member ==
"SampleGrad")
1358 baseParameterCount += 2;
1359 methodName +=
"Grad";
1362 if (memberReferenceExpression.Member ==
"SampleLevel")
1364 baseParameterCount++;
1365 methodName +=
"Lod";
1370 methodName +=
"Lod";
1373 if (methodInvocationExpression.Arguments.Count == baseParameterCount + 1)
1375 methodName +=
"Offset";
1377 else if (methodInvocationExpression.Arguments.Count != baseParameterCount)
1379 parserResult.Error(
"Unable to match arguments count with expected parameters for expression [{0}]", methodInvocationExpression.Span, methodInvocationExpression);
1380 return methodInvocationExpression;
1383 var samplerParameter =
new VariableReferenceExpression(glslSampler.Name);
1387 methodInvocationExpression.Arguments.Insert(0, samplerParameter);
1389 methodInvocationExpression.Arguments[0] = samplerParameter;
1392 if (hasBias && methodName ==
"textureOffset")
1394 var temp = methodInvocationExpression.Arguments[2];
1395 methodInvocationExpression.Arguments[3] = methodInvocationExpression.Arguments[2];
1396 methodInvocationExpression.Arguments[2] = temp;
1405 string mipLevel =
"?";
1407 switch (targetVariableType.Name.Text)
1415 case "Texture1DArray":
1419 case "Texture2DArray":
1420 case "Texture2DArrayDMS":
1426 methodInvocationExpression.Arguments.Insert(2, NewCast(
ScalarType.
Float,
new MemberReferenceExpression(methodInvocationExpression.Arguments[1].DeepClone(), mipLevel)));
1429 new MemberReferenceExpression(methodInvocationExpression.Arguments[1], dimP),
1433 methodInvocationExpression.Target =
new VariableReferenceExpression(methodName);
1445 if (typeReferenceExpression != null)
1448 var matrixType = typeReferenceExpression.Type.ResolveType() as
MatrixType;
1449 if (matrixType != null)
1451 methodInvocationExpression.Arguments = this.ConvertMatrixInitializer(matrixType, methodInvocationExpression.Arguments);
1456 if (methodDeclaration != null)
1458 for (
int i = methodInvocationExpression.Arguments.Count; i < methodDeclaration.
Parameters.Count; i++)
1459 methodInvocationExpression.Arguments.Add(methodDeclaration.Parameters[i].InitialValue);
1462 CheckCastMethod(methodInvocationExpression);
1465 RemoveStreamTypeFromMethodInvocation(methodInvocationExpression);
1467 return methodInvocationExpression;
1473 for (
int i = expression.
Arguments.Count - 1; i >= 0; i--)
1475 var argument = expression.Arguments[i];
1478 expression.Arguments.RemoveAt(i);
1483 private void RemoveStreamTypeFromMethodDefinition(
MethodDeclaration declaration)
1486 for (
int i = declaration.
Parameters.Count - 1; i >= 0; i--)
1488 var argument = declaration.Parameters[i];
1491 declaration.Parameters.RemoveAt(i);
1503 Visit((
Node)conditionalExpression);
1505 var conditionType = conditionalExpression.Condition.TypeInference.TargetType;
1512 return methodInvocation;
1516 conditionalExpression.Condition = ConvertCondition(conditionalExpression.Condition);
1519 return conditionalExpression;
1529 Visit((
Node)constantBuffer);
1532 foreach (var variable
in constantBuffer.Members.OfType<
Variable>())
1534 if (variable.InitialValue != null)
1536 parserResult.Warning(
"Initializer in uniform block are not supported in glsl [{0}]", variable.Span, variable);
1537 variable.InitialValue = null;
1550 Visit((
Node)varRefExpr);
1553 if (globalUniformVisitor.IsVariableAsGlobalTemporary(varRefExpr))
1559 var variable = FindDeclaration(varRefExpr.Name) as
Variable;
1560 if (variable != null)
1562 var result = this.ConvertReferenceToSemantics(varRefExpr, variable.Semantic(), variable.Type.ResolveType(), variable.Name, variable.Span);
1577 Visit((
Node)ifStatement);
1578 ifStatement.Condition = ConvertCondition(ifStatement.Condition);
1589 Visit((
Node)forStatement);
1592 if (UnrollForLoops && forStatement.Attributes.OfType<
AttributeDeclaration>().Any(x => x.Name.Text ==
"unroll"))
1596 var breakVisitor =
new BreakContinueVisitor();
1597 var hasBreak = breakVisitor.Run(forStatement, breakFlag,
"break", parserResult);
1601 var continueVisitor =
new BreakContinueVisitor();
1602 var hasContinue = continueVisitor.Run(forStatement, continueFlag,
"continue", parserResult);
1605 var varName = GetStartForStatement(forStatement, out startValue);
1607 if (varName != null)
1609 var iterCount = GetIterCountForStatement(forStatement, varName, startValue);
1614 statements.Statements.Add(forStatement.Start);
1620 var lastStatement = statements;
1622 for (
int i = 0; i < iterCount; ++i)
1624 var clonedBody = forStatement.Body.DeepClone();
1635 ifStatement.Then = blockStatement;
1636 lastStatement.Statements.Add(ifStatement);
1640 lastStatement.Statements.Add(blockStatement);
1642 lastStatement = blockStatement;
1651 parserResult.Error(
"Unable to unroll for statement [{0}]", forStatement.Span, forStatement);
1654 return forStatement;
1663 private static string GetStartForStatement(
ForStatement forStatement, out
int startValue)
1669 if (startStatement != null)
1671 var variable = startStatement.Content as
Variable;
1672 if (variable != null)
1675 var resultStart = evaluatorStart.Evaluate(variable.InitialValue);
1676 if (resultStart.HasErrors)
1678 startValue = (int)((
double)resultStart.Value);
1680 return variable.Name.Text;
1683 else if (startStatementAssign != null)
1692 var resultStart = evaluatorStart.Evaluate(assign.Value);
1693 if (resultStart.HasErrors)
1695 startValue = (int)((
double)resultStart.Value);
1697 return vre.Name.Text;
1712 private static int GetIterCountForStatement(
ForStatement forStatement,
string variableName,
int startValue)
1715 if (condition == null)
1719 var resultStop = evaluatorStop.Evaluate(condition.Right);
1720 if (resultStop.HasErrors)
1723 var stopValue = (int)((
double)resultStop.Value);
1727 if (stepExpr == null)
1729 var stepAssign = forStatement.Next as AssignmentExpression;
1730 if (stepAssign != null)
1734 var assignedVar = stepAssign.Target as VariableReferenceExpression;
1735 var valueAssigned = stepAssign.Value as BinaryExpression;
1736 if (assignedVar == null || valueAssigned == null)
1739 var left = valueAssigned.Left as VariableReferenceExpression;
1740 var right = valueAssigned.Right as VariableReferenceExpression;
1742 if (left != null && left.Name.Text == variableName && valueAssigned.Right is
LiteralExpression)
1744 step = (int)(valueAssigned.Right as LiteralExpression).Value;
1746 else if (right != null && right.Name.Text == variableName && valueAssigned.Left is LiteralExpression)
1748 step = (int)(valueAssigned.Left as LiteralExpression).Value;
1755 var assignedVar = stepAssign.Target as VariableReferenceExpression;
1756 if (assignedVar == null || assignedVar.Name.Text != variableName)
1760 var resultValueAssigned = evaluatorValueAssigned.Evaluate(stepAssign.Value);
1761 if (resultValueAssigned.HasErrors)
1764 step = (int)((
double)resultValueAssigned.Value);
1774 switch (stepExpr.Operator)
1776 case UnaryOperator.PostDecrement:
1777 case UnaryOperator.PreDecrement:
1780 case UnaryOperator.PostIncrement:
1781 case UnaryOperator.PreIncrement:
1787 switch (condition.Operator)
1789 case BinaryOperator.Less:
1790 return (stopValue - startValue - 1) / step + 1;
1791 case BinaryOperator.Greater:
1792 return (stopValue - startValue - 1) / step + 1;
1793 case BinaryOperator.LessEqual:
1794 return (stopValue - startValue) / step + 1;
1795 case BinaryOperator.GreaterEqual:
1796 return (stopValue - startValue) / step + 1;
1797 case BinaryOperator.Equality:
1799 if (startValue == stopValue)
1817 Visit((
Node)expression);
1830 var matrixType = expression.Target.TypeInference.TargetType as
MatrixType;
1831 if (matrixType != null)
1833 var swizzles = HlslSemanticAnalysis.MatrixSwizzleDecode(expression);
1835 if (swizzles.Count == 1)
1838 if (swizzles.Count > 1 && swizzles.Count <= 4)
1842 foreach (var swizzle
in swizzles)
1843 swizzleVectorInvoke.Arguments.Add(
new IndexerExpression(
new IndexerExpression(expression.Target,
new LiteralExpression(swizzle.Row)),
new LiteralExpression(swizzle.Column)));
1844 return swizzleVectorInvoke;
1859 var variable = ParentNode as Variable;
1864 if (variable != null)
1866 var variableType = variable.Type.ResolveType();
1868 var arrayType = variableType as
ArrayType;
1869 if (arrayType != null)
1871 return this.ConvertArrayInitializer(arrayType, arrayCreationExpression);
1878 var items =
new List<Expression>();
1879 FlattenArrayCreationExpression(arrayCreationExpression, items);
1884 if (matrixType != null)
1886 items = this.ConvertMatrixInitializer(matrixType, items);
1889 foreach (var expression
in items)
1890 castToType.Arguments.Add(expression);
1892 result = castToType;
1909 isAssignmentTarget =
true;
1910 assignExpression.Target = (
Expression)VisitDynamic(assignExpression.
Target);
1911 isAssignmentTarget =
false;
1912 assignExpression.Value = (
Expression)VisitDynamic(assignExpression.
Value);
1916 if (assignExpression.
Value == null)
1919 return assignExpression;
1942 Visit((
Node)binaryExpression);
1947 bool isLeftFrontFacing = string.Compare(VariableReferenceExpression.GetVariableName(binaryExpression.Left), gl_FrontFacing, StringComparison.OrdinalIgnoreCase) == 0;
1948 bool isRightFrontFacing = string.Compare(VariableReferenceExpression.GetVariableName(binaryExpression.Right), gl_FrontFacing, StringComparison.OrdinalIgnoreCase) == 0;
1949 if (isLeftFrontFacing || isRightFrontFacing)
1951 bool isLessOperator = binaryExpression.Operator == BinaryOperator.Less || binaryExpression.Operator == BinaryOperator.LessEqual;
1952 bool isGreaterOperator = binaryExpression.Operator == BinaryOperator.Greater || binaryExpression.Operator == BinaryOperator.GreaterEqual;
1955 var glFrontFacingVar = isLeftFrontFacing ? binaryExpression.Left : binaryExpression.Right;
1956 glFrontFacingVar.TypeInference.TargetType = ScalarType.Bool;
1957 if (isLessOperator || isGreaterOperator)
1959 if ((isLessOperator && isLeftFrontFacing) || (isRightFrontFacing && isGreaterOperator))
1962 return glFrontFacingVar;
1968 if (isLeftFrontFacing)
1969 binaryExpression.Left = newGlFrontFacing;
1971 binaryExpression.Right = newGlFrontFacing;
1977 var leftType = binaryExpression.Left.TypeInference.TargetType;
1978 var rightType = binaryExpression.Right.TypeInference.TargetType;
1980 Expression outputExpression = binaryExpression;
1982 if (leftType != null && rightType != null)
1991 matrixMul.Arguments.Add(binaryExpression.Left);
1992 matrixMul.Arguments.Add(binaryExpression.Right);
1994 outputExpression = matrixMul;
2002 matrixMul.Arguments.Add(binaryExpression.Left);
2003 matrixMul.Arguments.Add(binaryExpression.Right);
2005 outputExpression = matrixMul;
2011 if (isOperationOnVectors)
2013 string comparisonName;
2014 switch (binaryExpression.Operator)
2016 case BinaryOperator.Less:
2017 comparisonName =
"lessThan";
2019 case BinaryOperator.LessEqual:
2020 comparisonName =
"lessThanEqual";
2022 case BinaryOperator.Greater:
2023 comparisonName =
"greaterThan";
2025 case BinaryOperator.GreaterEqual:
2026 comparisonName =
"greaterThanEqual";
2028 case BinaryOperator.Equality:
2029 comparisonName =
"equal";
2031 case BinaryOperator.Inequality:
2032 comparisonName =
"notEqual";
2035 parserResult.Error(
"Unsupported binary expression on vectors [{0}]", binaryExpression.Span, binaryExpression);
2036 return binaryExpression;
2040 comparisonExpr.Arguments.Add(binaryExpression.Left);
2041 comparisonExpr.Arguments.Add(binaryExpression.Right);
2043 int dimension = ((
VectorType)binaryExpression.TypeInference.TargetType).Dimension;
2045 outputExpression = comparisonExpr;
2050 binaryExpression.Left = ConvertCondition(binaryExpression.Left);
2051 binaryExpression.Right = ConvertCondition(binaryExpression.Right);
2052 binaryExpression.TypeInference.TargetType = ScalarType.Bool;
2054 if (isOperationOnVectors)
2057 "Boolean operation && || on expression [{0}] cannot be converted safely to GLSL, as GLSL doesn't support boolean operators function on a per-component basis. Code is generated but invalid",
2058 binaryExpression.Span,
2064 return outputExpression;
2075 Visit((
Node)returnStatement);
2078 if (!IsInEntryPoint)
2079 return returnStatement;
2083 return ConvertReturn(returnStatement.Value,
true, returnStatement.
Span);
2099 for (
int i = 0; i < statementList.Statements.Count; i++)
2101 var stmt = statementList.Statements[i];
2102 bool converted =
false;
2109 var returnValue = ((ReturnStatement)stmt).Value;
2115 if (returnValue != null)
2117 var subStatements = ConvertReturn(((ReturnStatement)stmt).Value, emitReturn, stmt.
Span);
2119 newStatementList.AddRange((StatementList)subStatements);
2121 newStatementList.Add(subStatements);
2125 else if (!emitReturn)
2129 else if (stmt is DeclarationStatement)
2131 var variable = ((DeclarationStatement)stmt).Content as Variable;
2134 if (variable != null)
2135 variable.Qualifiers.Values.RemoveAll(qualifierArg => qualifierArg is
RegisterLocation || qualifierArg is
Semantic);
2137 else if (stmt is ExpressionStatement)
2139 var exprStmt = (ExpressionStatement)stmt;
2142 if (exprStmt.Expression is AssignmentExpression)
2144 var assignExpression = exprStmt.Expression as AssignmentExpression;
2149 var tupleType = typeReferenceExpression != null ? typeReferenceExpression.
Type.
ResolveType() : null;
2151 if (typeReferenceExpression != null && tupleType != null && !(tupleType is
MatrixType))
2154 const string TemporaryTupleName =
"_tuple_temp_";
2155 var variableTuple =
new Variable(
VectorType.
Float4, TemporaryTupleName, assignExpression.Target);
2156 tupleBlock.Statements.Add(
new DeclarationStatement(variableTuple));
2158 int startMember = 0;
2160 const string SwizzleMembers =
"xyzw";
2162 bool hasError =
false;
2164 foreach (var expression
in tupleExpression.
Arguments)
2166 var argumentType = expression.TypeInference.TargetType;
2167 if (argumentType != null)
2169 var argumentDimension = (argumentType is
VectorType) ? ((
VectorType)argumentType).Dimension : 1;
2171 tupleBlock.Statements.Add(
2172 new ExpressionStatement(
2173 new AssignmentExpression(
2176 new MemberReferenceExpression(
new VariableReferenceExpression(TemporaryTupleName), SwizzleMembers.Substring(startMember, argumentDimension)))));
2177 startMember += argumentDimension;
2186 newStatementList.Add(tupleBlock);
2197 if (method != null && method.Target is VariableReferenceExpression)
2199 var targetVariable = (VariableReferenceExpression) method.
Target;
2203 if (method.Member ==
"Append")
2214 if (targetType.Name ==
"TriangleStream")
2215 geometryLayoutOutput =
"triangle_strip";
2216 else if (targetType.Name ==
"LineStream")
2217 geometryLayoutOutput =
"line_strip";
2218 else if (targetType.Name ==
"PointStream")
2219 geometryLayoutOutput =
"points";
2222 parserResult.Error(
"Unknown OutputStream type [{0}] (should be TriangleStream, LineStream or PointStream", exprStmt.Span, targetType.Name);
2223 return newStatementList;
2226 var returnStatement = ConvertReturn(methodInvocationExpr.Arguments[0],
false, null);
2228 newStatementList.AddRange((StatementList) returnStatement);
2230 newStatementList.Add(returnStatement);
2231 newStatementList.Add(
new ExpressionStatement(
new MethodInvocationExpression(
new VariableReferenceExpression(
"EmitVertex"))));
2234 else if (method.Member ==
"RestartStrip")
2236 newStatementList.Add(
new ExpressionStatement(
new MethodInvocationExpression(
new VariableReferenceExpression(
"EndPrimitive"))));
2245 newStatementList.Add(stmt);
2248 Visit((
Node)newStatementList);
2250 return newStatementList;
2262 var targetIterator = indexerExpression.Target;
2263 var indices =
new List<Expression> { indexerExpression.Index };
2266 indices.Add(((IndexerExpression)targetIterator).Index);
2267 targetIterator = ((IndexerExpression)targetIterator).Target;
2271 var variableReferenceExpression = targetIterator as VariableReferenceExpression;
2273 if (variableReferenceExpression != null)
2275 var variable = FindDeclaration(variableReferenceExpression.Name) as Variable;
2278 var variableType = variable != null ? variable.Type.ResolveType() : null;
2279 var arrayType = variableType as
ArrayType;
2282 if (arrayType != null && arrayType.Dimensions.Count == indices.Count)
2284 if (!this.listOfMultidimensionArrayVariable.Contains(variable))
2285 this.listOfMultidimensionArrayVariable.Add(variable);
2291 for (
int i = 0; i < indices.Count; i++)
2294 for (
int j = i + 1; j < indices.Count; j++)
2296 var nextExpression = arrayType.Dimensions[j];
2297 indexExpression =
new BinaryExpression(
BinaryOperator.Multiply, indexExpression, nextExpression);
2300 finalIndex = finalIndex == null ? indexExpression :
new BinaryExpression(
BinaryOperator.Plus, finalIndex, indexExpression);
2304 indexerExpression =
new IndexerExpression(targetIterator, finalIndex);
2308 Visit((
Node)indexerExpression);
2313 if (matrixType != null && NoSwapForBinaryMatrixOperation && !isAssignmentTarget)
2315 if (indices.Count == 2)
2317 IndexerExpression nextExpression = null;
2320 for (
int i = 0; i < indices.Count; i++)
2322 nextExpression = nextExpression == null ?
new IndexerExpression(variableReferenceExpression, indices[i]) :
new IndexerExpression(nextExpression, indices[i]);
2324 return nextExpression;
2329 var matrixElementType = matrixType.Type.ResolveType() as
ScalarType;
2334 for (
int i = 0; i < matrixType.ColumnCount; i++)
2336 convertRowToColumnMethod.Arguments.Add(
new IndexerExpression(
new IndexerExpression(indexerExpression.Target,
new LiteralExpression(i)), indexerExpression.Index));
2338 return convertRowToColumnMethod;
2342 return indexerExpression;
2345 private void GenerateSamplerMappingAndStrip()
2350 TextureFunctionsCompatibilityProfile = TextureFunctionsCompatibilityProfile
2357 stripVisitor.KeepConstantBuffers = KeepConstantBuffer;
2358 stripVisitor.Visit(shader);
2361 foreach (var textureSampler
in samplerMapping)
2363 declarationListToRemove.Add(textureSampler.Key.Sampler);
2364 declarationListToRemove.Add(textureSampler.Key.Texture);
2365 AddGlobalDeclaration(textureSampler.Value);
2376 geometryLayoutInput = null;
2377 geometryInputParameter = null;
2378 geometryLayoutOutput = null;
2385 Visit((
Node)shader);
2388 TransformArrayDimensions();
2391 foreach (var cBuffer
in shader.Declarations.OfType<
ConstantBuffer>())
2393 AddExplicitLayout(cBuffer);
2397 foreach (var variable
in shader.Declarations.OfType<Variable>())
2399 var layoutRule = this.GetTagLayout(variable);
2400 bool isUniform = IsUniformLike(variable);
2403 if (!globalUniformVisitor.IsVariableAsGlobalTemporary(variable))
2407 variable.Qualifiers |= Ast.StorageQualifier.Uniform;
2410 var variableArrayType = variable.Type.ResolveType() as
ArrayType;
2411 if (variableArrayType != null && variable.InitialValue != null && !KeepUniformArrayInitializers)
2413 variable.InitialValue = null;
2416 if (UseBindingLayout)
2417 AddExplicitLayout(variable);
2421 if (UseLocationLayout && layoutRule.Location != null)
2423 layoutRule.Qualifier.Layouts.Add(
new LayoutKeyValue(
"location", layoutRule.Location));
2429 variable.Qualifiers.Values.RemoveAll(qualifierType => qualifierType is
RegisterLocation);
2430 variable.Qualifiers.Values.Remove(Ast.Hlsl.StorageQualifier.Static);
2431 variable.Qualifiers.Values.Remove(Ast.Hlsl.StorageQualifier.Shared);
2434 var type = variable.Type.ResolveType();
2436 variable.InitialValue = null;
2440 if (UseBindingLayout)
2442 foreach (var variable
in shader.Declarations.OfType<Variable>())
2444 if (variable.Qualifiers.Contains(Ast.StorageQualifier.Uniform))
2449 AddImplicitLayout(variable);
2455 foreach (var variable
in shader.Declarations.OfType<Variable>())
2457 var layoutRule = this.GetTagLayout(variable);
2460 if (layoutRule.Qualifier.Layouts.Count > 0)
2461 variable.Qualifiers.Values.Insert(0, layoutRule.Qualifier);
2464 if (layoutRule.Type != null)
2465 variable.Type =
new TypeName(layoutRule.Type) { Span = variable.Type.Span };
2467 if (layoutRule.Name != null && variable.Name.Text != layoutRule.Name)
2468 variable.Name =
new Identifier(layoutRule.Name);
2474 if (geometryLayoutInput != null)
2477 AddGeometryShaderInputDeclaration();
2478 AddGlobalDeclaration(
new Variable(
new TypeName(
string.Format(
"layout({0})", geometryLayoutInput)),
"in"));
2481 var maxVertexCount = entryPoint.Attributes().FirstOrDefault(x => x.Name ==
"maxvertexcount");
2482 if (maxVertexCount != null && geometryLayoutOutput != null)
2484 entryPoint.Attributes.Remove(maxVertexCount);
2487 AddGlobalDeclaration(
new Variable(
new TypeName(
string.Format(
"layout({0}, max_vertices={1})", geometryLayoutOutput, maxVertexCount.Parameters[0])),
"out"));
2492 foreach (var globalToLocalVariable
in inputAssignment)
2494 var globalVariable = globalToLocalVariable.Key;
2495 var localVariable = globalToLocalVariable.Value;
2496 int indexOfVariable = shader.Declarations.IndexOf(globalVariable) + 1;
2498 entryPoint.Body.Statements.Insert(0,
new ExpressionStatement(
new AssignmentExpression(
AssignmentOperator.Default,
2499 new VariableReferenceExpression(localVariable),
2500 localVariable.InitialValue as VariableReferenceExpression) { Span = globalVariable.Span }));
2502 localVariable.InitialValue = null;
2503 shader.Declarations.Insert(indexOfVariable,
new DeclarationStatement(localVariable) { Span = globalVariable.Span });
2507 RemoveTextureAndSamplerDeclarations();
2510 TransformInputAndOutputToInterfaceBlock();
2513 foreach (var structureType
in shader.Declarations.OfType<StructType>())
2515 if (structureType is Ast.Glsl.InterfaceType)
2518 foreach (var fieldRef
in GetMembers(structureType))
2520 var field = fieldRef.Field;
2521 field.Qualifiers = Qualifier.None;
2526 entryPoint.Parameters.Clear();
2529 entryPoint.Qualifiers = Qualifier.None;
2530 entryPoint.ReturnType = TypeBase.Void;
2534 private void TransformInputAndOutputToInterfaceBlock()
2537 if (!UseInterfaceForInOut && pipelineStage !=
PipelineStage.Geometry)
2540 var interfaceIn =
new Ast.Glsl.InterfaceType(VertexIOInterfaceName) {Qualifiers = Ast.ParameterQualifier.In};
2542 var interfaceOut =
new Ast.Glsl.InterfaceType(VertexIOInterfaceName) {Qualifiers = Ast.ParameterQualifier.Out};
2544 var isInAllowed = pipelineStage != PipelineStage.Vertex && pipelineStage != PipelineStage.Geometry;
2545 var isOutAllowed = pipelineStage != PipelineStage.Pixel;
2547 for (
int i = shader.Declarations.Count - 1; i >= 0; i--)
2549 var variable = shader.Declarations[i] as Variable;
2550 if (variable == null || variable.Type is Ast.Glsl.InterfaceType)
2553 if (isInAllowed && variable.Qualifiers.Contains(Ast.ParameterQualifier.In))
2555 variable.Qualifiers.Values.Remove(Ast.ParameterQualifier.In);
2556 interfaceIn.Fields.Insert(0, variable);
2557 shader.Declarations.RemoveAt(i);
2559 else if (isOutAllowed && variable.Qualifiers.Contains(Ast.ParameterQualifier.Out))
2561 variable.Qualifiers.Values.Remove(Ast.ParameterQualifier.Out);
2562 interfaceOut.Fields.Insert(0, variable);
2563 shader.Declarations.RemoveAt(i);
2568 var index = shader.Declarations.IndexOf(entryPoint);
2569 if (interfaceOut.Fields.Count > 0)
2570 shader.Declarations.Insert(index, interfaceOut);
2572 if (interfaceIn.Fields.Count > 0)
2573 shader.Declarations.Insert(index, interfaceIn);
2577 private void AddGeometryShaderInputDeclaration()
2588 var arrayType = (
ArrayType) geometryInputParameter.Type;
2590 var interfaceType =
new Ast.Glsl.InterfaceType { Name = VertexIOInterfaceName };
2593 var result = evaluator.Evaluate(arrayType.Dimensions[0]);
2595 int arrayLength = 0;
2596 if (result.HasErrors)
2598 result.CopyTo(parserResult);
2602 arrayLength = Convert.ToInt32(result.Value);
2605 if (structType != null)
2607 int insertPosition = 0;
2609 geometryInputParameter.Qualifiers = Qualifier.None;
2610 entryPoint.Body.Statements.Insert(insertPosition,
new DeclarationStatement(geometryInputParameter));
2613 const string GSInputName =
"_gs_input_";
2615 for (
int i = 0; i < arrayLength; i++)
2617 foreach (var field
in structType.Fields)
2623 var glVariableName = GetGlVariableNameFromSemantic(field.Semantic(),
true);
2624 if (glVariableName != null && glVariableName.StartsWith(
"gl_"))
2626 var newIndexerExpression =
new IndexerExpression(
new VariableReferenceExpression(
"gl_in"),
new LiteralExpression(i));
2634 var variable = field.DeepClone();
2635 if (UseLocationLayout)
2637 var variableTag = this.GetTagLayout(variable);
2639 if (variableTag.Location == null)
2641 if (UseSemanticForLocation)
2643 variableTag.Location =
"S_" + variable.Semantic().Name.Text;
2647 variableTag.Location = location;
2653 variableTag.Qualifier.Layouts.Add(
new LayoutKeyValue(
"location", variableTag.Location));
2655 variable.Qualifiers = Qualifier.None;
2656 variable.Qualifiers |= variableTag.Qualifier;
2658 interfaceType.Fields.Add(variable);
2664 entryPoint.Body.Statements.Insert(insertPosition,
new ExpressionStatement(
new AssignmentExpression(
AssignmentOperator.Default, dest, src)));
2669 var globalInterfaceType =
new Variable(
new ArrayType(interfaceType,
new EmptyExpression()), GSInputName) { Qualifiers = Ast.ParameterQualifier.In };
2671 AddGlobalDeclaration(globalInterfaceType);
2675 private void RemoveTextureAndSamplerDeclarations()
2678 shader.Declarations.RemoveAll(x => (x is Variable) && (((Variable)x).Type is
TextureType));
2679 shader.Declarations.RemoveAll(declarationListToRemove.Contains);
2685 var variable = node as Variable;
2686 if (variable != null)
2688 var variableRef = variable.InitialValue as VariableReferenceExpression;
2689 if (variable.Type is
TextureType || (variableRef != null && declarationListToRemove.Contains(variableRef.TypeInference.Declaration)))
2708 Visit((
Node)parenthesizedExpression);
2711 parenthesizedExpression.TypeInference.TargetType = parenthesizedExpression.Content.TypeInference.TargetType;
2717 var expressionList = (
ExpressionList)parenthesizedExpression.Content;
2718 return ConvertToSafeExpressionForBinary(expressionList[expressionList.Count - 1]);
2722 return parenthesizedExpression;
2728 private void SplitTypeDefs()
2730 var newDeclarations =
new List<Node>();
2731 foreach (var declaration
in this.shader.Declarations)
2733 var
typedef = declaration as Typedef;
2734 if (
typedef != null &&
typedef.Type is StructType)
2736 var structType = typedef.Type as StructType;
2737 if (
typedef.Type.Name == null)
2739 typedef.Type.Name = (typedef.IsGroup ? typedef.SubDeclarators[0].Name : typedef.Name) +
"_";
2741 newDeclarations.Add(typedef.Type);
2743 typedef.Type =
new TypeName(
typedef.Type.Name) {
TypeInference = { Declaration = structType, TargetType = typedef.Type } };
2745 if (
typedef.IsGroup)
2747 foreach (var typedefDeclarator
in typedef.SubDeclarators)
2749 typedefDeclarator.TypeInference.Declaration = structType;
2750 typedefDeclarator.TypeInference.TargetType = structType;
2755 typedef.TypeInference.Declaration = structType;
2756 typedef.TypeInference.TargetType = structType;
2759 newDeclarations.Add(
typedef);
2763 newDeclarations.Add(declaration);
2766 shader.Declarations = newDeclarations;
2781 private static void AllocateNewBinding(
bool[] allocatedRegisters,
int startingIndex,
int sizeOfAllocation)
2783 for (
int i = 0; i < sizeOfAllocation; i++)
2784 allocatedRegisters[startingIndex + i] =
true;
2818 private static int FindAvailableBinding(
bool[] allocatedRegisters,
int startingIndex,
int sizeOfAllocation)
2821 int allocSize = sizeOfAllocation;
2822 for (
int i = startingIndex; i < allocatedRegisters.Length; i++)
2824 if (allocatedRegisters[i])
2827 allocSize = sizeOfAllocation;
2855 private static bool IsUniformLike(Variable variable)
2857 return !variable.Qualifiers.Contains(Ast.ParameterQualifier.InOut) && !variable.
Qualifiers.
Contains(Ast.ParameterQualifier.In) && !variable.Qualifiers.Contains(Ast.ParameterQualifier.Out)
2858 && !variable.
Qualifiers.
Contains(Ast.Hlsl.StorageQualifier.Static) && !variable.Qualifiers.Contains(Ast.StorageQualifier.Const);
2870 private static KeyValuePair<string, int> ParseSemantic(
string semantic)
2874 foreach (var semanticModifier
in SemanticModifiers)
2876 if (semantic.ToLower().EndsWith(semanticModifier))
2879 semantic = semantic.Substring(0, semantic.Length - semanticModifier.Length);
2884 return Semantic.Parse(semantic);
2893 private void AddExplicitLayout(Variable variable)
2895 var layout = this.GetTagLayout(variable);
2896 var registerLocation = variable.Qualifiers.Values.OfType<
RegisterLocation>().FirstOrDefault();
2898 if (registerLocation != null && layout.Binding == null)
2901 var
register = registerLocation.Register.Text;
2903 var allocatedRegister = register.StartsWith(
"s") ? allocatedRegistersForSamplers : allocatedRegistersForUniforms;
2904 string registerIndexStr =
register[1] !=
'[' ? register.Substring(1) :
register.Substring(2,
register.Length - 3);
2906 if (!
int.TryParse(registerIndexStr, NumberStyles.Integer, CultureInfo.InvariantCulture, out registerIndex))
2908 parserResult.Error(
"Invalid layout binding for variable [{0}]", variable.Span, variable);
2912 var
size = GetNumberOfFloat4FromVariable(variable.
Type);
2914 var newIndex = FindAvailableBinding(allocatedRegister, registerIndex, size);
2917 if (newIndex != registerIndex)
2919 parserResult.Warning(
"Unable to use explicit layout for variable {0} as the location is already used. Use of an implicit layout", variable.Span, variable);
2920 AddImplicitLayout(variable);
2924 AllocateNewBinding(allocatedRegister, registerIndex, size);
2925 layout.Binding = registerIndex;
2926 layout.Qualifier.Layouts.Add(
new LayoutKeyValue(
"binding", registerIndex));
2938 var
register = cBuffer.Register;
2939 cBuffer.Register = null;
2942 if (
register != null)
2944 var registerStr = register.Register.Text;
2946 var layout = this.GetTagLayout(cBuffer, registerStr);
2948 if (registerStr.StartsWith(
"b"))
2951 string registerIndexStr = registerStr.Substring(1);
2953 if (!
int.TryParse(registerIndexStr, NumberStyles.Integer, CultureInfo.InvariantCulture, out registerIndex))
2955 parserResult.Error(
"Invalid layout binding for Constant Buffer [{0}]", cBuffer.Span, cBuffer);
2962 if (layout.Binding == null)
2963 layout.Binding = registerIndex;
2966 if (layout.Binding != null)
2968 cBuffer.Register =
new RegisterLocation(
string.Empty, layout.Binding.ToString());
2973 if (UseLocationLayout)
2975 foreach (var variable
in cBuffer.Members.OfType<Variable>())
2977 var packOffset = variable.Qualifiers.OfType<
PackOffset>().FirstOrDefault();
2979 if (packOffset != null)
2981 variable.Qualifiers = Qualifier.None;
2982 variable.Qualifiers |=
new Ast.Glsl.LayoutQualifier(
new LayoutKeyValue(
"location", packOffset.ToFloat4SlotIndex()));
2997 private void AddGlobalDeclaration<T>(
T declaration,
bool forceToAdd =
false) where T :
Node,
IDeclaration
3000 if (!declaration.Name.Text.StartsWith(
"gl_") || forceToAdd)
3002 var index = shader.Declarations.IndexOf(entryPoint);
3003 shader.Declarations.Insert(index, declaration);
3006 var topStack = ScopeStack.LastOrDefault();
3007 if (topStack != null)
3008 topStack.AddDeclaration(declaration);
3017 private void AddImplicitLayout(Variable variable)
3019 var registerLocation = variable.Qualifiers.Values.OfType<
RegisterLocation>().FirstOrDefault();
3020 var layout = this.GetTagLayout(variable);
3022 if (registerLocation == null && layout.Binding == null)
3027 var allocatedRegister = variable.Type is
SamplerType ? allocatedRegistersForSamplers : allocatedRegistersForUniforms;
3028 var
size = GetNumberOfFloat4FromVariable(variable.
Type);
3030 int registerIndex = FindAvailableBinding(allocatedRegister, 0, size);
3034 if (registerIndex < 0)
3035 parserResult.Error(
"Unable to find a free slot for uniform {0}", variable.Span, variable);
3038 AllocateNewBinding(allocatedRegister, registerIndex, size);
3039 layout.Binding = registerIndex;
3040 layout.Qualifier.Layouts.Add(
new LayoutKeyValue(
"binding", registerIndex));
3056 private Variable BindLocation(
Semantic semantic,
TypeBase typebase,
bool isInput,
string defaultName, ref
int location,
SourceSpan span)
3058 var variableFromSemantic = GetVariableFromSemantic(semantic, typebase, isInput, defaultName, span);
3059 if (!variableFromSemantic.Name.Text.StartsWith(
"gl_"))
3061 var variableTag = this.GetTagLayout(variableFromSemantic);
3063 if (variableTag.Location == null)
3065 if (UseSemanticForLocation)
3067 variableTag.Location =
"S_" + semantic.Name.Text;
3071 variableTag.Location = location;
3078 return variableFromSemantic;
3090 private string CalculateGlslPrefix(
ScalarType type)
3092 string prefix = string.Empty;
3094 prefix = string.Empty;
3115 if (typeReferenceExpression != null)
3119 var arrayType = typeReferenceExpression.Type as
ArrayType;
3120 if (arrayType != null)
3122 if (methodInvocationExpression.
Arguments.Count == 1)
3124 var argument = methodInvocationExpression.Arguments[0];
3125 methodInvocationExpression.Arguments.Clear();
3127 var argType = argument.TypeInference.TargetType;
3128 var arrayElementType = arrayType.Type.ResolveType();
3129 if (argType is
VectorType && arrayElementType is
ScalarType && arrayType.Dimensions.Count == 1)
3133 for (
int i = 0; i < vectorType.Dimension; i++)
3137 if (vectorType.Type != arrayElementType)
3140 methodInvocationExpression.Arguments.Add(indexerExpression);
3159 var expressionType = expression.TypeInference.TargetType;
3171 TypeBase glslType = semanticAsVariable.Type;
3173 var defaultGlslRef =
new VariableReferenceExpression(name) {
TypeInference = { Declaration = semanticAsVariable, TargetType = glslType } };
3175 var semanticVectorType = semanticType as
VectorType;
3176 var glslVectorType = glslType as VectorType;
3177 if (semanticVectorType != null && glslVectorType != null)
3179 if (semanticVectorType.Dimension < glslVectorType.Dimension)
3184 if (semanticVectorType.Dimension > glslVectorType.Dimension)
3190 return defaultGlslRef;
3197 if (varRefExpr != null)
3199 bool isInputOrOutput =
false;
3201 if (IsInEntryPoint && (semantic != null || (type != null && type is StructType)))
3203 bool isInput = inputs.Any(x => x.Name == varRefExpr.Name);
3204 bool isOutput = outputs.Any(x => x.Name == varRefExpr.Name);
3206 isInputOrOutput = isInput || isOutput;
3211 if (((isInput || isOutput) && !(type is StructType)) || (isOutput && !isAssignmentTarget))
3213 var variable = GetVariableFromSemantic(semantic, type, isInput, varName, span );
3214 Variable newVariable;
3215 inputAssignment.TryGetValue(variable, out newVariable);
3217 if (isInput && isAssignmentTarget && newVariable == null)
3219 newVariable =
new Variable(variable.Type,
"local_" + variable.Name.Text, CastSemanticToReferenceType(variable.Name, type, variable));
3220 inputAssignment.Add(variable, newVariable);
3221 return new VariableReferenceExpression(newVariable);
3224 if (newVariable != null)
3225 variable = newVariable;
3227 return this.CastSemanticToReferenceType(variable.Name, type, variable);
3232 if (!isInputOrOutput)
3234 var variable = FindDeclaration(varRefExpr.
Name) as Variable;
3236 if (variable != null)
3238 Variable newVariable;
3239 inputAssignment.TryGetValue(variable, out newVariable);
3240 if (isAssignmentTarget && IsUniformLike(variable) && shader.Declarations.Contains(variable) && newVariable == null)
3242 newVariable =
new Variable(variable.Type,
"local_" + variable.Name.Text,
new VariableReferenceExpression(variable.Name) { TypeInference = { TargetType = variable.Type } });
3243 inputAssignment.Add(variable, newVariable);
3246 if (newVariable != null)
3247 return new VariableReferenceExpression(newVariable.
Name) {
TypeInference = { TargetType = newVariable.Type.ResolveType() } };
3255 private void ReturnStruct(StructType structType,
Expression returnValueExpression,
StatementList statementList)
3257 var span = returnValueExpression.Span;
3258 foreach (var fieldRef
in GetMembers(structType))
3260 var field = fieldRef.Field;
3264 var fieldType = field.Type.ResolveType();
3265 var fieldArrayType = fieldType as ArrayType;
3267 var semanticVariable = GetVariableFromSemantic(field.Semantic(), fieldType,
false, fieldRef.FieldNamePath, span);
3270 if (fieldArrayType != null && semanticVariable.Name.Text.StartsWith(
"gl_"))
3272 var arrayDimension = fieldArrayType.Dimensions[0] as LiteralExpression;
3273 var arrayValue = arrayDimension != null ? Convert.ChangeType(arrayDimension.Literal.Value, typeof(
int)) : null;
3274 if (arrayDimension != null && arrayValue != null)
3276 var
count = (int)arrayValue;
3277 for (
int i = 0; i <
count; i++)
3279 var semantic = field.Semantic();
3280 var newSemantic =
new Semantic(semantic.BaseName + i);
3283 new ExpressionStatement(
3284 new AssignmentExpression(
3286 new VariableReferenceExpression(GetVariableFromSemantic(newSemantic, fieldArrayType,
false, fieldRef.FieldNamePath, span).Name),
3287 new IndexerExpression(fieldRef.GetMemberReference(returnValueExpression),
new LiteralExpression(i)))) { Span = span });
3293 parserResult.Error(
"Unable to convert semantic expression [{0}]. Array dimension must be a literal expression", field.Span, field);
3298 var semanticValue = (
Expression)fieldRef.GetMemberReference(returnValueExpression);
3299 if (fieldType != semanticVariable.Type)
3301 semanticValue = NewCast(semanticVariable.Type, semanticValue);
3305 new ExpressionStatement(
3306 new AssignmentExpression(
3307 AssignmentOperator.Default,
new VariableReferenceExpression(semanticVariable.Name) { TypeInference = { Declaration = semanticVariable } }, semanticValue)) { Span = returnValueExpression.Span });
3329 StructType structType = null;
3332 if (returnValueExpression != null)
3335 span = returnValueExpression.Span;
3337 var varRefExpr = returnValueExpression as VariableReferenceExpression;
3338 if (varRefExpr != null)
3340 var variableDeclarator = varRefExpr.TypeInference.Declaration as Variable;
3341 structType = variableDeclarator != null ? variableDeclarator.Type.ResolveType() as StructType : null;
3343 if (structType != null)
3345 ReturnStruct(structType, returnValueExpression, statementList);
3352 if (methodRefExp != null)
3354 var variableDeclarator = methodRefExp.Target.TypeInference.Declaration as
MethodDeclaration;
3355 structType = variableDeclarator != null ? variableDeclarator.ReturnType.ResolveType() as StructType : null;
3358 if (structType != null)
3363 statementList.Add(
new DeclarationStatement(
new Variable(
new TypeName(structType.
Name),
"_local_ret_", returnValueExpression)));
3365 var localRet =
new VariableReferenceExpression(
"_local_ret_");
3367 ReturnStruct(structType, localRet, statementList);
3371 if (CurrentFunction.Semantic() != null)
3373 var semantic = CurrentFunction.Semantic();
3375 new ExpressionStatement(
3376 new AssignmentExpression(
3378 new VariableReferenceExpression(GetVariableFromSemantic(semantic, CurrentFunction.ReturnType.ResolveType(),
false, null, semantic.Span).Name),
3379 returnValueExpression)) { Span = span.Value } );
3384 foreach (var variable
in this.outputs)
3386 structType = variable.Type.ResolveType() as StructType;
3387 if (structType != null)
3390 variable.Qualifiers = Qualifier.None;
3391 ReturnStruct(structType,
new VariableReferenceExpression(variable.Name), statementList);
3396 this.RemapCoordinates(statementList);
3413 private TypeBase FindTypeByName(
string name)
3415 return FindDeclaration(name) as
TypeBase;
3427 private VariableLayoutRule FindVariableLayoutBySemantic(
string name)
3429 VariableLayoutRule rule;
3430 this.VariableLayouts.TryGetValue(name, out rule);
3443 private ConstantBufferLayoutRule FindConstantBufferLayoutByRegister(
string name)
3445 ConstantBufferLayoutRule rule;
3446 this.ConstantBufferLayouts.TryGetValue(name, out rule);
3462 foreach (var nextElement
in from.
Items)
3466 FlattenArrayCreationExpression((ArrayInitializerExpression)nextElement, to);
3468 to.Add(nextElement);
3472 private Variable FindGlobalVariableFromExpression(
Expression expression)
3474 var variableRef = expression as VariableReferenceExpression;
3475 if (variableRef != null)
3477 var variable = variableRef.TypeInference.Declaration as Variable;
3479 if (variable != null)
3482 if (!shader.Declarations.Contains(variable) && variable.InitialValue != null)
3484 return this.FindGlobalVariableFromExpression(variable.InitialValue);
3488 if (shader.Declarations.Contains(variable))
3506 private Variable GetGLSampler(Variable sampler, Variable texture,
bool forceNullSampler)
3508 Variable glslSampler;
3510 if (sampler == null && !forceNullSampler)
3513 var matchingTextureSampler = samplerMapping.Where(x => x.Key.Texture == texture);
3514 if (!matchingTextureSampler.Any())
3519 return matchingTextureSampler.First().Value;
3522 var samplerKey =
new SamplerTextureKey(sampler, texture);
3523 if (!samplerMapping.TryGetValue(samplerKey, out glslSampler))
3540 private int GetNumberOfFloat4FromVariable(
TypeBase typeOfVar)
3542 var variableType = typeOfVar.ResolveType();
3545 if (matrixType != null)
3546 return matrixType.RowCount * matrixType.ColumnCount / 4;
3548 var arrayType = variableType as ArrayType;
3549 if (arrayType != null)
3553 var result = evaluator.Evaluate(arrayType.Dimensions[0]);
3555 if (result.HasErrors)
3557 result.CopyTo(parserResult);
3561 var dimValue = Convert.ToInt32(result.Value);
3562 return dimValue * GetNumberOfFloat4FromVariable(arrayType.Type);
3566 var structType = variableType as StructType;
3567 if (structType != null)
3570 foreach (var variable
in structType.Fields)
3572 structSize += GetNumberOfFloat4FromVariable(variable.Type.ResolveType());
3601 type = type.ResolveType();
3603 bool isArray = type is ArrayType;
3604 TypeBase elementType = isArray ? ((ArrayType)type).Type.ResolveType() : type;
3607 int semanticIndex = 0;
3609 var glSemantic = semantic;
3611 if (glSemantic != null)
3613 glSemantic = ResolveSemantic(semantic, type, isInput, varName, out defaultType, out semanticIndex, span);
3620 string variableName = glSemantic == null ? varName : glSemantic.Name.Text;
3622 bool addGlslGlobalVariable = string.Compare(variableName,
"gl_Position", StringComparison.InvariantCultureIgnoreCase) == 0 && defaultType != type;
3624 if (variableName.StartsWith(
"gl_fragdata", StringComparison.InvariantCultureIgnoreCase) && isPixelShaderOutputFragDataMuliType)
3628 variableName = varName != null ?
"out_gl_fragdata_" + varName :
"out_gl_fragdata";
3629 addGlslGlobalVariable =
true;
3633 var variable = FindDeclaration(variableName) as Variable;
3634 if (variable == null)
3636 variable =
new Variable(defaultType, variableName) { Span = span };
3638 if (addGlslGlobalVariable)
3640 variable.Type = type;
3643 variable.Qualifiers |= Ast.ParameterQualifier.In;
3647 variable.Qualifiers |= Ast.ParameterQualifier.Out;
3651 AddGlobalDeclaration(variable, addGlslGlobalVariable);
3665 private TagLayout GetTagLayout(Node node,
string alias = null)
3667 var variable = node as Variable;
3670 var layoutTag = node.GetTag(TagLayoutKey) as TagLayout;
3671 if (layoutTag == null)
3673 layoutTag =
new TagLayout();
3674 node.SetTag(TagLayoutKey, layoutTag);
3676 if (variable != null)
3679 if (MapRules.TryGetValue(variable.Name, out mapType))
3681 layoutTag.Type = mapType.Type;
3688 if (variable != null)
3690 var variableLayoutRule = this.FindVariableLayoutBySemantic(alias);
3691 if (variableLayoutRule != null)
3694 if (variableLayoutRule.Location != null)
3697 if (
int.TryParse(variableLayoutRule.Location, out locationIndex))
3699 layoutTag.Location = locationIndex;
3703 layoutTag.Location = variableLayoutRule.Location;
3708 layoutTag.Name = variable.Qualifiers.Contains(Ast.ParameterQualifier.Out) ? variableLayoutRule.NameOutput : variableLayoutRule.Name;
3711 else if (constantBuffer != null)
3713 var cBufferLayoutRule = this.FindConstantBufferLayoutByRegister(alias);
3714 if (cBufferLayoutRule != null)
3716 if (cBufferLayoutRule.Binding != null)
3719 if (
int.TryParse(cBufferLayoutRule.Binding, out bindingIndex))
3721 layoutTag.Binding = bindingIndex;
3725 layoutTag.Binding = cBufferLayoutRule.Binding;
3732 if (variable != null)
3737 if (variable != null && layoutTag.Name == null)
3738 layoutTag.Name = variable.Name.Text;
3740 layoutTag.Qualifier =
new Ast.Glsl.LayoutQualifier();
3749 private void RebindVariableReferenceExpressions()
3755 if (node is VariableReferenceExpression)
3757 var variableRef = (VariableReferenceExpression)node;
3758 if (variableRef.TypeInference.Declaration is Variable)
3759 variableRef.Name = variableRef.TypeInference.Declaration.Name;
3761 else if (node is MethodInvocationExpression)
3763 var methodRef = (MethodInvocationExpression)node;
3764 var variableRef = methodRef.Target as VariableReferenceExpression;
3765 var methodDeclaration = variableRef != null ? variableRef.TypeInference.Declaration as
MethodDeclaration : null;
3766 if (variableRef != null && methodDeclaration != null && !methodDeclaration.IsBuiltin)
3767 variableRef.Name = methodDeclaration.Name;
3777 private void RemoveDefaultParametersForMethods()
3784 if (declaration != null && declaration.InitialValue != null)
3785 declaration.InitialValue = null;
3790 private static string RenameGlslKeyword(
string name)
3792 if (GlslKeywords.IsReserved(name))
3793 name =
"_" + name +
"_";
3796 return name.Replace(
"__",
"_t_");
3808 new ExpressionStatement(
3809 new AssignmentExpression(
3812 new BinaryExpression(
3814 new BinaryExpression(
3817 new LiteralExpression(2.0f)),
3821 new ExpressionStatement(
3822 new AssignmentExpression(
3825 new BinaryExpression(
3827 new VariableReferenceExpression(
"ParadoxFlipRendertarget"),
3836 private void RenameGlslKeywords()
3843 var variableRef = node as VariableReferenceExpression;
3844 if (declaration != null && declaration.Name != null)
3846 if (!(declaration is Variable && ((Variable)declaration).
Type.Name.Text.StartsWith(
"layout")))
3848 declaration.Name.Text = RenameGlslKeyword(declaration.
Name.
Text);
3851 else if (variableRef != null)
3853 variableRef.Name.Text = RenameGlslKeyword(variableRef.Name.Text);
3860 private KeyValuePair<string, int> GetGlVariableFromSemantic(
Semantic rawSemantic,
bool isInput, out
string semanticGl, out
string semanticGlBase, out
int semanticIndex)
3862 var semanticName = rawSemantic.Name.Text;
3863 var semantic = ParseSemantic(semanticName);
3865 Dictionary<string, string> semanticMapping = null;
3866 switch (pipelineStage)
3868 case PipelineStage.Vertex:
3869 semanticMapping = isInput ? builtinVertexInputs : builtinVertexOutputs;
3871 case PipelineStage.Geometry:
3872 semanticMapping = isInput ? builtinGeometryInputs : builtinGeometryOutputs;
3874 case PipelineStage.Pixel:
3875 semanticMapping = isInput ? builtinPixelInputs : builtinPixelOutputs;
3881 if (semanticMapping != null && !semanticMapping.TryGetValue(semanticName, out semanticGl))
3882 semanticMapping.TryGetValue(semantic.Key, out semanticGl);
3885 if (semanticName != null && semanticName.Equals(
"TEXCOORD0") && IsPointSpriteShader && pipelineStage == PipelineStage.Pixel)
3886 semanticGl =
"gl_PointCoord";
3889 semanticGlBase = semanticGl;
3890 semanticIndex = semantic.Value;
3892 if (semanticGl != null && semanticGl.EndsWith(
"[]"))
3894 semanticGlBase = semanticGl.Substring(0, semanticGl.Length - 2);
3897 semanticGl = semanticGlBase +
"[" + semantic.Value +
"]";
3903 private string GetGlVariableNameFromSemantic(
Semantic rawSemantic,
bool isInput)
3905 string semanticGlBase = null;
3906 string semanticGl = null;
3908 GetGlVariableFromSemantic(rawSemantic, isInput, out semanticGl, out semanticGlBase, out semanticIndex);
3924 string semanticGlBase = null;
3925 string semanticGl = null;
3926 var semantic = GetGlVariableFromSemantic(rawSemantic, isInput, out semanticGl, out semanticGlBase, out semanticIndex);
3928 if (semanticGl == null)
3932 semanticGl =
"a_" + (this.UseSemanticForVariable ? semantic.Key + semantic.Value : varName);
3933 else if ((isInput ==
false) && (pipelineStage == PipelineStage.Pixel))
3934 semanticGl =
"vout_" + (this.UseSemanticForVariable ? semantic.Key + semantic.Value : varName);
3936 semanticGl =
"v_" + (this.UseSemanticForVariable ? semantic.Key + semantic.Value : varName);
3938 var variable = FindDeclaration(semanticGl) as Variable;
3939 if (variable == null)
3941 variable =
new Variable(type, semanticGl) { Span = span };
3942 variable.Qualifiers |= isInput ? Ast.ParameterQualifier.In : Ast.ParameterQualifier.Out;
3946 this.GetTagLayout(variable, rawSemantic.Name.Text);
3948 AddGlobalDeclaration(variable);
3954 if (builtinGlslTypes.TryGetValue(semanticGlBase, out glslType))
3957 var arrayType = type as ArrayType;
3958 if (arrayType != null)
3959 glslType =
new ArrayType(glslType, arrayType.Dimensions.ToArray());
3963 parserResult.Warning(
"No default type defined for glsl semantic [{0}]. Use [{1}] implicit type instead.", rawSemantic.Span, semanticGlBase, type);
3974 private void TranformToGlslTypes()
3976 var mapToGlsl =
new Dictionary<TypeBase, TypeBase>();
3979 foreach (var type
in new[] { ScalarType.Bool, ScalarType.Int, ScalarType.UInt, ScalarType.Float, ScalarType.Double, ScalarType.Half })
3981 var targetSubType = type == ScalarType.Half ? ScalarType.Float : type;
3982 var prefix = CalculateGlslPrefix(type);
3984 for (
int i = 2; i <= 4; ++i)
3985 mapToGlsl.Add(
new VectorType(type, i),
new TypeName(prefix +
"vec" + i));
3988 mapToGlsl.Add(
new VectorType(type, 1), targetSubType);
3992 foreach (var type
in new[] { ScalarType.Double, ScalarType.Float, ScalarType.Half })
3994 var prefix = CalculateGlslPrefix(type);
3995 for (
int i = 2; i <= 4; ++i)
3997 for (
int j = 2; j <= 4; ++j)
4000 int column = NoSwapForBinaryMatrixOperation ? j : i;
4001 int row = NoSwapForBinaryMatrixOperation ? i : j;
4003 string matrixName = i == j ? string.Format(prefix +
"mat{0}", i) :
string.Format(prefix +
"mat{0}x{1}", column, row);
4005 mapToGlsl.Add(
new MatrixType(type, i, j),
new TypeName(matrixName));
4011 mapToGlsl.Add(
new MatrixType(
ScalarType.
Float, 1, 1), ScalarType.Float);
4014 mapToGlsl.Add(SamplerType.Sampler, SamplerType.Sampler2D);
4015 mapToGlsl.Add(SamplerType.SamplerCube,
new TypeName(
"samplerCube"));
4022 if (node is
TypeBase && !(node is Typedef) && !(node is ArrayType))
4025 var targetType = type.ResolveType();
4027 if (mapToGlsl.TryGetValue(targetType, out outputType))
4038 private void TransformArrayDimensions()
4040 foreach (var variable
in listOfMultidimensionArrayVariable)
4044 var arrayType = (ArrayType)variable.Type.ResolveType();
4045 var arrayElementType = arrayType.Type.ResolveType();
4048 foreach (var subscript
in arrayType.Dimensions)
4049 newSubscript = newSubscript == null ? subscript :
new BinaryExpression(
BinaryOperator.Multiply, newSubscript, subscript);
4052 var newArrayType =
new ArrayType {
Type =
new TypeName(arrayElementType) };
4053 newArrayType.Dimensions.Add(newSubscript);
4054 variable.Type = newArrayType;
4058 foreach (var variable
in shader.Declarations.OfType<Variable>())
4060 var variableArrayType = variable.Type.ResolveType() as ArrayType;
4061 if (variableArrayType != null)
4063 if (variable.InitialValue != null)
4065 var arrayInitializers = variable.InitialValue as MethodInvocationExpression;
4066 if (arrayInitializers != null && variableArrayType.Dimensions.Count == 1)
4068 var currentDimension = variableArrayType.Dimensions[0] as LiteralExpression;
4069 if (currentDimension != null)
4071 int currentDim = Convert.ToInt32(currentDimension.Literal.Value);
4072 if (currentDim < arrayInitializers.Arguments.Count)
4074 variableArrayType.Dimensions.Clear();
4075 variableArrayType.Dimensions.Add(
new LiteralExpression(arrayInitializers.Arguments.Count));
4095 var arrayElementType = arrayType.Type.ResolveType();
4097 var newArrayExpression =
new MethodInvocationExpression(
new IndexerExpression(
new TypeReferenceExpression(arrayType.
Type),
new LiteralExpression()));
4098 var arrayItems =
new List<Expression>();
4099 FlattenArrayCreationExpression(arrayInitializer, arrayItems);
4102 newArrayExpression.Arguments.AddRange(arrayItems);
4106 var vectorType = arrayElementType as VectorType;
4107 if (vectorType != null)
4110 if ((arrayItems.Count % vectorType.Dimension) == 0 && arrayItems.All(arg => (arg.TypeInference.TargetType is
ScalarType)))
4112 var arguments =
new List<Expression>();
4113 var vectorArgs =
new List<Expression>();
4114 foreach (var arg
in arrayItems)
4116 vectorArgs.Add(arg);
4117 if (vectorArgs.Count == vectorType.Dimension)
4119 arguments.Add(
new MethodInvocationExpression(
new TypeReferenceExpression(vectorType), vectorArgs.ToArray()));
4124 newArrayExpression.Arguments = arguments;
4130 arrayType.Dimensions.Clear();
4131 arrayType.Dimensions.Add(
new LiteralExpression(newArrayExpression.Arguments.Count));
4134 return newArrayExpression;
4145 private List<Expression> ConvertMatrixInitializer(MatrixType matrixType, List<Expression> initializers)
4147 if (!NoSwapForBinaryMatrixOperation)
4148 return initializers;
4150 var newInitializers =
new List<Expression>();
4152 int columnCount = matrixType.ColumnCount;
4153 int rowCount = matrixType.RowCount;
4159 if (rowCount == initializers.Count)
4163 for (
int columnIndex = 0; columnIndex < columnCount; columnIndex++)
4166 var columnInitializer =
new MethodInvocationExpression(
new TypeReferenceExpression(columnInitializerType));
4167 newInitializers.Add(columnInitializer);
4169 for (
int rowIndex = 0; rowIndex < rowCount; rowIndex++)
4171 var elementIndexer =
new IndexerExpression(initializers[rowIndex],
new LiteralExpression(columnIndex));
4172 columnInitializer.Arguments.Add(elementIndexer);
4176 else if ((rowCount * columnCount) == initializers.Count)
4180 for (
int columnIndex = 0; columnIndex < columnCount; columnIndex++)
4182 for (
int rowIndex = 0; rowIndex < rowCount; rowIndex++)
4184 newInitializers.Add(initializers[rowCount * rowIndex + columnIndex]);
4190 newInitializers = initializers;
4191 parserResult.Warning(
"Unable to convert matrix initializer [{0}] to matrix type [{1}]", matrixType.Span, string.Join(
",", initializers), matrixType);
4194 return newInitializers;
4200 private void TransformGlobalMultipleVariableToSingleVariable()
4202 var declarations =
new List<Node>();
4204 foreach (var declaration
in shader.Declarations)
4206 var variable = declaration as Variable;
4207 if (variable != null && variable.IsGroup)
4209 foreach (var subVariable
in variable.SubVariables)
4212 subVariable.Qualifiers = Qualifier.None;
4213 subVariable.Qualifiers |= variable.Qualifiers;
4214 declarations.Add(subVariable);
4218 declarations.Add(declaration);
4221 shader.Declarations = declarations;
4225 private static List<StructMemberReference> GetMembers(StructType structType, List<StructMemberReference> members = null, List<Variable> fieldStack = null )
4229 if (members == null)
4231 members = (List<StructMemberReference>)structType.
GetTag(
"Members");
4232 if (members != null)
4235 members =
new List<StructMemberReference>();
4236 structType.SetTag(
"Members", members);
4239 if (fieldStack == null)
4240 fieldStack =
new List<Variable>();
4243 foreach (var field
in structType.
Fields.SelectMany(item => item.Instances()))
4245 var fieldType = field.Type.ResolveType();
4248 if (fieldType is StructType)
4250 fieldStack.Add(field);
4251 GetMembers((StructType)fieldType, members, fieldStack);
4252 fieldStack.RemoveAt(fieldStack.Count - 1);
4256 var structMember =
new StructMemberReference();
4257 structMember.Field = field;
4258 structMember.ParentFields.AddRange(fieldStack);
4260 var fieldPath =
new StringBuilder();
4261 bool isFirst =
true;
4262 foreach(var parentField
in Enumerable.Reverse(fieldStack))
4265 fieldPath.Append(
"_");
4266 fieldPath.Append(parentField.Name);
4270 if (fieldPath.Length > 0)
4271 fieldPath.Append(
"_");
4272 fieldPath.Append(field.Name);
4274 structMember.FieldNamePath = fieldPath.ToString();
4275 members.Add(structMember);
4284 return new MethodInvocationExpression(
new TypeReferenceExpression(type), expressions);
4287 private class StructMemberReference
4289 public string FieldNamePath;
4295 foreach (var parentField
in Enumerable.Reverse(ParentFields))
4299 return currentMemberRef;
4302 public List<Variable> ParentFields =
new List<Variable>();
4304 public Variable
Field;
4307 class SemanticReference
4309 public SemanticReference(
string name,
Expression variableReference)
4312 this.VariableReference = variableReference;
4325 private class TagLayout
4327 #region Constants and Fields
4329 public object Binding {
get; set; }
4331 public object Location {
get; set; }
4337 public Ast.Glsl.LayoutQualifier
Qualifier;
Base class for all vector types
SiliconStudio.Shaders.Ast.Hlsl.ConstantBuffer ConstantBuffer
static readonly ScalarType Bool
Scalar bool.
TypeBase TargetType
Gets or sets the type.
Identifier Name
Gets or sets the name.
Statement VisitStatementAsMemberInvocation(Statement statement, MethodInvocationExpression methodInvocationExpression, MemberReferenceExpression memberReferenceExpression)
Visits a statement that is a member invocation.
TypeBase Type
Gets or sets the type.
Describes a binary expression.
static readonly ScalarType Int
Scalar int.
UnaryOperator
Unary operator used in all binary expressions (except assignment expression).
Technique Visit(Technique technique)
Visits the specified technique.
List< Statement > Statements
Gets or sets the statements.
List< Expression > Items
Gets or sets the items.
TypeInference TypeInference
Gets or sets the resolved reference.
Statement Visit(Statement statement)
Visits the specified statement.
Expression Visit(ArrayInitializerExpression arrayCreationExpression)
Visits the specified array creation expression.
void PostVisitEntryPoint(MethodDefinition function)
Visits the entry point.
Expression Visit(BinaryExpression binaryExpression)
Visits the specified binary expression.
SourceSpan Span
Gets or sets the source span.
Keyword expression statement like continue; break; discard;
ShaderModel
Describes a HLSL ShaderModel (SM2, SM3, SM4...etc.)
string Text
Gets or sets the name.
SiliconStudio.Shaders.Ast.Glsl.LayoutQualifier LayoutQualifier
static readonly TextureType Texture2D
A Texture2D
Qualifier Qualifiers
Gets or sets the qualifiers.
Identifier Member
Gets or sets the member.
Statement VisitStatementAsFunctionInvocation(Statement statement, MethodInvocationExpression methodInvocationExpression, VariableReferenceExpression methodVar)
Visits a statement that is a function invocation.
Expression used to initliaze an array {...expressions,}
void Visit(IfStatement ifStatement)
Visits the specified if statement.
TypeBase Type
Gets or sets the type.
static readonly TextureType TextureCube
An TextureCube.
BinaryOperator
Binary operator used in all binary expressions (except assignment expression).
TypeBase Type
Gets or sets the type.
Node Visit(Variable variable)
Visits the specified variable.
void Visit(Shader shader)
Visits the specified shader.
static readonly TextureType Texture3D
A Texture3D.
virtual TypeBase ResolveType()
Resolves the type.
Expression Target
Gets or sets the target receving the assigment.
bool IsDimensionEmpty
Gets a value indicating whether this instance is dimension empty.
AssignmentOperator
Assignment operator used in assignment expression (a = b) or statements (a = b;)
int ColumnCount
Gets or sets the column count.
static readonly VectorType Float4
A Float4
An expression surrounded by parenthesis.
A method definition with a body of statements.
static readonly ScalarType Half
Scalar half.
Expression Visit(MemberReferenceExpression expression)
Visits the specified expression.
static readonly VectorType Int4
A Int4
static readonly ScalarType UInt
Scalar unsigned int.
TypeInference TypeInference
Gets or sets the type reference.
static readonly ScalarType Float
Sclar float.
Expression Value
Gets or sets the value of the assigment..
Identifier Name
Gets or sets the name.
void Run(ParsingResult parserResultIn)
Runs the convertor on the specified parser result.
A declaration inside a statement.
A reference to a variable.
static readonly TextureType Texture1D
A Texture1D.
Statement Visit(StatementList statementList)
Visits the specified statement list.
Describe a register location
Base root class for all statements.
A single parameter declaration.
Describes a packoffset(value).
The type of the serialized type will be passed as a generic arguments of the serializer. Example: serializer of A becomes instantiated as Serializer{A}.
List< Expression > Arguments
Gets or sets the arguments.
void Visit(MethodDefinition function)
Visits the specified function.
SiliconStudio.Paradox.Games.Mathematics.Half Half
static TypeBase GetBaseType(TypeBase type)
A member reference in the form {this}.{Name}
The strip visitor collects all function and declaration used by a set of entrypoints and remove any u...
Expression Visit(IndexerExpression indexerExpression)
Visits the specified indexer expression.
Expression Visit(ConditionalExpression conditionalExpression)
Visits the specified conditional expression.
HRESULT Convert(_In_ const Image &srcImage, _In_ DXGI_FORMAT format, _In_ DWORD filter, _In_ float threshold, _Out_ ScratchImage &image)
static void Prepare(Shader shader)
Prepares the specified shader for glsl to hlsl conversion (before type inference analysis).
static bool IsStreamType(TypeBase targetType)
Determines whether the specified type is a a stream type.
Expression Visit(MethodInvocationExpression methodInvocationExpression)
Visits the specified method invocation expression.
Node Visit(ForStatement forStatement)
Visit the for statement and unroll it if necessary
SiliconStudio.Shaders.Ast.SourceSpan SourceSpan
Expression Visit(CastExpression castExpression)
Visits the specified cast expression.
static readonly ScalarType Double
Scalar double.
SiliconStudio.Shaders.Ast.StorageQualifier StorageQualifier
Declaration of a constant buffer.
void PrepareVisitEntryPoint(MethodDefinition function)
Prepares the visit of entry point.
Toplevel container of a shader parsing result.
bool Contains(CompositeEnum enumValue)
Determines whether [contains] [the specified enum value].
List< Parameter > Parameters
Gets or sets the parameters.
A reference to a variable.
Describe a register location
static readonly VectorType Int2
A Int2
TypeBase Type
Gets or sets the type.
OrderedSet< CompositeEnum > Values
Gets or sets the values.
Toplevel interface for a declaration.
Statement VisitStatementAsAssignExpression(Statement statement, AssignmentExpression assignmentExpression)
HlslToGlslConvertor(string entryPointName, PipelineStage pipelineStage, ShaderModel shaderModel, bool useBuiltinSemantic=true)
Initializes a new instance of the HlslToGlslConvertor class.
Expression Visit(AssignmentExpression assignExpression)
Visits the specified assign expression.
SiliconStudio.Shaders.Ast.ParameterQualifier ParameterQualifier
Statement Visit(ReturnStatement returnStatement)
Visits the specified return statement.
Identifier Name
Gets or sets the type name.
Expression Visit(VariableReferenceExpression varRefExpr)
Visits the specified var ref expr.
Collect the texture and sampler pair used in the HLSL shader.
virtual Expression Visit(ParenthesizedExpression parenthesizedExpression)
Visits the specified parenthesized expression.
Expression Target
Gets or sets the this.
List< Variable > Fields
Gets or sets the fields.
HLSL to GLSL conversion requires several steps:
_In_ size_t _In_ size_t size
PipelineStage
Enum to specify pipeline stage.
void Visit(ConstantBuffer constantBuffer)
Visits the specified constant buffer.
object GetTag(object tagKey)
Gets a tag value associated to this node..
Specialized ParameterQualifier for Hlsl.
static bool IsInteger(TypeBase type)
Determines whether the specified type is an integer.