Exemplo n.º 1
0
        void ProcessValues(ref StageValue obj, out MetaStage minStage, out MetaStage maxStage, Expression inArg, out Expression outArg)
        {
            minStage = obj.MinStage;
            maxStage = obj.MaxStage;

            var stageArg = ProcessValue(inArg);

            if (stageArg.MinStage > minStage)
            {
                minStage = stageArg.MinStage;
            }

            if (stageArg.MaxStage < maxStage)
            {
                maxStage = stageArg.MaxStage;
            }

            if (maxStage < minStage)
            {
                maxStage = minStage;
            }

            outArg = ProcessStage(stageArg, minStage, maxStage).Value;
            obj    = ProcessStage(obj, minStage, maxStage);
        }
Exemplo n.º 2
0
        Expression ProcessVertexBuffer(StageValue vertexBuffer)
        {
            Expression result;

            if (!VertexBuffers.TryGetValue(vertexBuffer.Value.ToString(), out result))
            {
                var src  = vertexBuffer.Value.Source;
                var type = ILFactory.GetType(src, "Uno.Graphics.VertexBuffer");

                if (vertexBuffer.Value.ReturnType.Equals(type))
                {
                    result = ProcessStage(vertexBuffer, MetaStage.Volatile, MetaStage.Volatile).Value;
                    VertexBuffers.Add(vertexBuffer.Value.ToString(), result);
                    return(result);
                }

                var loc = LocationStack.Last();
                var mp  = GetProperty(loc);

                var name  = CreateFieldName(mp, loc);
                var owner = Path.DrawBlock.Method.DeclaringType;

                var field = new Field(src, owner, name, null, Modifiers.Private | Modifiers.Generated, 0, type);
                owner.Fields.Add(field);

                result = new LoadField(src, new This(src, owner), field);
                VertexBuffers.Add(vertexBuffer.Value.ToString(), result);

                if (vertexBuffer.MinStage > MetaStage.Volatile)
                {
                    Log.Error(src, ErrorCode.E5025, "Vertex buffer cannot be accessed from " + vertexBuffer.MinStage + " stage");
                    return(result);
                }
                else if (vertexBuffer.MinStage == MetaStage.Volatile)
                {
                    InitScope.Statements.Add(
                        new StoreField(src, new This(src, owner), field,
                                       ILFactory.NewObject(src, "Uno.Graphics.VertexBuffer",
                                                           ILFactory.GetExpression(src, "Uno.Graphics.BufferUsage.Dynamic"))));

                    FrameScope.Statements.Add(
                        ILFactory.CallMethod(src, new LoadField(src, new This(src, owner), field), "Update",
                                             vertexBuffer.Value));
                }
                else
                {
                    InitScope.Statements.Add(
                        new StoreField(src, new This(src, owner), field,
                                       ILFactory.NewObject(src, "Uno.Graphics.VertexBuffer",
                                                           vertexBuffer.Value,
                                                           ILFactory.GetExpression(src, "Uno.Graphics.BufferUsage.Immutable"))));
                }

                FreeScope.Statements.Add(
                    ILFactory.CallMethod(src, new LoadField(src, new This(src, owner), field), "Dispose"));
            }

            return(result);
        }
Exemplo n.º 3
0
 void DetectVertexCount(StageValue buffer)
 {
     foreach (var p in buffer.Value.ReturnType.Properties)
     {
         if (p.UnoName == "Length")
         {
             AddDetectedVertexCount(new StageValue(new GetProperty(buffer.Value.Source, buffer.Value, p), buffer.MinStage, buffer.MaxStage));
             return;
         }
     }
 }
Exemplo n.º 4
0
        void AddDetectedVertexCount(StageValue c)
        {
            var key = c.Value.ToString();

            foreach (var d in DetectedVertexCounts)
            {
                if (d.Value.ToString() == key)
                {
                    return;
                }
            }

            DetectedVertexCounts.Add(c);
        }
Exemplo n.º 5
0
        StageValue ProcessShaderConstant(StageValue s, MetaLocation loc, MetaProperty mp)
        {
            s = ProcessStage(s, MetaStage.Volatile, MetaStage.Volatile);

            var key = s.Value.ToString();

            int index;

            if (!Constants.TryGetValue(key, out index))
            {
                index = DrawState.RuntimeConstants.Count;
                DrawState.RuntimeConstants.Add(new ShaderVariable(s.Value.ReturnType, CreateShaderName(mp, loc, s.Value), s.Value));
                Constants.Add(key, index);
            }

            return(new StageValue(new RuntimeConst(s.Value.Source, DrawState, index), MetaStage.Vertex, MetaStage.Pixel));
        }
Exemplo n.º 6
0
        void AdjustFunctionStageRange(ref StageValue obj, Function func)
        {
            // TODO: Implement code analyzer to make sure func will work in shader or not
            if (obj.MaxStage >= MetaStage.Volatile &&
                !Backend.ShaderBackend.IsIntrinsic(func) &&
                func.Body == null)
            {
                obj.MaxStage = MetaStage.Volatile;
            }

            var shaderStageObj = func.TryGetAttribute(Essentials.RequireShaderStageAttribute);

            if (shaderStageObj != null)
            {
                obj.MinStage = obj.MaxStage = (MetaStage)(int)shaderStageObj;
            }
        }
Exemplo n.º 7
0
        internal StageValue ProcessStage(StageValue sym, MetaStage min, MetaStage max)
        {
            var loc = LocationStack.Last();
            var mp  = GetProperty(loc);

            if (max < sym.MinStage)
            {
                Log.Error(sym.Value.Source, ErrorCode.E5015, sym.MinStage.ToLiteral().Quote() + " cannot be accessed from stage " + max.ToLiteral().Quote() + " while processing " + mp.Name.Quote() + " at " + mp.Source + " in " + Path.Quote() + " at " + Path.Source);
                return(new StageValue(Expression.Invalid, MetaStage.Const));
            }

            // Handle stage change if necessary or default to lowest possible stage
            if (min > sym.MaxStage ||
                min > sym.MinStage && sym.Value != null && !InlineOnStage(min, sym.Value))
            {
                return(ProcessStageChange(sym, sym.MinStage, min, loc, mp));
            }

            return(sym);
        }
Exemplo n.º 8
0
        StageValue ProcessFixedArrayDeclaration(FixedArrayDeclaration s)
        {
            Expression[] initializer = null;

            var minStage = MetaStage.Const;
            var maxStage = MetaStage.Max;

            if (s.OptionalInitializer != null)
            {
                var stageValues = new StageValue[s.OptionalInitializer.Length];

                for (int i = 0; i < stageValues.Length; i++)
                {
                    var v = stageValues[i] = ProcessValue(s.OptionalInitializer[i]);

                    if (v.MinStage > minStage)
                    {
                        minStage = v.MinStage;
                    }

                    if (v.MaxStage < maxStage)
                    {
                        maxStage = v.MaxStage;
                    }
                }

                initializer = new Expression[stageValues.Length];

                if (maxStage < minStage)
                {
                    maxStage = minStage;
                }

                for (int i = 0; i < stageValues.Length; i++)
                {
                    initializer[i] = ProcessStage(stageValues[i], minStage, maxStage).Value;
                }
            }

            return(new StageValue(new PlaceholderArray(s.Source, s.Variable.ValueType, initializer), minStage, maxStage));
        }
Exemplo n.º 9
0
        void AdjustInstanceStageRange(ref StageValue obj, DataType dt, bool isFieldOrPropertyAccess)
        {
            // Default volatile on static members and current class members
            if (obj.MaxStage >= MetaStage.Volatile &&
                (obj.Value == null || obj.Value.ActualValue is This || obj.Value.ActualValue is Base) &&
                (obj.Value != null || isFieldOrPropertyAccess))
            {
                obj.MinStage = MetaStage.Volatile;
            }

            if (isFieldOrPropertyAccess &&
                !Backend.ShaderBackend.IsIntrinsic(dt))
            {
                obj.MaxStage = MetaStage.Volatile;
            }

            var shaderStageObj = dt.TryGetAttribute(Essentials.RequireShaderStageAttribute);

            if (shaderStageObj != null)
            {
                obj.MinStage = obj.MaxStage = (MetaStage)(int)shaderStageObj;
            }
        }
Exemplo n.º 10
0
        void ProcessIndexBuffer(Source vaSrc, StageValue indexBuffer, StageValue indexType)
        {
            if (IndexBuffer == null && indexBuffer.Value == null && IndexType == null && indexType.Value == null ||
                indexBuffer.Value != null && IndexBuffer == indexBuffer.Value.ToString() && indexType.Value != null && IndexType == indexType.Value.ToString())
            {
                // OK
                return;
            }

            if (IndexBuffer != null || indexBuffer.Value == null || IndexType != null || indexType.Value == null)
            {
                Log.Error(vaSrc, ErrorCode.E5023, "Index buffer argument must be consistent for all <vertex_attrib>s in " + Path.Quote());
                return;
            }

            var src  = indexBuffer.Value.Source;
            var type = ILFactory.GetType(src, "Uno.Graphics.IndexBuffer");

            IndexBuffer = indexBuffer.Value.ToString();
            IndexType   = indexType.Value.ToString();

            if (indexBuffer.Value.ReturnType.Equals(type))
            {
                DrawState.OptionalIndices = new IndexBinding(
                    ProcessStage(indexType, MetaStage.Volatile, MetaStage.Volatile).Value,
                    ProcessStage(indexBuffer, MetaStage.Volatile, MetaStage.Volatile).Value);

                return;
            }

            var loc = LocationStack.Last();
            var mp  = GetProperty(loc);

            var name  = CreateFieldName(mp, loc);
            var owner = Path.DrawBlock.Method.DeclaringType;

            var field = new Field(src, owner, name,
                                  null, Modifiers.Private | Modifiers.Generated, 0, type);

            owner.Fields.Add(field);

            DrawState.OptionalIndices = new IndexBinding(
                ProcessStage(indexType, MetaStage.Volatile, MetaStage.Volatile).Value,
                new LoadField(src, new This(src, owner), field));

            if (indexBuffer.MinStage > MetaStage.Volatile)
            {
                Log.Error(src, ErrorCode.E5024, "Index buffer cannot be accessed from " + indexBuffer.MinStage + " stage");
                return;
            }

            if (indexBuffer.MinStage == MetaStage.Volatile)
            {
                InitScope.Statements.Add(
                    new StoreField(src, new This(src, owner), field,
                                   ILFactory.NewObject(src, "Uno.Graphics.IndexBuffer",
                                                       ILFactory.GetExpression(src, "Uno.Graphics.BufferUsage.Dynamic"))));

                FrameScope.Statements.Add(
                    ILFactory.CallMethod(src, new LoadField(src, new This(src, owner), field), "Update",
                                         indexBuffer.Value));
            }
            else
            {
                InitScope.Statements.Add(
                    new StoreField(src, new This(src, owner), field, ILFactory.NewObject(src, "Uno.Graphics.IndexBuffer",
                                                                                         indexBuffer.Value,
                                                                                         ILFactory.GetExpression(src, "Uno.Graphics.BufferUsage.Immutable"))));
            }

            FreeScope.Statements.Add(
                ILFactory.CallMethod(src, new LoadField(src, new This(src, owner), field), "Dispose"));
        }
Exemplo n.º 11
0
        StageValue ProcessMetaProperty(MetaLocation loc, bool required = true)
        {
            StageValue result;

            if (ProcessedMetaProperties.TryGetValue(loc, out result))
            {
                return(new StageValue(result.Value.CopyExpression(new CopyState(DrawState.Path.DrawBlock.Method)), result.MinStage, result.MaxStage));
            }

            var mp  = GetProperty(loc);
            var def = GetValidDefinition(loc);

            if (def == null)
            {
                if (required)
                {
                    Log.Error(CreateTrace(mp, loc, null), ErrorCode.E5004, "No valid definition of " + mp.Name.Quote() + " was found in " + Path.Quote());
                    return(new StageValue(Expression.Invalid, MetaStage.Const));
                }

                return(new StageValue(null, MetaStage.Const));
            }

            // Detect circular references (should not happen)
            foreach (var ploc in LocationStack)
            {
                if (ploc == loc)
                {
                    Log.Error(CreateTrace(mp, loc, LocationStack), ErrorCode.E5005, "Circular reference to " + mp.Name.Quote() + " detected while processing " + Path.Quote());
                    return(new StageValue(Expression.Invalid, MetaStage.Const));
                }
            }

            LocationStack.Add(loc);

            switch (def.Value.StatementType)
            {
            case StatementType.Expression:
                result       = ProcessValue(def.Value as Expression);
                result.Value = new FunctionCompiler(Compiler, mp).CompileImplicitCast(def.Value.Source, mp.ReturnType, result.Value);
                break;

            case StatementType.Scope:
                result = ScopeProcessor.Process(this, def.Value as Scope);
                break;

            case StatementType.FixedArrayDeclaration:
                result = ProcessFixedArrayDeclaration(def.Value as FixedArrayDeclaration);
                break;

            default:
                // Should not happen
                Log.Error(def.Value.Source, ErrorCode.I5006, "<" + def.Value.StatementType + "> is not supported by ShaderGenerator");
                result = new StageValue(Expression.Invalid, MetaStage.Const);
                ProcessedMetaProperties.Add(loc, result);
                return(result);
            }

            LocationStack.RemoveLast();

            if (!InlineOnStage(result.MinStage, result.Value))
            {
                MetaStage resultStage;
                Scope     resultScope;

                switch (result.MinStage)
                {
                case MetaStage.Pixel:
                    resultStage = MetaStage.Pixel;
                    resultScope = PixelScope;
                    break;

                case MetaStage.Vertex:
                    resultStage = MetaStage.Vertex;
                    resultScope = VertexScope;
                    break;

                case MetaStage.Volatile:
                    resultStage = MetaStage.Volatile;
                    resultScope = FrameScope;
                    break;

                default:
                    resultStage = MetaStage.ReadOnly;
                    resultScope = InitScope;
                    break;
                }

                var val = new PlaceholderValue(mp, loc, result.Value, resultStage);
                result = new StageValue(new PlaceholderReference(val), val.Stage);
                resultScope.Statements.Add(new VariableDeclaration(mp.Source, null, CreateLocalName(mp, loc), val.ReturnType, VariableType.Default, val));
            }
            else if (!(result.Value is PlaceholderReference) && !(result.Value is PlaceholderValue) && !(result.Value is Constant))
            {
                result.Value = new PlaceholderValue(mp, loc, result.Value, MetaStage.Undefined);
            }

            ProcessedMetaProperties.Add(loc, result);
            return(result);
        }
Exemplo n.º 12
0
        internal StageValue ProcessStageChange(StageValue s, MetaStage fromStage, MetaStage toStage, MetaLocation loc, MetaProperty mp)
        {
            if (s.Value == null)
            {
                return(new StageValue(null, toStage));
            }

            if (s.MinStage > fromStage)
            {
                Log.Error(s.Value.Source, ErrorCode.I5016, "Stage error");
                return(new StageValue(Expression.Invalid, toStage));
            }

            switch (toStage)
            {
            case MetaStage.Pixel:
            case MetaStage.Vertex:
                if (fromStage == MetaStage.Vertex && toStage == MetaStage.Pixel)
                {
                    // Vertex -> Pixel: Varying

                    var key = s.Value.ToString();

                    int index;
                    if (!Varyings.TryGetValue(key, out index))
                    {
                        index = DrawState.Varyings.Count;
                        DrawState.Varyings.Add(new ShaderVariable(s.Value.ReturnType, CreateShaderName(mp, loc, s.Value), s.Value));
                        Varyings.Add(key, index);
                    }

                    return(new StageValue(new LoadVarying(s.Value.Source, DrawState, index), MetaStage.Pixel, MetaStage.Pixel));
                }
                else if (s.Value.ReturnType == Essentials.Bool || s.Value.ReturnType == Essentials.Int)
                {
                    return(ProcessShaderConstant(s, loc, mp));
                }
                else
                {
                    // Init,Frame -> Vertex,Pixel: Uniform

                    s = ProcessStage(s, MetaStage.Volatile, MetaStage.Volatile);

                    var val = s.Value.ActualValue;
                    var dt  = val.ReturnType;
                    var key = val.ToString();

                    int index;
                    if (!Uniforms.TryGetValue(key, out index))
                    {
                        index = DrawState.Uniforms.Count;

                        switch (dt.TypeType)
                        {
                        case TypeType.FixedArray:
                            // Ugly workaround. ResolvedMetaPropertyValue could already be an address
                            if (!(val is PlaceholderValue && (val as PlaceholderValue).Value is AddressOf))
                            {
                                val = new AddressOf(val.ActualValue, AddressType.Const);
                            }

                            break;

                        case TypeType.RefArray:
                            var at = dt as RefArrayType;
                            var et = at.ElementType;

                            var size = ProcessShaderConstant(
                                new StageValue(ILFactory.GetProperty(s.Value.Source, s.Value, "Length"), s.MinStage, s.MaxStage),
                                loc, mp).Value;

                            dt = new FixedArrayType(s.Value.Source, et, size, Essentials.Int);
                            break;
                        }

                        DrawState.Uniforms.Add(new ShaderVariable(dt, CreateShaderName(mp, loc, val), val));
                        Uniforms.Add(key, index);
                    }

                    Expression u = new LoadUniform(s.Value.Source, DrawState, index);

                    if (u.ReturnType.IsFixedArray)
                    {
                        u = new AddressOf(u, AddressType.Const);
                    }

                    return(new StageValue(u, MetaStage.Vertex, MetaStage.Pixel));
                }

            case MetaStage.Volatile:
                if (fromStage <= MetaStage.ReadOnly)
                {
                    // Init -> Frame: Field

                    var src = s.Value.Source;
                    var dt  = Path.DrawBlock.Method.DeclaringType;
                    var obj = new This(src, dt).Address;
                    var key = s.Value.ToString();

                    Field field;
                    if (!Fields.TryGetValue(key, out field))
                    {
                        for (int i = 0; i < InitScope.Statements.Count; i++)
                        {
                            if (InitScope.Statements[i] is StoreField)
                            {
                                var sf = InitScope.Statements[i] as StoreField;
                                if (sf.Field.ReturnType.Equals(s.Value.ReturnType) && sf.Value.ToString() == key)
                                {
                                    field = sf.Field;
                                }
                            }
                        }

                        if (field == null)
                        {
                            field = new Field(src, dt, CreateFieldName(mp, loc, s.Value),
                                              null, Modifiers.Private | Modifiers.Generated, 0, s.Value.ReturnType);
                            dt.Fields.Add(field);
                            InitScope.Statements.Add(new StoreField(src, obj, field, s.Value));
                        }

                        Fields.Add(key, field);
                    }

                    return(new StageValue(new LoadField(src, obj, field), MetaStage.ReadOnly, MetaStage.Volatile));
                }
                break;

            case MetaStage.ReadOnly:
                return(s);
            }

            Log.Error(s.Value.Source, ErrorCode.E5017, fromStage.ToLiteral().Quote() + " cannot be accessed from " + toStage.ToLiteral() + " stage while processing " + mp.Name.Quote() + " at " + mp.Source + " in " + Path.Quote() + " at " + Path.Source);
            return(new StageValue(Expression.Invalid, MetaStage.Const));
        }
Exemplo n.º 13
0
        internal StageValue ProcessValue(Expression e)
        {
            if (e == null)
            {
                return(new StageValue(null, MetaStage.Const));
            }

            switch (e.ExpressionType)
            {
            case ExpressionType.StageOp:
            {
                var s  = e as StageOp;
                var op = ProcessValue(s.Operand);

                if (s.Stage > MetaStage.Volatile)
                {
                    op = ProcessStage(op, s.Stage, s.Stage);
                }
                else if (op.MinStage > MetaStage.Volatile)
                {
                    Log.Error(s.Operand.Source, ErrorCode.E0000, "Invalid " + s.Stage.ToLiteral() + " expression in " + Path.Quote());
                    return(new StageValue(Expression.Invalid, s.Stage, s.Stage));
                }

                op.MinStage = s.Stage;
                return(op);
            }

            case ExpressionType.NewVertexAttrib:
                return(ProcessVertexAttrib(e as NewVertexAttrib));

            case ExpressionType.NewPixelSampler:
                return(ProcessPixelSampler(e as NewPixelSampler));

            case ExpressionType.GetMetaProperty:
            {
                var s   = e as GetMetaProperty;
                var loc = TryGetLocation(LocationStack.Last(), s.Name, s.Offset);

                if (loc == null)
                {
                    if (s.Offset == 0)
                    {
                        Log.Error(s.Source, ErrorCode.E5019, s.Name.Quote() + " was not found in " + Path.Quote());
                    }
                    else
                    {
                        Log.Error(s.Source, ErrorCode.E5020, "Previous declaration of " + s.Name.Quote() + " was not found in " + Path.Quote());
                    }

                    return(new StageValue(Expression.Invalid, MetaStage.Const));
                }

                return(ProcessMetaProperty(loc.Value));
            }

            case ExpressionType.GetMetaObject:
            {
                var s   = e as GetMetaObject;
                var obj = TryGetObject(LocationStack.Last());

                if (obj == null || !obj.ReturnType.IsSubclassOfOrEqual(s.ReturnType))
                {
                    Log.Error(s.Source, ErrorCode.E0000, "Unable to resolve instance of " + s.ReturnType.Quote() + " in " + Path.Quote());
                }

                var objStage = ProcessValue(obj);
                return(new StageValue(objStage.Value, objStage.MinStage, objStage.MaxStage));
            }

            case ExpressionType.Invalid:
            case ExpressionType.Constant:
            case ExpressionType.Default:
            case ExpressionType.ExternOp:
            case ExpressionType.ExternString:
                return(new StageValue(e, MetaStage.Const));

            case ExpressionType.This:
            case ExpressionType.Base:
            case ExpressionType.TypeOf:
                return(new StageValue(e, MetaStage.ReadOnly, MetaStage.Volatile));

            case ExpressionType.CapturedArgument:
            case ExpressionType.CapturedLocal:
            case ExpressionType.LoadArgument:
                return(new StageValue(e, MetaStage.Volatile, MetaStage.Volatile));

            case ExpressionType.RuntimeConst:
                return(new StageValue(e, MetaStage.Vertex, MetaStage.Pixel));

            case ExpressionType.LoadUniform:
                return(new StageValue(e, MetaStage.Vertex, MetaStage.Pixel));

            case ExpressionType.LoadVarying:
                return(new StageValue(e, MetaStage.Pixel, MetaStage.Pixel));

            case ExpressionType.LoadVertexAttrib:
                return(new StageValue(e, MetaStage.Vertex, MetaStage.Vertex));

            case ExpressionType.FixOp:
            {
                var s  = e as FixOp;
                var ps = ProcessValue(s.Operand);
                return(new StageValue(new FixOp(s.Source, s.Operator, ps.Value), ps.MinStage, ps.MaxStage));
            }

            case ExpressionType.AddressOf:
            {
                var s  = e as AddressOf;
                var ps = ProcessValue(s.Operand);
                return(new StageValue(new AddressOf(ps.Value, s.AddressType), ps.MinStage, ps.MaxStage));
            }

            case ExpressionType.BranchOp:
            {
                var s = e as BranchOp;

                Expression left, right;
                MetaStage  minStage, maxStage;
                ProcessValues(out minStage, out maxStage, s.Left, out left, s.Right, out right);

                return(new StageValue(new BranchOp(s.Source, s.ReturnType, s.BranchType, left, right), minStage, maxStage));
            }

            case ExpressionType.ReferenceOp:
            {
                var s = e as ReferenceOp;

                Expression left, right;
                MetaStage  minStage, maxStage;
                ProcessValues(out minStage, out maxStage, s.Left, out left, s.Right, out right);

                return(new StageValue(new ReferenceOp(s.Source, s.ReturnType, s.EqualityType, left, right), minStage, maxStage));
            }

            case ExpressionType.SequenceOp:
            {
                var s = e as SequenceOp;

                Expression left, right;
                MetaStage  minStage, maxStage;
                ProcessValues(out minStage, out maxStage, s.Left, out left, s.Right, out right);

                return(new StageValue(new SequenceOp(left, right), minStage, maxStage));
            }

            case ExpressionType.ConditionalOp:
            {
                var s  = e as ConditionalOp;
                var ps = ProcessValue(s.Condition);

                Expression a, b;
                MetaStage  minStage, maxStage;
                ProcessValues(ref ps, out minStage, out maxStage, s.True, out a, s.False, out b);

                return(new StageValue(new ConditionalOp(s.Source, ps.Value, a, b), minStage, maxStage));
            }

            case ExpressionType.NullOp:
            {
                var s  = e as NullOp;
                var ps = StageValue.Default;

                if (ps.MaxStage > MetaStage.Volatile)
                {
                    ps.MaxStage = MetaStage.Volatile;
                }

                Expression left, right;
                MetaStage  minStage, maxStage;
                ProcessValues(ref ps, out minStage, out maxStage, s.Left, out left, s.Right, out right);

                return(new StageValue(new NullOp(s.Source, left, right), minStage, maxStage));
            }

            case ExpressionType.IsOp:
            {
                var s  = e as IsOp;
                var ps = ProcessValue(s.Operand);

                if (ps.MaxStage > MetaStage.Volatile)
                {
                    ps.MaxStage = MetaStage.Volatile;
                }

                return(new StageValue(new IsOp(s.Source, ps.Value, s.TestType, s.ReturnType), ps.MinStage, ps.MaxStage));
            }

            case ExpressionType.AsOp:
            {
                var s  = e as AsOp;
                var ps = ProcessValue(s.Operand);

                if (ps.MaxStage > MetaStage.Volatile)
                {
                    ps.MaxStage = MetaStage.Volatile;
                }

                return(new StageValue(new AsOp(s.Source, ps.Value, s.ReturnType), ps.MinStage, ps.MaxStage));
            }

            case ExpressionType.LoadField:
            {
                var s  = e as LoadField;
                var ps = ProcessValue(s.Object);
                AdjustInstanceStageRange(ref ps, s.Field.DeclaringType, true);

                return(new StageValue(new LoadField(s.Source, ps.Value, s.Field), ps.MinStage, ps.MaxStage));
            }

            case ExpressionType.LoadElement:
            {
                var s  = e as LoadElement;
                var ps = ProcessValue(s.Array);

                Expression index;
                MetaStage  minStage, maxStage;
                ProcessValues(ref ps, out minStage, out maxStage, s.Index, out index);

                return(new StageValue(new LoadElement(s.Source, ps.Value, index), minStage, maxStage));
            }

            case ExpressionType.Swizzle:
            {
                var s  = e as Swizzle;
                var ps = ProcessValue(s.Object);
                AdjustInstanceStageRange(ref ps, s.Object.ReturnType, true);

                return(new StageValue(new Swizzle(s.Source, s.Constructor, ps.Value, s.Fields), ps.MinStage, ps.MaxStage));
            }

            case ExpressionType.GetProperty:
            {
                var s  = e as GetProperty;
                var ps = ProcessValue(s.Object);
                AdjustInstanceStageRange(ref ps, s.Property.DeclaringType, true);
                AdjustFunctionStageRange(ref ps, s.Property.GetMethod);

                MetaStage minStage, maxStage;
                var       args = ProcessValues(ref ps, out minStage, out maxStage, s.Arguments);

                return(new StageValue(new GetProperty(s.Source, ps.Value, s.Property, args), minStage, maxStage));
            }

            case ExpressionType.NewObject:
            {
                var s = e as NewObject;

                var ps = new StageValue(null, MetaStage.ReadOnly,
                                        s.ReturnType.IsReferenceType ? MetaStage.Volatile : MetaStage.Max);

                AdjustFunctionStageRange(ref ps, s.Constructor);

                MetaStage minStage, maxStage;
                var       args = ProcessValues(ref ps, out minStage, out maxStage, s.Arguments);

                return(new StageValue(new NewObject(s.Source, s.Constructor, args), minStage, maxStage));
            }

            case ExpressionType.NewArray:
            {
                var s = e as NewArray;

                var ps = new StageValue(null, MetaStage.ReadOnly,
                                        s.ArrayType.ElementType.IsReferenceType ? MetaStage.Volatile : MetaStage.Max);

                if (s.Size == null)
                {
                    MetaStage minStage, maxStage;
                    var       initializers = ProcessValues(ref ps, out minStage, out maxStage, s.Initializers);
                    return(new StageValue(new NewArray(s.Source, (RefArrayType)s.ReturnType, initializers), minStage, maxStage));
                }
                else
                {
                    Expression size;
                    MetaStage  minStage, maxStage;
                    ProcessValues(ref ps, out minStage, out maxStage, s.Size, out size);
                    return(new StageValue(new NewArray(s.Source, (RefArrayType)s.ReturnType, size), minStage, maxStage));
                }
            }

            case ExpressionType.CallMethod:
            {
                var s  = e as CallMethod;
                var ps = ProcessValue(s.Object);
                AdjustInstanceStageRange(ref ps, s.Method.DeclaringType, false);
                AdjustFunctionStageRange(ref ps, s.Method);

                MetaStage minStage, maxStage;
                var       args = ProcessValues(ref ps, out minStage, out maxStage, s.Arguments);

                return(new StageValue(new CallMethod(s.Source, ps.Value, s.Method, args), minStage, maxStage));
            }

            case ExpressionType.CallCast:
            {
                var s  = e as CallCast;
                var ps = ProcessValue(s.Operand);
                AdjustFunctionStageRange(ref ps, s.Cast);

                return(new StageValue(new CallCast(s.Source, s.Cast, ps.Value), ps.MinStage, ps.MaxStage));
            }

            case ExpressionType.CallBinOp:
            {
                var s  = e as CallBinOp;
                var ps = StageValue.Default;
                AdjustFunctionStageRange(ref ps, s.Operator);

                Expression left, right;
                MetaStage  minStage, maxStage;
                ProcessValues(ref ps, out minStage, out maxStage, s.Left, out left, s.Right, out right);

                return(new StageValue(new CallBinOp(s.Source, s.Operator, left, right), minStage, maxStage));
            }

            case ExpressionType.CallUnOp:
            {
                var s  = e as CallUnOp;
                var ps = ProcessValue(s.Operand);
                AdjustFunctionStageRange(ref ps, s.Operator);

                return(new StageValue(new CallUnOp(s.Source, s.Operator, ps.Value), ps.MinStage, ps.MaxStage));
            }

            case ExpressionType.CastOp:
            {
                var s  = e as CastOp;
                var ps = ProcessValue(s.Operand);

                if (ps.MaxStage > MetaStage.Volatile)
                {
                    ps.MaxStage = MetaStage.Volatile;
                }

                return(new StageValue(new CastOp(s.Source, s.ReturnType, ps.Value), ps.MinStage, ps.MaxStage));
            }

            case ExpressionType.StoreElement:
            case ExpressionType.StoreField:
            case ExpressionType.StoreArgument:
            case ExpressionType.StoreLocal:
            case ExpressionType.SetProperty:
                Log.Error(e.Source, ErrorCode.E5021, "Not allowed to use assign operators inside meta property definitions");
                return(new StageValue(Expression.Invalid, MetaStage.Const));
            }

            Log.Error(e.Source, ErrorCode.I5022, "<" + e.ExpressionType + "> is not supported by ShaderGenerator");
            return(new StageValue(Expression.Invalid, MetaStage.Const));
        }
