Sfoglia il codice sorgente

pipeline signature building, triangle ok

Nicolas Cannasse 3 anni fa
parent
commit
192a2a85cf
1 ha cambiato i file con 154 aggiunte e 8 eliminazioni
  1. 154 8
      h3d/impl/DX12Driver.hx

+ 154 - 8
h3d/impl/DX12Driver.hx

@@ -5,6 +5,7 @@ package h3d.impl;
 import h3d.impl.Driver;
 import h3d.impl.Driver;
 import dx.Dx12;
 import dx.Dx12;
 import haxe.Int64;
 import haxe.Int64;
+import h3d.mat.Pass;
 
 
 private typedef Driver = Dx12;
 private typedef Driver = Dx12;
 
 
@@ -18,10 +19,21 @@ class DxFrame {
 	}
 	}
 }
 }
 
 
+class CachedPipeline {
+	public var bytes : hl.Bytes;
+	public var size : Int;
+	public var pipeline : GraphicsPipelineState;
+	public function new() {
+	}
+}
+
 class CompiledShader {
 class CompiledShader {
+	public var inputCount : Int;
 	public var inputNames : InputNames;
 	public var inputNames : InputNames;
-	public var pipeline : GraphicsPipelineState;
+	public var pipeline : GraphicsPipelineStateDesc;
+	public var pipelines : Map<Int,hl.NativeArray<CachedPipeline>> = new Map();
 	public var rootSignature : RootSignature;
 	public var rootSignature : RootSignature;
+	public var inputLayout : hl.CArray<InputElementDesc>;
 	public function new() {
 	public function new() {
 	}
 	}
 }
 }
@@ -37,16 +49,30 @@ class CompiledShader {
 	@:packed public var viewport(default,null) : Viewport;
 	@:packed public var viewport(default,null) : Viewport;
 	@:packed public var rect(default,null) : Rect;
 	@:packed public var rect(default,null) : Rect;
 
 
+	public var pass : h3d.mat.Pass;
+
 	public function new() {
 	public function new() {
 		renderTargets = new hl.Bytes(8 * 8);
 		renderTargets = new hl.Bytes(8 * 8);
 		depthStencils = new hl.Bytes(8 * 8);
 		depthStencils = new hl.Bytes(8 * 8);
 		vertexViews = hl.CArray.alloc(VertexBufferView, 16);
 		vertexViews = hl.CArray.alloc(VertexBufferView, 16);
+		pass = new h3d.mat.Pass("default");
+		pass.stencil = new h3d.mat.Stencil();
 	}
 	}
 
 
 }
 }
 
 
 class DX12Driver extends h3d.impl.Driver {
 class DX12Driver extends h3d.impl.Driver {
 
 
+	static inline var PSIGN_MATID = 0;
+	static inline var PSIGN_COLOR_MASK = PSIGN_MATID + 4;
+	static inline var PSIGN_STENCIL_MASK = PSIGN_COLOR_MASK + 1;
+	static inline var PSIGN_STENCIL_OPS = PSIGN_STENCIL_MASK + 3;
+	static inline var PSIGN_RENDER_TARGETS = PSIGN_STENCIL_OPS + 4;
+	static inline var PSIGN_BUF_OFFSETS = PSIGN_RENDER_TARGETS + 8;
+
+	var pipelineSignature = new hl.Bytes(64);
+	var adlerOut = new hl.Bytes(4);
+
 	var driver : DriverInstance;
 	var driver : DriverInstance;
 	var hasDeviceError = false;
 	var hasDeviceError = false;
 	var window : dx.Window;
 	var window : dx.Window;
@@ -60,6 +86,9 @@ class DX12Driver extends h3d.impl.Driver {
 	var rtvAddress : Address;
 	var rtvAddress : Address;
 	var currentFrame : Int;
 	var currentFrame : Int;
 	var fenceValue : Int64 = 0;
 	var fenceValue : Int64 = 0;
+	var needPipelineFlush = false;
+	var currentPass : h3d.mat.Pass;
+	var renderTargetCount = 1;
 
 
 	var currentWidth : Int;
 	var currentWidth : Int;
 	var currentHeight : Int;
 	var currentHeight : Int;
@@ -127,6 +156,7 @@ class DX12Driver extends h3d.impl.Driver {
 
 
 		tmp.viewport.width = currentWidth;
 		tmp.viewport.width = currentWidth;
 		tmp.viewport.height = currentHeight;
 		tmp.viewport.height = currentHeight;
+		tmp.viewport.maxDepth = 1;
 		tmp.rect.right = currentWidth;
 		tmp.rect.right = currentWidth;
 		tmp.rect.bottom = currentHeight;
 		tmp.rect.bottom = currentHeight;
 		frame.commandList.iaSetPrimitiveTopology(TRIANGLELIST);
 		frame.commandList.iaSetPrimitiveTopology(TRIANGLELIST);
@@ -186,7 +216,7 @@ class DX12Driver extends h3d.impl.Driver {
 				d.instanceDataStepRate = perInst;
 				d.instanceDataStepRate = perInst;
 			} else
 			} else
 				d.inputSlotClass = PER_VERTEX_DATA;
 				d.inputSlotClass = PER_VERTEX_DATA;
-			d.alignedByteOffset = -1;
+			d.alignedByteOffset = 1; // will trigger error if not set in makePipeline()
 		}
 		}
 
 
 		var p = new GraphicsPipelineStateDesc();
 		var p = new GraphicsPipelineStateDesc();
@@ -201,15 +231,16 @@ class DX12Driver extends h3d.impl.Driver {
 		p.numRenderTargets = 1;
 		p.numRenderTargets = 1;
 		p.rtvFormats[0] = R8G8B8A8_UNORM;
 		p.rtvFormats[0] = R8G8B8A8_UNORM;
 		p.sampleDesc.count = 1;
 		p.sampleDesc.count = 1;
+		p.sampleMask = -1;
 		p.inputLayout.inputElementDescs = inputLayout[0];
 		p.inputLayout.inputElementDescs = inputLayout[0];
 		p.inputLayout.numElements = inputLayout.length;
 		p.inputLayout.numElements = inputLayout.length;
 
 
-		var state = Driver.createGraphicsPipelineState(p);
-
 		var c = new CompiledShader();
 		var c = new CompiledShader();
 		c.inputNames = InputNames.get([for( v in inputs ) v.name]);
 		c.inputNames = InputNames.get([for( v in inputs ) v.name]);
-		c.pipeline = state;
+		c.pipeline = p;
 		c.rootSignature = sign;
 		c.rootSignature = sign;
+		c.inputLayout = inputLayout;
+		c.inputCount = inputs.length;
 		return c;
 		return c;
 	}
 	}
 
 
@@ -222,8 +253,7 @@ class DX12Driver extends h3d.impl.Driver {
 		if( currentShader == sh )
 		if( currentShader == sh )
 			return false;
 			return false;
 		currentShader = sh;
 		currentShader = sh;
-		frame.commandList.setPipelineState(sh.pipeline);
-		frame.commandList.setGraphicsRootSignature(sh.rootSignature);
+		needPipelineFlush = true;
 		return true;
 		return true;
 	}
 	}
 
 
@@ -364,21 +394,137 @@ class DX12Driver extends h3d.impl.Driver {
 		throw "TODO";
 		throw "TODO";
 	}
 	}
 
 
