浏览代码

added dynamic buffer allocation

Nicolas Cannasse 3 年之前
父节点
当前提交
469a94216a
共有 1 个文件被更改,包括 97 次插入18 次删除
  1. 97 18
      h3d/impl/DX12Driver.hx

+ 97 - 18
h3d/impl/DX12Driver.hx

@@ -10,6 +10,24 @@ import h3d.mat.Stencil;
 
 
 private typedef Driver = Dx12;
 private typedef Driver = Dx12;
 
 
+class TempBuffer {
+	public var next : TempBuffer;
+	public var buffer : GpuResource;
+	public var size : Int;
+	public var lastUse : Int;
+	public function new() {
+	}
+	public inline function count() {
+		var b = this;
+		var k = 0;
+		while( b != null ) {
+			k++;
+			b = b.next;
+		}
+		return k;
+	}
+}
+
 class DxFrame {
 class DxFrame {
 	public var backBuffer : ResourceData;
 	public var backBuffer : ResourceData;
 	public var depthBuffer : GpuResource;
 	public var depthBuffer : GpuResource;
@@ -19,6 +37,8 @@ class DxFrame {
 	public var toRelease : Array<Resource> = [];
 	public var toRelease : Array<Resource> = [];
 	public var shaderResourceViews : ManagedHeap;
 	public var shaderResourceViews : ManagedHeap;
 	public var samplerViews : ManagedHeap;
 	public var samplerViews : ManagedHeap;
+	public var availableBuffers : TempBuffer;
+	public var usedBuffers : TempBuffer;
 	public function new() {
 	public function new() {
 	}
 	}
 }
 }
@@ -186,13 +206,17 @@ class ResourceData {
 	}
 	}
 }
 }
 
 
-class IndexBufferData extends ResourceData {
+class BufferData extends ResourceData {
+	public var uploaded : Bool;
+}
+
+class IndexBufferData extends BufferData {
 	public var view : IndexBufferView;
 	public var view : IndexBufferView;
 	public var count : Int;
 	public var count : Int;
 	public var bits : Int;
 	public var bits : Int;
 }
 }
 
 
-class VertexBufferData extends ResourceData {
+class VertexBufferData extends BufferData {
 	public var view : dx.Dx12.VertexBufferView;
 	public var view : dx.Dx12.VertexBufferView;
 	public var stride : Int;
 	public var stride : Int;
 }
 }
