예제 #1
0
        internal static Type Resolve(ShaderTranslationContext sc, string typeName, SyntaxTokenList modifiers = default)
        {
            Type t = null;

            foreach (SyntaxToken m in modifiers)
            {
                for (int i = 0; i < PointerModifiers.Length; i++)
                {
                    if (m.ValueText == PointerModifiers[i])
                    {
                        typeName += "&";
                        goto PostModifierCheck; // Yes, it's a goto! It's also a nested loop ;)
                    }
                }
            }

PostModifierCheck:
            if (!_baseTypeAliases.TryGetValue(typeName, out t))
            {
                t = RetrieveType(typeName);
            }

            if (t == null)
            {
                Type sType = sc.ShaderType;
                t = sc.Parent.Reflection.Assembly.GetType($"{sc.ShaderType.Namespace}.{sc.ShaderType.Name}+{typeName}");

                if (t == null)
                {
                    t = ResolveGeneric(sc, typeName);
                }
            }

            return(t);
        }
예제 #2
0
        private static Type ResolveGeneric(ShaderTranslationContext sc, string typeName)
        {
            int  bIndex = typeName.IndexOf('<');
            Type t      = null;

            if (bIndex > -1)
            {
                // TODO garbage generation from arrays?
                string   typeParams = typeName.Substring(bIndex, typeName.Length - bIndex);
                string[] inners     = typeParams.Substring(1, typeParams.Length - 2).Split(_genericTypeDelimiter, StringSplitOptions.None);
                string   outer      = typeName.Substring(0, bIndex);
                Type[]   innerTypes = new Type[inners.Length];

                for (int i = 0; i < inners.Length; i++)
                {
                    inners[i]     = inners[i].Trim();
                    innerTypes[i] = Resolve(sc, inners[i]);
                }

                string outerTypeName = $"{outer}`{inners.Length}";
                Type   outerType     = Resolve(sc, outerTypeName);
                t = outerType?.MakeGenericType(innerTypes);
            }

            return(t);
        }
예제 #3
0
        internal override void TranslateFieldPostfix(ShaderTranslationContext sc, VariableDeclaratorSyntax syntax, MappedField field, int fieldIndex, MappedConstantBuffer cBufferMap)
        {
            char?regName = null;

            // Constant buffer fields do not have registers assigned to them.
            if (cBufferMap == null)
            {
                if (field.ResourceBaseType == ShaderResourceBaseType.Sampler)
                {
                    regName = 's';
                }
                else if (field.ResourceBaseType == ShaderResourceBaseType.Texture || field.ResourceBaseType == ShaderResourceBaseType.Buffer)
                {
                    regName = 't';
                }
                else if (field.Type.IsUnorderedAccessType)
                {
                    regName = 'u';
                }
            }

            int fieldTypeSize = field.Info.FieldType.IsValueType ? Marshal.SizeOf(field.Info.FieldType) : 0;

            TranslatePostfixAttributes(sc, field.Attributes, regName, fieldIndex, fieldTypeSize, cBufferMap);
        }
예제 #4
0
        private void MapShaderNodes(TranslationContext context, SyntaxNode node, string strNamespace)
        {
            if (node is ClassDeclarationSyntax classNode)
            {
                string typeName = $"{strNamespace}.{classNode.Identifier}";
                Type   t        = context.Reflection.Assembly.GetType(typeName, false, false);
                if (t != null && context.Reflection.IsShaderType(t))
                {
                    ShaderTranslationContext sc = Pooling.ShaderContexts.Get();
                    sc.Initialize(context, classNode, t);
                    context.Shaders.Add(sc);
                    Message($"Mapped {t.FullName}");

                    // TODO: Remove this return if nested shaders are ever supported.
                    return;
                }
            }
            else if (node is NamespaceDeclarationSyntax nsNode)
            {
                if (strNamespace.Length > 0)
                {
                    strNamespace += ".";
                }

                strNamespace += nsNode.Name;
            }

            IEnumerable <SyntaxNode> stuff = node.ChildNodes();

            foreach (SyntaxNode child in stuff)
            {
                MapShaderNodes(context, child, strNamespace);
            }
        }
