Auto merge of #26660 - kunalmohan:gpu-async-resource, r=kvark

Make WebGPU resource creation async and prevent panic during shutdown if WebGPU is enabled.

<!-- Please describe your changes on the following line: -->
1. Make WebGPU resource creation async.
2. Remove some unused code in `WebGPURequest::RequestAdapter`.
3. Prevent panic during shutdown. Since WGPU thread is killed before script, sender and receiver in the script panic at either of the two places-
a. If a buffer is still alive, script tries to send `WebGPURequest::DestroyBuffer` to server while dropping the buffer during shutdown.
7170a69695/components/script/dom/gpubuffer.rs (L118-L122) 7170a69695/components/script/dom/gpubuffer.rs (L182-L186)
b. Receiver in script-thread panics with `RecvError` as soon as sender on server side is dropped. 7170a69695/components/script/script_thread.rs (L1456-L1457)

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
- [X] These changes fix #25472 (GitHub issue number if applicable)

<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because ___

<!-- 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-05-27 00:54:16 -04:00 committed by GitHub
commit 07eb9ab3fe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 65 additions and 165 deletions

View file

@ -179,10 +179,16 @@ impl GPUBufferMethods for GPUBuffer {
}, },
_ => {}, _ => {},
}; };
self.channel if let Err(e) = self
.channel
.0 .0
.send(WebGPURequest::DestroyBuffer(self.buffer.0)) .send(WebGPURequest::DestroyBuffer(self.buffer.0))
.unwrap(); {
warn!(
"Failed to send WebGPURequest::DestroyBuffer({:?}) ({})",
self.buffer.0, e
);
};
*self.state.borrow_mut() = GPUBufferState::Destroyed; *self.state.borrow_mut() = GPUBufferState::Destroyed;
} }

View file

@ -16,11 +16,10 @@ use crate::dom::gpubuffer::GPUBuffer;
use crate::dom::gpucommandbuffer::GPUCommandBuffer; use crate::dom::gpucommandbuffer::GPUCommandBuffer;
use crate::dom::gpucomputepassencoder::GPUComputePassEncoder; use crate::dom::gpucomputepassencoder::GPUComputePassEncoder;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use ipc_channel::ipc;
use std::cell::Cell; use std::cell::Cell;
use std::collections::HashSet; use std::collections::HashSet;
use webgpu::wgt::BufferUsage; use webgpu::wgt::BufferUsage;
use webgpu::{WebGPU, WebGPUCommandEncoder, WebGPURequest}; use webgpu::{self, WebGPU, WebGPURequest};
const BUFFER_COPY_ALIGN_MASK: u64 = 3; const BUFFER_COPY_ALIGN_MASK: u64 = 3;
@ -40,7 +39,7 @@ pub struct GPUCommandEncoder {
#[ignore_malloc_size_of = "defined in webgpu"] #[ignore_malloc_size_of = "defined in webgpu"]
channel: WebGPU, channel: WebGPU,
label: DomRefCell<Option<DOMString>>, label: DomRefCell<Option<DOMString>>,
encoder: WebGPUCommandEncoder, encoder: webgpu::WebGPUCommandEncoder,
buffers: DomRefCell<HashSet<DomRoot<GPUBuffer>>>, buffers: DomRefCell<HashSet<DomRoot<GPUBuffer>>>,
state: DomRefCell<GPUCommandEncoderState>, state: DomRefCell<GPUCommandEncoderState>,
valid: Cell<bool>, valid: Cell<bool>,
@ -49,7 +48,7 @@ pub struct GPUCommandEncoder {
impl GPUCommandEncoder { impl GPUCommandEncoder {
pub fn new_inherited( pub fn new_inherited(
channel: WebGPU, channel: WebGPU,
encoder: WebGPUCommandEncoder, encoder: webgpu::WebGPUCommandEncoder,
valid: bool, valid: bool,
) -> GPUCommandEncoder { ) -> GPUCommandEncoder {
GPUCommandEncoder { GPUCommandEncoder {
@ -66,7 +65,7 @@ impl GPUCommandEncoder {
pub fn new( pub fn new(
global: &GlobalScope, global: &GlobalScope,
channel: WebGPU, channel: WebGPU,
encoder: WebGPUCommandEncoder, encoder: webgpu::WebGPUCommandEncoder,
valid: bool, valid: bool,
) -> DomRoot<GPUCommandEncoder> { ) -> DomRoot<GPUCommandEncoder> {
reflect_dom_object( reflect_dom_object(
@ -77,7 +76,7 @@ impl GPUCommandEncoder {
} }
impl GPUCommandEncoder { impl GPUCommandEncoder {
pub fn id(&self) -> WebGPUCommandEncoder { pub fn id(&self) -> webgpu::WebGPUCommandEncoder {
self.encoder self.encoder
} }
@ -179,11 +178,9 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
/// https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-finish /// https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-finish
fn Finish(&self, _descriptor: &GPUCommandBufferDescriptor) -> DomRoot<GPUCommandBuffer> { fn Finish(&self, _descriptor: &GPUCommandBufferDescriptor) -> DomRoot<GPUCommandBuffer> {
let (sender, receiver) = ipc::channel().unwrap();
self.channel self.channel
.0 .0
.send(WebGPURequest::CommandEncoderFinish { .send(WebGPURequest::CommandEncoderFinish {
sender,
command_encoder_id: self.encoder.0, command_encoder_id: self.encoder.0,
// TODO(zakorgy): We should use `_descriptor` here after it's not empty // TODO(zakorgy): We should use `_descriptor` here after it's not empty
// and the underlying wgpu-core struct is serializable // and the underlying wgpu-core struct is serializable
@ -191,7 +188,7 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
.expect("Failed to send Finish"); .expect("Failed to send Finish");
*self.state.borrow_mut() = GPUCommandEncoderState::Closed; *self.state.borrow_mut() = GPUCommandEncoderState::Closed;
let buffer = receiver.recv().unwrap(); let buffer = webgpu::WebGPUCommandBuffer(self.encoder.0);
GPUCommandBuffer::new( GPUCommandBuffer::new(
&self.global(), &self.global(),
self.channel.clone(), self.channel.clone(),

View file

@ -39,7 +39,6 @@ use crate::dom::gpusampler::GPUSampler;
use crate::dom::gpushadermodule::GPUShaderModule; use crate::dom::gpushadermodule::GPUShaderModule;
use crate::script_runtime::JSContext as SafeJSContext; use crate::script_runtime::JSContext as SafeJSContext;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use ipc_channel::ipc;
use js::jsapi::{Heap, JSObject}; use js::jsapi::{Heap, JSObject};
use js::jsval::{JSVal, ObjectValue}; use js::jsval::{JSVal, ObjectValue};
use js::typedarray::{ArrayBuffer, CreateWith}; use js::typedarray::{ArrayBuffer, CreateWith};
@ -48,7 +47,7 @@ use std::ptr::{self, NonNull};
use webgpu::wgpu::binding_model::{ use webgpu::wgpu::binding_model::{
BindGroupEntry, BindGroupLayoutEntry, BindingResource, BindingType, BufferBinding, BindGroupEntry, BindGroupLayoutEntry, BindingResource, BindingType, BufferBinding,
}; };
use webgpu::{wgt, WebGPU, WebGPUDevice, WebGPUQueue, WebGPURequest, WebGPUSampler}; use webgpu::{self, wgt, WebGPU, WebGPURequest};
#[dom_struct] #[dom_struct]
pub struct GPUDevice { pub struct GPUDevice {
@ -61,7 +60,7 @@ pub struct GPUDevice {
#[ignore_malloc_size_of = "mozjs"] #[ignore_malloc_size_of = "mozjs"]
limits: Heap<*mut JSObject>, limits: Heap<*mut JSObject>,
label: DomRefCell<Option<DOMString>>, label: DomRefCell<Option<DOMString>>,
device: WebGPUDevice, device: webgpu::WebGPUDevice,
default_queue: Dom<GPUQueue>, default_queue: Dom<GPUQueue>,
} }
@ -71,7 +70,7 @@ impl GPUDevice {
adapter: &GPUAdapter, adapter: &GPUAdapter,
extensions: Heap<*mut JSObject>, extensions: Heap<*mut JSObject>,
limits: Heap<*mut JSObject>, limits: Heap<*mut JSObject>,
device: WebGPUDevice, device: webgpu::WebGPUDevice,
queue: &GPUQueue, queue: &GPUQueue,
) -> GPUDevice { ) -> GPUDevice {
Self { Self {
@ -93,8 +92,8 @@ impl GPUDevice {
adapter: &GPUAdapter, adapter: &GPUAdapter,
extensions: Heap<*mut JSObject>, extensions: Heap<*mut JSObject>,
limits: Heap<*mut JSObject>, limits: Heap<*mut JSObject>,
device: WebGPUDevice, device: webgpu::WebGPUDevice,
queue: WebGPUQueue, queue: webgpu::WebGPUQueue,
) -> DomRoot<GPUDevice> { ) -> DomRoot<GPUDevice> {
let queue = GPUQueue::new(global, channel.clone(), queue); let queue = GPUQueue::new(global, channel.clone(), queue);
reflect_dom_object( reflect_dom_object(
@ -171,7 +170,6 @@ impl GPUDeviceMethods for GPUDevice {
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbuffer /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbuffer
fn CreateBuffer(&self, descriptor: &GPUBufferDescriptor) -> DomRoot<GPUBuffer> { fn CreateBuffer(&self, descriptor: &GPUBufferDescriptor) -> DomRoot<GPUBuffer> {
let (valid, wgpu_descriptor) = self.validate_buffer_descriptor(descriptor); let (valid, wgpu_descriptor) = self.validate_buffer_descriptor(descriptor);
let (sender, receiver) = ipc::channel().unwrap();
let id = self let id = self
.global() .global()
.wgpu_id_hub() .wgpu_id_hub()
@ -180,14 +178,13 @@ impl GPUDeviceMethods for GPUDevice {
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateBuffer { .send(WebGPURequest::CreateBuffer {
sender,
device_id: self.device.0, device_id: self.device.0,
buffer_id: id, buffer_id: id,
descriptor: wgpu_descriptor, descriptor: wgpu_descriptor,
}) })
.expect("Failed to create WebGPU buffer"); .expect("Failed to create WebGPU buffer");
let buffer = receiver.recv().unwrap(); let buffer = webgpu::WebGPUBuffer(id);
GPUBuffer::new( GPUBuffer::new(
&self.global(), &self.global(),
@ -209,7 +206,6 @@ impl GPUDeviceMethods for GPUDevice {
descriptor: &GPUBufferDescriptor, descriptor: &GPUBufferDescriptor,
) -> Vec<JSVal> { ) -> Vec<JSVal> {
let (valid, wgpu_descriptor) = self.validate_buffer_descriptor(descriptor); let (valid, wgpu_descriptor) = self.validate_buffer_descriptor(descriptor);
let (sender, receiver) = ipc::channel().unwrap();
let buffer_id = self let buffer_id = self
.global() .global()
.wgpu_id_hub() .wgpu_id_hub()
@ -218,7 +214,6 @@ impl GPUDeviceMethods for GPUDevice {
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateBufferMapped { .send(WebGPURequest::CreateBufferMapped {
sender,
device_id: self.device.0, device_id: self.device.0,
buffer_id, buffer_id,
descriptor: wgpu_descriptor.clone(), descriptor: wgpu_descriptor.clone(),
@ -235,7 +230,7 @@ impl GPUDeviceMethods for GPUDevice {
.is_ok()); .is_ok());
} }
let buffer = receiver.recv().unwrap(); let buffer = webgpu::WebGPUBuffer(buffer_id);
let buff = GPUBuffer::new( let buff = GPUBuffer::new(
&self.global(), &self.global(),
self.channel.clone(), self.channel.clone(),
@ -398,7 +393,6 @@ impl GPUDeviceMethods for GPUDevice {
valid &= max_dynamic_uniform_buffers_per_pipeline_layout >= 0 && valid &= max_dynamic_uniform_buffers_per_pipeline_layout >= 0 &&
max_dynamic_storage_buffers_per_pipeline_layout >= 0; max_dynamic_storage_buffers_per_pipeline_layout >= 0;
let (sender, receiver) = ipc::channel().unwrap();
let bind_group_layout_id = self let bind_group_layout_id = self
.global() .global()
.wgpu_id_hub() .wgpu_id_hub()
@ -407,14 +401,13 @@ impl GPUDeviceMethods for GPUDevice {
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateBindGroupLayout { .send(WebGPURequest::CreateBindGroupLayout {
sender,
device_id: self.device.0, device_id: self.device.0,
bind_group_layout_id, bind_group_layout_id,
bindings: bindings.clone(), bindings: bindings.clone(),
}) })
.expect("Failed to create WebGPU BindGroupLayout"); .expect("Failed to create WebGPU BindGroupLayout");
let bgl = receiver.recv().unwrap(); let bgl = webgpu::WebGPUBindGroupLayout(bind_group_layout_id);
let binds = descriptor let binds = descriptor
.entries .entries
@ -478,7 +471,6 @@ impl GPUDeviceMethods for GPUDevice {
max_dynamic_uniform_buffers_per_pipeline_layout >= 0 && max_dynamic_uniform_buffers_per_pipeline_layout >= 0 &&
max_dynamic_storage_buffers_per_pipeline_layout >= 0; max_dynamic_storage_buffers_per_pipeline_layout >= 0;
let (sender, receiver) = ipc::channel().unwrap();
let pipeline_layout_id = self let pipeline_layout_id = self
.global() .global()
.wgpu_id_hub() .wgpu_id_hub()
@ -487,14 +479,13 @@ impl GPUDeviceMethods for GPUDevice {
self.channel self.channel
.0 .0
.send(WebGPURequest::CreatePipelineLayout { .send(WebGPURequest::CreatePipelineLayout {
sender,
device_id: self.device.0, device_id: self.device.0,
pipeline_layout_id, pipeline_layout_id,
bind_group_layouts: bgl_ids, bind_group_layouts: bgl_ids,
}) })
.expect("Failed to create WebGPU PipelineLayout"); .expect("Failed to create WebGPU PipelineLayout");
let pipeline_layout = receiver.recv().unwrap(); let pipeline_layout = webgpu::WebGPUPipelineLayout(pipeline_layout_id);
GPUPipelineLayout::new(&self.global(), bind_group_layouts, pipeline_layout, valid) GPUPipelineLayout::new(&self.global(), bind_group_layouts, pipeline_layout, valid)
} }
@ -539,7 +530,7 @@ impl GPUDeviceMethods for GPUDevice {
}), }),
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let (sender, receiver) = ipc::channel().unwrap();
let bind_group_id = self let bind_group_id = self
.global() .global()
.wgpu_id_hub() .wgpu_id_hub()
@ -548,7 +539,6 @@ impl GPUDeviceMethods for GPUDevice {
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateBindGroup { .send(WebGPURequest::CreateBindGroup {
sender,
device_id: self.device.0, device_id: self.device.0,
bind_group_id, bind_group_id,
bind_group_layout_id: descriptor.layout.id().0, bind_group_layout_id: descriptor.layout.id().0,
@ -556,7 +546,7 @@ impl GPUDeviceMethods for GPUDevice {
}) })
.expect("Failed to create WebGPU BindGroup"); .expect("Failed to create WebGPU BindGroup");
let bind_group = receiver.recv().unwrap(); let bind_group = webgpu::WebGPUBindGroup(bind_group_id);
GPUBindGroup::new(&self.global(), bind_group, valid) GPUBindGroup::new(&self.global(), bind_group, valid)
} }
@ -565,7 +555,6 @@ impl GPUDeviceMethods for GPUDevice {
&self, &self,
descriptor: RootedTraceableBox<GPUShaderModuleDescriptor>, descriptor: RootedTraceableBox<GPUShaderModuleDescriptor>,
) -> DomRoot<GPUShaderModule> { ) -> DomRoot<GPUShaderModule> {
let (sender, receiver) = ipc::channel().unwrap();
let program: Vec<u32> = match &descriptor.code { let program: Vec<u32> = match &descriptor.code {
Uint32Array(program) => program.to_vec(), Uint32Array(program) => program.to_vec(),
String(program) => program.chars().map(|c| c as u32).collect::<Vec<u32>>(), String(program) => program.chars().map(|c| c as u32).collect::<Vec<u32>>(),
@ -578,14 +567,13 @@ impl GPUDeviceMethods for GPUDevice {
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateShaderModule { .send(WebGPURequest::CreateShaderModule {
sender,
device_id: self.device.0, device_id: self.device.0,
program_id, program_id,
program, program,
}) })
.expect("Failed to create WebGPU ShaderModule"); .expect("Failed to create WebGPU ShaderModule");
let shader_module = receiver.recv().unwrap(); let shader_module = webgpu::WebGPUShaderModule(program_id);
GPUShaderModule::new(&self.global(), shader_module) GPUShaderModule::new(&self.global(), shader_module)
} }
@ -602,11 +590,10 @@ impl GPUDeviceMethods for GPUDevice {
.wgpu_id_hub() .wgpu_id_hub()
.lock() .lock()
.create_compute_pipeline_id(self.device.0.backend()); .create_compute_pipeline_id(self.device.0.backend());
let (sender, receiver) = ipc::channel().unwrap();
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateComputePipeline { .send(WebGPURequest::CreateComputePipeline {
sender,
device_id: self.device.0, device_id: self.device.0,
compute_pipeline_id, compute_pipeline_id,
pipeline_layout_id: pipeline.0, pipeline_layout_id: pipeline.0,
@ -615,7 +602,7 @@ impl GPUDeviceMethods for GPUDevice {
}) })
.expect("Failed to create WebGPU ComputePipeline"); .expect("Failed to create WebGPU ComputePipeline");
let compute_pipeline = receiver.recv().unwrap(); let compute_pipeline = webgpu::WebGPUComputePipeline(compute_pipeline_id);
GPUComputePipeline::new(&self.global(), compute_pipeline) GPUComputePipeline::new(&self.global(), compute_pipeline)
} }
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createcommandencoder /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createcommandencoder
@ -623,7 +610,6 @@ impl GPUDeviceMethods for GPUDevice {
&self, &self,
_descriptor: &GPUCommandEncoderDescriptor, _descriptor: &GPUCommandEncoderDescriptor,
) -> DomRoot<GPUCommandEncoder> { ) -> DomRoot<GPUCommandEncoder> {
let (sender, receiver) = ipc::channel().unwrap();
let command_encoder_id = self let command_encoder_id = self
.global() .global()
.wgpu_id_hub() .wgpu_id_hub()
@ -632,12 +618,12 @@ impl GPUDeviceMethods for GPUDevice {
self.channel self.channel
.0 .0
.send(WebGPURequest::CreateCommandEncoder { .send(WebGPURequest::CreateCommandEncoder {
sender,
device_id: self.device.0, device_id: self.device.0,
command_encoder_id, command_encoder_id,
}) })
.expect("Failed to create WebGPU command encoder"); .expect("Failed to create WebGPU command encoder");
let encoder = receiver.recv().unwrap();
let encoder = webgpu::WebGPUCommandEncoder(command_encoder_id);
GPUCommandEncoder::new(&self.global(), self.channel.clone(), encoder, true) GPUCommandEncoder::new(&self.global(), self.channel.clone(), encoder, true)
} }
@ -683,7 +669,7 @@ impl GPUDeviceMethods for GPUDevice {
}) })
.expect("Failed to create WebGPU sampler"); .expect("Failed to create WebGPU sampler");
let sampler = WebGPUSampler(sampler_id); let sampler = webgpu::WebGPUSampler(sampler_id);
GPUSampler::new( GPUSampler::new(
&self.global(), &self.global(),

View file

@ -2016,6 +2016,7 @@ impl ScriptThread {
WebGPUMsg::FreeCommandBuffer(id) => self.gpu_id_hub.lock().kill_command_buffer_id(id), WebGPUMsg::FreeCommandBuffer(id) => self.gpu_id_hub.lock().kill_command_buffer_id(id),
WebGPUMsg::FreeSampler(id) => self.gpu_id_hub.lock().kill_sampler_id(id), WebGPUMsg::FreeSampler(id) => self.gpu_id_hub.lock().kill_sampler_id(id),
WebGPUMsg::FreeShaderModule(id) => self.gpu_id_hub.lock().kill_shader_module_id(id), WebGPUMsg::FreeShaderModule(id) => self.gpu_id_hub.lock().kill_shader_module_id(id),
WebGPUMsg::Exit => *self.webgpu_port.borrow_mut() = None,
_ => {}, _ => {},
} }
} }

View file

@ -31,6 +31,7 @@ pub enum WebGPUMsg {
FreeSampler(SamplerId), FreeSampler(SamplerId),
FreeSurface(SurfaceId), FreeSurface(SurfaceId),
FreeShaderModule(ShaderModuleId), FreeShaderModule(ShaderModuleId),
Exit,
} }
#[derive(Debug)] #[derive(Debug)]

View file

@ -45,7 +45,6 @@ pub type WebGPUResponseResult = Result<WebGPUResponse, String>;
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
pub enum WebGPURequest { pub enum WebGPURequest {
CommandEncoderFinish { CommandEncoderFinish {
sender: IpcSender<WebGPUCommandBuffer>,
command_encoder_id: id::CommandEncoderId, command_encoder_id: id::CommandEncoderId,
// TODO(zakorgy): Serialize CommandBufferDescriptor in wgpu-core // TODO(zakorgy): Serialize CommandBufferDescriptor in wgpu-core
// wgpu::command::CommandBufferDescriptor, // wgpu::command::CommandBufferDescriptor,
@ -59,39 +58,33 @@ pub enum WebGPURequest {
size: wgt::BufferAddress, size: wgt::BufferAddress,
}, },
CreateBindGroup { CreateBindGroup {
sender: IpcSender<WebGPUBindGroup>,
device_id: id::DeviceId, device_id: id::DeviceId,
bind_group_id: id::BindGroupId, bind_group_id: id::BindGroupId,
bind_group_layout_id: id::BindGroupLayoutId, bind_group_layout_id: id::BindGroupLayoutId,
bindings: Vec<BindGroupEntry>, bindings: Vec<BindGroupEntry>,
}, },
CreateBindGroupLayout { CreateBindGroupLayout {
sender: IpcSender<WebGPUBindGroupLayout>,
device_id: id::DeviceId, device_id: id::DeviceId,
bind_group_layout_id: id::BindGroupLayoutId, bind_group_layout_id: id::BindGroupLayoutId,
bindings: Vec<BindGroupLayoutEntry>, bindings: Vec<BindGroupLayoutEntry>,
}, },
CreateBuffer { CreateBuffer {
sender: IpcSender<WebGPUBuffer>,
device_id: id::DeviceId, device_id: id::DeviceId,
buffer_id: id::BufferId, buffer_id: id::BufferId,
descriptor: wgt::BufferDescriptor<String>, descriptor: wgt::BufferDescriptor<String>,
}, },
CreateBufferMapped { CreateBufferMapped {
sender: IpcSender<WebGPUBuffer>,
device_id: id::DeviceId, device_id: id::DeviceId,
buffer_id: id::BufferId, buffer_id: id::BufferId,
descriptor: wgt::BufferDescriptor<String>, descriptor: wgt::BufferDescriptor<String>,
}, },
CreateCommandEncoder { CreateCommandEncoder {
sender: IpcSender<WebGPUCommandEncoder>,
device_id: id::DeviceId, device_id: id::DeviceId,
// 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,
}, },
CreateComputePipeline { CreateComputePipeline {
sender: IpcSender<WebGPUComputePipeline>,
device_id: id::DeviceId, device_id: id::DeviceId,
compute_pipeline_id: id::ComputePipelineId, compute_pipeline_id: id::ComputePipelineId,
pipeline_layout_id: id::PipelineLayoutId, pipeline_layout_id: id::PipelineLayoutId,
@ -99,7 +92,6 @@ pub enum WebGPURequest {
entry_point: String, entry_point: String,
}, },
CreatePipelineLayout { CreatePipelineLayout {
sender: IpcSender<WebGPUPipelineLayout>,
device_id: id::DeviceId, device_id: id::DeviceId,
pipeline_layout_id: id::PipelineLayoutId, pipeline_layout_id: id::PipelineLayoutId,
bind_group_layouts: Vec<id::BindGroupLayoutId>, bind_group_layouts: Vec<id::BindGroupLayoutId>,
@ -110,7 +102,6 @@ pub enum WebGPURequest {
descriptor: wgt::SamplerDescriptor<String>, descriptor: wgt::SamplerDescriptor<String>,
}, },
CreateShaderModule { CreateShaderModule {
sender: IpcSender<WebGPUShaderModule>,
device_id: id::DeviceId, device_id: id::DeviceId,
program_id: id::ShaderModuleId, program_id: id::ShaderModuleId,
program: Vec<u32>, program: Vec<u32>,
@ -196,6 +187,7 @@ impl WebGPU {
struct WGPU { struct WGPU {
receiver: IpcReceiver<WebGPURequest>, receiver: IpcReceiver<WebGPURequest>,
sender: IpcSender<WebGPURequest>, sender: IpcSender<WebGPURequest>,
script_sender: IpcSender<WebGPUMsg>,
global: wgpu::hub::Global<IdentityRecyclerFactory>, global: wgpu::hub::Global<IdentityRecyclerFactory>,
adapters: Vec<WebGPUAdapter>, adapters: Vec<WebGPUAdapter>,
devices: Vec<WebGPUDevice>, devices: Vec<WebGPUDevice>,
@ -210,11 +202,12 @@ impl WGPU {
script_sender: IpcSender<WebGPUMsg>, script_sender: IpcSender<WebGPUMsg>,
) -> Self { ) -> Self {
let factory = IdentityRecyclerFactory { let factory = IdentityRecyclerFactory {
sender: script_sender, sender: script_sender.clone(),
}; };
WGPU { WGPU {
receiver, receiver,
sender, sender,
script_sender,
global: wgpu::hub::Global::new("wgpu-core", factory), global: wgpu::hub::Global::new("wgpu-core", factory),
adapters: Vec::new(), adapters: Vec::new(),
devices: Vec::new(), devices: Vec::new(),
@ -225,21 +218,12 @@ impl WGPU {
fn run(mut self) { fn run(mut self) {
while let Ok(msg) = self.receiver.recv() { while let Ok(msg) = self.receiver.recv() {
match msg { match msg {
WebGPURequest::CommandEncoderFinish { WebGPURequest::CommandEncoderFinish { command_encoder_id } => {
sender,
command_encoder_id,
} => {
let global = &self.global; let global = &self.global;
let command_buffer_id = gfx_select!(command_encoder_id => global.command_encoder_finish( let _ = gfx_select!(command_encoder_id => global.command_encoder_finish(
command_encoder_id, command_encoder_id,
&wgt::CommandBufferDescriptor::default() &wgt::CommandBufferDescriptor::default()
)); ));
if let Err(e) = sender.send(WebGPUCommandBuffer(command_buffer_id)) {
warn!(
"Failed to send response to WebGPURequest::CommandEncoderFinish ({})",
e
)
}
}, },
WebGPURequest::CopyBufferToBuffer { WebGPURequest::CopyBufferToBuffer {
command_encoder_id, command_encoder_id,
@ -260,7 +244,6 @@ impl WGPU {
)); ));
}, },
WebGPURequest::CreateBindGroup { WebGPURequest::CreateBindGroup {
sender,
device_id, device_id,
bind_group_id, bind_group_id,
bind_group_layout_id, bind_group_layout_id,
@ -273,19 +256,10 @@ impl WGPU {
entries_length: bindings.len(), entries_length: bindings.len(),
label: ptr::null(), label: ptr::null(),
}; };
let bg_id = gfx_select!(bind_group_id => let _ = gfx_select!(bind_group_id =>
global.device_create_bind_group(device_id, &descriptor, bind_group_id)); global.device_create_bind_group(device_id, &descriptor, bind_group_id));
let bind_group = WebGPUBindGroup(bg_id);
if let Err(e) = sender.send(bind_group) {
warn!(
"Failed to send response to WebGPURequest::CreateBindGroup ({})",
e
)
}
}, },
WebGPURequest::CreateBindGroupLayout { WebGPURequest::CreateBindGroupLayout {
sender,
device_id, device_id,
bind_group_layout_id, bind_group_layout_id,
bindings, bindings,
@ -296,19 +270,10 @@ impl WGPU {
entries_length: bindings.len(), entries_length: bindings.len(),
label: ptr::null(), label: ptr::null(),
}; };
let bgl_id = gfx_select!(bind_group_layout_id => let _ = gfx_select!(bind_group_layout_id =>
global.device_create_bind_group_layout(device_id, &descriptor, bind_group_layout_id)); global.device_create_bind_group_layout(device_id, &descriptor, bind_group_layout_id));
let bgl = WebGPUBindGroupLayout(bgl_id);
if let Err(e) = sender.send(bgl) {
warn!(
"Failed to send response to WebGPURequest::CreateBindGroupLayout ({})",
e
)
}
}, },
WebGPURequest::CreateBuffer { WebGPURequest::CreateBuffer {
sender,
device_id, device_id,
buffer_id, buffer_id,
descriptor, descriptor,
@ -319,17 +284,9 @@ impl WGPU {
usage: descriptor.usage, usage: descriptor.usage,
label: ptr::null(), label: ptr::null(),
}; };
let id = gfx_select!(buffer_id => global.device_create_buffer(device_id, &desc, buffer_id)); let _ = gfx_select!(buffer_id => global.device_create_buffer(device_id, &desc, buffer_id));
let buffer = WebGPUBuffer(id);
if let Err(e) = sender.send(buffer) {
warn!(
"Failed to send response to WebGPURequest::CreateBuffer ({})",
e
)
}
}, },
WebGPURequest::CreateBufferMapped { WebGPURequest::CreateBufferMapped {
sender,
device_id, device_id,
buffer_id, buffer_id,
descriptor, descriptor,
@ -340,34 +297,18 @@ impl WGPU {
usage: descriptor.usage, usage: descriptor.usage,
label: ptr::null(), label: ptr::null(),
}; };
let (buffer_id, _arr_buff_ptr) = gfx_select!(buffer_id => let _ = gfx_select!(buffer_id =>
global.device_create_buffer_mapped(device_id, &desc, buffer_id)); global.device_create_buffer_mapped(device_id, &desc, buffer_id));
let buffer = WebGPUBuffer(buffer_id);
if let Err(e) = sender.send(buffer) {
warn!(
"Failed to send response to WebGPURequest::CreateBufferMapped ({})",
e
)
}
}, },
WebGPURequest::CreateCommandEncoder { WebGPURequest::CreateCommandEncoder {
sender,
device_id, device_id,
command_encoder_id, command_encoder_id,
} => { } => {
let global = &self.global; let global = &self.global;
let id = gfx_select!(command_encoder_id => let _ = gfx_select!(command_encoder_id =>
global.device_create_command_encoder(device_id, &Default::default(), command_encoder_id)); global.device_create_command_encoder(device_id, &Default::default(), command_encoder_id));
if let Err(e) = sender.send(WebGPUCommandEncoder(id)) {
warn!(
"Failed to send response to WebGPURequest::CreateCommandEncoder ({})",
e
)
}
}, },
WebGPURequest::CreateComputePipeline { WebGPURequest::CreateComputePipeline {
sender,
device_id, device_id,
compute_pipeline_id, compute_pipeline_id,
pipeline_layout_id, pipeline_layout_id,
@ -383,19 +324,10 @@ impl WGPU {
entry_point: entry_point.as_ptr(), entry_point: entry_point.as_ptr(),
}, },
}; };
let cp_id = gfx_select!(compute_pipeline_id => let _ = gfx_select!(compute_pipeline_id =>
global.device_create_compute_pipeline(device_id, &descriptor, compute_pipeline_id)); global.device_create_compute_pipeline(device_id, &descriptor, compute_pipeline_id));
let compute_pipeline = WebGPUComputePipeline(cp_id);
if let Err(e) = sender.send(compute_pipeline) {
warn!(
"Failed to send response to WebGPURequest::CreateComputePipeline ({})",
e
)
}
}, },
WebGPURequest::CreatePipelineLayout { WebGPURequest::CreatePipelineLayout {
sender,
device_id, device_id,
pipeline_layout_id, pipeline_layout_id,
bind_group_layouts, bind_group_layouts,
@ -405,16 +337,8 @@ impl WGPU {
bind_group_layouts: bind_group_layouts.as_ptr(), bind_group_layouts: bind_group_layouts.as_ptr(),
bind_group_layouts_length: bind_group_layouts.len(), bind_group_layouts_length: bind_group_layouts.len(),
}; };
let pl_id = gfx_select!(pipeline_layout_id => let _ = gfx_select!(pipeline_layout_id =>
global.device_create_pipeline_layout(device_id, &descriptor, pipeline_layout_id)); global.device_create_pipeline_layout(device_id, &descriptor, pipeline_layout_id));
let pipeline_layout = WebGPUPipelineLayout(pl_id);
if let Err(e) = sender.send(pipeline_layout) {
warn!(
"Failed to send response to WebGPURequest::CreatePipelineLayout ({})",
e
)
}
}, },
WebGPURequest::CreateSampler { WebGPURequest::CreateSampler {
device_id, device_id,
@ -427,7 +351,6 @@ impl WGPU {
global.device_create_sampler(device_id, &descriptor.map_label(|_| st.as_ptr()), sampler_id)); global.device_create_sampler(device_id, &descriptor.map_label(|_| st.as_ptr()), sampler_id));
}, },
WebGPURequest::CreateShaderModule { WebGPURequest::CreateShaderModule {
sender,
device_id, device_id,
program_id, program_id,
program, program,
@ -439,22 +362,17 @@ impl WGPU {
length: program.len(), length: program.len(),
}, },
}; };
let sm_id = gfx_select!(program_id => let _ = gfx_select!(program_id =>
global.device_create_shader_module(device_id, &descriptor, program_id)); global.device_create_shader_module(device_id, &descriptor, program_id));
let shader_module = WebGPUShaderModule(sm_id);
if let Err(e) = sender.send(shader_module) {
warn!(
"Failed to send response to WebGPURequest::CreateShaderModule ({})",
e
)
}
}, },
WebGPURequest::DestroyBuffer(buffer) => { WebGPURequest::DestroyBuffer(buffer) => {
let global = &self.global; let global = &self.global;
gfx_select!(buffer => global.buffer_destroy(buffer)); gfx_select!(buffer => global.buffer_destroy(buffer));
}, },
WebGPURequest::Exit(sender) => { WebGPURequest::Exit(sender) => {
if let Err(e) = self.script_sender.send(WebGPUMsg::Exit) {
warn!("Failed to send WebGPUMsg::Exit to script ({})", e);
}
drop(self.global); drop(self.global);
if let Err(e) = sender.send(()) { if let Err(e) = sender.send(()) {
warn!("Failed to send response to WebGPURequest::Exit ({})", e) warn!("Failed to send response to WebGPURequest::Exit ({})", e)
@ -466,31 +384,22 @@ impl WGPU {
options, options,
ids, ids,
} => { } => {
let adapter_id = if let Some(pos) = self let adapter_id = match self.global.pick_adapter(
.adapters &options,
.iter() wgpu::instance::AdapterInputs::IdSet(&ids, |id| id.backend()),
.position(|adapter| ids.contains(&adapter.0)) ) {
{ Some(id) => id,
self.adapters[pos].0 None => {
} else { if let Err(e) =
let adapter_id = match self.global.pick_adapter( sender.send(Err("Failed to get webgpu adapter".to_string()))
&options, {
wgpu::instance::AdapterInputs::IdSet(&ids, |id| id.backend()), warn!(
) { "Failed to send response to WebGPURequest::RequestAdapter ({})",
Some(id) => id, e
None => { )
if let Err(e) = }
sender.send(Err("Failed to get webgpu adapter".to_string())) return;
{ },
warn!(
"Failed to send response to WebGPURequest::RequestAdapter ({})",
e
)
}
return;
},
};
adapter_id
}; };
let adapter = WebGPUAdapter(adapter_id); let adapter = WebGPUAdapter(adapter_id);
self.adapters.push(adapter); self.adapters.push(adapter);