fix(webgpu): request adapter's storage-buffer limit, not hardcoded 16 #9

Merged
catbot merged 1 commit from claude/issue-8 into master 2026-05-31 23:58:19 +02:00
Member

Problem

additional/dom-webgpu.js hardcoded the device's maxStorageBuffersPerShaderStage request to 16, even when the adapter supports far more (64 in our test env). The wavefront SHADE kernel already binds ~16 storage buffers (group(1) RT/work buffers + wfPayload, group(2) wfIndirect) before any user binding, so any RT pipeline declaring 2+ user storage buffers at @group(3) overflowed the limit and the pipeline failed to build:

Too many bindings of type StorageBuffers in Stage ShaderStages(COMPUTE),
limit is 16, count was 19.

This contradicted WAVEFRONT-DESIGN.md's claim that Phase 7 binding packing was unnecessary because the device has 64 storage buffers/stage — the adapter reported 64, but the device was clamped to 16.

Fix

Request the adapter's reported maxStorageBuffersPerShaderStage / maxStorageBuffersInPipelineLayout instead of a fixed 16. clamp already mins against the adapter cap, so baseline-only devices still get a valid request; the || 16 fallback plus the existing typeof cap === "number" guard handle limit names a browser doesn't expose (Firefox returns null for maxStorageBuffersInPipelineLayout, so it's simply not requested). Also updated the design doc to note Phase 7's skip now depends on this.

Verification

No automated tests exist for the JS bridge (crafter-build test → "No tests matched"), so verified directly in Firefox with real WebGPU:

  • Adapter reports maxStorageBuffersPerShaderStage: 64; the device now requests 64 (was 16).
  • A 17-storage-buffer compute pipeline fails with the exact reported error on a device clamped to 16, and builds cleanly on a device requesting the adapter's 64.
  • RTStress builds and renders correctly via the wavefront tracer (rtPipelines=1, no validation errors, normal per-pass timings).

Screenshots

RTStress wavefront RT

Resolves #8

## Problem `additional/dom-webgpu.js` hardcoded the device's `maxStorageBuffersPerShaderStage` request to **16**, even when the adapter supports far more (64 in our test env). The wavefront **SHADE** kernel already binds ~16 storage buffers (group(1) RT/work buffers + `wfPayload`, group(2) `wfIndirect`) *before* any user binding, so any RT pipeline declaring 2+ user storage buffers at `@group(3)` overflowed the limit and the pipeline failed to build: ``` Too many bindings of type StorageBuffers in Stage ShaderStages(COMPUTE), limit is 16, count was 19. ``` This contradicted `WAVEFRONT-DESIGN.md`'s claim that Phase 7 binding packing was unnecessary because the device has 64 storage buffers/stage — the *adapter* reported 64, but the *device* was clamped to 16. ## Fix Request the adapter's reported `maxStorageBuffersPerShaderStage` / `maxStorageBuffersInPipelineLayout` instead of a fixed 16. `clamp` already mins against the adapter cap, so baseline-only devices still get a valid request; the `|| 16` fallback plus the existing `typeof cap === "number"` guard handle limit names a browser doesn't expose (Firefox returns `null` for `maxStorageBuffersInPipelineLayout`, so it's simply not requested). Also updated the design doc to note Phase 7's skip now depends on this. ## Verification No automated tests exist for the JS bridge (`crafter-build test` → "No tests matched"), so verified directly in Firefox with real WebGPU: - Adapter reports `maxStorageBuffersPerShaderStage: 64`; the device now requests 64 (was 16). - A 17-storage-buffer compute pipeline **fails** with the exact reported error on a device clamped to 16, and **builds cleanly** on a device requesting the adapter's 64. - RTStress builds and renders correctly via the wavefront tracer (`rtPipelines=1`, no validation errors, normal per-pass timings). ## Screenshots ![RTStress wavefront RT](https://forgejo.catcrafts.net/attachments/78ca8a4a-2cc8-4dfe-a77c-fc74bce9d3d3) Resolves #8
dom-webgpu.js capped maxStorageBuffersPerShaderStage at 16 even when the
adapter reports far more (64 in our test env). The wavefront SHADE kernel
already binds ~16 storage buffers before any user binding, so any RT
pipeline declaring 2+ user storage buffers at @group(3) overflowed the
limit and failed to build with "Too many bindings of type StorageBuffers".

Request the adapter's reported maxStorageBuffersPerShaderStage /
maxStorageBuffersInPipelineLayout instead of a fixed 16. `clamp` already
mins against the adapter cap, so baseline-only devices still get a valid
request, and the `|| 16` fallback + the `typeof cap === "number"` guard
handle limit names a browser doesn't expose (Firefox returns null for
maxStorageBuffersInPipelineLayout).

Verified in-browser: a 17-storage-buffer compute pipeline fails with the
exact reported error on a device clamped to 16, and builds cleanly on a
device requesting the adapter's 64. RTStress renders correctly.

Resolves #8

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
catbot merged commit 6470c12db5 into master 2026-05-31 23:58:19 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Catcrafts/Crafter.Graphics!9
No description provided.