protected virtual void Visit(MethodInvocationExpression methodInvocationExpression)
        {
            // Visit childrens first
            Visit((Node)methodInvocationExpression);

            var nestedMethodRef = methodInvocationExpression.Target as VariableReferenceExpression;

            if (nestedMethodRef != null)
            {
                var nestedMethod = nestedMethodRef.TypeInference.Declaration as MethodDefinition;
                if (nestedMethod != null && !nestedMethod.IsBuiltin)
                {
                    this.ProcessMethodInvocation(methodInvocationExpression, nestedMethod);
                }
            }
        }
        public override Node Visit(MethodInvocationExpression methodInvocationExpression)
        {
            // Visit childrens first
            base.Visit(methodInvocationExpression);

            var nestedMethodRef = methodInvocationExpression.Target as VariableReferenceExpression;

            if (nestedMethodRef != null)
            {
                var nestedMethod = nestedMethodRef.TypeInference.Declaration as MethodDefinition;
                if (nestedMethod != null && !nestedMethod.IsBuiltin)
                {
                    this.ProcessMethodInvocation(methodInvocationExpression, nestedMethod);
                }
            }

            return methodInvocationExpression;
        }
Beispiel #3
0
        /// <summary>
        /// Test if a method invocation expression has the same signature.
        /// </summary>
        /// <param name="methodInvocationExpression">The method invocation expression.</param>
        /// <returns>True if the method passed has the same signature</returns>
        public bool IsSameSignature(MethodInvocationExpression methodInvocationExpression)
        {
            if (methodInvocationExpression == null)
                return false;

            Identifier methodName;
            var target = methodInvocationExpression.Target as MemberReferenceExpression;
            if (target != null)
                methodName = target.Member;
            else
            {
                var vre = methodInvocationExpression.Target as VariableReferenceExpression;
                if (vre == null)
                    return false;
                methodName = vre.Name;
            }

            if (Name != methodName)
                return false;
            if (Parameters.Count != methodInvocationExpression.Arguments.Count)
                return false;
            for (int i = 0; i < Parameters.Count; i++)
            {
                var parameter = Parameters[i];
                var parameterAgainst = methodInvocationExpression.Arguments[i];
                var parameterType = parameter.Type.ResolveType();
                
                if (parameterAgainst.TypeInference.TargetType == null)
                    return false;

                var parameterAgainstType = parameterAgainst.TypeInference.TargetType.ResolveType();
                if (parameterType != parameterAgainstType)
                    return false;
            }
            return true;
        }
Beispiel #4
0
 /// <summary>
 /// Finds the method in the mixin
 /// </summary>
 /// <param name="expression">>The expression of the method reference</param>
 /// <returns>a collection of the base methods if found</returns>
 public IEnumerable<MethodDeclarationShaderCouple> FindMethod(MethodInvocationExpression expression)
 {
     foreach (var method in LocalVirtualTable.Methods)
     {
         if (method.Method.IsSameSignature(expression) && method.Method is MethodDefinition)
             yield return method;
     }
 }
Beispiel #5
0
        protected void Visit(MethodInvocationExpression expression)
        {
            // First, dispatch to resolve type of node at deeper level
            Visit((Node)expression);

            // Add appropriate cast for all arguments
            for (int i = 0; i < expression.Arguments.Count; ++i)
            {
                var argument = expression.Arguments[i];
                var targetType = argument.TypeInference.TargetType;
                if (targetType != null && !(targetType is ObjectType))
                    expression.Arguments[i] = Cast(targetType, argument.TypeInference.ExpectedType ?? targetType, argument);
            }
        }
 /// <summary>
 /// Insert a method reference
 /// </summary>
 /// <param name="methodDeclaration">the method</param>
 /// <param name="expression">the reference</param>
 public void InsertMethod(MethodDeclaration methodDeclaration, MethodInvocationExpression expression)
 {
     if (!MethodsReferences.ContainsKey(methodDeclaration))
         MethodsReferences.Add(methodDeclaration, new HashSet<MethodInvocationExpression>());
     MethodsReferences[methodDeclaration].Add(expression);
 }
        /// <summary>
        /// Analyse the MethodInvocationExpression, link to the base calls, remove "this" from virtual calls, store in the correct list for later analysis
        /// </summary>
        /// <param name="expression">the method expression</param>
        /// <param name="methodName">the method name</param>
        /// <param name="declarations">the special declarations</param>
        protected override void ProcessMethodInvocation(MethodInvocationExpression expression, string methodName, List<IDeclaration> declarations)
        {
            bool callBaseProcessMethodInvocation = true;
            bool isNotBaseCall = true;

            // check if it is a base/this invocation
            var memberReferenceExpression = expression.Target as MemberReferenceExpression;
            if (memberReferenceExpression != null)
            {
                var variableReferenceExpression = memberReferenceExpression.Target as VariableReferenceExpression;
                if (variableReferenceExpression != null)
                {
                    switch (variableReferenceExpression.Name.Text)
                    {
                        case "base":
                            {
                                parsingInfo.BaseMethodCalls.Add(expression);
                                isNotBaseCall = false;
                                callBaseProcessMethodInvocation = false;

                                // get a base method declaration
                                MethodDeclaration baseMethod = null;
                                foreach (var mixin in analyzedModuleMixin.InheritanceList)
                                {
                                    baseMethod = mixin.LocalVirtualTable.Methods.Select(x => x.Method).FirstOrDefault(x => x.IsSameSignature(expression));
                                    if (baseMethod != null)
                                        break;
                                }
                                if (baseMethod == null)
                                    baseMethod = analyzedModuleMixin.LocalVirtualTable.Methods.Select(x => x.Method).FirstOrDefault(x => x.IsSameSignature(expression));
                                
                                if (baseMethod != null)
                                {
                                    expression.TypeInference.TargetType = baseMethod.ReturnType.ResolveType();
                                    expression.Target.TypeInference.Declaration = baseMethod;
                                }
                                else
                                    Error(XenkoMessageCode.ErrorImpossibleBaseCall, memberReferenceExpression.Span, expression, analyzedModuleMixin.MixinName);
                                break;
                            }
                        case "this":
                            {
                                // remove "this" keyword
                                var vre = new VariableReferenceExpression(memberReferenceExpression.Member);
                                expression.Target = vre;
                                
                                callBaseProcessMethodInvocation = false;
                                
                                // get top method declaration
                                var topMethod = analyzedModuleMixin.VirtualTable.Methods.Select(x => x.Method).FirstOrDefault(x => x.IsSameSignature(expression));
                                if (topMethod != null)
                                {
                                    expression.TypeInference.TargetType = topMethod.ReturnType.ResolveType();
                                    expression.Target.TypeInference.Declaration = topMethod;
                                }
                                else
                                    Error(XenkoMessageCode.ErrorImpossibleVirtualCall, memberReferenceExpression.Span, expression, analyzedModuleMixin.MixinName, analyzedModuleMixin.MixinName);

                                memberReferenceExpression = null;

                                break;
                            }
                    }
                    
                }

                if (expression.Target is MemberReferenceExpression)
                {
                    var typeCall = (expression.Target as MemberReferenceExpression).Target.TypeInference.TargetType;
                    if (typeCall is ShaderClassType)
                        declarations.AddRange(FindDeclarationsFromObject(typeCall, memberReferenceExpression.Member));
                }
            }

            // call base
            if (callBaseProcessMethodInvocation)
                base.ProcessMethodInvocation(expression, methodName, declarations);

            var methodDecl = expression.Target.TypeInference.Declaration as MethodDeclaration;
            var isBuiltIn = true;

            if (methodDecl != null)
            {
                // check if it is a recursive call
                if (ReferenceEquals(currentVisitedMethod, expression.Target.TypeInference.Declaration)) // How to handle "this" keyword?
                    Error(XenkoMessageCode.ErrorCyclicMethod, currentVisitedMethod.Span, currentVisitedMethod, analyzedModuleMixin.MixinName);

                // check if it is a build-in method
                isBuiltIn = !methodDecl.ContainsTag(XenkoTags.ShaderScope);

                if (memberReferenceExpression != null)
                {
                    var varDecl = memberReferenceExpression.Target.TypeInference.Declaration as Variable;
                    if (memberReferenceExpression.Target is IndexerExpression)
                        varDecl = (memberReferenceExpression.Target as IndexerExpression).Target.TypeInference.Declaration as Variable;

                    if (varDecl != null && varDecl.Qualifiers.Contains(StorageQualifier.Extern))
                    {
                        if (IsStageInitMember(memberReferenceExpression))
                            expression.SetTag(XenkoTags.StageInitRef, null);
                        else
                            expression.SetTag(XenkoTags.ExternRef, null);
                    }

                    var shaderDecl = memberReferenceExpression.Target.TypeInference.Declaration as ShaderClassType;
                    if (shaderDecl != null && shaderDecl != analyzedModuleMixin.Shader && analyzedModuleMixin.InheritanceList.All(x => x.Shader != shaderDecl))
                        expression.SetTag(XenkoTags.StaticRef, null);
                }

                if (!isBuiltIn)
                {
                    // store if not a base call
                    if (isNotBaseCall && !expression.ContainsTag(XenkoTags.ExternRef) && !expression.ContainsTag(XenkoTags.StageInitRef) && !expression.ContainsTag(XenkoTags.StaticRef))
                        parsingInfo.ThisMethodCalls.Add(expression);

                    if (methodDecl.Qualifiers.Contains(XenkoStorageQualifier.Stage))
                        parsingInfo.StageMethodCalls.Add(expression);
                }
            }
        }
 /// <summary>
 /// Find a static method
 /// </summary>
 /// <param name="expression">the calling expression</param>
 /// <returns>the correct called method</returns>
 private MethodDeclaration FindStaticMethod(MethodInvocationExpression expression)
 {
     var defMixin = (expression.Target.TypeInference.Declaration as MethodDeclaration).GetTag(XenkoTags.ShaderScope) as ModuleMixin;
     defMixin = mixContext[defMixin.MixinName];
     return defMixin.GetMethodFromExpression(expression.Target);
 }
        /// <summary>
        /// Gets the last override of the method
        /// </summary>
        /// <param name="methodCall">the method call</param>
        /// <returns>the declaration</returns>
        private MethodDeclaration GetThisStageMethod(MethodInvocationExpression methodCall)
        {
            var mixin = methodCall.GetTag(XenkoTags.CurrentShader) as ModuleMixin;
            var vtReference = mixin.VirtualTable.GetBaseDeclaration(methodCall.Target.TypeInference.Declaration as MethodDeclaration);
            foreach (var stageMethodList in StageMethodInheritance)
            {
                if (stageMethodList == null || stageMethodList.Count == 0)
                    continue;

                var firstOccurence = stageMethodList.First();
                var occurenceMixin = firstOccurence.GetTag(XenkoTags.ShaderScope) as ModuleMixin;
                var listVTReference = occurenceMixin.VirtualTable.GetBaseDeclaration(firstOccurence);

                if (vtReference.Slot != listVTReference.Slot || vtReference.Shader != listVTReference.Shader)
                    continue;

                return stageMethodList.Last();
            }
            return null;
        }
