public void Visit(Variable variable)
 {
     variable.Qualifiers.Values.Remove(ParadoxStorageQualifier.Stream);
     variable.Qualifiers.Values.Remove(ParadoxStorageQualifier.Stage);
     variable.Qualifiers.Values.Remove(ParadoxStorageQualifier.PatchStream);
     Visit((Node)variable);
 }
        private void CheckUsage(Variable variable)
        {
            if (variable == null)
                return;

            if (VariablesUsages.ContainsKey(variable))
                VariablesUsages[variable] = true;
        }
 /// <inheritdoc />
 public override void Visit(Variable variable)
 {
     if (VariableAsParameterKey)
     {
         WriteVariableAsParameterKey(variable);
     }
     else
     {
         if (IsXkfx)
         {
             base.Visit(variable);
         }
     }
 }
        public bool Run(ForStatement forStatement, Variable breakFlag, string keywordName, ParsingResult logger)
        {
            keyword = keywordName;

            Visit(forStatement.Body);

            if (logger != null)
                parserResult.CopyTo(logger);

            if (parserResult.HasErrors)
                return false;

            TransformBreaks(breakFlag);
            
            return scopeList.Count > 0;
        }
Exemple #5
0
        /// <summary>
        /// Writes the variable.
        /// </summary>
        /// <param name="variable">The variable.</param>
        protected void WriteVariable(Variable variable)
        {
            // Pre Attributes
            Write(variable.Attributes, true);

            // Pre qualifiers
            Write(variable.Qualifiers, true);

            var arrayType = variable.Type as ArrayType;
            var baseType = arrayType == null ? variable.Type : arrayType.Type;

            // If this is a variable declarator not attached to a group, output the type
            if (!isInVariableGroup)
            {
                IsDeclaratingVariable.Push(true);
                VisitDynamic(baseType);
                IsDeclaratingVariable.Pop();
                WriteSpace();
            }

            if (variable.IsGroup)
            {
                // Enter a variable group
                isInVariableGroup = true;

                for (int i = 0; i < variable.SubVariables.Count; i++)
                {
                    var subVariable = variable.SubVariables[i];
                    if (i > 0)
                        Write(",").WriteSpace();
                    VisitDynamic(subVariable);
                }

                isInVariableGroup = false;
            }
            else
            {
                Write(variable.Name);
            }

            if (arrayType != null)
            {
                WriteRankSpecifiers(arrayType.Dimensions);
            }

            // Post qualifiers
            Write(variable.Qualifiers, false);

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

            WriteInitializer(variable.InitialValue);

            // A variable can be a parameter or a grouped variable.
            // If this is a parameter and we are visiting a method declaration, don't output the ";"
            // If we are inside a group variable, don't output ";" as the upper level will add "," to separate variables.
            if (!isInVariableGroup && !isVisitingVariableInlines)
                WriteLine(";");

        }
 /// <summary>
 /// Initializes a new instance of the <see cref="VariableReferenceExpression"/> class.
 /// </summary>
 /// <param name="variable">The variable.</param>
 public VariableReferenceExpression(Variable variable)
 {
     Name = variable.Name;
     TypeInference.TargetType = variable.Type.ResolveType();
 }
        /// <summary>
        /// Link all the stage compositions in case it is referenced at several places.
        /// </summary>
        /// <param name="variable">The variable of the composition.</param>
        /// <param name="composition">The composition.</param>
        /// <param name="dictionary">The already registered compositions.</param>
        /// <param name="extraDictionary">The new compositions.</param>
        /// <param name="log">The logger.</param>
        private static void FullLinkStageCompositions(Variable variable, List<ModuleMixin> composition, CompositionDictionary dictionary, Dictionary<Variable, List<ModuleMixin>> extraDictionary, LoggerResult log)
        {
            var mixin = variable.GetTag(ParadoxTags.ShaderScope) as ModuleMixin;
            if (mixin != null)
            {
                var className = mixin.MixinName;
                foreach (var item in dictionary)
                {
                    if (item.Key == variable)
                        continue;

                    foreach (var module in item.Value)
                    {
                        if (module.MixinName == className || module.InheritanceList.Any(x => x.MixinName == className))
                        {
                            // add reference
                            var foundVars = module.FindAllVariablesByName(variable.Name).Where(value => value.Variable.Qualifiers.Contains(ParadoxStorageQualifier.Compose)).ToList();;
                            if (foundVars.Count > 1)
                            {
                                log.Error(ParadoxMessageCode.ErrorAmbiguousComposition, new SourceSpan(), variable.Name);
                            }
                            else if (foundVars.Count > 0)
                            {
                                // if there is already a filled composition, it means that the ShaderMixinSource filled the composition information at two different places
                                // TODO: verify that
                                var foundVar = foundVars[0].Variable;
                                List<ModuleMixin> previousList;
                                if (dictionary.TryGetValue(foundVar, out previousList))
                                {
                                    previousList.AddRange(composition); 
                                }
                                else
                                    extraDictionary.Add(foundVars[0].Variable, composition);
                            }
                            else
                            {
                                // No matching variable was found
                                // TODO: log a message?
                            }
                        }
                    }
                }
            }
        }
        private void ChangeVariableType(Variable samplerVariable, TypeBase newType)
        {
            if (samplerVariable != null)
            {
                samplerVariable.Type = newType;
                if (samplerVariable is Parameter)
                {
                    return;
                }

                var variableInitialValue = samplerVariable.InitialValue as VariableReferenceExpression;
                if (variableInitialValue != null)
                {
                    this.ChangeVariableType(variableInitialValue.TypeInference.Declaration as Variable, newType);
                }
            }
        }
