Skip to content

Commit 60d30f1

Browse files
committed
[update] specification.
1 parent be6737b commit 60d30f1

File tree

1 file changed

+27
-25
lines changed

1 file changed

+27
-25
lines changed

docs/specs/uniform-buffers-and-bind-groups.md

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ title: "Uniform Buffers and Bind Groups"
33
document_id: "ubo-spec-2025-10-11"
44
status: "draft"
55
created: "2025-10-11T00:00:00Z"
6-
last_updated: "2025-10-11T00:00:00Z"
7-
version: "0.1.0"
6+
last_updated: "2025-10-13T00:00:00Z"
7+
version: "0.1.1"
88
engine_workspace_version: "2023.1.30"
99
wgpu_version: "26.0.1"
1010
shader_backend_default: "naga"
1111
winit_version: "0.29.10"
12-
repo_commit: "0fdc489f5560acf809ca9cd8440f086baab7bad5"
12+
repo_commit: "a9ecb6df8188fb189e3221598b36f6cf757697bb"
1313
owners: ["lambda-sh"]
1414
reviewers: ["engine", "rendering"]
1515
tags: ["spec", "rendering", "uniforms", "bind-groups", "wgpu"]
@@ -76,9 +76,8 @@ Per-frame commands: BeginRenderPass -> SetPipeline -> SetBindGroup -> Draw -> En
7676
- Module: `lambda_platform::wgpu::bind`
7777
- `struct BindGroupLayout { raw: wgpu::BindGroupLayout, label: Option<String> }`
7878
- `struct BindGroup { raw: wgpu::BindGroup, label: Option<String> }`
79-
- `enum Visibility { Vertex, Fragment, Compute, BothVF, All }`
79+
- `enum Visibility { Vertex, Fragment, Compute, VertexAndFragment, All }`
8080
- Maps to `wgpu::ShaderStages`.
81-
- `enum BindingKind { Uniform { dynamic: bool }, /* future: SampledTexture, Sampler, Storage*/ }`
8281
- `struct BindGroupLayoutBuilder { entries: Vec<wgpu::BindGroupLayoutEntry>, label: Option<String> }`
8382
- `fn new() -> Self`
8483
- `fn with_uniform(mut self, binding: u32, visibility: Visibility) -> Self`
@@ -93,23 +92,23 @@ Per-frame commands: BeginRenderPass -> SetPipeline -> SetBindGroup -> Draw -> En
9392
- `fn build(self, device: &wgpu::Device) -> BindGroup`
9493

9594
Validation and limits
96-
- On `build`, validate against `wgpu::Limits`:
97-
- `max_uniform_buffer_binding_size` for explicit sizes.
98-
- `min_uniform_buffer_offset_alignment` for dynamic offsets (caller provides
99-
aligned `offset`; builder re-checks and errors if misaligned).
100-
- `max_bind_groups` when composing pipeline layouts (exposed via helper).
101-
- Return detailed error strings mapped into high-level errors in `lambda-rs`.
95+
- Current implementation defers validation to `wgpu` and backend validators.
96+
Builders do not perform explicit limit checks yet; invalid inputs will surface
97+
as `wgpu` validation errors at creation/bind time.
98+
- No explicit checks for `max_uniform_buffer_binding_size` in builders.
99+
- Dynamic offset alignment is not re-validated; callers must ensure offsets are
100+
multiples of `min_uniform_buffer_offset_alignment`.
101+
- Pipeline layout size (`max_bind_groups`) is not pre-validated by the builder.
102102

103103
Helpers
104-
- `fn shader_stages(vis: Visibility) -> wgpu::ShaderStages`
105-
- `fn align_up(value: u64, align: u64) -> u64`
104+
- No dedicated helpers are exposed in the platform layer yet.
106105

107106
## High-Level API Design (lambda-rs)
108107

