4 using System.Collections.Generic;
7 using SiliconStudio.Paradox.Shaders.Parser.Ast;
8 using SiliconStudio.Paradox.Shaders.Parser.Utility;
9 using SiliconStudio.Shaders.Ast;
10 using SiliconStudio.Shaders.Ast.Hlsl;
11 using SiliconStudio.Shaders.Utility;
15 namespace SiliconStudio.Paradox.Shaders.Parser.Mixins
17 internal class ParadoxStreamCreator
19 #region private static members
21 private readonly
static string[] GeometryShaderUnOptimizedSemantics = {
"SV_RenderTargetArrayIndex" };
25 #region Private members
35 private ModuleMixin mainModuleMixin;
40 private List<ModuleMixin> mixinInheritance =
new List<ModuleMixin>();
45 private HashSet<MethodDefinition> entryPointMethods =
new HashSet<MethodDefinition>();
50 private Dictionary<MethodDeclaration, List<StreamUsageInfo>> streamsUsages =
new Dictionary<MethodDeclaration, List<StreamUsageInfo>>();
55 private Dictionary<PdxShaderStage, List<MethodDeclaration>> methodsPerShaderStage =
new Dictionary<PdxShaderStage, List<MethodDeclaration>>();
60 private ParadoxStreamAnalyzer streamAnalyzer;
73 shader = shaderClassType;
74 mainModuleMixin = mixin;
75 mixinInheritance = mixins;
81 var streamCreator =
new ParadoxStreamCreator(shaderClassType, mixin, mixins, errorLog);
91 streamAnalyzer =
new ParadoxStreamAnalyzer(errorWarningLog);
92 streamAnalyzer.Run(shader);
94 if (errorWarningLog.HasErrors)
97 streamsUsages = streamAnalyzer.StreamsUsageByMethodDefinition;
100 var vertexShaderMethod = FindEntryPoint(
"VSMain");
101 var hullShaderMethod = FindEntryPoint(
"HSMain");
102 var hullConstantShaderMethod = FindEntryPoint(
"HSConstantMain");
103 var domainShaderMethod = FindEntryPoint(
"DSMain");
104 var geometryShaderMethod = FindEntryPoint(
"GSMain");
105 var pixelShaderMethod = FindEntryPoint(
"PSMain");
106 var computeShaderMethod = FindEntryPoint(
"CSMain");
108 if (vertexShaderMethod != null)
110 if (pixelShaderMethod != null)
112 if (geometryShaderMethod != null)
114 if (hullShaderMethod != null)
116 if (domainShaderMethod != null)
118 if (computeShaderMethod != null)
121 if (!(hullShaderMethod == null && hullConstantShaderMethod == null && domainShaderMethod == null) && (hullShaderMethod == null || hullConstantShaderMethod == null || domainShaderMethod == null))
123 errorWarningLog.Error(ParadoxMessageCode.ErrorIncompleteTesselationShader,
new SourceSpan());
127 StreamStageUsage streamStageUsageVS = vertexShaderMethod == null ? null : StreamAnalysisPerShader(vertexShaderMethod.GetTag(
ParadoxTags.
ShaderScope) as ModuleMixin, vertexShaderMethod, PdxShaderStage.Vertex);
128 StreamStageUsage streamStageUsageHS = hullShaderMethod == null ? null : StreamAnalysisPerShader(hullShaderMethod.GetTag(
ParadoxTags.
ShaderScope) as ModuleMixin, hullShaderMethod, PdxShaderStage.Hull);
129 StreamStageUsage streamStageUsageHSCS = hullConstantShaderMethod == null ? null : StreamAnalysisPerShader(hullConstantShaderMethod.GetTag(
ParadoxTags.
ShaderScope) as ModuleMixin, hullConstantShaderMethod, PdxShaderStage.Constant);
130 StreamStageUsage streamStageUsageDS = domainShaderMethod == null ? null : StreamAnalysisPerShader(domainShaderMethod.GetTag(
ParadoxTags.
ShaderScope) as ModuleMixin, domainShaderMethod, PdxShaderStage.Domain);
131 StreamStageUsage streamStageUsageGS = geometryShaderMethod == null ? null : StreamAnalysisPerShader(geometryShaderMethod.GetTag(
ParadoxTags.
ShaderScope) as ModuleMixin, geometryShaderMethod, PdxShaderStage.Geometry);
132 StreamStageUsage streamStageUsagePS = pixelShaderMethod == null ? null : StreamAnalysisPerShader(pixelShaderMethod.GetTag(
ParadoxTags.
ShaderScope) as ModuleMixin, pixelShaderMethod, PdxShaderStage.Pixel);
133 StreamStageUsage streamStageUsageCS = computeShaderMethod == null ? null : StreamAnalysisPerShader(computeShaderMethod.GetTag(
ParadoxTags.
ShaderScope) as ModuleMixin, computeShaderMethod, PdxShaderStage.Compute);
136 if (streamStageUsageGS != null && streamStageUsageVS != null)
138 var needToAdd =
true;
139 foreach (var variable
in streamStageUsageGS.OutStreamList.OfType<
Variable>())
141 var sem = variable.Qualifiers.OfType<
Semantic>().FirstOrDefault();
142 if (sem != null && sem.Name.Text ==
"SV_Position")
152 foreach (var variable
in streamStageUsageVS.OutStreamList.OfType<
Variable>())
154 var sem = variable.Qualifiers.OfType<
Semantic>().FirstOrDefault();
155 if (sem != null && sem.Name.Text ==
"SV_Position")
157 streamStageUsageGS.OutStreamList.Add(variable);
167 var shaderStreamsUsage =
new List<StreamStageUsage>();
170 if (vertexShaderMethod != null)
172 entryPointMethods.Add(vertexShaderMethod);
173 shaderStreamsUsage.Add(streamStageUsageVS);
175 if (hullShaderMethod != null)
177 entryPointMethods.Add(hullShaderMethod);
178 shaderStreamsUsage.Add(streamStageUsageHS);
180 if (hullConstantShaderMethod != null)
182 entryPointMethods.Add(hullConstantShaderMethod);
183 shaderStreamsUsage.Add(streamStageUsageHSCS);
185 if (domainShaderMethod != null)
187 entryPointMethods.Add(domainShaderMethod);
188 shaderStreamsUsage.Add(streamStageUsageDS);
190 if (geometryShaderMethod != null)
192 entryPointMethods.Add(geometryShaderMethod);
193 shaderStreamsUsage.Add(streamStageUsageGS);
195 if (pixelShaderMethod != null)
197 entryPointMethods.Add(pixelShaderMethod);
198 shaderStreamsUsage.Add(streamStageUsagePS);
200 if (computeShaderMethod != null)
202 entryPointMethods.Add(computeShaderMethod);
205 BubbleUpStreamUsages(shaderStreamsUsage);
207 if (computeShaderMethod != null)
208 ComputeShaderStreamAnalysis(streamStageUsageCS);
213 var tagCleaner =
new ParadoxTagCleaner();
214 tagCleaner.Run(shader);
216 outputStructure = GenerateStreams(vertexShaderMethod, streamStageUsageVS,
"VS", outputStructure);
217 outputStructure = GenerateStreamsForHullShader(hullShaderMethod, hullConstantShaderMethod, streamStageUsageHS,
"HS", outputStructure);
218 outputStructure = GenerateStreamsForDomainShader(domainShaderMethod, streamStageUsageDS,
"DS", outputStructure);
219 outputStructure = GenerateStreamsWithSpecialDataInput(geometryShaderMethod, streamStageUsageGS,
"GS", outputStructure);
220 outputStructure = GenerateStreams(pixelShaderMethod, streamStageUsagePS,
"PS", outputStructure,
false);
222 outputStructure = GenerateStreams(computeShaderMethod, streamStageUsageCS,
"CS", null);
224 RemoveUselessAndSortMethods();
229 #region Private methods
234 private void RemoveUselessAndSortMethods()
237 shader.Members.RemoveAll(methods.Contains);
239 var zeroCalledMethods =
new HashSet<MethodDeclaration>();
240 var methodReferenceCounter = methods.ToDictionary(x => x, x => 0);
242 foreach (var reference
in streamsUsages)
244 foreach (var usage
in reference.Value.Where(x => x.CallType ==
StreamCallType.Method))
247 if (methodReferenceCounter.TryGetValue(usage.MethodDeclaration, out value))
248 methodReferenceCounter[usage.MethodDeclaration] = value + 1;
249 else if (!entryPointMethods.Contains(usage.MethodDeclaration))
250 zeroCalledMethods.Add(usage.MethodDeclaration);
255 zeroCalledMethods.UnionWith(methodReferenceCounter.Where(x => x.Value == 0 && !entryPointMethods.Contains(x.Key)).Select(x => x.Key));
256 BuildOrderedMethodUsageList(zeroCalledMethods, methodReferenceCounter);
258 var finalMethodsList = BuildOrderedMethodUsageList(
new HashSet<MethodDeclaration>(entryPointMethods), methodReferenceCounter);
259 finalMethodsList.Reverse();
260 shader.Members.AddRange(finalMethodsList);
269 private List<MethodDeclaration> BuildOrderedMethodUsageList(HashSet<MethodDeclaration> startList, Dictionary<MethodDeclaration, int> methodReferenceCounter)
271 var finalMethodsList =
new List<MethodDeclaration>();
272 while (startList.Count > 0)
274 var newZeroCalledMethods =
new List<MethodDeclaration>();
276 foreach (var method
in startList)
278 finalMethodsList.Add(method);
280 List<StreamUsageInfo> reference;
281 if (streamsUsages.TryGetValue(method, out reference))
283 foreach (var usage
in reference.Where(x => x.CallType ==
StreamCallType.Method))
286 if (methodReferenceCounter.TryGetValue(usage.MethodDeclaration, out value))
288 methodReferenceCounter[usage.MethodDeclaration] = value - 1;
290 newZeroCalledMethods.Add(usage.MethodDeclaration);
297 startList.UnionWith(newZeroCalledMethods);
300 return finalMethodsList;
310 for (
int i = mixinInheritance.Count - 1; i >= 0; --i)
312 var mixin = mixinInheritance[i];
314 for (
int j = 0; j < i; ++j)
316 count += mixin.MixinName == mixinInheritance[j].MixinName ? 1 : 0;
319 var method = mixin.LocalVirtualTable.Methods.FirstOrDefault(x => x.Method.Name.Text == name && x.Method is
MethodDefinition);
334 var visitedMethods =
new List<MethodDeclaration>();
335 var streamStageUsage =
new StreamStageUsage {
ShaderStage = shaderStage };
336 FindStreamsUsage(entryPoint, streamStageUsage.InStreamList, streamStageUsage.OutStreamList, visitedMethods);
337 visitedMethods.Clear();
339 return streamStageUsage;
349 private void FindStreamsUsage(
MethodDeclaration currentMethod, List<IDeclaration> inStreamList, List<IDeclaration> outStreamList, List<MethodDeclaration> visitedMethods)
351 if (visitedMethods.Contains(currentMethod))
353 errorWarningLog.Error(ParadoxMessageCode.ErrorRecursiveCall, currentMethod.Span, currentMethod);
357 if (currentMethod != null)
359 var newListVisitedMethods =
new List<MethodDeclaration>();
360 newListVisitedMethods.AddRange(visitedMethods);
361 newListVisitedMethods.Add(currentMethod);
363 List<StreamUsageInfo> streamUsageList;
364 if (streamsUsages.TryGetValue(currentMethod, out streamUsageList))
367 foreach (var streamUsage
in streamUsageList)
371 var isOutStream = outStreamList.Contains(streamUsage.Variable);
372 var isInStream = inStreamList.Contains(streamUsage.Variable);
374 if (streamUsage.Usage ==
StreamUsage.Write && !isOutStream)
375 outStreamList.Add(streamUsage.Variable);
376 else if (streamUsage.Usage ==
StreamUsage.Read && !isOutStream && !isInStream)
377 inStreamList.Add(streamUsage.Variable);
381 if (streamUsage.MethodDeclaration != null)
382 FindStreamsUsage(streamUsage.MethodDeclaration, inStreamList, outStreamList, newListVisitedMethods);
385 errorWarningLog.Error(ParadoxMessageCode.ErrorStreamUsageInitialization, streamUsage.Expression.Span, streamUsage.Expression);
395 private void BubbleUpStreamUsages(List<StreamStageUsage> streamStageUsages)
397 for (
int i = streamStageUsages.Count - 1; i > 0; --i)
399 var nextStreamUsage = streamStageUsages[i];
400 var prevStreamUsage = streamStageUsages[i - 1];
405 var semVar =
new List<IDeclaration>();
406 var nonSemVar =
new List<IDeclaration>();
407 foreach (var variable
in nextStreamUsage.OutStreamList)
409 var sem = (variable as
Variable).Qualifiers.OfType<
Semantic>().FirstOrDefault();
410 if (sem != null && (sem.Name.Text.StartsWith(
"SV_Target") || sem.Name.Text ==
"SV_Depth"))
411 semVar.Add(variable);
413 nonSemVar.Add(variable);
415 nextStreamUsage.InterStreamList.AddRange(nonSemVar);
416 nextStreamUsage.OutStreamList = semVar;
422 foreach (var variable
in nextStreamUsage.InStreamList)
424 if (!prevStreamUsage.OutStreamList.Contains(variable))
426 prevStreamUsage.OutStreamList.Add(variable);
428 if (!prevStreamUsage.InStreamList.Contains(variable))
429 prevStreamUsage.InStreamList.Add(variable);
434 var toKeep =
new List<IDeclaration>();
435 foreach (var variable
in prevStreamUsage.OutStreamList)
437 var sem = (variable as
Variable).Qualifiers.OfType<
Semantic>().FirstOrDefault();
438 if (nextStreamUsage.InStreamList.Contains(variable)
439 || ((nextStreamUsage.ShaderStage == PdxShaderStage.Pixel || nextStreamUsage.ShaderStage == PdxShaderStage.Geometry) && sem != null && sem.Name.Text ==
"SV_Position"))
440 toKeep.Add(variable);
441 else if (nextStreamUsage.ShaderStage ==
PdxShaderStage.Pixel && prevStreamUsage.ShaderStage ==
PdxShaderStage.Geometry && sem != null && sem.Name.Text ==
"SV_RenderTargetArrayIndex")
443 toKeep.Add(variable);
444 nextStreamUsage.InStreamList.Add(variable);
447 prevStreamUsage.InterStreamList.Add(variable);
450 prevStreamUsage.OutStreamList.Clear();
451 prevStreamUsage.OutStreamList.AddRange(toKeep);
459 private void ComputeShaderStreamAnalysis(StreamStageUsage streamStageUsage)
463 streamStageUsage.InterStreamList.AddRange(streamStageUsage.OutStreamList);
464 streamStageUsage.OutStreamList.Clear();
478 if (entryPoint != null)
481 var inStreamStruct = prevOuputStructure ?? CreateStreamStructure(streamStageUsage.InStreamList, stageName +
"_INPUT");
482 var outStreamStruct = CreateStreamStructure(streamStageUsage.OutStreamList, stageName +
"_OUTPUT",
true, autoGenSem);
484 var intermediateStreamStruct = CreateIntermediateStructType(streamStageUsage, stageName);
487 if (inStreamStruct.Fields.Count != 0)
489 entryPoint.Parameters.Add(
new Parameter(
new TypeName(inStreamStruct.Name),
"input"));
490 entryPoint.Parameters[0].Qualifiers.Values.Remove(ParameterQualifier.InOut);
494 entryPoint.Body.InsertRange(0, CreateStreamFromInput(intermediateStreamStruct,
"streams", inStreamStruct,
new VariableReferenceExpression(
"input")));
495 if (outStreamStruct.Fields.Count != 0)
497 entryPoint.Body.AddRange(CreateOutputFromStream(outStreamStruct,
"output", intermediateStreamStruct,
"streams"));
499 entryPoint.ReturnType =
new TypeName(outStreamStruct.Name);
503 var visitedMethods =
new HashSet<MethodDeclaration>();
504 var methodsWithStreams =
new List<MethodDeclaration>();
505 PropagateStreamsParameter(entryPoint, inStreamStruct, intermediateStreamStruct, outStreamStruct, visitedMethods, methodsWithStreams);
507 CheckCrossStageMethodCall(streamStageUsage.ShaderStage, methodsWithStreams);
509 if (prevOuputStructure == null)
510 shader.Members.Insert(0, inStreamStruct);
511 if (outStreamStruct.Fields.Count != 0)
512 shader.Members.Insert(0, outStreamStruct);
513 shader.Members.Insert(0, intermediateStreamStruct);
515 return outStreamStruct;
518 return prevOuputStructure;
531 if (entryPoint != null)
533 var inStreamStruct = prevOuputStructure ?? CreateStreamStructure(streamStageUsage.InStreamList, stageName +
"_INPUT");
534 var outStreamStruct = CreateStreamStructure(streamStageUsage.OutStreamList, stageName +
"_OUTPUT");
536 var mixin = entryPoint.GetTag(ParadoxTags.ShaderScope) as ModuleMixin;
538 var intermediateStreamStruct = CreateIntermediateStructType(streamStageUsage, stageName);
541 var streamsDeclaration =
new DeclarationStatement(
new Variable(
new TypeName(intermediateStreamStruct.Name),
"streams") { InitialValue = new CastExpression { From = new LiteralExpression(0), Target = new TypeName(intermediateStreamStruct.Name) } });
542 entryPoint.Body.Insert(0, streamsDeclaration);
545 var outputStatements = CreateOutputFromStream(outStreamStruct,
"output", intermediateStreamStruct,
"streams").ToList();
548 var replacor =
new ParadoxReplaceAppend(streamAnalyzer.AppendMethodCalls, outputStatements, outputVre);
549 ReplaceAppendMethod(entryPoint, replacor);
551 var visitedMethods =
new Stack<MethodDeclaration>();
552 var inStructType =
new TypeName(inStreamStruct.Name);
553 var outStructType =
new TypeName(outStreamStruct.Name);
554 RecursiveRename(entryPoint, inStructType, null, outStructType, null, visitedMethods);
557 var streamsVisitedMethods =
new HashSet<MethodDeclaration>();
558 var methodsWithStreams =
new List<MethodDeclaration>();
559 PropagateStreamsParameter(entryPoint, inStreamStruct, intermediateStreamStruct, outStreamStruct, streamsVisitedMethods, methodsWithStreams);
561 CheckCrossStageMethodCall(streamStageUsage.ShaderStage, methodsWithStreams);
563 if (prevOuputStructure == null)
564 shader.Members.Insert(0, inStreamStruct);
565 shader.Members.Insert(0, outStreamStruct);
566 shader.Members.Insert(0, intermediateStreamStruct);
568 return outStreamStruct;
571 return prevOuputStructure;
579 private void ReplaceAppendMethod(
MethodDefinition entryPoint, ParadoxReplaceAppend replacor)
581 replacor.Run(entryPoint);
583 List<StreamUsageInfo> nextMethods;
584 if (streamsUsages.TryGetValue(entryPoint, out nextMethods))
585 nextMethods.Where(x => x.CallType ==
StreamCallType.Method).Select(x => x.MethodDeclaration as
MethodDefinition).Where(x => x != null).ToList().ForEach(x => ReplaceAppendMethod(x, replacor));
601 if (entryPoint != null)
604 var outStreamStruct = GenerateStreamsWithSpecialDataInput(entryPoint, streamStageUsage, stageName, prevOuputStructure);
605 var inStreamStruct = prevOuputStructure ?? shader.Members.OfType<
StructType>().FirstOrDefault(x => x.Name.Text == stageName +
"_INPUT");
606 var intermediateStreamStruct = shader.Members.OfType<StructType>().FirstOrDefault(x => x.Name.Text == stageName +
"_STREAMS");
608 if (inStreamStruct == null)
609 throw new Exception(
"inStreamStruct cannot be null");
611 var inStructType =
new TypeName(inStreamStruct.Name);
612 var outStructType =
new TypeName(outStreamStruct.Name);
615 var outputName =
"output";
616 var outputParam = entryPoint.Parameters.FirstOrDefault(x => x.Type.Name.Text == outStreamStruct.Name.Text);
617 if (outputParam != null)
619 outputName = outputParam.Name.Text;
620 entryPoint.Parameters.Remove(outputParam);
624 entryPoint.Body.Insert(0, CreateStructInit(outStreamStruct, outputName));
625 entryPoint.ReturnType = outStructType;
627 if (entryPointHSConstant != null)
628 GenerateStreamsForHullShaderConstant(entryPointHSConstant, inStructType, outStructType);
630 return outStreamStruct;
633 return prevOuputStructure;
644 if (entryPoint != null)
646 var constStreamStruct = CreateStreamStructure(mainModuleMixin.VirtualTable.Variables.Select(x => x.Variable).Where(x => x.Qualifiers.Contains(ParadoxStorageQualifier.PatchStream)).Distinct().ToList<IDeclaration>(),
"HS_CONSTANTS");
647 var typeConst =
new TypeName(constStreamStruct.Name);
649 var visitedMethods =
new Stack<MethodDeclaration>();
650 RecursiveRename(entryPoint, inStreamStructTypeName, outStreamStructTypeName, outStreamStructTypeName, typeConst, visitedMethods);
653 var constParamName =
"constants";
654 var constParam = entryPoint.Parameters.FirstOrDefault(x => x.Type.Name.Text == constStreamStruct.Name.Text);
655 if (constParam != null)
657 constParamName = constParam.Name.Text;
658 entryPoint.Parameters.Remove(constParam);
662 new Variable(typeConst, constParamName)
667 entryPoint.Body.Insert(0, constDecl);
670 entryPoint.ReturnType = typeConst;
672 shader.Members.Insert(0, constStreamStruct);
686 if (entryPoint != null)
688 var outStreamStruct = GenerateStreamsForHullShader(entryPoint, null, streamStageUsage, stageName, prevOuputStructure);
690 var visitedMethods =
new Stack<MethodDeclaration>();
691 RecursiveRename(entryPoint, null, null, null,
new TypeName(
"HS_CONSTANTS"), visitedMethods);
693 return outStreamStruct;
696 return prevOuputStructure;
709 private bool PropagateStreamsParameter(
MethodDefinition methodDefinition,
StructType inputStream,
StructType intermediateStream,
StructType outputStream, HashSet<MethodDeclaration> visitedMethods, List<MethodDeclaration> methodsWithStreams)
711 var needStream =
false;
713 if (methodDefinition != null)
715 if (visitedMethods.Contains(methodDefinition))
716 return methodDefinition.
Parameters.Count > 0 && methodDefinition.
Parameters[0].Type == intermediateStream;
718 List<StreamUsageInfo> streamUsageInfos;
719 if (streamsUsages.TryGetValue(methodDefinition, out streamUsageInfos))
721 needStream = streamUsageInfos.Any(x => x.CallType == StreamCallType.Member || x.CallType == StreamCallType.Direct);
722 visitedMethods.Add(methodDefinition);
724 List<MethodDeclaration> calls;
725 if (TryGetMethodCalls(methodDefinition, out calls))
726 needStream = calls.Aggregate(needStream, (res, calledmethod) => res | PropagateStreamsParameter(calledmethod as
MethodDefinition, inputStream, intermediateStream, outputStream, visitedMethods, methodsWithStreams));
728 if (needStream && !entryPointMethods.Contains(methodDefinition))
732 foreach (var methodRef
in mainModuleMixin.ClassReferences.MethodsReferences[methodDefinition])
735 methodRef.Arguments.Insert(0, vre);
738 param.Qualifiers |= ParameterQualifier.InOut;
739 methodDefinition.Parameters.Insert(0, param);
741 methodsWithStreams.Add(methodDefinition);
745 TransformStreamsAssignments(methodDefinition, inputStream, intermediateStream, outputStream);
761 foreach (var assignment
in streamAnalyzer.AssignationsToStream)
764 var index = SearchExpressionStatement(methodDefinition.
Body, assignment, out parent);
765 if (index < 0 || parent == null)
769 var statementList = CreateOutputFromStream(outputStreamStruct, (assignment.Target as
VariableReferenceExpression).
Name.
Text, intermediateStreamStruct,
"streams").ToList();
770 statementList.RemoveAt(0);
771 methodDefinition.Body.RemoveAt(index);
772 methodDefinition.Body.InsertRange(index, statementList);
776 foreach (var assignment
in streamAnalyzer.StreamAssignations)
779 var index = SearchExpressionStatement(methodDefinition.
Body, assignment, out parent);
780 if (index < 0 || parent == null)
783 var statementList = CreateStreamFromInput(intermediateStreamStruct,
"streams", inputStreamStruct, assignment.Value,
false).ToList();
784 statementList.RemoveAt(0);
785 parent.RemoveAt(index);
786 parent.InsertRange(index, statementList);
801 topStatement = ((BlockStatement)topStatement).Statements;
804 var statementList = (StatementList)topStatement;
805 var index = statementList.IndexOf(statementList.OfType<
ExpressionStatement>().FirstOrDefault(x => x.Expression == expression));
808 parentStatement = (StatementList)topStatement;
816 var index = SearchExpressionStatement(statement, expression, out parentStatement);
821 parentStatement = null;
836 if (methodDeclaration == null || visitedMethods.Contains(methodDeclaration))
839 RenameInputOutput(methodDeclaration, inputName, input2Name, outputName, constantsName);
840 visitedMethods.Push(methodDeclaration);
842 List<MethodDeclaration> calls;
843 if (TryGetMethodCalls(methodDeclaration, out calls))
845 foreach (var calledmethod
in calls)
846 RecursiveRename(calledmethod, inputName, input2Name, outputName, constantsName, visitedMethods);
857 private bool TryGetMethodCalls(
MethodDeclaration currentMethod, out List<MethodDeclaration> calledMethods)
859 List<StreamUsageInfo> streamUsageInfos;
860 if (streamsUsages.TryGetValue(currentMethod, out streamUsageInfos))
863 calledMethods = streamUsageInfos.Where(x => x.CallType == StreamCallType.Method).Select(x => x.MethodDeclaration).ToList();
867 calledMethods = null;
881 if (inputName != null)
884 replacor.Run(methodDeclaration);
886 if (input2Name != null)
889 replacor.Run(methodDeclaration);
891 if (outputName != null)
894 replacor.Run(methodDeclaration);
896 if (constantsName != null)
899 replacor.Run(methodDeclaration);
908 private void CheckCrossStageMethodCall(
PdxShaderStage shaderStage, List<MethodDeclaration> methodsWithStreams)
910 foreach (var stageList
in methodsPerShaderStage)
912 var stage = stageList.Key;
913 if (stage != shaderStage)
915 foreach (var method
in methodsWithStreams)
917 if (stageList.Value.Contains(method))
919 errorWarningLog.Error(ParadoxMessageCode.ErrorCrossStageMethodCall, method.Span, method, stage, shaderStage);
924 methodsPerShaderStage.Add(shaderStage, methodsWithStreams);
929 #region Private static methods
942 foreach (var currentField
in inputStruct.
Fields)
947 if (streamStruct.
Fields.All(x => x.Name != currentField.Name))
954 if (basicTransformation)
965 foreach (var field
in streamStruct.
Fields.Where(x => x.Name == currentField.Name))
971 var iteratorName = field.Name.Text +
"_Iter";
979 var clonedExpression = fieldAssigner.Run(ParadoxAssignmentCloner.Run(initialValue));
987 yield
return forLoop;
991 var fieldAssigner =
new StreamFieldVisitor(field);
993 var clonedExpression = fieldAssigner.Run(ParadoxAssignmentCloner.Run(initialValue));
1016 foreach (var currentField
in outputStruct.
Fields)
1037 yield
return CreateStructInit(streamStruct, streamName);
1039 foreach (var statement
in AssignStreamFromInput(streamStruct, streamName, inputStruct, initialValue, basicTransformation))
1041 yield
return statement;
1055 yield
return CreateStructInit(outputStruct, outputName);
1057 foreach (var statement
in AssignOutputFromStream(outputStruct, outputName, streamStruct, streamName))
1059 yield
return statement;
1069 private static StructType CreateStreamStructure(List<IDeclaration> streamsDeclarationList,
string structName,
bool useSem =
true,
bool addAutoSem =
true)
1072 foreach (var streamDecl
in streamsDeclarationList)
1074 var streamVar = streamDecl as
Variable;
1075 if (streamVar != null)
1077 var variable =
new Variable(streamVar.Type, streamVar.Name) { Span = streamVar.Span };
1079 foreach (var qualifier
in streamVar.Qualifiers.OfType<
Semantic>())
1080 variable.Qualifiers |= qualifier;
1082 if (useSem && addAutoSem)
1084 var semantic = variable.Qualifiers.Values.OfType<
Semantic>().FirstOrDefault();
1085 if (semantic == null)
1086 variable.Qualifiers |=
new Semantic(variable.Name.Text.ToUpper() +
"_SEM");
1089 tempStruct.Fields.Add(variable);
1101 private static StructType CreateIntermediateStructType(StreamStageUsage streamStageUsage,
string stageName)
1103 var tempList =
new List<IDeclaration>();
1104 tempList.AddRange(streamStageUsage.InStreamList);
1105 tempList.AddRange(streamStageUsage.InterStreamList);
1106 tempList.AddRange(streamStageUsage.OutStreamList);
1107 return CreateStreamStructure(tempList.Distinct().ToList(), stageName +
"_STREAMS",
false,
false);
1121 InitialValue = new CastExpression { From = new LiteralExpression(0), Target = new TypeName(structType.Name) }
1143 public List<IDeclaration> InStreamList =
new List<IDeclaration>();
1144 public List<IDeclaration> InterStreamList =
new List<IDeclaration>();
1145 public List<IDeclaration> OutStreamList =
new List<IDeclaration>();
Describes a binary expression.
static readonly ParadoxType Constants
Specialized ParameterQualifier for Hlsl.
static readonly ScalarType Int
Scalar int.
UnaryOperator
Unary operator used in all binary expressions (except assignment expression).
SiliconStudio.Shaders.Ast.ParameterQualifier ParameterQualifier
SiliconStudio.Core.Diagnostics.LoggerResult LoggerResult
string Text
Gets or sets the name.
static readonly ParadoxType Input2
BinaryOperator
Binary operator used in all binary expressions (except assignment expression).
A class to collect parsing/expression messages.
virtual IEnumerable< Node > Childrens()
Gets the child nodes.
AssignmentOperator
Assignment operator used in assignment expression (a = b) or statements (a = b;)
A method definition with a body of statements.
Identifier Name
Gets or sets the name.
A declaration inside a statement.
static readonly ParadoxType Input
Base root class for all statements.
A single parameter declaration.
A member reference in the form {this}.{Name}
StatementList Body
Gets or sets the list of statements.
SiliconStudio.Shaders.Ast.SourceSpan SourceSpan
static readonly ParadoxType Output
List< Parameter > Parameters
Gets or sets the parameters.
A reference to a variable.
ShaderStage
Enum to specify shader stage.
Identifier Name
Gets or sets the type name.
List< Variable > Fields
Gets or sets the fields.
static readonly SiliconStudio.Shaders.Ast.StorageQualifier Clone
Clone keyword (clone).