mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Add GPUSupportedFeatures and update GPUSupportedLimits (#30359)
* GPUSupportedFeatures * New supported limits * Update expectations
This commit is contained in:
parent
6ea394a701
commit
d22d97f8c8
12 changed files with 243 additions and 17058 deletions
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
|
|
162
components/script/dom/gpusupportedfeatures.rs
Normal file
162
components/script/dom/gpusupportedfeatures.rs
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue