/// <summary>
        /// Generates a OpenGL sampler based on sampler/texture combination.
        /// </summary>
        /// <param name="sampler">The D3D sampler (can be null).</param>
        /// <param name="texture">The D3D texture.</param>
        private void GenerateGLSampler(Variable sampler, Variable texture, bool needsComparison = false)
        {
            Variable glslSampler;

            if (texture == null)
            {
                throw new InvalidOperationException();
            }

            var samplerKey = new SamplerTextureKey(sampler, texture);

            if (!samplerMapping.TryGetValue(samplerKey, out glslSampler))
            {
                var samplerType     = texture.Type.ResolveType();
                var samplerTypeName = samplerType.Name.Text;

                if (samplerTypeName.StartsWith("Texture"))
                {
                    samplerTypeName = "sampler" + samplerTypeName.Substring("Texture".Length);
                }
                else if (samplerTypeName.StartsWith("Buffer"))
                {
                    samplerTypeName = "samplerBuffer";
                }

                // TODO: How do we support this on OpenGL ES 2.0? Cast to int/uint on Load()/Sample()?
                var genericSamplerType = samplerType as IGenerics;
                if (genericSamplerType != null && genericSamplerType.GenericArguments.Count == 1)
                {
                    var genericArgument = genericSamplerType.GenericArguments[0].ResolveType();
                    if (TypeBase.GetBaseType(genericArgument) == ScalarType.UInt)
                    {
                        samplerTypeName = "u" + samplerTypeName;
                    }
                    else if (TypeBase.GetBaseType(genericArgument) == ScalarType.Int)
                    {
                        samplerTypeName = "i" + samplerTypeName;
                    }
                }

                // Handle comparison samplers
                if (needsComparison)
                {
                    samplerTypeName += "Shadow";
                }

                glslSampler = new Variable(new TypeName(samplerTypeName), texture.Name + (sampler != null ? "_" + sampler.Name : "_NoSampler"))
                {
                    Span = sampler == null ? texture.Span : sampler.Span
                };
                samplerMapping.Add(samplerKey, glslSampler);
            }
        }
Exemple #2
0
        public static TypeBase MakeGenericInstance(this GenericBaseType genericType, TypeBase genericTemplateType)
        {
            // TODO cache generic instance that are using predefined hlsl types
            var newType = genericTemplateType.DeepClone();

            var genericParameters         = ((IGenerics)newType).GenericParameters;
            var genericArguments          = ((IGenerics)newType).GenericArguments;
            var genericInstanceParameters = genericType.Parameters;

            var genericParameterTypes     = new TypeBase[genericParameters.Count];
            var genericBaseParameterTypes = new TypeBase[genericParameters.Count];

            // Look for parameter instance types
            for (int i = 0; i < genericInstanceParameters.Count; i++)
            {
                var genericInstanceParameter = genericInstanceParameters[i];
                if (genericInstanceParameter is TypeBase)
                {
                    var genericInstanceParameterType = (TypeBase)genericInstanceParameter;
                    genericParameterTypes[i]     = genericInstanceParameterType;
                    genericBaseParameterTypes[i] = TypeBase.GetBaseType(genericInstanceParameterType);
                    genericParameters[i]         = genericParameterTypes[i];
                    genericArguments.Add(genericInstanceParameterType);
                }
            }

            // Replace all references to template arguments to their respective generic instance types
            SearchVisitor.Run(
                newType,
                node =>
            {
                var typeInferencer = node as ITypeInferencer;
                if (typeInferencer != null && typeInferencer.TypeInference.Declaration is GenericDeclaration)
                {
                    var genericDeclaration = (GenericDeclaration)typeInferencer.TypeInference.Declaration;
                    var i         = genericDeclaration.Index;
                    var targeType = genericDeclaration.IsUsingBase ? genericBaseParameterTypes[i] : genericParameterTypes[i];

                    if (node is TypeBase)
                    {
                        return(targeType.ResolveType());
                    }
                }

                return(node);
            });


            return(newType);
        }
Exemple #3
0
        protected void Visit(IndexerExpression expression)
        {
            // First, dispatch to resolve type of node at deeper level
            Visit((Node)expression);

            var indexerType = expression.Index.TypeInference.TargetType;

            if (indexerType != null)
            {
                var baseType = TypeBase.GetBaseType(indexerType);
                if (baseType == ScalarType.Float || baseType == ScalarType.Double)
                {
                    expression.Index = Cast(indexerType, ScalarType.Int, expression.Index);
                }
            }
        }
Exemple #4
0
        public override Node Visit(IndexerExpression expression)
        {
            // First, dispatch to resolve type of node at deeper level
            base.Visit(expression);

            var indexerType = expression.Index.TypeInference.TargetType;

            if (indexerType != null)
            {
                var baseType = TypeBase.GetBaseType(indexerType);
                if (baseType == ScalarType.Float || baseType == ScalarType.Double)
                {
                    expression.Index = Cast(indexerType, ScalarType.Int, expression.Index);
                }
            }

            return(expression);
        }
 /// <summary>
 /// Check if convert is necessary
 /// </summary>
 /// <param name="leftType">Type of the left.</param>
 /// <param name="rightType">Type of the right.</param>
 /// <returns>True if a cast is necessary between this two types</returns>
 public static bool NeedConvertForBinary(TypeBase leftType, TypeBase rightType)
 {
     return(leftType != null && rightType != null && leftType != rightType
            &&
            !((leftType is ScalarType && (rightType is VectorType || rightType is MatrixType) && TypeBase.GetBaseType(rightType) == leftType) ||
              (rightType is ScalarType && (leftType is VectorType || leftType is MatrixType) && TypeBase.GetBaseType(leftType) == rightType)));
 }
Exemple #6
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);
            }
        }