فهرست منبع

changed MultiBuffer handling : hash name (faster access) and return linked list (no Array allocation)
added NullDriver to disable draw calls

ncannasse 11 سال پیش
والد
کامیت
ffef9e7a20
7فایلهای تغییر یافته به همراه187 افزوده شده و 25 حذف شده
  1. 13 1
      h3d/Engine.hx
  2. 11 0
      h3d/impl/Buffer.hx
  3. 4 4
      h3d/impl/Driver.hx
  4. 120 0
      h3d/impl/NullDriver.hx
  5. 16 11
      h3d/impl/Stage3dDriver.hx
  6. 23 7
      h3d/prim/MeshPrimitive.hx
  7. 0 2
      hxd/impl/FastIO.hx

+ 13 - 1
h3d/Engine.hx

@@ -109,6 +109,18 @@ class Engine {
 	public inline function renderQuadBuffer( b : h3d.impl.Buffer, start = 0, max = -1 ) {
 		return renderBuffer(b, mem.quadIndexes, 2, start, max);
 	}
+	
+	public function enableDriver( ?b : Bool ) {
+		if( b == null )
+			b = Std.is(driver, h3d.impl.NullDriver);
+		if( b ) {
+			var d = Std.instance(driver, h3d.impl.NullDriver);
+			if( d != null )
+				driver = d.driver;
+		} else if( !Std.is(driver,h3d.impl.NullDriver) ) {
+			driver = new h3d.impl.NullDriver(driver);
+		}
+	}
 
 	// we use preallocated indexes so all the triangles are stored inside our buffers
 	function renderBuffer( b : h3d.impl.Buffer, indexes : h3d.impl.Indexes, vertPerTri : Int, startTri = 0, drawTri = -1 ) {
@@ -161,7 +173,7 @@ class Engine {
 		}
 	}
 	
-	public function renderMultiBuffers( buffers : Array<h3d.impl.Buffer.BufferOffset>, indexes : h3d.impl.Indexes, startTri = 0, drawTri = -1 ) {
+	public function renderMultiBuffers( buffers : h3d.impl.Buffer.BufferOffset, indexes : h3d.impl.Indexes, startTri = 0, drawTri = -1 ) {
 		var maxTri = Std.int(indexes.count / 3);
 		if( maxTri <= 0 ) return;
 		driver.selectMultiBuffers(buffers);

+ 11 - 0
h3d/impl/Buffer.hx

@@ -65,9 +65,19 @@ class Buffer {
 }
 
 class BufferOffset {
+	public var id : Int;
 	public var b : Buffer;
 	public var offset : Int;
+	
+	/*
+		This is used to return a list of BufferOffset without allocating an array
+	*/
+	public var next : BufferOffset;
+	
+	static var UID = 0;
+	
 	public function new(b, offset) {
+		this.id = UID++;
 		this.b = b;
 		this.offset = offset;
 	}
@@ -76,5 +86,6 @@ class BufferOffset {
 			b.dispose();
 			b = null;
 		}
+		next = null;
 	}
 }

+ 4 - 4
h3d/impl/Driver.hx

@@ -51,14 +51,14 @@ class Driver {
 		return false;
 	}
 	
-	public function selectBuffer( buffer : VertexBuffer ) {
-	}
-	
 	public function getShaderInputNames() : Array<String> {
 		return null;
 	}
 	
-	public function selectMultiBuffers( buffers : Array<Buffer.BufferOffset> ) {
+	public function selectBuffer( buffer : VertexBuffer ) {
+	}
+	
+	public function selectMultiBuffers( buffers : Buffer.BufferOffset ) {
 	}
 	
 	public function draw( ibuf : IndexBuffer, startIndex : Int, ntriangles : Int ) {

+ 120 - 0
h3d/impl/NullDriver.hx

@@ -0,0 +1,120 @@
+package h3d.impl;
+import h3d.impl.Driver;
+
+class NullDriver extends Driver {
+
+	public var driver : Driver;
+	
+	public function new( driver ) {
+		this.driver = driver;
+	}
+	
+	override function isDisposed() {
+		return driver.isDisposed();
+	}
+	
+	override function dispose() {
+		driver.dispose();
+	}
+
+	override function reset() {
+		driver.reset();
+	}
+
+	override function present() {
+		driver.present();
+	}
+
+	override function clear( r : Float, g : Float, b : Float, a : Float ) {
+		driver.clear(r, g, b, a);
+	}
+	
+	override function getDriverName( details : Bool ) {
+		return "Null Driver - " + driver.getDriverName(details);
+	}
+	
+	override function init( onCreate : Bool -> Void, forceSoftware = false ) {
+		driver.init(onCreate, forceSoftware);
+	}
+
+	override function resize( width : Int, height : Int ) {
+		driver.resize(width, height);
+	}
+
+	override function selectMaterial( mbits : Int ) {
+		driver.selectMaterial(mbits);
+	}
+	
+	override function selectShader( shader : Shader ) : Bool {
+		return driver.selectShader(shader);
+	}
+	
+	override function getShaderInputNames() : Array<String> {
+		return driver.getShaderInputNames();
+	}
+	
+	override function isHardware() {
+		return driver.isHardware();
+	}
+	
+	override function setDebug( b : Bool ) {
+		driver.setDebug(b);
+	}
+	
+	override function allocTexture( t : h3d.mat.Texture ) : Texture {
+		return driver.allocTexture(t);
+	}
+
+	override function allocIndexes( count : Int ) : IndexBuffer {
+		return driver.allocIndexes(count);
+	}
+
+	override function allocVertex( count : Int, stride : Int ) : VertexBuffer {
+		return driver.allocVertex(count,stride);
+	}
+	
+	override function disposeTexture( t : Texture ) {
+		driver.disposeTexture(t);
+	}
+	
+	override function disposeIndexes( i : IndexBuffer ) {
+		driver.disposeIndexes(i);
+	}
+	
+	override function disposeVertex( v : VertexBuffer ) {
+		driver.disposeVertex(v);
+	}
+	
+	override function uploadIndexesBuffer( i : IndexBuffer, startIndice : Int, indiceCount : Int, buf : hxd.IndexBuffer, bufPos : Int ) {
+		driver.uploadIndexesBuffer(i, startIndice, indiceCount, buf, bufPos);
+	}
+
+	override function uploadIndexesBytes( i : IndexBuffer, startIndice : Int, indiceCount : Int, buf : haxe.io.Bytes , bufPos : Int ) {
+		driver.uploadIndexesBytes(i, startIndice, indiceCount, buf, bufPos);
+	}
+	
+	override function uploadVertexBuffer( v : VertexBuffer, startVertex : Int, vertexCount : Int, buf : hxd.FloatBuffer, bufPos : Int ) {
+		driver.uploadVertexBuffer(v, startVertex, vertexCount, buf, bufPos);
+	}
+
+	override function uploadVertexBytes( v : VertexBuffer, startVertex : Int, vertexCount : Int, buf : haxe.io.Bytes, bufPos : Int ) {
+		driver.uploadVertexBytes(v, startVertex, vertexCount, buf, bufPos);
+	}
+	
+	override function uploadTextureBitmap( t : h3d.mat.Texture, bmp : hxd.BitmapData, mipLevel : Int, side : Int ) {
+		driver.uploadTextureBitmap(t, bmp, mipLevel, side);
+	}
+
+	override function uploadTexturePixels( t : h3d.mat.Texture, pixels : hxd.Pixels, mipLevel : Int, side : Int ) {
+		driver.uploadTexturePixels(t, pixels, mipLevel, side);
+	}
+
+	/*
+	public function selectBuffer( buffer : VertexBuffer )
+	public function selectMultiBuffers( buffers : Array<Buffer.BufferOffset> )
+	public function draw( ibuf : IndexBuffer, startIndex : Int, ntriangles : Int )
+	public function setRenderZone( x : Int, y : Int, width : Int, height : Int )
+	public function setRenderTarget( tex : Null<Texture>, useDepth : Bool, clearColor : Int )
+	*/
+	
+}

+ 16 - 11
h3d/impl/Stage3dDriver.hx

@@ -41,7 +41,7 @@ class Stage3dDriver extends Driver {
 	var curMatBits : Int;
 	var curShader : hxsl.Shader.ShaderInstance;
 	var curBuffer : VertexBuffer;
-	var curMultiBuffer : Array<h3d.impl.Buffer.BufferOffset>;
+	var curMultiBuffer : Array<Int>;
 	var curAttributes : Int;
 	var curTextures : Array<h3d.mat.Texture>;
 	var curSamplerBits : Array<Int>;
@@ -67,7 +67,7 @@ class Stage3dDriver extends Driver {
 		curMatBits = -1;
 		curShader = null;
 		curBuffer = null;
-		curMultiBuffer = null;
+		curMultiBuffer = [];
 		for( i in 0...curAttributes )
 			ctx.setVertexBufferAt(i, null);
 		curAttributes = 0;
@@ -265,7 +265,7 @@ class Stage3dDriver extends Driver {
 			}
 			// force remapping of vertex buffer
 			curBuffer = null;
-			curMultiBuffer = null;
+			curMultiBuffer[0] = -1;
 			curShader = s;
 		}
 		if( s.varsChanged ) {
@@ -300,7 +300,7 @@ class Stage3dDriver extends Driver {
 		if( v == curBuffer )
 			return;
 		curBuffer = v;
-		curMultiBuffer = null;
+		curMultiBuffer[0] = -1;
 		if( v.stride < curShader.stride )
 			throw "Buffer stride (" + v.stride + ") and shader stride (" + curShader.stride + ") mismatch";
 		if( !v.written )
@@ -322,35 +322,40 @@ class Stage3dDriver extends Driver {
 		return curShader.bufferNames;
 	}
 	
-	override function selectMultiBuffers( buffers : Array<Buffer.BufferOffset> ) {
+	override function selectMultiBuffers( buffers : Buffer.BufferOffset ) {
 		// select the multiple buffers elements
-		var changed = curMultiBuffer == null || curMultiBuffer.length != buffers.length;
-		if( !changed )
-			for( i in 0...curMultiBuffer.length )
-				if( buffers[i] != curMultiBuffer[i] ) {
+		var changed = false;
+		if( !changed ) {
+			var b = buffers;
+			for( i in 0...curAttributes ) {
+				if( b == null || b.id != curMultiBuffer[i] ) {
 					changed = true;
 					break;
 				}
+				b = b.next;
+			}
+		}
 		if( changed ) {
 			var pos = 0, offset = 0;
 			var bits = curShader.bufferFormat;
+			var b = buffers;
 			while( offset < curShader.stride ) {
 				var size = bits & 7;
-				var b = buffers[pos];
 				if( b.b.next != null )
 					throw "Buffer is split";
 				if( !b.b.b.vbuf.written )
 					b.b.b.vbuf.finalize(this);
 				ctx.setVertexBufferAt(pos, b.b.b.vbuf.vbuf, b.offset, FORMAT[size]);
+				curMultiBuffer[pos] = b.id;
 				offset += size == 0 ? 1 : size;
 				bits >>= 3;
 				pos++;
+				b = b.next;
 			}
 			for( i in pos...curAttributes )
 				ctx.setVertexBufferAt(i, null);
 			curAttributes = pos;
 			curBuffer = null;
-			curMultiBuffer = buffers;
 		}
 	}
 	

+ 23 - 7
h3d/prim/MeshPrimitive.hx

@@ -2,18 +2,27 @@ package h3d.prim;
 
 class MeshPrimitive extends Primitive {
 		
-	var bufferCache : Map<String,h3d.impl.Buffer.BufferOffset>;
+	var bufferCache : Map<Int,h3d.impl.Buffer.BufferOffset>;
 	
 	function allocBuffer( engine : h3d.Engine, name : String ) {
 		return null;
 	}
 	
+	// TODO : in HxSL 3, we might instead allocate unique ID per name
+	static inline function hash( name : String ) {
+		var id = 0;
+		for( i in 0...name.length )
+			id = id * 223 + name.charCodeAt(i);
+		return id & 0x0FFFFFFF;
+	}
+	
 	function addBuffer( name : String, buf, offset = 0 ) {
 		if( bufferCache == null )
 			bufferCache = new Map();
-		var old = bufferCache.get(name);
+		var id = hash(name);
+		var old = bufferCache.get(id);
 		if( old != null ) old.dispose();
-		bufferCache.set(name, new h3d.impl.Buffer.BufferOffset(buf, offset));
+		bufferCache.set(id, new h3d.impl.Buffer.BufferOffset(buf, offset));
 	}
 
 	override public function dispose() {
@@ -28,15 +37,22 @@ class MeshPrimitive extends Primitive {
 	function getBuffers( engine : h3d.Engine ) {
 		if( bufferCache == null )
 			bufferCache = new Map();
-		var buffers = [];
+		var buffers = null, prev = null;
 		for( name in engine.driver.getShaderInputNames() ) {
-			var b = bufferCache.get(name);
+			var id = hash(name);
+			var b = bufferCache.get(id);
 			if( b == null ) {
 				b = allocBuffer(engine, name);
 				if( b == null ) throw "Buffer " + name + " is not available";
-				bufferCache.set(name, b);
+				bufferCache.set(id, b);
+			}
+			b.next = null;
+			if( prev == null ) {
+				buffers = prev = b;
+			} else {
+				prev.next = b;
+				prev = b;
 			}
-			buffers.push(b);
 		}
 		return buffers;
 	}

+ 0 - 2
hxd/impl/FastIO.hx

@@ -68,7 +68,6 @@ class FastIntIO extends FastIO<Int> {
 			flush((write < read ? write : (write - read)) * 4);
 			if( !hasNext() )
 				break;
-			var k = 0;
 			for( id in this ) {
 				var x = id & ((1 << bits) - 1);
 				var y = id >>> bits;
@@ -78,7 +77,6 @@ class FastIntIO extends FastIO<Int> {
 				add2d(x - 1, y, bits);
 				add2d(x, y + 1, bits);
 				add2d(x, y - 1, bits);
-				k += 4;
 			}
 		}
 	}