Esempio n. 1
0
        StageValue ProcessVertexAttrib(NewVertexAttrib s)
        {
            var vertexAttributeType = ProcessValue(s.VertexAttributeType);
            var vertexBuffer        = ProcessValue(s.VertexBuffer);
            var vertexOffset        = ProcessValue(s.VertexBufferOffset);
            var vertexStride        = ProcessValue(s.VertexBufferStride);

            var indexType   = ProcessValue(s.OptionalIndexType);
            var indexBuffer = ProcessValue(s.OptionalIndexBuffer);

            var loc  = LocationStack.Last();
            var mp   = GetProperty(loc);
            var name = CreateShaderName(mp, loc);

            int attrIndex = DrawState.VertexAttributes.Count;

            DetectVertexCount(indexBuffer.Value != null
                    ? indexBuffer
                    : vertexBuffer);
            ProcessIndexBuffer(s.Source, indexBuffer, indexType);

            DrawState.VertexAttributes.Add(new VertexAttribute(s.ReturnType, name,
                                                               ProcessStage(vertexAttributeType, MetaStage.Volatile, MetaStage.Volatile).Value,
                                                               ProcessVertexBuffer(vertexBuffer),
                                                               ProcessStage(vertexOffset, MetaStage.Volatile, MetaStage.Volatile).Value,
                                                               ProcessStage(vertexStride, MetaStage.Volatile, MetaStage.Volatile).Value));

            return(new StageValue(new LoadVertexAttrib(s.Source, DrawState, attrIndex), MetaStage.Vertex, MetaStage.Vertex));
        }
Esempio 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);
        }
Esempio n. 3
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);
        }
Esempio n. 4
0
        StageValue ProcessPixelSampler(NewPixelSampler s)
        {
            var texture = ProcessValuesToStage(MetaStage.Volatile, s.Texture);

            int index;

            if (!PixelSamplers.TryGetValue(texture.ToString(), out index))
            {
                var loc = LocationStack.Last();
                var mp  = GetProperty(loc);

                index = DrawState.PixelSamplers.Count;
                DrawState.PixelSamplers.Add(new PixelSampler(GetSamplerType(s.Source, texture.ReturnType), CreateShaderName(mp, loc, texture), texture));
                PixelSamplers.Add(texture.ToString(), index);

                if (s.OptionalState != null)
                {
                    DrawState.PixelSamplers[index].OptionalState = ProcessValuesToStage(MetaStage.Volatile, s.OptionalState);
                }
            }
            else
            {
                var oldState = DrawState.PixelSamplers[index].OptionalState;
                var newState = s.OptionalState != null
                             ? ProcessValuesToStage(MetaStage.Volatile, s.OptionalState)
                             : null;

                if (oldState == null && newState != null ||
                    oldState != null && newState == null ||
                    oldState != null && !oldState.IsInvalid && newState != null && !newState.IsInvalid && oldState.ToString() != newState.ToString())
                {
                    Log.Warning(s.Source, ErrorCode.W0000, "Ignoring sampler state. Texture is already sampled using a different sampler state in " + Path.Quote() + ". Reuse the existing sampler state to remove this warning.");
                }
            }

            return(new StageValue(new LoadPixelSampler(s.Source, DrawState, index), MetaStage.Pixel, MetaStage.Pixel));
        }
Esempio n. 5
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"));
        }
Esempio n. 6
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));
        }