Explorar el Código

setRenderTargets ok and dynamic realloc clear

Nicolas Cannasse hace 3 años
padre
commit
fa63dc4418
Se han modificado 1 ficheros con 110 adiciones y 60 borrados
  1. 110 60
      h3d/impl/DX12Driver.hx

+ 110 - 60
h3d/impl/DX12Driver.hx

@@ -10,7 +10,7 @@ import h3d.mat.Pass;
 private typedef Driver = Dx12;
 
 class DxFrame {
-	public var backBuffer : GpuResource;
+	public var backBuffer : ResourceData;
 	public var depthBuffer : GpuResource;
 	public var allocator : CommandAllocator;
 	public var commandList : CommandList;
@@ -61,6 +61,8 @@ class CompiledShader {
 	public var depthStencils : hl.BytesAccess<Address>;
 	public var vertexViews : hl.CArray<VertexBufferView>;
 	public var descriptors2 : hl.NativeArray<DescriptorHeap>;
+	public var viewports : hl.CArray<Viewport>;
+	public var rects : hl.CArray<Rect>;
 	@:packed public var heap(default,null) : HeapProperties;
 	@:packed public var barrier(default,null) : ResourceBarrier;
 	@:packed public var clearColor(default,null) : ClearColor;
@@ -80,6 +82,8 @@ class CompiledShader {
 		renderTargets = new hl.Bytes(8 * 8);
 		depthStencils = new hl.Bytes(8);
 		vertexViews = hl.CArray.alloc(VertexBufferView, 16);
+		viewports = hl.CArray.alloc(Viewport, 8);
+		rects = hl.CArray.alloc(Rect, 8);
 		pass = new h3d.mat.Pass("default");
 		pass.stencil = new h3d.mat.Stencil();
 		tex2DSRV.dimension = TEXTURE2D;
@@ -197,6 +201,16 @@ class VertexBufferData extends ResourceData {
 
 class TextureData extends ResourceData {
 	public var format : DxgiFormat;
+	public var color : h3d.Vector;
+	var clearColorChanges : Int;
+	public function setClearColor( c : h3d.Vector ) {
+		var color = color;
+		if( clearColorChanges > 10 || (color.r == c.r && color.g == c.g && color.b == c.b && color.a == c.a) )
+			return false;
+		clearColorChanges++;
+		color.load(c);
+		return true;
+	}
 }
 
 class DepthBufferData extends ResourceData {
@@ -259,6 +273,7 @@ class DX12Driver extends h3d.impl.Driver {
 		frames = [];
 		for(i in 0...BUFFER_COUNT) {
 			var f = new DxFrame();
+			f.backBuffer = new ResourceData();
 			f.allocator = new CommandAllocator(DIRECT);
 			f.commandList = new CommandList(DIRECT, f.allocator, null);
 			f.commandList.close();
@@ -287,12 +302,7 @@ class DX12Driver extends h3d.impl.Driver {
 		while( frame.toRelease.length > 0 )
 			frame.toRelease.pop().release();
 
-		var b = tmp.barrier;
-		b.resource = frame.backBuffer;
-		b.subResource = -1;
-		b.stateBefore = PRESENT;
-		b.stateAfter = RENDER_TARGET;
-		frame.commandList.resourceBarrier(b);
+		transition(frame.backBuffer, RENDER_TARGET);
 		frame.commandList.iaSetPrimitiveTopology(TRIANGLELIST);
 
 		renderTargetViews.next();
@@ -316,7 +326,20 @@ class DX12Driver extends h3d.impl.Driver {
 			clear.g = color.g;
 			clear.b = color.b;
 			clear.a = color.a;
-			frame.commandList.clearRenderTargetView(tmp.renderTargets[0], clear);
+			var count = currentRenderTargets.length;
+			if( count == 0 ) count = 1;
+			for( i in 0...count ) {
+				var tex = currentRenderTargets[i];
+				if( tex != null && tex.t.setClearColor(color) ) {
+					// update texture to use another clear value
+					var prev = tex.t;
+					tex.t = allocTexture(tex);
+					@:privateAccess tex.t.clearColorChanges = prev.clearColorChanges;
+					frame.toRelease.push(prev.res);
+					Driver.createRenderTargetView(tex.t.res, null, tmp.renderTargets[i]);
+				}
+				frame.commandList.clearRenderTargetView(tmp.renderTargets[i], clear);
+			}
 		}
 		if( depth != null || stencil != null )
 			frame.commandList.clearDepthStencilView(tmp.depthStencils[0], depth != null ? (stencil != null ? BOTH : DEPTH) : STENCIL, (depth:Float), stencil);
@@ -343,8 +366,8 @@ class DX12Driver extends h3d.impl.Driver {
 		waitGpu();
 
 		for( f in frames ) {
-			if( f.backBuffer != null )
-				f.backBuffer.release();
+			if( f.backBuffer.res != null )
+				f.backBuffer.res.release();
 			if( f.depthBuffer != null )
 				f.depthBuffer.release();
 		}
@@ -355,8 +378,9 @@ class DX12Driver extends h3d.impl.Driver {
 		depthStenciViews.clear();
 
 		for( i => f in frames ) {
-			f.backBuffer = Driver.getBackBuffer(i);
-			f.backBuffer.setName("Backbuffer#"+i);
+			f.backBuffer.res = Driver.getBackBuffer(i);
+			f.backBuffer.res.setName("Backbuffer#"+i);
+			f.backBuffer.state = PRESENT;
 
 			var desc = new ResourceDesc();
 			var flags = new haxe.EnumFlags();
@@ -412,23 +436,49 @@ class DX12Driver extends h3d.impl.Driver {
 		res.state = to;
 	}
 
+
+	function getRTBits( tex : h3d.mat.Texture ) {
+		inline function mk(channels,format) {
+			return ((channels - 1) << 2) | (format + 1);
+		}
+		return switch( tex.format ) {
+		case RGBA: mk(4,0);
+		case R8: mk(1, 0);
+		case RG8: mk(2, 0);
+		case RGB8: mk(3, 0);
+		case R16F: mk(1,1);
+		case RG16F: mk(2,1);
+		case RGB16F: mk(3,1);
+		case RGBA16F: mk(4,1);
+		case R32F: mk(1,2);
+		case RG32F: mk(2,2);
+		case RGB32F: mk(3,2);
+		case RGBA32F: mk(4,2);
+		default: throw "Unsupported RT format "+tex.format;
+		}
+	}
+
+	function getDepthView( tex : h3d.mat.Texture ) {
+		if( tex != null && tex.depthBuffer == null ) {
+			depthEnabled = false;
+			return null;
+		}
+		var depthView = depthStenciViews.alloc(1);
+		Driver.createDepthStencilView(tex == null ? frame.depthBuffer : @:privateAccess tex.depthBuffer.b.res, null, depthView);
+		var depths = tmp.depthStencils;
+		depths[0] = depthView;
+		depthEnabled = true;
+		return depths;
+	}
+
 	override function setRenderTarget(tex:Null<h3d.mat.Texture>, layer:Int = 0, mipLevel:Int = 0) {
 
 		if( tex != null ) transition(tex.t, RENDER_TARGET);
 
 		var texView = renderTargetViews.alloc(1);
-		Driver.createRenderTargetView(tex == null ? frame.backBuffer : tex.t.res, null, texView);
+		Driver.createRenderTargetView(tex == null ? frame.backBuffer.res : tex.t.res, null, texView);
 		tmp.renderTargets[0] = texView;
-		var depths = null;
-		if( tex == null || tex.depthBuffer != null ) {
-			var depthView = depthStenciViews.alloc(1);
-			Driver.createDepthStencilView(tex == null ? frame.depthBuffer : @:privateAccess tex.depthBuffer.b.res, null, depthView);
-			depths = tmp.depthStencils;
-			depths[0] = depthView;
-			depthEnabled = true;
-		} else
-			depthEnabled = false;
-		frame.commandList.omSetRenderTargets(1, tmp.renderTargets, true, depths);
+		frame.commandList.omSetRenderTargets(1, tmp.renderTargets, true, getDepthView(tex));
 
 		while( currentRenderTargets.length > 0 ) currentRenderTargets.pop();
 		if( tex != null ) currentRenderTargets.push(tex);
@@ -443,33 +493,38 @@ class DX12Driver extends h3d.impl.Driver {
 		frame.commandList.rsSetScissorRects(1, tmp.rect);
 		frame.commandList.rsSetViewports(1, tmp.viewport);
 
-		pipelineSignature.setI32(PSIGN_RENDER_TARGETS, tex == null ? 0 : getRTBits(tex) | (depths == null ? 0 : 0x80000000));
+		pipelineSignature.setI32(PSIGN_RENDER_TARGETS, tex == null ? 0 : getRTBits(tex) | (depthEnabled ? 0x80000000 : 0));
 		needPipelineFlush = true;
 	}
 
-	function getRTBits( tex : h3d.mat.Texture ) {
-		inline function mk(channels,format) {
-			return ((channels - 1) << 2) | (format + 1);
-		}
-		return switch( tex.format ) {
-		case RGBA: mk(4,0);
-		case R8: mk(1, 0);
-		case RG8: mk(2, 0);
-		case RGB8: mk(3, 0);
-		case R16F: mk(1,1);
-		case RG16F: mk(2,1);
-		case RGB16F: mk(3,1);
-		case RGBA16F: mk(4,1);
-		case R32F: mk(1,2);
-		case RG32F: mk(2,2);
-		case RGB32F: mk(3,2);
-		case RGBA32F: mk(4,2);
-		default: throw "Unsupported RT format "+tex.format;
+	override function setRenderTargets(textures:Array<h3d.mat.Texture>) {
+		while( currentRenderTargets.length > textures.length )
+			currentRenderTargets.pop();
+
+		var texViews = renderTargetViews.alloc(textures.length);
+		var bits = 0;
+		for( i => t in textures ) {
+			var view = texViews.offset(renderTargetViews.stride * i);
+			Driver.createRenderTargetView(t.t.res, null, view);
+			tmp.renderTargets[i] = view;
+			currentRenderTargets[i] = t;
+			bits |= getRTBits(t) << (i << 2);
+			var vp = tmp.viewports[i];
+			vp.width = t.width;
+			vp.height = t.height;
+			vp.maxDepth = 1;
+			var rect = tmp.rects[i];
+			rect.right = t.width;
+			rect.bottom = t.height;
+			transition(t.t, RENDER_TARGET);
 		}
-	}
 
-	override function setRenderTargets(textures:Array<h3d.mat.Texture>) {
-		throw "TODO";
+		frame.commandList.omSetRenderTargets(textures.length, tmp.renderTargets, true, getDepthView(textures[0]));
+		frame.commandList.rsSetScissorRects(textures.length, tmp.rects[0]);
+		frame.commandList.rsSetViewports(textures.length, tmp.viewports[0]);
+
+		pipelineSignature.setI32(PSIGN_RENDER_TARGETS, bits | (depthEnabled ? 0x80000000 : 0));
+		needPipelineFlush = true;
 	}
 
 	override function captureRenderBuffer( pixels : hxd.Pixels ) {
@@ -929,13 +984,15 @@ class DX12Driver extends h3d.impl.Driver {
 
 		var clear = null;
 		if( isRT ) {
+			var color = t.t == null || t.t.color == null ? new h3d.Vector(0,0,0,0) : t.t.color; // reuse prev color
 			desc.flags.set(ALLOW_RENDER_TARGET);
 			clear = tmp.clearValue;
 			clear.format = desc.format;
-			clear.color.r = 0;
-			clear.color.g = 0;
-			clear.color.b = 0;
-			clear.color.a = 0;
+			clear.color.r = color.r;
+			clear.color.g = color.g;
+			clear.color.b = color.b;
+			clear.color.a = color.a;
+			td.color = color;
 		}
 
 		td.state = isRT ? RENDER_TARGET : COPY_DEST;
@@ -1199,7 +1256,7 @@ class DX12Driver extends h3d.impl.Driver {
 		var wire = Pass.getWireframe(passBits);
 		if( wire != 0 ) cull = 0;
 
-		var rtCount = p.numRenderTargets;
+		var rtCount = currentRenderTargets.length;
 		if( rtCount == 0 ) rtCount = 1;
 
 		p.numRenderTargets = rtCount;
@@ -1231,7 +1288,7 @@ class DX12Driver extends h3d.impl.Driver {
 			d.alignedByteOffset = pipelineSignature.getUI8(PSIGN_BUF_OFFSETS + i) << 2;
 		}
 
-		if( stencilMask != 0 || stencilOp != 0 ) throw "TODO:stencil";
+		if( stencilMask != 0 || stencilOp != 0 ) trace("TODO:stencil");
 
 		return Driver.createGraphicsPipelineState(p);
 	}
@@ -1287,15 +1344,6 @@ class DX12Driver extends h3d.impl.Driver {
 	}
 
 	function flushFrame() {
-
-		// necessary even if we don't present so we don't get an error at begin frame
-		var barrier = tmp.barrier;
-		barrier.resource = frame.backBuffer;
-		barrier.subResource = -1;
-		barrier.stateBefore = RENDER_TARGET;
-		barrier.stateAfter = PRESENT;
-		frame.commandList.resourceBarrier(barrier);
-
 		frame.commandList.close();
 		frame.commandList.execute();
 		currentShader = null;
@@ -1305,6 +1353,8 @@ class DX12Driver extends h3d.impl.Driver {
 	}
 
 	override function present() {
+
+		transition(frame.backBuffer, PRESENT);
 		flushFrame();
 		Driver.present(window.vsync);