@vgpu/render 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +1 -1
  2. package/dist/index.d.ts +5 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +3 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/perf/frame-time-measure.d.ts +22 -0
  7. package/dist/perf/frame-time-measure.d.ts.map +1 -0
  8. package/dist/perf/frame-time-measure.js +91 -0
  9. package/dist/perf/frame-time-measure.js.map +1 -0
  10. package/dist/perf/gpu-frame-time.d.ts +49 -0
  11. package/dist/perf/gpu-frame-time.d.ts.map +1 -0
  12. package/dist/perf/gpu-frame-time.js +50 -0
  13. package/dist/perf/gpu-frame-time.js.map +1 -0
  14. package/dist/perf/index.d.ts +5 -0
  15. package/dist/perf/index.d.ts.map +1 -0
  16. package/dist/perf/index.js +3 -0
  17. package/dist/perf/index.js.map +1 -0
  18. package/dist/perf/pixel-diff.d.ts +27 -0
  19. package/dist/perf/pixel-diff.d.ts.map +1 -0
  20. package/dist/perf/pixel-diff.js +40 -0
  21. package/dist/perf/pixel-diff.js.map +1 -0
  22. package/dist/pipeline-descriptor.d.ts +35 -0
  23. package/dist/pipeline-descriptor.d.ts.map +1 -0
  24. package/dist/pipeline-descriptor.js +44 -0
  25. package/dist/pipeline-descriptor.js.map +1 -0
  26. package/dist/pipeline.d.ts +22 -33
  27. package/dist/pipeline.d.ts.map +1 -1
  28. package/dist/pipeline.js +30 -46
  29. package/dist/pipeline.js.map +1 -1
  30. package/dist/render-pass.d.ts.map +1 -1
  31. package/dist/render-pass.js +4 -0
  32. package/dist/render-pass.js.map +1 -1
  33. package/dist/storage-buffer.d.ts +81 -0
  34. package/dist/storage-buffer.d.ts.map +1 -0
  35. package/dist/storage-buffer.js +91 -0
  36. package/dist/storage-buffer.js.map +1 -0
  37. package/dist/uniform.d.ts +55 -0
  38. package/dist/uniform.d.ts.map +1 -0
  39. package/dist/uniform.js +64 -0
  40. package/dist/uniform.js.map +1 -0
  41. package/package.json +8 -3
  42. package/src/createRenderPipeline.docs.md +34 -0
  43. package/src/perf/perf.docs.md +45 -0
  44. package/src/storage-buffer.docs.md +102 -0
  45. package/src/uniform.docs.md +70 -0