Exemple #9
0
        private void LinkConstant(string cbName, Variable variable, LocalParameterKey parameterKey)
        {
            // If the constant buffer is not present, add it
            var constantBuffer = effectReflection.ConstantBuffers.FirstOrDefault(buffer => buffer.Name == cbName);
            if (constantBuffer == null)
            {
                constantBuffer = new ShaderConstantBufferDescription() {Name = cbName};
                effectReflection.ConstantBuffers.Add(constantBuffer);
                var constantBufferBinding = new EffectParameterResourceData { Param = { KeyName = cbName, Class = EffectParameterClass.ConstantBuffer, Type = EffectParameterType.Buffer, RawName = cbName }, SlotStart = -1 };
                effectReflection.ResourceBindings.Add(constantBufferBinding);
                valueBindings.Add(constantBuffer, new List<EffectParameterValueData>());
            }

            // Get the list of members of this constant buffer
            var members = valueBindings[constantBuffer];

            var binding = new EffectParameterValueData
                {
                    Param =
                        {
                            KeyName = parameterKey.Name,
                            Class = parameterKey.Class,
                            Type = parameterKey.Type,
                            RawName = variable.Name
                        },
                    RowCount = parameterKey.RowCount,
                    ColumnCount = parameterKey.ColumnCount,
                    Count = parameterKey.Count,
                };
            
            members.Add(binding);
        }
 /// <summary>
 /// Adds a stream usage to the current method
 /// </summary>
 /// <param name="variable">the stream Variable</param>
 /// <param name="expression">the calling expression</param>
 /// <param name="usage">the encountered usage</param>
 private void AddStreamUsage(Variable variable, SiliconStudio.Shaders.Ast.Expression expression, StreamUsage usage)
 {
     currentStreamUsageList.Add(new StreamUsageInfo { CallType = StreamCallType.Member, Variable = variable, Expression = expression, Usage = usage });
 }
        public override void Visit(Variable variableStatement)
        {
            base.Visit(variableStatement);

            var parentBlock = this.NodeStack.OfType<StatementList>().LastOrDefault();
            if (parentBlock != null && variableStatement.Type == StreamsType.Streams && variableStatement.InitialValue is VariableReferenceExpression && ((VariableReferenceExpression)(variableStatement.InitialValue)).TypeInference.TargetType.IsStreamsType())
            {
                VariableStreamsAssignment.Add(variableStatement, parentBlock);
            }
        }
