Browse Source

WebGPURenderer: extract common draw call logic from backends (#29358)

* draw params

* add missing return

---------

Co-authored-by: aardgoose <angus.sawyer@email.com>
aardgoose 2 weeks ago
parent
commit
10a7df8500

+ 56 - 0
src/renderers/common/RenderObject.js

@@ -61,6 +61,7 @@ export default class RenderObject {
 		this.attributes = null;
 		this.pipeline = null;
 		this.vertexBuffers = null;
+		this.drawParams = null;
 
 		this.updateClipping( renderContext.clippingContext );
 
@@ -183,6 +184,61 @@ export default class RenderObject {
 
 	}
 
+	getDrawParameters() {
+
+		const { object, material, geometry, group, drawRange } = this;
+
+		const drawParams = this.drawParams || ( this.drawParams = {
+			vertexCount: 0,
+			firstVertex: 0,
+			instanceCount: 0,
+			firstInstance: 0
+		} );
+
+		const index = this.getIndex();
+		const hasIndex = ( index !== null );
+		const instanceCount = geometry.isInstancedBufferGeometry ? geometry.instanceCount : ( object.count > 1 ? object.count : 1 );
+
+		if ( instanceCount === 0 ) return null;
+
+		drawParams.instanceCount = instanceCount;
+
+		if ( object.isBatchedMesh === true ) return drawParams;
+
+		let rangeFactor = 1;
+
+		if ( material.wireframe === true && ! object.isPoints && ! object.isLineSegments && ! object.isLine && ! object.isLineLoop ) {
+
+			rangeFactor = 2;
+
+		}
+
+		let firstVertex = drawRange.start * rangeFactor;
+		let lastVertex = ( drawRange.start + drawRange.count ) * rangeFactor;
+
+		if ( group !== null ) {
+
+			firstVertex = Math.max( firstVertex, group.start * rangeFactor );
+			lastVertex = Math.min( lastVertex, ( group.start + group.count ) * rangeFactor );
+
+		}
+
+		const itemCount = hasIndex === true ? index.count : geometry.attributes.position.count;
+
+		firstVertex = Math.max( firstVertex, 0 );
+		lastVertex = Math.min( lastVertex, itemCount );
+
+		const count = lastVertex - firstVertex;
+
+		if ( count < 0 || count === Infinity ) return null;
+
+		drawParams.vertexCount = count;
+		drawParams.firstVertex = firstVertex;
+
+		return drawParams;
+
+	}
+
 	getMaterialCacheKey() {
 
 		const { object, material } = this;

+ 10 - 43
src/renderers/webgl-fallback/WebGLBackend.js

@@ -597,6 +597,10 @@ class WebGLBackend extends Backend {
 
 		const contextData = this.get( context );
 
+		const drawParms = renderObject.getDrawParameters();
+
+		if ( drawParms === null ) return;
+
 		//
 
 		this._bindUniforms( renderObject.getBindings() );
@@ -635,9 +639,6 @@ class WebGLBackend extends Backend {
 
 		const index = renderObject.getIndex();
 
-		const geometry = renderObject.geometry;
-		const drawRange = renderObject.drawRange;
-
 		//
 
 		const lastObject = contextData.lastOcclusionObject;
@@ -668,8 +669,6 @@ class WebGLBackend extends Backend {
 		}
 
 		//
-		let rangeFactor = 1;
-
 		const renderer = this.bufferRenderer;
 
 		if ( object.isPoints ) renderer.mode = gl.POINTS;
@@ -683,8 +682,6 @@ class WebGLBackend extends Backend {
 				state.setLineWidth( material.wireframeLinewidth * this.renderer.getPixelRatio() );
 				renderer.mode = gl.LINES;
 
-				rangeFactor = 2;
-
 			} else {
 
 				renderer.mode = gl.TRIANGLES;
@@ -695,56 +692,26 @@ class WebGLBackend extends Backend {
 
 		//
 
-		const group = renderObject.group;
-
+		const { vertexCount, instanceCount } = drawParms;
+		let { firstVertex } = drawParms;
 
 		renderer.object = object;
 
-
-		let firstVertex = drawRange.start * rangeFactor;
-		let lastVertex = ( drawRange.start + drawRange.count ) * rangeFactor;
-
-		if ( group !== null ) {
-
-			firstVertex = Math.max( firstVertex, group.start * rangeFactor );
-			lastVertex = Math.min( lastVertex, ( group.start + group.count ) * rangeFactor );
-
-		}
-
 		if ( index !== null ) {
 
+			firstVertex *= index.array.BYTES_PER_ELEMENT;
+
 			const indexData = this.get( index );
-			const indexCount = index.count;
 
 			renderer.index = index.count;
 			renderer.type = indexData.type;
 
-			firstVertex = Math.max( firstVertex, 0 );
-			lastVertex = Math.min( lastVertex, indexCount );
-
 		} else {
 
 			renderer.index = 0;
 
-			const vertexCount = geometry.attributes.position.count;
-
-			firstVertex = Math.max( firstVertex, 0 );
-			lastVertex = Math.min( lastVertex, vertexCount );
-
 		}
 
-		const count = lastVertex - firstVertex;
-
-		if ( count < 0 || count === Infinity ) return;
-
-		if ( index !== null ) {
-
-			firstVertex *= index.array.BYTES_PER_ELEMENT;
-
-		}
-
-		const instanceCount = this.getInstanceCount( renderObject );
-
 		if ( object.isBatchedMesh ) {
 
 			if ( object._multiDrawInstances !== null ) {
@@ -763,11 +730,11 @@ class WebGLBackend extends Backend {
 
 		} else if ( instanceCount > 1 ) {
 
-			renderer.renderInstances( firstVertex, count, instanceCount );
+			renderer.renderInstances( firstVertex, vertexCount, instanceCount );
 
 		} else {
 
-			renderer.render( firstVertex, count );
+			renderer.render( firstVertex, vertexCount );
 
 		}
 		//

+ 9 - 45
src/renderers/webgpu/WebGPUBackend.js

@@ -829,13 +829,17 @@ class WebGPUBackend extends Backend {
 
 	draw( renderObject, info ) {
 
-		const { object, material, geometry, context, pipeline, group } = renderObject;
+		const { object, context, pipeline } = renderObject;
 		const bindings = renderObject.getBindings();
 		const renderContextData = this.get( context );
 		const pipelineGPU = this.get( pipeline ).pipeline;
 		const currentSets = renderContextData.currentSets;
 		const passEncoderGPU = renderContextData.currentPass;
 
+		const drawParms = renderObject.getDrawParameters();
+
+		if ( drawParms === null ) return;
+
 		// pipeline
 
 		if ( currentSets.pipeline !== pipelineGPU ) {
@@ -936,31 +940,6 @@ class WebGPUBackend extends Backend {
 
 		// draw
 
-		const drawRange = renderObject.drawRange;
-
-		let rangeFactor = 1;
-
-		if ( material.wireframe === true && ! object.isPoints && ! object.isLineSegments && ! object.isLine && ! object.isLineLoop ) {
-
-			rangeFactor = 2;
-
-		}
-
-		let firstVertex = drawRange.start * rangeFactor;
-		let lastVertex = ( drawRange.start + drawRange.count ) * rangeFactor;
-
-		if ( group !== null ) {
-
-			firstVertex = Math.max( firstVertex, group.start * rangeFactor );
-			lastVertex = Math.min( lastVertex, ( group.start + group.count ) * rangeFactor );
-
-		}
-
-
-
-		const instanceCount = this.getInstanceCount( renderObject );
-		if ( instanceCount === 0 ) return;
-
 		if ( object.isBatchedMesh === true ) {
 
 			const starts = object._multiDrawStarts;
@@ -981,32 +960,17 @@ class WebGPUBackend extends Backend {
 
 		} else if ( hasIndex === true ) {
 
-			const indexCount = index.count;
-
-			firstVertex = Math.max( firstVertex, 0 );
-			lastVertex = Math.min( lastVertex, indexCount );
+			const { vertexCount: indexCount, instanceCount, firstVertex: firstIndex } = drawParms;
 
-			const count = lastVertex - firstVertex;
-
-			if ( count < 0 || count === Infinity ) return;
-
-			passEncoderGPU.drawIndexed( count, instanceCount, firstVertex, 0, 0 );
+			passEncoderGPU.drawIndexed( indexCount, instanceCount, firstIndex, 0, 0 );
 
 			info.update( object, indexCount, instanceCount );
 
 		} else {
 
-			const positionAttribute = geometry.attributes.position;
-			const vertexCount = positionAttribute.count;
-
-			firstVertex = Math.max( firstVertex, 0 );
-			lastVertex = Math.min( lastVertex, vertexCount );
-
-			const count = lastVertex - firstVertex;
-
-			if ( count < 0 || count === Infinity ) return;
+			const { vertexCount, instanceCount, firstVertex } = drawParms;
 
-			passEncoderGPU.draw( count, instanceCount, firstVertex, 0 );
+			passEncoderGPU.draw( vertexCount, instanceCount, firstVertex, 0 );
 
 			info.update( object, vertexCount, instanceCount );