@@ -0,0 +1,102 @@
1
+ # StorageBuffer
2
+
3
+ `StorageBuffer` is one stable storage buffer for a single render (or compute)
4
+ pass, rewritten as needed and change-gated by the caller. It is the
5
+ storage-buffer counterpart to `Uniform`: it creates a `storage | copy_dst`
6
+ buffer, a bind group layout with a single storage binding at binding 0, and a
7
+ bind group wired to that buffer. `write()` uploads bytes with
8
+ `queue.writeBuffer` at a fixed offset — there is no dynamic offset and the bind
9
+ group never changes.
10
+
11
+ ## When to use `StorageBuffer` vs `Uniform` vs `UniformPool`
12
+
13
+ Use `StorageBuffer` when the data is too large or too dynamic for a uniform:
14
+ arrays, runtime-sized data, particle/instance state, lookup tables. Storage
15
+ buffers can be much larger than uniforms — up to the adapter's
16
+ `maxStorageBufferBindingSize` (typically 128 MiB) versus a uniform's 64 KiB —
17
+ and the shader can write them with `access: "read-write"`.
18
+
19
+ Use `Uniform` for the common "globals/camera per pass" case: a small, fixed,
20
+ read-only buffer (`var<uniform>`).
21
+
22
+ Use `UniformPool` only when you have **many** small per-draw uniforms. It is a
23
+ dynamic-offset ring allocator: every slot binding is marked
24
+ `hasDynamicOffset: true` and the whole CPU mirror is re-uploaded each frame.
25
+
26
+ ## `access`: read vs read-write
27
+
28
+ `access` controls the bind group layout entry type. Both modes default to
29
+ `FRAGMENT | COMPUTE` visibility:
30
+
31
+ - `"read"` (default) → WGSL `var<storage, read>`, layout type
32
+ `"read-only-storage"`.
33
+ - `"read-write"` → WGSL `var<storage, read_write>`, layout type `"storage"`.
34
+
35
+ > Neither default includes `VERTEX`. Read-write storage is forbidden in the
36
+ > vertex stage outright. Read-only storage is _allowed_ in the vertex stage, but
37
+ > `maxStorageBuffersInVertexStage` is **0** on many adapters (software/CI Vulkan,
38
+ > some mobile GPUs) — a `VERTEX`-visible default silently invalidates the layout
39
+ > there and the draw no-ops. For vertex-stage read-only storage, pass
40
+ > `visibility: VERTEX | …` explicitly **and** raise `maxStorageBuffersInVertexStage`
41
+ > via `requiredLimits` when requesting the device.
42
+
43
+ ## Constructor
44
+
45
+ ```ts
46
+ new StorageBuffer(device, {
47
+ size, // byte size of the storage buffer (required)
48
+ label, // optional debug label for buffer, layout, and bind group
49
+ access, // "read" (default) | "read-write"
50
+ visibility, // GPUShaderStageFlags; defaults by access (see above)
51
+ bindGroupLayout, // optional pipeline-owned layout to reuse instead of creating one
52
+ });
53
+ ```
54
+
55
+ - `size`: byte size of the storage buffer. May be far larger than a uniform.
56
+ - `label`: optional debug label; suffixed `.bgl` / `.bg` for the layout and bind
57
+ group.
58
+ - `access`: `"read"` (default, read-only storage) or `"read-write"` (writable
59
+ storage). Selects the layout entry type and the default visibility.
60
+ - `visibility`: shader stages that access binding 0. Defaults to
61
+ `FRAGMENT | COMPUTE` for both access modes (no `VERTEX` — see the note above).
62
+ Ignored when `bindGroupLayout` is provided.
63
+ - `bindGroupLayout`: reuse a pipeline-owned bind group layout instead of creating
64
+ one. Its binding 0 must be a storage buffer compatible with `size` and
65
+ `access`.
66
+
67
+ ## Members
68
+
69
+ - `storageBuffer.gpu`: the underlying storage `GPUBuffer`.
70
+ - `storageBuffer.buffer`: the VGPU `Buffer` wrapper around `gpu`.
71
+ - `storageBuffer.bindGroup`: the `GPUBindGroup` to bind for the pass.
72
+ - `storageBuffer.bindGroupLayout`: the `GPUBindGroupLayout` (created or reused).
73
+ - `storageBuffer.size`: the buffer byte size.
74
+ - `storageBuffer.access`: the resolved access mode (`"read"` or `"read-write"`).
75
+ - `storageBuffer.write(data, offset = 0)`: uploads `data` via
76
+ `device.queue.writeBuffer(gpu, offset, data)`. No dynamic offset; the bind
77
+ group is unchanged. Call only when the contents actually change.
78
+ - `storageBuffer.destroy()` / `storageBuffer.dispose()`: releases the backing
79
+ buffer once; idempotent.
80
+
81
+ ## Example
82
+
83
+ ```ts
84
+ // A read-only array the fragment shader samples:
85
+ // @group(0) @binding(0) var<storage, read> values: array<f32>;
86
+ const storage = new StorageBuffer(device, { size: 4 * count, label: "values" });
87
+ storage.write(new Float32Array(values));
88
+
89
+ const pipeline = createRenderPipelineFromDescriptor(device, {
90
+ layout: device.gpu.createPipelineLayout({ bindGroupLayouts: [storage.bindGroupLayout] }),
91
+ vertex: { module, entryPoint: "vs_main" },
92
+ fragment: { module, entryPoint: "fs_main", targets: [{ format }] },
93
+ });
94
+
95
+ pass.setPipeline(pipeline);
96
+ pass.setBindGroup(0, storage.bindGroup);
97
+ pass.draw(3);
98
+
99
+ // A compute-written scratch buffer:
100
+ // @group(0) @binding(0) var<storage, read_write> out: array<u32>;
101
+ const scratch = new StorageBuffer(device, { size: 4 * count, access: "read-write" });
102
+ ```
@@ -0,0 +1,70 @@
1
+ # Uniform
2
+
3
+ `Uniform` is one stable uniform buffer for a single render pass, rewritten per
4
+ frame and change-gated by the caller. It creates a `uniform | copy_dst` buffer,
5
+ a bind group layout with a single uniform binding at binding 0, and a bind group
6
+ wired to that buffer. `write()` uploads bytes with `queue.writeBuffer` at a fixed
7
+ offset — there is no dynamic offset and the bind group never changes.
8
+
9
+ ## When to use `Uniform` vs `UniformPool`
10
+
11
+ Use `Uniform` for the common "globals/camera per pass" case: a single buffer you
12
+ overwrite each frame, where you decide when the contents actually changed.
13
+
14
+ Use `UniformPool` only when you have **many** per-draw uniforms. It is a
15
+ dynamic-offset ring allocator: every slot binding is marked
16
+ `hasDynamicOffset: true` and the whole CPU mirror is re-uploaded each frame. For
17
+ one stable buffer that is the wrong shape — it forces a dynamic-offset layout and
18
+ defeats change-gating.
19
+
20
+ ## Constructor
21
+
22
+ ```ts
23
+ new Uniform(device, {
24
+ size, // byte size of the uniform buffer (required)
25
+ label, // optional debug label for buffer, layout, and bind group
26
+ visibility, // GPUShaderStageFlags; defaults to VERTEX | FRAGMENT
27
+ bindGroupLayout, // optional pipeline-owned layout to reuse instead of creating one
28
+ });
29
+ ```
30
+
31
+ - `size`: byte size of the uniform buffer.
32
+ - `label`: optional debug label; suffixed `.bgl` / `.bg` for the layout and bind
33
+ group.
34
+ - `visibility`: shader stages that read binding 0. Defaults to
35
+ `GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT`. Ignored when
36
+ `bindGroupLayout` is provided.
37
+ - `bindGroupLayout`: reuse a pipeline-owned bind group layout instead of creating
38
+ one. Its binding 0 must be a uniform buffer compatible with `size`.
39
+
40
+ ## Members
41
+
42
+ - `uniform.gpu`: the underlying uniform `GPUBuffer`.
43
+ - `uniform.buffer`: the VGPU `Buffer` wrapper around `gpu`.
44
+ - `uniform.bindGroup`: the `GPUBindGroup` to bind for the pass.
45
+ - `uniform.bindGroupLayout`: the `GPUBindGroupLayout` (created or reused).
46
+ - `uniform.size`: the buffer byte size.
47
+ - `uniform.write(data, offset = 0)`: uploads `data` via
48
+ `device.queue.writeBuffer(gpu, offset, data)`. No dynamic offset; the bind group
49
+ is unchanged. Call only when the uniform contents actually change.
50
+ - `uniform.destroy()` / `uniform.dispose()`: releases the backing buffer once;
51
+ idempotent.
52
+
53
+ ## Example
54
+
55
+ ```ts
56
+ const uniform = new Uniform(device, { size: 64, label: "globals" });
57
+
58
+ // Per frame, only when inputs changed:
59
+ if (dirty) uniform.write(globalsBytes);
60
+
61
+ const pipeline = createRenderPipelineFromDescriptor(device, {
62
+ layout: device.gpu.createPipelineLayout({ bindGroupLayouts: [uniform.bindGroupLayout] }),
63
+ vertex: { module, entryPoint: "vs_main" },
64
+ fragment: { module, entryPoint: "fs_main", targets: [{ format }] },
65
+ });
66
+
67
+ pass.setPipeline(pipeline);
68
+ pass.setBindGroup(0, uniform.bindGroup);
69
+ pass.draw(3);
70
+ ```