Exemplo n.º 14
0
        Expression[] ProcessValues(ref StageValue obj, out MetaStage minStage, out MetaStage maxStage, params Expression[] args)
        {
            switch (args.Length)
            {
            case 0:
                minStage = obj.MinStage;
                maxStage = obj.MaxStage;
                return(new Expression[0]);

            case 1:
            {
                Expression arg;
                ProcessValues(ref obj, out minStage, out maxStage, args[0], out arg);
                return(new[] { arg });
            }

            case 2:
            {
                Expression arg0, arg1;
                ProcessValues(ref obj, out minStage, out maxStage, args[0], out arg0, args[1], out arg1);
                return(new[] { arg0, arg1 });
            }

            default:
            {
                minStage = obj.MinStage;
                maxStage = obj.MaxStage;

                var stageArgs = new StageValue[args.Length];

                for (int i = 0; i < args.Length; i++)
                {
                    stageArgs[i] = ProcessValue(args[i]);

                    if (stageArgs[i].MinStage > minStage)
                    {
                        minStage = stageArgs[i].MinStage;
                    }

                    if (stageArgs[i].MaxStage < maxStage)
                    {
                        maxStage = stageArgs[i].MaxStage;
                    }
                }

                if (maxStage < minStage)
                {
                    maxStage = minStage;
                }

                var result = new Expression[args.Length];

                for (int i = 0; i < args.Length; i++)
                {
                    result[i] = ProcessStage(stageArgs[i], minStage, maxStage).Value;
                }

                obj = ProcessStage(obj, minStage, maxStage);

                return(result);
            }
            }
        }