Exemple #12
0
 public bool IsUniformReadWrite(Variable variable)
 {
     return UniformReadWriteList.Contains(variable);
 }
Exemple #13
0
 public bool IsVariableAsGlobalTemporary(Variable variable)
 {
     return UniformUsedWriteFirstList.Contains(variable);
 }
Exemple #14
0
 public void Visit(Variable variable)
 {
     Visit((Node)variable);
     var containers = GetDeclarationContainers();
     if (containers.Count > 1)
     {
         var container = containers[containers.Count - 2];
         AddReference((Node)container, variable);
     }
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ForEachStatement"/> class.
 /// </summary>
 /// <param name="variable">The variable.</param>
 /// <param name="collection">The collection.</param>
 public ForEachStatement(Variable variable, Expression collection)
 {
     Variable = variable;
     Collection = collection;
 }
Exemple #16
0
        protected void Visit(Variable variable)
        {
            var parameterKey = GetLinkParameterKey(variable);
            if (parameterKey == null) return;

            var resolvedType = variable.Type.ResolveType();
            if (resolvedType is ArrayType)
            {
                resolvedType = ((ArrayType)resolvedType).Type;
            }
            if (resolvedType is StateType)
            {
                var samplerState = SamplerStateDescription.Default;

                var stateInitializer = variable.InitialValue as StateInitializer;
                if (stateInitializer != null)
                {
                    foreach (var samplerField in stateInitializer.Items.OfType<AssignmentExpression>())
                    {
                        string key = samplerField.Target.ToString();
                        string value = samplerField.Value.ToString();

                        if (key == "Filter")
                        {
                            switch (value)
                            {
                                case "COMPARISON_MIN_MAG_LINEAR_MIP_POINT":
                                    samplerState.Filter = TextureFilter.ComparisonMinMagLinearMipPoint;
                                    break;
                                case "COMPARISON_MIN_MAG_MIP_POINT":
                                    samplerState.Filter = TextureFilter.ComparisonPoint;
                                    break;
                                case "MIN_MAG_LINEAR_MIP_POINT":
                                    samplerState.Filter = TextureFilter.MinMagLinearMipPoint;
                                    break;
                                case "MIN_MAG_MIP_LINEAR":
                                    samplerState.Filter = TextureFilter.Linear;
                                    break;
                                case "ANISOTROPIC":
                                    samplerState.Filter = TextureFilter.Anisotropic;
                                    break;
                                case "MIN_MAG_MIP_POINT":
                                    samplerState.Filter = TextureFilter.Point;
                                    break;
                                default:
                                    parsingResult.Error(XenkoMessageCode.SamplerFilterNotSupported, variable.Span, value);
                                    break;
                            }
                        }
                        else if (key == "ComparisonFunc")
                        {
                            CompareFunction compareFunction;
                            Enum.TryParse(value, true, out compareFunction);
                            samplerState.CompareFunction = compareFunction;
                        }
                        else if (key == "AddressU" || key == "AddressV" || key == "AddressW")
                        {
                            TextureAddressMode textureAddressMode;
                            Enum.TryParse(value, true, out textureAddressMode);
                            switch (key)
                            {
                                case "AddressU":
                                    samplerState.AddressU = textureAddressMode;
                                    break;
                                case "AddressV":
                                    samplerState.AddressV = textureAddressMode;
                                    break;
                                case "AddressW":
                                    samplerState.AddressW = textureAddressMode;
                                    break;
                                default:
                                    parsingResult.Error(XenkoMessageCode.SamplerAddressModeNotSupported, variable.Span, key);
                                    break;
                            }
                        }
                        else if (key == "BorderColor")
                        {
                            var borderColor = samplerField.Value as MethodInvocationExpression;
                            if (borderColor != null)
                            {
                                var targetType = borderColor.Target as TypeReferenceExpression;
                                if (targetType != null && targetType.Type.ResolveType() == VectorType.Float4 && borderColor.Arguments.Count == 4)
                                {
                                    var values = new float[4];
                                    for (int i = 0; i < 4; i++)
                                    {
                                        var argValue = borderColor.Arguments[i] as LiteralExpression;
                                        if (argValue != null)
                                        {
                                            values[i] = (float)Convert.ChangeType(argValue.Value, typeof(float));
                                        }
                                        else
                                        {
                                            parsingResult.Error(XenkoMessageCode.SamplerBorderColorNotSupported, variable.Span, borderColor.Arguments[i]);
                                        }
                                    }

                                    samplerState.BorderColor = new Color4(values);
                                }
                                else
                                {
                                    parsingResult.Error(XenkoMessageCode.SamplerBorderColorNotSupported, variable.Span, variable);
                                }
                            }
                            else
                            {
                                parsingResult.Error(XenkoMessageCode.SamplerBorderColorNotSupported, variable.Span, variable);
                            }
                        }
                        else if (key == "MinLOD")
                        {
                            samplerState.MinMipLevel = float.Parse(value);
                        }
                        else if (key == "MaxLOD")
                        {
                            samplerState.MaxMipLevel = float.Parse(value);
                        }
                        else if (key == "MaxAnisotropy")
                        {
                            samplerState.MaxAnisotropy = int.Parse(value);
                        }
                        else
                        {
                            parsingResult.Error(XenkoMessageCode.SamplerFieldNotSupported, variable.Span, variable);
                        }
                    }
                }

                effectReflection.SamplerStates.Add(new EffectSamplerStateBinding(parameterKey.Name, samplerState));
                LinkVariable(effectReflection, variable.Name, parameterKey);
            }
            else if (variable.Type is TextureType || variable.Type is GenericType)
            {
                LinkVariable(effectReflection, variable.Name, parameterKey);
            }
            else
            {
                ParseConstantBufferVariable("$Globals", variable);
            }
        }
Exemple #17
0
        private void ParseConstantBufferVariable(string cbName, Variable variable)
        {
            if (variable.Qualifiers.Contains(SiliconStudio.Shaders.Ast.Hlsl.StorageQualifier.Static) ||
                variable.Qualifiers.Contains(StorageQualifier.Const) ||
                variable.Qualifiers.Contains(SiliconStudio.Shaders.Ast.Hlsl.StorageQualifier.Groupshared)
                )
                return;

            if (variable.Qualifiers.Contains(XenkoStorageQualifier.Stream))
            {
                parsingResult.Error(XenkoMessageCode.StreamVariableWithoutPrefix, variable.Span, variable);
                return;
            }

            foreach (var attribute in variable.Attributes.OfType<AttributeDeclaration>())
            {
                if (attribute.Name == "Link")
                {
                    if (attribute.Parameters.Count != 1)
                    {
                        parsingResult.Error(XenkoMessageCode.LinkArgumentsError, variable.Span);
                    }
                }
            }

            //// Try to resolve key
            var parameterKey = GetLinkParameterKey(variable);

            if (parameterKey != null)
            {
                LinkConstant(cbName, variable, parameterKey);
            }
            else
            {
                parsingResult.Error(XenkoMessageCode.LinkError, variable.Span, variable);
            }
        }
Exemple #18
0
        protected void Visit(Variable variable)
        {
            // First, dispatch to resolve type of node at deeper level
            Visit((Node)variable);

            if (variable.InitialValue != null)
            {
                var expressionType = variable.InitialValue.TypeInference.TargetType;
                if (!(expressionType is ObjectType))
                {
                    variable.InitialValue = Cast(expressionType, variable.Type.ResolveType(), variable.InitialValue);
                }
            }
        }
        protected void WriteVariableAsParameterKey(Variable variable)
        {
            if (!IsParameterKey(variable))
            {
                return;
            }

            IsColorStatus = variable.Attributes.OfType<AttributeDeclaration>().Any(x => x.Name == "Color");
            ProcessInitialValueStatus = false;
            IsArrayStatus = false;

            var variableType = variable.Attributes.OfType<AttributeDeclaration>().Where(x => x.Name == "Type").Select(x => (string)x.Parameters[0].Value).FirstOrDefault();
            var variableMap = variable.Attributes.OfType<AttributeDeclaration>().Where(x => x.Name == "Map").Select(x => (string)x.Parameters[0].Value).FirstOrDefault();

            // ParameterKey shouldn't contain only the underlying type in case of arrays (we use slots)
            var parameterType = variable.Type;

            string parameterKeyType;
            if (IsXkfx)
            {
                parameterKeyType = "Permutation";
            }
            else
            {
                while (parameterType is ArrayType)
                {
                    parameterType = ((ArrayType)parameterType).Type;
                }

                if (parameterType is ObjectType || IsTextureType(parameterType) || IsBufferType(parameterType))
                {
                    parameterKeyType = "Object";
                }
                else
                {
                    parameterKeyType = "Value";
                }
            }

            Write($"public static readonly {parameterKeyType}ParameterKey<");
            if (variableType == null)
                VisitDynamic(parameterType);
            else
                Write(variableType);
            Write("> ");
            Write(variable.Name);
            Write(" = ");
            if (variableMap == null)
            {
                Write($"ParameterKeys.New{parameterKeyType}<");
                if (variableType == null)
                    VisitDynamic(parameterType);
                else
                    Write(variableType);
                Write(">(");
                if (ProcessInitialValueStatus && variable.InitialValue != null)
                {
                    var initialValueString = variable.InitialValue.ToString();

                    if (initialValueString != "null")
                    {
                        if (IsArrayStatus)
                        {
                            initialValueString = variable.Type.ToString() + initialValueString;
                        }

                        // Rename float2/3/4 to Vector2/3/4
                        if (initialValueString.StartsWith("float2")
                            || initialValueString.StartsWith("float3")
                            || initialValueString.StartsWith("float4"))
                            initialValueString = initialValueString.Replace("float", "new Vector");
                        else if (IsArrayStatus)
                        {
                            initialValueString = "new " + initialValueString;
                        }

                        if (IsColorStatus)
                        {
                            initialValueString = initialValueString.Replace("Vector3", "Color3");
                            initialValueString = initialValueString.Replace("Vector4", "Color4");
                        }
                    }
                    Write(initialValueString);
                }
                Write(")");
            }
            else
            {
                Write(variableMap);
            }
            WriteLine(";");

            IsColorStatus = false;
            IsArrayStatus = false;
            ProcessInitialValueStatus = false;
        }
 /// <inheritdoc />
 public override void Visit(Variable variable)
 {
     WriteLinkLine(variable);
     WriteVariable(variable);
 }
        //public override void Visit(ConstantBuffer constantBuffer)
        //{
        //    VisitDynamic(constantBuffer);
        //}

        internal bool IsParameterKey(Variable variable)
        {
            // Don't generate a parameter key for variable stored storage qualifier: extern, const, compose, stream
            if (variable.Qualifiers.Contains(SiliconStudio.Shaders.Ast.Hlsl.StorageQualifier.Extern)
                || variable.Qualifiers.Contains(StorageQualifier.Const)
                || variable.Qualifiers.Contains(XenkoStorageQualifier.Compose)
                || variable.Qualifiers.Contains(XenkoStorageQualifier.PatchStream)
                || variable.Qualifiers.Contains(SiliconStudio.Shaders.Ast.Hlsl.StorageQualifier.Groupshared)
                || variable.Qualifiers.Contains(XenkoStorageQualifier.Stream))
                return false;

            // Don't generate a parameter key for [Link] or [RenameLink]
            if (variable.Attributes.OfType<AttributeDeclaration>().Any(x => x.Name == "RenameLink" || x.Name == "Link"))
                return false;

            return true;
        }
 /// <summary>
 /// Test if the variable should be in a constant buffer
 /// </summary>
 /// <param name="variable">the variable</param>
 /// <returns>true/false</returns>
 private bool IsOutOfCBufferVariable(Variable variable)
 {
     return variable.Type is SamplerType || variable.Type is SamplerStateType || variable.Type is TextureType || variable.Type is StateType || variable.Type.ResolveType() is ObjectType;
 }
        /// <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 samplerTypeName = texture.Type.ResolveType().Name.Text.Replace("Texture", "sampler");

                // 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);
            }
        }
 /// <summary>
 /// Test if the variable should be in a constant buffer
 /// </summary>
 /// <param name="variable">the variable</param>
 /// <returns>true/false</returns>
 private bool KeepVariableInCBuffer(Variable variable)
 {
     return !(variable.Qualifiers.Contains(XenkoStorageQualifier.Extern) || variable.Qualifiers.Contains(XenkoStorageQualifier.Stream) || variable.Qualifiers.Contains(XenkoStorageQualifier.PatchStream) || IsOutOfCBufferVariable(variable) || variable.Qualifiers.Contains(StorageQualifier.Const));
 }
