Beispiel #1
0
        protected override void OnTranslate(ShaderTranslationContext sc, MethodDeclarationSyntax syntax, ScopeInfo scope)
        {
            MethodInfo info = sc.GetMethodInfo(syntax);

            if (info != null)
            {
                MappedEntryPoint ep = null;
                sc.EntryPointsByMethod.TryGetValue(info, out ep);

                sc.Source.AppendLineBreak();
                ScopeInfo mScope = sc.Source.OpenScope(ScopeType.Method, null, ep);
                mScope.Method = info;

                ShaderType returnType = ShaderType.TranslateType(sc, syntax.ReturnType.ToString());

                ep?.Translator?.TranslatePrefix(sc, info, syntax, ep);
                sc.Source.Append($"{returnType.Translation} {syntax.Identifier.ValueText}");

                sc.Complete(syntax.ReturnType);
                sc.Complete(syntax.ConstraintClauses);
                sc.Complete(syntax.AttributeLists);

                if (syntax.TypeParameterList != null)
                {
                    sc.CompleteSelfAndChildren(syntax.TypeParameterList);
                }

                // Translate parameters before method body.
                sc.Runner.Translate(sc, syntax.ParameterList, 0);
                ep?.Translator?.TranslatePostfix(sc, info, syntax, ep);
            }
        }
Beispiel #2
0
        protected override void OnTranslate(ShaderTranslationContext sc, ParameterSyntax syntax, ScopeInfo scope)
        {
            ScopeInfo        methodScope = scope.FindOfType(ScopeType.Method);
            MethodInfo       methodInfo  = null;
            MappedEntryPoint ep          = null;

            if (scope.Type == ScopeType.Parentheses)
            {
                if (scope.Items.Last() != syntax)
                {
                    sc.Source.OpenScope(ScopeType.ParenthesesItem);
                }
            }

            if (methodScope != null)
            {
                methodInfo = methodScope.Method;
                sc.EntryPointsByMethod.TryGetValue(methodInfo, out ep);
            }

            // TODO pass to language variable translation, since parameters can have attributes
            ShaderType type        = ShaderType.TranslateType(sc, syntax.Type.ToString());
            bool       wasAppended = false;

            if (ep != null)
            {
                (ParameterInfo pInfo, int pIndex) = sc.GetParameterInfo(methodInfo, syntax.Identifier.ValueText);
                IEnumerable <Attribute> pAttributes = pInfo.GetCustomAttributes();

                ep.Translator?.TranslateParameterPrefix(sc, syntax, ep, pInfo, pAttributes, pIndex);
                sc.Source.Append($"{type.Translation} {syntax.Identifier.ValueText}");
                ep.Translator?.TranslateParameterPostfix(sc, syntax, ep, pInfo, pAttributes, pIndex);
                wasAppended = true;
            }

            if (!wasAppended)
            {
                sc.Source.Append($"{type.Translation} {syntax.Identifier.ValueText}");
            }

            sc.Complete(syntax.Type);
            sc.Complete(syntax.AttributeLists);
        }
        protected override void OnTranslate(ShaderTranslationContext sc, PropertyDeclarationSyntax syntax, ScopeInfo scope)
        {
            ScopeInfo classScope = scope.FindOfType(ScopeType.Class);
            ScopeInfo pScope     = sc.Source.OpenScope(ScopeType.Property);

            pScope.Identifier = syntax.Identifier.ValueText;

            sc.Complete(syntax.Type);

            pScope.TypeInfo = ShaderType.TranslateType(sc, syntax.Type.ToString());
        }
        protected override void OnTranslate(ShaderTranslationContext sc, ObjectCreationExpressionSyntax syntax, ScopeInfo scope)
        {
            // Are we directly inside an initializer? (i.e. array initializer)
            if (scope.Type == ScopeType.ArrayInitializer)
            {
                if (syntax != scope.Items.Last())
                {
                    sc.Source.OpenScope(ScopeType.ArrayElement);
                }
            }

            string     typeName = syntax.Type.ToString();
            ShaderType type     = ShaderType.TranslateType(sc, typeName);

            sc.Complete(syntax.Type);

            // Handle initializers. These require declaring as a local variable above the current syntax node.
            if (syntax.Initializer != null)
            {
                switch (syntax.Parent)
                {
                case ReturnStatementSyntax returnSyntax:
                case AssignmentExpressionSyntax assignSyntax:
                    string strInit = type.Translation;
                    string varName = sc.Parent.GetNewVariableName("oc_init");

                    scope.DeclareLocal(sc, () =>
                    {
                        sc.Source.Append($"{type.Translation} {varName} = {type.Translation}");
                        sc.Runner.Translate(sc, syntax.ArgumentList);
                        sc.Source.Append(";");
                        sc.Source.AppendLineBreak();

                        ScopeInfo iScope  = sc.Source.OpenScope(ScopeType.ExpandedInitializer);
                        iScope.Identifier = varName;

                        sc.Runner.Translate(sc, syntax.Initializer);
                    });

                    sc.Source.Append(varName);
                    break;

                default:
                    sc.Source.Append(type.Translation);
                    break;
                }
            }
            else
            {
                sc.Source.Append(type.Translation);
            }
        }
