Jelajahi Sumber

added pipeline cache buffer stride if needed

Nicolas Cannasse 1 tahun lalu
induk
melakukan
00e91ccdba
2 mengubah file dengan 92 tambahan dan 18 penghapusan
  1. 2 2
      h3d/impl/DX12Driver.hx
  2. 90 16
      h3d/impl/PipelineCache.hx

+ 2 - 2
h3d/impl/DX12Driver.hx

@@ -1635,7 +1635,7 @@ class DX12Driver extends h3d.impl.Driver {
 			v.sizeInBytes = bview.sizeInBytes;
 			v.strideInBytes = bview.strideInBytes;
 			if( inf.offset >= 256 ) throw "assert";
-			pipelineBuilder.setBuffer(i, inf);
+			pipelineBuilder.setBuffer(i, inf, bview.strideInBytes);
 		}
 		frame.commandList.iaSetVertexBuffers(0, currentShader.inputCount, views[0]);
 	}
@@ -1651,7 +1651,7 @@ class DX12Driver extends h3d.impl.Driver {
 			v.sizeInBytes = bview.sizeInBytes;
 			v.strideInBytes = bview.strideInBytes;
 			if( inf.offset >= 256 ) throw "assert";
-			pipelineBuilder.setBuffer(i, inf);
+			pipelineBuilder.setBuffer(i, inf, bview.strideInBytes);
 		}
 		frame.commandList.iaSetVertexBuffers(0, map.length, views[0]);
 	}

+ 90 - 16
h3d/impl/PipelineCache.hx

@@ -1,7 +1,50 @@
 package h3d.impl;
 
