Пример #1
0
 /// <inheritdoc/>
 public bool Equals(StructType other)
 {
     return base.Equals(other);
 }
Пример #2
0
        private void Visit(StructType structType)
        {
            Visit((Node)structType);

            if (structType.ContainsTag(ParadoxTags.ShaderScope))
                parsingInfo.StructureDefinitions.Add(structType);
        }
Пример #3
0
        /// <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));
                        }
                    }
                }
            }
        }
Пример #4
0
 /// <summary>
 /// Finds the member type reference.
 /// </summary>
 /// <param name="structType">Type of the struct.</param>
 /// <param name="memberReference">The member reference.</param>
 protected virtual void FindMemberTypeReference(StructType structType, MemberReferenceExpression memberReference)
 {
     foreach (var field in structType.Fields)
     {
         foreach (var variableDeclarator in field.Instances())
         {
             if (variableDeclarator.Name == memberReference.Member)
             {
                 memberReference.TypeInference.Declaration = variableDeclarator;
                 memberReference.TypeInference.TargetType = variableDeclarator.Type.ResolveType();
                 return;
             }
         }
     }
 }
Пример #5
0
        /// <summary>
        /// Checks if a function needs to have a stream strucutre added in its declaration
        /// </summary>
        /// <param name="methodDefinition">the method definition</param>
        /// <param name="inputStream">The stage input structure stream.</param>
        /// <param name="intermediateStream">the stream structure</param>
        /// <param name="outputStream">The stage output stream structure.</param>
        /// <param name="visitedMethods">the list of already visited methods</param>
        /// <param name="methodsWithStreams">The list of methods that have a streams argument.</param>
        /// <returns>true if needed, false otherwise</returns>
        private bool PropagateStreamsParameter(MethodDefinition methodDefinition, StructType inputStream, StructType intermediateStream, StructType outputStream, HashSet<MethodDeclaration> visitedMethods, List<MethodDeclaration> methodsWithStreams)
        {
            var needStream = false;

            if (methodDefinition != null)
            {
                if (visitedMethods.Contains(methodDefinition))
                    return methodDefinition.Parameters.Count > 0 && methodDefinition.Parameters[0].Type == intermediateStream;

                List<StreamUsageInfo> streamUsageInfos;
                if (streamsUsages.TryGetValue(methodDefinition, out streamUsageInfos))
                {
                    needStream = streamUsageInfos.Any(x => x.CallType == StreamCallType.Member || x.CallType == StreamCallType.Direct);
                    visitedMethods.Add(methodDefinition);

                    List<MethodDeclaration> calls;
                    if (TryGetMethodCalls(methodDefinition, out calls))
                        needStream = calls.Aggregate(needStream, (res, calledmethod) => res | PropagateStreamsParameter(calledmethod as MethodDefinition, inputStream, intermediateStream, outputStream, visitedMethods, methodsWithStreams));

                    if (needStream && !entryPointMethods.Contains(methodDefinition))
                    {
                        var param = new Parameter(new TypeName(intermediateStream.Name), "streams");

                        foreach (var methodRef in mainModuleMixin.ClassReferences.MethodsReferences[methodDefinition])
                        {
                            var vre = new VariableReferenceExpression(param.Name) { TypeInference = { Declaration = param, TargetType = param.Type } };
                            methodRef.Arguments.Insert(0, vre);
                        }

                        param.Qualifiers |= ParameterQualifier.InOut;
                        methodDefinition.Parameters.Insert(0, param);

                        // If any parameters in the method are streams, then replace by using the intermediate stream
                        foreach (var parameter in methodDefinition.Parameters)
                        {
                            if (parameter.Type == StreamsType.Streams)
                            {
                                parameter.Type = new TypeName(intermediateStream.Name);
                            }
                        }

                        methodsWithStreams.Add(methodDefinition);
                    }
                }

                TransformStreamsAssignments(methodDefinition, inputStream, intermediateStream, outputStream);
            }
            return needStream;
        }