Beispiel #5
0
 protected override void OnTranslate(ShaderTranslationContext sc, ClassDeclarationSyntax syntax, ScopeInfo scope)
 {
     if ($"{sc.ShaderType.Namespace}.{syntax.Identifier.ValueText}" != sc.Name)
     {
         // TODO does the shader language support classes?
         //      If not, we need a system to translate the class into another form of usable output source.
         Type      t      = sc.Parent.Reflection.Assembly.GetType($"{scope.Namespace}+{syntax.Identifier.ValueText}");
         ScopeInfo cScope = sc.Source.OpenScope(ScopeType.Class, t);
     }
     else
     {
         sc.Complete(syntax.BaseList);
     }
 }
        protected override void OnTranslate(ShaderTranslationContext sc, VariableDeclarationSyntax syntax, ScopeInfo scope)
        {
            string     typeName = syntax.Type.ToString();
            ShaderType type     = ShaderType.TranslateType(sc, typeName);

            ScopeInfo tScope = sc.Source.OpenScope(ScopeType.Typed, type);

            tScope.TypeInfo = type;
            tScope.IsLocal  = syntax.Parent is LocalDeclarationStatementSyntax;
            tScope.Items    = syntax.Variables;

            if (syntax.Parent is FieldDeclarationSyntax fieldSyntax)
            {
                tScope.TranslatedModifiers = sc.Language.TranslateModifiers(fieldSyntax.Modifiers);
            }

            sc.Complete(syntax.Type);
        }
