Skip to content

Commit

Permalink
Fix to WebGPU vertex buffer setup (#6274)
Browse files Browse the repository at this point in the history
Co-authored-by: Martin Valigursky <mvaligursky@snapchat.com>
  • Loading branch information
mvaligursky and Martin Valigursky authored Apr 23, 2024
1 parent 3a577bc commit 518b986
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 3 deletions.
2 changes: 1 addition & 1 deletion examples/src/examples/graphics/mesh-morph-many/config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
* @type {import('../../../../types.mjs').ExampleConfig}
*/
export default {
WEBGPU_ENABLED: false
WEBGPU_ENABLED: true
};
36 changes: 34 additions & 2 deletions src/platform/graphics/webgpu/webgpu-graphics-device.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { path } from '../../../core/path.js';

import {
PIXELFORMAT_RGBA32F, PIXELFORMAT_RGBA8, PIXELFORMAT_BGRA8, DEVICETYPE_WEBGPU,
BUFFERUSAGE_READ, BUFFERUSAGE_COPY_DST
BUFFERUSAGE_READ, BUFFERUSAGE_COPY_DST, semanticToLocation
} from '../constants.js';
import { GraphicsDevice } from '../graphics-device.js';
import { DebugGraphics } from '../debug-graphics.js';
Expand All @@ -30,6 +30,8 @@ import { WebgpuResolver } from './webgpu-resolver.js';
import { WebgpuCompute } from './webgpu-compute.js';
import { WebgpuBuffer } from './webgpu-buffer.js';

const _uniqueLocations = new Map();

class WebgpuGraphicsDevice extends GraphicsDevice {
/**
* Object responsible for caching and creation of render pipelines.
Expand Down Expand Up @@ -452,16 +454,45 @@ class WebgpuGraphicsDevice extends GraphicsDevice {

submitVertexBuffer(vertexBuffer, slot) {

const elements = vertexBuffer.format.elements;
const format = vertexBuffer.format;
const { interleaved, elements } = format;
const elementCount = elements.length;
const vbBuffer = vertexBuffer.impl.buffer;

if (interleaved) {
// for interleaved buffers, we use a single vertex buffer, and attributes are specified using the layout
this.passEncoder.setVertexBuffer(slot, vbBuffer);
return 1;
}

// non-interleaved - vertex buffer per attribute
for (let i = 0; i < elementCount; i++) {
this.passEncoder.setVertexBuffer(slot + i, vbBuffer, elements[i].offset);
}

return elementCount;
}

validateVBLocations(vb0, vb1) {

// in case of multiple VBs, validate all elements use unique locations
const validateVB = (vb) => {
const { elements } = vb.format;
for (let i = 0; i < elements.length; i++) {
const name = elements[i].name;
const location = semanticToLocation[name];
if (_uniqueLocations.has(location)) {
Debug.errorOnce(`Vertex buffer element location ${location} used by [${name}] is already used by element [${_uniqueLocations.get(location)}], while rendering [${DebugGraphics.toString()}]`);
}
_uniqueLocations.set(location, name);
}
};

validateVB(vb0);
validateVB(vb1);
_uniqueLocations.clear();
}

draw(primitive, numInstances = 1, keepBuffers) {

if (this.shader.ready && !this.shader.failed) {
Expand All @@ -479,6 +510,7 @@ class WebgpuGraphicsDevice extends GraphicsDevice {
if (vb0) {
const vbSlot = this.submitVertexBuffer(vb0, 0);
if (vb1) {
Debug.call(() => this.validateVBLocations(vb0, vb1));
this.submitVertexBuffer(vb1, vbSlot);
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/platform/graphics/webgpu/webgpu-vertex-buffer-layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ class WebgpuVertexBufferLayout {
// type {GPUVertexBufferLayout[]}
const layout = [];

// Note: If the VertexFormat is interleaved, we use a single vertex buffer with multiple
// attributes. This uses a smaller number of vertex buffers (1), which has performance
// benefits when setting it up on the device.
// If the VertexFormat is not interleaved, we use multiple vertex buffers, one per
// attribute. This is less efficient, but is required as there is a pretty small
// limit on the attribute offsets in the vertex buffer layout.
const addFormat = (format) => {
const interleaved = format.interleaved;
const stepMode = format.instancing ? 'instance' : 'vertex';
Expand Down

0 comments on commit 518b986

Please sign in to comment.