Beispiel #10
0
 public void Visit(MethodInvocationExpression methodInvocationExpression)
 {
     Visit((Node)methodInvocationExpression);
     AddReference(GetDeclarationContainer(), (Node)methodInvocationExpression.TypeInference.Declaration);
 }
Beispiel #11
0
 protected override void Visit(MethodInvocationExpression methodInvocationExpression)
 {
     // Save the number of variable in read-only mode
     countReadBeforeInvoke = uniformReadList.Count;
     base.Visit(methodInvocationExpression);
 }
Beispiel #12
0
        protected virtual void Visit(MethodInvocationExpression expression)
        {
            Visit((Node)expression);
            
            var methodAsVariable = expression.Target as VariableReferenceExpression;
            var methodAsType = expression.Target as TypeReferenceExpression;

            IEnumerable<IDeclaration> declarationsIterator = null;

            string methodName;

            // Check if this is a Variable or Typename
            if (methodAsVariable != null)
            {
                methodName = methodAsVariable.Name.Text;
                declarationsIterator = FindDeclarations(methodAsVariable.Name);
            }
            else if (methodAsType != null)
            {
                var returnType = methodAsType.Type.ResolveType();
                expression.TypeInference.TargetType = returnType;

                if (!(returnType is ScalarType || returnType is VectorType || returnType is MatrixType))
                    Warning(MessageCode.WarningTypeAsConstructor, expression.Span, expression.Target);

                return;
            }
            else
            {
                var target = expression.Target as MemberReferenceExpression;
                if (target != null)
                {
                    var memberReferenceExpression = target;

                    declarationsIterator = FindDeclarationsFromObject(memberReferenceExpression.Target.TypeInference.TargetType, memberReferenceExpression.Member.Text);
                    methodName = string.Format("{0}", target);
                }
                else
                {
                    Warning(MessageCode.WarningTypeInferenceUnknownExpression, expression.Span, expression.Target);
                    methodName = string.Format("{0}", expression.Target);
                }
            }

            // If no declarations were found, this is an error
            if (declarationsIterator == null)
            {
                Error(MessageCode.ErrorNoReferencedMethod, expression.Span, methodName);
                return;
            }

            // Grab the declarations
            var declarations = declarationsIterator.ToList();
            ProcessMethodInvocation(expression, methodName, declarations);
        }
        /// <inheritdoc/>
        public override void Visit(MethodInvocationExpression methodInvocationExpression)
        {
            if (methodInvocationExpression.Target is TypeReferenceExpression)
            {
                var methodName = (methodInvocationExpression.Target as TypeReferenceExpression).Type.Name.Text;
                if (hlslScalarTypeNames.Contains(methodName))
                {
                    var evaluator = new ExpressionEvaluator();
                    var subResult = evaluator.Evaluate(methodInvocationExpression.Arguments[0]);
                    values.Push(subResult.Value);
                    return;
                }
            }

            result.Error("Method invocation expression evaluation [{0}] is not supported", methodInvocationExpression.Span, methodInvocationExpression);
        }