예제 #5
0
        internal void Translate(ShaderTranslationContext sc, SyntaxNode syntax, int depth = 0)
        {
            if (sc.IsCompleted(syntax))
            {
                return;
            }

            Type      t         = syntax.GetType();
            ScopeInfo lastScope = sc.Source.CurrentScope;

            if (_processors.TryGetValue(t, out NodeProcessor processor))
            {
                processor.Translate(sc, syntax, sc.Source.CurrentScope);
            }
            //else
            //   sc.Source.Append($"{Environment.NewLine}{new string('\t', depth)}// [[No translator for {t.Name}]] ");

            sc.Complete(syntax);

            IEnumerable <SyntaxNode> children = syntax.ChildNodes();

            foreach (SyntaxNode child in children)
            {
                Translate(sc, child, depth + 1);
            }

            while (lastScope != sc.Source.CurrentScope)
            {
                sc.Source.CloseScope();
            }
        }
예제 #6
0
        private void TranslatePostfixAttributes(ShaderTranslationContext sc, IEnumerable <Attribute> attributes, char?registerName, int fieldIndex, int fieldSize, MappedConstantBuffer cBuffer)
        {
            foreach (Attribute a in attributes)
            {
                switch (a)
                {
                case RegisterAttribute regAtt:
                    if (registerName == null)
                    {
                        continue;
                    }

                    int slotID = (int)(regAtt.Slot + fieldIndex);
                    cBuffer?.BindSlots.Add(new BindPointInfo(regAtt.Model, regAtt.ApplicableEntryPoint, slotID));

                    if (regAtt.ApplicableEntryPoint == EntryPointType.AnyOrNone)
                    {
                        sc.Source.Append($" : register({registerName}{slotID})");
                    }
                    else
                    {
                        string profile = regAtt.Model.ToString().Replace("SM", _profileNames[regAtt.ApplicableEntryPoint]);
                        sc.Source.Append($" : register({profile}, {registerName}{slotID})");
                    }
                    break;

                case PackOffsetAttribute packAtt:
                    if (cBuffer == null)
                    {
                        continue;
                    }

                    int totalComponentOffset = (packAtt.OffsetRegister * COMPONENTS_PER_REGISTER) + (int)packAtt.OffsetComponent;
                    totalComponentOffset += (int)Math.Floor((fieldSize * fieldIndex) / (float)COMPONENT_BYTE_SIZE);
                    PackOffsetComponent component = (PackOffsetComponent)(totalComponentOffset % COMPONENTS_PER_REGISTER);
                    int register = (int)Math.Floor(totalComponentOffset / (float)COMPONENTS_PER_REGISTER);

                    string componentName = component.ToString().ToLower();
                    sc.Source.Append($" : packoffset(c{register}.{componentName})");

                    break;

                case SemanticAttribute semAtt:
                    if (cBuffer != null)
                    {
                        continue;
                    }

                    string semanticName = semAtt.Semantic.ToString().ToUpper();
                    sc.Source.Append($" : {semanticName}");

                    if (semAtt.Slot >= 0)
                    {
                        sc.Source.Append(semAtt.Slot.ToString());
                    }
                    break;
                }
            }
        }
예제 #7
0
        internal static string GetIntrinsicTranslation(ShaderTranslationContext context, string cSharpName)
        {
            if (_intrinsicMethods.TryGetValue(context.Parent.Language.Language, out LanguageInfo info))
            {
                if (info.Intrinsics.TryGetValue(cSharpName, out LanguageMethodInfo methodInfo))
                {
                    return(methodInfo.NativeName);
                }
            }

            return(cSharpName);
        }
예제 #8
0
 internal void Initialize(ShaderTranslationContext sc, TranslationFlags flags)
 {
     _flags                  = flags;
     _language               = sc.Language;
     _currentScope           = Pooling.Scopes.Get();
     _currentScope.Type      = ScopeType.Class;
     _currentScope.TypeInfo  = new ShaderType(_language, sc.ShaderType.Name, sc.ShaderType);
     _currentScope.Namespace = $"{sc.ShaderType.Namespace}.{sc.ShaderType.Name}";
     _rootScope              = _currentScope;
     _firstSegment           = Pooling.SourceSegments.Get();
     _firstSegment.Value     = "";
     _curSegment             = _firstSegment;
     _lastSegment            = _curSegment;
 }
예제 #9
0
        /// <summary>
        /// Finds an insertion point to declare local syntax, such as a local variable. This is generally used for expanding an initializer into full syntax.<para/>
        /// A callback is provided to output translated syntax at the correct location before returning to the end of the output source code.
        /// </summary>
        /// <param name="sc"></param>
        /// <param name="callback"></param>
        internal void DeclareLocal(ShaderTranslationContext sc, Action callback)
        {
            // The root scope implements IDeclarativeScope, so eventually we will hit that if no others are avaialble along the way.
            ScopeInfo si = this;

            while (si != null)
            {
                if (si.Type == ScopeType.Block && si.Parent.Type == ScopeType.Method)
                {
                    sc.Source.GoToSegment(si.OpeningSegment);
                    callback();
                    sc.Source.GoToEnd();
                    return;
                }

                si = si.Parent;
            }
        }
