mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Initial implementation of WebGPU API
This commit is contained in:
parent
47e39af0f3
commit
12893aa010
30 changed files with 923 additions and 7 deletions
153
components/webgpu/lib.rs
Normal file
153
components/webgpu/lib.rs
Normal file
|
@ -0,0 +1,153 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
#[macro_use]
|
||||
extern crate serde;
|
||||
#[macro_use]
|
||||
pub extern crate wgpu_native as wgpu;
|
||||
|
||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||
use servo_config::pref;
|
||||
use wgpu::adapter_get_info;
|
||||
use wgpu::TypedId;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub enum WebGPUResponse {
|
||||
RequestAdapter(String, WebGPUAdapter),
|
||||
RequestDevice,
|
||||
}
|
||||
|
||||
pub type WebGPUResponseResult = Result<WebGPUResponse, String>;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub enum WebGPURequest {
|
||||
RequestAdapter(IpcSender<WebGPUResponseResult>, wgpu::RequestAdapterOptions),
|
||||
RequestDevice,
|
||||
Exit(IpcSender<()>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct WebGPU(pub IpcSender<WebGPURequest>);
|
||||
|
||||
impl WebGPU {
|
||||
pub fn new() -> Option<Self> {
|
||||
if !pref!(dom.webgpu.enabled) {
|
||||
return None;
|
||||
}
|
||||
let (sender, receiver) = match ipc::channel() {
|
||||
Ok(sender_and_receiver) => sender_and_receiver,
|
||||
Err(e) => {
|
||||
warn!(
|
||||
"Failed to create sender and receiciver for WGPU thread ({})",
|
||||
e
|
||||
);
|
||||
return None;
|
||||
},
|
||||
};
|
||||
|
||||
if let Err(e) = std::thread::Builder::new()
|
||||
.name("WGPU".to_owned())
|
||||
.spawn(move || {
|
||||
WGPU::new(receiver).run();
|
||||
})
|
||||
{
|
||||
warn!("Failed to spwan WGPU thread ({})", e);
|
||||
return None;
|
||||
}
|
||||
Some(WebGPU(sender))
|
||||
}
|
||||
|
||||
pub fn exit(&self, sender: IpcSender<()>) -> Result<(), &'static str> {
|
||||
self.0
|
||||
.send(WebGPURequest::Exit(sender))
|
||||
.map_err(|_| "Failed to send Exit message")
|
||||
}
|
||||
}
|
||||
|
||||
struct WGPU {
|
||||
receiver: IpcReceiver<WebGPURequest>,
|
||||
global: wgpu::Global,
|
||||
adapters: Vec<WebGPUAdapter>,
|
||||
// Track invalid adapters https://gpuweb.github.io/gpuweb/#invalid
|
||||
_invalid_adapters: Vec<WebGPUAdapter>,
|
||||
}
|
||||
|
||||
impl WGPU {
|
||||
fn new(receiver: IpcReceiver<WebGPURequest>) -> Self {
|
||||
WGPU {
|
||||
receiver,
|
||||
global: wgpu::Global::new("webgpu-native"),
|
||||
adapters: Vec::new(),
|
||||
_invalid_adapters: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn deinit(self) {
|
||||
self.global.delete()
|
||||
}
|
||||
|
||||
fn run(mut self) {
|
||||
while let Ok(msg) = self.receiver.recv() {
|
||||
match msg {
|
||||
WebGPURequest::RequestAdapter(sender, options) => {
|
||||
let adapter_id = match wgpu::request_adapter(
|
||||
&self.global,
|
||||
&options,
|
||||
// TODO: The ids we pass here should be generated by the client
|
||||
&[
|
||||
wgpu::Id::zip(0, 0, wgpu::Backend::Vulkan),
|
||||
wgpu::Id::zip(0, 0, wgpu::Backend::Metal),
|
||||
wgpu::Id::zip(0, 0, wgpu::Backend::Dx12),
|
||||
],
|
||||
) {
|
||||
Some(id) => id,
|
||||
None => {
|
||||
if let Err(e) =
|
||||
sender.send(Err("Failed to get webgpu adapter".to_string()))
|
||||
{
|
||||
warn!(
|
||||
"Failed to send response to WebGPURequest::RequestAdapter ({})",
|
||||
e
|
||||
)
|
||||
}
|
||||
return;
|
||||
},
|
||||
};
|
||||
let adapter = WebGPUAdapter(adapter_id);
|
||||
self.adapters.push(adapter);
|
||||
let info =
|
||||
gfx_select!(adapter_id => adapter_get_info(&self.global, adapter_id));
|
||||
if let Err(e) =
|
||||
sender.send(Ok(WebGPUResponse::RequestAdapter(info.name, adapter)))
|
||||
{
|
||||
warn!(
|
||||
"Failed to send response to WebGPURequest::RequestAdapter ({})",
|
||||
e
|
||||
)
|
||||
}
|
||||
},
|
||||
WebGPURequest::RequestDevice => {},
|
||||
WebGPURequest::Exit(sender) => {
|
||||
self.deinit();
|
||||
if let Err(e) = sender.send(()) {
|
||||
warn!("Failed to send response to WebGPURequest::Exit ({})", e)
|
||||
}
|
||||
return;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
pub struct WebGPUAdapter(pub wgpu::AdapterId);
|
||||
|
||||
impl MallocSizeOf for WebGPUAdapter {
|
||||
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue