Upgrade whole webgpu stack (#29795)

* Allow noidl files in script/dom/webidls

* Upgrade wgpu to 0.16 and refresh whole webgpu implementation

* Update WebGPU test expectations

* misc

* MutNullableDom -> DomRefCell<Option<Dom for GPUTexture

* Direct use of GPUTextureDescriptor

* Remove config from GPUCanvasContext

* misc

* finally blue color

* gpubuffer "handle" error

* GPU object have non-null label

* gpu limits and info

* use buffer_size

* fix warnings

* Cleanup

* device destroy

* fallback adapter

* mach update-webgpu write webgpu commit hash in file

* Mising deps in CI for webgpu tests

* Updated expectations

* Fixups

* early reject

* DomRefCell<Option<Dom -> MutNullableDom for GPUTexture
This commit is contained in:
Samson 2023-08-21 01:16:46 +02:00 committed by GitHub
parent fed3491f23
commit 71e0372ac1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
96 changed files with 15612 additions and 4023 deletions

View file

@ -55,7 +55,7 @@ jobs:
run: |
python3 -m pip install --upgrade pip virtualenv
sudo apt update
sudo apt install -qy --no-install-recommends libgl1 libssl1.1 libdbus-1-3 libxcb-xfixes0-dev libxcb-shape0-dev libunwind8 libegl1-mesa
sudo apt install -qy --no-install-recommends libgl1 libssl1.1 libdbus-1-3 libxcb-xfixes0-dev libxcb-shape0-dev libunwind8 libgl1-mesa-dri mesa-vulkan-drivers libegl1-mesa
sudo apt install ./libffi6_3.2.1-8_amd64.deb
python3 ./mach bootstrap-gstreamer
- name: Sync from upstream WPT

635
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -153,7 +153,7 @@ DOMInterfaces = {
},
'GPUAdapter': {
'inRealms': ['RequestDevice'],
'inRealms': ['RequestDevice', 'RequestAdapterInfo'],
},
'GPUBuffer': {
@ -161,7 +161,7 @@ DOMInterfaces = {
},
'GPUDevice': {
'inRealms': ['PopErrorScope', 'Lost'],
'inRealms': ['PopErrorScope', 'GetLost'],
}
}

View file

@ -23,6 +23,8 @@ use std::rc::Rc;
use webgpu::wgt::PowerPreference;
use webgpu::{wgpu, WebGPUResponse, WebGPUResponseResult};
use super::bindings::codegen::Bindings::GPUTextureBinding::GPUTextureFormat;
#[dom_struct]
pub struct GPU {
reflector_: Reflector,
@ -105,7 +107,7 @@ impl GPUMethods for GPU {
let power_preference = match options.powerPreference {
Some(GPUPowerPreference::Low_power) => PowerPreference::LowPower,
Some(GPUPowerPreference::High_performance) => PowerPreference::HighPerformance,
None => PowerPreference::Default,
None => PowerPreference::default(),
};
let ids = global.wgpu_id_hub().lock().create_adapter_ids();
@ -116,6 +118,7 @@ impl GPUMethods for GPU {
wgpu::instance::RequestAdapterOptions {
power_preference,
compatible_surface: None,
force_fallback_adapter: options.forceFallbackAdapter,
},
ids,
))
@ -125,21 +128,34 @@ impl GPUMethods for GPU {
}
promise
}
// https://gpuweb.github.io/gpuweb/#dom-gpu-getpreferredcanvasformat
fn GetPreferredCanvasFormat(&self) -> GPUTextureFormat {
// TODO: real implementation
GPUTextureFormat::Rgba8unorm
}
}
impl AsyncWGPUListener for GPU {
fn handle_response(&self, response: WebGPUResponseResult, promise: &Rc<Promise>) {
match response {
Ok(WebGPUResponse::RequestAdapter {
adapter_name,
adapter_info,
adapter_id,
limits,
channel,
}) => {
let adapter = GPUAdapter::new(
&self.global(),
channel,
DOMString::from(format!("{} ({:?})", adapter_name, adapter_id.0.backend())),
DOMString::from(format!(
"{} ({:?})",
adapter_info.name,
adapter_id.0.backend()
)),
Heap::default(),
limits,
adapter_info,
adapter_id,
);
promise.resolve_native(&adapter);

View file

@ -3,11 +3,11 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::{
GPUAdapterMethods, GPUDeviceDescriptor, GPUExtensionName, GPULimits,
GPUAdapterMethods, GPUDeviceDescriptor, GPUFeatureName,
};
use crate::dom::bindings::error::Error;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope;
use crate::dom::gpu::response_async;
@ -15,13 +15,14 @@ use crate::dom::gpu::AsyncWGPUListener;
use crate::dom::gpudevice::GPUDevice;
use crate::dom::promise::Promise;
use crate::realms::InRealm;
use crate::script_runtime::JSContext as SafeJSContext;
use dom_struct::dom_struct;
use js::jsapi::{Heap, JSObject};
use std::ptr::NonNull;
use std::convert::TryFrom;
use std::rc::Rc;
use webgpu::{wgt, WebGPU, WebGPUAdapter, WebGPURequest, WebGPUResponse, WebGPUResponseResult};
use super::types::{GPUAdapterInfo, GPUSupportedLimits};
#[dom_struct]
pub struct GPUAdapter {
reflector_: Reflector,
@ -31,6 +32,8 @@ pub struct GPUAdapter {
name: DOMString,
#[ignore_malloc_size_of = "mozjs"]
extensions: Heap<*mut JSObject>,
limits: Dom<GPUSupportedLimits>,
info: Dom<GPUAdapterInfo>,
#[no_trace]
adapter: WebGPUAdapter,
}
@ -40,6 +43,8 @@ impl GPUAdapter {
channel: WebGPU,
name: DOMString,
extensions: Heap<*mut JSObject>,
limits: &GPUSupportedLimits,
info: &GPUAdapterInfo,
adapter: WebGPUAdapter,
) -> Self {
Self {
@ -47,6 +52,8 @@ impl GPUAdapter {
channel,
name,
extensions,
limits: Dom::from_ref(limits),
info: Dom::from_ref(info),
adapter,
}
}
@ -56,11 +63,15 @@ impl GPUAdapter {
channel: WebGPU,
name: DOMString,
extensions: Heap<*mut JSObject>,
limits: wgt::Limits,
info: wgt::AdapterInfo,
adapter: WebGPUAdapter,
) -> DomRoot<Self> {
let limits = GPUSupportedLimits::new(global, limits);
let info = GPUAdapterInfo::new(global, info);
reflect_dom_object(
Box::new(GPUAdapter::new_inherited(
channel, name, extensions, adapter,
channel, name, extensions, &limits, &info, adapter,
)),
global,
)
@ -68,57 +79,116 @@ impl GPUAdapter {
}
impl GPUAdapterMethods for GPUAdapter {
// https://gpuweb.github.io/gpuweb/#dom-gpuadapter-name
fn Name(&self) -> DOMString {
self.name.clone()
}
// https://gpuweb.github.io/gpuweb/#dom-gpuadapter-extensions
fn Extensions(&self, _cx: SafeJSContext) -> NonNull<JSObject> {
NonNull::new(self.extensions.get()).unwrap()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuadapter-requestdevice
fn RequestDevice(&self, descriptor: &GPUDeviceDescriptor, comp: InRealm) -> Rc<Promise> {
// Step 2
let promise = Promise::new_in_current_realm(comp);
let sender = response_async(&promise, self);
let mut features = wgt::Features::empty();
for &ext in descriptor.extensions.iter() {
if ext == GPUExtensionName::Depth_clamping {
features.insert(wgt::Features::DEPTH_CLAMPING);
} else if ext == GPUExtensionName::Texture_compression_bc {
features.insert(wgt::Features::TEXTURE_COMPRESSION_BC)
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)
},
}
}
let desc = wgt::DeviceDescriptor {
let mut desc = wgt::DeviceDescriptor {
features,
limits: wgt::Limits {
max_bind_groups: descriptor.limits.maxBindGroups,
max_dynamic_uniform_buffers_per_pipeline_layout: descriptor
.limits
.maxDynamicUniformBuffersPerPipelineLayout,
max_dynamic_storage_buffers_per_pipeline_layout: descriptor
.limits
.maxDynamicStorageBuffersPerPipelineLayout,
max_sampled_textures_per_shader_stage: descriptor
.limits
.maxSampledTexturesPerShaderStage,
max_samplers_per_shader_stage: descriptor.limits.maxSamplersPerShaderStage,
max_storage_buffers_per_shader_stage: descriptor
.limits
.maxStorageBuffersPerShaderStage,
max_storage_textures_per_shader_stage: descriptor
.limits
.maxStorageTexturesPerShaderStage,
max_uniform_buffers_per_shader_stage: descriptor
.limits
.maxUniformBuffersPerShaderStage,
max_uniform_buffer_binding_size: descriptor.limits.maxUniformBufferBindingSize,
..Default::default()
},
shader_validation: true,
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() {
"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,
"maxDynamicUniformBuffersPerPipelineLayout" => {
desc.limits.max_dynamic_uniform_buffers_per_pipeline_layout = v
},
"maxDynamicStorageBuffersPerPipelineLayout" => {
desc.limits.max_dynamic_storage_buffers_per_pipeline_layout = v
},
"maxSampledTexturesPerShaderStage" => {
desc.limits.max_sampled_textures_per_shader_stage = v
},
"maxSamplersPerShaderStage" => desc.limits.max_samplers_per_shader_stage = v,
"maxStorageBuffersPerShaderStage" => {
desc.limits.max_storage_buffers_per_shader_stage = v
},
"maxStorageTexturesPerShaderStage" => {
desc.limits.max_storage_textures_per_shader_stage = v
},
"maxUniformBuffersPerShaderStage" => {
desc.limits.max_uniform_buffers_per_shader_stage = v
},
"maxUniformBufferBindingSize" => {
desc.limits.max_uniform_buffer_binding_size = v
},
"maxStorageBufferBindingSize" => {
desc.limits.max_storage_buffer_binding_size = v
},
"minUniformBufferOffsetAlignment" => {
desc.limits.min_uniform_buffer_offset_alignment = v
},
"minStorageBufferOffsetAlignment" => {
desc.limits.min_storage_buffer_offset_alignment = v
},
"maxVertexBuffers" => desc.limits.max_vertex_buffers = v,
"maxVertexAttributes" => desc.limits.max_vertex_attributes = v,
"maxVertexBufferArrayStride" => desc.limits.max_vertex_buffer_array_stride = v,
"maxInterStageShaderComponents" => {
desc.limits.max_inter_stage_shader_components = v
},
"maxComputeWorkgroupStorageSize" => {
desc.limits.max_compute_workgroup_storage_size = v
},
"maxComputeInvocationsPerWorkgroup" => {
desc.limits.max_compute_invocations_per_workgroup = v
},
"maxComputeWorkgroupSizeX" => desc.limits.max_compute_workgroup_size_x = v,
"maxComputeWorkgroupSizeY" => desc.limits.max_compute_workgroup_size_y = v,
"maxComputeWorkgroupSizeZ" => desc.limits.max_compute_workgroup_size_z = v,
"maxComputeWorkgroupsPerDimension" => {
desc.limits.max_compute_workgroups_per_dimension = v
},
_ => {
error!("Unknown required limit: {k} with value {v}");
promise.reject_error(Error::Operation);
return promise;
},
}
}
}
let id = self
.global()
.wgpu_id_hub()
@ -136,15 +206,40 @@ impl GPUAdapterMethods for GPUAdapter {
descriptor: desc,
device_id: id,
pipeline_id,
label: descriptor.parent.label.as_ref().map(|s| s.to_string()),
},
))
.is_err()
{
promise.reject_error(Error::Operation);
}
// Step 5
promise
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuadapter-isfallbackadapter
fn IsFallbackAdapter(&self) -> bool {
//TODO
false
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuadapter-requestadapterinfo
fn RequestAdapterInfo(&self, unmask_hints: Vec<DOMString>, comp: InRealm) -> Rc<Promise> {
// XXX: Adapter info should be generated here ...
// Step 1
let promise = Promise::new_in_current_realm(comp);
// Step 4
if !unmask_hints.is_empty() {
todo!("unmaskHints on RequestAdapterInfo");
}
promise.resolve_native(&*self.info);
// Step 5
promise
}
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-limits
fn Limits(&self) -> DomRoot<GPUSupportedLimits> {
DomRoot::from_ref(&self.limits)
}
}
impl AsyncWGPUListener for GPUAdapter {
@ -154,40 +249,16 @@ impl AsyncWGPUListener for GPUAdapter {
device_id,
queue_id,
descriptor,
label,
}) => {
let limits = GPULimits {
maxBindGroups: descriptor.limits.max_bind_groups,
maxDynamicStorageBuffersPerPipelineLayout: descriptor
.limits
.max_dynamic_storage_buffers_per_pipeline_layout,
maxDynamicUniformBuffersPerPipelineLayout: descriptor
.limits
.max_dynamic_uniform_buffers_per_pipeline_layout,
maxSampledTexturesPerShaderStage: descriptor
.limits
.max_sampled_textures_per_shader_stage,
maxSamplersPerShaderStage: descriptor.limits.max_samplers_per_shader_stage,
maxStorageBuffersPerShaderStage: descriptor
.limits
.max_storage_buffers_per_shader_stage,
maxStorageTexturesPerShaderStage: descriptor
.limits
.max_storage_textures_per_shader_stage,
maxUniformBufferBindingSize: descriptor.limits.max_uniform_buffer_binding_size,
maxUniformBuffersPerShaderStage: descriptor
.limits
.max_uniform_buffers_per_shader_stage,
};
let device = GPUDevice::new(
&self.global(),
self.channel.clone(),
&self,
Heap::default(),
limits,
descriptor.limits,
device_id,
queue_id,
label,
descriptor.label.unwrap_or_default(),
);
self.global().add_gpu_device(&device);
promise.resolve_native(&device);

View file

@ -0,0 +1,56 @@
/* 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/. */
use super::bindings::codegen::Bindings::GPUAdapterInfoBinding::GPUAdapterInfoMethods;
use super::bindings::reflector::reflect_dom_object;
use super::bindings::root::DomRoot;
use crate::dom::bindings::reflector::Reflector;
use crate::dom::globalscope::GlobalScope;
use crate::test::DOMString;
use dom_struct::dom_struct;
use webgpu::wgt::AdapterInfo;
#[dom_struct]
pub struct GPUAdapterInfo {
reflector_: Reflector,
#[ignore_malloc_size_of = "defined in wgpu-types"]
#[no_trace]
info: AdapterInfo,
}
impl GPUAdapterInfo {
fn new_inherited(info: AdapterInfo) -> Self {
Self {
reflector_: Reflector::new(),
info,
}
}
pub fn new(global: &GlobalScope, info: AdapterInfo) -> DomRoot<Self> {
reflect_dom_object(Box::new(Self::new_inherited(info)), global)
}
}
// TODO: wgpu does not expose right fields right now
impl GPUAdapterInfoMethods for GPUAdapterInfo {
/// https://gpuweb.github.io/gpuweb/#dom-gpuadapterinfo-vendor
fn Vendor(&self) -> DOMString {
DOMString::new()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuadapterinfo-architecture
fn Architecture(&self) -> DOMString {
DOMString::new()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuadapterinfo-device
fn Device(&self) -> DOMString {
DOMString::new()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuadapterinfo-description
fn Description(&self) -> DOMString {
DOMString::from_string(self.info.driver_info.clone())
}
}

View file

@ -15,7 +15,7 @@ use webgpu::{WebGPUBindGroup, WebGPUDevice};
#[dom_struct]
pub struct GPUBindGroup {
reflector_: Reflector,
label: DomRefCell<Option<USVString>>,
label: DomRefCell<USVString>,
#[no_trace]
bind_group: WebGPUBindGroup,
#[no_trace]
@ -28,7 +28,7 @@ impl GPUBindGroup {
bind_group: WebGPUBindGroup,
device: WebGPUDevice,
layout: &GPUBindGroupLayout,
label: Option<USVString>,
label: USVString,
) -> Self {
Self {
reflector_: Reflector::new(),
@ -44,7 +44,7 @@ impl GPUBindGroup {
bind_group: WebGPUBindGroup,
device: WebGPUDevice,
layout: &GPUBindGroupLayout,
label: Option<USVString>,
label: USVString,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPUBindGroup::new_inherited(
@ -63,12 +63,12 @@ impl GPUBindGroup {
impl GPUBindGroupMethods for GPUBindGroup {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
fn SetLabel(&self, value: USVString) {
*self.label.borrow_mut() = value;
}
}

View file

@ -14,13 +14,13 @@ use webgpu::WebGPUBindGroupLayout;
#[dom_struct]
pub struct GPUBindGroupLayout {
reflector_: Reflector,
label: DomRefCell<Option<USVString>>,
label: DomRefCell<USVString>,
#[no_trace]
bind_group_layout: WebGPUBindGroupLayout,
}
impl GPUBindGroupLayout {
fn new_inherited(bind_group_layout: WebGPUBindGroupLayout, label: Option<USVString>) -> Self {
fn new_inherited(bind_group_layout: WebGPUBindGroupLayout, label: USVString) -> Self {
Self {
reflector_: Reflector::new(),
label: DomRefCell::new(label),
@ -31,7 +31,7 @@ impl GPUBindGroupLayout {
pub fn new(
global: &GlobalScope,
bind_group_layout: WebGPUBindGroupLayout,
label: Option<USVString>,
label: USVString,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPUBindGroupLayout::new_inherited(bind_group_layout, label)),
@ -48,12 +48,12 @@ impl GPUBindGroupLayout {
impl GPUBindGroupLayoutMethods for GPUBindGroupLayout {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
fn SetLabel(&self, value: USVString) {
*self.label.borrow_mut() = value;
}
}

View file

@ -61,7 +61,7 @@ pub struct GPUBuffer {
#[ignore_malloc_size_of = "defined in webgpu"]
#[no_trace]
channel: WebGPU,
label: DomRefCell<Option<USVString>>,
label: DomRefCell<USVString>,
state: Cell<GPUBufferState>,
#[no_trace]
buffer: WebGPUBuffer,
@ -80,7 +80,7 @@ impl GPUBuffer {
state: GPUBufferState,
size: GPUSize64,
map_info: DomRefCell<Option<GPUBufferMapInfo>>,
label: Option<USVString>,
label: USVString,
) -> Self {
Self {
reflector_: Reflector::new(),
@ -104,7 +104,7 @@ impl GPUBuffer {
state: GPUBufferState,
size: GPUSize64,
map_info: DomRefCell<Option<GPUBufferMapInfo>>,
label: Option<USVString>,
label: USVString,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPUBuffer::new_inherited(
@ -127,20 +127,22 @@ impl GPUBuffer {
impl Drop for GPUBuffer {
fn drop(&mut self) {
self.Destroy()
if let Err(e) = self.Destroy() {
error!("GPUBuffer destruction failed with {e:?}!"); // TODO: should we allow panic here?
};
}
}
impl GPUBufferMethods for GPUBuffer {
#[allow(unsafe_code)]
/// https://gpuweb.github.io/gpuweb/#dom-gpubuffer-unmap
fn Unmap(&self) {
fn Unmap(&self) -> Fallible<()> {
let cx = GlobalScope::get_cx();
// Step 1
match self.state.get() {
GPUBufferState::Unmapped | GPUBufferState::Destroyed => {
// TODO: Record validation error on the current scope
return;
return Ok(());
},
// Step 3
GPUBufferState::Mapped | GPUBufferState::MappedAtCreation => {
@ -176,16 +178,17 @@ impl GPUBufferMethods for GPUBuffer {
// Step 4
self.state.set(GPUBufferState::Unmapped);
*self.map_info.borrow_mut() = None;
Ok(())
}
/// https://gpuweb.github.io/gpuweb/#dom-gpubuffer-destroy
fn Destroy(&self) {
fn Destroy(&self) -> Fallible<()> {
let state = self.state.get();
match state {
GPUBufferState::Mapped | GPUBufferState::MappedAtCreation => {
self.Unmap();
self.Unmap()?;
},
GPUBufferState::Destroyed => return,
GPUBufferState::Destroyed => return Ok(()),
_ => {},
};
if let Err(e) = self
@ -199,6 +202,7 @@ impl GPUBufferMethods for GPUBuffer {
);
};
self.state.set(GPUBufferState::Destroyed);
Ok(())
}
#[allow(unsafe_code)]
@ -330,12 +334,12 @@ impl GPUBufferMethods for GPUBuffer {
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
fn SetLabel(&self, value: USVString) {
*self.label.borrow_mut() = value;
}
}

View file

@ -2,20 +2,19 @@
* 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/. */
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::GPUCanvasContextBinding::{
GPUCanvasContextMethods, GPUSwapChainDescriptor,
GPUCanvasConfiguration, GPUCanvasContextMethods,
};
use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::GPUDeviceBinding::GPUDeviceMethods;
use crate::dom::bindings::codegen::Bindings::GPUObjectBaseBinding::GPUObjectDescriptorBase;
use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::{
GPUExtent3D, GPUExtent3DDict, GPUTextureDescriptor, GPUTextureDimension, GPUTextureFormat,
};
use crate::dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementBinding::HTMLCanvasElementMethods;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom};
use crate::dom::bindings::root::{DomRoot, LayoutDom};
use crate::dom::globalscope::GlobalScope;
use crate::dom::gpuswapchain::GPUSwapChain;
use crate::dom::htmlcanvaselement::{HTMLCanvasElement, LayoutCanvasRenderingContextHelpers};
use crate::dom::node::{document_from_node, Node, NodeDamage};
use arrayvec::ArrayVec;
@ -24,33 +23,98 @@ use euclid::default::Size2D;
use ipc_channel::ipc;
use script_layout_interface::HTMLCanvasDataSource;
use std::cell::Cell;
use webgpu::WebGPUTexture;
use webgpu::{wgpu::id, wgt, WebGPU, WebGPURequest, PRESENTATION_BUFFER_COUNT};
use webrender_api::{
units, ExternalImageData, ExternalImageId, ExternalImageType, ImageData, ImageDescriptor,
ImageDescriptorFlags, ImageFormat, ImageKey,
};
use super::bindings::codegen::Bindings::GPUTextureUsageBinding::GPUTextureUsageConstants;
use super::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas;
use super::bindings::error::{Error, Fallible};
use super::bindings::root::MutNullableDom;
use super::gputexture::GPUTexture;
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd)]
pub struct WebGPUContextId(pub u64);
// TODO: make all this derivables available via new Bindings.conf option
impl Clone for GPUCanvasConfiguration {
fn clone(&self) -> Self {
Self {
alphaMode: self.alphaMode.clone(),
device: self.device.clone(),
format: self.format.clone(),
usage: self.usage.clone(),
viewFormats: self.viewFormats.clone(),
}
}
}
impl Clone for HTMLCanvasElementOrOffscreenCanvas {
fn clone(&self) -> Self {
match self {
Self::HTMLCanvasElement(arg0) => Self::HTMLCanvasElement(arg0.clone()),
Self::OffscreenCanvas(arg0) => Self::OffscreenCanvas(arg0.clone()),
}
}
}
impl malloc_size_of::MallocSizeOf for GPUTextureDescriptor {
fn size_of(&self, ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
match self {
Self {
parent,
dimension,
format,
mipLevelCount,
sampleCount,
size,
usage,
viewFormats,
} => {
parent.size_of(ops) +
dimension.size_of(ops) +
format.size_of(ops) +
mipLevelCount.size_of(ops) +
sampleCount.size_of(ops) +
size.size_of(ops) +
usage.size_of(ops) +
viewFormats.size_of(ops)
},
}
}
}
impl malloc_size_of::MallocSizeOf for HTMLCanvasElementOrOffscreenCanvas {
fn size_of(&self, ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
match self {
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => canvas.size_of(ops),
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => canvas.size_of(ops),
}
}
}
#[dom_struct]
pub struct GPUCanvasContext {
reflector_: Reflector,
#[ignore_malloc_size_of = "channels are hard"]
#[no_trace]
channel: WebGPU,
canvas: Dom<HTMLCanvasElement>,
#[no_trace]
size: Cell<Size2D<u32>>,
swap_chain: DomRefCell<Option<Dom<GPUSwapChain>>>,
/// https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-canvas
canvas: HTMLCanvasElementOrOffscreenCanvas,
// TODO: can we have wgpu surface that is hw accelerated inside wr ...
#[ignore_malloc_size_of = "Defined in webrender"]
#[no_trace]
webrender_image: Cell<Option<webrender_api::ImageKey>>,
context_id: WebGPUContextId,
/// https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-currenttexture-slot
texture: MutNullableDom<GPUTexture>,
}
impl GPUCanvasContext {
fn new_inherited(canvas: &HTMLCanvasElement, size: Size2D<u32>, channel: WebGPU) -> Self {
fn new_inherited(canvas: HTMLCanvasElementOrOffscreenCanvas, channel: WebGPU) -> Self {
let (sender, receiver) = ipc::channel().unwrap();
if let Err(e) = channel.0.send((None, WebGPURequest::CreateContext(sender))) {
warn!("Failed to send CreateContext ({:?})", e);
@ -59,22 +123,19 @@ impl GPUCanvasContext {
Self {
reflector_: Reflector::new(),
channel,
canvas: Dom::from_ref(canvas),
size: Cell::new(size),
swap_chain: DomRefCell::new(None),
canvas,
webrender_image: Cell::new(None),
context_id: WebGPUContextId(external_id.0),
texture: MutNullableDom::default(),
}
}
pub fn new(
global: &GlobalScope,
canvas: &HTMLCanvasElement,
size: Size2D<u32>,
channel: WebGPU,
) -> DomRoot<Self> {
pub fn new(global: &GlobalScope, canvas: &HTMLCanvasElement, channel: WebGPU) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPUCanvasContext::new_inherited(canvas, size, channel)),
Box::new(GPUCanvasContext::new_inherited(
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(canvas)),
channel,
)),
global,
)
}
@ -91,7 +152,7 @@ impl GPUCanvasContext {
}
pub fn send_swap_chain_present(&self) {
let texture_id = self.swap_chain.borrow().as_ref().unwrap().texture_id().0;
let texture_id = self.texture_id().unwrap().0;
let encoder_id = self
.global()
.wgpu_id_hub()
@ -116,13 +177,26 @@ impl GPUCanvasContext {
self.context_id
}
pub fn mark_as_dirty(&self) {
self.canvas
.upcast::<Node>()
.dirty(NodeDamage::OtherNodeDamage);
pub fn texture_id(&self) -> Option<WebGPUTexture> {
self.texture.get().map(|t| t.id())
}
let document = document_from_node(&*self.canvas);
document.add_dirty_webgpu_canvas(self);
pub fn mark_as_dirty(&self) {
if let HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) = &self.canvas {
canvas.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
let document = document_from_node(&**canvas);
document.add_dirty_webgpu_canvas(self);
}
// TODO(sagudev): offscreen canvas also dirty?
}
fn size(&self) -> Size2D<u64> {
match &self.canvas {
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => {
Size2D::new(canvas.Width() as u64, canvas.Height() as u64)
},
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => canvas.get_size(),
}
}
}
@ -134,37 +208,49 @@ impl LayoutCanvasRenderingContextHelpers for LayoutDom<'_, GPUCanvasContext> {
}
impl GPUCanvasContextMethods for GPUCanvasContext {
/// https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-configureswapchain
fn ConfigureSwapChain(&self, descriptor: &GPUSwapChainDescriptor) -> DomRoot<GPUSwapChain> {
if let Some(chain) = &*self.swap_chain.borrow() {
chain.destroy(self.context_id.0, self.webrender_image.get().unwrap());
self.webrender_image.set(None);
}
*self.swap_chain.borrow_mut() = None;
/// https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-canvas
fn Canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas {
self.canvas.clone()
}
let mut buffer_ids = ArrayVec::<id::BufferId, PRESENTATION_BUFFER_COUNT>::new();
for _ in 0..PRESENTATION_BUFFER_COUNT {
buffer_ids.push(
self.global()
.wgpu_id_hub()
.lock()
.create_buffer_id(descriptor.device.id().0.backend()),
);
}
/// https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-configure
fn Configure(&self, descriptor: &GPUCanvasConfiguration) {
// Step 1 is let
// Step 2
// TODO: device features
let format = match descriptor.format {
GPUTextureFormat::Rgba8unorm | GPUTextureFormat::Rgba8unorm_srgb => ImageFormat::RGBA8,
GPUTextureFormat::Bgra8unorm | GPUTextureFormat::Bgra8unorm_srgb => ImageFormat::BGRA8,
_ => panic!("SwapChain format({:?}) not supported", descriptor.format), // TODO: Better handling
};
// Step 3
// TODO: device features
// Step 4
let size = self.size();
let text_desc = GPUTextureDescriptor {
format: descriptor.format,
mipLevelCount: 1,
sampleCount: 1,
usage: descriptor.usage | GPUTextureUsageConstants::COPY_SRC, // TODO: specs
size: GPUExtent3D::GPUExtent3DDict(GPUExtent3DDict {
width: size.width as u32,
height: size.height as u32,
depthOrArrayLayers: 1,
}),
viewFormats: descriptor.viewFormats.clone(),
// other members to default
parent: GPUObjectDescriptorBase { label: None },
dimension: GPUTextureDimension::_2d,
};
// Step 8
let image_desc = ImageDescriptor {
format: match descriptor.format {
GPUTextureFormat::Rgba8unorm => ImageFormat::RGBA8,
GPUTextureFormat::Bgra8unorm => ImageFormat::BGRA8,
_ => panic!("SwapChain format({:?}) not supported", descriptor.format),
},
size: units::DeviceIntSize::new(
self.size.get().width as i32,
self.size.get().height as i32,
),
format,
size: units::DeviceIntSize::new(size.width as i32, size.height as i32),
stride: Some(
(((self.size.get().width * 4) | (wgt::COPY_BYTES_PER_ROW_ALIGNMENT - 1)) + 1)
as i32,
(((size.width as u32 * 4) | (wgt::COPY_BYTES_PER_ROW_ALIGNMENT - 1)) + 1) as i32,
),
offset: 0,
flags: ImageDescriptorFlags::from_bits(1).unwrap(),
@ -178,6 +264,16 @@ impl GPUCanvasContextMethods for GPUCanvasContext {
let (sender, receiver) = ipc::channel().unwrap();
let mut buffer_ids = ArrayVec::<id::BufferId, PRESENTATION_BUFFER_COUNT>::new();
for _ in 0..PRESENTATION_BUFFER_COUNT {
buffer_ids.push(
self.global()
.wgpu_id_hub()
.lock()
.create_buffer_id(descriptor.device.id().0.backend()),
);
}
self.channel
.0
.send((
@ -193,37 +289,42 @@ impl GPUCanvasContextMethods for GPUCanvasContext {
))
.expect("Failed to create WebGPU SwapChain");
let usage = if descriptor.usage % 2 == 0 {
descriptor.usage + 1
} else {
descriptor.usage
};
let text_desc = GPUTextureDescriptor {
parent: GPUObjectDescriptorBase { label: None },
dimension: GPUTextureDimension::_2d,
format: descriptor.format,
mipLevelCount: 1,
sampleCount: 1,
usage,
size: GPUExtent3D::GPUExtent3DDict(GPUExtent3DDict {
width: self.size.get().width,
height: self.size.get().height,
depth: 1,
}),
};
let texture = descriptor.device.CreateTexture(&text_desc);
self.texture
.set(Some(&descriptor.device.CreateTexture(&text_desc)));
self.webrender_image.set(Some(receiver.recv().unwrap()));
}
let swap_chain = GPUSwapChain::new(
&self.global(),
self.channel.clone(),
&self,
&*texture,
descriptor.parent.label.as_ref().cloned(),
);
*self.swap_chain.borrow_mut() = Some(Dom::from_ref(&*swap_chain));
swap_chain
/// https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-unconfigure
fn Unconfigure(&self) {
if let Some(image_key) = self.webrender_image.take() {
if let Err(e) = self.channel.0.send((
None,
WebGPURequest::DestroySwapChain {
external_id: self.context_id.0,
image_key,
},
)) {
warn!(
"Failed to send DestroySwapChain-ImageKey({:?}) ({})",
image_key, e
);
}
}
self.texture.take();
}
/// https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-getcurrenttexture
fn GetCurrentTexture(&self) -> Fallible<DomRoot<GPUTexture>> {
// Step 5.
self.mark_as_dirty();
// Step 6.
self.texture.get().ok_or(Error::InvalidState)
}
}
impl Drop for GPUCanvasContext {
fn drop(&mut self) {
self.Unconfigure()
}
}

View file

@ -28,7 +28,7 @@ pub struct GPUCommandBuffer {
#[ignore_malloc_size_of = "defined in webgpu"]
#[no_trace]
channel: WebGPU,
label: DomRefCell<Option<USVString>>,
label: DomRefCell<USVString>,
#[no_trace]
command_buffer: WebGPUCommandBuffer,
buffers: DomRefCell<HashSet<Dom<GPUBuffer>>>,
@ -39,7 +39,7 @@ impl GPUCommandBuffer {
channel: WebGPU,
command_buffer: WebGPUCommandBuffer,
buffers: HashSet<DomRoot<GPUBuffer>>,
label: Option<USVString>,
label: USVString,
) -> Self {
Self {
channel,
@ -55,7 +55,7 @@ impl GPUCommandBuffer {
channel: WebGPU,
command_buffer: WebGPUCommandBuffer,
buffers: HashSet<DomRoot<GPUBuffer>>,
label: Option<USVString>,
label: USVString,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPUCommandBuffer::new_inherited(
@ -95,12 +95,12 @@ impl GPUCommandBuffer {
impl GPUCommandBufferMethods for GPUCommandBuffer {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
fn SetLabel(&self, value: USVString) {
*self.label.borrow_mut() = value;
}
}

View file

@ -5,14 +5,10 @@
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUSize64;
use crate::dom::bindings::codegen::Bindings::GPUCommandEncoderBinding::{
GPUBufferCopyView, GPUCommandBufferDescriptor, GPUCommandEncoderMethods,
GPUComputePassDescriptor, GPUOrigin3D, GPURenderPassDescriptor, GPUStencilLoadValue,
GPUStoreOp, GPUTextureCopyView, GPUTextureDataLayout,
GPUCommandEncoderMethods, GPUComputePassDescriptor, GPUOrigin3D, GPURenderPassDescriptor,
GPUStoreOp,
};
use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::GPUExtent3D;
use crate::dom::bindings::codegen::UnionTypes::{
GPULoadOpOrDoubleSequenceOrGPUColorDict as GPUColorLoad, GPULoadOpOrFloat,
};
use crate::dom::bindings::num::Finite;
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
@ -31,6 +27,14 @@ use std::collections::HashSet;
use webgpu::wgpu::command as wgpu_com;
use webgpu::{self, wgt, WebGPU, WebGPURequest};
use super::bindings::codegen::Bindings::GPUCommandBufferBinding::GPUCommandBufferDescriptor;
use super::bindings::codegen::Bindings::GPUCommandEncoderBinding::{
GPUImageCopyBuffer, GPUImageCopyTexture, GPUImageDataLayout, GPULoadOp,
};
use super::bindings::codegen::Bindings::GPUTextureViewBinding::GPUTextureAspect;
use super::bindings::codegen::UnionTypes::DoubleSequenceOrGPUColorDict;
// TODO(sagudev): this is different now
// https://gpuweb.github.io/gpuweb/#enumdef-encoder-state
#[derive(MallocSizeOf, PartialEq)]
pub enum GPUCommandEncoderState {
@ -46,7 +50,7 @@ pub struct GPUCommandEncoder {
#[ignore_malloc_size_of = "defined in webgpu"]
#[no_trace]
channel: WebGPU,
label: DomRefCell<Option<USVString>>,
label: DomRefCell<USVString>,
#[no_trace]
encoder: webgpu::WebGPUCommandEncoder,
buffers: DomRefCell<HashSet<DomRoot<GPUBuffer>>>,
@ -60,7 +64,7 @@ impl GPUCommandEncoder {
channel: WebGPU,
device: &GPUDevice,
encoder: webgpu::WebGPUCommandEncoder,
label: Option<USVString>,
label: USVString,
) -> Self {
Self {
channel,
@ -79,7 +83,7 @@ impl GPUCommandEncoder {
channel: WebGPU,
device: &GPUDevice,
encoder: webgpu::WebGPUCommandEncoder,
label: Option<USVString>,
label: USVString,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPUCommandEncoder::new_inherited(
@ -107,12 +111,12 @@ impl GPUCommandEncoder {
impl GPUCommandEncoderMethods for GPUCommandEncoder {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
fn SetLabel(&self, value: USVString) {
*self.label.borrow_mut() = value;
}
@ -129,7 +133,16 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
let compute_pass = if !self.valid.get() {
None
} else {
Some(wgpu_com::ComputePass::new(self.encoder.0))
Some(wgpu_com::ComputePass::new(
self.encoder.0,
&wgpu_com::ComputePassDescriptor {
label: descriptor
.parent
.label
.as_ref()
.map(|l| Cow::Borrowed(&**l)),
},
))
};
GPUComputePassEncoder::new(
@ -137,7 +150,7 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
self.channel.clone(),
&self,
compute_pass,
descriptor.parent.label.as_ref().cloned(),
descriptor.parent.label.clone().unwrap_or_default(),
)
}
@ -155,38 +168,20 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
None
} else {
let depth_stencil = descriptor.depthStencilAttachment.as_ref().map(|depth| {
let (depth_load_op, clear_depth) = match depth.depthLoadValue {
GPULoadOpOrFloat::GPULoadOp(_) => (wgpu_com::LoadOp::Load, 0.0f32),
GPULoadOpOrFloat::Float(f) => (wgpu_com::LoadOp::Clear, *f),
};
let (stencil_load_op, clear_stencil) = match depth.stencilLoadValue {
GPUStencilLoadValue::GPULoadOp(_) => (wgpu_com::LoadOp::Load, 0u32),
GPUStencilLoadValue::RangeEnforcedUnsignedLong(l) => {
(wgpu_com::LoadOp::Clear, l)
wgpu_com::RenderPassDepthStencilAttachment {
depth: wgpu_com::PassChannel {
load_op: convert_load_op(depth.depthLoadOp),
store_op: convert_store_op(depth.depthStoreOp),
clear_value: *depth.depthClearValue.unwrap_or_default(),
read_only: depth.depthReadOnly,
},
};
let depth_channel = wgpu_com::PassChannel {
load_op: depth_load_op,
store_op: match depth.depthStoreOp {
GPUStoreOp::Store => wgpu_com::StoreOp::Store,
GPUStoreOp::Clear => wgpu_com::StoreOp::Clear,
stencil: wgpu_com::PassChannel {
load_op: convert_load_op(depth.stencilLoadOp),
store_op: convert_store_op(depth.stencilStoreOp),
clear_value: depth.stencilClearValue,
read_only: depth.stencilReadOnly,
},
clear_value: clear_depth,
read_only: depth.depthReadOnly,
};
let stencil_channel = wgpu_com::PassChannel {
load_op: stencil_load_op,
store_op: match depth.stencilStoreOp {
GPUStoreOp::Store => wgpu_com::StoreOp::Store,
GPUStoreOp::Clear => wgpu_com::StoreOp::Clear,
},
clear_value: clear_stencil,
read_only: depth.stencilReadOnly,
};
wgpu_com::DepthStencilAttachmentDescriptor {
attachment: depth.attachment.id().0,
depth: depth_channel,
stencil: stencil_channel,
view: depth.view.id().0,
}
});
@ -196,56 +191,54 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
.colorAttachments
.iter()
.map(|color| {
let (load_op, clear_value) = match color.loadValue {
GPUColorLoad::GPULoadOp(_) => {
(wgpu_com::LoadOp::Load, wgt::Color::TRANSPARENT)
},
GPUColorLoad::DoubleSequence(ref s) => {
let mut w = s.clone();
if w.len() < 3 {
w.resize(3, Finite::wrap(0.0f64));
}
w.resize(4, Finite::wrap(1.0f64));
(
wgpu_com::LoadOp::Clear,
wgt::Color {
r: *w[0],
g: *w[1],
b: *w[2],
a: *w[3],
},
)
},
GPUColorLoad::GPUColorDict(ref d) => (
wgpu_com::LoadOp::Clear,
wgt::Color {
r: *d.r,
g: *d.g,
b: *d.b,
a: *d.a,
},
),
};
let channel = wgpu_com::PassChannel {
load_op,
store_op: match color.storeOp {
GPUStoreOp::Store => wgpu_com::StoreOp::Store,
GPUStoreOp::Clear => wgpu_com::StoreOp::Clear,
load_op: convert_load_op(Some(color.loadOp)),
store_op: convert_store_op(Some(color.storeOp)),
clear_value: if let Some(clear_val) = &color.clearValue {
match clear_val {
DoubleSequenceOrGPUColorDict::DoubleSequence(s) => {
let mut w = s.clone();
if w.len() < 3 {
w.resize(3, Finite::wrap(0.0f64));
}
w.resize(4, Finite::wrap(1.0f64));
wgt::Color {
r: *w[0],
g: *w[1],
b: *w[2],
a: *w[3],
}
},
DoubleSequenceOrGPUColorDict::GPUColorDict(d) => {
wgt::Color {
r: *d.r,
g: *d.g,
b: *d.b,
a: *d.a,
}
},
}
} else {
wgt::Color::TRANSPARENT
},
clear_value,
read_only: false,
};
wgpu_com::ColorAttachmentDescriptor {
attachment: color.attachment.id().0,
Some(wgpu_com::RenderPassColorAttachment {
resolve_target: color.resolveTarget.as_ref().map(|t| t.id().0),
channel,
}
view: color.view.id().0,
})
})
.collect::<Vec<_>>(),
),
depth_stencil_attachment: depth_stencil.as_ref(),
label: descriptor
.parent
.label
.as_ref()
.map(|l| Cow::Borrowed(&**l)),
};
Some(wgpu_com::RenderPass::new(self.encoder.0, desc))
Some(wgpu_com::RenderPass::new(self.encoder.0, &desc))
};
GPURenderPassEncoder::new(
@ -253,7 +246,7 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
self.channel.clone(),
render_pass,
&self,
descriptor.parent.label.as_ref().cloned(),
descriptor.parent.label.clone().unwrap_or_default(),
)
}
@ -294,8 +287,8 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
/// https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-copybuffertotexture
fn CopyBufferToTexture(
&self,
source: &GPUBufferCopyView,
destination: &GPUTextureCopyView,
source: &GPUImageCopyBuffer,
destination: &GPUImageCopyTexture,
copy_size: GPUExtent3D,
) {
if !(*self.state.borrow() == GPUCommandEncoderState::Open) {
@ -313,8 +306,8 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
None,
WebGPURequest::CopyBufferToTexture {
command_encoder_id: self.encoder.0,
source: convert_buffer_cv(source),
destination: convert_texture_cv(destination),
source: convert_ic_buffer(source),
destination: convert_ic_texture(destination),
copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict(
&copy_size,
)),
@ -323,11 +316,11 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
.expect("Failed to send CopyBufferToTexture");
}
/// https://gpuweb.github.io/gpuweb/#GPUCommandEncoder-copyTextureToBuffer
/// https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-copybuffertotexture
fn CopyTextureToBuffer(
&self,
source: &GPUTextureCopyView,
destination: &GPUBufferCopyView,
source: &GPUImageCopyTexture,
destination: &GPUImageCopyBuffer,
copy_size: GPUExtent3D,
) {
if !(*self.state.borrow() == GPUCommandEncoderState::Open) {
@ -345,8 +338,8 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
None,
WebGPURequest::CopyTextureToBuffer {
command_encoder_id: self.encoder.0,
source: convert_texture_cv(source),
destination: convert_buffer_cv(destination),
source: convert_ic_texture(source),
destination: convert_ic_buffer(destination),
copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict(
&copy_size,
)),
@ -358,8 +351,8 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
/// https://gpuweb.github.io/gpuweb/#GPUCommandEncoder-copyTextureToTexture
fn CopyTextureToTexture(
&self,
source: &GPUTextureCopyView,
destination: &GPUTextureCopyView,
source: &GPUImageCopyTexture,
destination: &GPUImageCopyTexture,
copy_size: GPUExtent3D,
) {
if !(*self.state.borrow() == GPUCommandEncoderState::Open) {
@ -373,8 +366,8 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
None,
WebGPURequest::CopyTextureToTexture {
command_encoder_id: self.encoder.0,
source: convert_texture_cv(source),
destination: convert_texture_cv(destination),
source: convert_ic_texture(source),
destination: convert_ic_texture(destination),
copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict(
&copy_size,
)),
@ -406,24 +399,40 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
self.channel.clone(),
buffer,
self.buffers.borrow_mut().drain().collect(),
descriptor.parent.label.as_ref().cloned(),
descriptor.parent.label.clone().unwrap_or_default(),
)
}
}
fn convert_buffer_cv(buffer_cv: &GPUBufferCopyView) -> wgpu_com::BufferCopyView {
wgpu_com::BufferCopyView {
buffer: buffer_cv.buffer.id().0,
layout: convert_texture_data_layout(&buffer_cv.parent),
fn convert_load_op(op: Option<GPULoadOp>) -> wgpu_com::LoadOp {
match op {
Some(GPULoadOp::Load) => wgpu_com::LoadOp::Load,
Some(GPULoadOp::Clear) => wgpu_com::LoadOp::Clear,
None => wgpu_com::LoadOp::Clear,
}
}
pub fn convert_texture_cv(texture_cv: &GPUTextureCopyView) -> wgpu_com::TextureCopyView {
wgpu_com::TextureCopyView {
texture: texture_cv.texture.id().0,
mip_level: texture_cv.mipLevel,
origin: match texture_cv.origin {
GPUOrigin3D::RangeEnforcedUnsignedLongSequence(ref v) => {
fn convert_store_op(op: Option<GPUStoreOp>) -> wgpu_com::StoreOp {
match op {
Some(GPUStoreOp::Store) => wgpu_com::StoreOp::Store,
Some(GPUStoreOp::Discard) => wgpu_com::StoreOp::Discard,
None => wgpu_com::StoreOp::Discard,
}
}
fn convert_ic_buffer(ic_buffer: &GPUImageCopyBuffer) -> wgpu_com::ImageCopyBuffer {
wgpu_com::ImageCopyBuffer {
buffer: ic_buffer.buffer.id().0,
layout: convert_image_data_layout(&ic_buffer.parent),
}
}
pub fn convert_ic_texture(ic_texture: &GPUImageCopyTexture) -> wgpu_com::ImageCopyTexture {
wgpu_com::ImageCopyTexture {
texture: ic_texture.texture.id().0,
mip_level: ic_texture.mipLevel,
origin: match ic_texture.origin {
Some(GPUOrigin3D::RangeEnforcedUnsignedLongSequence(ref v)) => {
let mut w = v.clone();
w.resize(3, 0);
wgt::Origin3d {
@ -432,17 +441,23 @@ pub fn convert_texture_cv(texture_cv: &GPUTextureCopyView) -> wgpu_com::TextureC
z: w[2],
}
},
GPUOrigin3D::GPUOrigin3DDict(ref d) => wgt::Origin3d {
Some(GPUOrigin3D::GPUOrigin3DDict(ref d)) => wgt::Origin3d {
x: d.x,
y: d.y,
z: d.z,
},
None => wgt::Origin3d::default(),
},
aspect: match ic_texture.aspect {
GPUTextureAspect::All => wgt::TextureAspect::All,
GPUTextureAspect::Stencil_only => wgt::TextureAspect::StencilOnly,
GPUTextureAspect::Depth_only => wgt::TextureAspect::DepthOnly,
},
}
}
pub fn convert_texture_data_layout(data_layout: &GPUTextureDataLayout) -> wgt::TextureDataLayout {
wgt::TextureDataLayout {
pub fn convert_image_data_layout(data_layout: &GPUImageDataLayout) -> wgt::ImageDataLayout {
wgt::ImageDataLayout {
offset: data_layout.offset as wgt::BufferAddress,
bytes_per_row: data_layout.bytesPerRow,
rows_per_image: data_layout.rowsPerImage,

View file

@ -0,0 +1,27 @@
/* 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/. */
use crate::dom::bindings::reflector::Reflector;
use crate::script_runtime::JSContext;
use dom_struct::dom_struct;
use js::jsval::JSVal;
use super::bindings::codegen::Bindings::GPUCompilationInfoBinding::GPUCompilationInfoMethods;
use super::bindings::root::Dom;
use super::types::GPUCompilationMessage;
#[dom_struct]
pub struct GPUCompilationInfo {
reflector_: Reflector,
msg: Dom<GPUCompilationMessage>,
}
// TODO: wgpu does not expose right fields right now
impl GPUCompilationInfoMethods for GPUCompilationInfo {
/// https://gpuweb.github.io/gpuweb/#dom-gpucompilationinfo-messages
fn Messages(&self, _cx: JSContext) -> JSVal {
todo!()
}
}

View file

@ -0,0 +1,98 @@
/* 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/. */
#![allow(dead_code)] // this file is stub as wgpu does not provide info
use crate::dom::bindings::reflector::Reflector;
use crate::test::DOMString;
use dom_struct::dom_struct;
use super::bindings::codegen::Bindings::GPUCompilationMessageBinding::{
GPUCompilationMessageMethods, GPUCompilationMessageType,
};
use super::bindings::root::DomRoot;
use super::types::GlobalScope;
use crate::dom::bindings::reflector::reflect_dom_object;
#[dom_struct]
pub struct GPUCompilationMessage {
reflector_: Reflector,
// #[ignore_malloc_size_of = "defined in wgpu-types"]
message: DOMString,
mtype: GPUCompilationMessageType,
line_num: u64,
line_pos: u64,
offset: u64,
length: u64,
}
impl GPUCompilationMessage {
fn new_inherited(
message: DOMString,
mtype: GPUCompilationMessageType,
line_num: u64,
line_pos: u64,
offset: u64,
length: u64,
) -> Self {
Self {
reflector_: Reflector::new(),
message,
mtype,
line_num,
line_pos,
offset,
length,
}
}
pub fn new(
global: &GlobalScope,
message: DOMString,
mtype: GPUCompilationMessageType,
line_num: u64,
line_pos: u64,
offset: u64,
length: u64,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(Self::new_inherited(
message, mtype, line_num, line_pos, offset, length,
)),
global,
)
}
}
impl GPUCompilationMessageMethods for GPUCompilationMessage {
/// https://gpuweb.github.io/gpuweb/#dom-gpucompilationmessage-message
fn Message(&self) -> DOMString {
self.message.to_owned()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpucompilationmessage-type
fn Type(&self) -> GPUCompilationMessageType {
self.mtype
}
/// https://gpuweb.github.io/gpuweb/#dom-gpucompilationmessage-linenum
fn LineNum(&self) -> u64 {
self.line_num
}
/// https://gpuweb.github.io/gpuweb/#dom-gpucompilationmessage-linepos
fn LinePos(&self) -> u64 {
self.line_pos
}
/// https://gpuweb.github.io/gpuweb/#dom-gpucompilationmessage-offset
fn Offset(&self) -> u64 {
self.offset
}
/// https://gpuweb.github.io/gpuweb/#dom-gpucompilationmessage-length
fn Length(&self) -> u64 {
self.length
}
}

View file

@ -18,13 +18,15 @@ use webgpu::{
WebGPU, WebGPURequest,
};
use super::bindings::error::Fallible;
#[dom_struct]
pub struct GPUComputePassEncoder {
reflector_: Reflector,
#[ignore_malloc_size_of = "defined in webgpu"]
#[no_trace]
channel: WebGPU,
label: DomRefCell<Option<USVString>>,
label: DomRefCell<USVString>,
#[ignore_malloc_size_of = "defined in wgpu-core"]
#[no_trace]
compute_pass: DomRefCell<Option<ComputePass>>,
@ -36,7 +38,7 @@ impl GPUComputePassEncoder {
channel: WebGPU,
parent: &GPUCommandEncoder,
compute_pass: Option<ComputePass>,
label: Option<USVString>,
label: USVString,
) -> Self {
Self {
channel,
@ -52,7 +54,7 @@ impl GPUComputePassEncoder {
channel: WebGPU,
parent: &GPUCommandEncoder,
compute_pass: Option<ComputePass>,
label: Option<USVString>,
label: USVString,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPUComputePassEncoder::new_inherited(
@ -68,26 +70,26 @@ impl GPUComputePassEncoder {
impl GPUComputePassEncoderMethods for GPUComputePassEncoder {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
fn SetLabel(&self, value: USVString) {
*self.label.borrow_mut() = value;
}
/// https://gpuweb.github.io/gpuweb/#dom-gpucomputepassencoder-dispatch
fn Dispatch(&self, x: u32, y: u32, z: u32) {
/// https://gpuweb.github.io/gpuweb/#dom-gpucomputepassencoder-dispatchworkgroups
fn DispatchWorkgroups(&self, x: u32, y: u32, z: u32) {
if let Some(compute_pass) = self.compute_pass.borrow_mut().as_mut() {
wgpu_comp::wgpu_compute_pass_dispatch(compute_pass, x, y, z);
wgpu_comp::wgpu_compute_pass_dispatch_workgroups(compute_pass, x, y, z);
}
}
/// https://gpuweb.github.io/gpuweb/#dom-gpucomputepassencoder-dispatchindirect
fn DispatchIndirect(&self, indirect_buffer: &GPUBuffer, indirect_offset: u64) {
/// https://gpuweb.github.io/gpuweb/#dom-gpucomputepassencoder-dispatchworkgroupsindirect
fn DispatchWorkgroupsIndirect(&self, indirect_buffer: &GPUBuffer, indirect_offset: u64) {
if let Some(compute_pass) = self.compute_pass.borrow_mut().as_mut() {
wgpu_comp::wgpu_compute_pass_dispatch_indirect(
wgpu_comp::wgpu_compute_pass_dispatch_workgroups_indirect(
compute_pass,
indirect_buffer.id().0,
indirect_offset,
@ -96,7 +98,7 @@ impl GPUComputePassEncoderMethods for GPUComputePassEncoder {
}
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-endpass
fn EndPass(&self) {
fn End(&self) -> Fallible<()> {
let compute_pass = self.compute_pass.borrow_mut().take();
self.channel
.0
@ -107,12 +109,13 @@ impl GPUComputePassEncoderMethods for GPUComputePassEncoder {
compute_pass,
},
))
.expect("Failed to send RunComputePass");
.expect("Failed to send RunComputePass"); //TODO: handle error
self.command_encoder.set_state(
GPUCommandEncoderState::Open,
GPUCommandEncoderState::EncodingComputePass,
);
Ok(())
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuprogrammablepassencoder-setbindgroup

View file

@ -18,7 +18,7 @@ use webgpu::{WebGPUBindGroupLayout, WebGPUComputePipeline};
#[dom_struct]
pub struct GPUComputePipeline {
reflector_: Reflector,
label: DomRefCell<Option<USVString>>,
label: DomRefCell<USVString>,
#[no_trace]
compute_pipeline: WebGPUComputePipeline,
#[no_trace]
@ -29,7 +29,7 @@ pub struct GPUComputePipeline {
impl GPUComputePipeline {
fn new_inherited(
compute_pipeline: WebGPUComputePipeline,
label: Option<USVString>,
label: USVString,
bgls: Vec<WebGPUBindGroupLayout>,
device: &GPUDevice,
) -> Self {
@ -45,7 +45,7 @@ impl GPUComputePipeline {
pub fn new(
global: &GlobalScope,
compute_pipeline: WebGPUComputePipeline,
label: Option<USVString>,
label: USVString,
bgls: Vec<WebGPUBindGroupLayout>,
device: &GPUDevice,
) -> DomRoot<Self> {
@ -69,12 +69,12 @@ impl GPUComputePipeline {
impl GPUComputePipelineMethods for GPUComputePipeline {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
fn SetLabel(&self, value: USVString) {
*self.label.borrow_mut() = value;
}
@ -86,7 +86,7 @@ impl GPUComputePipelineMethods for GPUComputePipeline {
Ok(GPUBindGroupLayout::new(
&self.global(),
self.bind_group_layouts[index as usize],
None,
USVString::default(),
))
}
}

File diff suppressed because it is too large Load diff

View file

@ -11,22 +11,33 @@ use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope;
use dom_struct::dom_struct;
use super::bindings::codegen::Bindings::GPUDeviceLostInfoBinding::GPUDeviceLostReason;
#[dom_struct]
pub struct GPUDeviceLostInfo {
reflector_: Reflector,
message: DOMString,
reason: GPUDeviceLostReason,
}
impl GPUDeviceLostInfo {
fn new_inherited(message: DOMString) -> Self {
fn new_inherited(message: DOMString, reason: GPUDeviceLostReason) -> Self {
Self {
reflector_: Reflector::new(),
message,
reason,
}
}
pub fn new(global: &GlobalScope, message: DOMString) -> DomRoot<Self> {
reflect_dom_object(Box::new(GPUDeviceLostInfo::new_inherited(message)), global)
pub fn new(
global: &GlobalScope,
message: DOMString,
reason: GPUDeviceLostReason,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPUDeviceLostInfo::new_inherited(message, reason)),
global,
)
}
}
@ -35,4 +46,9 @@ impl GPUDeviceLostInfoMethods for GPUDeviceLostInfo {
fn Message(&self) -> DOMString {
self.message.clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpudevicelostinfo-reason
fn Reason(&self) -> GPUDeviceLostReason {
self.reason
}
}

View file

@ -14,7 +14,7 @@ use webgpu::{WebGPUBindGroupLayout, WebGPUPipelineLayout};
#[dom_struct]
pub struct GPUPipelineLayout {
reflector_: Reflector,
label: DomRefCell<Option<USVString>>,
label: DomRefCell<USVString>,
#[no_trace]
pipeline_layout: WebGPUPipelineLayout,
#[no_trace]
@ -24,7 +24,7 @@ pub struct GPUPipelineLayout {
impl GPUPipelineLayout {
fn new_inherited(
pipeline_layout: WebGPUPipelineLayout,
label: Option<USVString>,
label: USVString,
bgls: Vec<WebGPUBindGroupLayout>,
) -> Self {
Self {
@ -38,7 +38,7 @@ impl GPUPipelineLayout {
pub fn new(
global: &GlobalScope,
pipeline_layout: WebGPUPipelineLayout,
label: Option<USVString>,
label: USVString,
bgls: Vec<WebGPUBindGroupLayout>,
) -> DomRoot<Self> {
reflect_dom_object(
@ -64,12 +64,12 @@ impl GPUPipelineLayout {
impl GPUPipelineLayoutMethods for GPUPipelineLayout {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
fn SetLabel(&self, value: USVString) {
*self.label.borrow_mut() = value;
}
}

View file

@ -0,0 +1,35 @@
/* 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/. */
#![allow(dead_code)] // this file is stub
use crate::dom::bindings::reflector::Reflector;
use dom_struct::dom_struct;
use super::bindings::codegen::Bindings::GPUQuerySetBinding::GPUQuerySetMethods;
use super::bindings::str::USVString;
#[dom_struct]
pub struct GPUQuerySet {
reflector_: Reflector,
// #[ignore_malloc_size_of = "defined in wgpu-types"]
}
// TODO: wgpu does not expose right fields right now
impl GPUQuerySetMethods for GPUQuerySet {
/// https://gpuweb.github.io/gpuweb/#dom-gpuqueryset-destroy
fn Destroy(&self) {
todo!()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn Label(&self) -> USVString {
todo!()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, _value: USVString) {
todo!()
}
}

View file

@ -4,9 +4,6 @@
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUSize64;
use crate::dom::bindings::codegen::Bindings::GPUCommandEncoderBinding::{
GPUTextureCopyView, GPUTextureDataLayout,
};
use crate::dom::bindings::codegen::Bindings::GPUQueueBinding::GPUQueueMethods;
use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::GPUExtent3D;
use crate::dom::bindings::codegen::UnionTypes::ArrayBufferViewOrArrayBuffer as BufferSource;
@ -17,12 +14,16 @@ use crate::dom::bindings::str::USVString;
use crate::dom::globalscope::GlobalScope;
use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState};
use crate::dom::gpucommandbuffer::GPUCommandBuffer;
use crate::dom::gpucommandencoder::{convert_texture_cv, convert_texture_data_layout};
use crate::dom::gpucommandencoder::{convert_ic_texture, convert_image_data_layout};
use crate::dom::gpudevice::{convert_texture_size_to_dict, convert_texture_size_to_wgt, GPUDevice};
use dom_struct::dom_struct;
use ipc_channel::ipc::IpcSharedMemory;
use webgpu::{identity::WebGPUOpResult, wgt, WebGPU, WebGPUQueue, WebGPURequest};
use super::bindings::codegen::Bindings::GPUCommandEncoderBinding::{
GPUImageCopyTexture, GPUImageDataLayout,
};
#[dom_struct]
pub struct GPUQueue {
reflector_: Reflector,
@ -30,7 +31,7 @@ pub struct GPUQueue {
#[no_trace]
channel: WebGPU,
device: DomRefCell<Option<Dom<GPUDevice>>>,
label: DomRefCell<Option<USVString>>,
label: DomRefCell<USVString>,
#[no_trace]
queue: WebGPUQueue,
}
@ -41,7 +42,7 @@ impl GPUQueue {
channel,
reflector_: Reflector::new(),
device: DomRefCell::new(None),
label: DomRefCell::new(None),
label: DomRefCell::new(USVString::default()),
queue,
}
}
@ -59,12 +60,12 @@ impl GPUQueue {
impl GPUQueueMethods for GPUQueue {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
fn SetLabel(&self, value: USVString) {
*self.label.borrow_mut() = value;
}
@ -149,9 +150,9 @@ impl GPUQueueMethods for GPUQueue {
/// https://gpuweb.github.io/gpuweb/#dom-gpuqueue-writetexture
fn WriteTexture(
&self,
destination: &GPUTextureCopyView,
destination: &GPUImageCopyTexture,
data: BufferSource,
data_layout: &GPUTextureDataLayout,
data_layout: &GPUImageDataLayout,
size: GPUExtent3D,
) -> Fallible<()> {
let (bytes, len) = match data {
@ -164,8 +165,8 @@ impl GPUQueueMethods for GPUQueue {
return Err(Error::Operation);
}
let texture_cv = convert_texture_cv(destination);
let texture_layout = convert_texture_data_layout(data_layout);
let texture_cv = convert_ic_texture(destination);
let texture_layout = convert_image_data_layout(data_layout);
let write_size = convert_texture_size_to_wgt(&convert_texture_size_to_dict(&size));
let final_data = IpcSharedMemory::from_bytes(&bytes);

View file

@ -21,7 +21,7 @@ pub struct GPURenderBundle {
device: WebGPUDevice,
#[no_trace]
render_bundle: WebGPURenderBundle,
label: DomRefCell<Option<USVString>>,
label: DomRefCell<USVString>,
}
impl GPURenderBundle {
@ -29,7 +29,7 @@ impl GPURenderBundle {
render_bundle: WebGPURenderBundle,
device: WebGPUDevice,
channel: WebGPU,
label: Option<USVString>,
label: USVString,
) -> Self {
Self {
reflector_: Reflector::new(),
@ -45,7 +45,7 @@ impl GPURenderBundle {
render_bundle: WebGPURenderBundle,
device: WebGPUDevice,
channel: WebGPU,
label: Option<USVString>,
label: USVString,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPURenderBundle::new_inherited(
@ -67,12 +67,12 @@ impl GPURenderBundle {
impl GPURenderBundleMethods for GPURenderBundle {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
fn SetLabel(&self, value: USVString) {
*self.label.borrow_mut() = value;
}
}

View file

@ -20,6 +20,8 @@ use webgpu::{
wgt, WebGPU, WebGPURenderBundle, WebGPURequest,
};
use super::bindings::codegen::Bindings::GPURenderPipelineBinding::GPUIndexFormat;
#[dom_struct]
pub struct GPURenderBundleEncoder {
reflector_: Reflector,
@ -30,7 +32,7 @@ pub struct GPURenderBundleEncoder {
#[ignore_malloc_size_of = "defined in wgpu-core"]
#[no_trace]
render_bundle_encoder: DomRefCell<Option<RenderBundleEncoder>>,
label: DomRefCell<Option<USVString>>,
label: DomRefCell<USVString>,
}
impl GPURenderBundleEncoder {
@ -38,7 +40,7 @@ impl GPURenderBundleEncoder {
render_bundle_encoder: RenderBundleEncoder,
device: &GPUDevice,
channel: WebGPU,
label: Option<USVString>,
label: USVString,
) -> Self {
Self {
reflector_: Reflector::new(),
@ -54,7 +56,7 @@ impl GPURenderBundleEncoder {
render_bundle_encoder: RenderBundleEncoder,
device: &GPUDevice,
channel: WebGPU,
label: Option<USVString>,
label: USVString,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPURenderBundleEncoder::new_inherited(
@ -70,12 +72,12 @@ impl GPURenderBundleEncoder {
impl GPURenderBundleEncoderMethods for GPURenderBundleEncoder {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
fn SetLabel(&self, value: USVString) {
*self.label.borrow_mut() = value;
}
@ -103,11 +105,21 @@ impl GPURenderBundleEncoderMethods for GPURenderBundleEncoder {
}
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-setindexbuffer
fn SetIndexBuffer(&self, buffer: &GPUBuffer, offset: u64, size: u64) {
fn SetIndexBuffer(
&self,
buffer: &GPUBuffer,
index_format: GPUIndexFormat,
offset: u64,
size: u64,
) {
if let Some(encoder) = self.render_bundle_encoder.borrow_mut().as_mut() {
wgpu_bundle::wgpu_render_bundle_set_index_buffer(
encoder,
buffer.id().0,
match index_format {
GPUIndexFormat::Uint16 => wgt::IndexFormat::Uint16,
GPUIndexFormat::Uint32 => wgt::IndexFormat::Uint32,
},
offset,
wgt::BufferSize::new(size),
);
@ -175,7 +187,7 @@ impl GPURenderBundleEncoderMethods for GPURenderBundleEncoder {
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-drawindexedindirect
fn DrawIndexedIndirect(&self, indirect_buffer: &GPUBuffer, indirect_offset: u64) {
if let Some(encoder) = self.render_bundle_encoder.borrow_mut().as_mut() {
wgpu_bundle::wgpu_render_pass_bundle_indexed_indirect(
wgpu_bundle::wgpu_render_bundle_draw_indexed_indirect(
encoder,
indirect_buffer.id().0,
indirect_offset,
@ -214,7 +226,7 @@ impl GPURenderBundleEncoderMethods for GPURenderBundleEncoder {
render_bundle,
self.device.id(),
self.channel.clone(),
descriptor.parent.label.as_ref().cloned(),
descriptor.parent.label.clone().unwrap_or_default(),
)
}
}

View file

@ -21,13 +21,16 @@ use webgpu::{
wgt, WebGPU, WebGPURequest,
};
use super::bindings::codegen::Bindings::GPURenderPipelineBinding::GPUIndexFormat;
use super::bindings::error::Fallible;
#[dom_struct]
pub struct GPURenderPassEncoder {
reflector_: Reflector,
#[ignore_malloc_size_of = "defined in webgpu"]
#[no_trace]
channel: WebGPU,
label: DomRefCell<Option<USVString>>,
label: DomRefCell<USVString>,
#[ignore_malloc_size_of = "defined in wgpu-core"]
#[no_trace]
render_pass: DomRefCell<Option<RenderPass>>,
@ -39,7 +42,7 @@ impl GPURenderPassEncoder {
channel: WebGPU,
render_pass: Option<RenderPass>,
parent: &GPUCommandEncoder,
label: Option<USVString>,
label: USVString,
) -> Self {
Self {
channel,
@ -55,7 +58,7 @@ impl GPURenderPassEncoder {
channel: WebGPU,
render_pass: Option<RenderPass>,
parent: &GPUCommandEncoder,
label: Option<USVString>,
label: USVString,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPURenderPassEncoder::new_inherited(
@ -71,12 +74,12 @@ impl GPURenderPassEncoder {
impl GPURenderPassEncoderMethods for GPURenderPassEncoder {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
fn SetLabel(&self, value: USVString) {
*self.label.borrow_mut() = value;
}
@ -127,7 +130,7 @@ impl GPURenderPassEncoderMethods for GPURenderPassEncoder {
}
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-setblendcolor
fn SetBlendColor(&self, color: GPUColor) {
fn SetBlendConstant(&self, color: GPUColor) {
if let Some(render_pass) = self.render_pass.borrow_mut().as_mut() {
let colors = match color {
GPUColor::GPUColorDict(d) => wgt::Color {
@ -149,7 +152,7 @@ impl GPURenderPassEncoderMethods for GPURenderPassEncoder {
}
},
};
wgpu_render::wgpu_render_pass_set_blend_color(render_pass, &colors);
wgpu_render::wgpu_render_pass_set_blend_constant(render_pass, &colors);
}
}
@ -160,8 +163,8 @@ impl GPURenderPassEncoderMethods for GPURenderPassEncoder {
}
}
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-endpass
fn EndPass(&self) {
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-end
fn End(&self) -> Fallible<()> {
let render_pass = self.render_pass.borrow_mut().take();
self.channel
.0
@ -178,6 +181,7 @@ impl GPURenderPassEncoderMethods for GPURenderPassEncoder {
GPUCommandEncoderState::Open,
GPUCommandEncoderState::EncodingRenderPass,
);
Ok(())
}
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-setpipeline
@ -187,12 +191,22 @@ impl GPURenderPassEncoderMethods for GPURenderPassEncoder {
}
}
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-setindexbuffer
fn SetIndexBuffer(&self, buffer: &GPUBuffer, offset: u64, size: u64) {
/// https://gpuweb.github.io/gpuweb/#dom-gpurendercommandsmixin-setindexbuffer
fn SetIndexBuffer(
&self,
buffer: &GPUBuffer,
index_format: GPUIndexFormat,
offset: u64,
size: u64,
) {
if let Some(render_pass) = self.render_pass.borrow_mut().as_mut() {
wgpu_render::wgpu_render_pass_set_index_buffer(
render_pass,
buffer.id().0,
match index_format {
GPUIndexFormat::Uint16 => wgt::IndexFormat::Uint16,
GPUIndexFormat::Uint32 => wgt::IndexFormat::Uint32,
},
offset,
wgt::BufferSize::new(size),
);

View file

@ -18,7 +18,7 @@ use webgpu::{WebGPUBindGroupLayout, WebGPURenderPipeline};
#[dom_struct]
pub struct GPURenderPipeline {
reflector_: Reflector,
label: DomRefCell<Option<USVString>>,
label: DomRefCell<USVString>,
#[no_trace]
render_pipeline: WebGPURenderPipeline,
#[no_trace]
@ -29,7 +29,7 @@ pub struct GPURenderPipeline {
impl GPURenderPipeline {
fn new_inherited(
render_pipeline: WebGPURenderPipeline,
label: Option<USVString>,
label: USVString,
bgls: Vec<WebGPUBindGroupLayout>,
device: &GPUDevice,
) -> Self {
@ -45,7 +45,7 @@ impl GPURenderPipeline {
pub fn new(
global: &GlobalScope,
render_pipeline: WebGPURenderPipeline,
label: Option<USVString>,
label: USVString,
bgls: Vec<WebGPUBindGroupLayout>,
device: &GPUDevice,
) -> DomRoot<Self> {
@ -69,12 +69,12 @@ impl GPURenderPipeline {
impl GPURenderPipelineMethods for GPURenderPipeline {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
fn SetLabel(&self, value: USVString) {
*self.label.borrow_mut() = value;
}
@ -86,7 +86,7 @@ impl GPURenderPipelineMethods for GPURenderPipeline {
Ok(GPUBindGroupLayout::new(
&self.global(),
self.bind_group_layouts[index as usize],
None,
USVString::default(),
))
}
}

View file

@ -14,7 +14,7 @@ use webgpu::{WebGPUDevice, WebGPUSampler};
#[dom_struct]
pub struct GPUSampler {
reflector_: Reflector,
label: DomRefCell<Option<USVString>>,
label: DomRefCell<USVString>,
#[no_trace]
device: WebGPUDevice,
compare_enable: bool,
@ -27,7 +27,7 @@ impl GPUSampler {
device: WebGPUDevice,
compare_enable: bool,
sampler: WebGPUSampler,
label: Option<USVString>,
label: USVString,
) -> Self {
Self {
reflector_: Reflector::new(),
@ -43,7 +43,7 @@ impl GPUSampler {
device: WebGPUDevice,
compare_enable: bool,
sampler: WebGPUSampler,
label: Option<USVString>,
label: USVString,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPUSampler::new_inherited(
@ -65,12 +65,12 @@ impl GPUSampler {
impl GPUSamplerMethods for GPUSampler {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
fn SetLabel(&self, value: USVString) {
*self.label.borrow_mut() = value;
}
}

View file

@ -2,6 +2,8 @@
* 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/. */
use std::rc::Rc;
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::GPUShaderModuleBinding::GPUShaderModuleMethods;
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
@ -11,16 +13,19 @@ use crate::dom::globalscope::GlobalScope;
use dom_struct::dom_struct;
use webgpu::WebGPUShaderModule;
use super::bindings::error::Fallible;
use super::promise::Promise;
#[dom_struct]
pub struct GPUShaderModule {
reflector_: Reflector,
label: DomRefCell<Option<USVString>>,
label: DomRefCell<USVString>,
#[no_trace]
shader_module: WebGPUShaderModule,
}
impl GPUShaderModule {
fn new_inherited(shader_module: WebGPUShaderModule, label: Option<USVString>) -> Self {
fn new_inherited(shader_module: WebGPUShaderModule, label: USVString) -> Self {
Self {
reflector_: Reflector::new(),
label: DomRefCell::new(label),
@ -31,7 +36,7 @@ impl GPUShaderModule {
pub fn new(
global: &GlobalScope,
shader_module: WebGPUShaderModule,
label: Option<USVString>,
label: USVString,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPUShaderModule::new_inherited(shader_module, label)),
@ -48,12 +53,17 @@ impl GPUShaderModule {
impl GPUShaderModuleMethods for GPUShaderModule {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
fn SetLabel(&self, value: USVString) {
*self.label.borrow_mut() = value;
}
/// https://gpuweb.github.io/gpuweb/#dom-gpushadermodule-getcompilationinfo
fn CompilationInfo(&self) -> Fallible<Rc<Promise>> {
todo!()
}
}

View file

@ -0,0 +1,165 @@
/* 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/. */
use super::bindings::codegen::Bindings::GPUSupportedLimitsBinding::GPUSupportedLimitsBinding;
use super::bindings::reflector::reflect_dom_object;
use super::bindings::root::DomRoot;
use crate::dom::bindings::reflector::Reflector;
use crate::dom::globalscope::GlobalScope;
use dom_struct::dom_struct;
use webgpu::wgt::Limits;
use GPUSupportedLimitsBinding::GPUSupportedLimitsMethods;
#[dom_struct]
pub struct GPUSupportedLimits {
reflector_: Reflector,
#[ignore_malloc_size_of = "defined in wgpu-types"]
#[no_trace]
limits: Limits,
}
impl GPUSupportedLimits {
fn new_inherited(limits: Limits) -> Self {
Self {
reflector_: Reflector::new(),
limits,
}
}
pub fn new(global: &GlobalScope, limits: Limits) -> DomRoot<Self> {
reflect_dom_object(Box::new(Self::new_inherited(limits)), global)
}
}
impl GPUSupportedLimitsMethods for GPUSupportedLimits {
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxtexturedimension1d
fn MaxTextureDimension1D(&self) -> u32 {
self.limits.max_texture_dimension_1d
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxtexturedimension2d
fn MaxTextureDimension2D(&self) -> u32 {
self.limits.max_texture_dimension_2d
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxtexturedimension3d
fn MaxTextureDimension3D(&self) -> u32 {
self.limits.max_texture_dimension_3d
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxtexturearraylayers
fn MaxTextureArrayLayers(&self) -> u32 {
self.limits.max_texture_array_layers
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxbindgroups
fn MaxBindGroups(&self) -> u32 {
self.limits.max_bind_groups
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxdynamicuniformbuffersperpipelinelayout
fn MaxDynamicUniformBuffersPerPipelineLayout(&self) -> u32 {
self.limits.max_dynamic_uniform_buffers_per_pipeline_layout
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxdynamicstoragebuffersperpipelinelayout
fn MaxDynamicStorageBuffersPerPipelineLayout(&self) -> u32 {
self.limits.max_dynamic_storage_buffers_per_pipeline_layout
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxsampledtexturespershaderstage
fn MaxSampledTexturesPerShaderStage(&self) -> u32 {
self.limits.max_sampled_textures_per_shader_stage
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxsamplerspershaderstage
fn MaxSamplersPerShaderStage(&self) -> u32 {
self.limits.max_samplers_per_shader_stage
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxstoragebufferspershaderstage
fn MaxStorageBuffersPerShaderStage(&self) -> u32 {
self.limits.max_storage_buffers_per_shader_stage
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxstoragetexturespershaderstage
fn MaxStorageTexturesPerShaderStage(&self) -> u32 {
self.limits.max_storage_textures_per_shader_stage
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxuniformbufferspershaderstage
fn MaxUniformBuffersPerShaderStage(&self) -> u32 {
self.limits.max_uniform_buffers_per_shader_stage
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxuniformbufferbindingsize
fn MaxUniformBufferBindingSize(&self) -> u32 {
self.limits.max_uniform_buffer_binding_size
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxstoragebufferbindingsize
fn MaxStorageBufferBindingSize(&self) -> u32 {
self.limits.max_storage_buffer_binding_size
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-minuniformbufferoffsetalignment
fn MinUniformBufferOffsetAlignment(&self) -> u32 {
self.limits.min_uniform_buffer_offset_alignment
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-minstoragebufferoffsetalignment
fn MinStorageBufferOffsetAlignment(&self) -> u32 {
self.limits.min_storage_buffer_offset_alignment
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxvertexbuffers
fn MaxVertexBuffers(&self) -> u32 {
self.limits.max_vertex_buffers
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxvertexattributes
fn MaxVertexAttributes(&self) -> u32 {
self.limits.max_vertex_attributes
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxvertexbufferarraystride
fn MaxVertexBufferArrayStride(&self) -> u32 {
self.limits.max_vertex_buffer_array_stride
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxinterstageshadercomponents
fn MaxInterStageShaderComponents(&self) -> u32 {
self.limits.max_inter_stage_shader_components
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxcomputeworkgroupstoragesize
fn MaxComputeWorkgroupStorageSize(&self) -> u32 {
self.limits.max_compute_workgroup_storage_size
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxcomputeinvocationsperworkgroup
fn MaxComputeInvocationsPerWorkgroup(&self) -> u32 {
self.limits.max_compute_invocations_per_workgroup
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxcomputeworkgroupsizex
fn MaxComputeWorkgroupSizeX(&self) -> u32 {
self.limits.max_compute_workgroup_size_x
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxcomputeworkgroupsizey
fn MaxComputeWorkgroupSizeY(&self) -> u32 {
self.limits.max_compute_workgroup_size_y
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxcomputeworkgroupsizez
fn MaxComputeWorkgroupSizeZ(&self) -> u32 {
self.limits.max_compute_workgroup_size_z
}
/// https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxcomputeworkgroupsperdimension
fn MaxComputeWorkgroupsPerDimension(&self) -> u32 {
self.limits.max_compute_workgroups_per_dimension
}
}

View file

@ -1,97 +0,0 @@
/* 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/. */
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::GPUSwapChainBinding::GPUSwapChainMethods;
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::USVString;
use crate::dom::globalscope::GlobalScope;
use crate::dom::gpucanvascontext::GPUCanvasContext;
use crate::dom::gputexture::GPUTexture;
use dom_struct::dom_struct;
use webgpu::{WebGPU, WebGPURequest, WebGPUTexture};
use webrender_api::ImageKey;
#[dom_struct]
pub struct GPUSwapChain {
reflector_: Reflector,
#[ignore_malloc_size_of = "channels are hard"]
#[no_trace]
channel: WebGPU,
label: DomRefCell<Option<USVString>>,
context: Dom<GPUCanvasContext>,
texture: Dom<GPUTexture>,
}
impl GPUSwapChain {
fn new_inherited(
channel: WebGPU,
context: &GPUCanvasContext,
texture: &GPUTexture,
label: Option<USVString>,
) -> Self {
Self {
reflector_: Reflector::new(),
channel,
context: Dom::from_ref(context),
texture: Dom::from_ref(texture),
label: DomRefCell::new(label),
}
}
pub fn new(
global: &GlobalScope,
channel: WebGPU,
context: &GPUCanvasContext,
texture: &GPUTexture,
label: Option<USVString>,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPUSwapChain::new_inherited(
channel, context, texture, label,
)),
global,
)
}
}
impl GPUSwapChain {
pub fn destroy(&self, external_id: u64, image_key: ImageKey) {
if let Err(e) = self.channel.0.send((
None,
WebGPURequest::DestroySwapChain {
external_id,
image_key,
},
)) {
warn!(
"Failed to send DestroySwapChain-ImageKey({:?}) ({})",
image_key, e
);
}
}
pub fn texture_id(&self) -> WebGPUTexture {
self.texture.id()
}
}
impl GPUSwapChainMethods for GPUSwapChain {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
*self.label.borrow_mut() = value;
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuswapchain-getcurrenttexture
fn GetCurrentTexture(&self) -> DomRoot<GPUTexture> {
self.context.mark_as_dirty();
DomRoot::from_ref(&*self.texture)
}
}

View file

@ -19,7 +19,6 @@ use crate::dom::gpudevice::{
use crate::dom::gputextureview::GPUTextureView;
use dom_struct::dom_struct;
use std::cell::Cell;
use std::num::NonZeroU32;
use std::string::String;
use webgpu::{
identity::WebGPUOpResult, wgpu::resource, wgt, WebGPU, WebGPURequest, WebGPUTexture,
@ -31,7 +30,7 @@ pub struct GPUTexture {
reflector_: Reflector,
#[no_trace]
texture: WebGPUTexture,
label: DomRefCell<Option<USVString>>,
label: DomRefCell<USVString>,
device: Dom<GPUDevice>,
#[ignore_malloc_size_of = "channels are hard"]
#[no_trace]
@ -57,7 +56,7 @@ impl GPUTexture {
dimension: GPUTextureDimension,
format: GPUTextureFormat,
texture_usage: u32,
label: Option<USVString>,
label: USVString,
) -> Self {
Self {
reflector_: Reflector::new(),
@ -86,7 +85,7 @@ impl GPUTexture {
dimension: GPUTextureDimension,
format: GPUTextureFormat,
texture_usage: u32,
label: Option<USVString>,
label: USVString,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(GPUTexture::new_inherited(
@ -120,46 +119,37 @@ impl GPUTexture {
impl GPUTextureMethods for GPUTexture {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
fn SetLabel(&self, value: USVString) {
*self.label.borrow_mut() = value;
}
/// https://gpuweb.github.io/gpuweb/#dom-gputexture-createview
fn CreateView(&self, descriptor: &GPUTextureViewDescriptor) -> DomRoot<GPUTextureView> {
let scope_id = self.device.use_current_scope();
let mut valid = true;
let level_count = descriptor.mipLevelCount.and_then(|count| {
if count == 0 {
valid = false;
}
NonZeroU32::new(count)
});
let array_layer_count = descriptor.arrayLayerCount.and_then(|count| {
if count == 0 {
valid = false;
}
NonZeroU32::new(count)
});
let desc = if valid {
let desc = if !matches!(descriptor.mipLevelCount, Some(0)) &&
!matches!(descriptor.arrayLayerCount, Some(0))
{
Some(resource::TextureViewDescriptor {
label: convert_label(&descriptor.parent),
format: descriptor.format.map(convert_texture_format),
dimension: descriptor.dimension.map(convert_texture_view_dimension),
aspect: match descriptor.aspect {
GPUTextureAspect::All => wgt::TextureAspect::All,
GPUTextureAspect::Stencil_only => wgt::TextureAspect::StencilOnly,
GPUTextureAspect::Depth_only => wgt::TextureAspect::DepthOnly,
range: wgt::ImageSubresourceRange {
aspect: match descriptor.aspect {
GPUTextureAspect::All => wgt::TextureAspect::All,
GPUTextureAspect::Stencil_only => wgt::TextureAspect::StencilOnly,
GPUTextureAspect::Depth_only => wgt::TextureAspect::DepthOnly,
},
base_mip_level: descriptor.baseMipLevel,
mip_level_count: descriptor.mipLevelCount,
base_array_layer: descriptor.baseArrayLayer,
array_layer_count: descriptor.arrayLayerCount,
},
base_mip_level: descriptor.baseMipLevel,
level_count,
base_array_layer: descriptor.baseArrayLayer,
array_layer_count,
})
} else {
self.device.handle_server_msg(
@ -196,7 +186,7 @@ impl GPUTextureMethods for GPUTexture {
&self.global(),
texture_view,
&self,
descriptor.parent.label.as_ref().cloned(),
descriptor.parent.label.clone().unwrap_or_default(),
)
}

View file

@ -15,7 +15,7 @@ use webgpu::WebGPUTextureView;
#[dom_struct]
pub struct GPUTextureView {
reflector_: Reflector,
label: DomRefCell<Option<USVString>>,
label: DomRefCell<USVString>,
#[no_trace]
texture_view: WebGPUTextureView,
texture: Dom<GPUTexture>,
@ -25,7 +25,7 @@ impl GPUTextureView {
fn new_inherited(
texture_view: WebGPUTextureView,
texture: &GPUTexture,
label: Option<USVString>,
label: USVString,
) -> GPUTextureView {
Self {
reflector_: Reflector::new(),
@ -39,7 +39,7 @@ impl GPUTextureView {
global: &GlobalScope,
texture_view: WebGPUTextureView,
texture: &GPUTexture,
label: Option<USVString>,
label: USVString,
) -> DomRoot<GPUTextureView> {
reflect_dom_object(
Box::new(GPUTextureView::new_inherited(texture_view, texture, label)),
@ -56,12 +56,12 @@ impl GPUTextureView {
impl GPUTextureViewMethods for GPUTextureView {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<USVString>) {
fn SetLabel(&self, value: USVString) {
*self.label.borrow_mut() = value;
}
}

View file

@ -10,6 +10,8 @@ use crate::dom::globalscope::GlobalScope;
use dom_struct::dom_struct;
use js::rust::HandleObject;
use super::bindings::error::Fallible;
#[dom_struct]
pub struct GPUValidationError {
reflector_: Reflector,
@ -46,8 +48,8 @@ impl GPUValidationError {
global: &GlobalScope,
proto: Option<HandleObject>,
message: DOMString,
) -> DomRoot<Self> {
GPUValidationError::new_with_proto(global, proto, message)
) -> Fallible<DomRoot<Self>> {
Ok(GPUValidationError::new_with_proto(global, proto, message))
}
}

View file

@ -269,9 +269,8 @@ impl HTMLCanvasElement {
.script_to_constellation_chan()
.send(ScriptMsg::GetWebGPUChan(sender));
let window = window_from_node(self);
let size = self.get_size();
let channel = receiver.recv().expect("Failed to get WebGPU channel");
let context = GPUCanvasContext::new(window.upcast::<GlobalScope>(), self, size, channel);
let context = GPUCanvasContext::new(window.upcast::<GlobalScope>(), self, channel);
*self.context.borrow_mut() = Some(CanvasContext::WebGPU(Dom::from_ref(&*context)));
Some(context)
}
@ -374,7 +373,7 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement {
"webgl2" | "experimental-webgl2" => self
.get_or_init_webgl2_context(cx, options)
.map(RenderingContext::WebGL2RenderingContext),
"gpupresent" => self
"webgpu" => self
.get_or_init_webgpu_context()
.map(RenderingContext::GPUCanvasContext),
_ => None,

View file

@ -321,6 +321,7 @@ pub mod gamepadpose;
pub mod globalscope;
pub mod gpu;
pub mod gpuadapter;
pub mod gpuadapterinfo;
pub mod gpubindgroup;
pub mod gpubindgrouplayout;
pub mod gpubuffer;
@ -329,6 +330,8 @@ pub mod gpucanvascontext;
pub mod gpucolorwrite;
pub mod gpucommandbuffer;
pub mod gpucommandencoder;
pub mod gpucompilationinfo;
pub mod gpucompilationmessage;
pub mod gpucomputepassencoder;
pub mod gpucomputepipeline;
pub mod gpudevice;
@ -336,6 +339,7 @@ pub mod gpudevicelostinfo;
pub mod gpumapmode;
pub mod gpuoutofmemoryerror;
pub mod gpupipelinelayout;
pub mod gpuqueryset;
pub mod gpuqueue;
pub mod gpurenderbundle;
pub mod gpurenderbundleencoder;
@ -344,7 +348,7 @@ pub mod gpurenderpipeline;
pub mod gpusampler;
pub mod gpushadermodule;
pub mod gpushaderstage;
pub mod gpuswapchain;
pub mod gpusupportedlimits;
pub mod gputexture;
pub mod gputextureusage;
pub mod gputextureview;

View file

@ -5,15 +5,16 @@
// https://gpuweb.github.io/gpuweb/#gpu-interface
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPU {
[NewObject]
Promise<GPUAdapter?> requestAdapter(optional GPURequestAdapterOptions options = {});
GPUTextureFormat getPreferredCanvasFormat();
};
// https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions
dictionary GPURequestAdapterOptions {
GPUPowerPreference powerPreference;
boolean forceFallbackAdapter = false;
};
// https://gpuweb.github.io/gpuweb/#enumdef-gpupowerpreference
enum GPUPowerPreference {
"low-power",
"high-performance"

View file

@ -5,35 +5,29 @@
// https://gpuweb.github.io/gpuweb/#gpuadapter
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPUAdapter {
readonly attribute DOMString name;
readonly attribute object extensions;
//readonly attribute GPULimits limits; Dont expose higher limits for now.
//[SameObject] readonly attribute GPUSupportedFeatures features;
[SameObject] readonly attribute GPUSupportedLimits limits;
readonly attribute boolean isFallbackAdapter;
Promise<GPUDevice?> requestDevice(optional GPUDeviceDescriptor descriptor = {});
[NewObject]
Promise<GPUDevice> requestDevice(optional GPUDeviceDescriptor descriptor = {});
[NewObject]
Promise<GPUAdapterInfo> requestAdapterInfo(optional sequence<DOMString> unmaskHints = []);
};
dictionary GPUDeviceDescriptor : GPUObjectDescriptorBase {
sequence<GPUExtensionName> extensions = [];
GPULimits limits = {};
dictionary GPUDeviceDescriptor {
sequence<GPUFeatureName> requiredFeatures = [];
record<DOMString, GPUSize64> requiredLimits;
};
enum GPUExtensionName {
"depth-clamping",
enum GPUFeatureName {
"depth-clip-control",
"depth24unorm-stencil8",
"depth32float-stencil8",
"pipeline-statistics-query",
"texture-compression-bc",
"texture-compression-etc2",
"texture-compression-astc",
"timestamp-query",
};
dictionary GPULimits {
GPUSize32 maxBindGroups = 4;
GPUSize32 maxDynamicUniformBuffersPerPipelineLayout = 8;
GPUSize32 maxDynamicStorageBuffersPerPipelineLayout = 4;
GPUSize32 maxSampledTexturesPerShaderStage = 16;
GPUSize32 maxSamplersPerShaderStage = 16;
GPUSize32 maxStorageBuffersPerShaderStage = 4;
GPUSize32 maxStorageTexturesPerShaderStage = 4;
GPUSize32 maxUniformBuffersPerShaderStage = 12;
GPUSize32 maxUniformBufferBindingSize = 16384;
"indirect-first-instance",
};

View file

@ -0,0 +1,12 @@
/* 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/. */
// https://gpuweb.github.io/gpuweb/#gpuadapterinfo
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPUAdapterInfo {
readonly attribute DOMString vendor;
readonly attribute DOMString architecture;
readonly attribute DOMString device;
readonly attribute DOMString description;
};

View file

@ -13,16 +13,14 @@ dictionary GPUBindGroupDescriptor : GPUObjectDescriptorBase {
required sequence<GPUBindGroupEntry> entries;
};
typedef (GPUSampler or GPUTextureView or GPUBufferBindings) GPUBindingResource;
typedef (GPUSampler or GPUTextureView or GPUBufferBinding) GPUBindingResource;
dictionary GPUBindGroupEntry {
required GPUIndex32 binding;
required GPUBindingResource resource;
};
// Note: Servo codegen doesn't like the name `GPUBufferBinding` because it's already occupied
// dictionary GPUBufferBinding {
dictionary GPUBufferBindings {
dictionary GPUBufferBinding {
required GPUBuffer buffer;
GPUSize64 offset = 0;
GPUSize64 size;

View file

@ -15,22 +15,54 @@ dictionary GPUBindGroupLayoutDescriptor : GPUObjectDescriptorBase {
dictionary GPUBindGroupLayoutEntry {
required GPUIndex32 binding;
required GPUShaderStageFlags visibility;
required GPUBindingType type;
boolean hasDynamicOffset;
GPUSize64 minBufferBindingSize;
GPUTextureViewDimension viewDimension;
GPUTextureComponentType textureComponentType;
GPUTextureFormat storageTextureFormat;
GPUBufferBindingLayout buffer;
GPUSamplerBindingLayout sampler;
GPUTextureBindingLayout texture;
GPUStorageTextureBindingLayout storageTexture;
};
enum GPUBindingType {
"uniform-buffer",
"storage-buffer",
"readonly-storage-buffer",
"sampler",
"comparison-sampler",
"sampled-texture",
"multisampled-texture",
"readonly-storage-texture",
"writeonly-storage-texture"
enum GPUBufferBindingType {
"uniform",
"storage",
"read-only-storage",
};
dictionary GPUBufferBindingLayout {
GPUBufferBindingType type = "uniform";
boolean hasDynamicOffset = false;
GPUSize64 minBindingSize = 0;
};
enum GPUSamplerBindingType {
"filtering",
"non-filtering",
"comparison",
};
dictionary GPUSamplerBindingLayout {
GPUSamplerBindingType type = "filtering";
};
enum GPUTextureSampleType {
"float",
"unfilterable-float",
"depth",
"sint",
"uint",
};
dictionary GPUTextureBindingLayout {
GPUTextureSampleType sampleType = "float";
GPUTextureViewDimension viewDimension = "2d";
boolean multisampled = false;
};
enum GPUStorageTextureAccess {
"write-only",
};
dictionary GPUStorageTextureBindingLayout {
GPUStorageTextureAccess access = "write-only";
required GPUTextureFormat format;
GPUTextureViewDimension viewDimension = "2d";
};

View file

@ -5,10 +5,13 @@
// https://gpuweb.github.io/gpuweb/#gpubuffer
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
interface GPUBuffer {
[NewObject]
Promise<undefined> mapAsync(GPUMapModeFlags mode, optional GPUSize64 offset = 0, optional GPUSize64 size);
[Throws] ArrayBuffer getMappedRange(optional GPUSize64 offset = 0, optional GPUSize64 size);
[NewObject, Throws]
ArrayBuffer getMappedRange(optional GPUSize64 offset = 0, optional GPUSize64 size);
[Throws]
undefined unmap();
[Throws]
undefined destroy();
};
GPUBuffer includes GPUObjectBase;
@ -19,4 +22,4 @@ dictionary GPUBufferDescriptor : GPUObjectDescriptorBase {
boolean mappedAtCreation = false;
};
typedef unsigned long long GPUSize64;
typedef [EnforceRange] unsigned long long GPUSize64;

View file

@ -16,5 +16,4 @@ interface GPUBufferUsage {
const GPUBufferUsageFlags INDIRECT = 0x0100;
const GPUBufferUsageFlags QUERY_RESOLVE = 0x0200;
};
typedef [EnforceRange] unsigned long GPUBufferUsageFlags;

View file

@ -5,13 +5,27 @@
// https://gpuweb.github.io/gpuweb/#gpucanvascontext
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPUCanvasContext {
GPUSwapChain configureSwapChain(GPUSwapChainDescriptor descriptor);
readonly attribute (HTMLCanvasElement or OffscreenCanvas) canvas;
//Promise<GPUTextureFormat> getSwapChainPreferredFormat(GPUDevice device);
// Calling configure() a second time invalidates the previous one,
// and all of the textures it's produced.
undefined configure(GPUCanvasConfiguration descriptor);
undefined unconfigure();
[Throws]
GPUTexture getCurrentTexture();
};
dictionary GPUSwapChainDescriptor : GPUObjectDescriptorBase {
enum GPUCanvasAlphaMode {
"opaque",
"premultiplied",
};
dictionary GPUCanvasConfiguration {
required GPUDevice device;
required GPUTextureFormat format;
GPUTextureUsageFlags usage = 0x10; // GPUTextureUsage.OUTPUT_ATTACHMENT
GPUTextureUsageFlags usage = 0x10; // GPUTextureUsage.RENDER_ATTACHMENT
sequence<GPUTextureFormat> viewFormats = [];
// PredefinedColorSpace colorSpace = "srgb"; // TODO
GPUCanvasAlphaMode alphaMode = "opaque";
};

View file

@ -2,7 +2,7 @@
* 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/. */
// https://gpuweb.github.io/gpuweb/#gpucolorwrite
// https://gpuweb.github.io/gpuweb/#namespacedef-gpucolorwrite
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPUColorWrite {
const GPUColorWriteFlags RED = 0x1;

View file

@ -5,6 +5,8 @@
// https://gpuweb.github.io/gpuweb/#gpucommandbuffer
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
interface GPUCommandBuffer {
//readonly attribute Promise<double> executionTime;
};
GPUCommandBuffer includes GPUObjectBase;
dictionary GPUCommandBufferDescriptor : GPUObjectDescriptorBase {
};

View file

@ -5,8 +5,10 @@
// https://gpuweb.github.io/gpuweb/#gpucommandencoder
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
interface GPUCommandEncoder {
GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor);
[NewObject]
GPUComputePassEncoder beginComputePass(optional GPUComputePassDescriptor descriptor = {});
[NewObject]
GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor);
undefined copyBufferToBuffer(
GPUBuffer source,
@ -16,78 +18,117 @@ interface GPUCommandEncoder {
GPUSize64 size);
undefined copyBufferToTexture(
GPUBufferCopyView source,
GPUTextureCopyView destination,
GPUImageCopyBuffer source,
GPUImageCopyTexture destination,
GPUExtent3D copySize);
undefined copyTextureToBuffer(
GPUTextureCopyView source,
GPUBufferCopyView destination,
GPUImageCopyTexture source,
GPUImageCopyBuffer destination,
GPUExtent3D copySize);
undefined copyTextureToTexture(
GPUTextureCopyView source,
GPUTextureCopyView destination,
GPUImageCopyTexture source,
GPUImageCopyTexture destination,
GPUExtent3D copySize);
//void pushDebugGroup(USVString groupLabel);
//void popDebugGroup();
//void insertDebugMarker(USVString markerLabel);
/*
undefined copyImageBitmapToTexture(
GPUImageBitmapCopyView source,
GPUImageCopyTexture destination,
GPUExtent3D copySize);
*/
//void writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex);
//void resolveQuerySet(
// GPUQuerySet querySet,
// GPUSize32 firstQuery,
// GPUSize32 queryCount,
// GPUBuffer destination,
// GPUSize64 destinationOffset);
//undefined pushDebugGroup(USVString groupLabel);
//undefined popDebugGroup();
//undefined insertDebugMarker(USVString markerLabel);
[NewObject]
GPUCommandBuffer finish(optional GPUCommandBufferDescriptor descriptor = {});
};
GPUCommandEncoder includes GPUObjectBase;
dictionary GPUImageDataLayout {
GPUSize64 offset = 0;
GPUSize32 bytesPerRow;
GPUSize32 rowsPerImage;
};
dictionary GPUImageCopyBuffer : GPUImageDataLayout {
required GPUBuffer buffer;
};
dictionary GPUImageCopyExternalImage {
required (ImageBitmap or HTMLCanvasElement or OffscreenCanvas) source;
GPUOrigin2D origin = {};
boolean flipY = false;
};
dictionary GPUImageCopyTexture {
required GPUTexture texture;
GPUIntegerCoordinate mipLevel = 0;
GPUOrigin3D origin;
GPUTextureAspect aspect = "all";
};
dictionary GPUImageCopyTextureTagged : GPUImageCopyTexture {
//GPUPredefinedColorSpace colorSpace = "srgb"; //TODO
boolean premultipliedAlpha = false;
};
dictionary GPUImageBitmapCopyView {
//required ImageBitmap imageBitmap; //TODO
GPUOrigin2D origin;
};
dictionary GPUComputePassDescriptor : GPUObjectDescriptorBase {
};
dictionary GPUCommandBufferDescriptor : GPUObjectDescriptorBase {
};
//
dictionary GPURenderPassDescriptor : GPUObjectDescriptorBase {
required sequence<GPURenderPassColorAttachmentDescriptor> colorAttachments;
GPURenderPassDepthStencilAttachmentDescriptor depthStencilAttachment;
//GPUQuerySet occlusionQuerySet;
required sequence<GPURenderPassColorAttachment> colorAttachments;
GPURenderPassDepthStencilAttachment depthStencilAttachment;
GPUQuerySet occlusionQuerySet;
};
dictionary GPURenderPassColorAttachmentDescriptor {
required GPUTextureView attachment;
dictionary GPURenderPassColorAttachment {
required GPUTextureView view;
GPUTextureView resolveTarget;
required (GPULoadOp or GPUColor) loadValue;
GPUStoreOp storeOp = "store";
GPUColor clearValue;
required GPULoadOp loadOp;
required GPUStoreOp storeOp;
};
dictionary GPURenderPassDepthStencilAttachmentDescriptor {
required GPUTextureView attachment;
dictionary GPURenderPassDepthStencilAttachment {
required GPUTextureView view;
required (GPULoadOp or float) depthLoadValue;
required GPUStoreOp depthStoreOp;
float depthClearValue;
GPULoadOp depthLoadOp;
GPUStoreOp depthStoreOp;
boolean depthReadOnly = false;
required GPUStencilLoadValue stencilLoadValue;
required GPUStoreOp stencilStoreOp;
GPUStencilValue stencilClearValue = 0;
GPULoadOp stencilLoadOp;
GPUStoreOp stencilStoreOp;
boolean stencilReadOnly = false;
};
typedef (GPULoadOp or GPUStencilValue) GPUStencilLoadValue;
enum GPULoadOp {
"load"
"load",
"clear"
};
enum GPUStoreOp {
"store",
"clear"
"discard"
};
dictionary GPURenderPassLayout: GPUObjectDescriptorBase {
// TODO: We don't support nullable enumerated arguments yet
required sequence<GPUTextureFormat> colorFormats;
GPUTextureFormat depthStencilFormat;
GPUSize32 sampleCount = 1;
};
dictionary GPUColorDict {
@ -98,21 +139,11 @@ dictionary GPUColorDict {
};
typedef (sequence<double> or GPUColorDict) GPUColor;
dictionary GPUTextureDataLayout {
GPUSize64 offset = 0;
required GPUSize32 bytesPerRow;
GPUSize32 rowsPerImage = 0;
};
dictionary GPUBufferCopyView : GPUTextureDataLayout {
required GPUBuffer buffer;
};
dictionary GPUTextureCopyView {
required GPUTexture texture;
GPUIntegerCoordinate mipLevel = 0;
GPUOrigin3D origin = {};
dictionary GPUOrigin2DDict {
GPUIntegerCoordinate x = 0;
GPUIntegerCoordinate y = 0;
};
typedef (sequence<GPUIntegerCoordinate> or GPUOrigin2DDict) GPUOrigin2D;
dictionary GPUOrigin3DDict {
GPUIntegerCoordinate x = 0;

View file

@ -0,0 +1,11 @@
/* 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/. */
// https://gpuweb.github.io/gpuweb/#gpucompilationinfo
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPUCompilationInfo {
// codegen hates it
//[Cached, Frozen, Pure]
readonly attribute /*sequence<GPUCompilationMessage>*/ any messages;
};

View file

@ -0,0 +1,20 @@
/* 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/. */
// https://gpuweb.github.io/gpuweb/#gpucompilationmessage
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPUCompilationMessage {
readonly attribute DOMString message;
readonly attribute GPUCompilationMessageType type;
readonly attribute unsigned long long lineNum;
readonly attribute unsigned long long linePos;
readonly attribute unsigned long long offset;
readonly attribute unsigned long long length;
};
enum GPUCompilationMessageType {
"error",
"warning",
"info"
};

View file

@ -6,15 +6,12 @@
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
interface GPUComputePassEncoder {
undefined setPipeline(GPUComputePipeline pipeline);
undefined dispatch(GPUSize32 x, optional GPUSize32 y = 1, optional GPUSize32 z = 1);
undefined dispatchIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
undefined dispatchWorkgroups(GPUSize32 x, optional GPUSize32 y = 1, optional GPUSize32 z = 1);
//[Pref="dom.webgpu.indirect-dispatch.enabled"]
undefined dispatchWorkgroupsIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
//void beginPipelineStatisticsQuery(GPUQuerySet querySet, GPUSize32 queryIndex);
//void endPipelineStatisticsQuery();
//void writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex);
undefined endPass();
[Throws]
undefined end();
};
GPUComputePassEncoder includes GPUObjectBase;
GPUComputePassEncoder includes GPUProgrammablePassEncoder;

View file

@ -9,19 +9,23 @@ interface GPUComputePipeline {
GPUComputePipeline includes GPUObjectBase;
GPUComputePipeline includes GPUPipelineBase;
dictionary GPUPipelineDescriptorBase : GPUObjectDescriptorBase {
GPUPipelineLayout layout;
enum GPUAutoLayoutMode {
"auto"
};
dictionary GPUProgrammableStageDescriptor {
required GPUShaderModule module;
required DOMString entryPoint;
dictionary GPUPipelineDescriptorBase : GPUObjectDescriptorBase {
required (GPUPipelineLayout or GPUAutoLayoutMode) layout;
};
dictionary GPUComputePipelineDescriptor : GPUPipelineDescriptorBase {
required GPUProgrammableStageDescriptor computeStage;
required GPUProgrammableStage compute;
};
interface mixin GPUPipelineBase {
[Throws] GPUBindGroupLayout getBindGroupLayout(unsigned long index);
};
dictionary GPUProgrammableStage {
required GPUShaderModule module;
required USVString entryPoint;
};

View file

@ -4,15 +4,20 @@
// https://gpuweb.github.io/gpuweb/#gpudevice
[Exposed=(Window, DedicatedWorker), /*Serializable,*/ Pref="dom.webgpu.enabled"]
interface GPUDevice : EventTarget {
[SameObject] readonly attribute GPUAdapter adapter;
readonly attribute object extensions;
readonly attribute object limits;
interface GPUDevice: EventTarget {
//[SameObject] readonly attribute GPUSupportedFeatures features;
[SameObject] readonly attribute GPUSupportedLimits limits;
[SameObject] readonly attribute GPUQueue defaultQueue;
// Overriding the name to avoid collision with `class Queue` in gcc
[SameObject, BinaryName="getQueue"] readonly attribute GPUQueue queue;
undefined destroy();
[NewObject, Throws]
GPUBuffer createBuffer(GPUBufferDescriptor descriptor);
[NewObject]
GPUTexture createTexture(GPUTextureDescriptor descriptor);
[NewObject]
GPUSampler createSampler(optional GPUSamplerDescriptor descriptor = {});
GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor);
@ -22,16 +27,22 @@ interface GPUDevice : EventTarget {
GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor);
GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor);
GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor);
//Promise<GPUComputePipeline> createReadyComputePipeline(GPUComputePipelineDescriptor descriptor);
//Promise<GPURenderPipeline> createReadyRenderPipeline(GPURenderPipelineDescriptor descriptor);
[NewObject]
Promise<GPUComputePipeline> createComputePipelineAsync(GPUComputePipelineDescriptor descriptor);
[NewObject]
Promise<GPURenderPipeline> createRenderPipelineAsync(GPURenderPipelineDescriptor descriptor);
[NewObject]
GPUCommandEncoder createCommandEncoder(optional GPUCommandEncoderDescriptor descriptor = {});
[NewObject]
GPURenderBundleEncoder createRenderBundleEncoder(GPURenderBundleEncoderDescriptor descriptor);
//[NewObject]
//GPUQuerySet createQuerySet(GPUQuerySetDescriptor descriptor);
};
GPUDevice includes GPUObjectBase;
//TODO
dictionary GPUCommandEncoderDescriptor : GPUObjectDescriptorBase {
boolean measureExecutionTime = false;
};

View file

@ -5,9 +5,16 @@
// https://gpuweb.github.io/gpuweb/#gpudevicelostinfo
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPUDeviceLostInfo {
readonly attribute GPUDeviceLostReason reason;
readonly attribute DOMString message;
};
enum GPUDeviceLostReason {
"unknown",
"destroyed",
};
partial interface GPUDevice {
[Throws]
readonly attribute Promise<GPUDeviceLostInfo> lost;
};

View file

@ -2,7 +2,7 @@
* 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/. */
// https://gpuweb.github.io/gpuweb/#gpumapmode
// https://gpuweb.github.io/gpuweb/#namespacedef-gpumapmode
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPUMapMode {
const GPUMapModeFlags READ = 0x0001;

View file

@ -5,7 +5,7 @@
// https://gpuweb.github.io/gpuweb/#gpuobjectbase
[Exposed=(Window)]
interface mixin GPUObjectBase {
attribute USVString? label;
attribute USVString label;
};
dictionary GPUObjectDescriptorBase {

View file

@ -6,16 +6,11 @@
[Exposed=(Window, DedicatedWorker)]
interface mixin GPUProgrammablePassEncoder {
undefined setBindGroup(GPUIndex32 index, GPUBindGroup bindGroup,
optional sequence<GPUBufferDynamicOffset> dynamicOffsets = []);
optional sequence<GPUBufferDynamicOffset> dynamicOffsets = []);
// void setBindGroup(GPUIndex32 index, GPUBindGroup bindGroup,
// Uint32Array dynamicOffsetsData,
// GPUSize64 dynamicOffsetsDataStart,
// GPUSize64 dynamicOffsetsDataLength);
// void pushDebugGroup(DOMString groupLabel);
// void popDebugGroup();
// void insertDebugMarker(DOMString markerLabel);
//undefined pushDebugGroup(USVString groupLabel);
//undefined popDebugGroup();
//undefined insertDebugMarker(USVString markerLabel);
};
typedef [EnforceRange] unsigned long GPUBufferDynamicOffset;

View file

@ -0,0 +1,30 @@
/* 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/. */
// https://gpuweb.github.io/gpuweb/#gpuqueryset
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
interface GPUQuerySet {
undefined destroy();
};
GPUQuerySet includes GPUObjectBase;
dictionary GPUQuerySetDescriptor : GPUObjectDescriptorBase {
required GPUQueryType type;
required GPUSize32 count;
sequence<GPUPipelineStatisticName> pipelineStatistics = [];
};
enum GPUPipelineStatisticName {
"vertex-shader-invocations",
"clipper-invocations",
"clipper-primitives-out",
"fragment-shader-invocations",
"compute-shader-invocations"
};
enum GPUQueryType {
"occlusion",
"pipeline-statistics",
"timestamp"
};

View file

@ -5,27 +5,30 @@
// https://gpuweb.github.io/gpuweb/#gpuqueue
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
interface GPUQueue {
undefined submit(sequence<GPUCommandBuffer> commandBuffers);
undefined submit(sequence<GPUCommandBuffer> buffers);
//GPUFence createFence(optional GPUFenceDescriptor descriptor = {});
//void signal(GPUFence fence, GPUFenceValue signalValue);
//TODO:
//Promise<undefined> onSubmittedWorkDone();
[Throws] undefined writeBuffer(
[Throws]
undefined writeBuffer(
GPUBuffer buffer,
GPUSize64 bufferOffset,
/*[AllowShared]*/ BufferSource data,
BufferSource data,
optional GPUSize64 dataOffset = 0,
optional GPUSize64 size);
[Throws] undefined writeTexture(
GPUTextureCopyView destination,
/*[AllowShared]*/ BufferSource data,
GPUTextureDataLayout dataLayout,
[Throws]
undefined writeTexture(
GPUImageCopyTexture destination,
BufferSource data,
GPUImageDataLayout dataLayout,
GPUExtent3D size);
//void copyImageBitmapToTexture(
// GPUImageBitmapCopyView source,
// GPUTextureCopyView destination,
// GPUExtent3D copySize);
//[Throws]
//undefined copyExternalImageToTexture(
// GPUImageCopyExternalImage source,
// GPUImageCopyTextureTagged destination,
// GPUExtent3D copySize);
};
GPUQueue includes GPUObjectBase;

View file

@ -11,8 +11,7 @@ GPURenderBundleEncoder includes GPUObjectBase;
GPURenderBundleEncoder includes GPUProgrammablePassEncoder;
GPURenderBundleEncoder includes GPURenderEncoderBase;
dictionary GPURenderBundleEncoderDescriptor : GPUObjectDescriptorBase {
required sequence<GPUTextureFormat> colorFormats;
GPUTextureFormat depthStencilFormat;
GPUSize32 sampleCount = 1;
dictionary GPURenderBundleEncoderDescriptor : GPURenderPassLayout {
boolean depthReadOnly = false;
boolean stencilReadOnly = false;
};

View file

@ -2,27 +2,33 @@
* 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/. */
// https://gpuweb.github.io/gpuweb/#gpurenderencoderbase
// https://gpuweb.github.io/gpuweb/#gpurendercommandsmixin
[Exposed=(Window, DedicatedWorker)]
interface mixin GPURenderEncoderBase {
undefined setPipeline(GPURenderPipeline pipeline);
undefined setIndexBuffer(GPUBuffer buffer, optional GPUSize64 offset = 0, optional GPUSize64 size = 0);
undefined setVertexBuffer(
GPUIndex32 slot,
GPUBuffer buffer,
optional GPUSize64 offset = 0,
optional GPUSize64 size = 0
);
undefined setIndexBuffer(GPUBuffer buffer,
GPUIndexFormat indexFormat,
optional GPUSize64 offset = 0,
optional GPUSize64 size = 0);
undefined setVertexBuffer(GPUIndex32 slot,
GPUBuffer buffer,
optional GPUSize64 offset = 0,
optional GPUSize64 size = 0);
undefined draw(GPUSize32 vertexCount, optional GPUSize32 instanceCount = 1,
optional GPUSize32 firstVertex = 0, optional GPUSize32 firstInstance = 0);
undefined drawIndexed(GPUSize32 indexCount, optional GPUSize32 instanceCount = 1,
optional GPUSize32 firstIndex = 0,
optional GPUSignedOffset32 baseVertex = 0,
optional GPUSize32 firstInstance = 0);
undefined draw(GPUSize32 vertexCount,
optional GPUSize32 instanceCount = 1,
optional GPUSize32 firstVertex = 0,
optional GPUSize32 firstInstance = 0);
undefined drawIndexed(GPUSize32 indexCount,
optional GPUSize32 instanceCount = 1,
optional GPUSize32 firstIndex = 0,
optional GPUSignedOffset32 baseVertex = 0,
optional GPUSize32 firstInstance = 0);
//[Pref="dom.webgpu.indirect-dispatch.enabled"]
undefined drawIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
//[Pref="dom.webgpu.indirect-dispatch.enabled"]
undefined drawIndexedIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
};

View file

@ -6,25 +6,27 @@
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPURenderPassEncoder {
undefined setViewport(float x, float y,
float width, float height,
float minDepth, float maxDepth);
float width, float height,
float minDepth, float maxDepth);
undefined setScissorRect(GPUIntegerCoordinate x, GPUIntegerCoordinate y,
GPUIntegerCoordinate width, GPUIntegerCoordinate height);
GPUIntegerCoordinate width, GPUIntegerCoordinate height);
undefined setBlendColor(GPUColor color);
undefined setBlendConstant(GPUColor color);
undefined setStencilReference(GPUStencilValue reference);
//void beginOcclusionQuery(GPUSize32 queryIndex);
//void endOcclusionQuery();
//undefined beginOcclusionQuery(GPUSize32 queryIndex);
//undefined endOcclusionQuery();
//void beginPipelineStatisticsQuery(GPUQuerySet querySet, GPUSize32 queryIndex);
//void endPipelineStatisticsQuery();
//undefined beginPipelineStatisticsQuery(GPUQuerySet querySet, GPUSize32 queryIndex);
//undefined endPipelineStatisticsQuery();
//void writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex);
//undefined writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex);
undefined executeBundles(sequence<GPURenderBundle> bundles);
undefined endPass();
[Throws]
undefined end();
};
GPURenderPassEncoder includes GPUObjectBase;
GPURenderPassEncoder includes GPUProgrammablePassEncoder;

View file

@ -10,21 +10,21 @@ GPURenderPipeline includes GPUObjectBase;
GPURenderPipeline includes GPUPipelineBase;
dictionary GPURenderPipelineDescriptor : GPUPipelineDescriptorBase {
required GPUProgrammableStageDescriptor vertexStage;
GPUProgrammableStageDescriptor fragmentStage;
required GPUPrimitiveTopology primitiveTopology;
GPURasterizationStateDescriptor rasterizationState = {};
required sequence<GPUColorStateDescriptor> colorStates;
GPUDepthStencilStateDescriptor depthStencilState;
GPUVertexStateDescriptor vertexState = {};
GPUSize32 sampleCount = 1;
GPUSampleMask sampleMask = 0xFFFFFFFF;
boolean alphaToCoverageEnabled = false;
required GPUVertexState vertex;
GPUPrimitiveState primitive = {};
GPUDepthStencilState depthStencil;
GPUMultisampleState multisample = {};
GPUFragmentState fragment;
};
typedef [EnforceRange] unsigned long GPUSampleMask;
dictionary GPUPrimitiveState {
GPUPrimitiveTopology topology = "triangle-list";
GPUIndexFormat stripIndexFormat;
GPUFrontFace frontFace = "ccw";
GPUCullMode cullMode = "none";
// Enable depth clamping (requires "depth-clamping" feature)
boolean clampDepth = false;
};
enum GPUPrimitiveTopology {
"point-list",
@ -34,19 +34,6 @@ enum GPUPrimitiveTopology {
"triangle-strip"
};
typedef [EnforceRange] long GPUDepthBias;
dictionary GPURasterizationStateDescriptor {
GPUFrontFace frontFace = "ccw";
GPUCullMode cullMode = "none";
// Enable depth clamping (requires "depth-clamping" extension)
boolean clampDepth = false;
GPUDepthBias depthBias = 0;
float depthBiasSlopeScale = 0;
float depthBiasClamp = 0;
};
enum GPUFrontFace {
"ccw",
"cw"
@ -58,15 +45,31 @@ enum GPUCullMode {
"back"
};
dictionary GPUColorStateDescriptor {
required GPUTextureFormat format;
dictionary GPUMultisampleState {
GPUSize32 count = 1;
GPUSampleMask mask = 0xFFFFFFFF;
boolean alphaToCoverageEnabled = false;
};
GPUBlendDescriptor alphaBlend = {};
GPUBlendDescriptor colorBlend = {};
dictionary GPUFragmentState: GPUProgrammableStage {
required sequence<GPUColorTargetState> targets;
};
dictionary GPUColorTargetState {
required GPUTextureFormat format;
GPUBlendState blend;
GPUColorWriteFlags writeMask = 0xF; // GPUColorWrite.ALL
};
dictionary GPUBlendDescriptor {
dictionary GPUBlendState {
required GPUBlendComponent color;
required GPUBlendComponent alpha;
};
typedef [EnforceRange] unsigned long GPUSampleMask;
typedef [EnforceRange] long GPUDepthBias;
dictionary GPUBlendComponent {
GPUBlendFactor srcFactor = "one";
GPUBlendFactor dstFactor = "zero";
GPUBlendOperation operation = "add";
@ -75,17 +78,17 @@ dictionary GPUBlendDescriptor {
enum GPUBlendFactor {
"zero",
"one",
"src-color",
"one-minus-src-color",
"src",
"one-minus-src",
"src-alpha",
"one-minus-src-alpha",
"dst-color",
"one-minus-dst-color",
"dst",
"one-minus-dst",
"dst-alpha",
"one-minus-dst-alpha",
"src-alpha-saturated",
"blend-color",
"one-minus-blend-color"
"constant",
"one-minus-constant",
};
enum GPUBlendOperation {
@ -96,6 +99,30 @@ enum GPUBlendOperation {
"max"
};
dictionary GPUDepthStencilState {
required GPUTextureFormat format;
boolean depthWriteEnabled = false;
GPUCompareFunction depthCompare = "always";
GPUStencilFaceState stencilFront = {};
GPUStencilFaceState stencilBack = {};
GPUStencilValue stencilReadMask = 0xFFFFFFFF;
GPUStencilValue stencilWriteMask = 0xFFFFFFFF;
GPUDepthBias depthBias = 0;
float depthBiasSlopeScale = 0;
float depthBiasClamp = 0;
};
dictionary GPUStencilFaceState {
GPUCompareFunction compare = "always";
GPUStencilOperation failOp = "keep";
GPUStencilOperation depthFailOp = "keep";
GPUStencilOperation passOp = "keep";
};
enum GPUStencilOperation {
"keep",
"zero",
@ -107,85 +134,63 @@ enum GPUStencilOperation {
"decrement-wrap"
};
typedef [EnforceRange] unsigned long GPUStencilValue;
dictionary GPUDepthStencilStateDescriptor {
required GPUTextureFormat format;
boolean depthWriteEnabled = false;
GPUCompareFunction depthCompare = "always";
GPUStencilStateFaceDescriptor stencilFront = {};
GPUStencilStateFaceDescriptor stencilBack = {};
GPUStencilValue stencilReadMask = 0xFFFFFFFF;
GPUStencilValue stencilWriteMask = 0xFFFFFFFF;
};
dictionary GPUStencilStateFaceDescriptor {
GPUCompareFunction compare = "always";
GPUStencilOperation failOp = "keep";
GPUStencilOperation depthFailOp = "keep";
GPUStencilOperation passOp = "keep";
};
enum GPUIndexFormat {
"uint16",
"uint32"
"uint32",
};
typedef [EnforceRange] unsigned long GPUStencilValue;
enum GPUVertexFormat {
"uchar2",
"uchar4",
"char2",
"char4",
"uchar2norm",
"uchar4norm",
"char2norm",
"char4norm",
"ushort2",
"ushort4",
"short2",
"short4",
"ushort2norm",
"ushort4norm",
"short2norm",
"short4norm",
"half2",
"half4",
"float",
"float2",
"float3",
"float4",
"uint",
"uint2",
"uint3",
"uint4",
"int",
"int2",
"int3",
"int4"
"uint8x2",
"uint8x4",
"sint8x2",
"sint8x4",
"unorm8x2",
"unorm8x4",
"snorm8x2",
"snorm8x4",
"uint16x2",
"uint16x4",
"sint16x2",
"sint16x4",
"unorm16x2",
"unorm16x4",
"snorm16x2",
"snorm16x4",
"float16x2",
"float16x4",
"float32",
"float32x2",
"float32x3",
"float32x4",
"uint32",
"uint32x2",
"uint32x3",
"uint32x4",
"sint32",
"sint32x2",
"sint32x3",
"sint32x4",
};
enum GPUInputStepMode {
enum GPUVertexStepMode {
"vertex",
"instance"
"instance",
};
dictionary GPUVertexStateDescriptor {
GPUIndexFormat indexFormat = "uint32";
sequence<GPUVertexBufferLayoutDescriptor?> vertexBuffers = [];
dictionary GPUVertexState: GPUProgrammableStage {
sequence<GPUVertexBufferLayout?> buffers = [];
};
dictionary GPUVertexBufferLayoutDescriptor {
dictionary GPUVertexBufferLayout {
required GPUSize64 arrayStride;
GPUInputStepMode stepMode = "vertex";
required sequence<GPUVertexAttributeDescriptor> attributes;
GPUVertexStepMode stepMode = "vertex";
required sequence<GPUVertexAttribute> attributes;
};
dictionary GPUVertexAttributeDescriptor {
dictionary GPUVertexAttribute {
required GPUVertexFormat format;
required GPUSize64 offset;
required GPUIndex32 shaderLocation;
};

View file

@ -16,9 +16,9 @@ dictionary GPUSamplerDescriptor : GPUObjectDescriptorBase {
GPUFilterMode minFilter = "nearest";
GPUFilterMode mipmapFilter = "nearest";
float lodMinClamp = 0;
float lodMaxClamp = 0xfffff; // TODO: What should this be? Was Number.MAX_VALUE.
float lodMaxClamp = 1000.0; // TODO: What should this be?
GPUCompareFunction compare;
unsigned short maxAnisotropy = 1;
[Clamp] unsigned short maxAnisotropy = 1;
};
enum GPUAddressMode {
@ -29,7 +29,7 @@ enum GPUAddressMode {
enum GPUFilterMode {
"nearest",
"linear"
"linear",
};
enum GPUCompareFunction {

View file

@ -5,11 +5,13 @@
// https://gpuweb.github.io/gpuweb/#gpushadermodule
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
interface GPUShaderModule {
[Throws]
Promise<GPUCompilationInfo> compilationInfo();
};
GPUShaderModule includes GPUObjectBase;
typedef (Uint32Array or DOMString) GPUShaderCode;
dictionary GPUShaderModuleDescriptor : GPUObjectDescriptorBase {
required GPUShaderCode code;
// UTF8String is not observably different from USVString
required USVString code;
object sourceMap;
};

View file

@ -5,9 +5,9 @@
// https://gpuweb.github.io/gpuweb/#typedefdef-gpushaderstageflags
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
interface GPUShaderStage {
const GPUShaderStageFlags VERTEX = 0x1;
const GPUShaderStageFlags FRAGMENT = 0x2;
const GPUShaderStageFlags COMPUTE = 0x4;
const GPUShaderStageFlags VERTEX = 1;
const GPUShaderStageFlags FRAGMENT = 2;
const GPUShaderStageFlags COMPUTE = 4;
};
typedef unsigned long GPUShaderStageFlags;
typedef [EnforceRange] unsigned long GPUShaderStageFlags;

View file

@ -2,9 +2,8 @@
* 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/. */
// https://gpuweb.github.io/gpuweb/#gpuswapchain
// https://gpuweb.github.io/gpuweb/#gpusupportedfeatures
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPUSwapChain {
GPUTexture getCurrentTexture();
interface GPUSupportedFeatures {
readonly setlike<DOMString>;
};
GPUSwapChain includes GPUObjectBase;

View file

@ -0,0 +1,34 @@
/* 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/. */
// https://gpuweb.github.io/gpuweb/#gpusupportedlimits
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPUSupportedLimits {
readonly attribute unsigned long maxTextureDimension1D;
readonly attribute unsigned long maxTextureDimension2D;
readonly attribute unsigned long maxTextureDimension3D;
readonly attribute unsigned long maxTextureArrayLayers;
readonly attribute unsigned long maxBindGroups;
readonly attribute unsigned long maxDynamicUniformBuffersPerPipelineLayout;
readonly attribute unsigned long maxDynamicStorageBuffersPerPipelineLayout;
readonly attribute unsigned long maxSampledTexturesPerShaderStage;
readonly attribute unsigned long maxSamplersPerShaderStage;
readonly attribute unsigned long maxStorageBuffersPerShaderStage;
readonly attribute unsigned long maxStorageTexturesPerShaderStage;
readonly attribute unsigned long maxUniformBuffersPerShaderStage;
readonly attribute unsigned long maxUniformBufferBindingSize;
readonly attribute unsigned long maxStorageBufferBindingSize;
readonly attribute unsigned long minUniformBufferOffsetAlignment;
readonly attribute unsigned long minStorageBufferOffsetAlignment;
readonly attribute unsigned long maxVertexBuffers;
readonly attribute unsigned long maxVertexAttributes;
readonly attribute unsigned long maxVertexBufferArrayStride;
readonly attribute unsigned long maxInterStageShaderComponents;
readonly attribute unsigned long maxComputeWorkgroupStorageSize;
readonly attribute unsigned long maxComputeInvocationsPerWorkgroup;
readonly attribute unsigned long maxComputeWorkgroupSizeX;
readonly attribute unsigned long maxComputeWorkgroupSizeY;
readonly attribute unsigned long maxComputeWorkgroupSizeZ;
readonly attribute unsigned long maxComputeWorkgroupsPerDimension;
};

View file

@ -5,6 +5,7 @@
// https://gpuweb.github.io/gpuweb/#gputexture
[Exposed=(Window, DedicatedWorker), Serializable , Pref="dom.webgpu.enabled"]
interface GPUTexture {
[NewObject]
GPUTextureView createView(optional GPUTextureViewDescriptor descriptor = {});
undefined destroy();
@ -18,12 +19,13 @@ dictionary GPUTextureDescriptor : GPUObjectDescriptorBase {
GPUTextureDimension dimension = "2d";
required GPUTextureFormat format;
required GPUTextureUsageFlags usage;
sequence<GPUTextureFormat> viewFormats = [];
};
enum GPUTextureDimension {
"1d",
"2d",
"3d"
"3d",
};
enum GPUTextureFormat {
@ -57,9 +59,8 @@ enum GPUTextureFormat {
"bgra8unorm",
"bgra8unorm-srgb",
// Packed 32-bit formats
//"rgb9e5ufloat",
"rgb10a2unorm",
//"rg11b10ufloat",
"rg11b10float",
// 64-bit formats
"rg32uint",
@ -75,7 +76,7 @@ enum GPUTextureFormat {
"rgba32float",
// Depth and stencil formats
//"stencil8",
//"stencil8", //TODO
//"depth16unorm",
"depth24plus",
"depth24plus-stencil8",
@ -94,29 +95,22 @@ enum GPUTextureFormat {
"bc5-rg-unorm",
"bc5-rg-snorm",
"bc6h-rgb-ufloat",
//"bc6h-rgb-float",
"bc6h-rgb-float",
"bc7-rgba-unorm",
"bc7-rgba-unorm-srgb",
// "depth24unorm-stencil8" extension
// "depth24unorm-stencil8" feature
//"depth24unorm-stencil8",
// "depth32float-stencil8" extension
// "depth32float-stencil8" feature
//"depth32float-stencil8",
};
enum GPUTextureComponentType {
"float",
"sint",
"uint",
// Texture is used with comparison sampling only.
"depth-comparison"
};
typedef [EnforceRange] unsigned long GPUIntegerCoordinate;
dictionary GPUExtent3DDict {
required GPUIntegerCoordinate width;
required GPUIntegerCoordinate height;
required GPUIntegerCoordinate depth;
GPUIntegerCoordinate height = 1;
GPUIntegerCoordinate depthOrArrayLayers = 1;
};
typedef [EnforceRange] unsigned long GPUIntegerCoordinate;
typedef (sequence<GPUIntegerCoordinate> or GPUExtent3DDict) GPUExtent3D;

View file

@ -2,14 +2,14 @@
* 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/. */
// https://gpuweb.github.io/gpuweb/#gputextureusage
// https://gpuweb.github.io/gpuweb/#typedefdef-gputextureusageflags
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPUTextureUsage {
const GPUTextureUsageFlags COPY_SRC = 0x01;
const GPUTextureUsageFlags COPY_DST = 0x02;
const GPUTextureUsageFlags SAMPLED = 0x04;
const GPUTextureUsageFlags STORAGE = 0x08;
const GPUTextureUsageFlags OUTPUT_ATTACHMENT = 0x10;
const GPUTextureUsageFlags TEXTURE_BINDING = 0x04;
const GPUTextureUsageFlags STORAGE_BINDING = 0x08;
const GPUTextureUsageFlags RENDER_ATTACHMENT = 0x10;
};
typedef [EnforceRange] unsigned long GPUTextureUsageFlags;

View file

@ -5,6 +5,7 @@
// https://gpuweb.github.io/gpuweb/#gpuvalidationerror
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPUValidationError {
[Throws]
constructor(DOMString message);
readonly attribute DOMString message;
};
@ -18,5 +19,6 @@ enum GPUErrorFilter {
partial interface GPUDevice {
undefined pushErrorScope(GPUErrorFilter filter);
[NewObject]
Promise<GPUError?> popErrorScope();
};

View file

@ -22,5 +22,17 @@ servo_config = { path = "../config" }
smallvec = { workspace = true, features = ["serde"] }
webrender_api = { workspace = true }
webrender_traits = { path = "../webrender_traits" }
wgpu-core = { version = "0.6.0", git = "https://github.com/gfx-rs/wgpu", features = ["replay", "trace", "serial-pass"], rev = "e72724a6e393503c73f37e86aa9317a5c62e32b8" }
wgpu-types = { version = "0.6.0", git = "https://github.com/gfx-rs/wgpu", features = ["replay", "trace"], rev = "e72724a6e393503c73f37e86aa9317a5c62e32b8" }
wgpu-core = { version = "0.16", features = ["replay", "trace", "serial-pass", "wgsl"] }
wgpu-types = { version = "0.16" }
[target.'cfg(any(target_os = "ios", target_os = "macos"))'.dependencies.wgpu-core]
version = "0.16"
features = ["replay", "trace", "serial-pass", "metal"]
[target.'cfg(all(unix, not(target_os = "ios"), not(target_os = "macos")))'.dependencies.wgpu-core]
version = "0.16"
features = ["replay", "trace", "serial-pass", "vulkan"]
[target.'cfg(windows)'.dependencies.wgpu-core]
version = "0.16"
features = ["replay", "trace", "serial-pass", "dx11", "dx12", "vulkan"]

View file

@ -10,8 +10,8 @@ use wgpu::{
hub::{GlobalIdentityHandlerFactory, IdentityHandler, IdentityHandlerFactory},
id::{
AdapterId, BindGroupId, BindGroupLayoutId, BufferId, CommandBufferId, ComputePipelineId,
DeviceId, PipelineLayoutId, RenderBundleId, RenderPipelineId, SamplerId, ShaderModuleId,
SurfaceId, SwapChainId, TextureId, TextureViewId, TypedId,
DeviceId, PipelineLayoutId, QuerySetId, RenderBundleId, RenderPipelineId, SamplerId,
ShaderModuleId, StagingBufferId, SurfaceId, TextureId, TextureViewId, TypedId,
},
};
use wgt::Backend;
@ -28,7 +28,6 @@ pub enum WebGPUMsg {
FreeAdapter(AdapterId),
FreeDevice(DeviceId),
FreeBuffer(BufferId),
FreeSwapChain(SwapChainId),
FreePipelineLayout(PipelineLayoutId),
FreeComputePipeline(ComputePipelineId),
FreeRenderPipeline(RenderPipelineId),
@ -41,6 +40,8 @@ pub enum WebGPUMsg {
FreeSurface(SurfaceId),
FreeShaderModule(ShaderModuleId),
FreeRenderBundle(RenderBundleId),
FreeStagingBuffer(StagingBufferId),
FreeQuerySet(QuerySetId),
WebGPUOpResult {
device: WebGPUDevice,
scope_id: Option<ErrorScopeId>,
@ -92,9 +93,14 @@ impl_identity_handler!(TextureId, "texture", WebGPUMsg::FreeTexture);
impl_identity_handler!(TextureViewId, "texture_view", WebGPUMsg::FreeTextureView);
impl_identity_handler!(BufferId, "buffer", WebGPUMsg::FreeBuffer);
impl_identity_handler!(BindGroupId, "bind_group", WebGPUMsg::FreeBindGroup);
impl_identity_handler!(SwapChainId, "swap_chain", WebGPUMsg::FreeSwapChain);
impl_identity_handler!(ShaderModuleId, "shader_module", WebGPUMsg::FreeShaderModule);
impl_identity_handler!(RenderBundleId, "render_bundle", WebGPUMsg::FreeRenderBundle);
impl_identity_handler!(
StagingBufferId,
"staging_buffer",
WebGPUMsg::FreeStagingBuffer
);
impl_identity_handler!(QuerySetId, "quary_set", WebGPUMsg::FreeQuerySet);
impl_identity_handler!(
RenderPipelineId,
"render_pipeline",
@ -149,7 +155,7 @@ where
IdentityRecycler: IdentityHandler<I>,
{
type Filter = IdentityRecycler;
fn spawn(&self, _min_index: u32) -> Self::Filter {
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
sender: self.sender.clone(),
self_sender: self.self_sender.clone(),

View file

@ -35,11 +35,14 @@ use webrender_traits::{
WebrenderExternalImageApi, WebrenderExternalImageRegistry, WebrenderImageHandlerType,
WebrenderImageSource,
};
use wgpu::device::DeviceDescriptor;
use wgpu::pipeline::ShaderModuleDescriptor;
use wgpu::resource::{BufferMapCallback, BufferMapCallbackC};
use wgpu::{
binding_model::{BindGroupDescriptor, BindGroupLayoutDescriptor, PipelineLayoutDescriptor},
command::{
BufferCopyView, ComputePass, RenderBundleDescriptor, RenderBundleEncoder, RenderPass,
TextureCopyView,
ComputePass, ImageCopyBuffer, ImageCopyTexture, RenderBundleDescriptor,
RenderBundleEncoder, RenderPass,
},
device::{HostMap, ImplicitPipelineIds},
id,
@ -50,6 +53,7 @@ use wgpu::{
TextureDescriptor, TextureViewDescriptor,
},
};
use wgt::{Dx12Compiler, InstanceDescriptor};
pub type ErrorScopeId = NonZeroU64;
const DEVICE_POLL_INTERVAL: u64 = 100;
@ -58,15 +62,15 @@ pub const PRESENTATION_BUFFER_COUNT: usize = 10;
#[derive(Debug, Deserialize, Serialize)]
pub enum WebGPUResponse {
RequestAdapter {
adapter_name: String,
adapter_info: wgt::AdapterInfo,
adapter_id: WebGPUAdapter,
limits: wgt::Limits,
channel: WebGPU,
},
RequestDevice {
device_id: WebGPUDevice,
queue_id: WebGPUQueue,
descriptor: wgt::DeviceDescriptor,
label: Option<String>,
descriptor: wgt::DeviceDescriptor<Option<String>>,
},
BufferMapAsync(IpcSharedMemory),
}
@ -100,20 +104,20 @@ pub enum WebGPURequest {
},
CopyBufferToTexture {
command_encoder_id: id::CommandEncoderId,
source: BufferCopyView,
destination: TextureCopyView,
source: ImageCopyBuffer,
destination: ImageCopyTexture,
copy_size: wgt::Extent3d,
},
CopyTextureToBuffer {
command_encoder_id: id::CommandEncoderId,
source: TextureCopyView,
destination: BufferCopyView,
source: ImageCopyTexture,
destination: ImageCopyBuffer,
copy_size: wgt::Extent3d,
},
CopyTextureToTexture {
command_encoder_id: id::CommandEncoderId,
source: TextureCopyView,
destination: TextureCopyView,
source: ImageCopyTexture,
destination: ImageCopyTexture,
copy_size: wgt::Extent3d,
},
CreateBindGroup {
@ -164,7 +168,8 @@ pub enum WebGPURequest {
CreateShaderModule {
device_id: id::DeviceId,
program_id: id::ShaderModuleId,
program: Vec<u32>,
program: String,
label: Option<String>,
},
CreateSwapChain {
device_id: id::DeviceId,
@ -186,6 +191,7 @@ pub enum WebGPURequest {
descriptor: Option<TextureViewDescriptor<'static>>,
},
DestroyBuffer(id::BufferId),
DestroyDevice(id::DeviceId),
DestroySwapChain {
external_id: u64,
image_key: ImageKey,
@ -208,10 +214,9 @@ pub enum WebGPURequest {
RequestDevice {
sender: IpcSender<WebGPUResponseResult>,
adapter_id: WebGPUAdapter,
descriptor: wgt::DeviceDescriptor,
descriptor: wgt::DeviceDescriptor<Option<String>>,
device_id: id::DeviceId,
pipeline_id: PipelineId,
label: Option<String>,
},
RunComputePass {
command_encoder_id: id::CommandEncoderId,
@ -251,8 +256,8 @@ pub enum WebGPURequest {
},
WriteTexture {
queue_id: id::QueueId,
texture_cv: TextureCopyView,
data_layout: wgt::TextureDataLayout,
texture_cv: ImageCopyTexture,
data_layout: wgt::ImageDataLayout,
size: wgt::Extent3d,
data: IpcSharedMemory,
},
@ -371,7 +376,14 @@ impl<'a> WGPU<'a> {
receiver,
sender,
script_sender,
global: wgpu::hub::Global::new("wgpu-core", factory, wgt::BackendBit::PRIMARY),
global: wgpu::hub::Global::new(
"wgpu-core",
factory,
InstanceDescriptor {
backends: wgt::Backends::PRIMARY,
dx12_shader_compiler: Dx12Compiler::default(),
},
),
adapters: Vec::new(),
devices: HashMap::new(),
_invalid_adapters: Vec::new(),
@ -409,7 +421,7 @@ impl<'a> WGPU<'a> {
external_id: None,
};
self.buffer_maps.insert(buffer_id, Rc::new(map_info));
// TODO(sagudev): replace with safe callback
unsafe extern "C" fn callback(
status: BufferMapAsyncStatus,
userdata: *mut u8,
@ -420,10 +432,11 @@ impl<'a> WGPU<'a> {
let msg = match status {
BufferMapAsyncStatus::Success => {
let global = &info.global;
let data_pt = gfx_select!(info.buffer_id =>
let (slice_pointer, range_size) = gfx_select!(info.buffer_id =>
global.buffer_get_mapped_range(info.buffer_id, 0, None))
.unwrap();
let data = slice::from_raw_parts(data_pt, info.size);
let data =
slice::from_raw_parts(slice_pointer, range_size as usize);
Ok(WebGPUResponse::BufferMapAsync(IpcSharedMemory::from_bytes(
data,
)))
@ -440,10 +453,14 @@ impl<'a> WGPU<'a> {
let operation = BufferMapOperation {
host: host_map,
callback,
user_data: convert_to_pointer(
self.buffer_maps.get(&buffer_id).unwrap().clone(),
),
callback: unsafe {
BufferMapCallback::from_c(BufferMapCallbackC {
callback,
user_data: convert_to_pointer(
self.buffer_maps.get(&buffer_id).unwrap().clone(),
),
})
},
};
let global = &self.global;
let result = gfx_select!(buffer_id => global.buffer_map_async(buffer_id, map_range, operation));
@ -472,10 +489,12 @@ impl<'a> WGPU<'a> {
{
Err(err.clone())
} else {
gfx_select!(command_encoder_id => global.command_encoder_finish(
command_encoder_id,
&wgt::CommandBufferDescriptor::default()
))
tuple_to_result(
gfx_select!(command_encoder_id => global.command_encoder_finish(
command_encoder_id,
&wgt::CommandBufferDescriptor::default()
)),
)
.map_err(|e| format!("{:?}", e))
};
self.encoder_record_error(command_encoder_id, &result);
@ -551,11 +570,8 @@ impl<'a> WGPU<'a> {
descriptor,
} => {
let global = &self.global;
let result = gfx_select!(bind_group_id =>
global.device_create_bind_group(device_id, &descriptor, bind_group_id));
if result.is_err() {
let _ = gfx_select!(bind_group_id => global.bind_group_error(bind_group_id));
}
let result = tuple_to_result(gfx_select!(bind_group_id =>
global.device_create_bind_group(device_id, &descriptor, bind_group_id)));
self.send_result(device_id, scope_id, result);
},
WebGPURequest::CreateBindGroupLayout {
@ -565,16 +581,10 @@ impl<'a> WGPU<'a> {
} => {
let global = &self.global;
if let Some(desc) = descriptor {
let result = gfx_select!(bind_group_layout_id =>
global.device_create_bind_group_layout(device_id, &desc, bind_group_layout_id));
if result.is_err() {
let _ = gfx_select!(bind_group_layout_id =>
global.bind_group_layout_error(bind_group_layout_id));
}
let result = tuple_to_result(gfx_select!(bind_group_layout_id =>
global.device_create_bind_group_layout(device_id, &desc, bind_group_layout_id)));
self.send_result(device_id, scope_id, result);
} else {
let _ = gfx_select!(bind_group_layout_id =>
global.bind_group_layout_error(bind_group_layout_id));
}
},
WebGPURequest::CreateBuffer {
@ -584,14 +594,10 @@ impl<'a> WGPU<'a> {
} => {
let global = &self.global;
if let Some(desc) = descriptor {
let result = gfx_select!(buffer_id =>
global.device_create_buffer(device_id, &desc, buffer_id));
if result.is_err() {
let _ = gfx_select!(buffer_id => global.buffer_error(buffer_id));
}
let result = tuple_to_result(gfx_select!(buffer_id =>
global.device_create_buffer(device_id, &desc, buffer_id)));
self.send_result(device_id, scope_id, result);
} else {
let _ = gfx_select!(buffer_id => global.buffer_error(buffer_id));
}
},
WebGPURequest::CreateCommandEncoder {
@ -601,11 +607,9 @@ impl<'a> WGPU<'a> {
} => {
let global = &self.global;
let desc = wgt::CommandEncoderDescriptor { label };
let result = gfx_select!(command_encoder_id =>
global.device_create_command_encoder(device_id, &desc, command_encoder_id));
if result.is_err() {
let _ = gfx_select!(command_encoder_id => global.command_encoder_error(command_encoder_id));
}
let result = tuple_to_result(gfx_select!(command_encoder_id =>
global.device_create_command_encoder(device_id, &desc, command_encoder_id)));
self.send_result(device_id, scope_id, result);
},
WebGPURequest::CreateComputePipeline {
@ -625,22 +629,14 @@ impl<'a> WGPU<'a> {
root_id: *layout,
group_ids: bgls.as_slice(),
});
let result = gfx_select!(compute_pipeline_id => global.device_create_compute_pipeline(
device_id,
&descriptor,
compute_pipeline_id,
implicit
));
if result.is_err() {
let _ = gfx_select!(compute_pipeline_id =>
global.compute_pipeline_error(compute_pipeline_id));
if let Some((layout, bgls)) = implicit_ids {
let _ = gfx_select!(layout => global.pipeline_layout_error(layout));
bgls.iter().for_each(|&bgl| {
let _ = gfx_select!(bgl => global.bind_group_layout_error(bgl));
});
}
}
let result = tuple_to_result(
gfx_select!(compute_pipeline_id => global.device_create_compute_pipeline(
device_id,
&descriptor,
compute_pipeline_id,
implicit
)),
);
self.send_result(device_id, scope_id, result);
},
WebGPURequest::CreateContext(sender) => {
@ -659,11 +655,8 @@ impl<'a> WGPU<'a> {
descriptor,
} => {
let global = &self.global;
let result = gfx_select!(pipeline_layout_id =>
global.device_create_pipeline_layout(device_id, &descriptor, pipeline_layout_id));
if result.is_err() {
let _ = gfx_select!(pipeline_layout_id => global.pipeline_layout_error(pipeline_layout_id));
}
let result = tuple_to_result(gfx_select!(pipeline_layout_id =>
global.device_create_pipeline_layout(device_id, &descriptor, pipeline_layout_id)));
self.send_result(device_id, scope_id, result);
},
WebGPURequest::CreateRenderPipeline {
@ -684,22 +677,9 @@ impl<'a> WGPU<'a> {
group_ids: bgls.as_slice(),
});
if let Some(desc) = descriptor {
let result = gfx_select!(render_pipeline_id =>
global.device_create_render_pipeline(device_id, &desc, render_pipeline_id, implicit));
if result.is_err() {
let _ = gfx_select!(render_pipeline_id =>
global.render_pipeline_error(render_pipeline_id));
if let Some((layout, bgls)) = implicit_ids {
let _ =
gfx_select!(layout => global.pipeline_layout_error(layout));
bgls.iter().for_each(|&bgl| {
let _ = gfx_select!(bgl => global.bind_group_layout_error(bgl));
});
}
}
let result = tuple_to_result(gfx_select!(render_pipeline_id =>
global.device_create_render_pipeline(device_id, &desc, render_pipeline_id, implicit)));
self.send_result(device_id, scope_id, result);
} else {
let _ = gfx_select!(render_pipeline_id => global.render_pipeline_error(render_pipeline_id));
}
},
WebGPURequest::CreateSampler {
@ -708,30 +688,31 @@ impl<'a> WGPU<'a> {
descriptor,
} => {
let global = &self.global;
let result = gfx_select!(sampler_id => global.device_create_sampler(
device_id,
&descriptor,
sampler_id
));
if result.is_err() {
let _ = gfx_select!(sampler_id => global.sampler_error(sampler_id));
}
let result = tuple_to_result(
gfx_select!(sampler_id => global.device_create_sampler(
device_id,
&descriptor,
sampler_id
)),
);
self.send_result(device_id, scope_id, result);
},
WebGPURequest::CreateShaderModule {
device_id,
program_id,
program,
label,
} => {
let global = &self.global;
let source =
wgpu_core::pipeline::ShaderModuleSource::SpirV(Cow::Owned(program));
let result = gfx_select!(program_id =>
global.device_create_shader_module(device_id, source, program_id));
if result.is_err() {
let _ =
gfx_select!(program_id => global.shader_module_error(program_id));
}
let source = wgpu_core::pipeline::ShaderModuleSource::Wgsl(
crate::Cow::Owned(program),
);
let desc = ShaderModuleDescriptor {
label: label.map(|s| s.into()),
shader_bound_checks: wgt::ShaderBoundChecks::default(),
};
let result = tuple_to_result(gfx_select!(program_id =>
global.device_create_shader_module(device_id, &desc, source, program_id)));
self.send_result(device_id, scope_id, result);
},
WebGPURequest::CreateSwapChain {
@ -785,17 +766,14 @@ impl<'a> WGPU<'a> {
} => {
let global = &self.global;
if let Some(desc) = descriptor {
let result = gfx_select!(texture_id => global.device_create_texture(
device_id,
&desc,
texture_id
));
if result.is_err() {
let _ = gfx_select!(texture_id => global.texture_error(texture_id));
}
let result = tuple_to_result(
gfx_select!(texture_id => global.device_create_texture(
device_id,
&desc,
texture_id
)),
);
self.send_result(device_id, scope_id, result);
} else {
let _ = gfx_select!(texture_id => global.texture_error(texture_id));
}
},
WebGPURequest::CreateTextureView {
@ -806,23 +784,25 @@ impl<'a> WGPU<'a> {
} => {
let global = &self.global;
if let Some(desc) = descriptor {
let result = gfx_select!(texture_view_id => global.texture_create_view(
texture_id,
&desc,
texture_view_id
));
if result.is_err() {
let _ = gfx_select!(texture_view_id => global.texture_view_error(texture_view_id));
}
let result = tuple_to_result(
gfx_select!(texture_view_id => global.texture_create_view(
texture_id,
&desc,
texture_view_id
)),
);
self.send_result(device_id, scope_id, result);
} else {
let _ = gfx_select!(texture_view_id => global.texture_view_error(texture_view_id));
}
},
WebGPURequest::DestroyBuffer(buffer) => {
let global = &self.global;
gfx_select!(buffer => global.buffer_drop(buffer, false));
},
WebGPURequest::DestroyDevice(device) => {
let global = &self.global;
gfx_select!(device => global.device_drop(device));
},
WebGPURequest::DestroySwapChain {
external_id,
image_key,
@ -852,7 +832,7 @@ impl<'a> WGPU<'a> {
},
WebGPURequest::DestroyTexture(texture) => {
let global = &self.global;
gfx_select!(texture => global.texture_drop(texture));
gfx_select!(texture => global.texture_drop(texture, true));
},
WebGPURequest::Exit(sender) => {
if let Err(e) = self.script_sender.send(WebGPUMsg::Exit) {
@ -885,14 +865,14 @@ impl<'a> WGPU<'a> {
device_id,
} => {
let global = &self.global;
let result = gfx_select!(render_bundle_id => global.render_bundle_encoder_finish(
render_bundle_encoder,
&descriptor,
render_bundle_id
));
if result.is_err() {
let _ = gfx_select!(render_bundle_id => global.render_bundle_error(render_bundle_id));
}
let result = tuple_to_result(
gfx_select!(render_bundle_id => global.render_bundle_encoder_finish(
render_bundle_encoder,
&descriptor,
render_bundle_id
)),
);
self.send_result(device_id, scope_id, result);
},
WebGPURequest::RequestAdapter {
@ -920,9 +900,12 @@ impl<'a> WGPU<'a> {
let global = &self.global;
let info =
gfx_select!(adapter_id => global.adapter_get_info(adapter_id)).unwrap();
let limits =
gfx_select!(adapter_id => global.adapter_limits(adapter_id)).unwrap();
if let Err(e) = sender.send(Ok(WebGPUResponse::RequestAdapter {
adapter_name: info.name,
adapter_info: info,
adapter_id: adapter,
limits,
channel: WebGPU(self.sender.clone()),
})) {
warn!(
@ -937,18 +920,23 @@ impl<'a> WGPU<'a> {
descriptor,
device_id,
pipeline_id,
label,
} => {
let desc = DeviceDescriptor {
label: descriptor.label.as_ref().map(|l| crate::Cow::from(l)),
features: descriptor.features.clone(),
limits: descriptor.limits.clone(),
};
let global = &self.global;
let id = match gfx_select!(device_id => global.adapter_request_device(
adapter_id.0,
&descriptor,
None,
device_id
)) {
let id = match tuple_to_result(
gfx_select!(device_id => global.adapter_request_device(
adapter_id.0,
&desc,
None,
device_id
)),
) {
Ok(id) => id,
Err(e) => {
let _ = gfx_select!(device_id => global.device_error(device_id));
if let Err(w) = sender.send(Err(format!("{:?}", e))) {
warn!(
"Failed to send response to WebGPURequest::RequestDevice ({})",
@ -967,7 +955,6 @@ impl<'a> WGPU<'a> {
device_id: device,
queue_id: queue,
descriptor,
label,
})) {
warn!(
"Failed to send response to WebGPURequest::RequestDevice ({})",
@ -1051,8 +1038,8 @@ impl<'a> WGPU<'a> {
let buffer_desc = wgt::BufferDescriptor {
label: None,
size: buffer_size,
usage: wgt::BufferUsage::MAP_READ |
wgt::BufferUsage::COPY_DST,
usage: wgt::BufferUsages::MAP_READ |
wgt::BufferUsages::COPY_DST,
mapped_at_creation: false,
};
let _ = gfx_select!(b_id => global.device_create_buffer(
@ -1084,23 +1071,24 @@ impl<'a> WGPU<'a> {
encoder_id
));
let buffer_cv = BufferCopyView {
let buffer_cv = ImageCopyBuffer {
buffer: buffer_id,
layout: wgt::TextureDataLayout {
layout: wgt::ImageDataLayout {
offset: 0,
bytes_per_row: buffer_stride,
rows_per_image: 0,
bytes_per_row: Some(buffer_stride),
rows_per_image: None,
},
};
let texture_cv = TextureCopyView {
let texture_cv = ImageCopyTexture {
texture: texture_id,
mip_level: 0,
origin: wgt::Origin3d::ZERO,
aspect: wgt::TextureAspect::All,
};
let copy_size = wgt::Extent3d {
width: size.width as u32,
height: size.height as u32,
depth: 1,
depth_or_array_layers: 1,
};
let _ = gfx_select!(encoder_id => global.command_encoder_copy_texture_to_buffer(
encoder_id,
@ -1126,6 +1114,7 @@ impl<'a> WGPU<'a> {
};
self.present_buffer_maps
.insert(buffer_id, Rc::new(map_info));
// TODO(sagudev): replace with safe callback
unsafe extern "C" fn callback(
status: BufferMapAsyncStatus,
userdata: *mut u8,
@ -1152,10 +1141,14 @@ impl<'a> WGPU<'a> {
}
let map_op = BufferMapOperation {
host: HostMap::Read,
callback,
user_data: convert_to_pointer(
self.present_buffer_maps.get(&buffer_id).unwrap().clone(),
),
callback: unsafe {
BufferMapCallback::from_c(BufferMapCallbackC {
callback,
user_data: convert_to_pointer(
self.present_buffer_maps.get(&buffer_id).unwrap().clone(),
),
})
},
};
let _ = gfx_select!(buffer_id => global.buffer_map_async(buffer_id, 0..buffer_size, map_op));
},
@ -1169,14 +1162,17 @@ impl<'a> WGPU<'a> {
} => {
let global = &self.global;
if !is_map_read {
let map_ptr = gfx_select!(buffer_id => global.buffer_get_mapped_range(
buffer_id,
offset,
wgt::BufferSize::new(size)
))
.unwrap();
unsafe { slice::from_raw_parts_mut(map_ptr, size as usize) }
.copy_from_slice(&array_buffer);
let (slice_pointer, range_size) =
gfx_select!(buffer_id => global.buffer_get_mapped_range(
buffer_id,
offset,
Some(size)
))
.unwrap();
unsafe {
slice::from_raw_parts_mut(slice_pointer, range_size as usize)
}
.copy_from_slice(&array_buffer);
}
let result = gfx_select!(buffer_id => global.buffer_unmap(buffer_id));
self.send_result(device_id, scope_id, result);
@ -1187,10 +1183,12 @@ impl<'a> WGPU<'a> {
external_id,
} => {
let global = &self.global;
let data_pt = gfx_select!(buffer_id =>
global.buffer_get_mapped_range(buffer_id, 0, None))
let (slice_pointer, range_size) = gfx_select!(buffer_id =>
global.buffer_get_mapped_range(buffer_id, 0, Some(buffer_size as u64)))
.unwrap();
let data = unsafe { slice::from_raw_parts(data_pt, buffer_size) }.to_vec();
let data =
unsafe { slice::from_raw_parts(slice_pointer, range_size as usize) }
.to_vec();
if let Some(present_data) =
self.wgpu_image_map.lock().unwrap().get_mut(&external_id)
{
@ -1297,6 +1295,14 @@ fn convert_to_pointer<T: Sized>(obj: Rc<T>) -> *mut u8 {
Rc::into_raw(obj) as *mut u8
}
fn tuple_to_result<T, E>(res: (T, Option<E>)) -> Result<T, E> {
if let Some(err) = res.1 {
Err(err)
} else {
Ok(res.0)
}
}
macro_rules! webgpu_resource {
($name:ident, $id:ty) => {
#[derive(Clone, Copy, Debug, Deserialize, Hash, PartialEq, Serialize)]
@ -1326,7 +1332,7 @@ webgpu_resource!(WebGPURenderBundle, id::RenderBundleId);
webgpu_resource!(WebGPURenderPipeline, id::RenderPipelineId);
webgpu_resource!(WebGPUSampler, id::SamplerId);
webgpu_resource!(WebGPUShaderModule, id::ShaderModuleId);
webgpu_resource!(WebGPUSwapChain, id::SwapChainId);
webgpu_resource!(WebGPUSurface, id::SurfaceId);
webgpu_resource!(WebGPUTexture, id::TextureId);
webgpu_resource!(WebGPUTextureView, id::TextureViewId);

View file

@ -26,7 +26,7 @@ libc = { workspace = true }
winapi = { workspace = true, features = ["wingdi", "winuser", "winnt", "winbase", "processenv", "namedpipeapi", "ntdef", "minwindef", "handleapi", "debugapi"] }
[build-dependencies]
cbindgen = "0.20"
cbindgen = "0.24"
[features]
debugmozjs = ["simpleservo/debugmozjs"]

View file

@ -775,7 +775,7 @@ tests/wpt/mozilla/tests for Servo-only tests""" % reference_path)
delete(path.join(tdir, "webgpu"))
copy_tree(path.join(clone_dir, "out-wpt"), path.join(tdir, "webgpu"))
# update commit
commit = subprocess.check_output(["git", "rev-parse", "HEAD"]).decode()
commit = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=clone_dir).decode()
with open(path.join(tdir, "checkout_commit.txt"), 'w') as file:
file.write(commit)
# clean up

View file

@ -25,17 +25,14 @@ packages = [
"base64",
"cfg-if",
"cookie",
"fixedbitset",
"getrandom",
"image",
"itoa",
"libloading",
"metal",
"miniz_oxide",
"num-rational",
"parking_lot",
"parking_lot_core",
"petgraph",
"png",
"rand",
"rand_chacha",
@ -74,14 +71,24 @@ packages = [
"digest",
"generic-array",
# Duplicated by winit/surfman update.
"raw-window-handle",
# Duplicated by surfman/wgpu update.
"bitflags",
"windows-sys",
"windows-targets",
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_msvc",
"windows_x86_64_gnullvm",
# Temporarily duplicated until gleam can be upgrded.
"uuid",
# winit port minibrowser (servo/servo#30049)
"clipboard-win",
"ahash",
]
# Files that are ignored for all tidy and lint checks.
files = [
@ -132,4 +139,4 @@ directories = [
# Directories that are checked for correct file extension
[check_ext]
# directory, list of expected file extensions
"./components/script/dom/webidls" = [".webidl"]
"./components/script/dom/webidls" = [".webidl", "noidl"]

View file

@ -470,7 +470,7 @@
[]
],
"checkout_commit.txt": [
"5db12b3c0c240f6567fa294f3fa56dfd75b6e891",
"ede5c184cdc42d0374d6e712f49f86313747cfea",
[]
],
"webgpu": {

File diff suppressed because it is too large Load diff

View file

@ -1,2 +1,2 @@
[canvas_clear.https.html]
expected: TIMEOUT
expected: CRASH

View file

@ -1,2 +1,2 @@
[canvas_colorspace_rgba16float.https.html]
expected: TIMEOUT
expected: CRASH

View file

@ -1,2 +1,2 @@
[canvas_complex_rgba16float_copy.https.html]
expected: TIMEOUT
expected: CRASH

View file

@ -1,2 +1,2 @@
[canvas_complex_rgba16float_draw.https.html]
expected: TIMEOUT
expected: CRASH

View file

@ -1,2 +1,2 @@
[canvas_complex_rgba16float_store.https.html]
expected: TIMEOUT
expected: CRASH

View file

@ -1,2 +1,2 @@
[canvas_complex_rgba8unorm_store.https.html]
expected: TIMEOUT
expected: CRASH

View file

@ -1,2 +1,2 @@
[canvas_composite_alpha_bgra8unorm_opaque_copy.https.html]
expected: TIMEOUT
expected: [PASS, FAIL]

View file

@ -1,2 +1,2 @@
[canvas_composite_alpha_bgra8unorm_opaque_draw.https.html]
expected: TIMEOUT
expected: [PASS, FAIL]

View file

@ -1,2 +1,2 @@
[canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html]
expected: TIMEOUT
expected: FAIL

View file

@ -1,2 +1,2 @@
[canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html]
expected: TIMEOUT
expected: FAIL

View file

@ -1,2 +1,2 @@
[canvas_composite_alpha_rgba16float_opaque_copy.https.html]
expected: TIMEOUT
expected: CRASH

View file

@ -1,2 +1,2 @@
[canvas_composite_alpha_rgba16float_opaque_draw.https.html]
expected: TIMEOUT
expected: CRASH

View file

@ -1,2 +1,2 @@
[canvas_composite_alpha_rgba16float_premultiplied_copy.https.html]
expected: TIMEOUT
expected: CRASH

View file

@ -1,2 +1,2 @@
[canvas_composite_alpha_rgba16float_premultiplied_draw.https.html]
expected: TIMEOUT
expected: CRASH

View file

@ -1,2 +1,2 @@
[canvas_composite_alpha_rgba8unorm_opaque_copy.https.html]
expected: TIMEOUT
expected: [PASS, FAIL]

View file

@ -1,2 +1,2 @@
[canvas_composite_alpha_rgba8unorm_opaque_draw.https.html]
expected: TIMEOUT
expected: [PASS, FAIL]

View file

@ -1,2 +1,2 @@
[canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html]
expected: TIMEOUT
expected: FAIL

View file

@ -1,2 +1,2 @@
[canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html]
expected: TIMEOUT
expected: FAIL

View file

@ -1,2 +1,2 @@
[canvas_image_rendering.https.html]
expected: TIMEOUT
expected: CRASH

View file

@ -1 +1 @@
9ab2eade6a818ed58ac1a7b36b706858f3ba5eb3
480edec387e8cd5bf5934680050c59a3f7a01438