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

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