Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ template <> struct JSIConverter<std::shared_ptr<rnwgpu::GPUDeviceDescriptor>> {
result->label = JSIConverter<std::optional<std::string>>::fromJSI(
runtime, prop, false);
}
if (value.hasProperty(runtime, "dawnToggles")) {
auto prop = value.getProperty(runtime, "dawnToggles");
result->dawnToggles = JSIConverter<
std::optional<std::shared_ptr<GPUDawnTogglesDescriptor>>>::fromJSI(
runtime, prop, false);
}
}

return result;
Expand Down
55 changes: 55 additions & 0 deletions packages/webgpu/src/__tests__/DawnToggles.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,59 @@ describe("Dawn toggles", () => {
});
expect(result).toBe(true);
});

// The tests above only assert that requestDevice resolves, which is true
// whether or not the toggle is parsed and chained onto the device descriptor.
// This test instead activates a real toggle (skip_validation) and observes a
// behavioral difference, so it fails if dawnToggles ever stops being applied.
it("applies skip_validation so a normally-invalid buffer creates without error", async () => {
// dawnToggles is a non-standard Dawn extension; browsers ignore it, so the
// behavioral difference only exists on the native (Dawn) backends.
if (client.OS === "web") {
return;
}
const result = await client.eval(({ gpu }) => {
// MAP_READ may only be combined with COPY_DST and MAP_WRITE only with
// COPY_SRC, so MAP_READ | MAP_WRITE is a validation error by default. The
// buffer is never used on the GPU, so creating it with validation skipped
// is harmless on every backend.
const invalid = {
size: 16,
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.MAP_WRITE,
};
// A fresh adapter per device: an adapter only vends a single device.
return gpu
.requestAdapter()
.then((adapter) => adapter!.requestDevice())
.then((control) => {
control.pushErrorScope("validation");
control.createBuffer(invalid);
return control.popErrorScope();
})
.then((controlError) =>
gpu
.requestAdapter()
.then((adapter) =>
adapter!.requestDevice({
dawnToggles: { enabledToggles: ["skip_validation"] },
}),
)
.then((toggled) => {
toggled.pushErrorScope("validation");
toggled.createBuffer(invalid);
return toggled.popErrorScope();
})
.then((toggledError) => ({
controlHadError: controlError !== null,
toggledHadError: toggledError !== null,
})),
);
});
// The operation is genuinely invalid on this build (guards against the test
// silently passing because the buffer became valid).
expect(result.controlHadError).toBe(true);
// skip_validation took effect, which is only possible if dawnToggles was
// parsed and chained onto the device descriptor.
expect(result.toggledHadError).toBe(false);
});
});
Loading