Beispiel #14
0
        /// <summary>
        /// Pres the process method invocation.
        /// </summary>
        /// <param name="expression">The expression.</param>
        /// <param name="methodName">Name of the method.</param>
        /// <param name="declarations">The declarations.</param>
        /// <returns></returns>
        protected virtual void ProcessMethodInvocation(MethodInvocationExpression expression, string methodName, List<IDeclaration> declarations)
        {
            // Get all arguments types infered
            var argumentTypeInferences = expression.Arguments.Select(x => x.TypeInference).ToArray();
            var argumentTypes = expression.Arguments.Select(x => x.TypeInference.TargetType).ToArray();

            // If any type could not be resolved previously, there is already an error, so return immediately
            if (argumentTypes.Any(x => x == null))
                return;

            var overloads = new List<FunctionOverloadScore>();

            // Use the most overriden method
            // TODO: Temporary workaround for user methods overriding builtin methods
            // Remove the builtin methods if there is any overriding
            var methodsDeclared = declarations.OfType<MethodDeclaration>().ToList();
            for (int i = 0; i < methodsDeclared.Count - 1; i++)
            {
                var leftMethod = methodsDeclared[i];
                for (int j = i + 1; j < methodsDeclared.Count; j++)
                {
                    if (leftMethod.IsSameSignature(methodsDeclared[j]))
                    {
                        methodsDeclared.RemoveAt(i);
                        i--;
                        break;
                    }
                }
            }

            // Try to match the function arguments with every overload
            foreach (var methodDeclaration in methodsDeclared)
            {
                var returnType = methodDeclaration.ReturnType.ResolveType();
                var parameterTypes = methodDeclaration.Parameters.Select(x => x.Type.ResolveType()).ToArray();

                // Number of parameters doesn't match
                if (argumentTypes.Length > parameterTypes.Length) continue;

                // Check for method calls that is using implicit parameter value
                if (argumentTypes.Length < parameterTypes.Length)
                {
                    bool allRemainingParametersHaveDefaultValues = true;
                    // Check for default values
                    for (int i = argumentTypes.Length; i < parameterTypes.Length; i++)
                    {
                        if (methodDeclaration.Parameters[i].InitialValue == null)
                        {
                            allRemainingParametersHaveDefaultValues = false;
                            break;
                        }
                    }

                    // If remaining parameters doesn't have any default values, then continue
                    if (!allRemainingParametersHaveDefaultValues) continue;
                }

                // Higher score = more conversion (score == 0 is perfect match)
                int score = 0;
                bool validOverload = true;

                // Check parameters
                for (int i = 0; i < argumentTypes.Length && validOverload; ++i)
                {
                    var argType = argumentTypes[i];
                    var expectedType = parameterTypes[i];

                    var argTypeBase = TypeBase.GetBaseType(argType);
                    var expectedTypeBase = TypeBase.GetBaseType(expectedType);

                    if (expectedTypeBase is GenericParameterType)
                    {
                        var genericParameterType = (GenericParameterType)expectedTypeBase;

                        // TODO handle dynamic score from constraint.
                        if (methodDeclaration.CheckConstraint(genericParameterType, argType))
                        {
                            score++;
                        }
                        else
                        {
                            validOverload = false;
                        }
                    }
                    else
                    {
                        // TODO, improve the whole test by using TypeBase equality when possible

                        // Then work on scalar type conversion ( float to int, signed to unsigned, different type)
                        var fromScalarType = argTypeBase as ScalarType;
                        var toScalarType = expectedTypeBase as ScalarType;

                        if (fromScalarType != null && toScalarType != null)
                        {
                            if (ScalarType.IsFloat(fromScalarType) && !ScalarType.IsFloat(toScalarType))
                            {
                                // Truncation from float to int
                                score += 7;
                            }
                            else if (fromScalarType != toScalarType)
                            {
                                // else different type (implicit cast is usually working)
                                score += 1;
                            }

                            if (!fromScalarType.IsUnsigned && toScalarType.IsUnsigned)
                            {
                                // int to unsigned 
                                score += 2;
                            }
                        }

                        // First, try to fix the base type (i.e. the "float" of float3x1)
                        if (argTypeBase != expectedTypeBase && expectedTypeBase is ScalarType)
                        {
                            if (!(argTypeBase is ScalarType))
                            {
                                score++; // +1 for type conversion
                            }
                            argType = TypeBase.CreateWithBaseType(argType, (ScalarType)expectedTypeBase);
                        }

                        validOverload = TestMethodInvocationArgument(argTypeBase, expectedTypeBase, argType, expectedType, ref score);
                    }
                }

                if (validOverload)
                    overloads.Add(
                        new FunctionOverloadScore { Declaration = methodDeclaration, ParameterTypes = parameterTypes, ReturnType = returnType, Score = score });
            }

            // In-place sort using List.Sort would be lighter
            var bestOverload = overloads.OrderBy(x => x.Score).FirstOrDefault();

            if (bestOverload != null)
            {
                expression.TypeInference.TargetType = bestOverload.ReturnType.ResolveType();

                // Override declaration to match exactly the declaration found by method overloaded resolution
                expression.Target.TypeInference.Declaration = bestOverload.Declaration;

                // Add appropriate cast
                for (int i = 0; i < argumentTypes.Length; ++i)
                {
                    argumentTypeInferences[i].ExpectedType = (bestOverload.ParameterTypes[i] is GenericParameterType)
                                                                 ? argumentTypes[i]
                                                                 : bestOverload.ParameterTypes[i].ResolveType();
                }
            }
            else
            {
                Error(MessageCode.ErrorNoOverloadedMethod, expression.Span, methodName);
            }
        }
        protected override void ProcessMethodInvocation(MethodInvocationExpression expression, string methodName, List<IDeclaration> declarations)
        {
            // Check for typedef method 
            if (methodName != null)
            {
                var varExp = expression.Target as VariableReferenceExpression;

                if (varExp != null)
                {
                    var typeDefDeclarator = declarations.OfType<Typedef>().FirstOrDefault();
                    if (typeDefDeclarator != null)
                    {
                        varExp.TypeInference.Declaration = typeDefDeclarator;
                        varExp.TypeInference.TargetType = typeDefDeclarator.ResolveType();

                        expression.TypeInference.Declaration = typeDefDeclarator;
                        expression.TypeInference.TargetType = typeDefDeclarator.ResolveType();
                        return;
                    }

                    //var builtInFunction = defaultDeclarations.FirstOrDefault(x => x.Name.Text == varExp.Name.Text && TestParametersType(expression, x)) as MethodDeclaration;
                    var builtInFunction = defaultDeclarations.FirstOrDefault(x => (x as MethodDeclaration != null) && (x as MethodDeclaration).IsSameSignature(expression)) as MethodDeclaration;
                    if (builtInFunction != null)
                    {
                        varExp.TypeInference.Declaration = builtInFunction;
                        varExp.TypeInference.TargetType = builtInFunction.ReturnType.ResolveType();

                        expression.TypeInference.Declaration = builtInFunction;
                        expression.TypeInference.TargetType = builtInFunction.ReturnType.ResolveType();
                        return;
                    }
                }
            }
            
            base.ProcessMethodInvocation(expression, methodName, declarations);
        }
        protected override void Visit(MethodInvocationExpression expression)
        {
            var methodAsVariable = expression.Target as VariableReferenceExpression;

            // We are not parsing CompileShader methods
            if (methodAsVariable != null)
            {
                switch (methodAsVariable.Name.Text)
                {
                    case "ConstructGSWithSO":
                    case "CompileShader":
                        return;
                }
            }            
            
            base.Visit(expression);
        }
