Bläddra i källkod

Improve MeshBatch.hx readability reordering methods.

clementlandrin 5 månader sedan
förälder
incheckning
f8e59be2bd
1 ändrade filer med 228 tillägg och 247 borttagningar
  1. 228 247
      h3d/scene/MeshBatch.hx

+ 228 - 247
h3d/scene/MeshBatch.hx

@@ -67,13 +67,14 @@ class MeshBatch extends MultiMaterial {
 	static var previousModelViewID = hxsl.Globals.allocID("global.previousModelView");
 	static var MAX_BUFFER_ELEMENTS = 4096;
 	static var MAX_STORAGE_BUFFER_ELEMENTS = 128 * 1024 * 1024 >> 2;
+	static var BATCH_START_FMT = hxd.BufferFormat.make([{ name : "Batch_Start", type : DFloat }]);
+	static var INDIRECT_DRAW_ARGUMENTS_FMT = hxd.BufferFormat.make([{ name : "", type : DVec4 }, { name : "", type : DFloat }]);
+	static var INSTANCE_OFFSETS_FMT = hxd.BufferFormat.make([{ name : "", type : DFloat }]);
 
 	var instanced : h3d.prim.Instanced;
 	var dataPasses : BatchData;
 	var needUpload = false;
 
-	public var lodDistance : Float;
-
 	public var meshBatchFlags(default, null) : haxe.EnumFlags<MeshBatchFlag>;
 	var enableLOD(get, never) : Bool;
 	function get_enableLOD() return meshBatchFlags.has( EnableLod );
@@ -117,6 +118,11 @@ class MeshBatch extends MultiMaterial {
 	**/
 	public var calcBounds = true;
 
+	/**
+	 * If set, this distance is used to compute screen ratio and lod on all the instances this frame
+	 */
+	public var lodDistance : Float;
+
 	var instancedParams : hxsl.Cache.BatchInstanceParams;
 	var emittedSubParts : Array<MeshBatchPart>;
 	var currentSubParts : Int;
@@ -135,62 +141,46 @@ class MeshBatch extends MultiMaterial {
 			@:privateAccess p.batchMode = true;
 	}
 
-	override function onRemove() {
-		super.onRemove();
-		cleanPasses();
-	}
+	public function begin( emitCountTip = -1, ?flags : haxe.EnumFlags<MeshBatchFlag> ) {
+		if ( flags != null ) {
+			#if (!js && !(hldx && !dx12))
+			var allowedLOD = flags.has(EnableLod) && ( primitiveSubPart != null || @:privateAccess instanced.primitive.lodCount() > 1 );
+			flags.setTo(EnableLod, allowedLOD);
+			#else
+			flags.setTo(EnableLod, false);
+			flags.setTo(EnableGpuCulling, false);
+			#end
+			// Set flags non-related to shaders
+			meshBatchFlags.setTo( EnableResizeDown, flags.has(EnableResizeDown) );
+			if ( meshBatchFlags != flags )
+				shadersChanged = true;
+			meshBatchFlags = flags;
+			meshBatchFlags.setTo( EnableStorageBuffer, mustCalcBufferFormat || useStorageBuffer );
+		}
 
-	inline function isCountBufferAllowed() {
-		#if hlsdl
-		return h3d.impl.GlDriver.hasMultiIndirectCount;
-		#else
-		return true;
-		#end
-	}
+		instanceCount = 0;
+		instanced.initBounds();
+		if( shadersChanged ) {
+			initShadersMapping();
+			shadersChanged = false;
+		}
 
-	function cleanPasses() {
+		if( emitCountTip < 0 )
+			emitCountTip = 128;
+		var p = dataPasses;
 		var alloc = hxd.impl.Allocator.get();
-		while( dataPasses != null ) {
-			dataPasses.pass.removeShader(dataPasses.shader);
-			for( b in dataPasses.buffers )
-				alloc.disposeBuffer(b);
-
-			if ( dataPasses.commandBuffers != null && dataPasses.commandBuffers.length > 0 ) {
-				@:privateAccess instanced.commands.data = null;
-				for ( buf in dataPasses.commandBuffers )
-					alloc.disposeBuffer(buf);
-				dataPasses.commandBuffers.resize(0);
-				for ( buf in dataPasses.countBuffers )
-					alloc.disposeBuffer(buf);
-				dataPasses.countBuffers.resize(0);
-				dataPasses.computePass = null;
-			}
-
-			if( dataPasses.instanceBuffers != null ) {
-				for( b in dataPasses.instanceBuffers )
-					b.dispose();
+		while( p != null ) {
+			var size = emitCountTip * p.paramsCount * 4;
+			if( p.data == null || p.data.length < size || ( meshBatchFlags.has(EnableResizeDown) && p.data.length > size << 1) ) {
+				if( p.data != null ) alloc.disposeFloats(p.data);
+				p.data = alloc.allocFloats(size);
 			}
-			alloc.disposeFloats(dataPasses.data);
-			dataPasses = dataPasses.next;
+			p = p.next;
 		}
-		if ( matInfos != null ) {
-			alloc.disposeBuffer(matInfos);
-			matInfos = null;
+		if ( primitiveSubPart != null && ( enableGPUCulling || enableLOD ) && instanceOffsetsCpu == null ) {
+			var size = emitCountTip * 2 * 4;
+			instanceOffsetsCpu = haxe.io.Bytes.alloc(size);
 		}
-		if( instanced.commands != null )
-			instanced.commands.dispose();
-
-		if ( subPartsInfos != null )
-			alloc.disposeBuffer(subPartsInfos);
-
-		if ( instanceOffsetsGpu != null )
-			alloc.disposeBuffer(instanceOffsetsGpu);
-		instanceOffsetsCpu = null;
-
-		primitiveSubBytes = null;
-		emittedSubParts = null;
-		countBytes = null;
-		shadersChanged = true;
 	}
 
 	function initShadersMapping() {
@@ -302,149 +292,6 @@ class MeshBatch extends MultiMaterial {
 		}
 	}
 
-	public function begin( emitCountTip = -1, ?flags : haxe.EnumFlags<MeshBatchFlag> ) {
-		if ( flags != null ) {
-			#if (!js && !(hldx && !dx12))
-			var allowedLOD = flags.has(EnableLod) && ( primitiveSubPart != null || @:privateAccess instanced.primitive.lodCount() > 1 );
-			flags.setTo(EnableLod, allowedLOD);
-			#else
-			flags.setTo(EnableLod, false);
-			flags.setTo(EnableGpuCulling, false);
-			#end
-			// Set flags non-related to shaders
-			meshBatchFlags.setTo( EnableResizeDown, flags.has(EnableResizeDown) );
-			if ( meshBatchFlags != flags )
-				shadersChanged = true;
-			meshBatchFlags = flags;
-			meshBatchFlags.setTo( EnableStorageBuffer, mustCalcBufferFormat || useStorageBuffer );
-		}
-
-		instanceCount = 0;
-		instanced.initBounds();
-		if( shadersChanged ) {
-			initShadersMapping();
-			shadersChanged = false;
-		}
-
-		if( emitCountTip < 0 )
-			emitCountTip = 128;
-		var p = dataPasses;
-		var alloc = hxd.impl.Allocator.get();
-		while( p != null ) {
-			var size = emitCountTip * p.paramsCount * 4;
-			if( p.data == null || p.data.length < size || ( meshBatchFlags.has(EnableResizeDown) && p.data.length > size << 1) ) {
-				if( p.data != null ) alloc.disposeFloats(p.data);
-				p.data = alloc.allocFloats(size);
-			}
-			p = p.next;
-		}
-		if ( primitiveSubPart != null && ( enableGPUCulling || enableLOD ) && instanceOffsetsCpu == null ) {
-			var size = emitCountTip * 2 * 4;
-			instanceOffsetsCpu = haxe.io.Bytes.alloc(size);
-		}
-	}
-
-	function syncData( batch : BatchData ) {
-
-		var startPos = batch.paramsCount * instanceCount << 2;
-		// in case we are bigger than emitCountTip
-		if( startPos + (batch.paramsCount<<2) > batch.data.length )
-			batch.data.grow(batch.data.length << 1);
-
-		var p = batch.params;
-		var buf = batch.data;
-		var shaders = batch.shaders;
-
-		var calcInv = false;
-		while( p != null ) {
-			var pos = startPos + p.pos;
-			inline function addMatrix(m:h3d.Matrix) {
-				buf[pos++] = m._11;
-				buf[pos++] = m._21;
-				buf[pos++] = m._31;
-				buf[pos++] = m._41;
-				buf[pos++] = m._12;
-				buf[pos++] = m._22;
-				buf[pos++] = m._32;
-				buf[pos++] = m._42;
-				buf[pos++] = m._13;
-				buf[pos++] = m._23;
-				buf[pos++] = m._33;
-				buf[pos++] = m._43;
-				buf[pos++] = m._14;
-				buf[pos++] = m._24;
-				buf[pos++] = m._34;
-				buf[pos++] = m._44;
-			}
-			if( p.perObjectGlobal != null ) {
-				if ( p.perObjectGlobal.gid == modelViewID ) {
-					addMatrix(worldPosition != null ? worldPosition : absPos);
-				} else if ( p.perObjectGlobal.gid == modelViewInverseID ) {
-					if( worldPosition == null )
-						addMatrix(getInvPos());
-					else {
-						if( !calcInv ) {
-							calcInv = true;
-							if( invWorldPosition == null ) invWorldPosition = new h3d.Matrix();
-							invWorldPosition.initInverse(worldPosition);
-						}
-						addMatrix(invWorldPosition);
-					}
-				} else if ( p.perObjectGlobal.gid == previousModelViewID )
-					addMatrix( worldPosition != null ? worldPosition : absPos );
-				else
-					throw "Unsupported global param "+p.perObjectGlobal.path;
-				p = p.next;
-				continue;
-			}
-			var curShader = shaders[p.instance];
-			switch( p.type ) {
-			case TVec(size, _):
-				switch( size ) {
-				case 2:
-					var v : h3d.Vector = curShader.getParamValue(p.index);
-					buf[pos++] = v.x;
-					buf[pos++] = v.y;
-				case 3:
-					var v : h3d.Vector = curShader.getParamValue(p.index);
-					buf[pos++] = v.x;
-					buf[pos++] = v.y;
-					buf[pos++] = v.z;
-				case 4:
-					var v : h3d.Vector4 = curShader.getParamValue(p.index);
-					buf[pos++] = v.x;
-					buf[pos++] = v.y;
-					buf[pos++] = v.z;
-					buf[pos++] = v.w;
-				}
-			case TFloat:
-				buf[pos++] = curShader.getParamFloatValue(p.index);
-			case TMat4:
-				var m : h3d.Matrix = curShader.getParamValue(p.index);
-				addMatrix(m);
-			default:
-				throw "Unsupported batch type "+p.type;
-			}
-			p = p.next;
-		}
-		needUpload = true;
-	}
-
-	override function addBoundsRec( b : h3d.col.Bounds, relativeTo: h3d.Matrix ) {
-		var old = primitive;
-		primitive = null;
-		super.addBoundsRec(b, relativeTo);
-		primitive = old;
-		if( primitive == null || flags.has(FIgnoreBounds) )
-			return;
-		// already transformed in absolute
-		var bounds = primitive.getBounds();
-		if( relativeTo == null )
-			b.add(bounds);
-		else
-			b.addTransform(bounds, relativeTo);
-	}
-
 	public function emitInstance() {
 		if( worldPosition == null ) syncPos();
 		var ps = primitiveSubPart;
@@ -513,38 +360,12 @@ class MeshBatch extends MultiMaterial {
 		instanceCount++;
 	}
 
-	public function disposeBuffers( useAllocator : Bool = true ) {
-		if( instanceCount == 0 ) return;
-		var p = dataPasses;
-		if ( useAllocator ) {
-			var alloc = hxd.impl.Allocator.get();
-			while( p != null ) {
-				for ( b in p.buffers )
-					alloc.disposeBuffer(b);
-				p.buffers.resize(0);
-				p = p.next;
-			}
-		} else {
-			while( p != null ) {
-				for ( b in p.buffers )
-					b.dispose();
-				p = p.next;
-			}
-		}
-	}
-
-	static var BATCH_START_FMT = hxd.BufferFormat.make([{ name : "Batch_Start", type : DFloat }]);
-	static var INDIRECT_DRAW_ARGUMENTS_FMT = hxd.BufferFormat.make([{ name : "", type : DVec4 }, { name : "", type : DFloat }]);
-	static var INSTANCE_OFFSETS_FMT = hxd.BufferFormat.make([{ name : "", type : DFloat }]);
-
 	override function sync(ctx:RenderContext) {
 		super.sync(ctx);
 		if( instanceCount == 0 ) return;
 		flush();
 	}
 
-	function addComputeShaders( pass : h3d.mat.Pass ) {}
-
 	public function flush() {
 		var p = dataPasses;
 		var alloc = hxd.impl.Allocator.get();
@@ -760,37 +581,90 @@ class MeshBatch extends MultiMaterial {
 		needUpload = false;
 	}
 
-	override function calcScreenRatio(ctx:RenderContext) {
-		curScreenRatio = @:privateAccess instanced.primitive.getBounds().dimension() / ( 2.0 * hxd.Math.max(lodDistance, 0.0001) );
-	}
+	function syncData( batch : BatchData ) {
 
-	override function draw(ctx:RenderContext) {
-		var p = dataPasses;
-		while( true ) {
-			if( p.pass == ctx.drawPass.pass ) {
-				var bufferIndex = ctx.drawPass.index & 0xFFFF;
-				if ( useStorageBuffer )
-					p.shader.Batch_StorageBuffer = p.buffers[bufferIndex];
-				else
-					p.shader.Batch_Buffer = p.buffers[bufferIndex];
-				if( p.instanceBuffers == null ) {
-					var count = hxd.Math.imin( instanceCount - p.maxInstance * bufferIndex, p.maxInstance );
-					instanced.setCommand(p.matIndex, instanced.screenRatioToLod(curScreenRatio), count);
-					if ( p.commandBuffers != null && p.commandBuffers.length > 0 ) {
-						@:privateAccess instanced.commands.data = p.commandBuffers[bufferIndex].vbuf;
-						@:privateAccess instanced.commands.countBuffer = p.countBuffers[bufferIndex].vbuf;
+		var startPos = batch.paramsCount * instanceCount << 2;
+		// in case we are bigger than emitCountTip
+		if( startPos + (batch.paramsCount<<2) > batch.data.length )
+			batch.data.grow(batch.data.length << 1);
+
+		var p = batch.params;
+		var buf = batch.data;
+		var shaders = batch.shaders;
+
+		var calcInv = false;
+		while( p != null ) {
+			var pos = startPos + p.pos;
+			inline function addMatrix(m:h3d.Matrix) {
+				buf[pos++] = m._11;
+				buf[pos++] = m._21;
+				buf[pos++] = m._31;
+				buf[pos++] = m._41;
+				buf[pos++] = m._12;
+				buf[pos++] = m._22;
+				buf[pos++] = m._32;
+				buf[pos++] = m._42;
+				buf[pos++] = m._13;
+				buf[pos++] = m._23;
+				buf[pos++] = m._33;
+				buf[pos++] = m._43;
+				buf[pos++] = m._14;
+				buf[pos++] = m._24;
+				buf[pos++] = m._34;
+				buf[pos++] = m._44;
+			}
+			if( p.perObjectGlobal != null ) {
+				if ( p.perObjectGlobal.gid == modelViewID ) {
+					addMatrix(worldPosition != null ? worldPosition : absPos);
+				} else if ( p.perObjectGlobal.gid == modelViewInverseID ) {
+					if( worldPosition == null )
+						addMatrix(getInvPos());
+					else {
+						if( !calcInv ) {
+							calcInv = true;
+							if( invWorldPosition == null ) invWorldPosition = new h3d.Matrix();
+							invWorldPosition.initInverse(worldPosition);
+						}
+						addMatrix(invWorldPosition);
 					}
-				} else
-					instanced.commands = p.instanceBuffers[bufferIndex];
-				break;
+				} else if ( p.perObjectGlobal.gid == previousModelViewID )
+					addMatrix( worldPosition != null ? worldPosition : absPos );
+				else
+					throw "Unsupported global param "+p.perObjectGlobal.path;
+				p = p.next;
+				continue;
+			}
+			var curShader = shaders[p.instance];
+			switch( p.type ) {
+			case TVec(size, _):
+				switch( size ) {
+				case 2:
+					var v : h3d.Vector = curShader.getParamValue(p.index);
+					buf[pos++] = v.x;
+					buf[pos++] = v.y;
+				case 3:
+					var v : h3d.Vector = curShader.getParamValue(p.index);
+					buf[pos++] = v.x;
+					buf[pos++] = v.y;
+					buf[pos++] = v.z;
+				case 4:
+					var v : h3d.Vector4 = curShader.getParamValue(p.index);
+					buf[pos++] = v.x;
+					buf[pos++] = v.y;
+					buf[pos++] = v.z;
+					buf[pos++] = v.w;
+				}
+			case TFloat:
+				buf[pos++] = curShader.getParamFloatValue(p.index);
+			case TMat4:
+				var m : h3d.Matrix = curShader.getParamValue(p.index);
+				addMatrix(m);
+			default:
+				throw "Unsupported batch type "+p.type;
 			}
 			p = p.next;
 		}
-		ctx.uploadParams();
-		var prev = ctx.drawPass.index;
-		ctx.drawPass.index >>= 16;
-		super.draw(ctx);
-		ctx.drawPass.index = prev;
+		needUpload = true;
 	}
 
 	override function emit(ctx:RenderContext) {
@@ -832,4 +706,111 @@ class MeshBatch extends MultiMaterial {
 		}
 	}
 
+	override function draw(ctx:RenderContext) {
+		var p = dataPasses;
+		while( true ) {
+			if( p.pass == ctx.drawPass.pass ) {
+				var bufferIndex = ctx.drawPass.index & 0xFFFF;
+				if ( useStorageBuffer )
+					p.shader.Batch_StorageBuffer = p.buffers[bufferIndex];
+				else
+					p.shader.Batch_Buffer = p.buffers[bufferIndex];
+				if( p.instanceBuffers == null ) {
+					var count = hxd.Math.imin( instanceCount - p.maxInstance * bufferIndex, p.maxInstance );
+					instanced.setCommand(p.matIndex, instanced.screenRatioToLod(curScreenRatio), count);
+					if ( p.commandBuffers != null && p.commandBuffers.length > 0 ) {
+						@:privateAccess instanced.commands.data = p.commandBuffers[bufferIndex].vbuf;
+						@:privateAccess instanced.commands.countBuffer = p.countBuffers[bufferIndex].vbuf;
+					}
+				} else
+					instanced.commands = p.instanceBuffers[bufferIndex];
+				break;
+			}
+			p = p.next;
+		}
+		ctx.uploadParams();
+		var prev = ctx.drawPass.index;
+		ctx.drawPass.index >>= 16;
+		super.draw(ctx);
+		ctx.drawPass.index = prev;
+	}
+
+	override function calcScreenRatio(ctx:RenderContext) {
+		curScreenRatio = @:privateAccess instanced.primitive.getBounds().dimension() / ( 2.0 * hxd.Math.max(lodDistance, 0.0001) );
+	}
+
+	override function addBoundsRec( b : h3d.col.Bounds, relativeTo: h3d.Matrix ) {
+		var old = primitive;
+		primitive = null;
+		super.addBoundsRec(b, relativeTo);
+		primitive = old;
+		if( primitive == null || flags.has(FIgnoreBounds) )
+			return;
+		// already transformed in absolute
+		var bounds = primitive.getBounds();
+		if( relativeTo == null )
+			b.add(bounds);
+		else
+			b.addTransform(bounds, relativeTo);
+	}
+
+	function addComputeShaders( pass : h3d.mat.Pass ) {}
+
+	inline function isCountBufferAllowed() {
+		#if hlsdl
+		return h3d.impl.GlDriver.hasMultiIndirectCount;
+		#else
+		return true;
+		#end
+	}
+
+	function cleanPasses() {
+		var alloc = hxd.impl.Allocator.get();
+		while( dataPasses != null ) {
+			dataPasses.pass.removeShader(dataPasses.shader);
+			for( b in dataPasses.buffers )
+				alloc.disposeBuffer(b);
+
+			if ( dataPasses.commandBuffers != null && dataPasses.commandBuffers.length > 0 ) {
+				@:privateAccess instanced.commands.data = null;
+				for ( buf in dataPasses.commandBuffers )
+					alloc.disposeBuffer(buf);
+				dataPasses.commandBuffers.resize(0);
+				for ( buf in dataPasses.countBuffers )
+					alloc.disposeBuffer(buf);
+				dataPasses.countBuffers.resize(0);
+				dataPasses.computePass = null;
+			}
+
+			if( dataPasses.instanceBuffers != null ) {
+				for( b in dataPasses.instanceBuffers )
+					b.dispose();
+			}
+			alloc.disposeFloats(dataPasses.data);
+			dataPasses = dataPasses.next;
+		}
+		if ( matInfos != null ) {
+			alloc.disposeBuffer(matInfos);
+			matInfos = null;
+		}
+		if( instanced.commands != null )
+			instanced.commands.dispose();
+
+		if ( subPartsInfos != null )
+			alloc.disposeBuffer(subPartsInfos);
+
+		if ( instanceOffsetsGpu != null )
+			alloc.disposeBuffer(instanceOffsetsGpu);
+		instanceOffsetsCpu = null;
+
+		primitiveSubBytes = null;
+		emittedSubParts = null;
+		countBytes = null;
+		shadersChanged = true;
+	}
+
+	override function onRemove() {
+		super.onRemove();
+		cleanPasses();
+	}
 }