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)); }
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); }
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); }
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)); }
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")); }
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)); }