Beispiel #17
0
 /// <summary>
 /// Add the method to its correct dictionary
 /// </summary>
 /// <param name="expression"></param>
 private void AddToMethodsReferences(MethodInvocationExpression expression)
 {
     var decl = expression.Target.TypeInference.Declaration as MethodDeclaration;
     if (decl != null)
     {
         if (!mainModuleMixin.ClassReferences.MethodsReferences.ContainsKey(decl))
             mainModuleMixin.ClassReferences.MethodsReferences.Add(decl, new HashSet<MethodInvocationExpression>());
         mainModuleMixin.ClassReferences.MethodsReferences[decl].Add(expression);
     }
 }
Beispiel #18
0
        protected override void ProcessMethodInvocation(MethodInvocationExpression invoke, MethodDefinition method)
        {

            // Handle the case where a parameter can be out
            // If this is the case, we need to check that 
            for (int i = 0; i < invoke.Arguments.Count; i++)
            {
                var arg = invoke.Arguments[i];
                var variable = this.GetUniform(arg);
                var parameter = method.Parameters[i];
                if (variable != null && parameter.Qualifiers.Contains(Ast.Hlsl.ParameterQualifier.Out))
                {
                    bool isUniformWasAlreadyUsedAsRead = false;
                    for (int j = 0; j < countReadBeforeInvoke; j++)
                    {
                        if (ReferenceEquals(uniformReadList[i], variable))
                        {
                            isUniformWasAlreadyUsedAsRead = true;
                            break;
                        }
                    }

                    // If this is a out parameter, and the variable was not already used as a read, then
                    // we can remove it from the uniform read list
                    if (!isUniformWasAlreadyUsedAsRead)
                    {
                        uniformReadList.Remove(variable);
                        if (!UniformUsedWriteFirstList.Contains(variable))
                            UniformUsedWriteFirstList.Add(variable);
                    }
                }
            }

            this.VisitDynamic(method);
        }
Beispiel #19
0
        /// <summary>
        /// Remove the method from the correctdictionary
        /// </summary>
        /// <param name="expression"></param>
        private void RemoveFromMethodsReferences(MethodInvocationExpression expression, ModuleMixin mixin)
        {
            foreach (var refList in mixin.ClassReferences.MethodsReferences)
                refList.Value.RemoveWhere(x => x == expression);

            foreach (var refList in mainModuleMixin.ClassReferences.MethodsReferences)
                refList.Value.RemoveWhere(x => x == expression);
        }
        protected override void  ProcessMethodInvocation(MethodInvocationExpression invoke, MethodDefinition method)
        {
            var textureParameters = new List<Parameter>();
            var parameterValues = new List<Expression>();
            var parameterGlobalValues = new List<Variable>();

            var samplerTypes = new List<int>();

            for (int i = 0; i < method.Parameters.Count; i++)
            {
                var parameter = method.Parameters[i];
                if (parameter.Type is TextureType || parameter.Type is StateType)
                {
                    textureParameters.Add(parameter);

                    // Find global variable
                    var parameterValue = this.FindGlobalVariable(invoke.Arguments[i]);

                    // Set the tag ScopeValue for the current parameter
                    parameter.SetTag(ScopeValueKey, parameterValue);

                    // Add only new variable
                    if (!parameterGlobalValues.Contains(parameterValue))
                        parameterGlobalValues.Add(parameterValue);
                }
                else if ( i < invoke.Arguments.Count)
                {
                    parameterValues.Add(invoke.Arguments[i]);
                    if (parameter.Type is SamplerType)
                    {
                        samplerTypes.Add(i);
                    }
                }
            }

            // We have texture/sampler parameters. We need to generate a new specialized method
            if (textureParameters.Count > 0)
            {
                // Order parameter values by name
                parameterGlobalValues.Sort((left, right) => left.Name.Text.CompareTo(right.Name.Text));

                var methodKey = new TextureSamplerMethodKey(method);

                int indexOf = textureSamplerMethods.IndexOf(methodKey);

                if (indexOf < 0)
                {
                    methodKey.Initialize(cloneContext);
                    textureSamplerMethods.Add(methodKey);
                }
                else
                {
                    // If a key is found again, add it as it was reused in order to keep usage in order
                    methodKey = textureSamplerMethods[indexOf];
                    textureSamplerMethods.RemoveAt(indexOf);
                    textureSamplerMethods.Add(methodKey);
                }

                methodKey.Invokers.Add(invoke);

                var newTarget = new VariableReferenceExpression(methodKey.NewMethod.Name) { TypeInference = { Declaration = methodKey.NewMethod, TargetType = invoke.TypeInference.TargetType } };
                invoke.Target = newTarget;
                invoke.Arguments = parameterValues;
                invoke.TypeInference.Declaration = methodKey.NewMethod;
                invoke.TypeInference.TargetType = invoke.TypeInference.TargetType;

                this.VisitDynamic(methodKey.NewMethod);
            }
            else
            {
                // Visit the method callstack
                this.VisitDynamic(method);

                // There is an anonymous sampler type
                // We need to resolve its types after the method definition was processed
                if (samplerTypes.Count > 0)
                {
                    foreach (var samplerTypeIndex in samplerTypes)
                    {
                        var samplerRef = invoke.Arguments[samplerTypeIndex] as VariableReferenceExpression;
                        if (samplerRef != null)
                        {
                            var samplerDecl = samplerRef.TypeInference.Declaration as Variable;
                            ChangeVariableType(samplerDecl, method.Parameters[samplerTypeIndex].Type);
                        }
                    }
                }
            }

            // Remove temporary parameters
            if (textureParameters.Count > 0)
            {
                foreach (var textureParameter in textureParameters)
                {
                    textureParameter.RemoveTag(ScopeValueKey);
                }
            }
        }
