mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Implement mapReadAsync function of GPUBuffer
Implemented the `mapReadAsync` and fixed the `unmap` functions of `GPUBuffer`. Added `mapped` internal slot for tracking the ArrayBuffer/Promise. Added more states to the `GPUBufferState` enum.
This commit is contained in:
parent
92f5b36f49
commit
2df4d9fce4
5 changed files with 253 additions and 62 deletions
|
@ -150,6 +150,10 @@ DOMInterfaces = {
|
||||||
|
|
||||||
'GPUAdapter': {
|
'GPUAdapter': {
|
||||||
'inRealms': ['RequestDevice'],
|
'inRealms': ['RequestDevice'],
|
||||||
|
},
|
||||||
|
|
||||||
|
'GPUBuffer': {
|
||||||
|
'inRealms': ['MapReadAsync'],
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,17 +6,36 @@ use crate::dom::bindings::cell::{DomRefCell, Ref};
|
||||||
use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::{
|
use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::{
|
||||||
self, GPUBufferMethods, GPUBufferSize,
|
self, GPUBufferMethods, GPUBufferSize,
|
||||||
};
|
};
|
||||||
|
use crate::dom::bindings::error::Error;
|
||||||
|
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::DomRoot;
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
|
use crate::dom::bindings::trace::RootedTraceableBox;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::gpu::{response_async, AsyncWGPUListener};
|
||||||
|
use crate::dom::promise::Promise;
|
||||||
|
use crate::realms::InRealm;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
|
use js::jsapi::{Heap, JSObject};
|
||||||
|
use js::jsval::UndefinedValue;
|
||||||
|
use js::rust::jsapi_wrapped::{DetachArrayBuffer, IsPromiseObject, RejectPromise};
|
||||||
|
use js::rust::MutableHandle;
|
||||||
|
use js::typedarray::{ArrayBuffer, CreateWith};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use webgpu::{WebGPU, WebGPUBuffer, WebGPUDevice, WebGPURequest};
|
use std::ptr;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use webgpu::{
|
||||||
|
wgpu::resource::BufferUsage, WebGPU, WebGPUBuffer, WebGPUDevice, WebGPURequest, WebGPUResponse,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(MallocSizeOf)]
|
// https://gpuweb.github.io/gpuweb/#buffer-state
|
||||||
|
#[derive(Clone, MallocSizeOf)]
|
||||||
pub enum GPUBufferState {
|
pub enum GPUBufferState {
|
||||||
Mapped,
|
MappedForReading,
|
||||||
|
MappedForWriting,
|
||||||
|
MappedPendingForReading,
|
||||||
|
MappedPendingForWriting,
|
||||||
Unmapped,
|
Unmapped,
|
||||||
Destroyed,
|
Destroyed,
|
||||||
}
|
}
|
||||||
|
@ -24,7 +43,7 @@ pub enum GPUBufferState {
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct GPUBuffer {
|
pub struct GPUBuffer {
|
||||||
reflector_: Reflector,
|
reflector_: Reflector,
|
||||||
#[ignore_malloc_size_of = "channels are hard"]
|
#[ignore_malloc_size_of = "defined in webgpu"]
|
||||||
channel: WebGPU,
|
channel: WebGPU,
|
||||||
label: DomRefCell<Option<DOMString>>,
|
label: DomRefCell<Option<DOMString>>,
|
||||||
size: GPUBufferSize,
|
size: GPUBufferSize,
|
||||||
|
@ -33,6 +52,8 @@ pub struct GPUBuffer {
|
||||||
buffer: WebGPUBuffer,
|
buffer: WebGPUBuffer,
|
||||||
device: WebGPUDevice,
|
device: WebGPUDevice,
|
||||||
valid: Cell<bool>,
|
valid: Cell<bool>,
|
||||||
|
#[ignore_malloc_size_of = "defined in mozjs"]
|
||||||
|
mapping: RootedTraceableBox<Heap<*mut JSObject>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GPUBuffer {
|
impl GPUBuffer {
|
||||||
|
@ -44,6 +65,7 @@ impl GPUBuffer {
|
||||||
size: GPUBufferSize,
|
size: GPUBufferSize,
|
||||||
usage: u32,
|
usage: u32,
|
||||||
valid: bool,
|
valid: bool,
|
||||||
|
mapping: RootedTraceableBox<Heap<*mut JSObject>>,
|
||||||
) -> GPUBuffer {
|
) -> GPUBuffer {
|
||||||
Self {
|
Self {
|
||||||
reflector_: Reflector::new(),
|
reflector_: Reflector::new(),
|
||||||
|
@ -55,6 +77,7 @@ impl GPUBuffer {
|
||||||
valid: Cell::new(valid),
|
valid: Cell::new(valid),
|
||||||
device,
|
device,
|
||||||
buffer,
|
buffer,
|
||||||
|
mapping,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,10 +91,11 @@ impl GPUBuffer {
|
||||||
size: GPUBufferSize,
|
size: GPUBufferSize,
|
||||||
usage: u32,
|
usage: u32,
|
||||||
valid: bool,
|
valid: bool,
|
||||||
|
mapping: RootedTraceableBox<Heap<*mut JSObject>>,
|
||||||
) -> DomRoot<GPUBuffer> {
|
) -> DomRoot<GPUBuffer> {
|
||||||
reflect_dom_object(
|
reflect_dom_object(
|
||||||
Box::new(GPUBuffer::new_inherited(
|
Box::new(GPUBuffer::new_inherited(
|
||||||
channel, buffer, device, state, size, usage, valid,
|
channel, buffer, device, state, size, usage, valid, mapping,
|
||||||
)),
|
)),
|
||||||
global,
|
global,
|
||||||
GPUBufferBinding::Wrap,
|
GPUBufferBinding::Wrap,
|
||||||
|
@ -104,19 +128,59 @@ impl Drop for GPUBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GPUBufferMethods for GPUBuffer {
|
impl GPUBufferMethods for GPUBuffer {
|
||||||
|
#[allow(unsafe_code)]
|
||||||
/// https://gpuweb.github.io/gpuweb/#dom-gpubuffer-unmap
|
/// https://gpuweb.github.io/gpuweb/#dom-gpubuffer-unmap
|
||||||
fn Unmap(&self) {
|
fn Unmap(&self) {
|
||||||
self.channel
|
let cx = self.global().get_cx();
|
||||||
.0
|
// Step 1
|
||||||
.send(WebGPURequest::UnmapBuffer(self.buffer))
|
match *self.state.borrow() {
|
||||||
.unwrap();
|
GPUBufferState::Unmapped | GPUBufferState::Destroyed => {
|
||||||
|
// TODO: Record validation error on the current scope
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
GPUBufferState::MappedForWriting => {
|
||||||
|
// Step 3.1
|
||||||
|
match ArrayBuffer::from(self.mapping.get()) {
|
||||||
|
Ok(array_buffer) => {
|
||||||
|
self.channel
|
||||||
|
.0
|
||||||
|
.send(WebGPURequest::UnmapBuffer(
|
||||||
|
self.device.0,
|
||||||
|
self.id(),
|
||||||
|
array_buffer.to_vec(),
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
// Step 3.2
|
||||||
|
unsafe {
|
||||||
|
DetachArrayBuffer(*cx, self.mapping.handle());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
// Step 2
|
||||||
|
unsafe {
|
||||||
|
if IsPromiseObject(self.mapping.handle()) {
|
||||||
|
let err = Error::Abort;
|
||||||
|
rooted!(in(*cx) let mut undef = UndefinedValue());
|
||||||
|
err.to_jsval(*cx, &self.global(), undef.handle_mut());
|
||||||
|
RejectPromise(*cx, self.mapping.handle(), undef.handle());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
};
|
||||||
|
// Step 3.3
|
||||||
|
self.mapping.set(ptr::null_mut());
|
||||||
|
// Step 4
|
||||||
*self.state.borrow_mut() = GPUBufferState::Unmapped;
|
*self.state.borrow_mut() = GPUBufferState::Unmapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://gpuweb.github.io/gpuweb/#dom-gpubuffer-destroy
|
/// https://gpuweb.github.io/gpuweb/#dom-gpubuffer-destroy
|
||||||
fn Destroy(&self) {
|
fn Destroy(&self) {
|
||||||
match *self.state.borrow() {
|
let state = self.state.borrow().clone();
|
||||||
GPUBufferState::Mapped => {
|
match state {
|
||||||
|
GPUBufferState::MappedForReading | GPUBufferState::MappedForWriting => {
|
||||||
self.Unmap();
|
self.Unmap();
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
|
@ -128,6 +192,72 @@ impl GPUBufferMethods for GPUBuffer {
|
||||||
*self.state.borrow_mut() = GPUBufferState::Destroyed;
|
*self.state.borrow_mut() = GPUBufferState::Destroyed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
/// https://gpuweb.github.io/gpuweb/#dom-gpubuffer-mapreadasync
|
||||||
|
fn MapReadAsync(&self, comp: InRealm) -> Rc<Promise> {
|
||||||
|
// Step 1 & 2
|
||||||
|
let promise = Promise::new_in_current_realm(&self.global(), comp);
|
||||||
|
match *self.state.borrow() {
|
||||||
|
GPUBufferState::Unmapped => {
|
||||||
|
match BufferUsage::from_bits(self.usage) {
|
||||||
|
Some(usage) => {
|
||||||
|
if !usage.contains(BufferUsage::MAP_READ) {
|
||||||
|
// TODO: Record validation error on the current scope
|
||||||
|
promise.reject_error(Error::Abort);
|
||||||
|
return promise;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
promise.reject_error(Error::Abort);
|
||||||
|
return promise;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
promise.reject_error(Error::Abort);
|
||||||
|
return promise;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// Step 3
|
||||||
|
self.mapping.set(*promise.promise_obj());
|
||||||
|
// Step 4
|
||||||
|
*self.state.borrow_mut() = GPUBufferState::MappedPendingForReading;
|
||||||
|
|
||||||
|
// Step 5.1
|
||||||
|
if unsafe {
|
||||||
|
ArrayBuffer::create(
|
||||||
|
*self.global().get_cx(),
|
||||||
|
CreateWith::Length(self.size as u32),
|
||||||
|
MutableHandle::from_raw(self.mapping.handle_mut()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
promise.reject_error(Error::Operation);
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sender = response_async(&promise, self);
|
||||||
|
if self
|
||||||
|
.channel
|
||||||
|
.0
|
||||||
|
.send(WebGPURequest::MapReadAsync(
|
||||||
|
sender,
|
||||||
|
self.buffer.0,
|
||||||
|
self.device.0,
|
||||||
|
self.usage,
|
||||||
|
self.size,
|
||||||
|
))
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
promise.reject_error(Error::Operation);
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 6
|
||||||
|
promise
|
||||||
|
}
|
||||||
|
|
||||||
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
|
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
|
||||||
fn GetLabel(&self) -> Option<DOMString> {
|
fn GetLabel(&self) -> Option<DOMString> {
|
||||||
self.label.borrow().clone()
|
self.label.borrow().clone()
|
||||||
|
@ -138,3 +268,25 @@ impl GPUBufferMethods for GPUBuffer {
|
||||||
*self.label.borrow_mut() = value;
|
*self.label.borrow_mut() = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsyncWGPUListener for GPUBuffer {
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>) {
|
||||||
|
match response {
|
||||||
|
WebGPUResponse::MapReadAsync(bytes) => unsafe {
|
||||||
|
match ArrayBuffer::from(self.mapping.get()) {
|
||||||
|
Ok(mut array_buffer) => {
|
||||||
|
// Step 5.2
|
||||||
|
array_buffer.update(&bytes);
|
||||||
|
// Step 5.3
|
||||||
|
*self.state.borrow_mut() = GPUBufferState::MappedForReading;
|
||||||
|
// Step 5.4
|
||||||
|
promise.resolve_native(&array_buffer);
|
||||||
|
},
|
||||||
|
_ => promise.reject_error(Error::Operation),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
_ => promise.reject_error(Error::Operation),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ use webgpu::wgpu::binding_model::{
|
||||||
ShaderStage,
|
ShaderStage,
|
||||||
};
|
};
|
||||||
use webgpu::wgpu::resource::{BufferDescriptor, BufferUsage};
|
use webgpu::wgpu::resource::{BufferDescriptor, BufferUsage};
|
||||||
use webgpu::{WebGPU, WebGPUBuffer, WebGPUDevice, WebGPUQueue, WebGPURequest};
|
use webgpu::{WebGPU, WebGPUDevice, WebGPUQueue, WebGPURequest};
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct GPUDevice {
|
pub struct GPUDevice {
|
||||||
|
@ -106,38 +106,6 @@ impl GPUDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GPUDevice {
|
impl GPUDevice {
|
||||||
unsafe fn resolve_create_buffer_mapped(
|
|
||||||
&self,
|
|
||||||
cx: SafeJSContext,
|
|
||||||
gpu_buffer: WebGPUBuffer,
|
|
||||||
array_buffer: Vec<u8>,
|
|
||||||
descriptor: BufferDescriptor,
|
|
||||||
valid: bool,
|
|
||||||
) -> Vec<JSVal> {
|
|
||||||
rooted!(in(*cx) let mut js_array_buffer = ptr::null_mut::<JSObject>());
|
|
||||||
let mut out = Vec::new();
|
|
||||||
assert!(ArrayBuffer::create(
|
|
||||||
*cx,
|
|
||||||
CreateWith::Slice(array_buffer.as_slice()),
|
|
||||||
js_array_buffer.handle_mut(),
|
|
||||||
)
|
|
||||||
.is_ok());
|
|
||||||
|
|
||||||
let buff = GPUBuffer::new(
|
|
||||||
&self.global(),
|
|
||||||
self.channel.clone(),
|
|
||||||
gpu_buffer,
|
|
||||||
self.device,
|
|
||||||
GPUBufferState::Mapped,
|
|
||||||
descriptor.size,
|
|
||||||
descriptor.usage.bits(),
|
|
||||||
valid,
|
|
||||||
);
|
|
||||||
out.push(ObjectValue(buff.reflector().get_jsobject().get()));
|
|
||||||
out.push(ObjectValue(js_array_buffer.get()));
|
|
||||||
out
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate_buffer_descriptor(
|
fn validate_buffer_descriptor(
|
||||||
&self,
|
&self,
|
||||||
descriptor: &GPUBufferDescriptor,
|
descriptor: &GPUBufferDescriptor,
|
||||||
|
@ -223,6 +191,7 @@ impl GPUDeviceMethods for GPUDevice {
|
||||||
descriptor.size,
|
descriptor.size,
|
||||||
descriptor.usage,
|
descriptor.usage,
|
||||||
valid,
|
valid,
|
||||||
|
RootedTraceableBox::new(Heap::default()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,11 +214,33 @@ impl GPUDeviceMethods for GPUDevice {
|
||||||
))
|
))
|
||||||
.expect("Failed to create WebGPU buffer");
|
.expect("Failed to create WebGPU buffer");
|
||||||
|
|
||||||
let (buffer, array_buffer) = receiver.recv().unwrap();
|
rooted!(in(*cx) let mut js_array_buffer = ptr::null_mut::<JSObject>());
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.resolve_create_buffer_mapped(cx, buffer, array_buffer, wgpu_descriptor, valid)
|
assert!(ArrayBuffer::create(
|
||||||
|
*cx,
|
||||||
|
CreateWith::Length(descriptor.size as u32),
|
||||||
|
js_array_buffer.handle_mut(),
|
||||||
|
)
|
||||||
|
.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let buffer = receiver.recv().unwrap();
|
||||||
|
let buff = GPUBuffer::new(
|
||||||
|
&self.global(),
|
||||||
|
self.channel.clone(),
|
||||||
|
buffer,
|
||||||
|
self.device,
|
||||||
|
GPUBufferState::MappedForWriting,
|
||||||
|
wgpu_descriptor.size,
|
||||||
|
wgpu_descriptor.usage.bits(),
|
||||||
|
valid,
|
||||||
|
RootedTraceableBox::from_box(Heap::boxed(js_array_buffer.get())),
|
||||||
|
);
|
||||||
|
|
||||||
|
vec![
|
||||||
|
ObjectValue(buff.reflector().get_jsobject().get()),
|
||||||
|
ObjectValue(js_array_buffer.get()),
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://gpuweb.github.io/gpuweb/#GPUDevice-createBindGroupLayout
|
/// https://gpuweb.github.io/gpuweb/#GPUDevice-createBindGroupLayout
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
// 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<ArrayBuffer> mapReadAsync();
|
Promise<ArrayBuffer> mapReadAsync();
|
||||||
// Promise<ArrayBuffer> mapWriteAsync();
|
// Promise<ArrayBuffer> mapWriteAsync();
|
||||||
void unmap();
|
void unmap();
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ extern crate log;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub extern crate wgpu_core as wgpu;
|
pub extern crate wgpu_core as wgpu;
|
||||||
|
|
||||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{self, IpcReceiver, IpcSender, IpcSharedMemory};
|
||||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||||
use servo_config::pref;
|
use servo_config::pref;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
@ -16,6 +16,7 @@ use smallvec::SmallVec;
|
||||||
pub enum WebGPUResponse {
|
pub enum WebGPUResponse {
|
||||||
RequestAdapter(String, WebGPUAdapter, WebGPU),
|
RequestAdapter(String, WebGPUAdapter, WebGPU),
|
||||||
RequestDevice(WebGPUDevice, WebGPUQueue, wgpu::instance::DeviceDescriptor),
|
RequestDevice(WebGPUDevice, WebGPUQueue, wgpu::instance::DeviceDescriptor),
|
||||||
|
MapReadAsync(IpcSharedMemory),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type WebGPUResponseResult = Result<WebGPUResponse, String>;
|
pub type WebGPUResponseResult = Result<WebGPUResponse, String>;
|
||||||
|
@ -41,7 +42,7 @@ pub enum WebGPURequest {
|
||||||
wgpu::resource::BufferDescriptor,
|
wgpu::resource::BufferDescriptor,
|
||||||
),
|
),
|
||||||
CreateBufferMapped(
|
CreateBufferMapped(
|
||||||
IpcSender<(WebGPUBuffer, Vec<u8>)>,
|
IpcSender<WebGPUBuffer>,
|
||||||
WebGPUDevice,
|
WebGPUDevice,
|
||||||
wgpu::id::BufferId,
|
wgpu::id::BufferId,
|
||||||
wgpu::resource::BufferDescriptor,
|
wgpu::resource::BufferDescriptor,
|
||||||
|
@ -79,7 +80,14 @@ pub enum WebGPURequest {
|
||||||
wgpu::id::ShaderModuleId,
|
wgpu::id::ShaderModuleId,
|
||||||
Vec<u32>,
|
Vec<u32>,
|
||||||
),
|
),
|
||||||
UnmapBuffer(WebGPUBuffer),
|
MapReadAsync(
|
||||||
|
IpcSender<WebGPUResponseResult>,
|
||||||
|
wgpu::id::BufferId,
|
||||||
|
wgpu::id::DeviceId,
|
||||||
|
u32,
|
||||||
|
u64,
|
||||||
|
),
|
||||||
|
UnmapBuffer(wgpu::id::DeviceId, WebGPUBuffer, Vec<u8>),
|
||||||
DestroyBuffer(WebGPUBuffer),
|
DestroyBuffer(WebGPUBuffer),
|
||||||
CreateCommandEncoder(
|
CreateCommandEncoder(
|
||||||
IpcSender<WebGPUCommandEncoder>,
|
IpcSender<WebGPUCommandEncoder>,
|
||||||
|
@ -251,27 +259,26 @@ impl WGPU {
|
||||||
},
|
},
|
||||||
WebGPURequest::CreateBufferMapped(sender, device, id, descriptor) => {
|
WebGPURequest::CreateBufferMapped(sender, device, id, descriptor) => {
|
||||||
let global = &self.global;
|
let global = &self.global;
|
||||||
let buffer_size = descriptor.size as usize;
|
let (buffer_id, _arr_buff_ptr) = gfx_select!(id =>
|
||||||
|
|
||||||
let (buffer_id, arr_buff_ptr) = gfx_select!(id =>
|
|
||||||
global.device_create_buffer_mapped(device.0, &descriptor, id));
|
global.device_create_buffer_mapped(device.0, &descriptor, id));
|
||||||
let buffer = WebGPUBuffer(buffer_id);
|
let buffer = WebGPUBuffer(buffer_id);
|
||||||
|
|
||||||
let mut array_buffer = Vec::with_capacity(buffer_size);
|
if let Err(e) = sender.send(buffer) {
|
||||||
unsafe {
|
|
||||||
array_buffer.set_len(buffer_size);
|
|
||||||
std::ptr::copy(arr_buff_ptr, array_buffer.as_mut_ptr(), buffer_size);
|
|
||||||
};
|
|
||||||
if let Err(e) = sender.send((buffer, array_buffer)) {
|
|
||||||
warn!(
|
warn!(
|
||||||
"Failed to send response to WebGPURequest::CreateBufferMapped ({})",
|
"Failed to send response to WebGPURequest::CreateBufferMapped ({})",
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
WebGPURequest::UnmapBuffer(buffer) => {
|
WebGPURequest::UnmapBuffer(device_id, buffer, array_buffer) => {
|
||||||
let global = &self.global;
|
let global = &self.global;
|
||||||
gfx_select!(buffer.0 => global.buffer_unmap(buffer.0));
|
|
||||||
|
gfx_select!(buffer.0 => global.device_set_buffer_sub_data(
|
||||||
|
device_id,
|
||||||
|
buffer.0,
|
||||||
|
0,
|
||||||
|
array_buffer.as_slice()
|
||||||
|
));
|
||||||
},
|
},
|
||||||
WebGPURequest::DestroyBuffer(buffer) => {
|
WebGPURequest::DestroyBuffer(buffer) => {
|
||||||
let global = &self.global;
|
let global = &self.global;
|
||||||
|
@ -412,6 +419,43 @@ impl WGPU {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
WebGPURequest::MapReadAsync(sender, buffer_id, device_id, usage, size) => {
|
||||||
|
let global = &self.global;
|
||||||
|
let on_read = move |status: wgpu::resource::BufferMapAsyncStatus,
|
||||||
|
ptr: *const u8| {
|
||||||
|
match status {
|
||||||
|
wgpu::resource::BufferMapAsyncStatus::Success => {
|
||||||
|
let array_buffer =
|
||||||
|
unsafe { std::slice::from_raw_parts(ptr, size as usize) };
|
||||||
|
if let Err(e) = sender.send(Ok(WebGPUResponse::MapReadAsync(
|
||||||
|
IpcSharedMemory::from_bytes(array_buffer),
|
||||||
|
))) {
|
||||||
|
warn!(
|
||||||
|
"Failed to send response to WebGPURequest::MapReadAsync ({})",
|
||||||
|
e
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
if let Err(e) = sender
|
||||||
|
.send(Err("MapReadAsync: Failed to map buffer".to_owned()))
|
||||||
|
{
|
||||||
|
warn!(
|
||||||
|
"Failed to send response to WebGPURequest::MapReadAsync ({})",
|
||||||
|
e
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
gfx_select!(buffer_id => global.buffer_map_async(
|
||||||
|
buffer_id,
|
||||||
|
wgpu::resource::BufferUsage::from_bits(usage).unwrap(),
|
||||||
|
0..size,
|
||||||
|
wgpu::resource::BufferMapOperation::Read(Box::new(on_read))
|
||||||
|
));
|
||||||
|
gfx_select!(device_id => global.device_poll(device_id, true));
|
||||||
|
},
|
||||||
WebGPURequest::Submit(queue_id, command_buffer_ids) => {
|
WebGPURequest::Submit(queue_id, command_buffer_ids) => {
|
||||||
let global = &self.global;
|
let global = &self.global;
|
||||||
let _ = gfx_select!(queue_id => global.queue_submit(
|
let _ = gfx_select!(queue_id => global.queue_submit(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue