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