Sfoglia il codice sorgente

added support for mesh batch to shader cache files

Nicolas Cannasse 6 anni fa
parent
commit
21547d6f60
3 ha cambiato i file con 75 aggiunte e 8 eliminazioni
  1. 1 0
      hxsl/Cache.hx
  2. 73 8
      hxsl/CacheFile.hx
  3. 1 0
      hxsl/RuntimeShader.hx

+ 1 - 0
hxsl/Cache.hx

@@ -291,6 +291,7 @@ class Cache {
 		var signParts = [for( i in r.spec.instances ) i.shader.data.name+"_" + i.bits + "_" + i.index];
 		var signParts = [for( i in r.spec.instances ) i.shader.data.name+"_" + i.bits + "_" + i.index];
 		r.spec.signature = haxe.crypto.Md5.encode(signParts.join(":"));
 		r.spec.signature = haxe.crypto.Md5.encode(signParts.join(":"));
 		r.signature = haxe.crypto.Md5.encode(Printer.shaderToString(r.vertex.data) + Printer.shaderToString(r.fragment.data));
 		r.signature = haxe.crypto.Md5.encode(Printer.shaderToString(r.vertex.data) + Printer.shaderToString(r.fragment.data));
+		r.batchMode = batchMode;
 
 
 		var r2 = byID.get(r.signature);
 		var r2 = byID.get(r.signature);
 		if( r2 != null )
 		if( r2 != null )

+ 73 - 8
hxsl/CacheFile.hx

@@ -31,6 +31,7 @@ class CacheFile extends Cache {
 	var shaders : Map<String,{ shader : SharedShader, version : String }> = new Map();
 	var shaders : Map<String,{ shader : SharedShader, version : String }> = new Map();
 	var runtimeShaders : Array<RuntimeShader> = [];
 	var runtimeShaders : Array<RuntimeShader> = [];
 	var linkers : Array<{ shader : Shader, vars : Array<hxsl.Output> }> = [];
 	var linkers : Array<{ shader : Shader, vars : Array<hxsl.Output> }> = [];
+	var batchers : Array<{ shader : SharedShader, rt : RuntimeShader }> = [];
 
 
 	// sources
 	// sources
 	var compiledSources : Map<String,{ vertex : String, fragment : String }> = new Map();
 	var compiledSources : Map<String,{ vertex : String, fragment : String }> = new Map();
@@ -69,6 +70,12 @@ class CacheFile extends Cache {
 		return shader;
 		return shader;
 	}
 	}
 
 
+	override function createBatchShader( rt ) {
+		var b = super.createBatchShader(rt);
+		batchers.push({ rt : rt, shader : b });
+		return b;
+	}
+
 	static var HEX = "0123456789abcdef";
 	static var HEX = "0123456789abcdef";
 
 
 	function load() {
 	function load() {
@@ -97,7 +104,7 @@ class CacheFile extends Cache {
 		} else if( !allowCompile )
 		} else if( !allowCompile )
 			throw "Missing " + file;
 			throw "Missing " + file;
 		if( linkCache.linked == null ) {
 		if( linkCache.linked == null ) {
-			var rt = link(makeDefaultShader());
+			var rt = link(makeDefaultShader(), false);
 			linkCache.linked = rt;
 			linkCache.linked = rt;
 			if( rt.vertex.code == null || rt.fragment.code == null ) {
 			if( rt.vertex.code == null || rt.fragment.code == null ) {
 				if( !allowCompile ) throw "Missing default shader code";
 				if( !allowCompile ) throw "Missing default shader code";
@@ -173,6 +180,16 @@ class CacheFile extends Cache {
 			linkMap.set(name, shader);
 			linkMap.set(name, shader);
 		}
 		}
 
 
+		batchers = [];
+		var batchMap = new Map();
+		while( true ) {
+			skip();
+			var name = readString();
+			if( name == null ) break;
+			var rt = readString();
+			batchMap.set(name, rt);
+		}
+
 		shaders = new Map();
 		shaders = new Map();
 		while( true ) {
 		while( true ) {
 			skip();
 			skip();
@@ -207,8 +224,12 @@ class CacheFile extends Cache {
 			var inst = [for( i in 0...f.readByte() ) {
 			var inst = [for( i in 0...f.readByte() ) {
 				var name = readString();
 				var name = readString();
 				var shader = shaders.get(name);
 				var shader = shaders.get(name);
-				if( shader == null ) missingShader = true;
-				{ shader : shader, bits : readIntHex(), index : f.readByte() };
+				var batch = null;
+				if( shader == null ) {
+					batch = batchMap.get(name);
+					if( batch == null ) missingShader = true;
+				}
+				{ shader : shader, batch : batch, bits : readIntHex(), index : f.readByte() };
 			}];
 			}];
 			var sign = readString();
 			var sign = readString();
 			if( missingShader ) continue;
 			if( missingShader ) continue;
@@ -219,14 +240,26 @@ class CacheFile extends Cache {
 
 
 		// recompile or load runtime shaders
 		// recompile or load runtime shaders
 		runtimeShaders = [];
 		runtimeShaders = [];
+		var rttMap = new Map<String,RuntimeShader>();
 		if( recompileRT ) {
 		if( recompileRT ) {
 
 
 			for( r in runtimes ) {
 			for( r in runtimes ) {
 				var shaderList = null;
 				var shaderList = null;
+				var batchMode = false;
 				r.inst.reverse();
 				r.inst.reverse();
 				for( i in r.inst ) {
 				for( i in r.inst ) {
 					var s = Type.createEmptyInstance(hxsl.Shader);
 					var s = Type.createEmptyInstance(hxsl.Shader);
 					@:privateAccess {
 					@:privateAccess {
+						if( i.shader == null ) {
+							var rt = rttMap.get(i.batch);
+							if( rt == null ) {
+								r = null; // was modified
+								break;
+							}
+							var sh = makeBatchShader(rt);
+							i.shader = { version : null, shader : sh.shader };
+							batchMode = true;
+						}
 						s.constBits = i.bits;
 						s.constBits = i.bits;
 						s.shader = i.shader.shader;
 						s.shader = i.shader.shader;
 						s.instance = i.shader.shader.getInstance(i.bits);
 						s.instance = i.shader.shader.getInstance(i.bits);
@@ -234,10 +267,12 @@ class CacheFile extends Cache {
 					}
 					}
 					shaderList = new hxsl.ShaderList(s, shaderList);
 					shaderList = new hxsl.ShaderList(s, shaderList);
 				}
 				}
-				var rt = link(shaderList); // will compile + update linkMap
+				if( r == null ) continue;
+				var rt = link(shaderList, batchMode); // will compile + update linkMap
 				if( rt.spec.signature != r.specSign )
 				if( rt.spec.signature != r.specSign )
 					throw "assert";
 					throw "assert";
 				runtimeShaders.push(rt);
 				runtimeShaders.push(rt);
+				rttMap.set(r.specSign, rt);
 			}
 			}
 
 
 		} else {
 		} else {
@@ -262,6 +297,16 @@ class CacheFile extends Cache {
 				for( i in spec.inst ) {
 				for( i in spec.inst ) {
 					var s = Type.createEmptyInstance(hxsl.Shader);
 					var s = Type.createEmptyInstance(hxsl.Shader);
 					@:privateAccess {
 					@:privateAccess {
+						if( i.shader == null ) {
+							var rt = rttMap.get(i.batch);
+							if( rt == null ) {
+								r = null; // was modified
+								break;
+							}
+							var sh = makeBatchShader(rt);
+							i.shader = { version : null, shader : sh.shader };
+							r.batchMode = true;
+						}
 						// pseudo instance
 						// pseudo instance
 						var scache = i.shader.shader.instanceCache;
 						var scache = i.shader.shader.instanceCache;
 						var inst = scache.get(i.bits);
 						var inst = scache.get(i.bits);
@@ -276,9 +321,11 @@ class CacheFile extends Cache {
 					}
 					}
 					shaderList = new hxsl.ShaderList(s, shaderList);
 					shaderList = new hxsl.ShaderList(s, shaderList);
 				}
 				}
+				if( r == null ) continue;
 				addToCache(r, shaderList);
 				addToCache(r, shaderList);
 				reviveRuntime(r);
 				reviveRuntime(r);
 				runtimeShaders.push(r);
 				runtimeShaders.push(r);
+				rttMap.set(spec.specSign, r);
 			}
 			}
 
 
 		}
 		}
@@ -411,6 +458,16 @@ class CacheFile extends Cache {
 		separator();
 		separator();
 		writeString(null);
 		writeString(null);
 
 
+		// batchers
+		batchers.sort(function(l1, l2) return @:privateAccess Reflect.compare(l1.shader.data.name,l2.shader.data.name));
+		for( b in batchers ) {
+			separator();
+			writeString(@:privateAccess b.shader.data.name);
+			writeString(@:privateAccess b.rt.spec.signature);
+		}
+		separator();
+		writeString(null);
+
 		// shaders
 		// shaders
 		var shaders = [for( s in shaders ) s];
 		var shaders = [for( s in shaders ) s];
 		shaders.sort(function(s1, s2) return Reflect.compare(s1.version, s2.version));
 		shaders.sort(function(s1, s2) return Reflect.compare(s1.version, s2.version));
@@ -514,12 +571,15 @@ class CacheFile extends Cache {
 		rc.paramsSize = r.paramsSize;
 		rc.paramsSize = r.paramsSize;
 		rc.globalsSize = r.globalsSize;
 		rc.globalsSize = r.globalsSize;
 		rc.texturesCount = r.texturesCount;
 		rc.texturesCount = r.texturesCount;
+		rc.bufferCount = r.bufferCount;
 		if( r.params != null )
 		if( r.params != null )
 			rc.params = r.params.clone(true);
 			rc.params = r.params.clone(true);
 		if( r.globals != null )
 		if( r.globals != null )
 			rc.globals = r.globals.clone(true);
 			rc.globals = r.globals.clone(true);
 		if( r.textures != null )
 		if( r.textures != null )
 			rc.textures = r.textures.clone(true);
 			rc.textures = r.textures.clone(true);
+		if( r.buffers != null )
+			rc.buffers = r.buffers.clone(true);
 		return rc;
 		return rc;
 	}
 	}
 
 
@@ -547,11 +607,14 @@ class CacheFile extends Cache {
 		}
 		}
 		rvParam(rd.params);
 		rvParam(rd.params);
 		rvParam(rd.textures);
 		rvParam(rd.textures);
+		rvParam(rd.buffers);
 		rvGlobal(rd.globals);
 		rvGlobal(rd.globals);
 		initGlobals(r, rd);
 		initGlobals(r, rd);
 	}
 	}
 
 
 	function sortBySpec( r1 : RuntimeShader, r2 : RuntimeShader ) {
 	function sortBySpec( r1 : RuntimeShader, r2 : RuntimeShader ) {
+		if( r1.batchMode != r2.batchMode )
+			return r1.batchMode ? 1 : -1;
 		var minLen = hxd.Math.imin(r1.spec.instances.length, r2.spec.instances.length);
 		var minLen = hxd.Math.imin(r1.spec.instances.length, r2.spec.instances.length);
 		for( i in 0...minLen ) {
 		for( i in 0...minLen ) {
 			var i1 = r1.spec.instances[i];
 			var i1 = r1.spec.instances[i];
@@ -581,19 +644,19 @@ class CacheFile extends Cache {
 
 
 	public dynamic function onMissingShader(shaders:hxsl.ShaderList) {
 	public dynamic function onMissingShader(shaders:hxsl.ShaderList) {
 		log("Missing shader " + [for( s in shaders ) @:privateAccess s.instance.shader.name+":" + s.priority]);
 		log("Missing shader " + [for( s in shaders ) @:privateAccess s.instance.shader.name+":" + s.priority]);
-		return link(null); // default fallback
+		return link(null, false); // default fallback
 	}
 	}
 
 
 	public dynamic function onNewShader(r:RuntimeShader) {
 	public dynamic function onNewShader(r:RuntimeShader) {
 		log("Compiled " + [for( i in r.spec.instances ) i.shader.data.name+(i.bits == 0 ? "" : ":" + StringTools.hex(i.bits))].join(" "));
 		log("Compiled " + [for( i in r.spec.instances ) i.shader.data.name+(i.bits == 0 ? "" : ":" + StringTools.hex(i.bits))].join(" "));
 	}
 	}
 
 
-	override function compileRuntimeShader(shaders:hxsl.ShaderList) {
+	override function compileRuntimeShader(shaders:hxsl.ShaderList, batchMode) {
 		if( isLoading )
 		if( isLoading )
-			return super.compileRuntimeShader(shaders);
+			return super.compileRuntimeShader(shaders, batchMode);
 		if( allowCompile ) {
 		if( allowCompile ) {
 			// was not found in previous cache, let's compile and cache it
 			// was not found in previous cache, let's compile and cache it
-			var s = super.compileRuntimeShader(shaders);
+			var s = super.compileRuntimeShader(shaders, batchMode);
 			onNewShader(s);
 			onNewShader(s);
 			waitCount++;
 			waitCount++;
 			haxe.Timer.delay(function() addNewShader(s), 0);
 			haxe.Timer.delay(function() addNewShader(s), 0);
@@ -612,6 +675,8 @@ class CacheFile extends Cache {
 		for( i in s.spec.instances ) {
 		for( i in s.spec.instances ) {
 			var inst = shaders.get(i.shader.data.name);
 			var inst = shaders.get(i.shader.data.name);
 			if( inst == null ) {
 			if( inst == null ) {
+				if( s.batchMode && StringTools.startsWith(i.shader.data.name,"batchShader_") )
+					continue;
 				var version = getShaderVersion(i.shader);
 				var version = getShaderVersion(i.shader);
 				inst = { shader : i.shader, version : version };
 				inst = { shader : i.shader, version : version };
 				shaders.set(i.shader.data.name, inst);
 				shaders.set(i.shader.data.name, inst);

+ 1 - 0
hxsl/RuntimeShader.hx

@@ -83,6 +83,7 @@ class RuntimeShader {
 		Several shaders with the different specification might still get the same resulting signature.
 		Several shaders with the different specification might still get the same resulting signature.
 	**/
 	**/
 	public var signature : String;
 	public var signature : String;
+	public var batchMode : Bool;
 	public var spec : { instances : Array<ShaderInstanceDesc>, signature : String };
 	public var spec : { instances : Array<ShaderInstanceDesc>, signature : String };
 
 
 	public function new() {
 	public function new() {