Exemple #25
0
 /// <summary>
 /// Merges attributes and qualifiers from another variable.
 /// </summary>
 /// <param name="from">The variable to merge attribute from.</param>
 public void MergeFrom(Variable from)
 {
     Qualifiers |= from.Qualifiers;
     Attributes.AddRange(from.Attributes);
 }
        /// <summary>
        /// Creates a ForStatement with the same behavior
        /// </summary>
        /// <param name="forEachStatement">the ForEachStatement</param>
        /// <returns>the ForStatement</returns>
        private static ForStatement ExpandForEachStatement(ForEachStatement forEachStatement)
        {
            if (forEachStatement != null)
            {
                var collec = forEachStatement.Collection.TypeInference.Declaration as Variable;
                LiteralExpression dimLit = null;
                if (collec.Type is ArrayType)
                {
                    if ((collec.Type as ArrayType).Dimensions.Count == 1)
                    {
                        dimLit = (collec.Type as ArrayType).Dimensions[0] as LiteralExpression;
                    }
                }

                if (dimLit != null)
                {
                    var initializer = new Variable(ScalarType.Int, forEachStatement.Variable.Name.Text + "Iter", new LiteralExpression(0));
                    var vre = new VariableReferenceExpression(initializer.Name);
                    var condition = new BinaryExpression(BinaryOperator.Less, vre, dimLit);
                    var next = new UnaryExpression(UnaryOperator.PreIncrement, vre);
                    ForStatement forStatement = new ForStatement(new DeclarationStatement(initializer), condition, next);
                    var body = new BlockStatement();

                    var variable = forEachStatement.Variable;
                    variable.InitialValue = new IndexerExpression(forEachStatement.Collection, new VariableReferenceExpression(initializer));
                    body.Statements.Add(new DeclarationStatement(variable));

                    if (forEachStatement.Body is BlockStatement)
                        body.Statements.AddRange((forEachStatement.Body as BlockStatement).Statements);
                    else
                        body.Statements.Add(forEachStatement.Body);

                    forStatement.Body = body;

                    return forStatement;
                }

                // TODO: multidimension-array?
                // TODO: unroll?
                // TODO: multiple foreach?
            }
            return null;
        }
