Auto merge of #27480 - kunalmohan:gpu-void-error, r=kvark

WebGPU-Report errors in Promise or void returning operations

<!-- Please describe your changes on the following line: -->
This also updates GPUBuffer mapping to match latest spec.

r?@kvark

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
This commit is contained in:
bors-servo 2020-08-04 16:37:16 -04:00 committed by GitHub
commit 549179bbd6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 489 additions and 305 deletions

6
Cargo.lock generated
View file

@ -3701,7 +3701,7 @@ checksum = "0419348c027fa7be448d2ae7ea0e4e04c2334c31dc4e74ab29f00a2a7ca69204"
[[package]] [[package]]
name = "naga" name = "naga"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/gfx-rs/naga?rev=94802078c3bc5d138f497419ea3e7a869f10916d#94802078c3bc5d138f497419ea3e7a869f10916d" source = "git+https://github.com/gfx-rs/naga?rev=1eb637038dd15fc1dad770eca8e6943424dbc122#1eb637038dd15fc1dad770eca8e6943424dbc122"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"fxhash", "fxhash",
@ -6911,7 +6911,7 @@ dependencies = [
[[package]] [[package]]
name = "wgpu-core" name = "wgpu-core"
version = "0.5.0" version = "0.5.0"
source = "git+https://github.com/gfx-rs/wgpu#9e4839eb049707629fa8a91e3603085433f352a4" source = "git+https://github.com/gfx-rs/wgpu#872a6c4c2bab5591838219c34e0cbf5fa9c2ec85"
dependencies = [ dependencies = [
"arrayvec 0.5.1", "arrayvec 0.5.1",
"bitflags", "bitflags",
@ -6938,7 +6938,7 @@ dependencies = [
[[package]] [[package]]
name = "wgpu-types" name = "wgpu-types"
version = "0.5.0" version = "0.5.0"
source = "git+https://github.com/gfx-rs/wgpu#9e4839eb049707629fa8a91e3603085433f352a4" source = "git+https://github.com/gfx-rs/wgpu#872a6c4c2bab5591838219c34e0cbf5fa9c2ec85"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"serde", "serde",

View file

@ -2169,7 +2169,7 @@ where
options, options,
ids, ids,
}; };
if webgpu_chan.0.send(adapter_request).is_err() { if webgpu_chan.0.send((None, adapter_request)).is_err() {
return warn!("Failed to send request adapter message on WebGPU channel"); return warn!("Failed to send request adapter message on WebGPU channel");
} }
}, },

View file

@ -831,6 +831,7 @@ malloc_size_of_is_0!(bool, char, str);
malloc_size_of_is_0!(u8, u16, u32, u64, u128, usize); malloc_size_of_is_0!(u8, u16, u32, u64, u128, usize);
malloc_size_of_is_0!(i8, i16, i32, i64, i128, isize); malloc_size_of_is_0!(i8, i16, i32, i64, i128, isize);
malloc_size_of_is_0!(f32, f64); malloc_size_of_is_0!(f32, f64);
malloc_size_of_is_0!(std::num::NonZeroU64);
malloc_size_of_is_0!(std::sync::atomic::AtomicBool); malloc_size_of_is_0!(std::sync::atomic::AtomicBool);
malloc_size_of_is_0!(std::sync::atomic::AtomicIsize); malloc_size_of_is_0!(std::sync::atomic::AtomicIsize);

View file

@ -138,6 +138,7 @@ use std::cell::{Cell, RefCell, UnsafeCell};
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
use std::hash::{BuildHasher, Hash}; use std::hash::{BuildHasher, Hash};
use std::mem; use std::mem;
use std::num::NonZeroU64;
use std::ops::{Deref, DerefMut, Range}; use std::ops::{Deref, DerefMut, Range};
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
@ -524,6 +525,7 @@ unsafe_no_jsmanaged_fields!(ActiveUniformBlockInfo);
unsafe_no_jsmanaged_fields!(bool, f32, f64, String, AtomicBool, AtomicUsize, Uuid, char); unsafe_no_jsmanaged_fields!(bool, f32, f64, String, AtomicBool, AtomicUsize, Uuid, char);
unsafe_no_jsmanaged_fields!(usize, u8, u16, u32, u64); unsafe_no_jsmanaged_fields!(usize, u8, u16, u32, u64);
unsafe_no_jsmanaged_fields!(isize, i8, i16, i32, i64); unsafe_no_jsmanaged_fields!(isize, i8, i16, i32, i64);
unsafe_no_jsmanaged_fields!(NonZeroU64);
unsafe_no_jsmanaged_fields!(Error); unsafe_no_jsmanaged_fields!(Error);
unsafe_no_jsmanaged_fields!(ServoUrl, ImmutableOrigin, MutableOrigin); unsafe_no_jsmanaged_fields!(ServoUrl, ImmutableOrigin, MutableOrigin);
unsafe_no_jsmanaged_fields!(Image, ImageMetadata, dyn ImageCache, PendingImageId); unsafe_no_jsmanaged_fields!(Image, ImageMetadata, dyn ImageCache, PendingImageId);

View file