+#if hl
+@:forward(setI32,setUI8,setUI16,getUI8,getUI16,getI32,sub)
+private abstract Bytes(hl.Bytes) from hl.Bytes {
+	public function new(size) this = new hl.Bytes(size);
+	public inline function compare( bytes : Bytes, size : Int ) {
+		return this.compare(0, bytes, 0, size);
+	}
+}
+#else
+@:forward(sub)
+private abstract Bytes(haxe.io.Bytes) from haxe.io.Bytes {
+	public function new(size) {
+		this = haxe.io.Bytes.alloc(size);
+	}
+	public inline function setI32(idx:Int,v:Int) {
+		this.setInt32(idx, v);
+	}
+	public inline function setUI8(idx:Int,v:Int) {
+		this.set(idx, v);
+	}
+	public inline function setUI16(idx:Int,v:Int) {
+		this.setUInt16(idx, v);
+	}
+	public inline function getI32(idx:Int) {
+		return this.getInt32(idx);
+	}
+	public inline function getUI8(idx:Int) {
+		return this.get(idx);
+	}
+	public inline function getUI16(idx:Int) {
+		return this.getUInt16(idx);
+	}
+	public function compare( bytes : Bytes, size : Int ) {
+		var bytes : haxe.io.Bytes = cast bytes;
+		for( i in 0...size ) {
+			var d = this.get(i) - bytes.get(i);
+			if( d != 0 ) return d;
+		}
+		return 0;
+	}
+}
+#end
+
 @:generic class CachedPipeline<T> {
-	public var bytes : hl.Bytes;
+	public var bytes : Bytes;
 	public var size : Int;
 	public var pipeline : T;
 	public function new() {
@@ -9,7 +52,7 @@ package h3d.impl;
 }
 
 @:forward(get,set)
-abstract PipelineCache<T>(Map<Int,hl.NativeArray<CachedPipeline<T>>>) {
+abstract PipelineCache<T>(Map<Int,#if hl hl.NativeArray #else Array #end<CachedPipeline<T>>>) {
 
 	public function new() {
 		this = new Map();
@@ -27,15 +70,19 @@ class PipelineBuilder {
 	static inline var PSIGN_RENDER_TARGETS = PSIGN_STENCIL_OPS + 4;
 	static inline var PSIGN_LAYOUT = PSIGN_RENDER_TARGETS + 8;
 	static inline var MAX_BUFFERS = 8;
-	static inline var PSIGN_SIZE = PSIGN_LAYOUT + MAX_BUFFERS * 2;
+	static inline var SHIFT_PER_BUFFER = #if js 2 #else 1 #end;
+	static inline var PSIGN_SIZE = PSIGN_LAYOUT + (MAX_BUFFERS << SHIFT_PER_BUFFER);
 
 	public var needFlush : Bool;
-	var signature = new hl.Bytes(64);
-	var adlerOut = new hl.Bytes(4);
+	var signature = new Bytes(64);
 	var tmpPass = new h3d.mat.Pass("");
 	var tmpStencil = new h3d.mat.Stencil();
+	#if hl
+	var adlerOut = new Bytes(4);
+	#end
 
 	public function new() {
+		if( PSIGN_SIZE > 64 ) throw "assert";
 	}
 
 	static function getRTBits( tex : h3d.mat.Texture ) {
@@ -95,8 +142,11 @@ class PipelineBuilder {
 		needFlush = true;
 	}
 
-	public inline function setBuffer( i : Int, inf : hxd.BufferFormat.BufferMapping ) {
-		signature.setUI16(PSIGN_LAYOUT + (i<<1), (inf.offset << 1) | inf.precision.toInt());
+	public inline function setBuffer( i : Int, inf : hxd.BufferFormat.BufferMapping, stride : Int ) {
+		signature.setUI16(PSIGN_LAYOUT + (i<<SHIFT_PER_BUFFER), (inf.offset << 1) | inf.precision.toInt());
+		#if js
+		signature.setUI16(PSIGN_LAYOUT + (i<<SHIFT_PER_BUFFER) + 2, stride);
+		#end
 		needFlush = true;
 	}
 
@@ -117,20 +167,41 @@ class PipelineBuilder {
 	}
 
 	public function getBufferInput( i : Int ) {
-		var b = signature.getUI16(PSIGN_LAYOUT + (i<<1));
+		var b = signature.getUI16(PSIGN_LAYOUT + (i<<SHIFT_PER_BUFFER));
 		return new hxd.BufferFormat.BufferMapping(i, (b >> 1) & ~3, @:privateAccess new hxd.BufferFormat.Precision(b & 7));
 	}
 
-	public function lookup<T>( cache : PipelineCache<T>, inputs : Int ) : CachedPipeline<T> {
-		needFlush = false;
-		var signature = signature;
-		var signatureSize = PSIGN_LAYOUT + (inputs << 1);
+	#if js
+	public function getBufferStride( i : Int ) {
+		return signature.getUI16(PSIGN_LAYOUT + (i << SHIFT_PER_BUFFER) + 2);
+	}
+	#end
+
+	function hashSign( size : Int ) {
+		#if hl
 		adlerOut.setI32(0, 0);
 		hl.Format.digest(adlerOut, signature, signatureSize, 3);
-		var hash = adlerOut.getI32(0);
+		return adlerOut.getI32(0);
+		#else
+		var tot = 0;
+		for( i in 0...size>>2 )
+			tot = (tot * 31 + signature.getI32(i<<2)) % 0x7FFFFFFF;
+		switch( size & 3 ) {
+		case 0:
+		case 2: tot = (tot * 31 + signature.getUI16(size - 2)) % 0x7FFFFFFF;
+		default: throw "assert";
+		}
+		return tot;
+		#end
+	}
+
+	public function lookup<T>( cache : PipelineCache<T>, inputs : Int ) : CachedPipeline<T> {
+		needFlush = false;
+		var signatureSize = PSIGN_LAYOUT + (inputs << SHIFT_PER_BUFFER);
+		var hash = hashSign(signatureSize);
 		var pipes = cache.get(hash);
 		if( pipes == null ) {
-			pipes = new hl.NativeArray(1);
+			pipes = #if hl new hl.NativeArray(1) #else [] #end;
 			cache.set(hash, pipes);
 		}
 		var insert = -1;
@@ -140,15 +211,18 @@ class PipelineBuilder {
 				insert = i;
 				break;
 			}
-			if( p.size == signatureSize && p.bytes.compare(0, signature, 0, signatureSize) == 0 )
+			if( p.size == signatureSize && p.bytes.compare(signature, signatureSize) == 0 )
 				return p;
 		}
-		var signatureBytes = @:privateAccess new haxe.io.Bytes(signature, signatureSize);
 		if( insert < 0 ) {
+			#if hl
 			var pipes2 = new hl.NativeArray(pipes.length + 1);
 			pipes2.blit(0, pipes, 0, insert);
 			cache.set(hash, pipes2);
 			pipes = pipes2;
+			#else
+			insert = pipes.length + 1;
+			#end
 		}
 		var cp = new CachedPipeline<T>();
 		cp.bytes = signature.sub(0, signatureSize);