/// <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); } }
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); }
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); } } }
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))); }
/// <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); } }