Add GPUSupportedFeatures and update GPUSupportedLimits (#30359)

* GPUSupportedFeatures

* New supported limits

* Update expectations
This commit is contained in:
Samson 2023-09-14 15:23:12 +02:00 committed by GitHub
parent 6ea394a701
commit d22d97f8c8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 243 additions and 17058 deletions

View file

@ -144,6 +144,7 @@ impl AsyncWGPUListener for GPU {
Ok(WebGPUResponse::RequestAdapter { Ok(WebGPUResponse::RequestAdapter {
adapter_info, adapter_info,
adapter_id, adapter_id,
features,
limits, limits,
channel, channel,
}) => { }) => {
@ -156,6 +157,7 @@ impl AsyncWGPUListener for GPU {
adapter_id.0.backend() adapter_id.0.backend()
)), )),
Heap::default(), Heap::default(),
features,
limits, limits,
adapter_info, adapter_info,
adapter_id, adapter_id,

View file

@ -9,9 +9,10 @@ use dom_struct::dom_struct;
use js::jsapi::{Heap, JSObject}; use js::jsapi::{Heap, JSObject};
use webgpu::{wgt, WebGPU, WebGPUAdapter, WebGPURequest, WebGPUResponse, WebGPUResponseResult}; use webgpu::{wgt, WebGPU, WebGPUAdapter, WebGPURequest, WebGPUResponse, WebGPUResponseResult};
use super::gpusupportedfeatures::GPUSupportedFeatures;
use super::types::{GPUAdapterInfo, GPUSupportedLimits}; use super::types::{GPUAdapterInfo, GPUSupportedLimits};
use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::{ use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::{
GPUAdapterMethods, GPUDeviceDescriptor, GPUFeatureName, GPUAdapterMethods, GPUDeviceDescriptor,
}; };
use crate::dom::bindings::error::Error; use crate::dom::bindings::error::Error;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
@ -20,6 +21,7 @@ use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::gpu::{response_async, AsyncWGPUListener}; use crate::dom::gpu::{response_async, AsyncWGPUListener};
use crate::dom::gpudevice::GPUDevice; use crate::dom::gpudevice::GPUDevice;
use crate::dom::gpusupportedfeatures::gpu_to_wgt_feature;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::realms::InRealm; use crate::realms::InRealm;
@ -32,6 +34,7 @@ pub struct GPUAdapter {
name: DOMString, name: DOMString,
#[ignore_malloc_size_of = "mozjs"] #[ignore_malloc_size_of = "mozjs"]
extensions: Heap<*mut JSObject>, extensions: Heap<*mut JSObject>,
features: Dom<GPUSupportedFeatures>,
limits: Dom<GPUSupportedLimits>, limits: Dom<GPUSupportedLimits>,
info: Dom<GPUAdapterInfo>, info: Dom<GPUAdapterInfo>,
#[no_trace] #[no_trace]
@ -43,6 +46,7 @@ impl GPUAdapter {
channel: WebGPU, channel: WebGPU,
name: DOMString, name: DOMString,
extensions: Heap<*mut JSObject>, extensions: Heap<*mut JSObject>,
features: &GPUSupportedFeatures,
limits: &GPUSupportedLimits, limits: &GPUSupportedLimits,
info: &GPUAdapterInfo, info: &GPUAdapterInfo,
adapter: WebGPUAdapter, adapter: WebGPUAdapter,
@ -52,6 +56,7 @@ impl GPUAdapter {
channel, channel,
name, name,
extensions, extensions,
features: Dom::from_ref(features),
limits: Dom::from_ref(limits), limits: Dom::from_ref(limits),
info: Dom::from_ref(info), info: Dom::from_ref(info),
adapter, adapter,
@ -63,15 +68,17 @@ impl GPUAdapter {
channel: WebGPU, channel: WebGPU,
name: DOMString, name: DOMString,
extensions: Heap<*mut JSObject>, extensions: Heap<*mut JSObject>,
features: wgt::Features,
limits: wgt::Limits, limits: wgt::Limits,
info: wgt::AdapterInfo, info: wgt::AdapterInfo,
adapter: WebGPUAdapter, adapter: WebGPUAdapter,
) -> DomRoot<Self> { ) -> DomRoot<Self> {
let features = GPUSupportedFeatures::Constructor(global, None, features).unwrap();
let limits = GPUSupportedLimits::new(global, limits); let limits = GPUSupportedLimits::new(global, limits);
let info = GPUAdapterInfo::new(global, info); let info = GPUAdapterInfo::new(global, info);
reflect_dom_object( reflect_dom_object(
Box::new(GPUAdapter::new_inherited( Box::new(GPUAdapter::new_inherited(
channel, name, extensions, &limits, &info, adapter, channel, name, extensions, &features, &limits, &info, adapter,
)), )),
global, global,
) )
@ -86,35 +93,14 @@ impl GPUAdapterMethods for GPUAdapter {
let sender = response_async(&promise, self); let sender = response_async(&promise, self);
let mut features = wgt::Features::empty(); let mut features = wgt::Features::empty();
for &ext in descriptor.requiredFeatures.iter() { for &ext in descriptor.requiredFeatures.iter() {
match ext { if let Some(feature) = gpu_to_wgt_feature(ext) {
GPUFeatureName::Depth_clip_control => { features.insert(feature);
features.insert(wgt::Features::DEPTH_CLIP_CONTROL) } else {
}, promise.reject_error(Error::Type(format!(
GPUFeatureName::Depth24unorm_stencil8 => { "{} is not supported feature",
promise.reject_error(Error::Type(String::from( ext.as_str()
"depth24unorm_stencil8 is not supported by wgpu", )));
))); return promise;
return promise;
},
GPUFeatureName::Depth32float_stencil8 => {
features.insert(wgt::Features::DEPTH32FLOAT_STENCIL8)
},
GPUFeatureName::Pipeline_statistics_query => {
features.insert(wgt::Features::PIPELINE_STATISTICS_QUERY)
},
GPUFeatureName::Texture_compression_bc => {
features.insert(wgt::Features::TEXTURE_COMPRESSION_BC)
},
GPUFeatureName::Texture_compression_etc2 => {
features.insert(wgt::Features::TEXTURE_COMPRESSION_ETC2)
},
GPUFeatureName::Texture_compression_astc => {
features.insert(wgt::Features::TEXTURE_COMPRESSION_ASTC)
},
GPUFeatureName::Timestamp_query => features.insert(wgt::Features::TIMESTAMP_QUERY),
GPUFeatureName::Indirect_first_instance => {
features.insert(wgt::Features::INDIRECT_FIRST_INSTANCE)
},
} }
} }
@ -123,15 +109,16 @@ impl GPUAdapterMethods for GPUAdapter {
limits: wgt::Limits::default(), limits: wgt::Limits::default(),
label: None, label: None,
}; };
if let Some(lim) = &descriptor.requiredLimits { if let Some(limits) = &descriptor.requiredLimits {
for (k, v) in (*lim).iter() { for (limit, value) in (*limits).iter() {
let v = u32::try_from(*v).unwrap_or(u32::MAX); let v = u32::try_from(*value).unwrap_or(u32::MAX);
match k.as_ref() { match limit.as_ref() {
"maxTextureDimension1D" => desc.limits.max_texture_dimension_1d = v, "maxTextureDimension1D" => desc.limits.max_texture_dimension_1d = v,
"maxTextureDimension2D" => desc.limits.max_texture_dimension_2d = v, "maxTextureDimension2D" => desc.limits.max_texture_dimension_2d = v,
"maxTextureDimension3D" => desc.limits.max_texture_dimension_3d = v, "maxTextureDimension3D" => desc.limits.max_texture_dimension_3d = v,
"maxTextureArrayLayers" => desc.limits.max_texture_array_layers = v, "maxTextureArrayLayers" => desc.limits.max_texture_array_layers = v,
"maxBindGroups" => desc.limits.max_bind_groups = v, "maxBindGroups" => desc.limits.max_bind_groups = v,
"maxBindingsPerBindGroup" => desc.limits.max_bindings_per_bind_group = v,
"maxDynamicUniformBuffersPerPipelineLayout" => { "maxDynamicUniformBuffersPerPipelineLayout" => {
desc.limits.max_dynamic_uniform_buffers_per_pipeline_layout = v desc.limits.max_dynamic_uniform_buffers_per_pipeline_layout = v
}, },
@ -164,6 +151,7 @@ impl GPUAdapterMethods for GPUAdapter {
desc.limits.min_storage_buffer_offset_alignment = v desc.limits.min_storage_buffer_offset_alignment = v
}, },
"maxVertexBuffers" => desc.limits.max_vertex_buffers = v, "maxVertexBuffers" => desc.limits.max_vertex_buffers = v,
"maxBufferSize" => desc.limits.max_buffer_size = *value,
"maxVertexAttributes" => desc.limits.max_vertex_attributes = v, "maxVertexAttributes" => desc.limits.max_vertex_attributes = v,
"maxVertexBufferArrayStride" => desc.limits.max_vertex_buffer_array_stride = v, "maxVertexBufferArrayStride" => desc.limits.max_vertex_buffer_array_stride = v,
"maxInterStageShaderComponents" => { "maxInterStageShaderComponents" => {
@ -182,9 +170,10 @@ impl GPUAdapterMethods for GPUAdapter {
desc.limits.max_compute_workgroups_per_dimension = v desc.limits.max_compute_workgroups_per_dimension = v
}, },
_ => { _ => {
error!("Unknown required limit: {k} with value {v}"); error!("Unknown required limit: {limit} with value {value}");
promise.reject_error(Error::Operation); // we should reject but spec is still evolving
return promise; // promise.reject_error(Error::Operation);
// return promise;
}, },
} }
} }
@ -236,7 +225,12 @@ impl GPUAdapterMethods for GPUAdapter {
promise promise
} }
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-limits /// https://gpuweb.github.io/gpuweb/#dom-gpuadapter-features
fn Features(&self) -> DomRoot<GPUSupportedFeatures> {
DomRoot::from_ref(&self.features)
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuadapter-limits
fn Limits(&self) -> DomRoot<GPUSupportedLimits> { fn Limits(&self) -> DomRoot<GPUSupportedLimits> {
DomRoot::from_ref(&self.limits) DomRoot::from_ref(&self.limits)
} }
@ -255,6 +249,7 @@ impl AsyncWGPUListener for GPUAdapter {
self.channel.clone(), self.channel.clone(),
&self, &self,
Heap::default(), Heap::default(),
descriptor.features,
descriptor.limits, descriptor.limits,
device_id, device_id,
queue_id, queue_id,

View file

@ -82,6 +82,7 @@ use crate::dom::gpurenderbundleencoder::GPURenderBundleEncoder;
use crate::dom::gpurenderpipeline::GPURenderPipeline; use crate::dom::gpurenderpipeline::GPURenderPipeline;
use crate::dom::gpusampler::GPUSampler; use crate::dom::gpusampler::GPUSampler;
use crate::dom::gpushadermodule::GPUShaderModule; use crate::dom::gpushadermodule::GPUShaderModule;
use crate::dom::gpusupportedfeatures::GPUSupportedFeatures;
use crate::dom::gputexture::GPUTexture; use crate::dom::gputexture::GPUTexture;
use crate::dom::gpuuncapturederrorevent::GPUUncapturedErrorEvent; use crate::dom::gpuuncapturederrorevent::GPUUncapturedErrorEvent;
use crate::dom::gpuvalidationerror::GPUValidationError; use crate::dom::gpuvalidationerror::GPUValidationError;
@ -120,6 +121,7 @@ pub struct GPUDevice {
adapter: Dom<GPUAdapter>, adapter: Dom<GPUAdapter>,
#[ignore_malloc_size_of = "mozjs"] #[ignore_malloc_size_of = "mozjs"]
extensions: Heap<*mut JSObject>, extensions: Heap<*mut JSObject>,
features: Dom<GPUSupportedFeatures>,
limits: Dom<GPUSupportedLimits>, limits: Dom<GPUSupportedLimits>,
label: DomRefCell<USVString>, label: DomRefCell<USVString>,
#[no_trace] #[no_trace]
@ -136,6 +138,7 @@ impl GPUDevice {
channel: WebGPU, channel: WebGPU,
adapter: &GPUAdapter, adapter: &GPUAdapter,
extensions: Heap<*mut JSObject>, extensions: Heap<*mut JSObject>,
features: &GPUSupportedFeatures,
limits: &GPUSupportedLimits, limits: &GPUSupportedLimits,
device: webgpu::WebGPUDevice, device: webgpu::WebGPUDevice,
queue: &GPUQueue, queue: &GPUQueue,
@ -146,6 +149,7 @@ impl GPUDevice {
channel, channel,
adapter: Dom::from_ref(adapter), adapter: Dom::from_ref(adapter),
extensions, extensions,
features: Dom::from_ref(features),
limits: Dom::from_ref(limits), limits: Dom::from_ref(limits),
label: DomRefCell::new(USVString::from(label)), label: DomRefCell::new(USVString::from(label)),
device, device,
@ -165,6 +169,7 @@ impl GPUDevice {
channel: WebGPU, channel: WebGPU,
adapter: &GPUAdapter, adapter: &GPUAdapter,
extensions: Heap<*mut JSObject>, extensions: Heap<*mut JSObject>,
features: wgt::Features,
limits: wgt::Limits, limits: wgt::Limits,
device: webgpu::WebGPUDevice, device: webgpu::WebGPUDevice,
queue: webgpu::WebGPUQueue, queue: webgpu::WebGPUQueue,
@ -172,9 +177,10 @@ impl GPUDevice {
) -> DomRoot<Self> { ) -> DomRoot<Self> {
let queue = GPUQueue::new(global, channel.clone(), queue); let queue = GPUQueue::new(global, channel.clone(), queue);
let limits = GPUSupportedLimits::new(global, limits); let limits = GPUSupportedLimits::new(global, limits);
let features = GPUSupportedFeatures::Constructor(global, None, features).unwrap();
let device = reflect_dom_object( let device = reflect_dom_object(
Box::new(GPUDevice::new_inherited( Box::new(GPUDevice::new_inherited(
channel, adapter, extensions, &limits, device, &queue, label, channel, adapter, extensions, &features, &limits, device, &queue, label,
)), )),
global, global,
); );
@ -343,6 +349,11 @@ impl GPUDevice {
} }
impl GPUDeviceMethods for GPUDevice { impl GPUDeviceMethods for GPUDevice {
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-features
fn Features(&self) -> DomRoot<GPUSupportedFeatures> {
DomRoot::from_ref(&self.features)
}
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-limits /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-limits
fn Limits(&self) -> DomRoot<GPUSupportedLimits> { fn Limits(&self) -> DomRoot<GPUSupportedLimits> {
DomRoot::from_ref(&self.limits) DomRoot::from_ref(&self.limits)

View file

@ -0,0 +1,162 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
// check-tidy: no specs after this line
use std::str::FromStr;
use dom_struct::dom_struct;
use indexmap::IndexSet;
use js::rust::HandleObject;
use webgpu::wgt;
use super::bindings::like::Setlike;
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::GPUFeatureName;
use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::GPUFeatureNameValues::pairs;
use crate::dom::bindings::codegen::Bindings::GPUSupportedFeaturesBinding::GPUSupportedFeaturesMethods;
use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::reflector::{reflect_dom_object_with_proto, Reflector};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope;
// manual hash derived
// TODO: allow derivables in bindings.conf
impl std::hash::Hash for GPUFeatureName {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
core::mem::discriminant(self).hash(state);
}
}
impl Eq for GPUFeatureName {}
#[dom_struct]
pub struct GPUSupportedFeatures {
reflector: Reflector,
// internal storage for features
#[custom_trace]
internal: DomRefCell<IndexSet<GPUFeatureName>>,
}
impl GPUSupportedFeatures {
fn new(
global: &GlobalScope,
proto: Option<HandleObject>,
features: wgt::Features,
) -> DomRoot<GPUSupportedFeatures> {
let mut set = IndexSet::new();
if features.contains(wgt::Features::DEPTH_CLIP_CONTROL) {
set.insert(GPUFeatureName::Depth_clip_control);
}
if features.contains(wgt::Features::DEPTH32FLOAT_STENCIL8) {
set.insert(GPUFeatureName::Depth32float_stencil8);
}
if features.contains(wgt::Features::PIPELINE_STATISTICS_QUERY) {
set.insert(GPUFeatureName::Pipeline_statistics_query);
}
if features.contains(wgt::Features::TEXTURE_COMPRESSION_BC) {
set.insert(GPUFeatureName::Texture_compression_bc);
}
if features.contains(wgt::Features::TEXTURE_COMPRESSION_ETC2) {
set.insert(GPUFeatureName::Texture_compression_etc2);
}
if features.contains(wgt::Features::TEXTURE_COMPRESSION_ASTC) {
set.insert(GPUFeatureName::Texture_compression_astc);
}
if features.contains(wgt::Features::TIMESTAMP_QUERY) {
set.insert(GPUFeatureName::Timestamp_query);
}
if features.contains(wgt::Features::INDIRECT_FIRST_INSTANCE) {
set.insert(GPUFeatureName::Indirect_first_instance);
}
reflect_dom_object_with_proto(
Box::new(GPUSupportedFeatures {
reflector: Reflector::new(),
internal: DomRefCell::new(set),
}),
global,
proto,
)
}
#[allow(non_snake_case)]
pub fn Constructor(
global: &GlobalScope,
proto: Option<HandleObject>,
features: wgt::Features,
) -> Fallible<DomRoot<GPUSupportedFeatures>> {
Ok(GPUSupportedFeatures::new(global, proto, features))
}
}
impl GPUSupportedFeaturesMethods for GPUSupportedFeatures {
fn Size(&self) -> u32 {
self.internal.size()
}
}
pub fn gpu_to_wgt_feature(feature: GPUFeatureName) -> Option<wgt::Features> {
match feature {
GPUFeatureName::Depth_clip_control => Some(wgt::Features::DEPTH_CLIP_CONTROL),
GPUFeatureName::Depth24unorm_stencil8 => None,
GPUFeatureName::Depth32float_stencil8 => Some(wgt::Features::DEPTH32FLOAT_STENCIL8),
GPUFeatureName::Pipeline_statistics_query => Some(wgt::Features::PIPELINE_STATISTICS_QUERY),
GPUFeatureName::Texture_compression_bc => Some(wgt::Features::TEXTURE_COMPRESSION_BC),
GPUFeatureName::Texture_compression_etc2 => Some(wgt::Features::TEXTURE_COMPRESSION_ETC2),
GPUFeatureName::Texture_compression_astc => Some(wgt::Features::TEXTURE_COMPRESSION_ASTC),
GPUFeatureName::Timestamp_query => Some(wgt::Features::TIMESTAMP_QUERY),
GPUFeatureName::Indirect_first_instance => Some(wgt::Features::INDIRECT_FIRST_INSTANCE),
}
}
// this should be autogenerate by bindings
impl FromStr for GPUFeatureName {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
pairs
.iter()
.find(|&&(key, _)| s == key)
.map(|&(_, ev)| ev)
.ok_or(())
}
}
// this error is wrong because if we inline Self::Key and Self::Value all errors are gone
#[allow(unrooted_must_root)]
impl Setlike for GPUSupportedFeatures {
type Key = DOMString;
#[inline(always)]
fn get_index(&self, index: u32) -> Option<Self::Key> {
self.internal
.get_index(index)
.map(|k| DOMString::from_string(k.as_str().to_owned()))
}
#[inline(always)]
fn size(&self) -> u32 {
self.internal.size()
}
#[inline(always)]
fn add(&self, _key: Self::Key) {
unreachable!("readonly");
}
#[inline(always)]
fn has(&self, key: Self::Key) -> bool {
if let Ok(key) = key.parse() {
self.internal.has(key)
} else {
false
}
}
#[inline(always)]
fn clear(&self) {
unreachable!("readonly");
}
#[inline(always)]
fn delete(&self, _key: Self::Key) -> bool {
unreachable!("readonly");
}
}

View file

@ -59,6 +59,11 @@ impl GPUSupportedLimitsMethods for GPUSupportedLimits {
self.limits.max_bind_groups self.limits.max_bind_groups
} }
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxbindingsperbindgroup
fn MaxBindingsPerBindGroup(&self) -> u32 {
self.limits.max_bindings_per_bind_group
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxdynamicuniformbuffersperpipelinelayout /// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxdynamicuniformbuffersperpipelinelayout
fn MaxDynamicUniformBuffersPerPipelineLayout(&self) -> u32 { fn MaxDynamicUniformBuffersPerPipelineLayout(&self) -> u32 {
self.limits.max_dynamic_uniform_buffers_per_pipeline_layout self.limits.max_dynamic_uniform_buffers_per_pipeline_layout
@ -95,13 +100,13 @@ impl GPUSupportedLimitsMethods for GPUSupportedLimits {
} }
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxuniformbufferbindingsize /// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxuniformbufferbindingsize
fn MaxUniformBufferBindingSize(&self) -> u32 { fn MaxUniformBufferBindingSize(&self) -> u64 {
self.limits.max_uniform_buffer_binding_size self.limits.max_uniform_buffer_binding_size as u64
} }
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxstoragebufferbindingsize /// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxstoragebufferbindingsize
fn MaxStorageBufferBindingSize(&self) -> u32 { fn MaxStorageBufferBindingSize(&self) -> u64 {
self.limits.max_storage_buffer_binding_size self.limits.max_storage_buffer_binding_size as u64
} }
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-minuniformbufferoffsetalignment /// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-minuniformbufferoffsetalignment
@ -119,6 +124,11 @@ impl GPUSupportedLimitsMethods for GPUSupportedLimits {
self.limits.max_vertex_buffers self.limits.max_vertex_buffers
} }
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxbuffersize
fn MaxBufferSize(&self) -> u64 {
self.limits.max_buffer_size
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxvertexattributes /// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxvertexattributes
fn MaxVertexAttributes(&self) -> u32 { fn MaxVertexAttributes(&self) -> u32 {
self.limits.max_vertex_attributes self.limits.max_vertex_attributes

View file

@ -348,6 +348,7 @@ pub mod gpurenderpipeline;
pub mod gpusampler; pub mod gpusampler;
pub mod gpushadermodule; pub mod gpushadermodule;
pub mod gpushaderstage; pub mod gpushaderstage;
pub mod gpusupportedfeatures;
pub mod gpusupportedlimits; pub mod gpusupportedlimits;
pub mod gputexture; pub mod gputexture;
pub mod gputextureusage; pub mod gputextureusage;

View file

@ -5,7 +5,7 @@
// https://gpuweb.github.io/gpuweb/#gpuadapter // https://gpuweb.github.io/gpuweb/#gpuadapter
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"] [Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPUAdapter { interface GPUAdapter {
//[SameObject] readonly attribute GPUSupportedFeatures features; [SameObject] readonly attribute GPUSupportedFeatures features;
[SameObject] readonly attribute GPUSupportedLimits limits; [SameObject] readonly attribute GPUSupportedLimits limits;
readonly attribute boolean isFallbackAdapter; readonly attribute boolean isFallbackAdapter;

View file

@ -5,7 +5,7 @@
// https://gpuweb.github.io/gpuweb/#gpudevice // https://gpuweb.github.io/gpuweb/#gpudevice
[Exposed=(Window, DedicatedWorker), /*Serializable,*/ Pref="dom.webgpu.enabled"] [Exposed=(Window, DedicatedWorker), /*Serializable,*/ Pref="dom.webgpu.enabled"]
interface GPUDevice: EventTarget { interface GPUDevice: EventTarget {
//[SameObject] readonly attribute GPUSupportedFeatures features; [SameObject] readonly attribute GPUSupportedFeatures features;
[SameObject] readonly attribute GPUSupportedLimits limits; [SameObject] readonly attribute GPUSupportedLimits limits;
// Overriding the name to avoid collision with `class Queue` in gcc // Overriding the name to avoid collision with `class Queue` in gcc

View file

@ -10,6 +10,8 @@ interface GPUSupportedLimits {
readonly attribute unsigned long maxTextureDimension3D; readonly attribute unsigned long maxTextureDimension3D;
readonly attribute unsigned long maxTextureArrayLayers; readonly attribute unsigned long maxTextureArrayLayers;
readonly attribute unsigned long maxBindGroups; readonly attribute unsigned long maxBindGroups;
//readonly attribute unsigned long maxBindGroupsPlusVertexBuffers;
readonly attribute unsigned long maxBindingsPerBindGroup;
readonly attribute unsigned long maxDynamicUniformBuffersPerPipelineLayout; readonly attribute unsigned long maxDynamicUniformBuffersPerPipelineLayout;
readonly attribute unsigned long maxDynamicStorageBuffersPerPipelineLayout; readonly attribute unsigned long maxDynamicStorageBuffersPerPipelineLayout;
readonly attribute unsigned long maxSampledTexturesPerShaderStage; readonly attribute unsigned long maxSampledTexturesPerShaderStage;
@ -17,14 +19,18 @@ interface GPUSupportedLimits {
readonly attribute unsigned long maxStorageBuffersPerShaderStage; readonly attribute unsigned long maxStorageBuffersPerShaderStage;
readonly attribute unsigned long maxStorageTexturesPerShaderStage; readonly attribute unsigned long maxStorageTexturesPerShaderStage;
readonly attribute unsigned long maxUniformBuffersPerShaderStage; readonly attribute unsigned long maxUniformBuffersPerShaderStage;
readonly attribute unsigned long maxUniformBufferBindingSize; readonly attribute unsigned long long maxUniformBufferBindingSize;
readonly attribute unsigned long maxStorageBufferBindingSize; readonly attribute unsigned long long maxStorageBufferBindingSize;
readonly attribute unsigned long minUniformBufferOffsetAlignment; readonly attribute unsigned long minUniformBufferOffsetAlignment;
readonly attribute unsigned long minStorageBufferOffsetAlignment; readonly attribute unsigned long minStorageBufferOffsetAlignment;
readonly attribute unsigned long maxVertexBuffers; readonly attribute unsigned long maxVertexBuffers;
readonly attribute unsigned long long maxBufferSize;
readonly attribute unsigned long maxVertexAttributes; readonly attribute unsigned long maxVertexAttributes;
readonly attribute unsigned long maxVertexBufferArrayStride; readonly attribute unsigned long maxVertexBufferArrayStride;
readonly attribute unsigned long maxInterStageShaderComponents; readonly attribute unsigned long maxInterStageShaderComponents;
//readonly attribute unsigned long maxInterStageShaderVariables;
//readonly attribute unsigned long maxColorAttachments;
//readonly attribute unsigned long maxColorAttachmentBytesPerSample;
readonly attribute unsigned long maxComputeWorkgroupStorageSize; readonly attribute unsigned long maxComputeWorkgroupStorageSize;
readonly attribute unsigned long maxComputeInvocationsPerWorkgroup; readonly attribute unsigned long maxComputeInvocationsPerWorkgroup;
readonly attribute unsigned long maxComputeWorkgroupSizeX; readonly attribute unsigned long maxComputeWorkgroupSizeX;

View file

@ -58,6 +58,7 @@ pub enum WebGPUResponse {
RequestAdapter { RequestAdapter {
adapter_info: wgt::AdapterInfo, adapter_info: wgt::AdapterInfo,
adapter_id: WebGPUAdapter, adapter_id: WebGPUAdapter,
features: wgt::Features,
limits: wgt::Limits, limits: wgt::Limits,
channel: WebGPU, channel: WebGPU,
}, },
@ -892,13 +893,17 @@ impl<'a> WGPU<'a> {
let adapter = WebGPUAdapter(adapter_id); let adapter = WebGPUAdapter(adapter_id);
self.adapters.push(adapter); self.adapters.push(adapter);
let global = &self.global; let global = &self.global;
// TODO: can we do this lazily
let info = let info =
gfx_select!(adapter_id => global.adapter_get_info(adapter_id)).unwrap(); gfx_select!(adapter_id => global.adapter_get_info(adapter_id)).unwrap();
let limits = let limits =
gfx_select!(adapter_id => global.adapter_limits(adapter_id)).unwrap(); gfx_select!(adapter_id => global.adapter_limits(adapter_id)).unwrap();
let features =
gfx_select!(adapter_id => global.adapter_features(adapter_id)).unwrap();
if let Err(e) = sender.send(Ok(WebGPUResponse::RequestAdapter { if let Err(e) = sender.send(Ok(WebGPUResponse::RequestAdapter {
adapter_info: info, adapter_info: info,
adapter_id: adapter, adapter_id: adapter,
features,
limits, limits,
channel: WebGPU(self.sender.clone()), channel: WebGPU(self.sender.clone()),
})) { })) {

File diff suppressed because it is too large Load diff