core: indirect draw passes, device feature list, drop handles-specific bundle heuristics

Amp-Thread-ID: https://ampcode.com/threads/T-01a0b2dd-db32-712d-99ce-12ce4a86d979
Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
Amp
2026-09-18 05:31:11 +00:00
co-authored by heaust
parent dda602c4a2
commit 49c80a209e
11 changed files with 123 additions and 56 deletions
+5 -1
View File
@@ -96,6 +96,7 @@ Pass {
vertexBuffers: VertexBinding[] = [],
indexBuffer?: IndexBinding,
draw: Draw = {},
indirect?: IndirectBinding,
dispatch: [u32,u32,u32] = [1,1,1]
}
Binding { group: u32 = 0, binding: u32 required, resource: string required,
@@ -106,9 +107,12 @@ DepthAttachment { resource: string required, clear: number = 1,
load: "clear"|"load" = "clear", store: "store"|"discard" = "store" }
VertexBinding { slot: u32 = 0, resource: string required, offset: u64 = 0 }
IndexBinding { resource: string required, format: "uint16"|"uint32" = "uint32", offset: u64 = 0 }
IndirectBinding { resource: string required, first: u32 = 0, count?: u32 }
Draw { vertices: u32 = 3, indices: u32 = 0, instances: u32 = 1,
firstVertex: u32 = 0, firstIndex: u32 = 0, baseVertex: i32 = 0,
firstInstance: u32 = 0 }
```
Render passes use `draw`; when `indexBuffer` exists, the indexed path uses `indices` (so set it nonzero), `firstIndex`, and `baseVertex`. Otherwise it uses `vertices` and `firstVertex`. Both use instance fields. Compute passes use `dispatch`. A pipeline ID is validated against the pass kind when the loadout is built. Binding offset/size and vertex/index offsets are bytes and must satisfy WebGPU alignment and range rules. Attachments require matching usages and formats; sampled/storage bindings likewise require matching texture usage, while WGSL determines binding type and visibility.
Render passes use `draw`; when `indexBuffer` exists, the indexed path uses `indices` (so set it nonzero), `firstIndex`, and `baseVertex`. Otherwise it uses `vertices` and `firstVertex`. Both use instance fields. Compute passes use `dispatch`.
`indirect` replaces `draw` (which must stay at its defaults) with one draw command per row of a buffer declared with `indirect` usage: rows `first .. first + count`, where `count` defaults to every row through the end of the array at activation time. Each row begins with the WebGPU command — `[vertexCount, instanceCount, firstVertex, firstInstance]` for non-indexed passes, `[indexCount, instanceCount, firstIndex, baseVertex: i32, firstInstance]` when `indexBuffer` exists — so the row stride must be at least 16 or 20 bytes; the rest of the row is caller-owned. A zero `instanceCount` skips the row cheaply, so callers can keep spare rows and toggle draws without recompiling. Nonzero `firstInstance` requires the device feature `indirect-first-instance` (see `init` result `features`); without it WebGPU silently draws nothing for that command. A pipeline ID is validated against the pass kind when the loadout is built. Binding offset/size and vertex/index offsets are bytes and must satisfy WebGPU alignment and range rules. Attachments require matching usages and formats; sampled/storage bindings likewise require matching texture usage, while WGSL determines binding type and visibility.