瀏覽代碼

Add uploadInstanceBufferBytes to driver to prevent realloc of InstanceBuffer if the new one is smaller than the previous one.

borisrp 4 月之前
父節點
當前提交
e47450fb37
共有 5 個文件被更改,包括 68 次插入11 次删除
  1. 7 0
      h3d/impl/DX12Driver.hx
  2. 6 0
      h3d/impl/DirectXDriver.hx
  3. 3 0
      h3d/impl/Driver.hx
  4. 27 0
      h3d/impl/GlDriver.hx
  5. 25 11
      h3d/impl/InstanceBuffer.hx

+ 7 - 0
h3d/impl/DX12Driver.hx

@@ -1523,6 +1523,13 @@ class DX12Driver extends h3d.impl.Driver {
 		b.data = buf;
 	}
 
+	override function uploadInstanceBufferBytes(b : InstanceBuffer, startVertex : Int, vertexCount : Int, buf : haxe.io.Bytes, bufPos : Int ) {
+		transition(b.data, COPY_DEST);
+		flushTransitions();
+		var strideBytes = 5 * 4;
+		updateBuffer(b.data, @:privateAccess buf.b.offset(bufPos), startVertex * strideBytes, vertexCount * strideBytes);
+	}
+
 	override function disposeBuffer(v:Buffer) {
 		disposeResource(v.vbuf);
 	}

+ 6 - 0
h3d/impl/DirectXDriver.hx

@@ -1403,6 +1403,12 @@ class DirectXDriver extends h3d.impl.Driver {
 		b.data = dx.Driver.createBuffer(b.commandCount * 5 * 4, Default, UnorderedAccess, None, DrawIndirectArgs, 4, buf);
 	}
 
+	override function uploadInstanceBufferBytes(b : InstanceBuffer, startVertex : Int, vertexCount : Int, buf : haxe.io.Bytes, bufPos : Int ) {
+		if( hasDeviceError ) return;
+		var strideBytes = 5 * 4;
+		updateBuffer(b.data, @:privateAccess buf.b.offset(bufPos), startVertex * strideBytes, vertexCount * strideBytes);
+	}
+
 	override function disposeInstanceBuffer(b:InstanceBuffer) {
 		(b.data : dx.Resource).release();
 		b.data = null;

+ 3 - 0
h3d/impl/Driver.hx

@@ -237,6 +237,9 @@ class Driver {
 	public function allocInstanceBuffer( b : h3d.impl.InstanceBuffer, bytes : haxe.io.Bytes ) {
 	}
 
+	public function uploadInstanceBufferBytes(b : h3d.impl.InstanceBuffer, startVertex : Int, vertexCount : Int, buf : haxe.io.Bytes, bufPos : Int ) {
+	}
+
 	public function disposeTexture( t : h3d.mat.Texture ) {
 	}
 

+ 27 - 0
h3d/impl/GlDriver.hx

@@ -1579,6 +1579,33 @@ class GlDriver extends Driver {
 		b.data = data;
 	}
 
+	// override function uploadBufferBytes( b : h3d.Buffer, startVertex : Int, vertexCount : Int, buf : haxe.io.Bytes, bufPos : Int ) {
+	// 	var stride = b.format.strideBytes;
+	// 	var type = b.flags.has(IndexBuffer) ? GL.ELEMENT_ARRAY_BUFFER : GL.ARRAY_BUFFER;
+	// 	gl.bindBuffer(type, b.vbuf);
+	// 	#if hl
+	// 	gl.bufferSubData(type, startVertex * stride, streamData(buf.getData(),bufPos,vertexCount * stride), bufPos * STREAM_POS, vertexCount * stride);
+	// 	#else
+	// 	var sub = new Uint8Array(buf.getData(), bufPos, vertexCount * stride);
+	// 	gl.bufferSubData(type, startVertex * stride, sub);
+	// 	#end
+	// 	gl.bindBuffer(type, null);
+	// 	if( b.flags.has(IndexBuffer) ) curIndexBuffer = null;
+	// }
+
+	override function uploadInstanceBufferBytes(b : InstanceBuffer, startVertex : Int, vertexCount : Int, buf : haxe.io.Bytes, bufPos : Int ) {
+		var stride = 5*4;
+		var type = GL.DRAW_INDIRECT_BUFFER;
+		#if hl
+		gl.bindBuffer(type, b.data);
+		gl.bufferSubData(type, startVertex * stride, streamData(buf.getData(),bufPos,vertexCount * stride), bufPos * STREAM_POS, vertexCount * stride);
+		#else
+	 	var sub = new Uint8Array(buf.getData(), bufPos, vertexCount * stride);
+	 	gl.bufferSubData(type, startVertex * stride, sub);
+		#end
+		gl.bindBuffer(type, null);
+	}
+
 	override function disposeInstanceBuffer(b:InstanceBuffer) {
 		b.data = null;
 	}

+ 25 - 11
h3d/impl/InstanceBuffer.hx

@@ -21,6 +21,17 @@ class InstanceBuffer {
 		this.startIndex = startIndex;
 	}
 
+	function updateTriCount(commandCount : Int, bytes : haxe.io.Bytes)
+	{
+		triCount = 0;
+		for( i in 0...commandCount ) {
+			var idxCount = bytes.getInt32(i * 20);
+			var instCount = bytes.getInt32(i * 20 + 4);
+			var tri = Std.int((idxCount * instCount) / 3);
+			triCount += tri;
+		}
+	}
+
 	/**
 		Bytes are structures of 5 i32 with the following values:
 		- indexCount : number of indexes per instance
@@ -30,19 +41,22 @@ class InstanceBuffer {
 		- startInstanceLocation : offset in per instance buffer
 	**/
 	public function setBuffer( commandCount : Int, bytes : haxe.io.Bytes ) {
-		dispose();
+		if(commandCount > this.commandCount){
+			dispose();
 
-		for( i in 0...commandCount ) {
-			var idxCount = bytes.getInt32(i * 20);
-			var instCount = bytes.getInt32(i * 20 + 4);
-			var tri = Std.int((idxCount * instCount) / 3);
-			triCount += tri;
-		}
+			updateTriCount(commandCount, bytes);
+			this.commandCount = commandCount;
+			this.indexCount = 0;
+			driver = h3d.Engine.getCurrent().driver;
+			driver.allocInstanceBuffer(this, bytes);
+		} else {
 
-		this.commandCount = commandCount;
-		this.indexCount = 0;
-		driver = h3d.Engine.getCurrent().driver;
-		driver.allocInstanceBuffer(this, bytes);
+			updateTriCount(commandCount, bytes);
+			this.commandCount = commandCount;
+			this.indexCount = 0;
+			driver = h3d.Engine.getCurrent().driver;
+			driver.uploadInstanceBufferBytes(this, 0, commandCount, bytes, 0);
+		}
 	}
 
 	public function dispose() {