Răsfoiți Sursa

changed Driver.getInputNames and MeshPrimitive.getBuffers to have more persistent layouts

Nicolas Cannasse 6 ani în urmă
părinte
comite
78f3002e18

+ 15 - 2
h3d/Buffer.hx

@@ -152,7 +152,11 @@ class Buffer {
 }
 
 class BufferOffset {
+	#if flash
+	static var UID = 0;
 	public var id : Int;
+	#end
+
 	public var buffer : Buffer;
 	public var offset : Int;
 
@@ -161,13 +165,22 @@ class BufferOffset {
 	*/
 	public var next : BufferOffset;
 
-	static var UID = 0;
-
 	public function new(buffer, offset) {
+		#if flash
 		this.id = UID++;
+		#end
 		this.buffer = buffer;
 		this.offset = offset;
 	}
+
+	public inline function clone() {
+		var b = new BufferOffset(buffer,offset);
+		#if flash
+		b.id = id;
+		#end
+		return b;
+	}
+
 	public function dispose() {
 		if( buffer != null ) {
 			buffer.dispose();

+ 6 - 5
h3d/impl/DirectXDriver.hx

@@ -38,7 +38,7 @@ private class CompiledShader {
 	public var vertex : ShaderContext;
 	public var fragment : ShaderContext;
 	public var layout : Layout;
-	public var inputs : Array<String>;
+	public var inputs : InputNames;
 	public var offsets : Array<Int>;
 	public function new() {
 	}
@@ -887,10 +887,10 @@ class DirectXDriver extends h3d.impl.Driver {
 			s = new CompiledShader();
 			var vertex = compileShader(shader.vertex);
 			var fragment = compileShader(shader.fragment);
+			var inputs = [];
 			if( hasDeviceError ) return false;
 			s.vertex = vertex.s;
 			s.fragment = fragment.s;
-			s.inputs = [];
 			s.offsets = [];
 
 			var layout = [], offset = 0;
@@ -923,7 +923,7 @@ class DirectXDriver extends h3d.impl.Driver {
 						e.inputSlotClass = PerVertexData;
 					layout.push(e);
 					s.offsets.push(offset);
-					s.inputs.push(v.name);
+					inputs.push(v.name);
 
 					var size = switch( v.type ) {
 					case TVec(n, _): n;
@@ -938,6 +938,7 @@ class DirectXDriver extends h3d.impl.Driver {
 			var n = new hl.NativeArray(layout.length);
 			for( i in 0...layout.length )
 				n[i] = layout[i];
+			s.inputs = InputNames.get(inputs);
 			s.layout = Driver.createInputLayout(n, vertex.bytes, vertex.bytes.length);
 			if( s.layout == null )
 				throw "Failed to create input layout";
@@ -952,7 +953,7 @@ class DirectXDriver extends h3d.impl.Driver {
 		return true;
 	}
 
-	override function getShaderInputNames():Array<String> {
+	override function getShaderInputNames() : InputNames {
 		return currentShader.inputs;
 	}
 
@@ -960,7 +961,7 @@ class DirectXDriver extends h3d.impl.Driver {
 		if( hasDeviceError ) return;
 		var vbuf = @:privateAccess buffer.buffer.vbuf;
 		var start = -1, max = -1, position = 0;
-		for( i in 0...currentShader.inputs.length ) {
+		for( i in 0...currentShader.inputs.names.length ) {
 			if( currentVBuffers[i] != vbuf.res || offsets[i] != currentShader.offsets[i] << 2 ) {
 				currentVBuffers[i] = vbuf.res;
 				strides[i] = buffer.buffer.stride << 2;

+ 21 - 1
h3d/impl/Driver.hx

@@ -125,6 +125,26 @@ enum RenderFlag {
 	CameraHandness;
 }
 
+class InputNames {
+	public var id(default,null) : Int;
+	public var names(default,null) : Array<String>;
+	function new(names) {
+		this.id = UID++;
+		this.names = names;
+	}
+	static var UID = 0;
+	static var CACHE = new Map<String,InputNames>();
+	public static function get( names : Array<String> ) {
+		var key = names.join("|");
+		var i = CACHE.get(key);
+		if( i == null ) {
+			i = new InputNames(names.copy());
+			CACHE.set(key,i);
+		}
+		return i;
+	}
+}
+
 class Driver {
 
 	public var logEnable : Bool;
@@ -198,7 +218,7 @@ class Driver {
 	public function uploadShaderBuffers( buffers : h3d.shader.Buffers, which : h3d.shader.Buffers.BufferKind ) {
 	}
 
-	public function getShaderInputNames() : Array<String> {
+	public function getShaderInputNames() : InputNames {
 		return null;
 	}
 

+ 6 - 5
h3d/impl/GlDriver.hx

@@ -131,7 +131,7 @@ private class CompiledProgram {
 	public var vertex : CompiledShader;
 	public var fragment : CompiledShader;
 	public var stride : Int;
-	public var attribNames : Array<String>;
+	public var inputs : InputNames;
 	public var attribs : Array<CompiledAttribute>;
 	public function new() {
 	}
@@ -283,7 +283,7 @@ class GlDriver extends Driver {
 	}
 
 	override function getShaderInputNames() {
-		return curShader.attribNames;
+		return curShader.inputs;
 	}
 
 	override function getNativeShaderCode( shader : hxsl.RuntimeShader ) {
@@ -415,7 +415,7 @@ class GlDriver extends Driver {
 			firstShader = false;
 			initShader(p, p.vertex, shader.vertex);
 			initShader(p, p.fragment, shader.fragment);
-			p.attribNames = [];
+			var attribNames = [];
 			p.attribs = [];
 			p.stride = 0;
 			for( v in shader.vertex.data.vars )
@@ -447,10 +447,11 @@ class GlDriver extends Driver {
 							}
 					}
 					p.attribs.push(a);
-					p.attribNames.push(v.name);
+					attribNames.push(v.name);
 					p.stride += size;
 				default:
 				}
+			p.inputs = InputNames.get(attribNames);
 			programs.set(shader.id, p);
 		}
 		if( curShader == p ) return false;
@@ -1233,7 +1234,7 @@ class GlDriver extends Driver {
 			for( i in 0...curShader.attribs.length ) {
 				var a = curShader.attribs[i];
 				var pos;
-				switch( curShader.attribNames[i] ) {
+				switch( curShader.inputs.names[i] ) {
 				case "position":
 					pos = 0;
 				case "normal":

+ 1 - 1
h3d/impl/LogDriver.hx

@@ -247,7 +247,7 @@ class LogDriver extends Driver {
 		return inf;
 	}
 
-	override function getShaderInputNames() : Array<String> {
+	override function getShaderInputNames() {
 		return d.getShaderInputNames();
 	}
 

+ 2 - 2
h3d/impl/NullDriver.hx

@@ -42,12 +42,12 @@ class NullDriver extends Driver {
 		return true;
 	}
 
-	override function getShaderInputNames() : Array<String> {
+	override function getShaderInputNames() : InputNames {
 		var names = [];
 		for( v in cur.vertex.data.vars )
 			if( v.kind == Input )
 				names.push(v.name);
-		return names;
+		return InputNames.get(names);
 	}
 
 	override function allocTexture( t : h3d.mat.Texture ) : Texture {

+ 6 - 6
h3d/impl/Stage3dDriver.hx

@@ -39,13 +39,12 @@ private class CompiledShader {
 	public var s : hxsl.RuntimeShader;
 	public var stride : Int;
 	public var bufferFormat : Int;
-	public var inputNames : Array<String>;
+	public var inputs : InputNames;
 	public var usedTextures : Array<Bool>;
 	public function new(s) {
 		this.s = s;
 		stride = 0;
 		bufferFormat = 0;
-		inputNames = [];
 		usedTextures = [];
 	}
 }
@@ -579,6 +578,7 @@ class Stage3dDriver extends Driver {
 		fdata.endian = flash.utils.Endian.LITTLE_ENDIAN;
 
 		var pos = 0;
+		var inputNames = [];
 		for( v in shader.vertex.data.vars )
 			if( v.kind == Input ) {
 				var size;
@@ -593,11 +593,11 @@ class Stage3dDriver extends Driver {
 				var idx = FORMAT.indexOf(fmt);
 				if( idx < 0 ) throw "assert " + fmt;
 				p.bufferFormat |= idx << (pos * 3);
-				p.inputNames.push(v.name);
+				inputNames.push(v.name);
 				p.stride += size;
 				pos++;
 			}
-
+		p.inputs = InputNames.get(inputNames);
 		p.p.upload(vdata, fdata);
 		return p;
 	}
@@ -711,7 +711,7 @@ class Stage3dDriver extends Driver {
 			}
 		} else {
 			offset = 8; // custom data starts after [position, normal, uv]
-			for( s in curShader.inputNames ) {
+			for( s in curShader.inputs.names ) {
 				switch( s ) {
 				case "position":
 					ctx.setVertexBufferAt(pos++, m.vbuf, 0, FORMAT[3]);
@@ -736,7 +736,7 @@ class Stage3dDriver extends Driver {
 	}
 
 	override function getShaderInputNames() {
-		return curShader.inputNames;
+		return curShader.inputs;
 	}
 
 	override function selectMultiBuffers( buffers : Buffer.BufferOffset ) {

+ 13 - 11
h3d/prim/MeshPrimitive.hx

@@ -3,8 +3,7 @@ package h3d.prim;
 class MeshPrimitive extends Primitive {
 
 	var bufferCache : Map<Int,h3d.Buffer.BufferOffset>;
-	var prevNames : Array<String>;
-	var prevBuffers : h3d.Buffer.BufferOffset;
+	var layouts : Map<Int,h3d.Buffer.BufferOffset>;
 
 	function allocBuffer( engine : h3d.Engine, name : String ) {
 		return null;
@@ -31,17 +30,20 @@ class MeshPrimitive extends Primitive {
 			for( b in bufferCache )
 				b.dispose();
 		bufferCache = null;
-		prevNames = null;
+		layouts = null;
 	}
 
 	function getBuffers( engine : h3d.Engine ) {
 		if( bufferCache == null )
 			bufferCache = new Map();
-		var names = @:privateAccess engine.driver.getShaderInputNames();
-		if( names == prevNames )
-			return prevBuffers;
-		var buffers = null, prev = null;
-		for( name in names ) {
+		if( layouts == null )
+			layouts = new Map();
+		var inputs = @:privateAccess engine.driver.getShaderInputNames();
+		var buffers = layouts.get(inputs.id);
+		if( buffers != null )
+			return buffers;
+		var prev = null;
+		for( name in inputs.names ) {
 			var id = hxsl.Globals.allocID(name);
 			var b = bufferCache.get(id);
 			if( b == null ) {
@@ -49,7 +51,7 @@ class MeshPrimitive extends Primitive {
 				if( b == null ) throw "Buffer " + name + " is not available";
 				bufferCache.set(id, b);
 			}
-			b.next = null;
+			b = b.clone();
 			if( prev == null ) {
 				buffers = prev = b;
 			} else {
@@ -57,8 +59,8 @@ class MeshPrimitive extends Primitive {
 				prev = b;
 			}
 		}
-		prevNames = names;
-		return prevBuffers = buffers;
+		layouts.set(inputs.id, buffers);
+		return buffers;
 	}
 
 	override function render( engine : h3d.Engine ) {