@ -127,7 +127,7 @@ use std::sync::Arc;
use std::thread::JoinHandle; use std::thread::JoinHandle;
use time::{get_time, Timespec}; use time::{get_time, Timespec};
use uuid::Uuid; use uuid::Uuid;
use webgpu::{identity::WebGPUOpResult, WebGPUDevice}; use webgpu::{identity::WebGPUOpResult, ErrorScopeId, WebGPUDevice};
#[derive(JSTraceable)] #[derive(JSTraceable)]
pub struct AutoCloseWorker { pub struct AutoCloseWorker {
@ -3023,7 +3023,7 @@ impl GlobalScope {
pub fn handle_wgpu_msg( pub fn handle_wgpu_msg(
&self, &self,
device: WebGPUDevice, device: WebGPUDevice,
scope: Option<u64>, scope: Option<ErrorScopeId>,
result: WebGPUOpResult, result: WebGPUOpResult,
) { ) {
self.gpu_devices self.gpu_devices

View file

@ -41,7 +41,7 @@ impl GPU {
} }
pub trait AsyncWGPUListener { pub trait AsyncWGPUListener {
fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>); fn handle_response(&self, response: WebGPUResponseResult, promise: &Rc<Promise>);
} }
struct WGPUResponse<T: AsyncWGPUListener + DomObject> { struct WGPUResponse<T: AsyncWGPUListener + DomObject> {
@ -53,13 +53,7 @@ impl<T: AsyncWGPUListener + DomObject> WGPUResponse<T> {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
fn response(self, response: WebGPUResponseResult) { fn response(self, response: WebGPUResponseResult) {
let promise = self.trusted.root(); let promise = self.trusted.root();
match response { self.receiver.root().handle_response(response, &promise);
Ok(response) => self.receiver.root().handle_response(response, &promise),
Err(error) => promise.reject_error(Error::Type(format!(
"Received error from WebGPU thread: {}",
error
))),
}
} }
} }
@ -134,13 +128,13 @@ impl GPUMethods for GPU {
} }
impl AsyncWGPUListener for GPU { impl AsyncWGPUListener for GPU {
fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>) { fn handle_response(&self, response: WebGPUResponseResult, promise: &Rc<Promise>) {
match response { match response {
WebGPUResponse::RequestAdapter { Ok(WebGPUResponse::RequestAdapter {
adapter_name, adapter_name,
adapter_id, adapter_id,
channel, channel,
} => { }) => {
let adapter = GPUAdapter::new( let adapter = GPUAdapter::new(
&self.global(), &self.global(),
channel, channel,
@ -150,7 +144,14 @@ impl AsyncWGPUListener for GPU {
); );
promise.resolve_native(&adapter); promise.resolve_native(&adapter);
}, },
_ => promise.reject_error(Error::Operation), Err(e) => {
warn!("Could not get GPUAdapter ({:?})", e);
promise.resolve_native(&None::<GPUAdapter>);
},
_ => {
warn!("GPU received wrong WebGPUResponse");
promise.reject_error(Error::Operation);
},
} }
} }
} }

View file

@ -20,7 +20,7 @@ use dom_struct::dom_struct;
use js::jsapi::{Heap, JSObject}; use js::jsapi::{Heap, JSObject};
use std::ptr::NonNull; use std::ptr::NonNull;
use std::rc::Rc; use std::rc::Rc;
use webgpu::{wgt, WebGPU, WebGPUAdapter, WebGPURequest, WebGPUResponse}; use webgpu::{wgt, WebGPU, WebGPUAdapter, WebGPURequest, WebGPUResponse, WebGPUResponseResult};
#[dom_struct] #[dom_struct]
pub struct GPUAdapter { pub struct GPUAdapter {
@ -97,14 +97,17 @@ impl GPUAdapterMethods for GPUAdapter {
if self if self
.channel .channel
.0 .0
.send(WebGPURequest::RequestDevice { .send((
sender, None,
adapter_id: self.adapter, WebGPURequest::RequestDevice {
descriptor: desc, sender,
device_id: id, adapter_id: self.adapter,
pipeline_id, descriptor: desc,
label: descriptor.parent.label.as_ref().map(|s| s.to_string()), device_id: id,
}) pipeline_id,
label: descriptor.parent.label.as_ref().map(|s| s.to_string()),
},
))
.is_err() .is_err()
{ {
promise.reject_error(Error::Operation); promise.reject_error(Error::Operation);
@ -114,14 +117,14 @@ impl GPUAdapterMethods for GPUAdapter {
} }
impl AsyncWGPUListener for GPUAdapter { impl AsyncWGPUListener for GPUAdapter {
fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>) { fn handle_response(&self, response: WebGPUResponseResult, promise: &Rc<Promise>) {
match response { match response {
WebGPUResponse::RequestDevice { Ok(WebGPUResponse::RequestDevice {
device_id, device_id,
queue_id, queue_id,
_descriptor, _descriptor,
label, label,
} => { }) => {
let device = GPUDevice::new( let device = GPUDevice::new(
&self.global(), &self.global(),
self.channel.clone(), self.channel.clone(),
@ -135,7 +138,14 @@ impl AsyncWGPUListener for GPUAdapter {
self.global().add_gpu_device(&device); self.global().add_gpu_device(&device);
promise.resolve_native(&device); promise.resolve_native(&device);
}, },
_ => promise.reject_error(Error::Operation), Err(e) => {
warn!("Could not get GPUDevice({:?})", e);
promise.reject_error(Error::Operation);
},
_ => {
warn!("GPUAdapter received wrong WebGPUResponse");
promise.reject_error(Error::Operation);
},
} }
} }
} }

View file

@ -8,10 +8,11 @@ use crate::dom::bindings::codegen::Bindings::GPUMapModeBinding::GPUMapModeConsta
use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::reflector::DomObject; use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::USVString; use crate::dom::bindings::str::USVString;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::gpu::{response_async, AsyncWGPUListener}; use crate::dom::gpu::{response_async, AsyncWGPUListener};
use crate::dom::gpudevice::GPUDevice;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::realms::InRealm; use crate::realms::InRealm;
use crate::script_runtime::JSContext; use crate::script_runtime::JSContext;
@ -25,8 +26,10 @@ use std::ffi::c_void;
use std::ops::Range; use std::ops::Range;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::rc::Rc; use std::rc::Rc;
use std::string::String;
use webgpu::{ use webgpu::{
wgpu::device::HostMap, WebGPU, WebGPUBuffer, WebGPUDevice, WebGPURequest, WebGPUResponse, identity::WebGPUOpResult, wgpu::device::HostMap, WebGPU, WebGPUBuffer, WebGPURequest,
WebGPUResponse, WebGPUResponseResult,
}; };
const RANGE_OFFSET_ALIGN_MASK: u64 = 8; const RANGE_OFFSET_ALIGN_MASK: u64 = 8;
@ -61,7 +64,7 @@ pub struct GPUBuffer {
label: DomRefCell<Option<USVString>>, label: DomRefCell<Option<USVString>>,
state: Cell<GPUBufferState>, state: Cell<GPUBufferState>,
buffer: WebGPUBuffer, buffer: WebGPUBuffer,
device: WebGPUDevice, device: Dom<GPUDevice>,
size: GPUSize64, size: GPUSize64,
#[ignore_malloc_size_of = "promises are hard"] #[ignore_malloc_size_of = "promises are hard"]
map_promise: DomRefCell<Option<Rc<Promise>>>, map_promise: DomRefCell<Option<Rc<Promise>>>,
@ -72,7 +75,7 @@ impl GPUBuffer {
fn new_inherited( fn new_inherited(
channel: WebGPU, channel: WebGPU,
buffer: WebGPUBuffer, buffer: WebGPUBuffer,
device: WebGPUDevice, device: &GPUDevice,
state: GPUBufferState, state: GPUBufferState,
size: GPUSize64, size: GPUSize64,
map_info: DomRefCell<Option<GPUBufferMapInfo>>, map_info: DomRefCell<Option<GPUBufferMapInfo>>,
@ -83,7 +86,7 @@ impl GPUBuffer {
channel, channel,
label: DomRefCell::new(label), label: DomRefCell::new(label),
state: Cell::new(state), state: Cell::new(state),
device, device: Dom::from_ref(device),
buffer, buffer,
map_promise: DomRefCell::new(None), map_promise: DomRefCell::new(None),
size, size,
@ -96,7 +99,7 @@ impl GPUBuffer {
global: &GlobalScope, global: &GlobalScope,
channel: WebGPU, channel: WebGPU,
buffer: WebGPUBuffer, buffer: WebGPUBuffer,
device: WebGPUDevice, device: &GPUDevice,
state: GPUBufferState, state: GPUBufferState,
size: GPUSize64, size: GPUSize64,
map_info: DomRefCell<Option<GPUBufferMapInfo>>, map_info: DomRefCell<Option<GPUBufferMapInfo>>,
@ -143,13 +146,19 @@ impl GPUBufferMethods for GPUBuffer {
let mut info = self.map_info.borrow_mut(); let mut info = self.map_info.borrow_mut();
let m_info = info.as_mut().unwrap(); let m_info = info.as_mut().unwrap();
let m_range = m_info.mapping_range.clone(); let m_range = m_info.mapping_range.clone();
if let Err(e) = self.channel.0.send(WebGPURequest::UnmapBuffer { if let Err(e) = self.channel.0.send((
buffer_id: self.id().0, self.device.use_current_scope(),
array_buffer: IpcSharedMemory::from_bytes(m_info.mapping.borrow().as_slice()), WebGPURequest::UnmapBuffer {
is_map_read: m_info.map_mode == Some(GPUMapModeConstants::READ), buffer_id: self.id().0,
offset: m_range.start, device_id: self.device.id().0,
size: m_range.end - m_range.start, array_buffer: IpcSharedMemory::from_bytes(
}) { m_info.mapping.borrow().as_slice(),
),
is_map_read: m_info.map_mode == Some(GPUMapModeConstants::READ),
offset: m_range.start,
size: m_range.end - m_range.start,
},
)) {
warn!("Failed to send Buffer unmap ({:?}) ({})", self.buffer.0, e); warn!("Failed to send Buffer unmap ({:?}) ({})", self.buffer.0, e);
} }
// Step 3.3 // Step 3.3
@ -180,7 +189,7 @@ impl GPUBufferMethods for GPUBuffer {
if let Err(e) = self if let Err(e) = self
.channel .channel
.0 .0
.send(WebGPURequest::DestroyBuffer(self.buffer.0)) .send((None, WebGPURequest::DestroyBuffer(self.buffer.0)))
{ {
warn!( warn!(
"Failed to send WebGPURequest::DestroyBuffer({:?}) ({})", "Failed to send WebGPURequest::DestroyBuffer({:?}) ({})",
@ -196,40 +205,53 @@ impl GPUBufferMethods for GPUBuffer {
&self, &self,
mode: u32, mode: u32,
offset: GPUSize64, offset: GPUSize64,
size: GPUSize64, size: Option<GPUSize64>,
comp: InRealm, comp: InRealm,
) -> Rc<Promise> { ) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(&self.global(), comp); let promise = Promise::new_in_current_realm(&self.global(), comp);
let map_range = if size == 0 { let range_size = if let Some(s) = size {
offset..self.size s
} else if offset >= self.size {
promise.reject_error(Error::Operation);
return promise;
} else { } else {
if offset + size > self.size { self.size - offset
warn!("Requested mapping size is greated than buffer size");
promise.reject_error(Error::Abort);
return promise;
}
offset..offset + size
}; };
let scope_id = self.device.use_current_scope();
if self.state.get() != GPUBufferState::Unmapped {
self.device.handle_server_msg(
scope_id,
WebGPUOpResult::ValidationError(String::from("Buffer is not Unmapped")),
);
promise.reject_error(Error::Abort);
return promise;
}
let host_map = match mode { let host_map = match mode {
GPUMapModeConstants::READ => HostMap::Read, GPUMapModeConstants::READ => HostMap::Read,
GPUMapModeConstants::WRITE => HostMap::Write, GPUMapModeConstants::WRITE => HostMap::Write,
_ => { _ => {
self.device.handle_server_msg(
scope_id,
WebGPUOpResult::ValidationError(String::from("Invalid MapModeFlags")),
);
promise.reject_error(Error::Abort); promise.reject_error(Error::Abort);
return promise; return promise;
}, },
}; };
if self.state.get() != GPUBufferState::Unmapped {
promise.reject_error(Error::Abort); let map_range = offset..offset + range_size;
return promise;
}
let sender = response_async(&promise, self); let sender = response_async(&promise, self);
if let Err(e) = self.channel.0.send(WebGPURequest::BufferMapAsync { if let Err(e) = self.channel.0.send((
sender, scope_id,
buffer_id: self.buffer.0, WebGPURequest::BufferMapAsync {
host_map, sender,
map_range: map_range.clone(), buffer_id: self.buffer.0,
}) { device_id: self.device.id().0,
host_map,
map_range: map_range.clone(),
},
)) {
warn!( warn!(
"Failed to send BufferMapAsync ({:?}) ({})", "Failed to send BufferMapAsync ({:?}) ({})",
self.buffer.0, e self.buffer.0, e
@ -256,9 +278,16 @@ impl GPUBufferMethods for GPUBuffer {
&self, &self,
cx: JSContext, cx: JSContext,
offset: GPUSize64, offset: GPUSize64,
size: GPUSize64, size: Option<GPUSize64>,
) -> Fallible<NonNull<JSObject>> { ) -> Fallible<NonNull<JSObject>> {
let m_end = if size == 0 { self.size } else { offset + size }; let range_size = if let Some(s) = size {
s
} else if offset >= self.size {
return Err(Error::Operation);
} else {
self.size - offset
};
let m_end = offset + range_size;
let mut info = self.map_info.borrow_mut(); let mut info = self.map_info.borrow_mut();
let m_info = info.as_mut().unwrap(); let m_info = info.as_mut().unwrap();
@ -267,7 +296,7 @@ impl GPUBufferMethods for GPUBuffer {
_ => false, _ => false,
}; };
valid &= offset % RANGE_OFFSET_ALIGN_MASK == 0 && valid &= offset % RANGE_OFFSET_ALIGN_MASK == 0 &&
(m_end - offset) % RANGE_SIZE_ALIGN_MASK == 0 && range_size % RANGE_SIZE_ALIGN_MASK == 0 &&
offset >= m_info.mapping_range.start && offset >= m_info.mapping_range.start &&
m_end <= m_info.mapping_range.end; m_end <= m_info.mapping_range.end;
valid &= m_info valid &= m_info
@ -285,7 +314,7 @@ impl GPUBufferMethods for GPUBuffer {
let array_buffer = unsafe { let array_buffer = unsafe {
NewExternalArrayBuffer( NewExternalArrayBuffer(
*cx, *cx,
(m_end - offset) as usize, range_size as usize,
m_info.mapping.borrow_mut()[offset as usize..m_end as usize].as_mut_ptr() as _, m_info.mapping.borrow_mut()[offset as usize..m_end as usize].as_mut_ptr() as _,
Some(free_func), Some(free_func),
Rc::into_raw(m_info.mapping.clone()) as _, Rc::into_raw(m_info.mapping.clone()) as _,
@ -311,9 +340,9 @@ impl GPUBufferMethods for GPUBuffer {
impl AsyncWGPUListener for GPUBuffer { impl AsyncWGPUListener for GPUBuffer {
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>) { fn handle_response(&self, response: WebGPUResponseResult, promise: &Rc<Promise>) {
match response { match response {
WebGPUResponse::BufferMapAsync(bytes) => { Ok(WebGPUResponse::BufferMapAsync(bytes)) => {
*self *self
.map_info .map_info
.borrow_mut() .borrow_mut()
@ -324,8 +353,12 @@ impl AsyncWGPUListener for GPUBuffer {
promise.resolve_native(&()); promise.resolve_native(&());
self.state.set(GPUBufferState::Mapped); self.state.set(GPUBufferState::Mapped);
}, },
Err(e) => {
warn!("Could not map buffer({:?})", e);
promise.reject_error(Error::Abort);
},
_ => { _ => {
warn!("Wrong WebGPUResponse received"); warn!("GPUBuffer received wrong WebGPUResponse");
promise.reject_error(Error::Operation); promise.reject_error(Error::Operation);
}, },
} }
@ -333,7 +366,7 @@ impl AsyncWGPUListener for GPUBuffer {
if let Err(e) = self if let Err(e) = self
.channel .channel
.0 .0
.send(WebGPURequest::BufferMapComplete(self.buffer.0)) .send((None, WebGPURequest::BufferMapComplete(self.buffer.0)))
{ {
warn!( warn!(
"Failed to send BufferMapComplete({:?}) ({})", "Failed to send BufferMapComplete({:?}) ({})",

View file

@ -45,7 +45,9 @@ pub struct GPUCanvasContext {
impl GPUCanvasContext { impl GPUCanvasContext {
fn new_inherited(canvas: &HTMLCanvasElement, size: Size2D<u32>, channel: WebGPU) -> Self { fn new_inherited(canvas: &HTMLCanvasElement, size: Size2D<u32>, channel: WebGPU) -> Self {
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let _ = channel.0.send(WebGPURequest::CreateContext(sender)); if let Err(e) = channel.0.send((None, WebGPURequest::CreateContext(sender))) {
warn!("Failed to send CreateContext ({:?})", e);
}
let external_id = receiver.recv().unwrap(); let external_id = receiver.recv().unwrap();
Self { Self {
reflector_: Reflector::new(), reflector_: Reflector::new(),
@ -88,11 +90,14 @@ impl GPUCanvasContext {
.wgpu_id_hub() .wgpu_id_hub()
.lock() .lock()
.create_command_encoder_id(texture_id.backend()); .create_command_encoder_id(texture_id.backend());
if let Err(e) = self.channel.0.send(WebGPURequest::SwapChainPresent { if let Err(e) = self.channel.0.send((
external_id: self.context_id.0, None,
texture_id, WebGPURequest::SwapChainPresent {
encoder_id, external_id: self.context_id.0,
}) { texture_id,
encoder_id,
},
)) {
warn!( warn!(
"Failed to send UpdateWebrenderData({:?}) ({})", "Failed to send UpdateWebrenderData({:?}) ({})",
self.context_id, e self.context_id, e
@ -168,14 +173,17 @@ impl GPUCanvasContextMethods for GPUCanvasContext {
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateSwapChain { .send((
device_id: descriptor.device.id().0, None,
buffer_ids, WebGPURequest::CreateSwapChain {
external_id: self.context_id.0, device_id: descriptor.device.id().0,
sender, buffer_ids,
image_desc, external_id: self.context_id.0,
image_data, sender,
}) image_desc,
image_data,
},
))
.expect("Failed to create WebGPU SwapChain"); .expect("Failed to create WebGPU SwapChain");
let usage = if descriptor.usage % 2 == 0 { let usage = if descriptor.usage % 2 == 0 {

View file

@ -29,7 +29,7 @@ use std::borrow::Cow;
use std::cell::Cell; use std::cell::Cell;
use std::collections::HashSet; use std::collections::HashSet;
use webgpu::wgpu::command as wgpu_com; use webgpu::wgpu::command as wgpu_com;
use webgpu::{self, wgt, WebGPU, WebGPURequest}; use webgpu::{self, identity::WebGPUOpResult, wgt, WebGPU, WebGPURequest};
// https://gpuweb.github.io/gpuweb/#enumdef-encoder-state // https://gpuweb.github.io/gpuweb/#enumdef-encoder-state
#[derive(MallocSizeOf, PartialEq)] #[derive(MallocSizeOf, PartialEq)]
@ -103,6 +103,10 @@ impl GPUCommandEncoder {
*self.state.borrow_mut() = GPUCommandEncoderState::Closed; *self.state.borrow_mut() = GPUCommandEncoderState::Closed;
} }
} }
pub fn device(&self) -> &GPUDevice {
&*self.device
}
} }
impl GPUCommandEncoderMethods for GPUCommandEncoder { impl GPUCommandEncoderMethods for GPUCommandEncoder {
@ -254,9 +258,15 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
size: GPUSize64, size: GPUSize64,
) { ) {
let valid = *self.state.borrow() == GPUCommandEncoderState::Open; let valid = *self.state.borrow() == GPUCommandEncoderState::Open;
let scope_id = self.device.use_current_scope();
if !valid { if !valid {
// TODO: Record an error in the current scope. self.device.handle_server_msg(
scope_id,
WebGPUOpResult::ValidationError(String::from(
"CommandEncoder is not in Open State",
)),
);
self.valid.set(false); self.valid.set(false);
return; return;
} }
@ -267,14 +277,18 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
.insert(DomRoot::from_ref(destination)); .insert(DomRoot::from_ref(destination));
self.channel self.channel
.0 .0
.send(WebGPURequest::CopyBufferToBuffer { .send((
command_encoder_id: self.encoder.0, scope_id,
source_id: source.id().0, WebGPURequest::CopyBufferToBuffer {
source_offset, command_encoder_id: self.encoder.0,
destination_id: destination.id().0, device_id: self.device.id().0,
destination_offset, source_id: source.id().0,
size, source_offset,
}) destination_id: destination.id().0,
destination_offset,
size,
},
))
.expect("Failed to send CopyBufferToBuffer"); .expect("Failed to send CopyBufferToBuffer");
} }
@ -286,9 +300,15 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
copy_size: GPUExtent3D, copy_size: GPUExtent3D,
) { ) {
let valid = *self.state.borrow() == GPUCommandEncoderState::Open; let valid = *self.state.borrow() == GPUCommandEncoderState::Open;
let scope_id = self.device.use_current_scope();
if !valid { if !valid {
// TODO: Record an error in the current scope. self.device.handle_server_msg(
scope_id,
WebGPUOpResult::ValidationError(String::from(
"CommandEncoder is not in Open State",
)),
);
self.valid.set(false); self.valid.set(false);
return; return;
} }
@ -299,12 +319,18 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
self.channel self.channel
.0 .0
.send(WebGPURequest::CopyBufferToTexture { .send((
command_encoder_id: self.encoder.0, scope_id,
source: convert_buffer_cv(source), WebGPURequest::CopyBufferToTexture {
destination: convert_texture_cv(destination), command_encoder_id: self.encoder.0,
copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict(&copy_size)), device_id: self.device.id().0,
}) source: convert_buffer_cv(source),
destination: convert_texture_cv(destination),
copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict(
&copy_size,
)),
},
))
.expect("Failed to send CopyBufferToTexture"); .expect("Failed to send CopyBufferToTexture");
} }
@ -316,9 +342,15 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
copy_size: GPUExtent3D, copy_size: GPUExtent3D,
) { ) {
let valid = *self.state.borrow() == GPUCommandEncoderState::Open; let valid = *self.state.borrow() == GPUCommandEncoderState::Open;
let scope_id = self.device.use_current_scope();
if !valid { if !valid {
// TODO: Record an error in the current scope. self.device.handle_server_msg(
scope_id,
WebGPUOpResult::ValidationError(String::from(
"CommandEncoder is not in Open State",
)),
);
self.valid.set(false); self.valid.set(false);
return; return;
} }
@ -329,12 +361,18 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
self.channel self.channel
.0 .0
.send(WebGPURequest::CopyTextureToBuffer { .send((
command_encoder_id: self.encoder.0, scope_id,
source: convert_texture_cv(source), WebGPURequest::CopyTextureToBuffer {
destination: convert_buffer_cv(destination), command_encoder_id: self.encoder.0,
copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict(&copy_size)), device_id: self.device.id().0,
}) source: convert_texture_cv(source),
destination: convert_buffer_cv(destination),
copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict(
&copy_size,
)),
},
))
.expect("Failed to send CopyTextureToBuffer"); .expect("Failed to send CopyTextureToBuffer");
} }
@ -346,21 +384,33 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
copy_size: GPUExtent3D, copy_size: GPUExtent3D,
) { ) {
let valid = *self.state.borrow() == GPUCommandEncoderState::Open; let valid = *self.state.borrow() == GPUCommandEncoderState::Open;
let scope_id = self.device.use_current_scope();
if !valid { if !valid {
// TODO: Record an error in the current scope. self.device.handle_server_msg(
scope_id,
WebGPUOpResult::ValidationError(String::from(
"CommandEncoder is not in Open State",
)),
);
self.valid.set(false); self.valid.set(false);
return; return;
} }
self.channel self.channel
.0 .0
.send(WebGPURequest::CopyTextureToTexture { .send((
command_encoder_id: self.encoder.0, scope_id,
source: convert_texture_cv(source), WebGPURequest::CopyTextureToTexture {
destination: convert_texture_cv(destination), command_encoder_id: self.encoder.0,
copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict(&copy_size)), device_id: self.device.id().0,
}) source: convert_texture_cv(source),
destination: convert_texture_cv(destination),
copy_size: convert_texture_size_to_wgt(&convert_texture_size_to_dict(
&copy_size,
)),
},
))
.expect("Failed to send CopyTextureToTexture"); .expect("Failed to send CopyTextureToTexture");
} }
@ -368,13 +418,15 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
fn Finish(&self, descriptor: &GPUCommandBufferDescriptor) -> DomRoot<GPUCommandBuffer> { fn Finish(&self, descriptor: &GPUCommandBufferDescriptor) -> DomRoot<GPUCommandBuffer> {
self.channel self.channel
.0 .0
.send(WebGPURequest::CommandEncoderFinish { .send((
command_encoder_id: self.encoder.0, self.device.use_current_scope(),
device_id: self.device.id().0, WebGPURequest::CommandEncoderFinish {
scope_id: self.device.use_current_scope(), command_encoder_id: self.encoder.0,
// TODO(zakorgy): We should use `_descriptor` here after it's not empty device_id: self.device.id().0,
// and the underlying wgpu-core struct is serializable // TODO(zakorgy): We should use `_descriptor` here after it's not empty
}) // and the underlying wgpu-core struct is serializable
},
))
.expect("Failed to send Finish"); .expect("Failed to send Finish");
*self.state.borrow_mut() = GPUCommandEncoderState::Closed; *self.state.borrow_mut() = GPUCommandEncoderState::Closed;

View file

@ -91,10 +91,14 @@ impl GPUComputePassEncoderMethods for GPUComputePassEncoder {
if let Some(compute_pass) = self.compute_pass.borrow_mut().take() { if let Some(compute_pass) = self.compute_pass.borrow_mut().take() {
self.channel self.channel
.0 .0
.send(WebGPURequest::RunComputePass { .send((
command_encoder_id: self.command_encoder.id().0, self.command_encoder.device().use_current_scope(),
compute_pass, WebGPURequest::RunComputePass {
}) command_encoder_id: self.command_encoder.id().0,
device_id: self.command_encoder.device().id().0,
compute_pass,
},
))
.expect("Failed to send RunComputePass"); .expect("Failed to send RunComputePass");
self.command_encoder.set_state( self.command_encoder.set_state(

View file

@ -71,9 +71,7 @@ use std::rc::Rc;
use webgpu::wgpu::{ use webgpu::wgpu::{
binding_model as wgpu_bind, command::RenderBundleEncoder, pipeline as wgpu_pipe, binding_model as wgpu_bind, command::RenderBundleEncoder, pipeline as wgpu_pipe,
}; };
use webgpu::{self, identity::WebGPUOpResult, wgt, WebGPU, WebGPURequest}; use webgpu::{self, identity::WebGPUOpResult, wgt, ErrorScopeId, WebGPU, WebGPURequest};
type ErrorScopeId = u64;
#[derive(JSTraceable, MallocSizeOf)] #[derive(JSTraceable, MallocSizeOf)]
struct ErrorScopeInfo { struct ErrorScopeInfo {
@ -131,7 +129,7 @@ impl GPUDevice {
scope_context: DomRefCell::new(ScopeContext { scope_context: DomRefCell::new(ScopeContext {
error_scopes: HashMap::new(), error_scopes: HashMap::new(),
scope_stack: Vec::new(), scope_stack: Vec::new(),
next_scope_id: 0, next_scope_id: ErrorScopeId::new(1).unwrap(),
}), }),
lost_promise: DomRefCell::new(None), lost_promise: DomRefCell::new(None),
} }
@ -148,12 +146,14 @@ impl GPUDevice {
label: Option<String>, label: Option<String>,
) -> DomRoot<Self> { ) -> DomRoot<Self> {
let queue = GPUQueue::new(global, channel.clone(), queue); let queue = GPUQueue::new(global, channel.clone(), queue);
reflect_dom_object( let device = reflect_dom_object(
Box::new(GPUDevice::new_inherited( Box::new(GPUDevice::new_inherited(
channel, adapter, extensions, limits, device, &queue, label, channel, adapter, extensions, limits, device, &queue, label,
)), )),
global, global,
) );
queue.set_device(&*device);
device
} }
} }
@ -311,12 +311,14 @@ impl GPUDeviceMethods for GPUDevice {
let scope_id = self.use_current_scope(); let scope_id = self.use_current_scope();
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateBuffer { .send((
device_id: self.device.0,
scope_id, scope_id,
buffer_id: id, WebGPURequest::CreateBuffer {
descriptor: wgpu_descriptor, device_id: self.device.0,
}) buffer_id: id,
descriptor: wgpu_descriptor,
},
))
.expect("Failed to create WebGPU buffer"); .expect("Failed to create WebGPU buffer");
let buffer = webgpu::WebGPUBuffer(id); let buffer = webgpu::WebGPUBuffer(id);
@ -341,7 +343,7 @@ impl GPUDeviceMethods for GPUDevice {
&self.global(), &self.global(),
self.channel.clone(), self.channel.clone(),
buffer, buffer,
self.device, &self,
state, state,
descriptor.size, descriptor.size,
map_info, map_info,
@ -449,12 +451,14 @@ impl GPUDeviceMethods for GPUDevice {
.create_bind_group_layout_id(self.device.0.backend()); .create_bind_group_layout_id(self.device.0.backend());
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateBindGroupLayout { .send((
device_id: self.device.0,
bind_group_layout_id,
scope_id, scope_id,
descriptor: desc, WebGPURequest::CreateBindGroupLayout {
}) device_id: self.device.0,
bind_group_layout_id,
descriptor: desc,
},
))
.expect("Failed to create WebGPU BindGroupLayout"); .expect("Failed to create WebGPU BindGroupLayout");
let bgl = webgpu::WebGPUBindGroupLayout(bind_group_layout_id); let bgl = webgpu::WebGPUBindGroupLayout(bind_group_layout_id);
@ -491,12 +495,14 @@ impl GPUDeviceMethods for GPUDevice {
.create_pipeline_layout_id(self.device.0.backend()); .create_pipeline_layout_id(self.device.0.backend());
self.channel self.channel
.0 .0
.send(WebGPURequest::CreatePipelineLayout { .send((
device_id: self.device.0,
pipeline_layout_id,
descriptor: desc,
scope_id, scope_id,
}) WebGPURequest::CreatePipelineLayout {
device_id: self.device.0,
pipeline_layout_id,
descriptor: desc,
},
))
.expect("Failed to create WebGPU PipelineLayout"); .expect("Failed to create WebGPU PipelineLayout");
let pipeline_layout = webgpu::WebGPUPipelineLayout(pipeline_layout_id); let pipeline_layout = webgpu::WebGPUPipelineLayout(pipeline_layout_id);
@ -551,12 +557,14 @@ impl GPUDeviceMethods for GPUDevice {
.create_bind_group_id(self.device.0.backend()); .create_bind_group_id(self.device.0.backend());
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateBindGroup { .send((
device_id: self.device.0,
bind_group_id,
descriptor: desc,
scope_id, scope_id,
}) WebGPURequest::CreateBindGroup {
device_id: self.device.0,
bind_group_id,
descriptor: desc,
},
))
.expect("Failed to create WebGPU BindGroup"); .expect("Failed to create WebGPU BindGroup");
let bind_group = webgpu::WebGPUBindGroup(bind_group_id); let bind_group = webgpu::WebGPUBindGroup(bind_group_id);
@ -590,12 +598,14 @@ impl GPUDeviceMethods for GPUDevice {
let scope_id = self.use_current_scope(); let scope_id = self.use_current_scope();
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateShaderModule { .send((
device_id: self.device.0,
scope_id, scope_id,
program_id, WebGPURequest::CreateShaderModule {
program, device_id: self.device.0,
}) program_id,
program,
},
))
.expect("Failed to create WebGPU ShaderModule"); .expect("Failed to create WebGPU ShaderModule");
let shader_module = webgpu::WebGPUShaderModule(program_id); let shader_module = webgpu::WebGPUShaderModule(program_id);
@ -629,12 +639,14 @@ impl GPUDeviceMethods for GPUDevice {
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateComputePipeline { .send((
device_id: self.device.0,
scope_id, scope_id,
compute_pipeline_id, WebGPURequest::CreateComputePipeline {
descriptor: desc, device_id: self.device.0,
}) compute_pipeline_id,
descriptor: desc,
},
))
.expect("Failed to create WebGPU ComputePipeline"); .expect("Failed to create WebGPU ComputePipeline");
let compute_pipeline = webgpu::WebGPUComputePipeline(compute_pipeline_id); let compute_pipeline = webgpu::WebGPUComputePipeline(compute_pipeline_id);
@ -658,12 +670,14 @@ impl GPUDeviceMethods for GPUDevice {
let scope_id = self.use_current_scope(); let scope_id = self.use_current_scope();
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateCommandEncoder { .send((
device_id: self.device.0,
scope_id, scope_id,
command_encoder_id, WebGPURequest::CreateCommandEncoder {
label: descriptor.parent.label.as_ref().map(|s| s.to_string()), device_id: self.device.0,
}) command_encoder_id,
label: descriptor.parent.label.as_ref().map(|s| s.to_string()),
},
))
.expect("Failed to create WebGPU command encoder"); .expect("Failed to create WebGPU command encoder");
let encoder = webgpu::WebGPUCommandEncoder(command_encoder_id); let encoder = webgpu::WebGPUCommandEncoder(command_encoder_id);
@ -708,12 +722,14 @@ impl GPUDeviceMethods for GPUDevice {
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateTexture { .send((
device_id: self.device.0,
texture_id,
descriptor: desc,
scope_id, scope_id,
}) WebGPURequest::CreateTexture {
device_id: self.device.0,
texture_id,
descriptor: desc,
},
))
.expect("Failed to create WebGPU Texture"); .expect("Failed to create WebGPU Texture");
let texture = webgpu::WebGPUTexture(texture_id); let texture = webgpu::WebGPUTexture(texture_id);
@ -759,12 +775,14 @@ impl GPUDeviceMethods for GPUDevice {
let scope_id = self.use_current_scope(); let scope_id = self.use_current_scope();
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateSampler { .send((
device_id: self.device.0,
scope_id, scope_id,
sampler_id, WebGPURequest::CreateSampler {
descriptor: desc, device_id: self.device.0,
}) sampler_id,
descriptor: desc,
},
))
.expect("Failed to create WebGPU sampler"); .expect("Failed to create WebGPU sampler");
let sampler = webgpu::WebGPUSampler(sampler_id); let sampler = webgpu::WebGPUSampler(sampler_id);
@ -901,12 +919,14 @@ impl GPUDeviceMethods for GPUDevice {
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateRenderPipeline { .send((
device_id: self.device.0,
render_pipeline_id,
scope_id, scope_id,
descriptor: desc, WebGPURequest::CreateRenderPipeline {
}) device_id: self.device.0,
render_pipeline_id,
descriptor: desc,
},
))
.expect("Failed to create WebGPU render pipeline"); .expect("Failed to create WebGPU render pipeline");
let render_pipeline = webgpu::WebGPURenderPipeline(render_pipeline_id); let render_pipeline = webgpu::WebGPURenderPipeline(render_pipeline_id);
@ -959,7 +979,7 @@ impl GPUDeviceMethods for GPUDevice {
fn PushErrorScope(&self, filter: GPUErrorFilter) { fn PushErrorScope(&self, filter: GPUErrorFilter) {
let mut context = self.scope_context.borrow_mut(); let mut context = self.scope_context.borrow_mut();
let scope_id = context.next_scope_id; let scope_id = context.next_scope_id;
context.next_scope_id += 1; context.next_scope_id = ErrorScopeId::new(scope_id.get() + 1).unwrap();
let err_scope = ErrorScopeInfo { let err_scope = ErrorScopeInfo {
op_count: 0, op_count: 0,
error: None, error: None,

View file

@ -11,24 +11,25 @@ use crate::dom::bindings::codegen::Bindings::GPUQueueBinding::GPUQueueMethods;
use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::GPUExtent3D; use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::GPUExtent3D;
use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::USVString; use crate::dom::bindings::str::USVString;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState}; use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState};
use crate::dom::gpucommandbuffer::GPUCommandBuffer; use crate::dom::gpucommandbuffer::GPUCommandBuffer;
use crate::dom::gpucommandencoder::{convert_texture_cv, convert_texture_data_layout}; use crate::dom::gpucommandencoder::{convert_texture_cv, convert_texture_data_layout};
use crate::dom::gpudevice::{convert_texture_size_to_dict, convert_texture_size_to_wgt}; use crate::dom::gpudevice::{convert_texture_size_to_dict, convert_texture_size_to_wgt, GPUDevice};
use dom_struct::dom_struct; use dom_struct::dom_struct;
use ipc_channel::ipc::IpcSharedMemory; use ipc_channel::ipc::IpcSharedMemory;
use js::rust::CustomAutoRooterGuard; use js::rust::CustomAutoRooterGuard;
use js::typedarray::ArrayBuffer; use js::typedarray::ArrayBuffer;
use webgpu::{wgt, WebGPU, WebGPUQueue, WebGPURequest}; use webgpu::{identity::WebGPUOpResult, wgt, WebGPU, WebGPUQueue, WebGPURequest};
#[dom_struct] #[dom_struct]
pub struct GPUQueue { pub struct GPUQueue {
reflector_: Reflector, reflector_: Reflector,
#[ignore_malloc_size_of = "defined in webgpu"] #[ignore_malloc_size_of = "defined in webgpu"]
channel: WebGPU, channel: WebGPU,
device: DomRefCell<Option<Dom<GPUDevice>>>,
label: DomRefCell<Option<USVString>>, label: DomRefCell<Option<USVString>>,
queue: WebGPUQueue, queue: WebGPUQueue,
} }
@ -38,6 +39,7 @@ impl GPUQueue {
GPUQueue { GPUQueue {
channel, channel,
reflector_: Reflector::new(), reflector_: Reflector::new(),
device: DomRefCell::new(None),
label: DomRefCell::new(None), label: DomRefCell::new(None),
queue, queue,
} }
@ -48,6 +50,12 @@ impl GPUQueue {
} }
} }
impl GPUQueue {
pub fn set_device(&self, device: &GPUDevice) {
*self.device.borrow_mut() = Some(Dom::from_ref(device));
}
}
impl GPUQueueMethods for GPUQueue { impl GPUQueueMethods for GPUQueue {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label /// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<USVString> { fn GetLabel(&self) -> Option<USVString> {
@ -67,17 +75,26 @@ impl GPUQueueMethods for GPUQueue {
_ => false, _ => false,
}) })
}); });
let scope_id = self.device.borrow().as_ref().unwrap().use_current_scope();
if !valid { if !valid {
// TODO: Generate error to the ErrorScope self.device.borrow().as_ref().unwrap().handle_server_msg(
scope_id,
WebGPUOpResult::ValidationError(String::from(
"Referenced GPUBuffer(s) are not Unmapped",
)),
);
return; return;
} }
let command_buffers = command_buffers.iter().map(|cb| cb.id().0).collect(); let command_buffers = command_buffers.iter().map(|cb| cb.id().0).collect();
self.channel self.channel
.0 .0
.send(WebGPURequest::Submit { .send((
queue_id: self.queue.0, scope_id,
command_buffers, WebGPURequest::Submit {
}) queue_id: self.queue.0,
command_buffers,
},
))
.unwrap(); .unwrap();
} }
@ -109,12 +126,15 @@ impl GPUQueueMethods for GPUQueue {
let final_data = IpcSharedMemory::from_bytes( let final_data = IpcSharedMemory::from_bytes(
&bytes[data_offset as usize..(data_offset + content_size) as usize], &bytes[data_offset as usize..(data_offset + content_size) as usize],
); );
if let Err(e) = self.channel.0.send(WebGPURequest::WriteBuffer { if let Err(e) = self.channel.0.send((
queue_id: self.queue.0, self.device.borrow().as_ref().unwrap().use_current_scope(),
buffer_id: buffer.id().0, WebGPURequest::WriteBuffer {
buffer_offset, queue_id: self.queue.0,
data: final_data, buffer_id: buffer.id().0,
}) { buffer_offset,
data: final_data,
},
)) {
warn!("Failed to send WriteBuffer({:?}) ({})", buffer.id(), e); warn!("Failed to send WriteBuffer({:?}) ({})", buffer.id(), e);
return Err(Error::Operation); return Err(Error::Operation);
} }
@ -142,13 +162,16 @@ impl GPUQueueMethods for GPUQueue {
let write_size = convert_texture_size_to_wgt(&convert_texture_size_to_dict(&size)); let write_size = convert_texture_size_to_wgt(&convert_texture_size_to_dict(&size));
let final_data = IpcSharedMemory::from_bytes(&bytes); let final_data = IpcSharedMemory::from_bytes(&bytes);
if let Err(e) = self.channel.0.send(WebGPURequest::WriteTexture { if let Err(e) = self.channel.0.send((
queue_id: self.queue.0, self.device.borrow().as_ref().unwrap().use_current_scope(),
texture_cv, WebGPURequest::WriteTexture {
data_layout: texture_layout, queue_id: self.queue.0,
size: write_size, texture_cv,
data: final_data, data_layout: texture_layout,
}) { size: write_size,
data: final_data,
},
)) {
warn!( warn!(
"Failed to send WriteTexture({:?}) ({})", "Failed to send WriteTexture({:?}) ({})",
destination.texture.id().0, destination.texture.id().0,

View file

@ -195,13 +195,15 @@ impl GPURenderBundleEncoderMethods for GPURenderBundleEncoder {
self.channel self.channel
.0 .0
.send(WebGPURequest::RenderBundleEncoderFinish { .send((
render_bundle_encoder: encoder, self.device.use_current_scope(),
descriptor: desc, WebGPURequest::RenderBundleEncoderFinish {
render_bundle_id, render_bundle_encoder: encoder,
device_id: self.device.id().0, descriptor: desc,
scope_id: self.device.use_current_scope(), render_bundle_id,
}) device_id: self.device.id().0,
},
))
.expect("Failed to send RenderBundleEncoderFinish"); .expect("Failed to send RenderBundleEncoderFinish");
let render_bundle = WebGPURenderBundle(render_bundle_id); let render_bundle = WebGPURenderBundle(render_bundle_id);

View file

@ -163,10 +163,14 @@ impl GPURenderPassEncoderMethods for GPURenderPassEncoder {
if let Some(render_pass) = self.render_pass.borrow_mut().take() { if let Some(render_pass) = self.render_pass.borrow_mut().take() {
self.channel self.channel
.0 .0
.send(WebGPURequest::RunRenderPass { .send((
command_encoder_id: self.command_encoder.id().0, self.command_encoder.device().use_current_scope(),
render_pass, WebGPURequest::RunRenderPass {
}) command_encoder_id: self.command_encoder.id().0,
device_id: self.command_encoder.device().id().0,
render_pass,
},
))
.expect("Failed to send RunRenderPass"); .expect("Failed to send RunRenderPass");
self.command_encoder.set_state( self.command_encoder.set_state(

View file

@ -57,10 +57,13 @@ impl GPUSwapChain {
impl GPUSwapChain { impl GPUSwapChain {
pub fn destroy(&self, external_id: u64, image_key: webrender_api::ImageKey) { pub fn destroy(&self, external_id: u64, image_key: webrender_api::ImageKey) {
if let Err(e) = self.channel.0.send(WebGPURequest::DestroySwapChain { if let Err(e) = self.channel.0.send((
external_id, None,
image_key, WebGPURequest::DestroySwapChain {
}) { external_id,
image_key,
},
)) {
warn!( warn!(
"Failed to send DestroySwapChain-ImageKey({:?}) ({})", "Failed to send DestroySwapChain-ImageKey({:?}) ({})",
image_key, e image_key, e

View file

@ -167,13 +167,15 @@ impl GPUTextureMethods for GPUTexture {
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateTextureView { .send((
texture_id: self.texture.0,
texture_view_id,
device_id: self.device.id().0,
descriptor: desc,
scope_id, scope_id,
}) WebGPURequest::CreateTextureView {
texture_id: self.texture.0,
texture_view_id,
device_id: self.device.id().0,
descriptor: desc,
},
))
.expect("Failed to create WebGPU texture view"); .expect("Failed to create WebGPU texture view");
let texture_view = WebGPUTextureView(texture_view_id); let texture_view = WebGPUTextureView(texture_view_id);
@ -191,7 +193,7 @@ impl GPUTextureMethods for GPUTexture {
if let Err(e) = self if let Err(e) = self
.channel .channel
.0 .0
.send(WebGPURequest::DestroyTexture(self.texture.0)) .send((None, WebGPURequest::DestroyTexture(self.texture.0)))
{ {
warn!( warn!(
"Failed to send WebGPURequest::DestroyTexture({:?}) ({})", "Failed to send WebGPURequest::DestroyTexture({:?}) ({})",

View file

@ -5,8 +5,7 @@
// https://gpuweb.github.io/gpuweb/#gpu-interface // https://gpuweb.github.io/gpuweb/#gpu-interface
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"] [Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPU { interface GPU {
// May reject with DOMException // TODO: DOMException("OperationError")? Promise<GPUAdapter?> requestAdapter(optional GPURequestAdapterOptions options = {});
Promise<GPUAdapter> requestAdapter(optional GPURequestAdapterOptions options = {});
}; };
// https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions // https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions

View file

@ -9,8 +9,7 @@ interface GPUAdapter {
readonly attribute object extensions; readonly attribute object extensions;
//readonly attribute GPULimits limits; Dont expose higher limits for now. //readonly attribute GPULimits limits; Dont expose higher limits for now.
// May reject with DOMException // TODO: DOMException("OperationError")? Promise<GPUDevice?> requestDevice(optional GPUDeviceDescriptor descriptor = {});
Promise<GPUDevice> requestDevice(optional GPUDeviceDescriptor descriptor = {});
}; };
dictionary GPUDeviceDescriptor : GPUObjectDescriptorBase { dictionary GPUDeviceDescriptor : GPUObjectDescriptorBase {

View file

@ -5,8 +5,8 @@
// https://gpuweb.github.io/gpuweb/#gpubuffer // https://gpuweb.github.io/gpuweb/#gpubuffer
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"] [Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
interface GPUBuffer { interface GPUBuffer {
Promise<void> mapAsync(GPUMapModeFlags mode, optional GPUSize64 offset = 0, optional GPUSize64 size = 0); Promise<void> mapAsync(GPUMapModeFlags mode, optional GPUSize64 offset = 0, optional GPUSize64 size);
[Throws] ArrayBuffer getMappedRange(optional GPUSize64 offset = 0, optional GPUSize64 size = 0); [Throws] ArrayBuffer getMappedRange(optional GPUSize64 offset = 0, optional GPUSize64 size);
void unmap(); void unmap();
void destroy(); void destroy();

View file

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::{WebGPUDevice, WebGPURequest}; use crate::{ErrorScopeId, WebGPUDevice, WebGPURequest};
use ipc_channel::ipc::IpcSender; use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -43,7 +43,7 @@ pub enum WebGPUMsg {
FreeRenderBundle(RenderBundleId), FreeRenderBundle(RenderBundleId),
WebGPUOpResult { WebGPUOpResult {
device: WebGPUDevice, device: WebGPUDevice,
scope_id: Option<u64>, scope_id: Option<ErrorScopeId>,
pipeline_id: PipelineId, pipeline_id: PipelineId,
result: WebGPUOpResult, result: WebGPUOpResult,
}, },
@ -57,12 +57,12 @@ pub enum WebGPUMsg {
#[derive(Debug)] #[derive(Debug)]
pub struct IdentityRecycler { pub struct IdentityRecycler {
sender: IpcSender<WebGPUMsg>, sender: IpcSender<WebGPUMsg>,
self_sender: IpcSender<WebGPURequest>, self_sender: IpcSender<(Option<ErrorScopeId>, WebGPURequest)>,
} }
pub struct IdentityRecyclerFactory { pub struct IdentityRecyclerFactory {
pub sender: IpcSender<WebGPUMsg>, pub sender: IpcSender<WebGPUMsg>,
pub self_sender: IpcSender<WebGPURequest>, pub self_sender: IpcSender<(Option<ErrorScopeId>, WebGPURequest)>,
} }
macro_rules! impl_identity_handler { macro_rules! impl_identity_handler {
@ -130,12 +130,14 @@ impl IdentityHandler<DeviceId> for IdentityRecycler {
} }
fn free(&self, id: DeviceId) { fn free(&self, id: DeviceId) {
log::debug!("free device {:?}", id); log::debug!("free device {:?}", id);
let msg = WebGPUMsg::FreeDevice(id); if self.sender.send(WebGPUMsg::FreeDevice(id)).is_err() {
if self.sender.send(msg).is_err() {
log::error!("Failed to send FreeDevice({:?}) to script", id); log::error!("Failed to send FreeDevice({:?}) to script", id);
} }
let msg_to_self = WebGPURequest::FreeDevice(id); if self
if self.self_sender.send(msg_to_self).is_err() { .self_sender
.send((None, WebGPURequest::FreeDevice(id)))
.is_err()
{
log::error!("Failed to send FreeDevice({:?}) to server", id); log::error!("Failed to send FreeDevice({:?}) to server", id);
} }
} }

View file

@ -22,6 +22,7 @@ use smallvec::SmallVec;
use std::borrow::Cow; use std::borrow::Cow;
use std::collections::HashMap; use std::collections::HashMap;
use std::ffi::CString; use std::ffi::CString;
use std::num::NonZeroU64;
use std::ptr; use std::ptr;
use std::rc::Rc; use std::rc::Rc;
use std::slice; use std::slice;
@ -41,6 +42,7 @@ use wgpu::{
resource::{BufferMapAsyncStatus, BufferMapOperation}, resource::{BufferMapAsyncStatus, BufferMapOperation},
}; };
pub type ErrorScopeId = NonZeroU64;
const DEVICE_POLL_INTERVAL: u64 = 100; const DEVICE_POLL_INTERVAL: u64 = 100;
pub const PRESENTATION_BUFFER_COUNT: usize = 10; pub const PRESENTATION_BUFFER_COUNT: usize = 10;
@ -67,6 +69,7 @@ pub enum WebGPURequest {
BufferMapAsync { BufferMapAsync {
sender: IpcSender<WebGPUResponseResult>, sender: IpcSender<WebGPUResponseResult>,
buffer_id: id::BufferId, buffer_id: id::BufferId,
device_id: id::DeviceId,
host_map: HostMap, host_map: HostMap,
map_range: std::ops::Range<u64>, map_range: std::ops::Range<u64>,
}, },
@ -74,12 +77,12 @@ pub enum WebGPURequest {
CommandEncoderFinish { CommandEncoderFinish {
command_encoder_id: id::CommandEncoderId, command_encoder_id: id::CommandEncoderId,
device_id: id::DeviceId, device_id: id::DeviceId,
scope_id: Option<u64>,
// TODO(zakorgy): Serialize CommandBufferDescriptor in wgpu-core // TODO(zakorgy): Serialize CommandBufferDescriptor in wgpu-core
// wgpu::command::CommandBufferDescriptor, // wgpu::command::CommandBufferDescriptor,
}, },
CopyBufferToBuffer { CopyBufferToBuffer {
command_encoder_id: id::CommandEncoderId, command_encoder_id: id::CommandEncoderId,
device_id: id::DeviceId,
source_id: id::BufferId, source_id: id::BufferId,
source_offset: wgt::BufferAddress, source_offset: wgt::BufferAddress,
destination_id: id::BufferId, destination_id: id::BufferId,
@ -88,44 +91,42 @@ pub enum WebGPURequest {
}, },
CopyBufferToTexture { CopyBufferToTexture {
command_encoder_id: id::CommandEncoderId, command_encoder_id: id::CommandEncoderId,
device_id: id::DeviceId,
source: BufferCopyView, source: BufferCopyView,
destination: TextureCopyView, destination: TextureCopyView,
copy_size: wgt::Extent3d, copy_size: wgt::Extent3d,
}, },
CopyTextureToBuffer { CopyTextureToBuffer {
command_encoder_id: id::CommandEncoderId, command_encoder_id: id::CommandEncoderId,
device_id: id::DeviceId,
source: TextureCopyView, source: TextureCopyView,
destination: BufferCopyView, destination: BufferCopyView,
copy_size: wgt::Extent3d, copy_size: wgt::Extent3d,
}, },
CopyTextureToTexture { CopyTextureToTexture {
command_encoder_id: id::CommandEncoderId, command_encoder_id: id::CommandEncoderId,
device_id: id::DeviceId,
source: TextureCopyView, source: TextureCopyView,
destination: TextureCopyView, destination: TextureCopyView,
copy_size: wgt::Extent3d, copy_size: wgt::Extent3d,
}, },
CreateBindGroup { CreateBindGroup {
device_id: id::DeviceId, device_id: id::DeviceId,
// TODO: Consider using NonZeroU64 to reduce enum size
scope_id: Option<u64>,
bind_group_id: id::BindGroupId, bind_group_id: id::BindGroupId,
descriptor: BindGroupDescriptor<'static>, descriptor: BindGroupDescriptor<'static>,
}, },
CreateBindGroupLayout { CreateBindGroupLayout {
device_id: id::DeviceId, device_id: id::DeviceId,
scope_id: Option<u64>,
bind_group_layout_id: id::BindGroupLayoutId, bind_group_layout_id: id::BindGroupLayoutId,
descriptor: wgt::BindGroupLayoutDescriptor<'static>, descriptor: wgt::BindGroupLayoutDescriptor<'static>,
}, },
CreateBuffer { CreateBuffer {
device_id: id::DeviceId, device_id: id::DeviceId,
scope_id: Option<u64>,
buffer_id: id::BufferId, buffer_id: id::BufferId,
descriptor: wgt::BufferDescriptor<Option<String>>, descriptor: wgt::BufferDescriptor<Option<String>>,
}, },
CreateCommandEncoder { CreateCommandEncoder {
device_id: id::DeviceId, device_id: id::DeviceId,
scope_id: Option<u64>,
// TODO(zakorgy): Serialize CommandEncoderDescriptor in wgpu-core // TODO(zakorgy): Serialize CommandEncoderDescriptor in wgpu-core
// wgpu::command::CommandEncoderDescriptor, // wgpu::command::CommandEncoderDescriptor,
command_encoder_id: id::CommandEncoderId, command_encoder_id: id::CommandEncoderId,
@ -133,32 +134,27 @@ pub enum WebGPURequest {
}, },
CreateComputePipeline { CreateComputePipeline {
device_id: id::DeviceId, device_id: id::DeviceId,
scope_id: Option<u64>,
compute_pipeline_id: id::ComputePipelineId, compute_pipeline_id: id::ComputePipelineId,
descriptor: ComputePipelineDescriptor<'static>, descriptor: ComputePipelineDescriptor<'static>,
}, },
CreateContext(IpcSender<webrender_api::ExternalImageId>), CreateContext(IpcSender<webrender_api::ExternalImageId>),
CreatePipelineLayout { CreatePipelineLayout {
device_id: id::DeviceId, device_id: id::DeviceId,
scope_id: Option<u64>,
pipeline_layout_id: id::PipelineLayoutId, pipeline_layout_id: id::PipelineLayoutId,
descriptor: wgt::PipelineLayoutDescriptor<'static, id::BindGroupLayoutId>, descriptor: wgt::PipelineLayoutDescriptor<'static, id::BindGroupLayoutId>,
}, },
CreateRenderPipeline { CreateRenderPipeline {
device_id: id::DeviceId, device_id: id::DeviceId,
scope_id: Option<u64>,
render_pipeline_id: id::RenderPipelineId, render_pipeline_id: id::RenderPipelineId,
descriptor: RenderPipelineDescriptor<'static>, descriptor: RenderPipelineDescriptor<'static>,
}, },
CreateSampler { CreateSampler {
device_id: id::DeviceId, device_id: id::DeviceId,
scope_id: Option<u64>,
sampler_id: id::SamplerId, sampler_id: id::SamplerId,
descriptor: wgt::SamplerDescriptor<Option<String>>, descriptor: wgt::SamplerDescriptor<Option<String>>,
}, },
CreateShaderModule { CreateShaderModule {
device_id: id::DeviceId, device_id: id::DeviceId,
scope_id: Option<u64>,
program_id: id::ShaderModuleId, program_id: id::ShaderModuleId,
program: Vec<u32>, program: Vec<u32>,
}, },
@ -172,7 +168,6 @@ pub enum WebGPURequest {
}, },
CreateTexture { CreateTexture {
device_id: id::DeviceId, device_id: id::DeviceId,
scope_id: Option<u64>,
texture_id: id::TextureId, texture_id: id::TextureId,
descriptor: wgt::TextureDescriptor<Option<String>>, descriptor: wgt::TextureDescriptor<Option<String>>,
}, },
@ -180,7 +175,6 @@ pub enum WebGPURequest {
texture_id: id::TextureId, texture_id: id::TextureId,
texture_view_id: id::TextureViewId, texture_view_id: id::TextureViewId,
device_id: id::DeviceId, device_id: id::DeviceId,
scope_id: Option<u64>,
descriptor: wgt::TextureViewDescriptor<Option<String>>, descriptor: wgt::TextureViewDescriptor<Option<String>>,
}, },
DestroyBuffer(id::BufferId), DestroyBuffer(id::BufferId),
@ -196,7 +190,6 @@ pub enum WebGPURequest {
descriptor: wgt::RenderBundleDescriptor<Option<String>>, descriptor: wgt::RenderBundleDescriptor<Option<String>>,
render_bundle_id: id::RenderBundleId, render_bundle_id: id::RenderBundleId,
device_id: id::DeviceId, device_id: id::DeviceId,
scope_id: Option<u64>,
}, },
RequestAdapter { RequestAdapter {
sender: IpcSender<WebGPUResponseResult>, sender: IpcSender<WebGPUResponseResult>,
@ -213,10 +206,12 @@ pub enum WebGPURequest {
}, },
RunComputePass { RunComputePass {
command_encoder_id: id::CommandEncoderId, command_encoder_id: id::CommandEncoderId,
device_id: id::DeviceId,
compute_pass: ComputePass, compute_pass: ComputePass,
}, },
RunRenderPass { RunRenderPass {
command_encoder_id: id::CommandEncoderId, command_encoder_id: id::CommandEncoderId,
device_id: id::DeviceId,
render_pass: RenderPass, render_pass: RenderPass,
}, },
Submit { Submit {
@ -230,6 +225,7 @@ pub enum WebGPURequest {
}, },
UnmapBuffer { UnmapBuffer {
buffer_id: id::BufferId, buffer_id: id::BufferId,
device_id: id::DeviceId,
array_buffer: IpcSharedMemory, array_buffer: IpcSharedMemory,
is_map_read: bool, is_map_read: bool,
offset: u64, offset: u64,
@ -264,7 +260,7 @@ struct BufferMapInfo<'a, T> {
} }
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
pub struct WebGPU(pub IpcSender<WebGPURequest>); pub struct WebGPU(pub IpcSender<(Option<ErrorScopeId>, WebGPURequest)>);
impl WebGPU { impl WebGPU {
pub fn new( pub fn new(
@ -322,14 +318,14 @@ impl WebGPU {
pub fn exit(&self, sender: IpcSender<()>) -> Result<(), &'static str> { pub fn exit(&self, sender: IpcSender<()>) -> Result<(), &'static str> {
self.0 self.0
.send(WebGPURequest::Exit(sender)) .send((None, WebGPURequest::Exit(sender)))
.map_err(|_| "Failed to send Exit message") .map_err(|_| "Failed to send Exit message")
} }
} }
struct WGPU<'a> { struct WGPU<'a> {
receiver: IpcReceiver<WebGPURequest>, receiver: IpcReceiver<(Option<ErrorScopeId>, WebGPURequest)>,
sender: IpcSender<WebGPURequest>, sender: IpcSender<(Option<ErrorScopeId>, WebGPURequest)>,
script_sender: IpcSender<WebGPUMsg>, script_sender: IpcSender<WebGPUMsg>,
global: wgpu::hub::Global<IdentityRecyclerFactory>, global: wgpu::hub::Global<IdentityRecyclerFactory>,
adapters: Vec<WebGPUAdapter>, adapters: Vec<WebGPUAdapter>,
@ -339,7 +335,8 @@ struct WGPU<'a> {
// Buffers with pending mapping // Buffers with pending mapping
buffer_maps: HashMap<id::BufferId, Rc<BufferMapInfo<'a, WebGPUResponseResult>>>, buffer_maps: HashMap<id::BufferId, Rc<BufferMapInfo<'a, WebGPUResponseResult>>>,
// Presentation Buffers with pending mapping // Presentation Buffers with pending mapping
present_buffer_maps: HashMap<id::BufferId, Rc<BufferMapInfo<'a, WebGPURequest>>>, present_buffer_maps:
HashMap<id::BufferId, Rc<BufferMapInfo<'a, (Option<ErrorScopeId>, WebGPURequest)>>>,
webrender_api: webrender_api::RenderApi, webrender_api: webrender_api::RenderApi,
webrender_document: webrender_api::DocumentId, webrender_document: webrender_api::DocumentId,
external_images: Arc<Mutex<WebrenderExternalImageRegistry>>, external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
@ -349,8 +346,8 @@ struct WGPU<'a> {
impl<'a> WGPU<'a> { impl<'a> WGPU<'a> {
fn new( fn new(
receiver: IpcReceiver<WebGPURequest>, receiver: IpcReceiver<(Option<ErrorScopeId>, WebGPURequest)>,
sender: IpcSender<WebGPURequest>, sender: IpcSender<(Option<ErrorScopeId>, WebGPURequest)>,
script_sender: IpcSender<WebGPUMsg>, script_sender: IpcSender<WebGPUMsg>,
webrender_api_sender: webrender_api::RenderApiSender, webrender_api_sender: webrender_api::RenderApiSender,
webrender_document: webrender_api::DocumentId, webrender_document: webrender_api::DocumentId,
@ -385,17 +382,18 @@ impl<'a> WGPU<'a> {
let _ = self.global.poll_all_devices(false); let _ = self.global.poll_all_devices(false);
self.last_poll = Instant::now(); self.last_poll = Instant::now();
} }
if let Ok(msg) = self.receiver.try_recv() { if let Ok((scope_id, msg)) = self.receiver.try_recv() {
match msg { match msg {
WebGPURequest::BufferMapAsync { WebGPURequest::BufferMapAsync {
sender, sender,
buffer_id, buffer_id,
device_id,
host_map, host_map,
map_range, map_range,
} => { } => {
let map_info = BufferMapInfo { let map_info = BufferMapInfo {
buffer_id, buffer_id,
sender, sender: sender.clone(),
global: &self.global, global: &self.global,
size: (map_range.end - map_range.start) as usize, size: (map_range.end - map_range.start) as usize,
external_id: None, external_id: None,
@ -409,22 +407,24 @@ impl<'a> WGPU<'a> {
let info = Rc::from_raw( let info = Rc::from_raw(
userdata as *const BufferMapInfo<WebGPUResponseResult>, userdata as *const BufferMapInfo<WebGPUResponseResult>,
); );
match status { let msg = match status {
BufferMapAsyncStatus::Success => { BufferMapAsyncStatus::Success => {
let global = &info.global; let global = &info.global;
let data_pt = gfx_select!(info.buffer_id => let data_pt = gfx_select!(info.buffer_id =>
global.buffer_get_mapped_range(info.buffer_id, 0, None)) global.buffer_get_mapped_range(info.buffer_id, 0, None))
.unwrap(); .unwrap();
let data = slice::from_raw_parts(data_pt, info.size); let data = slice::from_raw_parts(data_pt, info.size);
if let Err(e) = Ok(WebGPUResponse::BufferMapAsync(IpcSharedMemory::from_bytes(
info.sender.send(Ok(WebGPUResponse::BufferMapAsync( data,
IpcSharedMemory::from_bytes(data), )))
)))
{
warn!("Could not send BufferMapAsync Response ({})", e);
}
}, },
_ => error!("Could not map buffer({:?})", info.buffer_id), _ => {
warn!("Could not map buffer({:?})", info.buffer_id);
Err(String::from("Failed to map Buffer"))
},
};
if let Err(e) = info.sender.send(msg) {
warn!("Could not send BufferMapAsync Response ({})", e);
} }
} }
@ -436,7 +436,13 @@ impl<'a> WGPU<'a> {
), ),
}; };
let global = &self.global; let global = &self.global;
let _ = gfx_select!(buffer_id => global.buffer_map_async(buffer_id, map_range, operation)); let result = gfx_select!(buffer_id => global.buffer_map_async(buffer_id, map_range, operation));
if let Err(ref e) = result {
if let Err(w) = sender.send(Err(format!("{:?}", e))) {
warn!("Failed to send BufferMapAsync Response ({:?})", w);
}
}
self.send_result(device_id, scope_id, result);
}, },
WebGPURequest::BufferMapComplete(buffer_id) => { WebGPURequest::BufferMapComplete(buffer_id) => {
self.buffer_maps.remove(&buffer_id); self.buffer_maps.remove(&buffer_id);
@ -444,7 +450,6 @@ impl<'a> WGPU<'a> {
WebGPURequest::CommandEncoderFinish { WebGPURequest::CommandEncoderFinish {
command_encoder_id, command_encoder_id,
device_id, device_id,
scope_id,
} => { } => {
let global = &self.global; let global = &self.global;
let result = gfx_select!(command_encoder_id => global.command_encoder_finish( let result = gfx_select!(command_encoder_id => global.command_encoder_finish(
@ -455,6 +460,7 @@ impl<'a> WGPU<'a> {
}, },
WebGPURequest::CopyBufferToBuffer { WebGPURequest::CopyBufferToBuffer {
command_encoder_id, command_encoder_id,
device_id,
source_id, source_id,
source_offset, source_offset,
destination_id, destination_id,
@ -462,7 +468,7 @@ impl<'a> WGPU<'a> {
size, size,
} => { } => {
let global = &self.global; let global = &self.global;
let _ = gfx_select!(command_encoder_id => global.command_encoder_copy_buffer_to_buffer( let result = gfx_select!(command_encoder_id => global.command_encoder_copy_buffer_to_buffer(
command_encoder_id, command_encoder_id,
source_id, source_id,
source_offset, source_offset,
@ -470,52 +476,58 @@ impl<'a> WGPU<'a> {
destination_offset, destination_offset,
size size
)); ));
self.send_result(device_id, scope_id, result);
}, },
WebGPURequest::CopyBufferToTexture { WebGPURequest::CopyBufferToTexture {
command_encoder_id, command_encoder_id,
device_id,
source, source,
destination, destination,
copy_size, copy_size,
} => { } => {
let global = &self.global; let global = &self.global;
let _ = gfx_select!(command_encoder_id => global.command_encoder_copy_buffer_to_texture( let result = gfx_select!(command_encoder_id => global.command_encoder_copy_buffer_to_texture(
command_encoder_id, command_encoder_id,
&source, &source,
&destination, &destination,
&copy_size &copy_size
)); ));
self.send_result(device_id, scope_id, result);
}, },
WebGPURequest::CopyTextureToBuffer { WebGPURequest::CopyTextureToBuffer {
command_encoder_id, command_encoder_id,
device_id,
source, source,
destination, destination,
copy_size, copy_size,
} => { } => {
let global = &self.global; let global = &self.global;
let _ = gfx_select!(command_encoder_id => global.command_encoder_copy_texture_to_buffer( let result = gfx_select!(command_encoder_id => global.command_encoder_copy_texture_to_buffer(
command_encoder_id, command_encoder_id,
&source, &source,
&destination, &destination,
&copy_size &copy_size
)); ));
self.send_result(device_id, scope_id, result);
}, },
WebGPURequest::CopyTextureToTexture { WebGPURequest::CopyTextureToTexture {
command_encoder_id, command_encoder_id,
device_id,
source, source,
destination, destination,
copy_size, copy_size,
} => { } => {
let global = &self.global; let global = &self.global;
let _ = gfx_select!(command_encoder_id => global.command_encoder_copy_texture_to_texture( let result = gfx_select!(command_encoder_id => global.command_encoder_copy_texture_to_texture(
command_encoder_id, command_encoder_id,
&source, &source,
&destination, &destination,
&copy_size &copy_size
)); ));
self.send_result(device_id, scope_id, result);
}, },
WebGPURequest::CreateBindGroup { WebGPURequest::CreateBindGroup {
device_id, device_id,
scope_id,
bind_group_id, bind_group_id,
descriptor, descriptor,
} => { } => {
@ -526,7 +538,6 @@ impl<'a> WGPU<'a> {
}, },
WebGPURequest::CreateBindGroupLayout { WebGPURequest::CreateBindGroupLayout {
device_id, device_id,
scope_id,
bind_group_layout_id, bind_group_layout_id,
descriptor, descriptor,
} => { } => {
@ -537,7 +548,6 @@ impl<'a> WGPU<'a> {
}, },
WebGPURequest::CreateBuffer { WebGPURequest::CreateBuffer {
device_id, device_id,
scope_id,
buffer_id, buffer_id,
descriptor, descriptor,
} => { } => {
@ -556,7 +566,6 @@ impl<'a> WGPU<'a> {
}, },
WebGPURequest::CreateCommandEncoder { WebGPURequest::CreateCommandEncoder {
device_id, device_id,
scope_id,
command_encoder_id, command_encoder_id,
label, label,
} => { } => {
@ -576,7 +585,6 @@ impl<'a> WGPU<'a> {
}, },
WebGPURequest::CreateComputePipeline { WebGPURequest::CreateComputePipeline {
device_id, device_id,
scope_id,
compute_pipeline_id, compute_pipeline_id,
descriptor, descriptor,
} => { } => {
@ -597,7 +605,6 @@ impl<'a> WGPU<'a> {
}, },
WebGPURequest::CreatePipelineLayout { WebGPURequest::CreatePipelineLayout {
device_id, device_id,
scope_id,
pipeline_layout_id, pipeline_layout_id,
descriptor, descriptor,
} => { } => {
@ -609,7 +616,6 @@ impl<'a> WGPU<'a> {
//TODO: consider https://github.com/gfx-rs/wgpu/issues/684 //TODO: consider https://github.com/gfx-rs/wgpu/issues/684
WebGPURequest::CreateRenderPipeline { WebGPURequest::CreateRenderPipeline {
device_id, device_id,
scope_id,
render_pipeline_id, render_pipeline_id,
descriptor, descriptor,
} => { } => {
@ -620,7 +626,6 @@ impl<'a> WGPU<'a> {
}, },
WebGPURequest::CreateSampler { WebGPURequest::CreateSampler {
device_id, device_id,
scope_id,
sampler_id, sampler_id,
descriptor, descriptor,
} => { } => {
@ -642,7 +647,6 @@ impl<'a> WGPU<'a> {
}, },
WebGPURequest::CreateShaderModule { WebGPURequest::CreateShaderModule {
device_id, device_id,
scope_id,
program_id, program_id,
program, program,
} => { } => {
@ -697,7 +701,6 @@ impl<'a> WGPU<'a> {
}, },
WebGPURequest::CreateTexture { WebGPURequest::CreateTexture {
device_id, device_id,
scope_id,
texture_id, texture_id,
descriptor, descriptor,
} => { } => {
@ -721,7 +724,6 @@ impl<'a> WGPU<'a> {
texture_id, texture_id,
texture_view_id, texture_view_id,
device_id, device_id,
scope_id,
descriptor, descriptor,
} => { } => {
let global = &self.global; let global = &self.global;
@ -799,7 +801,6 @@ impl<'a> WGPU<'a> {
descriptor, descriptor,
render_bundle_id, render_bundle_id,
device_id, device_id,
scope_id,
} => { } => {
let global = &self.global; let global = &self.global;
let st; let st;
@ -863,14 +864,23 @@ impl<'a> WGPU<'a> {
label, label,
} => { } => {
let global = &self.global; let global = &self.global;
let result = gfx_select!(device_id => global.adapter_request_device( let id = match gfx_select!(device_id => global.adapter_request_device(
adapter_id.0, adapter_id.0,
&descriptor, &descriptor,
None, None,
device_id device_id
)); )) {
// TODO: Handle error gracefully acc. to spec. Ok(id) => id,
let id = result.unwrap(); Err(e) => {
if let Err(w) = sender.send(Err(format!("{:?}", e))) {
warn!(
"Failed to send response to WebGPURequest::RequestDevice ({})",
w
)
}
return;
},
};
let device = WebGPUDevice(id); let device = WebGPUDevice(id);
// Note: (zakorgy) Note sure if sending the queue is needed at all, // Note: (zakorgy) Note sure if sending the queue is needed at all,
// since wgpu-core uses the same id for the device and the queue // since wgpu-core uses the same id for the device and the queue
@ -890,30 +900,35 @@ impl<'a> WGPU<'a> {
}, },
WebGPURequest::RunComputePass { WebGPURequest::RunComputePass {
command_encoder_id, command_encoder_id,
device_id,
compute_pass, compute_pass,
} => { } => {
let global = &self.global; let global = &self.global;
let _ = gfx_select!(command_encoder_id => global.command_encoder_run_compute_pass( let result = gfx_select!(command_encoder_id => global.command_encoder_run_compute_pass(
command_encoder_id, command_encoder_id,
&compute_pass &compute_pass
)); ));
self.send_result(device_id, scope_id, result);
}, },
WebGPURequest::RunRenderPass { WebGPURequest::RunRenderPass {
command_encoder_id, command_encoder_id,
device_id,
render_pass, render_pass,
} => { } => {
let global = &self.global; let global = &self.global;
let _ = gfx_select!(command_encoder_id => global.command_encoder_run_render_pass( let result = gfx_select!(command_encoder_id => global.command_encoder_run_render_pass(
command_encoder_id, command_encoder_id,
&render_pass &render_pass
)); ));
self.send_result(device_id, scope_id, result);
}, },
WebGPURequest::Submit { WebGPURequest::Submit {
queue_id, queue_id,
command_buffers, command_buffers,
} => { } => {
let global = &self.global; let global = &self.global;
let _ = gfx_select!(queue_id => global.queue_submit(queue_id, &command_buffers)); let result = gfx_select!(queue_id => global.queue_submit(queue_id, &command_buffers));
self.send_result(queue_id, scope_id, result);
}, },
WebGPURequest::SwapChainPresent { WebGPURequest::SwapChainPresent {
external_id, external_id,
@ -1052,6 +1067,7 @@ impl<'a> WGPU<'a> {
}, },
WebGPURequest::UnmapBuffer { WebGPURequest::UnmapBuffer {
buffer_id, buffer_id,
device_id,
array_buffer, array_buffer,
is_map_read, is_map_read,
offset, offset,
@ -1068,7 +1084,8 @@ impl<'a> WGPU<'a> {
unsafe { slice::from_raw_parts_mut(map_ptr, size as usize) } unsafe { slice::from_raw_parts_mut(map_ptr, size as usize) }
.copy_from_slice(&array_buffer); .copy_from_slice(&array_buffer);
} }
let _ = gfx_select!(buffer_id => global.buffer_unmap(buffer_id)); let result = gfx_select!(buffer_id => global.buffer_unmap(buffer_id));
self.send_result(device_id, scope_id, result);
}, },
WebGPURequest::UpdateWebRenderData { WebGPURequest::UpdateWebRenderData {
buffer_id, buffer_id,
@ -1111,12 +1128,13 @@ impl<'a> WGPU<'a> {
} => { } => {
let global = &self.global; let global = &self.global;
//TODO: Report result to content process //TODO: Report result to content process
let _ = gfx_select!(queue_id => global.queue_write_buffer( let result = gfx_select!(queue_id => global.queue_write_buffer(
queue_id, queue_id,
buffer_id, buffer_id,
buffer_offset as wgt::BufferAddress, buffer_offset as wgt::BufferAddress,
&data &data
)); ));
self.send_result(queue_id, scope_id, result);
}, },
WebGPURequest::WriteTexture { WebGPURequest::WriteTexture {
queue_id, queue_id,
@ -1127,23 +1145,24 @@ impl<'a> WGPU<'a> {
} => { } => {
let global = &self.global; let global = &self.global;
//TODO: Report result to content process //TODO: Report result to content process
let _ = gfx_select!(queue_id => global.queue_write_texture( let result = gfx_select!(queue_id => global.queue_write_texture(
queue_id, queue_id,
&texture_cv, &texture_cv,
&data, &data,
&data_layout, &data_layout,
&size &size
)); ));
self.send_result(queue_id, scope_id, result);
}, },
} }
} }
} }
} }
fn send_result<U: id::TypedId, T: std::fmt::Debug>( fn send_result<U, T: std::fmt::Debug>(
&self, &self,
device_id: id::DeviceId, device_id: id::DeviceId,
scope_id: Option<u64>, scope_id: Option<ErrorScopeId>,
result: Result<U, T>, result: Result<U, T>,
) { ) {
let &pipeline_id = self.devices.get(&WebGPUDevice(device_id)).unwrap(); let &pipeline_id = self.devices.get(&WebGPUDevice(device_id)).unwrap();