Пример #6
0
        /// <summary>
        /// Transform stream assignments with correct input/ouput structures
        /// </summary>
        /// <param name="methodDefinition">the current method</param>
        /// <param name="inputStreamStruct">the input structure of the stage</param>
        /// <param name="intermediateStreamStruct">the intermediate structure of the stage</param>
        /// <param name="outputStreamStruct">the output structure of the stage</param>
        private void TransformStreamsAssignments(MethodDefinition methodDefinition, StructType inputStreamStruct, StructType intermediateStreamStruct, StructType outputStreamStruct)
        {
            var statementLists = new List<StatementList>();
            SearchVisitor.Run(
                methodDefinition,
                node =>
                {
                    if (node is StatementList)
                    {
                        statementLists.Add((StatementList)node);
                    }
                    return node;
                });

            // replace stream assignement with field values assignements
            foreach (var assignmentKeyBlock in streamAnalyzer.AssignationsToStream)
            {
                var assignment = assignmentKeyBlock.Key;
                var parent = assignmentKeyBlock.Value;
                if (!statementLists.Contains(parent))
                {
                    continue;
                }
                var index = SearchExpressionStatement(parent, assignment);

                // TODO: check that it is "output = streams"
                var statementList = CreateOutputFromStream(outputStreamStruct, (assignment.Target as VariableReferenceExpression).Name.Text, intermediateStreamStruct, "streams").ToList();
                statementList.RemoveAt(0); // do not keep the variable declaration
                methodDefinition.Body.RemoveAt(index);
                methodDefinition.Body.InsertRange(index, statementList);
            }

            // replace stream assignement with field values assignements
            foreach (var assignmentKeyBlock in streamAnalyzer.StreamAssignations)
            {
                var assignment = assignmentKeyBlock.Key;
                var parent = assignmentKeyBlock.Value;
                if (!statementLists.Contains(parent))
                {
                    continue;
                }
                var index = SearchExpressionStatement(parent, assignment);

                var statementList = CreateStreamFromInput(intermediateStreamStruct, "streams", inputStreamStruct, assignment.Value, false).ToList();
                statementList.RemoveAt(0); // do not keep the variable declaration
                parent.RemoveAt(index);
                parent.InsertRange(index, statementList);
            }

            foreach (var variableAndParent in streamAnalyzer.VariableStreamsAssignment)
            {
                var variable = variableAndParent.Key;
                var parent = variableAndParent.Value;

                if (!statementLists.Contains(parent))
                {
                    continue;
                }

                variable.Type = new TypeName(intermediateStreamStruct.Name);
            }
        }
Пример #7
0
        /// <summary>
        /// Generates a stream structure and add them to the Ast - for the hull shader and hull shader constant
        /// </summary>
        /// <param name="entryPoint">the entrypoint function</param>
        /// <param name="entryPointHSConstant">entrypoint for the hull shader constant</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 GenerateStreamsForHullShader(MethodDefinition entryPoint, MethodDefinition entryPointHSConstant, StreamStageUsage streamStageUsage, string stageName, StructType prevOuputStructure)
        {
            if (entryPoint != null)
            {
                // same behavior as geometry shader
                var outStreamStruct = GenerateStreamsWithSpecialDataInput(entryPoint, streamStageUsage, stageName, prevOuputStructure);
                var inStreamStruct = prevOuputStructure ?? shader.Members.OfType<StructType>().FirstOrDefault(x => x.Name.Text == stageName + "_INPUT");
                var intermediateStreamStruct = shader.Members.OfType<StructType>().FirstOrDefault(x => x.Name.Text == stageName + "_STREAMS");

                if (inStreamStruct == null)
                    throw new Exception("inStreamStruct cannot be null");

                var inStructType = new TypeName(inStreamStruct.Name);
                var outStructType = new TypeName(outStreamStruct.Name);

                // get the Output parameter, its name and remove it
                var outputName = "output";
                var outputParam = entryPoint.Parameters.FirstOrDefault(x => x.Type.Name.Text == outStreamStruct.Name.Text);
                if (outputParam != null)
                {
                    outputName = outputParam.Name.Text; // get the name of the parameter
                    entryPoint.Parameters.Remove(outputParam); // remove the parameter
                }

                entryPoint.Body.Add(new ReturnStatement { Value = new VariableReferenceExpression(outputName) });
                entryPoint.Body.Insert(0, CreateStructInit(outStreamStruct, outputName));
                entryPoint.ReturnType = outStructType;

                if (entryPointHSConstant != null)
                    GenerateStreamsForHullShaderConstant(entryPointHSConstant, inStructType, outStructType);

                return outStreamStruct;
            }

            return prevOuputStructure;
        }
