Skip to content

Commit

Permalink
Support for GPU timing reporting for compute passes in WebGPU (#7028)
Browse files Browse the repository at this point in the history
* Support for GPU timing reporting for compute passes in WebGPU

* fix

* descr->desc

---------

Co-authored-by: Martin Valigursky <[email protected]>
  • Loading branch information
mvaligursky and Martin Valigursky authored Oct 11, 2024
1 parent 6560131 commit cea6b42
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 25 deletions.
2 changes: 1 addition & 1 deletion examples/src/examples/compute/histogram.example.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ assetListLoader.load(() => {

// dispatch the compute shader
compute.setupDispatch(app.graphicsDevice.width, app.graphicsDevice.height);
device.computeDispatch([compute]);
device.computeDispatch([compute], 'HistogramDispatch');

// Read back the histogram data from the storage buffer. None that the returned promise
// will be resolved later, when the GPU is done running it, and so the histogram on the
Expand Down
2 changes: 1 addition & 1 deletion examples/src/examples/compute/particles.example.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ assetListLoader.load(() => {

// dispatch the compute shader to simulate the particles
compute.setupDispatch(1024 / 64, 1024);
device.computeDispatch([compute]);
device.computeDispatch([compute], 'ComputeParticlesDispatch');
}
});
});
Expand Down
2 changes: 1 addition & 1 deletion examples/src/examples/compute/texture-gen.example.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ assetListLoader.load(() => {
compute2.setupDispatch(srcTexture.width, srcTexture.height);

// dispatch both compute shaders in a single compute pass
device.computeDispatch([compute1, compute2]);
device.computeDispatch([compute1, compute2], 'ComputeModifyTextureDispatch');

// debug render the generated textures
app.drawTexture(0.6, 0.5, 0.6, 0.3, compute1.getParameter('outTexture'));
Expand Down
2 changes: 1 addition & 1 deletion examples/src/examples/compute/vertex-update.example.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ assetListLoader.load(() => {
compute.setupDispatch(mesh.vertexBuffer.numVertices);

// dispatch the compute shader
device.computeDispatch([compute]);
device.computeDispatch([compute], 'ModifyVBDispatch');

// solid / wireframe
entity.render.renderStyle = Math.floor(time * 0.5) % 2 ? pc.RENDERSTYLE_WIREFRAME : pc.RENDERSTYLE_SOLID;
Expand Down
4 changes: 4 additions & 0 deletions src/platform/graphics/gpu-profiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,14 @@ class GpuProfiler {

// log out timings
if (Tracing.get(TRACEID_GPU_TIMINGS)) {
Debug.trace(TRACEID_GPU_TIMINGS, `-- GPU timings for frame ${renderVersion} --`);
let total = 0;
for (let i = 0; i < allocations.length; ++i) {
const name = allocations[i];
total += timings[i];
Debug.trace(TRACEID_GPU_TIMINGS, `${timings[i].toFixed(2)} ms ${name}`);
}
Debug.trace(TRACEID_GPU_TIMINGS, `${total.toFixed(2)} ms TOTAL`);
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/platform/graphics/graphics-device.js
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ class GraphicsDevice extends EventHandler {
endRenderPass(renderPass) {
}

startComputePass() {
startComputePass(name) {
}

endComputePass() {
Expand Down Expand Up @@ -905,8 +905,9 @@ class GraphicsDevice extends EventHandler {
* Dispatch multiple compute shaders inside a single compute shader pass.
*
* @param {Array<Compute>} computes - An array of compute shaders to dispatch.
* @param {string} [name] - The name of the dispatch, used for debugging and reporting only.
*/
computeDispatch(computes) {
computeDispatch(computes, name = 'Unnamed') {
}

/**
Expand Down
45 changes: 26 additions & 19 deletions src/platform/graphics/webgpu/webgpu-graphics-device.js
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,22 @@ class WebgpuGraphicsDevice extends GraphicsDevice {
});
}

setupTimeStampWrites(passDesc, name) {
if (this.gpuProfiler._enabled) {
if (this.gpuProfiler.timestampQueriesSet) {
const slot = this.gpuProfiler.getSlot(name);

passDesc = passDesc ?? {};
passDesc.timestampWrites = {
querySet: this.gpuProfiler.timestampQueriesSet.querySet,
beginningOfPassWriteIndex: slot * 2,
endOfPassWriteIndex: slot * 2 + 1
};
}
}
return passDesc;
}

/**
* Start a render pass.
*
Expand All @@ -673,7 +689,7 @@ class WebgpuGraphicsDevice extends GraphicsDevice {

// create a new encoder for each pass
this.commandEncoder = this.wgpu.createCommandEncoder();
DebugHelper.setLabel(this.commandEncoder, `${renderPass.name}-CmdEncoder RT:${rt.name}`);
DebugHelper.setLabel(this.commandEncoder, `${renderPass.name}-CommandEncoder RT:${rt.name}`);

// framebuffer is initialized at the start of the frame
if (rt !== this.backBuffer) {
Expand All @@ -686,17 +702,7 @@ class WebgpuGraphicsDevice extends GraphicsDevice {
const renderPassDesc = wrt.renderPassDescriptor;

// timestamp
if (this.gpuProfiler._enabled) {
if (this.gpuProfiler.timestampQueriesSet) {
const slot = this.gpuProfiler.getSlot(renderPass.name);

renderPassDesc.timestampWrites = {
querySet: this.gpuProfiler.timestampQueriesSet.querySet,
beginningOfPassWriteIndex: slot * 2,
endOfPassWriteIndex: slot * 2 + 1
};
}
}
this.setupTimeStampWrites(renderPassDesc, renderPass.name);

// start the pass
this.passEncoder = this.commandEncoder.beginRenderPass(renderPassDesc);
Expand Down Expand Up @@ -772,23 +778,24 @@ class WebgpuGraphicsDevice extends GraphicsDevice {
WebgpuDebug.end(this, { renderPass });
}

startComputePass() {
startComputePass(name) {

WebgpuDebug.internal(this);
WebgpuDebug.validate(this);

// create a new encoder for each pass
this.commandEncoder = this.wgpu.createCommandEncoder();
DebugHelper.setLabel(this.commandEncoder, 'ComputePass-Encoder');
DebugHelper.setLabel(this.commandEncoder, `${name}-ComputePass-Encoder`);

// clear cached encoder state
this.pipeline = null;

// TODO: add performance queries to compute passes
// timestamp
const computePassDesc = this.setupTimeStampWrites(undefined, name);

// start the pass
this.passEncoder = this.commandEncoder.beginComputePass();
DebugHelper.setLabel(this.passEncoder, 'ComputePass');
this.passEncoder = this.commandEncoder.beginComputePass(computePassDesc);
DebugHelper.setLabel(this.passEncoder, `ComputePass-${name}`);

Debug.assert(!this.insideRenderPass, 'ComputePass cannot be started while inside another pass.');
this.insideRenderPass = true;
Expand Down Expand Up @@ -816,9 +823,9 @@ class WebgpuGraphicsDevice extends GraphicsDevice {
WebgpuDebug.end(this);
}

computeDispatch(computes) {
computeDispatch(computes, name = 'Unnamed') {

this.startComputePass();
this.startComputePass(name);

// update uniform buffers and bind groups
for (let i = 0; i < computes.length; i++) {
Expand Down

0 comments on commit cea6b42

Please sign in to comment.