예제 #10
0
 internal override string TranslateNumber(ShaderTranslationContext context, string number)
 {
     // NOTE: hexadecimal literals are supported in HLSL, binary literals are not, so we'll need to translate those.
     if (number.StartsWith("0b")) // Binary literal.
     {
         return(TranslateBinaryLiteral(number));
     }
     else // Hexadecimal + everything else.
     {
         int newLength = number.Length;
         for (int i = number.Length - 1; i >= 0; i--)
         {
             if (!char.IsNumber(number[i]))
             {
                 newLength = i;
                 break;
             }
         }
         return(number.Substring(0, newLength));
     }
 }
예제 #11
0
        internal override void TranslateFieldPrefix(ShaderTranslationContext sc, VariableDeclaratorSyntax syntax, MappedField field, int fieldIndex, MappedConstantBuffer cBufferMap)
        {
            if (typeof(IShaderResource).IsAssignableFrom(field.Info.FieldType))
            {
                sc.MappedFields.Add(field);
            }
            else
            {
                // HLSL puts all global, non-const static variables into the $Global constant buffer.
                if (cBufferMap == null && field.Info.FieldType.DeclaringType == sc.ShaderType)
                {
                    MappedConstantBuffer cBufferGlobal = null;
                    if (!sc.ConstantBuffers.TryGetValue(GLOBAL_CBUFFER_NAME, out cBufferGlobal))
                    {
                        cBufferGlobal = Pooling.MappedConstBuffers.Get();
                        sc.ConstantBuffers.Add(GLOBAL_CBUFFER_NAME, cBufferGlobal);
                    }

                    cBufferGlobal.AddField(field);
                }

                if (typeof(IMatrix).IsAssignableFrom(field.Info.FieldType))
                {
                    if (field.StructureType == ShaderStructureType.MatrixRowMajor)
                    {
                        sc.Source.Append("row_major ");
                    }
                    if (field.StructureType == ShaderStructureType.MatrixColumnMajor)
                    {
                        sc.Source.Append("column_Major ");
                    }
                }
            }

            foreach (Attribute at in field.Attributes)
            {
                switch (at)
                {
                case InterpolationAttribute attInterpolation:
                    foreach (InterpolationMode m in InterpolationAttribute.ModeValues)
                    {
                        if (m == InterpolationMode.None)
                        {
                            continue;
                        }

                        if ((attInterpolation.Flags & m) == m)
                        {
                            sc.Source.Append($" {m.ToString().ToLower()}");
                        }
                    }
                    break;

                case ComputeGroupSharedAttribute attGroupShared:
                    sc.Source.Append(" groupshared ");
                    break;

                case GloballyCoherentAttribute attGlobCoherent:
                    if (field.ResourceBaseType == ShaderResourceBaseType.RWBuffer || field.ResourceBaseType == ShaderResourceBaseType.RWTexture)
                    {
                        sc.Source.Append(" globallycoherent ");
                    }
                    break;
                }
            }
        }
예제 #12
0
 internal override void TranslateConstBufferHeader(ShaderTranslationContext sc, StructDeclarationSyntax syntax, MappedConstantBuffer cBufferMap, IEnumerable <Attribute> attributes)
 {
     throw new NotImplementedException();
 }
예제 #13
0
 internal override string TranslateNumber(ShaderTranslationContext context, string number)
 {
     throw new NotImplementedException();
 }
예제 #14
0
 internal override void TranslateForLoopPrefix(ShaderTranslationContext sc, ForStatementSyntax syntax)
 {
     // TODO Only unroll if loop iteration count is low enough.
     sc.Source.Append("[unroll]");
 }
