2
0
Эх сурвалжийг харах

params, globals, and tex2d variable tracking ok, ready to integrate

Nicolas Cannasse 11 жил өмнө
parent
commit
c1ded6db0a
7 өөрчлөгдсөн 193 нэмэгдсэн , 40 устгасан
  1. 107 5
      hxsl/Cache.hx
  2. 1 1
      hxsl/Eval.hx
  3. 33 3
      hxsl/Flatten.hx
  4. 6 24
      hxsl/Linker.hx
  5. 42 5
      hxsl/SharedShader.hx
  6. 2 0
      hxsl/Splitter.hx
  7. 2 2
      test/Test.hx

+ 107 - 5
hxsl/Cache.hx

@@ -1,8 +1,43 @@
 package hxsl;
 using hxsl.Ast;
 
+class AllocParam {
+	public var pos : Int;
+	public var instance : Int;
+	public var index : Int;
+	public var perObjectGlobal : AllocGlobal;
+	public function new(pos, instance, index) {
+		this.pos = pos;
+		this.instance = instance;
+		this.index = index;
+	}
+}
+
+class AllocGlobal {
+	public var pos : Int;
+	public var gid : Int;
+	public var path : String;
+	public function new(pos, path) {
+		this.pos = pos;
+		this.path = path;
+		this.gid = Globals.allocID(path);
+	}
+}
+
+class CompleteShader {
+	public var data : ShaderData;
+	public var params : Array<AllocParam>;
+	public var paramsSize : Int;
+	public var globals : Array<AllocGlobal>;
+	public var globalsSize : Int;
+	public var paramsTexture : Array<AllocParam>;
+	public var globalsTexture : Array<AllocGlobal>;
+	public function new() {
+	}
+}
+
 class SearchMap {
-	public var linked : { vertex : ShaderData, fragment : ShaderData };
+	public var linked : { vertex : CompleteShader, fragment : CompleteShader };
 	public var next : Map<Int,SearchMap>;
 	public function new() {
 	}
@@ -56,15 +91,82 @@ class Cache {
 		if( c.linked != null )
 			return c.linked;
 			
-		var s = new hxsl.Linker().link([for( s in instances ) s.shader], this.outVars[outVars]);
+		var linker = new hxsl.Linker();
+		var s = linker.link([for( s in instances ) s.shader], this.outVars[outVars]);
+		
+		// params tracking
+		var paramVars = new Map();
+		for( v in linker.allVars )
+			if( v.v.kind == Param ) {
+				switch( v.v.type ) {
+				case TStruct(_): continue;
+				default:
+				}
+				var i = instances[v.instanceIndex];
+				paramVars.set(v.id, { instance : v.instanceIndex, index : i.params.get(v.merged[0].id) } );
+			}
 		
 		var s = new hxsl.Splitter().split(s);
-		s.vertex = new Flatten().flatten(s.vertex, Vertex);
-		s.fragment = new Flatten().flatten(s.fragment, Fragment);
-		c.linked = s;
+		c.linked = {
+			vertex : flattenShader(s.vertex, Vertex, paramVars),
+			fragment : flattenShader(s.fragment, Fragment, paramVars),
+		};
 		return c.linked;
 	}
 	
+	function getPath( v : TVar ) {
+		if( v.parent == null )
+			return v.name;
+		return getPath(v.parent) + "." + v.name;
+	}
+	
+	function flattenShader( s : ShaderData, kind : FunctionKind, params : Map < Int, { instance:Int, index:Int } > ) {
+		var flat = new Flatten();
+		var c = new CompleteShader();
+		var data = flat.flatten(s, kind);
+		for( g in flat.allocData.keys() ) {
+			var alloc = flat.allocData.get(g);
+			switch( g.kind ) {
+			case Param:
+				var out = [];
+				for( a in alloc ) {
+					if( a.v == null ) continue; // padding
+					var p = params.get(a.v.id);
+					if( p == null ) {
+						var ap = new AllocParam(a.pos, -1, -1);
+						ap.perObjectGlobal = new AllocGlobal( -1, getPath(a.v));
+						out.push(ap);
+						continue;
+					}
+					out.push(new AllocParam(a.pos, p.instance, p.index));
+				}
+				switch( g.type ) {
+				case TArray(TSampler2D, _):
+					c.paramsTexture = out;
+				case TArray(TVec(4, VFloat),SConst(size)):
+					c.params = out;
+					c.paramsSize = size;
+				default: throw "assert";
+				}
+			case Global:
+				var out = [for( a in alloc ) if( a.v != null ) new AllocGlobal(a.pos, getPath(a.v))];
+				switch( g.type ) {
+				case TArray(TSampler2D, _):
+					c.globalsTexture = out;
+				case TArray(TVec(4, VFloat),SConst(size)):
+					c.globals = out;
+					c.globalsSize = size;
+				default:
+					throw "assert";
+				}
+			default: throw "assert";
+			}
+		}
+		trace(c);
+		c.data = data;
+		return c;
+	}
+	
 	static var INST : Cache;
 	public static function get() : Cache {
 		var c = INST;

+ 1 - 1
hxsl/Eval.hx

@@ -8,8 +8,8 @@ using hxsl.Ast;
 **/
 class Eval {
 	
+	public var varMap : Map<TVar,TVar>;
 	var constants : Map<TVar,TExprDef>;
-	var varMap : Map<TVar,TVar>;
 	var funMap : Map<TVar,TFunction>;
 	
 	public function new() {

+ 33 - 3
hxsl/Flatten.hx

@@ -21,6 +21,7 @@ class Flatten {
 	var params : Array<TVar>;
 	var outVars : Array<TVar>;
 	var varMap : Map<TVar,Alloc>;
+	public var allocData : Map< TVar, Array<Alloc> >;
 	
 	public function new() {
 	}
@@ -30,6 +31,7 @@ class Flatten {
 		params = [];
 		outVars = [];
 		varMap = new Map();
+		allocData = new Map();
 		for( v in s.vars )
 			gatherVar(v);
 		var prefix = switch( kind ) {
@@ -38,7 +40,9 @@ class Flatten {
 		default: throw "assert";
 		}
 		pack(prefix+"Globals", Global, globals, VFloat);
-		pack(prefix+"Params", Param, params, VFloat);
+		pack(prefix + "Params", Param, params, VFloat);
+		packTextures(prefix + "GTextures", Global, globals, TSampler2D);
+		packTextures(prefix + "PTextures", Param, params, TSampler2D);
 		return {
 			name : s.name,
 			vars : outVars,
@@ -90,6 +94,8 @@ class Flatten {
 		case TArray(t, SConst(len)):
 			var stride = Std.int(a.size / len);
 			return { e : TArrayDecl([for( i in 0...len ) access(new Alloc(a.g, a.t, a.pos + stride * i, stride), t, pos)]), t : t, p : pos };
+		case TSampler2D, TSamplerCube:
+			return read(a.pos);
 		default:
 			var size = varSize(t, a.t);
 			if( size <= 4 ) {
@@ -132,6 +138,29 @@ class Flatten {
 		return e;
 	}
 	
+	function packTextures( name : String, kind : VarKind, vars : Array<TVar>, t : Type ) {
+		var alloc = new Array<Alloc>();
+		var g : TVar = {
+			id : Tools.allocVarId(),
+			name : name,
+			type : t,
+			kind : kind,
+		};
+		for( v in vars ) {
+			if( v.type != t ) continue;
+			var a = new Alloc(g, null, alloc.length, 1);
+			a.v = v;
+			varMap.set(v, a);
+			alloc.push(a);
+		}
+		g.type = TArray(t, SConst(alloc.length));
+		if( alloc.length > 0 ) {
+			outVars.push(g);
+			allocData.set(g, alloc);
+		}
+		return g;
+	}
+	
 	function pack( name : String, kind : VarKind, vars : Array<TVar>, t : VecType ) {
 		var alloc = new Array<Alloc>(), apos = 0;
 		var g : TVar = {
@@ -143,7 +172,6 @@ class Flatten {
 		for( v in vars ) {
 			switch( v.type ) {
 			case TSampler2D, TSamplerCube:
-				outVars.push(v);
 				continue;
 			default:
 			}
@@ -177,8 +205,10 @@ class Flatten {
 			}
 		}
 		g.type = TArray(TVec(4, t), SConst(apos >> 2));
-		if( vars.length > 0 )
+		if( vars.length > 0 ) {
 			outVars.push(g);
+			allocData.set(g, alloc);
+		}
 		return g;
 	}
 	

+ 6 - 24
hxsl/Linker.hx

@@ -8,6 +8,7 @@ private class AllocatedVar {
 	public var merged : Array<TVar>;
 	public var kind : Null<FunctionKind>;
 	public var parent : AllocatedVar;
+	public var instanceIndex : Int;
 	public function new() {
 	}
 }
@@ -36,12 +37,13 @@ private class ShaderInfos {
 
 class Linker {
 
+	public var allVars : Array<AllocatedVar>;
 	var varMap : Map<String,AllocatedVar>;
-	var allVars : Array<AllocatedVar>;
 	var curShader : ShaderInfos;
 	var shaders : Array<ShaderInfos>;
 	var varIdMap : Map<Int,Int>;
 	var locals : Map<Int,Bool>;
+	var curInstance : Int;
 	
 	public function new() {
 	}
@@ -139,6 +141,7 @@ class Linker {
 		a.path = key;
 		a.id = vid;
 		a.parent = parent == null ? null : allocVar(parent, p);
+		a.instanceIndex = curInstance;
 		allVars.push(a);
 		varMap.set(key, a);
 		switch( v2.type ) {
@@ -149,29 +152,6 @@ class Linker {
 		return a;
 	}
 	
-	/*
-	function allocFun( f : TFunction ) : TFunction {
-		var f2 = funMap.get(f.ref.name);
-		if( f2 != null ) {
-			if( f2.fold == f )
-				return f2.fnew;
-			// generate unique name
-			var k = 2;
-			while( funMap.exists(f.ref.name + k) )
-				k++;
-			f.ref.name = f.ref.name + k;
-		}
-		var f2 : TFunction = {
-			ref : allocVar(f.ref, null, null, f.expr.p).v,
-			args : f.args, // no-op
-			ret : f.ret,
-			expr : mapExprVar(f.expr),
-		};
-		funMap.set(f2.ref.name, { fold : f, fnew : f2 });
-		return f2;
-	}
-	*/
-	
 	function mapExprVar( e : TExpr ) {
 		switch( e.e ) {
 		case TVar(v) if( !locals.exists(v.id) ):
@@ -261,6 +241,7 @@ class Linker {
 		locals = new Map();
 		
 		// globalize vars
+		curInstance = 0;
 		for( s in shadersData ) {
 			for( v in s.vars )
 				allocVar(v, null);
@@ -268,6 +249,7 @@ class Linker {
 				var v = allocVar(f.ref, f.expr.p);
 				v.kind = f.kind;
 			}
+			curInstance++;
 		}
 		
 		// create shader segments

+ 42 - 5
hxsl/SharedShader.hx

@@ -4,9 +4,11 @@ using hxsl.Ast;
 class ShaderInstance {
 	public var id : Int;
 	public var shader : ShaderData;
+	public var params : Map<Int,Int>;
 	public function new(shader) {
 		id = Tools.allocVarId();
 		this.shader = shader;
+		params = new Map();
 	}
 }
 
@@ -37,6 +39,7 @@ class SharedShader {
 	public var globals : Array<ShaderGlobal>;
 	public var consts : Array<ShaderConst>;
 	var instanceCache : Map<Int,ShaderInstance>;
+	var paramsCount : Int;
 	
 	public function new(src:String) {
 		instanceCache = new Map();
@@ -45,25 +48,59 @@ class SharedShader {
 		globals = [];
 		for( v in data.vars )
 			browseVar(v);
-		if( consts.length == 0 )
-			instanceCache.set(0, new ShaderInstance(data));
+		if( consts.length == 0 ) {
+			var i = new ShaderInstance(data);
+			paramsCount = 0;
+			for( v in data.vars )
+				addSelfParam(i, v);
+			instanceCache.set(0, i);
+		}
 	}
 	
 	public function getInstance( constBits : Int ) {
 		var i = instanceCache.get(constBits);
 		if( i != null )
 			return i;
-		var e = new hxsl.Eval();
+		var eval = new hxsl.Eval();
 		for( c in consts )
-			e.setConstant(c.v, switch( c.v.type ) {
+			eval.setConstant(c.v, switch( c.v.type ) {
 			case TBool: CBool((constBits >>> c.pos) & 1 != 0);
 			case TInt: CInt((constBits >>> c.pos) & ((1 << c.bits) - 1));
 			default: throw "assert";
 			});
-		i = new ShaderInstance(e.eval(data));
+		i = new ShaderInstance(eval.eval(data));
+		paramsCount = 0;
+		for( v in data.vars )
+			addParam(eval, i, v);
 		instanceCache.set(constBits, i);
 		return i;
 	}
+
+	function addSelfParam( i : ShaderInstance, v : TVar ) {
+		switch( v.type ) {
+		case TStruct(vl):
+			for( v in vl )
+				addSelfParam(i, v);
+		default:
+			if( v.kind == Param ) {
+				i.params.set( v.id,  paramsCount );
+				paramsCount++;
+			}
+		}
+	}
+
+	function addParam( eval : Eval, i : ShaderInstance, v : TVar ) {
+		switch( v.type ) {
+		case TStruct(vl):
+			for( v in vl )
+				addParam(eval, i, v);
+		default:
+			if( v.kind == Param ) {
+				i.params.set( eval.varMap.get(v).id,  paramsCount );
+				paramsCount++;
+			}
+		}
+	}
 	
 	function browseVar( v : TVar, ?path : String ) {
 		v.id = Tools.allocVarId();

+ 2 - 0
hxsl/Splitter.hx

@@ -152,6 +152,8 @@ class Splitter {
 	}
 	
 	function uniqueName( v : TVar ) {
+		if( v.kind == Global )
+			return;
 		v.parent = null;
 		var n = varNames.get(v.name);
 		if( n != null && n != v ) {

+ 2 - 2
test/Test.hx

@@ -376,8 +376,8 @@ class Test {
 			return s;
 		}
 			
-		var vs = compile(GL.VERTEX_SHADER, s.vertex);
-		var fs = compile(GL.FRAGMENT_SHADER, s.fragment);
+		var vs = compile(GL.VERTEX_SHADER, s.vertex.data);
+		var fs = compile(GL.FRAGMENT_SHADER, s.fragment.data);
 		
 		var p = gl.createProgram();
 		gl.attachShader(p, vs);