Exemple #27
0
 public virtual void Visit(Variable variable)
 {
     WriteLinkLine(variable);
     WriteVariable(variable);
 }
        /// <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);
            }
        }
        /// <summary>
        /// Visits the specified variable
        /// </summary>
        /// <param name="variable">The variable</param>
        public override Node Visit(Variable variable)
        {
            if (inSampler)
                return variable;
            
            if (variable.Type.IsSamplerStateType())
                inSampler = true;

            // type inference for variable
            if (ParentNode is ForEachStatement)
            {
                var forEachStatement = ParentNode as ForEachStatement;
                if (variable == forEachStatement.Variable)
                {
                    var finalType = forEachStatement.Collection.TypeInference.TargetType;
                    if (finalType is ArrayType)
                        finalType = (finalType as ArrayType).Type;
                    variable.Type = finalType;
                    if ((forEachStatement.Collection.TypeInference.Declaration as Variable).Qualifiers.Contains(StorageQualifier.Extern))
                        variable.Qualifiers |= StorageQualifier.Extern;
                }
            }

            base.Visit(variable);

            inSampler = false;

            if (currentVisitedMethod == null)
            {
                if (variable.InitialValue is VariableReferenceExpression)
                {
                    var vre = variable.InitialValue as VariableReferenceExpression;
                    if (vre.Name.Text == "stage")
                    {
                        if (variable.Qualifiers.Contains(StorageQualifier.Extern) && variable.Type.TypeInference.Declaration is ClassType)
                            parsingInfo.StageInitializedVariables.Add(variable);
                        else
                            Error(XenkoMessageCode.ErrorStageInitNotClassType, variable.Span, variable, analyzedModuleMixin.MixinName);
                    }
                }

                if (variable.Qualifiers.Contains(StorageQualifier.Extern))
                {
                    var varType = variable.Type;
                    if (varType is ArrayType)
                        varType = (varType as ArrayType).Type;

                    if (!(varType.TypeInference.Declaration is ClassType))
                        Error(XenkoMessageCode.ErrorExternNotClassType, variable.Span, variable, analyzedModuleMixin.MixinName);
                }

                // should not happen because extern keyword is set in the ShaderCompilationContext
                if (!variable.Qualifiers.Contains(StorageQualifier.Extern) && variable.Type.TypeInference.Declaration is ClassType)
                    Error(XenkoMessageCode.ErrorMissingExtern, variable.Span, variable, analyzedModuleMixin.MixinName);
            }

            // check var type
            if (variable.Type is VarType)
            {
                if (variable.InitialValue == null)
                    Error(XenkoMessageCode.ErrorVarNoInitialValue, variable.Span, variable, analyzedModuleMixin.MixinName);
                else if (variable.InitialValue.TypeInference.TargetType == null)
                    Error(XenkoMessageCode.ErrorVarNoTypeFound, variable.Span, variable, analyzedModuleMixin.MixinName);
                else
                {
                    variable.Type = variable.InitialValue.TypeInference.TargetType.ResolveType();
                    // If we have a var type referencing a generic type, try to use the non-generic version of it
                    if (variable.Type is GenericBaseType)
                    {
                        variable.Type = ((GenericBaseType)variable.Type).ToNonGenericType();
                    }
                }
            }

            if (variable.ContainsTag(XenkoTags.ShaderScope))
            {
                if (!parsingInfo.ClassReferences.VariablesReferences.ContainsKey(variable))
                    parsingInfo.ClassReferences.VariablesReferences.Add(variable, new HashSet<ExpressionNodeCouple>());
            }

            if (currentVisitedMethod != null && !(ParentNode is ForEachStatement))
            {
                if (FindFinalType(variable.Type) is ShaderClassType)
                    Error(XenkoMessageCode.ErrorShaderVariable, variable.Span, variable, analyzedModuleMixin.MixinName);
            }

            return variable;
        }
 public ParadoxReplaceExtern(Variable variable, IndexerExpression expression)
     : base(false, true)
 {
     VariableToReplace = variable;
     IndexerReplacement = expression;
 }