예제 #15
0
        internal static ShaderType TranslateType(ShaderTranslationContext sc, string typeName)
        {
            ShaderType type = null;

            if (sc.Language.TranslatedTypes.TryGetValue(typeName, out type))
            {
                return(type);
            }
            else
            {
                Type originalType = Resolve(sc, typeName);
                if (originalType != null)
                {
                    ShaderLanguage.Translation translation = sc.Parent.Language.GetTranslation(originalType);
                    if (translation != null)
                    {
                        type = new ShaderType(sc.Language, translation.NativeText, originalType);
                        sc.Language.TranslatedTypes.TryAdd(typeName, type);
                        return(type);
                    }
                    else // Attempt to find any interfaces on the type which can be translated instead.
                    {
                        Type   elementType = originalType.GetElementType();
                        Type[] iTypes;
                        if (elementType != null)
                        {
                            iTypes = elementType.GetInterfaces();
                        }
                        else
                        {
                            iTypes = originalType.GetInterfaces();
                        }

                        foreach (Type implemented in iTypes)
                        {
                            translation = sc.Parent.Language.GetTranslation(implemented);
                            if (translation != null)
                            {
                                string replacement = elementType?.Name ?? originalType.Name;

                                // TODO Does this need optimizing? Benchmark before changing.
                                for (int i = 0; i < IntrinsicPrefixes.Length; i++)
                                {
                                    replacement = replacement.Replace(IntrinsicPrefixes[i], "");
                                }

                                if (translation.UniformSizeIsSingular)
                                {
                                    if (typeof(UniformDimensions).IsAssignableFrom(originalType))
                                    {
                                        replacement = replacement.Substring(0, replacement.Length - 2);
                                    }
                                }

                                replacement = translation.NativeText + replacement;
                                type        = new ShaderType(sc.Language, replacement, originalType);
                                sc.Language.TranslatedTypes.TryAdd(typeName, type);
                                return(type);
                            }
                        }

                        // Create a placeholder type instead.
                        type = new ShaderType(sc.Language, typeName, originalType);
                        sc.Language.TranslatedTypes.TryAdd(typeName, type);
                        return(type);
                    }
                }

                // We have no known Type instance to use, so try to figure out if it's an array or not, manually.
                int openIndex = typeName.IndexOf("[");
                if (openIndex > -1 && typeName.EndsWith("]"))
                {
                    typeName = typeName.Substring(0, openIndex);
                    int    endLen         = typeName.Length - openIndex;
                    string reflectiveName = $"System.Object{typeName.Substring(openIndex, endLen)}";
                    type = new ShaderType(sc.Language, typeName, Type.GetType(reflectiveName));
                }
                else
                {
                    type = new ShaderType(sc.Language, typeName, typeof(object));
                }

                // Create a placeholder type using object base class instead.
                sc.Language.TranslatedTypes.TryAdd(typeName, type);
                return(type);
            }
        }
예제 #16
0
 /// <summary>
 /// Returns true
 /// </summary>
 /// <param name="sc">The <see cref="ShaderTranslationContext"/>.</param>
 /// <param name="syntax">The <see cref="SyntaxNode"/> to be translated.</param>
 internal abstract void Translate(ShaderTranslationContext sc, SyntaxNode syntax, ScopeInfo scope);
예제 #17
0
 internal abstract void TranslateConstBufferHeader(ShaderTranslationContext sc, StructDeclarationSyntax syntax, MappedConstantBuffer cBufferMap, IEnumerable <Attribute> attributes);
예제 #18
0
 internal override void TranslateForLoopPrefix(ShaderTranslationContext sc, ForStatementSyntax syntax)
 {
     throw new NotImplementedException();
 }
예제 #19
0
 internal abstract void TranslateFieldPostfix(ShaderTranslationContext sc, VariableDeclaratorSyntax syntax, MappedField field, int fieldIndex, MappedConstantBuffer cBufferMap);
예제 #20
0
 internal override void TranslateFieldPostfix(ShaderTranslationContext sc, VariableDeclaratorSyntax syntax, MappedField field, int fieldIndex, MappedConstantBuffer cBufferMap)
 {
     throw new NotImplementedException();
 }
예제 #21
0
 internal abstract string TranslateNumber(ShaderTranslationContext sc, string number);
예제 #22
0
 internal abstract void TranslateForLoopPrefix(ShaderTranslationContext sc, ForStatementSyntax syntax);
예제 #23
0
 internal override void TranslateConstBufferHeader(ShaderTranslationContext sc, StructDeclarationSyntax syntax, MappedConstantBuffer cBufferMap, IEnumerable <Attribute> attributes)
 {
     sc.Source.AppendLineBreak();
     sc.Source.Append($"cbuffer {cBufferMap.TypeInfo.Name}");
     TranslatePostfixAttributes(sc, attributes, 'b', 0, 0, cBufferMap);
 }