Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/platform/graphics/graphics-device.js
Original file line number Diff line number Diff line change
Expand Up @@ -784,9 +784,9 @@ class GraphicsDevice extends EventHandler {
this.initializeRenderState();
this.initializeContextCaches();

// Recreate buffer objects and reupload buffer data to the GPU
// Recreate buffer GPU objects; vertex/index reupload from CPU storage, storage buffers empty
for (const buffer of this.buffers) {
buffer.unlock();
buffer.restoreContext();
}

this.gpuProfiler?.restoreContext?.();
Expand Down
10 changes: 10 additions & 0 deletions src/platform/graphics/index-buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,16 @@ class IndexBuffer {
this.impl.loseContext();
}

/**
* Called when the rendering context is restored. Recreates the GPU buffer and uploads from
* {@link IndexBuffer#lock|lock} storage.
*
* @ignore
*/
restoreContext() {
this.unlock();
}

/**
* Returns the data format of the specified index buffer.
*
Expand Down
34 changes: 28 additions & 6 deletions src/platform/graphics/storage-buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ let id = 0;
* used to provide data for compute shader, and to store the result of the computation.
* Note that this class is only supported on the WebGPU platform.
*
* After a graphics device is lost and restored, the GPU backing for a storage buffer is
* recreated at the same byte size but its contents are undefined until you write to it again or
* repopulate it via compute.
*
* @category Graphics
*/
class StorageBuffer {
Expand All @@ -39,10 +43,7 @@ class StorageBuffer {
this.impl = graphicsDevice.createBufferImpl(usage);
this.impl.allocate(graphicsDevice, byteSize);

// Note: not registered in device.buffers — storage buffer contents are not
// recoverable on device-lost (no CPU-side shadow, may be GPU-written), so
// they don't participate in the engine's auto lose/restore iteration.
// Consumers handling device-lost must destroy() and recreate storage buffers.
graphicsDevice.buffers.add(this);

this.adjustVramSizeTracking(graphicsDevice._vram, this.byteSize);
}
Expand All @@ -51,8 +52,29 @@ class StorageBuffer {
* Frees resources associated with this storage buffer.
*/
destroy() {
this.adjustVramSizeTracking(this.device._vram, -this.byteSize);
this.impl.destroy(this.device);
const device = this.device;
device.buffers.delete(this);
this.impl.destroy(device);
this.adjustVramSizeTracking(device._vram, -this.byteSize);
}

/**
* Called when the rendering context was lost. It releases the GPU buffer handle.
*
* @ignore
*/
loseContext() {
this.impl.loseContext();
}

/**
* Called when the rendering context is restored. Recreates an empty GPU buffer of the same
* size; contents are not restored from CPU memory.
*
* @ignore
*/
restoreContext() {
this.impl.allocate(this.device, this.byteSize);
}

adjustVramSizeTracking(vram, size) {
Expand Down
10 changes: 10 additions & 0 deletions src/platform/graphics/vertex-buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,16 @@ class VertexBuffer {
this.impl.loseContext();
}

/**
* Called when the rendering context is restored. Recreates the GPU buffer and uploads from
* {@link VertexBuffer#lock|lock} storage.
*
* @ignore
*/
restoreContext() {
this.unlock();
}

/**
* Returns the data format of the specified vertex buffer.
*
Expand Down
18 changes: 9 additions & 9 deletions src/platform/graphics/webgpu/webgpu-buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class WebgpuBuffer {
}

loseContext() {
this.buffer = null;
}

allocate(device, size) {
Expand All @@ -45,6 +46,14 @@ class WebgpuBuffer {
size,
usage: this.usageFlags
});

DebugHelper.setLabel(this.buffer,
this.usageFlags & GPUBufferUsage.VERTEX ? 'VertexBuffer' :
this.usageFlags & GPUBufferUsage.INDEX ? 'IndexBuffer' :
this.usageFlags & GPUBufferUsage.UNIFORM ? 'UniformBuffer' :
this.usageFlags & GPUBufferUsage.STORAGE ? 'StorageBuffer' :
''
);
}

/**
Expand All @@ -66,15 +75,6 @@ class WebgpuBuffer {
this.usageFlags |= GPUBufferUsage.COPY_DST;
this.allocate(device, size);

DebugHelper.setLabel(this.buffer,
this.usageFlags & GPUBufferUsage.VERTEX ? 'VertexBuffer' :
this.usageFlags & GPUBufferUsage.INDEX ? 'IndexBuffer' :
this.usageFlags & GPUBufferUsage.UNIFORM ? 'UniformBuffer' :
this.usageFlags & GPUBufferUsage.STORAGE ? 'StorageBuffer' :
''
);


// mappedAtCreation path - this could be used when the data is provided

// this.buffer = device.wgpu.createBuffer({
Expand Down