Skip to content

Commit f36db5e

Browse files
authored
feat: Always flushing (#1822)
1 parent 9a7d1f7 commit f36db5e

File tree

18 files changed

+70
-108
lines changed

18 files changed

+70
-108
lines changed

apps/typegpu-docs/src/content/docs/fundamentals/pipelines.mdx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -325,9 +325,6 @@ It accepts the number of vertices and optionally the instance count, first verte
325325
After calling the method, the shader is set for execution immediately.
326326

327327
Compute pipelines are executed using the `dispatchWorkgroups` method, which accepts the number of workgroups in each dimension.
328-
Unlike render pipelines, after running this method, the execution is not submitted to the GPU immediately.
329-
In order to do so, `root['~unstable'].flush()` needs to be run.
330-
However, that is usually not necessary, as it is done automatically when trying to read the result of computation.
331328

332329
### Drawing with `drawIndexed`
333330

@@ -376,14 +373,14 @@ const mainFragment = tgpu['~unstable'].fragmentFn({
376373
const indexBuffer = root
377374
.createBuffer(d.arrayOf(d.u16, 6), [0, 2, 1, 0, 3, 2])
378375
.$usage('index');
379-
376+
380377
const pipeline = root['~unstable']
381378
.withVertex(vertex, { color: vertexLayout.attrib })
382379
.withFragment(mainFragment, { format: presentationFormat })
383380
.createPipeline()
384381
.withIndexBuffer(indexBuffer);
385382

386-
pipeline
383+
pipeline
387384
.with(vertexLayout, colorBuffer)
388385
.drawIndexed(6);
389386
```
@@ -407,8 +404,6 @@ root['~unstable'].beginRenderPass(
407404
pass.draw(3);
408405
},
409406
);
410-
411-
root['~unstable'].flush();
412407
```
413408

414409
It is also possible to access the underlying WebGPU resources for the TypeGPU pipelines, by calling `root.unwrap(pipeline)`.

apps/typegpu-docs/src/examples/image-processing/blur/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ const ioLayout = tgpu.bindGroupLayout({
6666
outTexture: { storageTexture: d.textureStorage2d('rgba8unorm') },
6767
});
6868

69-
const tileData = tgpu['~unstable'].workgroupVar(
69+
const tileData = tgpu.workgroupVar(
7070
d.arrayOf(d.arrayOf(d.vec3f, 128), 4),
7171
);
7272

@@ -191,7 +191,6 @@ function render() {
191191
loadOp: 'clear',
192192
storeOp: 'store',
193193
}).draw(3);
194-
root['~unstable'].flush();
195194
}
196195
render();
197196

apps/typegpu-docs/src/examples/rendering/3d-fish/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,6 @@ function frame(timestamp: DOMHighResTimeStamp) {
306306
.with(renderFishBindGroups[odd ? 1 : 0])
307307
.draw(fishModel.polygonCount, p.fishAmount);
308308

309-
root['~unstable'].flush();
310-
311309
requestAnimationFrame(frame);
312310
}
313311
enqueuePresetChanges();

apps/typegpu-docs/src/examples/rendering/cubemap-reflection/icosphere.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,8 +310,6 @@ export class IcosphereGenerator {
310310
.with(bindGroup)
311311
.dispatchWorkgroups(xGroups, yGroups, 1);
312312

313-
this.root['~unstable'].flush();
314-
315313
return nextBuffer;
316314
}
317315

apps/typegpu-docs/src/examples/rendering/cubemap-reflection/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,8 +315,6 @@ function render() {
315315
.with(renderBindGroup)
316316
.with(textureBindGroup)
317317
.draw(vertexBuffer.dataType.elementCount);
318-
319-
root['~unstable'].flush();
320318
}
321319

322320
function loop() {

apps/typegpu-docs/src/examples/rendering/simple-shadow/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,6 @@ function render() {
352352
}
353353
},
354354
);
355-
root['~unstable'].flush();
356355
}
357356
frameId = requestAnimationFrame(render);
358357

apps/typegpu-docs/src/examples/rendering/two-boxes/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,6 @@ function render() {
303303
drawObject(cubeBuffer, bindGroup, 36, 'clear');
304304
drawObject(secondCubeBuffer, secondBindGroup, 36, 'load');
305305
drawObject(planeBuffer, planeBindGroup, 6, 'load');
306-
root['~unstable'].flush();
307306
}
308307

309308
function frame() {

apps/typegpu-docs/src/examples/simulation/slime-mold-3d/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,8 +498,6 @@ function frame() {
498498
.with(renderBindGroups[1 - currentTexture])
499499
.draw(3);
500500

501-
root['~unstable'].flush();
502-
503501
currentTexture = 1 - currentTexture;
504502

505503
requestAnimationFrame(frame);

apps/typegpu-docs/src/examples/tests/texture-test/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ function render() {
7676
storeOp: 'store',
7777
})
7878
.draw(3);
79-
root['~unstable'].flush();
79+
8080
requestAnimationFrame(render);
8181
}
8282
requestAnimationFrame(render);

packages/typegpu/src/core/buffer/buffer.ts

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ class TgpuBufferImpl<TData extends AnyData> implements TgpuBuffer<TData> {
176176
public readonly resourceType = 'buffer';
177177
public flags: GPUBufferUsageFlags = GPUBufferUsage.COPY_DST |
178178
GPUBufferUsage.COPY_SRC;
179+
180+
readonly #device: GPUDevice;
179181
private _buffer: GPUBuffer | null = null;
180182
private _ownBuffer: boolean;
181183
private _destroyed = false;
@@ -189,12 +191,13 @@ class TgpuBufferImpl<TData extends AnyData> implements TgpuBuffer<TData> {
189191
usableAsIndex = false;
190192

191193
constructor(
192-
private readonly _group: ExperimentalTgpuRoot,
194+
root: ExperimentalTgpuRoot,
193195
public readonly dataType: TData,
194196
public readonly initialOrBuffer?: Infer<TData> | GPUBuffer | undefined,
195197
private readonly _disallowedUsages?:
196198
('uniform' | 'storage' | 'vertex' | 'index')[],
197199
) {
200+
this.#device = root.device;
198201
if (isGPUBuffer(initialOrBuffer)) {
199202
this._ownBuffer = false;
200203
this._buffer = initialOrBuffer;
@@ -205,14 +208,12 @@ class TgpuBufferImpl<TData extends AnyData> implements TgpuBuffer<TData> {
205208
}
206209

207210
get buffer() {
208-
const device = this._group.device;
209-
210211
if (this._destroyed) {
211212
throw new Error('This buffer has been destroyed');
212213
}
213214

214215
if (!this._buffer) {
215-
this._buffer = device.createBuffer({
216+
this._buffer = this.#device.createBuffer({
216217
size: sizeOf(this.dataType),
217218
usage: this.flags,
218219
mappedAtCreation: !!this.initial,
@@ -317,7 +318,6 @@ class TgpuBufferImpl<TData extends AnyData> implements TgpuBuffer<TData> {
317318

318319
write(data: Infer<TData>): void {
319320
const gpuBuffer = this.buffer;
320-
const device = this._group.device;
321321

322322
if (gpuBuffer.mapState === 'mapped') {
323323
const mapped = gpuBuffer.getMappedRange();
@@ -330,16 +330,12 @@ class TgpuBufferImpl<TData extends AnyData> implements TgpuBuffer<TData> {
330330
this._hostBuffer = new ArrayBuffer(size);
331331
}
332332

333-
// Flushing any commands yet to be encoded.
334-
this._group.flush();
335-
336333
this._writeToTarget(this._hostBuffer, data);
337-
device.queue.writeBuffer(gpuBuffer, 0, this._hostBuffer, 0, size);
334+
this.#device.queue.writeBuffer(gpuBuffer, 0, this._hostBuffer, 0, size);
338335
}
339336

340337
public writePartial(data: InferPartial<TData>): void {
341338
const gpuBuffer = this.buffer;
342-
const device = this._group.device;
343339

344340
const instructions = getWriteInstructions(this.dataType, data);
345341

@@ -352,7 +348,7 @@ class TgpuBufferImpl<TData extends AnyData> implements TgpuBuffer<TData> {
352348
}
353349
} else {
354350
for (const instruction of instructions) {
355-
device.queue.writeBuffer(
351+
this.#device.queue.writeBuffer(
356352
gpuBuffer,
357353
instruction.data.byteOffset,
358354
instruction.data,
@@ -365,19 +361,15 @@ class TgpuBufferImpl<TData extends AnyData> implements TgpuBuffer<TData> {
365361

366362
public clear(): void {
367363
const gpuBuffer = this.buffer;
368-
const device = this._group.device;
369364

370365
if (gpuBuffer.mapState === 'mapped') {
371366
new Uint8Array(gpuBuffer.getMappedRange()).fill(0);
372367
return;
373368
}
374369

375-
// Flushing any commands yet to be encoded.
376-
this._group.flush();
377-
378-
const encoder = device.createCommandEncoder();
370+
const encoder = this.#device.createCommandEncoder();
379371
encoder.clearBuffer(gpuBuffer);
380-
device.queue.submit([encoder.finish()]);
372+
this.#device.queue.submit([encoder.finish()]);
381373
}
382374

383375
copyFrom(srcBuffer: TgpuBuffer<MemIdentity<TData>>): void {
@@ -386,16 +378,13 @@ class TgpuBufferImpl<TData extends AnyData> implements TgpuBuffer<TData> {
386378
}
387379

388380
const size = sizeOf(this.dataType);
389-
const encoder = this._group.commandEncoder;
381+
const encoder = this.#device.createCommandEncoder();
390382
encoder.copyBufferToBuffer(srcBuffer.buffer, 0, this.buffer, 0, size);
383+
this.#device.queue.submit([encoder.finish()]);
391384
}
392385

393386
async read(): Promise<Infer<TData>> {
394-
// Flushing any commands yet to be encoded.
395-
this._group.flush();
396-
397387
const gpuBuffer = this.buffer;
398-
const device = this._group.device;
399388

400389
if (gpuBuffer.mapState === 'mapped') {
401390
const mapped = gpuBuffer.getMappedRange();
@@ -410,12 +399,12 @@ class TgpuBufferImpl<TData extends AnyData> implements TgpuBuffer<TData> {
410399
return res;
411400
}
412401

413-
const stagingBuffer = device.createBuffer({
402+
const stagingBuffer = this.#device.createBuffer({
414403
size: sizeOf(this.dataType),
415404
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
416405
});
417406

418-
const commandEncoder = device.createCommandEncoder();
407+
const commandEncoder = this.#device.createCommandEncoder();
419408
commandEncoder.copyBufferToBuffer(
420409
gpuBuffer,
421410
0,
@@ -424,8 +413,7 @@ class TgpuBufferImpl<TData extends AnyData> implements TgpuBuffer<TData> {
424413
sizeOf(this.dataType),
425414
);
426415

427-
device.queue.submit([commandEncoder.finish()]);
428-
await device.queue.onSubmittedWorkDone();
416+
this.#device.queue.submit([commandEncoder.finish()]);
429417
await stagingBuffer.mapAsync(GPUMapMode.READ, 0, sizeOf(this.dataType));
430418

431419
const res = readData(

0 commit comments

Comments
 (0)