Beispiel #21
0
        /// <summary>
        /// Gets the base stage method
        /// </summary>
        /// <param name="methodCall">the reference expression</param>
        /// <returns>the base declaration</returns>
        private MethodDeclaration GetBaseStageMethod(MethodInvocationExpression methodCall)
        {
            var mixin = methodCall.GetTag(XenkoTags.CurrentShader) as ModuleMixin;
            var vtReference = mixin.VirtualTable.GetBaseDeclaration(methodCall.Target.TypeInference.Declaration as MethodDeclaration);
            foreach (var stageMethodList in StageMethodInheritance)
            {
                if (stageMethodList == null || stageMethodList.Count == 0)
                    continue;

                var firstOccurence = stageMethodList.First();
                var occurenceMixin = firstOccurence.GetTag(XenkoTags.ShaderScope) as ModuleMixin;
                var listVTReference = occurenceMixin.VirtualTable.GetBaseDeclaration(firstOccurence);

                if (vtReference.Slot != listVTReference.Slot || vtReference.Shader != listVTReference.Shader)
                    continue;

                //TODO: can we call a base without overriding ?
                for (int j = stageMethodList.Count - 1; j > 0; --j)
                {
                    var decl = stageMethodList[j];
                    if (decl.GetTag(XenkoTags.ShaderScope) as ModuleMixin == mixin)
                        return stageMethodList[j - 1];
                }
                //for (int j = stageMethodList.Count - 1; j >= 0; --j)
                //{
                //    var decl = stageMethodList[j];
                //    if (decl.GetTag(XenkoTags.ShaderScope) as ModuleMixin == mixin)
                //    {
                //        if (j == 0)
                //            return stageMethodList[0];
                //        return stageMethodList[j - 1];
                //    }
                //}
            }
            return null;
        }
Beispiel #22
0
        public virtual void Visit(MethodInvocationExpression methodInvocationExpression)
        {
            VisitDynamic(methodInvocationExpression.Target);
            Write("(");
            for (int i = 0; i < methodInvocationExpression.Arguments.Count; i++)
            {
                var expression = methodInvocationExpression.Arguments[i];
                if (i > 0) Write(",").WriteSpace();

                VisitDynamic(expression);
            }

            Write(")");
        }
 private static MethodInvocationExpression Clone(MethodInvocationExpression expression)
 {
     var parameters = new Expression[expression.Arguments.Count];
     for (int i = 0; i < expression.Arguments.Count; ++i)
         parameters[i] = Clone(expression.Arguments[i]);
     return new MethodInvocationExpression(Clone(expression.Target), parameters);
 }
