public virtual void Visit(DeclarationStatement declarationStatement) { WriteLinkLine(declarationStatement); VisitDynamic(declarationStatement.Content); }
/// <inheritdoc /> public override void Visit(DeclarationStatement declarationStatement) { WriteLinkLine(declarationStatement); VisitDynamic(declarationStatement.Content); }
/// <summary> /// Modify the Hull shader constant /// </summary> /// <param name="entryPoint">the entrypoint method</param> /// <param name="inStreamStructTypeName">the input structure of the Hull shader</param> /// <param name="outStreamStructTypeName">the output structure of the Hull shader</param> private void GenerateStreamsForHullShaderConstant(MethodDefinition entryPoint, TypeName inStreamStructTypeName, TypeName outStreamStructTypeName) { if (entryPoint != null) { var constStreamStruct = CreateStreamStructure(mainModuleMixin.VirtualTable.Variables.Select(x => x.Variable).Where(x => x.Qualifiers.Contains(ParadoxStorageQualifier.PatchStream)).Distinct().ToList<IDeclaration>(), "HS_CONSTANTS"); var typeConst = new TypeName(constStreamStruct.Name); var visitedMethods = new Stack<MethodDeclaration>(); RecursiveRename(entryPoint, inStreamStructTypeName, outStreamStructTypeName, outStreamStructTypeName, typeConst, visitedMethods); // get the Constants parameter, its name and remove it var constParamName = "constants"; var constParam = entryPoint.Parameters.FirstOrDefault(x => x.Type.Name.Text == constStreamStruct.Name.Text); if (constParam != null) { constParamName = constParam.Name.Text; entryPoint.Parameters.Remove(constParam); // remove the parameter } var constDecl = new DeclarationStatement( new Variable(typeConst, constParamName) { InitialValue = new CastExpression { From = new LiteralExpression(0), Target = new TypeName(constStreamStruct.Name) } }); entryPoint.Body.Insert(0, constDecl); // insert structure instance declaration entryPoint.Body.Add(new ReturnStatement(new VariableReferenceExpression(constParamName))); // add a return statement entryPoint.ReturnType = typeConst; // change the return type shader.Members.Insert(0, constStreamStruct); } }
/// <summary> /// Creates assignement statements with its default value /// </summary> /// <param name="streamStruct">the stream structure</param> /// <param name="streamName">the name of the stream</param> /// <param name="inputStruct">the input structure</param> /// <param name="initialValue">the initial value</param> /// <param name="scopeStack">???</param> /// <returns>A collection of statements</returns> private static IEnumerable<Statement> AssignStreamFromInput(StructType streamStruct, string streamName, StructType inputStruct, Expression initialValue, bool basicTransformation) { foreach (var currentField in inputStruct.Fields) { // Ignore fields that don't exist in Streams. // It could happen if HSConstantMain references a stream (gets added to HS_OUTPUT), // and in HSMain CreateStreamFromInput() is called (this stream doesn't exist in DS_STREAMS). if (streamStruct.Fields.All(x => x.Name != currentField.Name)) continue; // If we have a scope stack (advanced analysis), then convert expression by appending // field to each reference to a variable of inputStruct type // i.e. "output = input1 * 3 + input2 * 5" will become "output.A = input1.A * 3 + input2.A * 5" // Otherwise consider it is as a simple a variable reference and directly append field. if (basicTransformation) { yield return new ExpressionStatement( new AssignmentExpression( AssignmentOperator.Default, new MemberReferenceExpression(new VariableReferenceExpression(streamName), currentField.Name), new MemberReferenceExpression(initialValue, currentField.Name))); } else { //yield return AssignStreamFieldFromInput(streamName, inputStruct, initialValue, scopeStack, currentField); foreach (var field in streamStruct.Fields.Where(x => x.Name == currentField.Name)) // TODO: where might be useless { if (field.Type is ArrayType) { //create a for loop var iteratorName = field.Name.Text + "_Iter"; var iterator = new Variable(ScalarType.Int, iteratorName, new LiteralExpression(0)); var start = new DeclarationStatement(iterator); var condition = new BinaryExpression(BinaryOperator.Less, new VariableReferenceExpression(iterator), (field.Type as ArrayType).Dimensions[0]); var next = new UnaryExpression(UnaryOperator.PreIncrement, new VariableReferenceExpression(iterator)); var forLoop = new ForStatement(start, condition, next); var fieldAssigner = new StreamFieldVisitor(field, new VariableReferenceExpression(iterator)); var clonedExpression = fieldAssigner.Run(ParadoxAssignmentCloner.Run(initialValue)); forLoop.Body = new ExpressionStatement( new AssignmentExpression( AssignmentOperator.Default, new IndexerExpression(new MemberReferenceExpression(new VariableReferenceExpression(streamName), currentField.Name), new VariableReferenceExpression(iterator)), clonedExpression)); yield return forLoop; } else { var fieldAssigner = new StreamFieldVisitor(field); //var clonedExpression = fieldAssigner.Run(initialValue.DeepClone()); var clonedExpression = fieldAssigner.Run(ParadoxAssignmentCloner.Run(initialValue)); yield return new ExpressionStatement( new AssignmentExpression( AssignmentOperator.Default, new MemberReferenceExpression(new VariableReferenceExpression(streamName), currentField.Name), clonedExpression)); } } } } }
/// <summary> /// Generates a stream structure and add them to the Ast - for the geometry shader /// </summary> /// <param name="entryPoint">the entrypoint function</param> /// <param name="streamStageUsage">the stream usage in this stage</param> /// <param name="stageName">the name of the stage</param> /// <param name="prevOuputStructure">the output structutre from the previous stage</param> /// <returns>the new output structure</returns> private StructType GenerateStreamsWithSpecialDataInput(MethodDefinition entryPoint, StreamStageUsage streamStageUsage, string stageName, StructType prevOuputStructure) { if (entryPoint != null) { var inStreamStruct = prevOuputStructure ?? CreateStreamStructure(streamStageUsage.InStreamList, stageName + "_INPUT"); var outStreamStruct = CreateStreamStructure(streamStageUsage.OutStreamList, stageName + "_OUTPUT"); var mixin = entryPoint.GetTag(ParadoxTags.ShaderScope) as ModuleMixin; var intermediateStreamStruct = CreateIntermediateStructType(streamStageUsage, stageName); // put the streams declaration at the beginning of the method body var streamsDeclaration = new DeclarationStatement(new Variable(new TypeName(intermediateStreamStruct.Name), "streams") { InitialValue = new CastExpression { From = new LiteralExpression(0), Target = new TypeName(intermediateStreamStruct.Name) } }); entryPoint.Body.Insert(0, streamsDeclaration); // add the declaration statements to the entrypoint and fill with the values var outputStatements = CreateOutputFromStream(outStreamStruct, "output", intermediateStreamStruct, "streams").ToList(); var outputVre = new VariableReferenceExpression(((outputStatements.First() as DeclarationStatement).Content as Variable).Name); var replacor = new ParadoxReplaceAppend(streamAnalyzer.AppendMethodCalls, outputStatements, outputVre); ReplaceAppendMethod(entryPoint, replacor); var visitedMethods = new Stack<MethodDeclaration>(); var inStructType = new TypeName(inStreamStruct.Name); var outStructType = new TypeName(outStreamStruct.Name); RecursiveRename(entryPoint, inStructType, null, outStructType, null, visitedMethods); // explore all the called functions var streamsVisitedMethods = new HashSet<MethodDeclaration>(); var methodsWithStreams = new List<MethodDeclaration>(); PropagateStreamsParameter(entryPoint, inStreamStruct, intermediateStreamStruct, outStreamStruct, streamsVisitedMethods, methodsWithStreams); CheckCrossStageMethodCall(streamStageUsage.ShaderStage, methodsWithStreams); if (prevOuputStructure == null) shader.Members.Insert(0, inStreamStruct); shader.Members.Insert(0, outStreamStruct); shader.Members.Insert(0, intermediateStreamStruct); return outStreamStruct; } return prevOuputStructure; }