Beispiel #7
0
 protected override void OnTranslate(ShaderTranslationContext sc, ArrayTypeSyntax syntax, ScopeInfo scope)
 {
     sc.Complete(syntax.ElementType);
 }
        protected override void OnTranslate(ShaderTranslationContext sc, VariableDeclaratorSyntax syntax, ScopeInfo scope)
        {
            if (scope.Type == ScopeType.Typed)
            {
                FieldInfo            fInfo      = null;
                MappedField          mField     = null;
                MappedConstantBuffer cBufferMap = null;

                if (scope.Parent.Type == ScopeType.Struct)
                {
                    fInfo = scope.Parent.TypeInfo.OriginalType.GetField(syntax.Identifier.ValueText);
                    sc.ConstantBuffers.TryGetValue(scope.Parent.TypeInfo.OriginalType.Name, out cBufferMap);
                }

                if (fInfo == null)
                {
                    sc.Fields.TryGetValue(syntax.Identifier.ValueText, out fInfo);
                }


                if (fInfo != null)
                {
                    int fieldIndex = scope.Items.IndexOf(syntax);
                    mField = Pooling.MappedFields.Get();
                    mField.Initialize(scope.TypeInfo, fInfo);
                    cBufferMap?.AddField(mField);

                    sc.Language.TranslateFieldPrefix(sc, syntax, mField, fieldIndex, cBufferMap);
                    sc.Source.Append($"{scope.TranslatedModifiers} ");
                    sc.Source.Append(scope.TypeInfo.Translation);
                    sc.Source.Append($" {syntax.Identifier.ValueText}");
                    sc.Language.TranslateFieldPostfix(sc, syntax, mField, fieldIndex, cBufferMap);
                }
                else
                {
                    sc.Source.Append($"{scope.TranslatedModifiers} ");
                    sc.Source.Append(scope.TypeInfo.Translation);
                    sc.Source.Append($" {syntax.Identifier.ValueText}");
                }

                // Handle corner-cases for array initializers.
                if (scope.TypeInfo != null && syntax.Initializer != null)
                {
                    if (scope.TypeInfo.WasArrayType)
                    {
                        switch (syntax.Initializer.Value)
                        {
                        case InitializerExpressionSyntax initSyntax:
                            IEnumerable <SyntaxNode> initChildren = initSyntax.ChildNodes();
                            int arraySize = initChildren.Count();
                            sc.Source.Append($"[{arraySize}]");

                            if (mField != null)
                            {
                                mField.ArrayDimensions.Add(arraySize);
                            }

                            // TODO multi-dimensional array support (e.g. [4][2]).
                            //     - For multi-dimensional arrays, we can simply take the dimensions directly.
                            //     - For jagged arrays, we need to find the largest sub-array and use that as the size for it's respective dimension.
                            break;

                        case ArrayCreationExpressionSyntax arraySyntax:
                            sc.Runner.Translate(sc, arraySyntax.Type);
                            break;
                        }
                    }
                }

                bool isForInitializer = (syntax.Parent is VariableDeclarationSyntax varDecSyntax && varDecSyntax.Parent is ForStatementSyntax forSyntax);
                if (!isForInitializer)
                {
                    if (syntax.Initializer != null && syntax.Initializer.Value is ObjectCreationExpressionSyntax objSyntax && objSyntax.Initializer != null)
                    {
                        ScopeInfo si = sc.Source.OpenScope(ScopeType.ExpandedInitializer);
                        si.Identifier = syntax.Identifier.ValueText;
                        sc.Source.Append(" = ");

                        // Are we instantiating a new struct value with no args?
                        if (objSyntax.ArgumentList.Arguments.Count == 0 && scope.TypeInfo.OriginalType.IsValueType)
                        {
                            sc.Source.Append($"({scope.TypeInfo.Translation})0;"); // TODO does GLSL allow this? Do we abstract or add a language property to check against?
                            sc.Source.AppendLineBreak();
                            sc.Complete(objSyntax.ArgumentList);
                            sc.Complete(objSyntax.Type);
                        }
                        else
                        {
                            sc.Source.Append(scope.TypeInfo.Translation);
                            sc.Runner.Translate(sc, objSyntax.ArgumentList);
                            sc.Source.Append(";");
                            sc.Source.AppendLineBreak();
                            sc.Runner.Translate(sc, objSyntax.Initializer);
                            sc.Complete(objSyntax.ArgumentList);
                            sc.Complete(objSyntax.Type);
                        }

                        // We no longer need to translate the object creation syntax, but we still want it's initializer.
                        sc.Complete(syntax.Initializer);
                        sc.Runner.Translate(sc, objSyntax.Initializer);
                    }
                    else
                    {
                        ScopeInfo si = sc.Source.OpenScope(ScopeType.Variable);
                        si.Identifier = syntax.Identifier.ValueText;
                    }
                }
            }
        protected override void OnTranslate(ShaderTranslationContext sc, MemberAccessExpressionSyntax syntax, ScopeInfo scope)
        {
            switch (syntax.Expression)
            {
            case IdentifierNameSyntax idSyntax:
                // Is this a static class identifier?
                // Static classes are abstract and sealed at IL level.
                Type targetType = ShaderType.Resolve(sc, idSyntax.Identifier.ValueText);
                if (targetType != null && targetType.IsClass && targetType.IsAbstract && targetType.IsSealed)
                {
                    // Is the member a constant value? If so, we can take it's value directly.
                    FieldInfo fInfo = targetType.GetField(syntax.Name.Identifier.ValueText);
                    if (fInfo != null && (fInfo.Attributes & FieldAttributes.Literal) == FieldAttributes.Literal)
                    {
                        object val = fInfo.GetValue(null);
                        if (val != null)
                        {
                            sc.Source.Append(val.ToString());
                            sc.CompleteChildren(syntax);
                            return;
                        }
                    }
                }
                else
                {
                    ScopeInfo cScope = scope.FindOfType(ScopeType.Class);
                    if (cScope == sc.Source.RootScope)
                    {
                        FieldInfo fInfo = cScope.TypeInfo.OriginalType.GetField(idSyntax.Identifier.ValueText);
                        if (fInfo != null && sc.ConstantBuffers.Values.Any(x => x.TypeInfo == fInfo.FieldType))
                        {
                            if (!sc.Language.InstancedConstantBuffers)
                            {
                                sc.CompleteSelfAndChildren(syntax.Expression);
                                sc.Runner.Translate(sc, syntax.Name);
                                return;
                            }
                        }
                    }
                }
                break;

            case ThisExpressionSyntax thisSyntax:
            case BaseExpressionSyntax baseSyntax:
                ScopeInfo pScope = scope.FindOfType(ScopeType.Class);
                if (pScope.TypeInfo.OriginalType == sc.ShaderType)
                {
                    sc.Complete(syntax.Expression);

                    // Are we translating a shader intrinsic method/function?
                    if (syntax.Name is IdentifierNameSyntax idSyntax && syntax.Parent is InvocationExpressionSyntax)
                    {
                        string translatedIntrinsic = ShaderType.GetIntrinsicTranslation(sc, idSyntax.Identifier.ValueText);
                        sc.Source.Append(translatedIntrinsic);
                        sc.Complete(syntax.Name);
                    }
                    return;
                }
                break;
            }

            sc.Runner.Translate(sc, syntax.Expression);
            sc.Source.Append(syntax.OperatorToken);
            sc.Runner.Translate(sc, syntax.Name);
        }