Pārlūkot izejas kodu

more directx support

ncannasse 8 gadi atpakaļ
vecāks
revīzija
55422f2c56
2 mainītis faili ar 130 papildinājumiem un 21 dzēšanām
  1. 129 20
      h3d/impl/DirectXDriver.hx
  2. 1 1
      h3d/impl/Driver.hx

+ 129 - 20
h3d/impl/DirectXDriver.hx

@@ -7,6 +7,7 @@ private class ShaderContext {
 	public var shader : Shader;
 	public var globalsSize : Int;
 	public var paramsSize : Int;
+	public var texturesCount : Int;
 	public var globals : dx.Resource;
 	public var params : dx.Resource;
 	public function new(shader) {
@@ -22,12 +23,26 @@ private class CompiledShader {
 	}
 }
 
+enum PipelineKind {
+	Vertex;
+	Pixel;
+}
+
+class PipelineState {
+	public var kind : PipelineKind;
+	public var samplers = new hl.NativeArray<SamplerState>(64);
+	public var resources = new hl.NativeArray<ShaderResourceView>(64);
+	public var buffers = new hl.NativeArray<dx.Resource>(16);
+	public function new(kind) {
+		this.kind = kind;
+	}
+}
+
 class DirectXDriver extends h3d.impl.Driver {
 
 	var driver : DriverInstance;
 	var shaders : Map<Int,CompiledShader>;
 	var box = new dx.Resource.ResourceBox();
-	var buffers = new hl.NativeArray<dx.Resource>(16);
 	var strides : Array<Int> = [];
 	var zeroes : Array<Int> = [for( i in 0...16 ) 0];
 	var currentShader : CompiledShader;
@@ -37,6 +52,10 @@ class DirectXDriver extends h3d.impl.Driver {
 	var currentTargets = new hl.NativeArray<RenderTargetView>(16);
 	var viewport : hl.BytesAccess<hl.F32> = new hl.Bytes(6 * 4);
 	var depthView : DepthStencilView;
+	var vertexShader = new PipelineState(Vertex);
+	var pixelShader = new PipelineState(Pixel);
+	var buffers = new hl.NativeArray<dx.Resource>(16);
+	var frame : Int;
 
 	public function new() {
 		shaders = new Map();
@@ -82,12 +101,10 @@ class DirectXDriver extends h3d.impl.Driver {
 		desc.depthClipEnable = true;
 		var rs = Driver.createRasterizerState(desc);
 		Driver.rsSetState(rs);
+	}
 
-		var desc = new SamplerStateDesc();
-		var ss = Driver.createSamplerState(desc);
-		var sarr = new hl.NativeArray(1);
-		sarr[0] = ss;
-		Driver.psSetSamplers(0, 1, sarr);
+	override function begin(frame:Int) {
+		this.frame = frame;
 	}
 
 	override function isDisposed() {
@@ -131,14 +148,22 @@ class DirectXDriver extends h3d.impl.Driver {
 		desc.usage = Default;
 		desc.bind = ShaderResource;
 		var tex = Driver.createTexture2d(desc);
-		return tex;
+
+		var vdesc = new ShaderResourceViewDesc();
+		vdesc.format = desc.format;
+		vdesc.dimension = Texture2D;
+		vdesc.start = 0; // top mip level
+		vdesc.count = -1; // all mip levels
+		var view = Driver.createShaderResourceView(tex, vdesc);
+		return { res : tex, view : view };
 	}
 
 	override function disposeTexture( t : h3d.mat.Texture ) {
 		var tt = t.t;
 		if( tt == null ) return;
 		t.t = null;
-		tt.release();
+		tt.view.release();
+		tt.res.release();
 	}
 
 	override function disposeVertexes(v:VertexBuffer) {
@@ -167,6 +192,18 @@ class DirectXDriver extends h3d.impl.Driver {
 		throw "TODO";
 	}
 
+	override function uploadTextureBitmap(t:h3d.mat.Texture, bmp:hxd.BitmapData, mipLevel:Int, side:Int) {
+		var pixels = bmp.getPixels();
+		uploadTexturePixels(t, pixels, mipLevel, side);
+		pixels.dispose();
+	}
+
+	override function uploadTexturePixels(t:h3d.mat.Texture, pixels:hxd.Pixels, mipLevel:Int, side:Int) {
+		if( mipLevel != 0 || side != 0 ) throw "TODO";
+		pixels.convert(RGBA);
+		t.t.res.updateSubresource(0, null, pixels.bytes, pixels.width << 2, 0);
+	}
+
 	function compileShader( shader : hxsl.RuntimeShader.RuntimeShaderData, compileOnly = false ) {
 		var h = new hxsl.HlslOut();
 		var source = h.run(shader.data);
@@ -187,6 +224,7 @@ class DirectXDriver extends h3d.impl.Driver {
 		var ctx = new ShaderContext(s);
 		ctx.globalsSize = shader.globalsSize;
 		ctx.paramsSize = shader.paramsSize;
+		ctx.texturesCount = shader.textures2DCount + shader.texturesCubeCount;
 		ctx.globals = dx.Driver.createBuffer(shader.globalsSize * 16, Dynamic, ConstantBuffer, CpuWrite, None, 0, null);
 		ctx.params = dx.Driver.createBuffer(shader.paramsSize * 16, Dynamic, ConstantBuffer, CpuWrite, None, 0, null);
 		return { s : ctx, bytes : bytes };
@@ -266,23 +304,94 @@ class DirectXDriver extends h3d.impl.Driver {
 	}
 
 	override function uploadShaderBuffers(buffers:h3d.shader.Buffers, which:h3d.shader.Buffers.BufferKind) {
+		uploadBuffers(vertexShader, currentShader.vertex, buffers.vertex, which);
+		uploadBuffers(pixelShader, currentShader.fragment, buffers.fragment, which);
+	}
+
+	function uploadBuffers( state : PipelineState, shader : ShaderContext, buffers : h3d.shader.Buffers.ShaderBuffers, which : h3d.shader.Buffers.BufferKind ) {
 		switch( which ) {
 		case Globals:
-			uploadShaderBuffer(currentShader.vertex.globals, buffers.vertex.globals, currentShader.vertex.globalsSize);
-			uploadShaderBuffer(currentShader.fragment.globals, buffers.fragment.globals, currentShader.fragment.globalsSize);
-			this.buffers[0] = currentShader.vertex.globals;
-			Driver.vsSetConstantBuffers(0, 1, this.buffers);
-			this.buffers[0] = currentShader.fragment.globals;
-			Driver.psSetConstantBuffers(0, 1, this.buffers);
+			if( shader.globalsSize > 0 ) {
+				uploadShaderBuffer(shader.globals, buffers.globals, shader.globalsSize);
+				if( state.buffers[0] != shader.globals ) {
+					state.buffers[0] = shader.globals;
+					switch( state.kind ) {
+					case Vertex:
+						Driver.vsSetConstantBuffers(0, 1, state.buffers, 0);
+					case Pixel:
+						Driver.psSetConstantBuffers(0, 1, state.buffers, 0);
+					}
+				}
+			}
 		case Params:
-			uploadShaderBuffer(currentShader.vertex.params, buffers.vertex.params, currentShader.vertex.paramsSize);
-			uploadShaderBuffer(currentShader.fragment.params, buffers.fragment.params, currentShader.fragment.paramsSize);
-			this.buffers[0] = currentShader.vertex.params;
-			Driver.vsSetConstantBuffers(1, 1, this.buffers);
-			this.buffers[0] = currentShader.fragment.params;
-			Driver.psSetConstantBuffers(1, 1, this.buffers);
+			if( shader.paramsSize > 0 ) {
+				uploadShaderBuffer(shader.params, buffers.params, shader.paramsSize);
+				if( state.buffers[1] != shader.params ) {
+					state.buffers[1] = shader.params;
+					switch( state.kind ) {
+					case Vertex:
+						Driver.vsSetConstantBuffers(1, 1, state.buffers, 1);
+					case Pixel:
+						Driver.psSetConstantBuffers(1, 1, state.buffers, 1);
+					}
+				}
+			}
 		case Textures:
+			var start = -1, max = -1;
+			var sstart = -1, smax = -1;
+			for( i in 0...shader.texturesCount ) {
+				var t = buffers.tex[i];
+				if( t == null || t.isDisposed() ) {
+					var color = h3d.mat.Defaults.loadingTextureColor;
+					t = h3d.mat.Texture.fromColor(color,(color>>>24)/255);
+				}
+				if( t != null && t.t == null && t.realloc != null ) {
+					t.alloc();
+					t.realloc();
+				}
+				t.lastFrame = frame;
+
+				var view = t.t.view;
+				if( view == state.resources[i] ) continue;
+
+				state.resources[i] = view;
+				max = i;
+				if( start < 0 ) start = i;
+
+				// make sampler state
+				var ss = getTextureSampler(t);
+				if( state.samplers[i] == ss ) continue;
+
+				state.samplers[i] = ss;
+				smax = i;
+				if( sstart < 0 ) sstart = i;
+			}
+			switch( state.kind) {
+			case Vertex:
+				if( max >= 0 ) Driver.vsSetShaderResources(start, max - start + 1, state.resources, start);
+				if( smax >= 0 ) Driver.vsSetSamplers(sstart, smax - sstart + 1, state.samplers, sstart);
+			case Pixel:
+				if( max >= 0 ) Driver.psSetShaderResources(start, max - start + 1, state.resources, start);
+				if( smax >= 0 ) Driver.psSetSamplers(sstart, smax - sstart + 1, state.samplers, sstart);
+			}
+		}
+	}
+
+
+	var defSampler : SamplerState;
+	function getTextureSampler( t : h3d.mat.Texture ) {
+		if( defSampler == null ) {
+			var desc = new SamplerDesc();
+			desc.filter = MinMagMipLinear;
+			desc.addressU = Wrap;
+			desc.addressV = Wrap;
+			desc.addressW = Wrap;
+			desc.maxAnisotropy = 1;
+			desc.comparisonFunc = Always;
+			desc.maxLod = 1e32;
+			defSampler = Driver.createSamplerState(desc);
 		}
+		return defSampler;
 	}
 
 	override function draw(ibuf:IndexBuffer, startIndex:Int, ntriangles:Int) {

+ 1 - 1
h3d/impl/Driver.hx

@@ -39,7 +39,7 @@ typedef Query = { q : psgl.GL.Query, kind : QueryKind };
 #elseif hldx
 typedef IndexBuffer = dx.Resource;
 typedef VertexBuffer = dx.Resource;
-typedef Texture = dx.Resource;
+typedef Texture = { res : dx.Resource, view : dx.Driver.ShaderResourceView };
 typedef DepthBuffer = dx.Driver.DepthStencilView;
 typedef Query = {};
 #else