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; }
/// <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); } } }
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); } }
public bool IsUniformReadWrite(Variable variable) { return UniformReadWriteList.Contains(variable); }
public bool IsVariableAsGlobalTemporary(Variable variable) { return UniformUsedWriteFirstList.Contains(variable); }
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; }
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); } }
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); } }
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)); }
/// <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; }
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; }