From 87833dc3e2518c9174413ed33484c941628d3a46 Mon Sep 17 00:00:00 2001 From: Alexapp Date: Fri, 20 Sep 2024 17:41:40 +0300 Subject: [PATCH 1/4] Implementation of baseVertex support --- src/platform/graphics/webgpu/webgpu-graphics-device.js | 2 +- src/scene/batching/batch-manager.js | 7 +++++-- src/scene/mesh.js | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/platform/graphics/webgpu/webgpu-graphics-device.js b/src/platform/graphics/webgpu/webgpu-graphics-device.js index b8b54e06008..9f86999becb 100644 --- a/src/platform/graphics/webgpu/webgpu-graphics-device.js +++ b/src/platform/graphics/webgpu/webgpu-graphics-device.js @@ -535,7 +535,7 @@ class WebgpuGraphicsDevice extends GraphicsDevice { if (ib) { this.indexBuffer = null; passEncoder.setIndexBuffer(ib.impl.buffer, ib.impl.format); - passEncoder.drawIndexed(primitive.count, numInstances, primitive.base, 0, 0); + passEncoder.drawIndexed(primitive.count, numInstances, primitive.base, primitive.baseVertex || 0, 0); } else { passEncoder.draw(primitive.count, numInstances, primitive.base, 0); } diff --git a/src/scene/batching/batch-manager.js b/src/scene/batching/batch-manager.js index 1aad48cf211..d21558a85c8 100644 --- a/src/scene/batching/batch-manager.js +++ b/src/scene/batching/batch-manager.js @@ -659,7 +659,7 @@ class BatchManager { batch = new Batch(meshInstances, dynamic, batchGroupId); this._batchList.push(batch); - let indexBase, numIndices, indexData; + let indexBase, indexBaseVertex, numIndices, indexData; let verticesOffset = 0; let indexOffset = 0; let transform; @@ -738,6 +738,7 @@ class BatchManager { // index buffer if (mesh.primitive[0].indexed) { indexBase = mesh.primitive[0].base; + indexBaseVertex = mesh.primitive[0].baseVertex || 0; numIndices = mesh.primitive[0].count; // source index buffer data mapped to its format @@ -746,6 +747,8 @@ class BatchManager { } else { // non-indexed + indexBaseVertex = 0; + const primitiveType = mesh.primitive[0].type; if (primitiveType === PRIMITIVE_TRIFAN || primitiveType === PRIMITIVE_TRISTRIP) { if (mesh.primitive[0].count === 4) { @@ -760,7 +763,7 @@ class BatchManager { } for (let j = 0; j < numIndices; j++) { - indices[j + indexOffset] = indexData[indexBase + j] + verticesOffset; + indices[j + indexOffset] = indexData[indexBase + indexBaseVertex + j] + verticesOffset; } indexOffset += numIndices; diff --git a/src/scene/mesh.js b/src/scene/mesh.js index 1f113c16fa0..5443dee4bc0 100644 --- a/src/scene/mesh.js +++ b/src/scene/mesh.js @@ -202,10 +202,11 @@ class Mesh extends RefCountedObject { * * - `base` is the offset of the first index or vertex to dispatch in the draw call. * - `count` is the number of indices or vertices to dispatch in the draw call. + * - `baseVertex` is the number added to each index value before indexing into the vertex buffers. (available only for WebGPU and Batching) * - `indexed` specifies whether to interpret the primitive as indexed, thereby using the * currently set index buffer. * - * @type {{type: number, base: number, count: number, indexed?: boolean}[]} + * @type {{type: number, base: number, count: number, baseVertex?: number, indexed?: boolean}[]} */ primitive = [{ type: 0, From 3461a1c51c2d65dfd894329021ae591074a17b63 Mon Sep 17 00:00:00 2001 From: Alexapp Date: Fri, 20 Sep 2024 18:58:12 +0300 Subject: [PATCH 2/4] Code refactoring: https://github.com/playcanvas/engine/pull/6978#discussion_r1768797488 --- src/platform/graphics/webgpu/webgpu-graphics-device.js | 2 +- src/scene/batching/batch-manager.js | 2 +- src/scene/mesh.js | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/platform/graphics/webgpu/webgpu-graphics-device.js b/src/platform/graphics/webgpu/webgpu-graphics-device.js index 9f86999becb..cf91811ca0f 100644 --- a/src/platform/graphics/webgpu/webgpu-graphics-device.js +++ b/src/platform/graphics/webgpu/webgpu-graphics-device.js @@ -535,7 +535,7 @@ class WebgpuGraphicsDevice extends GraphicsDevice { if (ib) { this.indexBuffer = null; passEncoder.setIndexBuffer(ib.impl.buffer, ib.impl.format); - passEncoder.drawIndexed(primitive.count, numInstances, primitive.base, primitive.baseVertex || 0, 0); + passEncoder.drawIndexed(primitive.count, numInstances, primitive.base, primitive.baseVertex, 0); } else { passEncoder.draw(primitive.count, numInstances, primitive.base, 0); } diff --git a/src/scene/batching/batch-manager.js b/src/scene/batching/batch-manager.js index d21558a85c8..128afd43cd1 100644 --- a/src/scene/batching/batch-manager.js +++ b/src/scene/batching/batch-manager.js @@ -738,7 +738,7 @@ class BatchManager { // index buffer if (mesh.primitive[0].indexed) { indexBase = mesh.primitive[0].base; - indexBaseVertex = mesh.primitive[0].baseVertex || 0; + indexBaseVertex = mesh.primitive[0].baseVertex; numIndices = mesh.primitive[0].count; // source index buffer data mapped to its format diff --git a/src/scene/mesh.js b/src/scene/mesh.js index 5443dee4bc0..26d59fa447d 100644 --- a/src/scene/mesh.js +++ b/src/scene/mesh.js @@ -206,11 +206,12 @@ class Mesh extends RefCountedObject { * - `indexed` specifies whether to interpret the primitive as indexed, thereby using the * currently set index buffer. * - * @type {{type: number, base: number, count: number, baseVertex?: number, indexed?: boolean}[]} + * @type {{type: number, base: number, count: number, baseVertex: number, indexed?: boolean}[]} */ primitive = [{ type: 0, base: 0, + baseVertex: 0, count: 0 }]; From fed4c64ec32e7ca7b090c1f72a5a649afa5f55d3 Mon Sep 17 00:00:00 2001 From: Alexapp Date: Sat, 21 Sep 2024 21:28:42 +0300 Subject: [PATCH 3/4] Code refactoring, documentation clarification. --- src/extras/mini-stats/render2d.js | 1 + src/platform/graphics/transform-feedback.js | 1 + .../graphics/webgpu/webgpu-clear-renderer.js | 1 + .../graphics/webgpu/webgpu-graphics-device.js | 39 ++++++++++++++++++- src/scene/batching/batch-manager.js | 2 +- src/scene/graphics/quad-render.js | 1 + src/scene/mesh.js | 1 + 7 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/extras/mini-stats/render2d.js b/src/extras/mini-stats/render2d.js index 6ea48e47cee..9e1d8bb716d 100644 --- a/src/extras/mini-stats/render2d.js +++ b/src/extras/mini-stats/render2d.js @@ -91,6 +91,7 @@ class Render2d { type: PRIMITIVE_TRIANGLES, indexed: true, base: 0, + baseVertex: 0, count: 0 }; this.quads = 0; diff --git a/src/platform/graphics/transform-feedback.js b/src/platform/graphics/transform-feedback.js index 7592105a3bf..6c97ca505a0 100644 --- a/src/platform/graphics/transform-feedback.js +++ b/src/platform/graphics/transform-feedback.js @@ -158,6 +158,7 @@ class TransformFeedback { device.draw({ type: PRIMITIVE_POINTS, base: 0, + baseVertex: 0, count: this._inputBuffer.numVertices, indexed: false }); diff --git a/src/platform/graphics/webgpu/webgpu-clear-renderer.js b/src/platform/graphics/webgpu/webgpu-clear-renderer.js index 92f1fb53d7a..63515d0a1b3 100644 --- a/src/platform/graphics/webgpu/webgpu-clear-renderer.js +++ b/src/platform/graphics/webgpu/webgpu-clear-renderer.js @@ -16,6 +16,7 @@ import { DepthState } from '../depth-state.js'; const primitive = { type: PRIMITIVE_TRISTRIP, base: 0, + baseVertex: 0, count: 4, indexed: false }; diff --git a/src/platform/graphics/webgpu/webgpu-graphics-device.js b/src/platform/graphics/webgpu/webgpu-graphics-device.js index cf91811ca0f..7b7fca7760a 100644 --- a/src/platform/graphics/webgpu/webgpu-graphics-device.js +++ b/src/platform/graphics/webgpu/webgpu-graphics-device.js @@ -497,6 +497,43 @@ class WebgpuGraphicsDevice extends GraphicsDevice { _uniqueLocations.clear(); } + /** + * Submits a graphical primitive to the hardware for immediate rendering. + * + * @param {object} primitive - Primitive object describing how to submit current vertex/index + * buffers. + * @param {number} primitive.type - The type of primitive to render. Can be: + * + * - {@link PRIMITIVE_POINTS} + * - {@link PRIMITIVE_LINES} + * - {@link PRIMITIVE_LINELOOP} + * - {@link PRIMITIVE_LINESTRIP} + * - {@link PRIMITIVE_TRIANGLES} + * - {@link PRIMITIVE_TRISTRIP} + * - {@link PRIMITIVE_TRIFAN} + * + * @param {number} primitive.base - The offset of the first index or vertex to dispatch in the + * draw call. + * @param {number} primitive.baseVertex - The number added to each index value before indexing into + * the vertex buffers. + * @param {number} primitive.count - The number of indices or vertices to dispatch in the draw + * call. + * @param {boolean} [primitive.indexed] - True to interpret the primitive as indexed, thereby + * using the currently set index buffer and false otherwise. + * @param {number} [numInstances] - The number of instances to render when using instancing. + * Defaults to 1. + * @param {boolean} [keepBuffers] - Optionally keep the current set of vertex / index buffers / + * VAO. This is used when rendering of multiple views, for example under WebXR. + * @example + * // Render a single, unindexed triangle + * device.draw({ + * type: pc.PRIMITIVE_TRIANGLES, + * base: 0, + * baseVertex: 0, + * count: 3, + * indexed: false + * }); + */ draw(primitive, numInstances = 1, keepBuffers) { if (this.shader.ready && !this.shader.failed) { @@ -535,7 +572,7 @@ class WebgpuGraphicsDevice extends GraphicsDevice { if (ib) { this.indexBuffer = null; passEncoder.setIndexBuffer(ib.impl.buffer, ib.impl.format); - passEncoder.drawIndexed(primitive.count, numInstances, primitive.base, primitive.baseVertex, 0); + passEncoder.drawIndexed(primitive.count, numInstances, primitive.base, primitive.baseVertex || 0, 0); } else { passEncoder.draw(primitive.count, numInstances, primitive.base, 0); } diff --git a/src/scene/batching/batch-manager.js b/src/scene/batching/batch-manager.js index 128afd43cd1..d21558a85c8 100644 --- a/src/scene/batching/batch-manager.js +++ b/src/scene/batching/batch-manager.js @@ -738,7 +738,7 @@ class BatchManager { // index buffer if (mesh.primitive[0].indexed) { indexBase = mesh.primitive[0].base; - indexBaseVertex = mesh.primitive[0].baseVertex; + indexBaseVertex = mesh.primitive[0].baseVertex || 0; numIndices = mesh.primitive[0].count; // source index buffer data mapped to its format diff --git a/src/scene/graphics/quad-render.js b/src/scene/graphics/quad-render.js index cfd78623b1b..7e9d4a4339d 100644 --- a/src/scene/graphics/quad-render.js +++ b/src/scene/graphics/quad-render.js @@ -14,6 +14,7 @@ import { processShader } from '../shader-lib/utils.js'; const _quadPrimitive = { type: PRIMITIVE_TRISTRIP, base: 0, + baseVertex: 0, count: 4, indexed: false }; diff --git a/src/scene/mesh.js b/src/scene/mesh.js index 26d59fa447d..bcee0437fa5 100644 --- a/src/scene/mesh.js +++ b/src/scene/mesh.js @@ -1046,6 +1046,7 @@ class Mesh extends RefCountedObject { this.primitive[RENDERSTYLE_POINTS] = { type: PRIMITIVE_POINTS, base: 0, + baseVertex: 0, count: this.vertexBuffer ? this.vertexBuffer.numVertices : 0, indexed: false }; From 215258f61bf3599cd0f0052dd37e9d7998a4aca8 Mon Sep 17 00:00:00 2001 From: Alexapp Date: Sun, 22 Sep 2024 03:22:20 +0300 Subject: [PATCH 4/4] Fix batch baseVertex offset. --- src/scene/batching/batch-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scene/batching/batch-manager.js b/src/scene/batching/batch-manager.js index d21558a85c8..fa473048376 100644 --- a/src/scene/batching/batch-manager.js +++ b/src/scene/batching/batch-manager.js @@ -763,7 +763,7 @@ class BatchManager { } for (let j = 0; j < numIndices; j++) { - indices[j + indexOffset] = indexData[indexBase + indexBaseVertex + j] + verticesOffset; + indices[j + indexOffset] = indexData[indexBase + j] + indexBaseVertex + verticesOffset; } indexOffset += numIndices;