Пример #8
0
        /// <summary>
        /// Creates a stream structure and assign its default values
        /// </summary>
        /// <param name="streamStruct">the structure</param>
        /// <param name="streamName">the name of the stream</param>
        /// <param name="inputStruct">the inputStructure</param>
        /// <param name="initialValue">the initial value of the struture</param>
        /// <param name="scopeStack">???</param>
        /// <returns>a collection of statements to insert in the body of a method</returns>
        private static IEnumerable<Statement> CreateStreamFromInput(StructType streamStruct, string streamName, StructType inputStruct, Expression initialValue, bool basicTransformation = true)
        {
            yield return CreateStructInit(streamStruct, streamName);

            foreach (var statement in AssignStreamFromInput(streamStruct, streamName, inputStruct, initialValue, basicTransformation))
            {
                yield return statement;
            }
        }
Пример #9
0
        /// <summary>
        /// Generates a stream structure and add them to the Ast
        /// </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 GenerateStreams(MethodDefinition entryPoint, StreamStageUsage streamStageUsage, string stageName, StructType prevOuputStructure, bool autoGenSem = true)
        {
            if (entryPoint != null)
            {
                // create the stream structures
                var inStreamStruct = prevOuputStructure ?? CreateStreamStructure(streamStageUsage.InStreamList, stageName + "_INPUT");
                var outStreamStruct = CreateStreamStructure(streamStageUsage.OutStreamList, stageName + "_OUTPUT", true, autoGenSem);

                var intermediateStreamStruct = CreateIntermediateStructType(streamStageUsage, stageName);

                // modify the entrypoint
                if (inStreamStruct.Fields.Count != 0)
                {
                    entryPoint.Parameters.Add(new Parameter(new TypeName(inStreamStruct.Name), "__input__"));
                    entryPoint.Parameters[0].Qualifiers.Values.Remove(ParameterQualifier.InOut);
                }

                // add the declaration statements to the entrypoint and fill with the values
                entryPoint.Body.InsertRange(0, CreateStreamFromInput(intermediateStreamStruct, "streams", inStreamStruct, new VariableReferenceExpression("__input__")));
                if (outStreamStruct.Fields.Count != 0)
                {
                    entryPoint.Body.AddRange(CreateOutputFromStream(outStreamStruct, "__output__", intermediateStreamStruct, "streams"));
                    entryPoint.Body.Add(new ReturnStatement { Value = new VariableReferenceExpression("__output__") });
                    entryPoint.ReturnType = new TypeName(outStreamStruct.Name);
                }

                // explore all the called functions
                var visitedMethods = new HashSet<MethodDeclaration>();
                var methodsWithStreams = new List<MethodDeclaration>();
                PropagateStreamsParameter(entryPoint, inStreamStruct, intermediateStreamStruct, outStreamStruct, visitedMethods, methodsWithStreams);
                
                CheckCrossStageMethodCall(streamStageUsage.ShaderStage, methodsWithStreams);

                if (prevOuputStructure == null)
                    shader.Members.Insert(0, inStreamStruct);
                if (outStreamStruct.Fields.Count != 0)
                    shader.Members.Insert(0, outStreamStruct);
                shader.Members.Insert(0, intermediateStreamStruct);

                return outStreamStruct;
            }

            return prevOuputStructure;
        }
Пример #10
0
        /// <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;
        }
Пример #11
0
 /// <summary>
 /// Creates an declaration for this structure
 /// </summary>
 /// <param name="structType">the structure</param>
 /// <param name="structVarName">the name of the variable</param>
 /// <returns>the declaration statement</returns>
 private static DeclarationStatement CreateStructInit(StructType structType, string structVarName)
 {
     return new DeclarationStatement(
         new Variable(new TypeName(structType.Name), structVarName)
             {
                 InitialValue = new CastExpression { From = new LiteralExpression(0), Target = new TypeName(structType.Name) }
             });
 }