+	override function selectMaterial( pass : h3d.mat.Pass ) @:privateAccess {
+		needPipelineFlush = true;
+		pipelineSignature.setI32(PSIGN_MATID, pass.bits);
+		pipelineSignature.setUI8(PSIGN_COLOR_MASK, pass.colorMask);
+		var st = pass.stencil;
+		if( st != null ) {
+			pipelineSignature.setI32(PSIGN_STENCIL_MASK, st.maskBits);
+			pipelineSignature.setI32(PSIGN_STENCIL_OPS, st.opBits);
+		} else {
+			pipelineSignature.setI32(PSIGN_STENCIL_MASK, 0);
+			pipelineSignature.setI32(PSIGN_STENCIL_OPS, 0);
+		}
+	}
+
 	override function selectMultiBuffers(buffers:h3d.Buffer.BufferOffset) {
 	override function selectMultiBuffers(buffers:h3d.Buffer.BufferOffset) {
 		var views = tmp.vertexViews;
 		var views = tmp.vertexViews;
 		var bufferCount = 0;
 		var bufferCount = 0;
 		while( buffers != null ) {
 		while( buffers != null ) {
-			var v = views[bufferCount++];
+			var v = views[bufferCount];
 			var bview = @:privateAccess buffers.buffer.buffer.vbuf.view;
 			var bview = @:privateAccess buffers.buffer.buffer.vbuf.view;
 			v.bufferLocation = bview.bufferLocation;
 			v.bufferLocation = bview.bufferLocation;
 			v.sizeInBytes = bview.sizeInBytes;
 			v.sizeInBytes = bview.sizeInBytes;
 			v.strideInBytes = bview.strideInBytes;
 			v.strideInBytes = bview.strideInBytes;
+			pipelineSignature.setUI8(PSIGN_BUF_OFFSETS + bufferCount, buffers.offset);
 			buffers = buffers.next;
 			buffers = buffers.next;
+			bufferCount++;
 		}
 		}
+		needPipelineFlush = true;
 		frame.commandList.iaSetVertexBuffers(0, bufferCount, views[0]);
 		frame.commandList.iaSetVertexBuffers(0, bufferCount, views[0]);
 	}
 	}
 
 
