瀏覽代碼

memoize signature for batch forced per instance params

Nicolas Cannasse 2 年之前
父節點
當前提交
44ae459e06
共有 3 個文件被更改,包括 53 次插入30 次删除
  1. 2 2
      h3d/scene/MeshBatch.hx
  2. 40 17
      hxsl/Cache.hx
  3. 11 11
      hxsl/CacheFile.hx

+ 2 - 2
h3d/scene/MeshBatch.hx

@@ -73,7 +73,7 @@ class MeshBatch extends MultiMaterial {
 	**/
 	**/
 	public var calcBounds = true;
 	public var calcBounds = true;
 
 
-	var forcedPerInstance : Array<{ shader : String, params : Array<String> }>;
+	var instancedParams : hxsl.Cache.BatchInstanceParams;
 
 
 	public function new( primitive, ?material, ?parent ) {
 	public function new( primitive, ?material, ?parent ) {
 		instanced = new h3d.prim.Instanced();
 		instanced = new h3d.prim.Instanced();
@@ -122,7 +122,7 @@ class MeshBatch extends MultiMaterial {
 				var manager = cast(ctx,h3d.pass.Default).manager;
 				var manager = cast(ctx,h3d.pass.Default).manager;
 				var shaders = p.getShadersRec();
 				var shaders = p.getShadersRec();
 				var rt = manager.compileShaders(shaders, false);
 				var rt = manager.compileShaders(shaders, false);
-				var shader = manager.shaderCache.makeBatchShader(rt, shaders, forcedPerInstance);
+				var shader = manager.shaderCache.makeBatchShader(rt, shaders, instancedParams);
 
 
 				var b = new BatchData();
 				var b = new BatchData();
 				b.indexCount = matInfo.count;
 				b.indexCount = matInfo.count;

+ 40 - 17
hxsl/Cache.hx

@@ -2,6 +2,26 @@ package hxsl;
 using hxsl.Ast;
 using hxsl.Ast;
 import hxsl.RuntimeShader;
 import hxsl.RuntimeShader;
 
 
+class BatchInstanceParams {
+
+	var forcedPerInstance : Array<{ shader : String, params : Array<String> }>;
+	var cachedSignature : String;
+
+	public function new( forcedPerInstance ) {
+		this.forcedPerInstance = forcedPerInstance;
+	}
+
+	public function getSignature() {
+		if( cachedSignature == null ) {
+			for( fp in forcedPerInstance )
+				fp.params.sort(Reflect.compare);
+			cachedSignature = haxe.crypto.Md5.encode([for( s in forcedPerInstance ) s.shader+"="+s.params.join(",")].join(";")).substr(0,8);
+		}
+		return cachedSignature;
+	}
+
+}
+
 class SearchMap {
 class SearchMap {
 	public var linked : RuntimeShader;
 	public var linked : RuntimeShader;
 	var nexts : Array<SearchMap> = [];
 	var nexts : Array<SearchMap> = [];
@@ -42,8 +62,9 @@ class Cache {
 
 
 	var linkCache : SearchMap;
 	var linkCache : SearchMap;
 	var linkShaders : Map<String, Shader>;
 	var linkShaders : Map<String, Shader>;
-	var batchShaders : Map<RuntimeShader, Map<String,{ shader : SharedShader, params : RuntimeShader.AllocParam, size : Int }>>;
+	var batchShaders : Map<RuntimeShader, { shader : SharedShader, params : RuntimeShader.AllocParam, size : Int }>;
 	var byID : Map<String, RuntimeShader>;
 	var byID : Map<String, RuntimeShader>;
+	var batchShadersParams : Map<String, Map<RuntimeShader, { shader : SharedShader, params : RuntimeShader.AllocParam, size : Int }>>;
 	public var constsToGlobal : Bool;
 	public var constsToGlobal : Bool;
 
 
 	function new() {
 	function new() {
@@ -51,6 +72,7 @@ class Cache {
 		linkCache = new SearchMap();
 		linkCache = new SearchMap();
 		linkShaders = new Map();
 		linkShaders = new Map();
 		batchShaders = new Map();
 		batchShaders = new Map();
+		batchShadersParams = new Map();
 		byID = new Map();
 		byID = new Map();
 	}
 	}
 
 
@@ -486,21 +508,21 @@ class Cache {
 		return c;
 		return c;
 	}
 	}
 
 
-	public function makeBatchShader( rt : RuntimeShader, shaders, forcedPerInstance : Array<{ shader : String, params : Array<String> }> ) : BatchShader {
-		var msh = batchShaders.get(rt); // don't use rt.id to avoid collisions on identical signatures
-		if( msh == null ) {
-			msh = new Map();
-			batchShaders.set(rt, msh);
-		}
-		if( forcedPerInstance != null ) {
-			for( fp in forcedPerInstance )
-				fp.params.sort(Reflect.compare);
+	public function makeBatchShader( rt : RuntimeShader, shaders, params : BatchInstanceParams ) : BatchShader {
+		var batchMap;
+		if( params == null )
+			batchMap = batchShaders;
+		else {
+			batchMap = batchShadersParams.get(params.getSignature());
+			if( batchMap == null ) {
+				batchMap = new Map();
+				batchShadersParams.set(params.getSignature(),batchMap);
+			}
 		}
 		}
-		var sign = forcedPerInstance == null ? "" : haxe.crypto.Md5.encode([for( s in forcedPerInstance ) s.shader+"="+s.params.join(",")].join(";")).substr(0,8);
-		var sh = msh.get(sign);
+		var sh = batchMap.get(rt); // don't use rt.id to avoid collisions on identical signatures
 		if( sh == null ) {
 		if( sh == null ) {
-			sh = createBatchShader(rt, shaders, forcedPerInstance, forcedPerInstance == null ? null : sign);
-			msh.set(sign,sh);
+			sh = createBatchShader(rt, shaders, params);
+			batchMap.set(rt,  sh);
 		}
 		}
 		var shader = std.Type.createEmptyInstance(BatchShader);
 		var shader = std.Type.createEmptyInstance(BatchShader);
 		@:privateAccess shader.shader = sh.shader;
 		@:privateAccess shader.shader = sh.shader;
@@ -518,9 +540,9 @@ class Cache {
 		return false;
 		return false;
 	}
 	}
 
 
-	function createBatchShader( rt : RuntimeShader, shaders : hxsl.ShaderList, forcedPerInstance : Array<{ shader : String, params : Array<String> }>, extraSign : String ) : { shader : SharedShader, params : RuntimeShader.AllocParam, size : Int } {
+	function createBatchShader( rt : RuntimeShader, shaders : hxsl.ShaderList, params : BatchInstanceParams ) : { shader : SharedShader, params : RuntimeShader.AllocParam, size : Int } {
 		var s = new hxsl.SharedShader("");
 		var s = new hxsl.SharedShader("");
-		var id = (extraSign == null ? rt.spec.signature : haxe.crypto.Md5.encode(rt.spec.signature + extraSign)).substr(0, 8);
+		var id = (params == null ? rt.spec.signature : haxe.crypto.Md5.encode(rt.spec.signature + params.getSignature())).substr(0, 8);
 
 
 		function declVar( name, t, kind ) : TVar {
 		function declVar( name, t, kind ) : TVar {
 			return {
 			return {
@@ -532,7 +554,8 @@ class Cache {
 		}
 		}
 
 
 		var instancedParams = [];
 		var instancedParams = [];
-		if( forcedPerInstance != null ) {
+		if( params != null ) {
+			var forcedPerInstance = @:privateAccess params.forcedPerInstance;
 			var instanceIndex = 1;
 			var instanceIndex = 1;
 			var forcedIndex = forcedPerInstance.length - 1;
 			var forcedIndex = forcedPerInstance.length - 1;
 			var s = shaders;
 			var s = shaders;

+ 11 - 11
hxsl/CacheFile.hx

@@ -31,7 +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, instance : Array<{shader:String,params:Array<String>}> }> = [];
+	var batchers : Array<{ shader : SharedShader, rt : RuntimeShader, params : hxsl.Cache.BatchInstanceParams }> = [];
 
 
 	// sources
 	// sources
 	var compiledSources : Map<String,{ vertex : String, fragment : String }> = new Map();
 	var compiledSources : Map<String,{ vertex : String, fragment : String }> = new Map();
@@ -69,9 +69,9 @@ class CacheFile extends Cache {
 		return shader;
 		return shader;
 	}
 	}
 
 
-	override function createBatchShader( rt, shaders, perInstance, sign ) {
-		var b = super.createBatchShader(rt, shaders, perInstance, sign);
-		batchers.push({ rt : rt, shader : b.shader, instance : perInstance });
+	override function createBatchShader( rt, shaders, params ) {
+		var b = super.createBatchShader(rt, shaders, params);
+		batchers.push({ rt : rt, shader : b.shader, params : params });
 		return b;
 		return b;
 	}
 	}
 
 
@@ -202,10 +202,10 @@ class CacheFile extends Cache {
 			if( name == null ) break;
 			if( name == null ) break;
 			var rt = readString();
 			var rt = readString();
 			var str = readStringOpt();
 			var str = readStringOpt();
-			var inst = null;
+			var params = null;
 			if( str != null )
 			if( str != null )
-				inst = [for( s in str.split(";") ) { var v = s.split("="); { shader : v[0], params : v[1].split(",") }}];
-			batchMap.set(name, { rt : rt, inst : inst });
+				params = new hxsl.Cache.BatchInstanceParams([for( s in str.split(";") ) { var v = s.split("="); { shader : v[0], params : v[1].split(",") }}]);
+			batchMap.set(name, { rt : rt, params : params });
 		}
 		}
 
 
 		shaders = new Map();
 		shaders = new Map();
@@ -274,7 +274,7 @@ class CacheFile extends Cache {
 								r = null; // was modified
 								r = null; // was modified
 								break;
 								break;
 							}
 							}
-							var sh = makeBatchShader(rt.rt, rt.shaders, i.batch.inst);
+							var sh = makeBatchShader(rt.rt, rt.shaders, i.batch.params);
 							i.shader = { version : null, shader : sh.shader };
 							i.shader = { version : null, shader : sh.shader };
 							batchMode = true;
 							batchMode = true;
 						}
 						}
@@ -326,7 +326,7 @@ class CacheFile extends Cache {
 								r = null; // was modified
 								r = null; // was modified
 								break;
 								break;
 							}
 							}
-							var sh = makeBatchShader(rt.rt, rt.shaders, i.batch.inst);
+							var sh = makeBatchShader(rt.rt, rt.shaders, i.batch.params);
 							i.shader = { version : null, shader : sh.shader };
 							i.shader = { version : null, shader : sh.shader };
 							r.batchMode = true;
 							r.batchMode = true;
 						}
 						}
@@ -488,8 +488,8 @@ class CacheFile extends Cache {
 			separator();
 			separator();
 			writeString(@:privateAccess b.shader.data.name);
 			writeString(@:privateAccess b.shader.data.name);
 			writeString(@:privateAccess b.rt.spec.signature);
 			writeString(@:privateAccess b.rt.spec.signature);
-			if( b.instance != null )
-				writeString([for( s in b.instance ) s.shader+"="+s.params.join(",")].join(";"), true);
+			if( b.params != null )
+				writeString([for( s in @:privateAccess b.params.forcedPerInstance ) s.shader+"="+s.params.join(",")].join(";"), true);
 		}
 		}
 		separator();
 		separator();
 		writeString(null);
 		writeString(null);