Beispiel #24
0
        /// <summary>
        /// Finds the top method - /!\ this is a hack because the mixin may not be analyzed yet /!\
        /// </summary>
        /// <param name="expression">The expression of the method reference</param>
        /// <returns>The base method if found</returns>
        public IEnumerable<MethodDeclarationShaderCouple> FindTopThisFunction(MethodInvocationExpression expression)
        {
            foreach (var method in FindMethod(expression))
                yield return method;

            for (int i = InheritanceList.Count - 1; i >= 0; --i)
            {
                foreach (var method in InheritanceList[i].FindMethod(expression))
                    yield return method;
            }
        }
        protected override void Visit(MethodInvocationExpression methodInvocationExpression)
        {
            // Visit first children
            base.Visit(methodInvocationExpression);

            // Convert member expression
            var variableRef = methodInvocationExpression.Target as VariableReferenceExpression;
            var memberRef = methodInvocationExpression.Target as MemberReferenceExpression;
            if (memberRef != null)
            {
                // TODO handle Texture2D<float> 
                var textureVariable = this.FindGlobalVariable(memberRef.Target);

                if (textureVariable != null)
                {
                    var textureType = textureVariable.Type.ResolveType();

                    if (textureType is TextureType || (textureType.IsBuiltIn && textureType.Name.Text.StartsWith("Texture", StringComparison.InvariantCultureIgnoreCase)))
                    {
                        switch (memberRef.Member)
                        {
                            case "Load":
                                {
                                    GenerateGLSampler(null, textureVariable);
                                }
                                break;
                            case "GetDimensions":
                                {
                                    textureAccesses.Add(textureVariable);
                                }
                                break;
                            case "Sample":
                            case "SampleBias":
                            case "SampleGrad":
                            case "SampleLevel":
                            case "SampleCmp":
                                {
                                    var sampler = this.FindGlobalVariable(methodInvocationExpression.Arguments[0]);
                                    if (sampler == null)
                                        throw new InvalidOperationException(string.Format("Unable to find sampler [{0}] as a global variable",
                                                                                          methodInvocationExpression.Arguments[0]));

                                    bool needsComparison = memberRef.Member == "SampleCmp";
                                    GenerateGLSampler(sampler, textureVariable, needsComparison);
                                }
                                break;
                        }
                    }
                }
            }
            else if (variableRef != null)
            {
                string methodName = variableRef.Name.Text;

                // Transform texture fetch
                var texFetchInfo = ParseTexFetch(methodName);
                if (texFetchInfo != null)
                {
                    var fetchInstructionSecondPart = string.Empty;
                    switch (texFetchInfo.Item2)
                    {
                        case TexFetchType.Default:
                            if (methodInvocationExpression.Arguments.Count == 4)
                                fetchInstructionSecondPart = "Grad";
                            break;
                        case TexFetchType.Bias:
                            // Bias is encoded in w, so replicated argument and extract only w. Compiler/optimizer should do the rest of the job.
                            methodInvocationExpression.Arguments.Add(new MemberReferenceExpression(new ParenthesizedExpression(methodInvocationExpression.Arguments[1]), "w"));
                            break;
                        case TexFetchType.Grad:
                            fetchInstructionSecondPart = "Grad";
                            break;
                        case TexFetchType.Proj:
                            fetchInstructionSecondPart = "Proj";
                            break;
                        case TexFetchType.Lod:
                            fetchInstructionSecondPart = "Lod";

                            // LOD is encoded in w, so replicated argument and extract only w. Compiler/optimizer should do the rest of the job.
                            methodInvocationExpression.Arguments.Add(new MemberReferenceExpression(new ParenthesizedExpression(methodInvocationExpression.Arguments[1]), "w"));
                            break;
                    }

                    if (TextureFunctionsCompatibilityProfile)
                    {
                        var stringBuilder = new StringBuilder("texture", 32);
                        if (texFetchInfo.Item1 == 4)
                            stringBuilder.Append("Cube");
                        else
                            stringBuilder.Append(texFetchInfo.Item1).Append('D');
                        stringBuilder.Append(fetchInstructionSecondPart);
                        variableRef.Name = stringBuilder.ToString();
                    }
                    else
                    {
                        variableRef.Name = "texture" + fetchInstructionSecondPart;
                    }

                    // TODO: Check how many components are required (for now it only do xy, but it might be x or xyz depending on texture dimension).
                    if (texFetchInfo.Item2 != TexFetchType.Proj)
                    {
                        var previousArgument = methodInvocationExpression.Arguments[1];
                        var sizeOfArguments = texFetchInfo.Item1 == 4 ? 3 : texFetchInfo.Item1;
                        var vectorType = previousArgument.TypeInference.TargetType as VectorType;

                        // If argument type is not the size of the expected argument, use explicit swizzle
                        if (vectorType == null || vectorType.Dimension != sizeOfArguments)
                            methodInvocationExpression.Arguments[1] = new MemberReferenceExpression(new ParenthesizedExpression(previousArgument), "xyzw".Substring(0, sizeOfArguments));
                    }

                    // Add the sampler
                    var samplerRefExpr = methodInvocationExpression.Arguments[0] as VariableReferenceExpression;
                    if (samplerRefExpr != null)
                    {
                        var samplerVariable = samplerRefExpr.TypeInference.Declaration as Variable;
                        var newSamplerType = texFetchInfo.Item1 < 4 ? new SamplerType("sampler" + texFetchInfo.Item1 + "D") : new SamplerType("samplerCube");
                        this.ChangeVariableType(samplerVariable, newSamplerType);
                    }
                }
            }            
        }
 protected virtual void ProcessMethodInvocation(MethodInvocationExpression invoke, MethodDefinition method)
 {
     this.VisitDynamic(method);
 }
        /// <summary>
        /// Calls the base method but modify the stream usage beforehand
        /// </summary>
        /// <param name="expression">the method expression</param>
        public override Node Visit(MethodInvocationExpression expression)
        {
            expression.SetTag(XenkoTags.CurrentShader, analyzedModuleMixin);

            base.Visit(expression);

            if (expression.TypeInference.TargetType == null && expression.Target.TypeInference.Declaration == null)
                Error(XenkoMessageCode.ErrorMissingMethod, expression.Span, expression, analyzedModuleMixin.MixinName);
            else if (!Equals(expression.TypeInference.Declaration, expression.Target.TypeInference.Declaration))
                expression.TypeInference.Declaration = expression.Target.TypeInference.Declaration;

            var methodDecl = expression.Target.TypeInference.Declaration as MethodDeclaration;

            if (methodDecl != null)
            {
                expression.Target.TypeInference.TargetType = (expression.Target.TypeInference.Declaration as MethodDeclaration).ReturnType.ResolveType();
                expression.TypeInference.TargetType = expression.Target.TypeInference.TargetType.ResolveType();

                if (currentVisitedMethod.Qualifiers.Contains(StorageQualifier.Static)
                    && !methodDecl.Qualifiers.Contains(StorageQualifier.Static)
                    && methodDecl.GetTag(XenkoTags.BaseDeclarationMixin) != null)
                {
                    Error(XenkoMessageCode.ErrorNonStaticCallInStaticMethod, expression.Span, currentVisitedMethod, methodDecl, analyzedModuleMixin.MixinName);
                }
            }

            // add to the reference list
            AddToMethodsReferences(expression);

            if (methodDecl != null)
                expression.Target.SetTag(XenkoTags.VirtualTableReference, methodDecl.GetTag(XenkoTags.VirtualTableReference));

            return expression;
        }
        /// <summary>
        /// Calls the base method but modify the stream usage beforehand
        /// </summary>
        /// <param name="expression">the method expression</param>
        public override void Visit(MethodInvocationExpression expression)
        {
            base.Visit(expression);

            var methodDecl = expression.Target.TypeInference.Declaration as MethodDeclaration;
            
            if (methodDecl != null)
            {
                // Stream analysis
                if (methodDecl.ContainsTag(XenkoTags.ShaderScope)) // this will prevent built-in function to appear in the list
                {
                    // test if the method was previously added
                    if (!alreadyAddedMethodsList.Contains(methodDecl))
                    {
                        currentStreamUsageList.Add(new StreamUsageInfo { CallType = StreamCallType.Method, MethodDeclaration = methodDecl, Expression = expression });
                        alreadyAddedMethodsList.Add(methodDecl);
                    }
                }
                for (int i = 0; i < expression.Arguments.Count; ++i)
                {
                    var arg = expression.Arguments[i] as MemberReferenceExpression; // TODO:

                    if (arg != null && IsStreamMember(arg))
                    {
                        var isOut = methodDecl.Parameters[i].Qualifiers.Contains(SiliconStudio.Shaders.Ast.ParameterQualifier.Out);

                        //if (methodDecl.Parameters[i].Qualifiers.Contains(Ast.ParameterQualifier.InOut))
                        //    Error(MessageCode.ErrorInOutStream, expression.Span, arg, methodDecl, contextModuleMixin.MixinName);

                        var usage = methodDecl.Parameters[i].Qualifiers.Contains(SiliconStudio.Shaders.Ast.ParameterQualifier.Out) ? StreamUsage.Write : StreamUsage.Read;
                        AddStreamUsage(arg.TypeInference.Declaration as Variable, arg, usage);
                    }
                }
            }

            // TODO: <shaderclasstype>.Append should be avoided
            if (expression.Target is MemberReferenceExpression && (expression.Target as MemberReferenceExpression).Target.TypeInference.TargetType is ClassType && (expression.Target as MemberReferenceExpression).Member.Text == "Append")
                AppendMethodCalls.Add(expression);
        }
 /// <summary>
 /// Adds the method reference to the list of methods references
 /// </summary>
 /// <param name="expression">the method reference expression</param>
 private void AddToMethodsReferences(MethodInvocationExpression expression)
 {
     var methodDecl = expression.Target.TypeInference.Declaration as MethodDeclaration;
     if (methodDecl != null && methodDecl.ContainsTag(XenkoTags.ShaderScope))
     {
         if (expression.ContainsTag(XenkoTags.StaticRef) || methodDecl.Qualifiers.Contains(StorageQualifier.Static))
             parsingInfo.StaticReferences.InsertMethod(methodDecl, expression);
         else if (expression.ContainsTag(XenkoTags.ExternRef))
             parsingInfo.ExternReferences.InsertMethod(methodDecl, expression);
         else if (expression.ContainsTag(XenkoTags.StageInitRef))
             parsingInfo.StageInitReferences.InsertMethod(methodDecl, expression);
         else
             parsingInfo.ClassReferences.InsertMethod(methodDecl, expression);
     }
     else
     {
         parsingInfo.NavigableNodes.Add(expression);
     }
 }
Beispiel #30
0
        private Expression Cast(TypeBase fromType, TypeBase toType, Expression expression)
        {
            if (fromType != null && toType != null)
            {
                if (fromType != toType)
                {
                    var castMethod = new MethodInvocationExpression(new TypeReferenceExpression(toType));
                    castMethod.Arguments.Add(expression);
                    expression = castMethod;
                    expression.TypeInference.TargetType = toType;
                }
            }

            return expression;
        }