Пример #12
0
        /// <summary>
        /// Generate a stream structure
        /// </summary>
        /// <param name="streamsDeclarationList">the list of the declarations</param>
        /// <param name="structName">the name of the structure</param>
        /// <returns>the structure</returns>
        private static StructType CreateStreamStructure(List<IDeclaration> streamsDeclarationList, string structName, bool useSem = true, bool addAutoSem = true)
        {
            var tempStruct = new StructType { Name = new Identifier(structName) };
            foreach (var streamDecl in streamsDeclarationList)
            {
                var streamVar = streamDecl as Variable;
                if (streamVar != null)
                {
                    var variable = new Variable(streamVar.Type, streamVar.Name) { Span = streamVar.Span };
                    if (useSem)
                        foreach (var qualifier in streamVar.Qualifiers.OfType<Semantic>())
                            variable.Qualifiers |= qualifier;

                    if (useSem && addAutoSem)
                    {
                        var semantic = variable.Qualifiers.Values.OfType<Semantic>().FirstOrDefault();
                        if (semantic == null)
                            variable.Qualifiers |= new Semantic(variable.Name.Text.ToUpper() + "_SEM");
                    }

                    tempStruct.Fields.Add(variable);
                }
            }
            return tempStruct;
        }
Пример #13
0
        /// <summary>
        /// Creates an output stream structure and assign its default values
        /// </summary>
        /// <param name="outputStruct">the structuer</param>
        /// <param name="outputName">the name of the structure</param>
        /// <param name="streamStruct">>the initial value of the struture</param>
        /// <param name="streamName">the name of the stream</param>
        /// <returns>a collection of statements to insert in the body of a method</returns>
        private static IEnumerable<Statement> CreateOutputFromStream(StructType outputStruct, string outputName, StructType streamStruct, string streamName)
        {
            yield return CreateStructInit(outputStruct, outputName);

            foreach (var statement in AssignOutputFromStream(outputStruct, outputName, streamStruct, streamName))
            {
                yield return statement;
            }
        }
Пример #14
0
        public virtual void Visit(StructType structType)
        {
            WriteLinkLine(structType);

            // Pre Attributes
            Write(structType.Attributes, true);

            WriteLinkLine(structType);
            Write("struct");
            if (structType.Name != null)
            {
                Write(" ");
                Write(structType.Name);
                WriteSpace();
            }

            // Post Attributes
            Write(structType.Attributes, false);

            OpenBrace();

            foreach (var variableDeclaration in structType.Fields) 
                VisitDynamic(variableDeclaration);

            CloseBrace(false).Write(";").WriteLine();
        }
Пример #15
0
        /// <summary>
        /// Generates a stream structure and add them to the Ast - for the domain 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 GenerateStreamsForDomainShader(MethodDefinition entryPoint, StreamStageUsage streamStageUsage, string stageName, StructType prevOuputStructure)
        {
            if (entryPoint != null)
            {
                var outStreamStruct = GenerateStreamsForHullShader(entryPoint, null, streamStageUsage, stageName, prevOuputStructure);

                var visitedMethods = new Stack<MethodDeclaration>();
                RecursiveRename(entryPoint, null, null, null, new TypeName("HS_CONSTANTS"), visitedMethods);

                return outStreamStruct;
            }

            return prevOuputStructure;
        }
        /// <summary>
        /// Visit a structure and store its definition
        /// </summary>
        /// <param name="structType">the structure definition</param>
        public override Node Visit(StructType structType)
        {
            if (structType.ContainsTag(XenkoTags.ShaderScope))
                parsingInfo.StructureDefinitions.Add(structType);

            return base.Visit(structType);
        }
Пример #17
0
 /// <summary>
 /// Creates assignement statements with its default value
 /// </summary>
 /// <param name="outputStruct">the output structure</param>
 /// <param name="outputName">the name of the output stream</param>
 /// <param name="streamStruct">the stream structure</param>
 /// <param name="streamName">the name of the stream</param>
 /// <returns>a collection of statements</returns>
 private static IEnumerable<Statement> AssignOutputFromStream(StructType outputStruct, string outputName, StructType streamStruct, string streamName)
 {
     foreach (var currentField in outputStruct.Fields)
     {
         yield return new ExpressionStatement(
             new AssignmentExpression(
                 AssignmentOperator.Default,
                 new MemberReferenceExpression(new VariableReferenceExpression(outputName), currentField.Name),
                 new MemberReferenceExpression(new VariableReferenceExpression(streamName), currentField.Name)));
     }
 }