109108
New module: `lambda::render::bind`
110109
- `pub struct BindGroupLayout { /* holds Rc<wgpu::BindGroupLayout> */ }`
111110
- `pub struct BindGroup { /* holds Rc<wgpu::BindGroup> */ }`
112-
- `pub enum BindingVisibility { Vertex, Fragment, Compute, BothVF, All }`
111+
- `pub enum BindingVisibility { Vertex, Fragment, Compute, VertexAndFragment, All }`
113112
- `pub struct BindGroupLayoutBuilder { /* mirrors platform builder */ }`
114113
- `pub fn new() -> Self`
115114
- `pub fn with_uniform(self, binding: u32, visibility: BindingVisibility) -> Self`
@@ -119,7 +118,7 @@ New module: `lambda::render::bind`
119118
- `pub struct BindGroupBuilder { /* mirrors platform builder */ }`
120119
- `pub fn new() -> Self`
121120
- `pub fn with_layout(self, layout: &BindGroupLayout) -> Self`
122-
- `pub fn with_uniform(self, binding: u32, buffer: &buffer::Buffer, offset: u64, size: Option<u64>) -> Self`
121+
- `pub fn with_uniform(self, binding: u32, buffer: &buffer::Buffer, offset: u64, size: Option<NonZeroU64>) -> Self`
123122
- `pub fn with_label(self, label: &str) -> Self`
124123
- `pub fn build(self, rc: &RenderContext) -> BindGroup`
125124

@@ -167,6 +166,9 @@ impl<T> UniformBuffer<T> {
167166
- Dynamic offsets must be multiples of
168167
`limits.min_uniform_buffer_offset_alignment`.
169168
- Respect `limits.max_uniform_buffer_binding_size` when slicing UBOs.
169+
- Matrices are column‑major in GLSL/WGSL. If your CPU math builds row‑major
170+
matrices, either transpose before uploading to the GPU or mark GLSL uniform
171+
blocks with `layout(row_major)` to avoid unexpected transforms.
170172

171173
## Example Usage
172174

@@ -242,20 +244,20 @@ let dyn_layout = BindGroupLayoutBuilder::new()
242244
.with_uniform_dynamic(0, BindingVisibility::Vertex)
243245
.build(&mut rc);
244246

245-
let stride = align_up(core::mem::size_of::<Globals>() as u64,
246-
rc.device().limits().min_uniform_buffer_offset_alignment);
247+
let align = rc.device().limits().min_uniform_buffer_offset_alignment;
248+
let size = core::mem::size_of::<Globals>() as u64;
249+
let stride = ((size + align - 1) / align) * align; // manual align-up
247250
let offsets = vec![0u32, stride as u32, (2*stride) as u32];
248251
RC::SetBindGroup { set: 0, group: dyn_group_id, dynamic_offsets: offsets };
249252
```
250253

251254
## Error Handling
252255

253256
- `BufferBuilder` already errors on zero length; keep behavior.
254-
- New bind errors returned during `build` with clear messages:
255-
- "uniform binding size exceeds max_uniform_buffer_binding_size"
256-
- "dynamic offset not aligned to min_uniform_buffer_offset_alignment"
257-
- "invalid binding index (duplicate or out of range)"
258-
- "pipeline layouts exceed device.max_bind_groups"
257+
- Bind group and layout builders currently do not pre‑validate against device limits.
258+
Invalid sizes/offsets typically surface as `wgpu` validation errors during creation
259+
or when calling `set_bind_group`. Ensure dynamic offsets are aligned to device limits
260+
and uniform ranges respect `max_uniform_buffer_binding_size`.
259261

260262
## Performance Notes
261263

@@ -278,7 +280,7 @@ Phase 1 (dynamic offsets)
278280
- Add small helper to compute aligned strides.
279281

280282
Phase 2 (ergonomics/testing)
281-
- Optional `UniformBuffer<T>` wrapper with `.write(&T)` for convenience.
283+
- Optional `UniformBuffer<T>` wrapper with `.write(&T)` for convenience (not implemented yet).
282284
- Unit tests for builders and validation; integration test that animates a
283285
triangle with a camera UBO.
284286

@@ -307,5 +309,5 @@ File layout
307309

308310
## Changelog
309311

310-
- 2025-10-11 (v0.1.0) — Initial draft aligned to roadmap; specifies platform
311-
and high-level APIs, commands, validation, examples, and phased delivery.
312+
- 2025-10-13 (v0.1.1) — Synced spec to implementation: renamed visibility enum variant to `VertexAndFragment`; clarified that builders defer validation to `wgpu`; updated `with_uniform` size type to `Option<NonZeroU64>`; added note on GPU column‑major matrices and CPU transpose guidance; adjusted dynamic offset example.
313+
- 2025-10-11 (v0.1.0) — Initial draft aligned to roadmap; specifies platform and high-level APIs, commands, validation, examples, and phased delivery.

0 commit comments

Comments
 (0)