Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement wgpuAdapterGetLimits, add test that limit requests are applied #21799

Merged
merged 9 commits into from
May 1, 2024
1 change: 1 addition & 0 deletions src/library_webgpu.js
Original file line number Diff line number Diff line change
Expand Up @@ -2604,6 +2604,7 @@ var LibraryWebGPU = {
setLimitU32IfDefined("maxInterStageShaderComponents", {{{ C_STRUCTS.WGPULimits.maxInterStageShaderComponents }}});
setLimitU32IfDefined("maxInterStageShaderVariables", {{{ C_STRUCTS.WGPULimits.maxInterStageShaderVariables }}});
setLimitU32IfDefined("maxColorAttachments", {{{ C_STRUCTS.WGPULimits.maxColorAttachments }}});
setLimitU32IfDefined("maxColorAttachmentBytesPerSample", {{{ C_STRUCTS.WGPULimits.maxColorAttachmentBytesPerSample }}});
setLimitU32IfDefined("maxComputeWorkgroupStorageSize", {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupStorageSize }}});
setLimitU32IfDefined("maxComputeInvocationsPerWorkgroup", {{{ C_STRUCTS.WGPULimits.maxComputeInvocationsPerWorkgroup }}});
setLimitU32IfDefined("maxComputeWorkgroupSizeX", {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupSizeX }}});
Expand Down
4 changes: 4 additions & 0 deletions test/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -4524,6 +4524,10 @@ def test_webgl_simple_extensions(self, simple_enable_extensions, webgl_version):
def test_webgpu_basic_rendering(self, args):
self.btest_exit('webgpu_basic_rendering.cpp', args=['-sUSE_WEBGPU'] + args)

@requires_graphics_hardware
def test_webgpu_required_limits(self):
self.btest_exit('webgpu_required_limits.cpp', args=['-sUSE_WEBGPU', '-sASYNCIFY'])

# TODO(#19645): Extend this test to proxied WebGPU when it's re-enabled.
@requires_graphics_hardware
def test_webgpu_basic_rendering_pthreads(self):
Expand Down
92 changes: 92 additions & 0 deletions test/webgpu_required_limits.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#include <cassert>
#include <emscripten.h>
#include <iostream>
#include <webgpu/webgpu.h>

int adapter_limit_maxColorAttachmentBytesPerSample = -1;

EM_ASYNC_JS(int, get_limit, (), {
if (!navigator.gpu) {
throw Error("WebGPU not supported.");
}

const adapter = await navigator.gpu.requestAdapter();
if (!adapter) {
throw Error("Couldn't request WebGPU adapter.");
}

console.log("adapter limits", adapter.limits);

return adapter.limits.maxColorAttachmentBytesPerSample;
kainino0x marked this conversation as resolved.
Show resolved Hide resolved
});

void on_device_request_ended(WGPURequestDeviceStatus status,
WGPUDevice device,
char const* message,
void* userdata) {
assert(status == WGPURequestDeviceStatus::WGPURequestDeviceStatus_Success);

WGPUSupportedLimits device_supported_limits{};
wgpuDeviceGetLimits(device, &device_supported_limits);

std::cout << "required maxColorAttachmentBytesPerSample="
<< adapter_limit_maxColorAttachmentBytesPerSample << std::endl;
std::cout << "supported maxColorAttachmentBytesPerSample="
<< device_supported_limits.limits.maxColorAttachmentBytesPerSample
<< std::endl;
kainino0x marked this conversation as resolved.
Show resolved Hide resolved

// device supported limit MUST be equal or larger than what was requested,
// otherwise device acquisition should have failed
assert(device_supported_limits.limits.maxColorAttachmentBytesPerSample >=
adapter_limit_maxColorAttachmentBytesPerSample);
}

void on_adapter_request_ended(WGPURequestAdapterStatus status,
WGPUAdapter adapter,
char const* message,
void* userdata) {
assert(status == WGPURequestAdapterStatus::WGPURequestAdapterStatus_Success);

// retrieving limits supported by adapter - currently unsupported!
// WGPUSupportedLimits adapter_supported_limits {};
// wgpuAdapterGetLimits(adapter, &adapter_supported_limits);
// adapter_limit_maxColorAttachmentBytesPerSample =
// adapter_supported_limits.limits.maxColorAttachmentBytesPerSample;

// use js callout instead
adapter_limit_maxColorAttachmentBytesPerSample = get_limit();
std::cout << "adapter supports maxColorAttachmentBytesPerSample="
<< adapter_limit_maxColorAttachmentBytesPerSample << std::endl;

// if max supported limit is the default, we cant check if requesting more works
if (adapter_limit_maxColorAttachmentBytesPerSample == 32) {
exit(0);
}

WGPURequiredLimits device_required_limits{};
device_required_limits.limits.minStorageBufferOffsetAlignment =
256; // irrelevant but needs to be set
device_required_limits.limits.minUniformBufferOffsetAlignment =
256; // irrelevant but needs to be set

// requesting adapter supported limit
device_required_limits.limits.maxColorAttachmentBytesPerSample =
adapter_limit_maxColorAttachmentBytesPerSample;

WGPUDeviceDescriptor device_desc{};
device_desc.requiredFeatureCount = 0;
device_desc.requiredLimits = &device_required_limits;

wgpuAdapterRequestDevice(
adapter, &device_desc, on_device_request_ended, nullptr);
}

int main() {
const WGPUInstance instance = wgpuCreateInstance(nullptr);

WGPURequestAdapterOptions adapter_options{};
wgpuInstanceRequestAdapter(
instance, &adapter_options, on_adapter_request_ended, nullptr);

return 0;
}