+
+	static var CULL : Array<CullMode> = [NONE,BACK,FRONT,NONE];
+	static var BLEND_OP : Array<BlendOp> = [ADD,SUBTRACT,REV_SUBTRACT,MIN,MAX];
+	static var COMP : Array<ComparisonFunc> = [ALWAYS, NEVER, EQUAL, NOT_EQUAL, GREATER, GREATER_EQUAL, LESS, LESS_EQUAL];
+	static var BLEND : Array<Blend> = [
+		ONE,ZERO,SRC_ALPHA,SRC_COLOR,DEST_ALPHA,DEST_COLOR,INV_SRC_ALPHA,INV_SRC_COLOR,INV_DEST_ALPHA,INV_DEST_COLOR,
+		SRC1_COLOR,SRC1_ALPHA,INV_SRC1_COLOR,INV_SRC1_ALPHA,SRC_ALPHA_SAT
+	];
+	static var BLEND_ALPHA : Array<Blend> = [
+		ONE,ZERO,SRC_ALPHA,SRC_ALPHA,DEST_ALPHA,DEST_ALPHA,INV_SRC_ALPHA,INV_SRC_ALPHA,INV_DEST_ALPHA,INV_DEST_ALPHA,
+		SRC1_ALPHA,SRC1_ALPHA,INV_SRC1_ALPHA,INV_SRC1_ALPHA,SRC_ALPHA_SAT,
+	];
+
+	function makePipeline( shader : CompiledShader ) {
+		var p = shader.pipeline;
+		var passBits = pipelineSignature.getI32(PSIGN_MATID);
+		var colorMask = pipelineSignature.getUI8(PSIGN_COLOR_MASK);
+		var stencilMask = pipelineSignature.getI32(PSIGN_STENCIL_MASK) & 0xFFFFFF;
+		var stencilOp = pipelineSignature.getI32(PSIGN_STENCIL_OPS);
+
+		var csrc = Pass.getBlendSrc(passBits);
+		var cdst = Pass.getBlendDst(passBits);
+		var asrc = Pass.getBlendAlphaSrc(passBits);
+		var adst = Pass.getBlendAlphaDst(passBits);
+		var cop = Pass.getBlendOp(passBits);
+		var aop = Pass.getBlendAlphaOp(passBits);
+		var dw = Pass.getDepthWrite(passBits);
+		var cmp = Pass.getDepthTest(passBits);
+		var cull = Pass.getCulling(passBits);
+		var wire = Pass.getWireframe(passBits);
+		if( wire != 0 ) cull = 0;
+
+		p.numRenderTargets = renderTargetCount;
+		p.rasterizerState.cullMode = CULL[cull];
+		p.rasterizerState.fillMode = wire == 0 ? SOLID : WIREFRAME;
+		p.depthStencilDesc.depthEnable = cmp != 0;
+		p.depthStencilDesc.depthWriteMask = dw == 0 ? ZERO : ALL;
+		p.depthStencilDesc.depthFunc = COMP[cmp];
+
+		var bl = p.blendState;
+		for( i in 0...renderTargetCount ) {
+			var t = bl.renderTargets[i];
+			t.blendEnable = csrc != 0 || cdst != 1;
+			t.srcBlend = BLEND[csrc];
+			t.dstBlend = BLEND[cdst];
+			t.srcBlendAlpha = BLEND_ALPHA[asrc];
+			t.dstBlendAlpha = BLEND_ALPHA[adst];
+			t.blendOp = BLEND_OP[cop];
+			t.blendOpAlpha = BLEND_OP[aop];
+			t.renderTargetWriteMask = colorMask;
+		}
+		for( i in 0...shader.inputCount ) {
+			var d = shader.inputLayout[i];
+			d.alignedByteOffset = pipelineSignature.getUI8(PSIGN_BUF_OFFSETS + i) << 2;
+		}
+
+		if( stencilMask != 0 || stencilOp != 0 ) throw "TODO:stencil";
+
+		return Driver.createGraphicsPipelineState(p);
+	}
+
+	function flushPipeline() {
+		if( !needPipelineFlush ) return;
+		needPipelineFlush = false;
+		var signature = pipelineSignature;
+		var signatureSize = PSIGN_BUF_OFFSETS + currentShader.inputCount;
+		hl.Format.digest(adlerOut, signature, signatureSize, 3);
+		var hash = adlerOut.getI32(0);
+		var pipes = currentShader.pipelines.get(hash);
+		if( pipes == null )
+			pipes = new hl.NativeArray(1);
+		var insert = -1;
+		for( i in 0...pipes.length ) {
+			var p = pipes[i];
+			if( p == null ) {
+				insert = i;
+				break;
+			}
+			if( p.size == signatureSize && p.bytes.compare(0, signature, 0, signatureSize) == 0 ) {
+				frame.commandList.setPipelineState(p.pipeline);
+				return;
+			}
+		}
+		if( insert < 0 ) {
+			var pipes2 = new hl.NativeArray(pipes.length + 1);
+			pipes2.blit(0, pipes, 0, insert);
+			currentShader.pipelines.set(hash, pipes2);
+			pipes = pipes2;
+		}
+		var cp = new CachedPipeline();
+		cp.bytes = signature.sub(0, signatureSize);
+		cp.size = signatureSize;
+		cp.pipeline = makePipeline(currentShader);
+		pipes[insert] = cp;
+		frame.commandList.setGraphicsRootSignature(currentShader.rootSignature);
+		frame.commandList.setPipelineState(cp.pipeline);
+	}
+
 	override function draw( ibuf : IndexBuffer, startIndex : Int, ntriangles : Int ) {
 	override function draw( ibuf : IndexBuffer, startIndex : Int, ntriangles : Int ) {
+		flushPipeline();
 		frame.commandList.iaSetIndexBuffer(ibuf.view);
 		frame.commandList.iaSetIndexBuffer(ibuf.view);
 		frame.commandList.drawIndexedInstanced(ibuf.count,1,0,0,0);
 		frame.commandList.drawIndexedInstanced(ibuf.count,1,0,0,0);
 	}
 	}