@@ -261,8 +285,10 @@ class DX12Driver extends h3d.impl.Driver {
 	var curStencilRef : Int = -1;
 	var curStencilRef : Int = -1;
 	var rtWidth : Int;
 	var rtWidth : Int;
 	var rtHeight : Int;
 	var rtHeight : Int;
+	var frameCount : Int;
 
 
 	static var BUFFER_COUNT = 2;
 	static var BUFFER_COUNT = 2;
+	public static var DEBUG = false;
 
 
 	public function new() {
 	public function new() {
 		window = @:privateAccess dx.Window.windows[0];
 		window = @:privateAccess dx.Window.windows[0];
@@ -284,7 +310,7 @@ class DX12Driver extends h3d.impl.Driver {
 
 
 	function reset() {
 	function reset() {
 		var flags = new DriverInitFlags();
 		var flags = new DriverInitFlags();
-		flags.set(DEBUG);
+		if( DEBUG ) flags.set(DriverInitFlag.DEBUG);
 		driver = Driver.create(window, flags);
 		driver = Driver.create(window, flags);
 		frames = [];
 		frames = [];
 		for(i in 0...BUFFER_COUNT) {
 		for(i in 0...BUFFER_COUNT) {
@@ -319,6 +345,23 @@ class DX12Driver extends h3d.impl.Driver {
 		while( frame.toRelease.length > 0 )
 		while( frame.toRelease.length > 0 )
 			frame.toRelease.pop().release();
 			frame.toRelease.pop().release();
 
 
+		var used = frame.usedBuffers;
+		var b = frame.availableBuffers;
+		var prev = null;
+		while( b != null ) {
+			if( b.lastUse < frameCount - 120 ) {
+				b.buffer.release();
+				b = b.next;
+			} else {
+				var n = b.next;
+				b.next = used;
+				used = b;
+				b = n;
+			}
+		}
+		frame.availableBuffers = used;
+		frame.usedBuffers = null;
+
 		transition(frame.backBuffer, RENDER_TARGET);
 		transition(frame.backBuffer, RENDER_TARGET);
 		frame.commandList.iaSetPrimitiveTopology(TRIANGLELIST);
 		frame.commandList.iaSetPrimitiveTopology(TRIANGLELIST);
 
 
@@ -921,6 +964,7 @@ class DX12Driver extends h3d.impl.Driver {
 		view.strideInBytes = m.stride << 2;
 		view.strideInBytes = m.stride << 2;
 		buf.view = view;
 		buf.view = view;
 		buf.stride = m.stride;
 		buf.stride = m.stride;
+		buf.uploaded = m.flags.has(Dynamic);
 		return buf;
 		return buf;
 	}
 	}
 
 
@@ -947,37 +991,46 @@ class DX12Driver extends h3d.impl.Driver {
 		disposeResource(v);
 		disposeResource(v);
 	}
 	}
 
 
-	function updateBuffer( res : GpuResource, bytes : hl.Bytes, startByte : Int, bytesCount : Int ) {
-		var tmpBuf = allocBuffer(bytesCount, UPLOAD, GENERIC_READ);
-		var ptr = tmpBuf.map(0, null);
-		ptr.blit(0, bytes, 0, bytesCount);
-		tmpBuf.unmap(0,null);
-		frame.commandList.copyBufferRegion(res, startByte, tmpBuf, 0, bytesCount);
-		frame.toRelease.push(tmpBuf);
+	function updateBuffer( b : BufferData, bytes : hl.Bytes, startByte : Int, bytesCount : Int ) {
+		var tmpBuf;
+		if( b.uploaded )
+			tmpBuf = allocDynamicBuffer(bytes.offset(startByte), bytesCount);
+		else {
+			var size = calcCBVSize(bytesCount);
+			tmpBuf = allocBuffer(size, UPLOAD, GENERIC_READ);
+			var ptr = tmpBuf.map(0, null);
+			ptr.blit(0, bytes, 0, bytesCount);
+			tmpBuf.unmap(0,null);
+		}
+		frame.commandList.copyBufferRegion(b.res, startByte, tmpBuf, 0, bytesCount);
+		if( !b.uploaded ) {
+			frame.toRelease.push(tmpBuf);
+			b.uploaded = true;
+		}
 	}
 	}
 
 
 	override function uploadIndexBuffer(i:IndexBuffer, startIndice:Int, indiceCount:Int, buf:hxd.IndexBuffer, bufPos:Int) {
 	override function uploadIndexBuffer(i:IndexBuffer, startIndice:Int, indiceCount:Int, buf:hxd.IndexBuffer, bufPos:Int) {
 		transition(i, COPY_DEST);
 		transition(i, COPY_DEST);
-		updateBuffer(i.res, hl.Bytes.getArray(buf.getNative()).offset(bufPos << i.bits), startIndice << i.bits, indiceCount << i.bits);
+		updateBuffer(i, hl.Bytes.getArray(buf.getNative()).offset(bufPos << i.bits), startIndice << i.bits, indiceCount << i.bits);
 		transition(i, INDEX_BUFFER);
 		transition(i, INDEX_BUFFER);
 	}
 	}
 
 
 	override function uploadIndexBytes(i:IndexBuffer, startIndice:Int, indiceCount:Int, buf:haxe.io.Bytes, bufPos:Int) {
 	override function uploadIndexBytes(i:IndexBuffer, startIndice:Int, indiceCount:Int, buf:haxe.io.Bytes, bufPos:Int) {
 		transition(i, COPY_DEST);
 		transition(i, COPY_DEST);
-		updateBuffer(i.res, @:privateAccess buf.b.offset(bufPos << i.bits), startIndice << i.bits, indiceCount << i.bits);
+		updateBuffer(i, @:privateAccess buf.b.offset(bufPos << i.bits), startIndice << i.bits, indiceCount << i.bits);
 		transition(i, INDEX_BUFFER);
 		transition(i, INDEX_BUFFER);
 	}
 	}
 
 
 	override function uploadVertexBuffer(v:VertexBuffer, startVertex:Int, vertexCount:Int, buf:hxd.FloatBuffer, bufPos:Int) {
 	override function uploadVertexBuffer(v:VertexBuffer, startVertex:Int, vertexCount:Int, buf:hxd.FloatBuffer, bufPos:Int) {
 		var data = hl.Bytes.getArray(buf.getNative()).offset(bufPos<<2);
 		var data = hl.Bytes.getArray(buf.getNative()).offset(bufPos<<2);
 		transition(v, COPY_DEST);
 		transition(v, COPY_DEST);
-		updateBuffer(v.res, data, startVertex * v.stride << 2, vertexCount * v.stride << 2);
+		updateBuffer(v, data, startVertex * v.stride << 2, vertexCount * v.stride << 2);
 		transition(v, VERTEX_AND_CONSTANT_BUFFER);
 		transition(v, VERTEX_AND_CONSTANT_BUFFER);
 	}
 	}
 
 
 	override function uploadVertexBytes(v:VertexBuffer, startVertex:Int, vertexCount:Int, buf:haxe.io.Bytes, bufPos:Int) {
 	override function uploadVertexBytes(v:VertexBuffer, startVertex:Int, vertexCount:Int, buf:haxe.io.Bytes, bufPos:Int) {
 		transition(v, COPY_DEST);
 		transition(v, COPY_DEST);
-		updateBuffer(v.res, @:privateAccess buf.b.offset(bufPos << 2), startVertex * v.stride << 2, vertexCount * v.stride << 2);
+		updateBuffer(v, @:privateAccess buf.b.offset(bufPos << 2), startVertex * v.stride << 2, vertexCount * v.stride << 2);
 		transition(v, VERTEX_AND_CONSTANT_BUFFER);
 		transition(v, VERTEX_AND_CONSTANT_BUFFER);
 	}
 	}
 
 
@@ -1144,12 +1197,37 @@ class DX12Driver extends h3d.impl.Driver {
 		return sz;
 		return sz;
  	}
  	}
 
 
-	function allocDynamicCBV( data : hl.Bytes, dataSize : Int ) {
-		var tmpBuf = allocBuffer(calcCBVSize(dataSize), UPLOAD, GENERIC_READ);
+	function allocDynamicBuffer( data : hl.Bytes, dataSize : Int ) {
+		var b = frame.availableBuffers, prev = null;
+		var tmpBuf = null;
+		var size = calcCBVSize(dataSize);
+		while( b != null ) {
+			if( b.size >= size && b.size < size << 1 ) {
+				tmpBuf = b.buffer;
+				if( prev == null )
+					frame.availableBuffers = b.next;
+				else
+					prev.next = b.next;
+				b.lastUse = frameCount;
+				b.next = frame.usedBuffers;
+				frame.usedBuffers = b;
+				break;
+			}
+			prev = b;
+			b = b.next;
+		}
+		if( tmpBuf == null ) {
+			tmpBuf = allocBuffer(size, UPLOAD, GENERIC_READ);
+			var b = new TempBuffer();
+			b.buffer = tmpBuf;
+			b.size = size;
+			b.lastUse = frameCount;
+			b.next = frame.usedBuffers;
+			frame.usedBuffers = b;
+		}
 		var ptr = tmpBuf.map(0, null);
 		var ptr = tmpBuf.map(0, null);
 		ptr.blit(0, data, 0, dataSize);
 		ptr.blit(0, data, 0, dataSize);
 		tmpBuf.unmap(0,null);
 		tmpBuf.unmap(0,null);
-		frame.toRelease.push(tmpBuf);
 		return tmpBuf;
 		return tmpBuf;
 	}
 	}
 
 
@@ -1162,7 +1240,7 @@ class DX12Driver extends h3d.impl.Driver {
 				if( regs.params & 0x100 != 0 ) {
 				if( regs.params & 0x100 != 0 ) {
 					// update CBV
 					// update CBV
 					var srv = frame.shaderResourceViews.alloc(1);
 					var srv = frame.shaderResourceViews.alloc(1);
-					var cbv = allocDynamicCBV(data,dataSize);
+					var cbv = allocDynamicBuffer(data,dataSize);
 					var desc = tmp.cbvDesc;
 					var desc = tmp.cbvDesc;
 					desc.bufferLocation = cbv.getGpuVirtualAddress();
 					desc.bufferLocation = cbv.getGpuVirtualAddress();
 					desc.sizeInBytes = calcCBVSize(dataSize);
 					desc.sizeInBytes = calcCBVSize(dataSize);
@@ -1437,6 +1515,7 @@ class DX12Driver extends h3d.impl.Driver {
 
 
 	override function present() {
 	override function present() {
 
 
+		frameCount++;
 		transition(frame.backBuffer, PRESENT);
 		transition(frame.backBuffer, PRESENT);
 		flushFrame();
 		flushFrame();
 		Driver.present(window.vsync);
 		Driver.present(window.vsync);