mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Implement GPUBuffer.mapAsync and update wgpu-core
This commit is contained in:
parent
0afe412d63
commit
b74cea3a46
18 changed files with 514 additions and 433 deletions
59
Cargo.lock
generated
59
Cargo.lock
generated
|
@ -1865,8 +1865,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "gfx-descriptor"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bf35f5d66d1bc56e63e68d7528441453f25992bd954b84309d23c659df2c5da"
|
||||
source = "git+https://github.com/gfx-rs/gfx-extras?rev=0f7dac1b05813948fa0e5999c4fe6473f0c98f9b#0f7dac1b05813948fa0e5999c4fe6473f0c98f9b"
|
||||
dependencies = [
|
||||
"fxhash",
|
||||
"gfx-hal",
|
||||
|
@ -1886,7 +1885,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "gfx-memory"
|
||||
version = "0.1.3"
|
||||
source = "git+https://github.com/gfx-rs/gfx-extras?rev=438353c3f75368c12024ad2fc03cbeb15f351fd9#438353c3f75368c12024ad2fc03cbeb15f351fd9"
|
||||
source = "git+https://github.com/gfx-rs/gfx-extras?rev=0f7dac1b05813948fa0e5999c4fe6473f0c98f9b#0f7dac1b05813948fa0e5999c4fe6473f0c98f9b"
|
||||
dependencies = [
|
||||
"fxhash",
|
||||
"gfx-hal",
|
||||
|
@ -3527,7 +3526,7 @@ checksum = "0419348c027fa7be448d2ae7ea0e4e04c2334c31dc4e74ab29f00a2a7ca69204"
|
|||
[[package]]
|
||||
name = "naga"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/gfx-rs/naga?rev=bce6358eb1026c13d2f1c6d365af37afe8869a86#bce6358eb1026c13d2f1c6d365af37afe8869a86"
|
||||
source = "git+https://github.com/gfx-rs/naga?rev=a9228d2aed38c71388489a95817238ff98198fa3#a9228d2aed38c71388489a95817238ff98198fa3"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"fxhash",
|
||||
|
@ -3955,16 +3954,7 @@ version = "0.2.0"
|
|||
source = "git+https://github.com/servo/webrender#1175acad2d4f49fa712e105c84149ac7f394261d"
|
||||
dependencies = [
|
||||
"euclid",
|
||||
"peek-poke-derive 0.2.1 (git+https://github.com/servo/webrender)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peek-poke"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d93fd6a575ebf1ac2668d08443c97a22872cfb463fd8b7ddd141e9f6be59af2f"
|
||||
dependencies = [
|
||||
"peek-poke-derive 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"peek-poke-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3979,19 +3969,6 @@ dependencies = [
|
|||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peek-poke-derive"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fb44a25c5bba983be0fc8592dfaf3e6d0935ce8be0c6b15b2a39507af34a926"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"quote 1.0.2",
|
||||
"syn",
|
||||
"synstructure",
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peeking_take_while"
|
||||
version = "0.1.2"
|
||||
|
@ -6014,6 +5991,25 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a41f40ed0e162c911ac6fcb53ecdc8134c46905fdbbae8c50add462a538b495f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0aa83a9a47081cd522c09c81b31aec2c9273424976f922ad61c053b58350b715"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracy-rs"
|
||||
version = "0.1.1"
|
||||
|
@ -6493,7 +6489,7 @@ dependencies = [
|
|||
"derive_more",
|
||||
"euclid",
|
||||
"malloc_size_of_derive",
|
||||
"peek-poke 0.2.0 (git+https://github.com/servo/webrender)",
|
||||
"peek-poke",
|
||||
"serde",
|
||||
"serde_bytes",
|
||||
"serde_derive",
|
||||
|
@ -6566,7 +6562,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "wgpu-core"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu#fc2dd481b2713cd0eda6ffa540faeaf7418fd051"
|
||||
source = "git+https://github.com/gfx-rs/wgpu#177a0b39acde46f86fc46e3e63be16283a2da399"
|
||||
dependencies = [
|
||||
"arrayvec 0.5.1",
|
||||
"bitflags",
|
||||
|
@ -6583,11 +6579,11 @@ dependencies = [
|
|||
"log",
|
||||
"naga",
|
||||
"parking_lot 0.10.2",
|
||||
"peek-poke 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ron",
|
||||
"serde",
|
||||
"smallvec 1.3.0",
|
||||
"spirv_headers",
|
||||
"tracing",
|
||||
"vec_map",
|
||||
"wgpu-types",
|
||||
]
|
||||
|
@ -6595,10 +6591,9 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "wgpu-types"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu#fc2dd481b2713cd0eda6ffa540faeaf7418fd051"
|
||||
source = "git+https://github.com/gfx-rs/wgpu#177a0b39acde46f86fc46e3e63be16283a2da399"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"peek-poke 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde",
|
||||
]
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ DOMInterfaces = {
|
|||
},
|
||||
|
||||
'GPUBuffer': {
|
||||
'inRealms': ['MapReadAsync'],
|
||||
'inRealms': ['MapAsync'],
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -165,10 +165,11 @@ use tendril::{StrTendril, TendrilSink};
|
|||
use time::{Duration, Timespec, Tm};
|
||||
use uuid::Uuid;
|
||||
use webgpu::{
|
||||
wgpu::command::RawPass, wgpu::id, WebGPU, WebGPUAdapter, WebGPUBindGroup,
|
||||
WebGPUBindGroupLayout, WebGPUBuffer, WebGPUCommandBuffer, WebGPUCommandEncoder,
|
||||
WebGPUComputePipeline, WebGPUDevice, WebGPUPipelineLayout, WebGPUQueue, WebGPURenderPipeline,
|
||||
WebGPUSampler, WebGPUShaderModule, WebGPUTexture, WebGPUTextureView,
|
||||
wgpu::command::{ComputePass, RenderPass},
|
||||
WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout, WebGPUBuffer,
|
||||
WebGPUCommandBuffer, WebGPUCommandEncoder, WebGPUComputePipeline, WebGPUDevice,
|
||||
WebGPUPipelineLayout, WebGPUQueue, WebGPURenderPipeline, WebGPUSampler, WebGPUShaderModule,
|
||||
WebGPUTexture, WebGPUTextureView,
|
||||
};
|
||||
use webrender_api::{DocumentId, ExternalImageId, ImageKey};
|
||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||
|
@ -581,7 +582,8 @@ unsafe_no_jsmanaged_fields!(WebGPUContextId);
|
|||
unsafe_no_jsmanaged_fields!(WebGPUCommandBuffer);
|
||||
unsafe_no_jsmanaged_fields!(WebGPUCommandEncoder);
|
||||
unsafe_no_jsmanaged_fields!(WebGPUDevice);
|
||||
unsafe_no_jsmanaged_fields!(Option<RawPass<id::CommandEncoderId>>);
|
||||
unsafe_no_jsmanaged_fields!(Option<RenderPass>);
|
||||
unsafe_no_jsmanaged_fields!(Option<ComputePass>);
|
||||
unsafe_no_jsmanaged_fields!(GPUBufferState);
|
||||
unsafe_no_jsmanaged_fields!(GPUCommandEncoderState);
|
||||
unsafe_no_jsmanaged_fields!(WebXRSwapChainId);
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::dom::bindings::cell::{DomRefCell, Ref};
|
||||
use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::{GPUBufferMethods, GPUSize64};
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::GPUMapModeBinding::GPUMapModeConstants;
|
||||
use crate::dom::bindings::error::Error;
|
||||
use crate::dom::bindings::reflector::DomObject;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
||||
|
@ -11,22 +12,28 @@ use crate::dom::bindings::root::DomRoot;
|
|||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::bindings::trace::RootedTraceableBox;
|
||||
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 js::jsapi::{Heap, JSObject};
|
||||
use js::jsval::UndefinedValue;
|
||||
use js::rust::jsapi_wrapped::{DetachArrayBuffer, IsPromiseObject, RejectPromise};
|
||||
use js::typedarray::ArrayBuffer;
|
||||
use js::rust::MutableHandle;
|
||||
use js::typedarray::{ArrayBuffer, CreateWith};
|
||||
use std::cell::Cell;
|
||||
use std::ptr;
|
||||
use webgpu::{WebGPU, WebGPUBuffer, WebGPUDevice, WebGPURequest};
|
||||
use std::rc::Rc;
|
||||
use webgpu::{
|
||||
wgpu::device::HostMap, WebGPU, WebGPUBuffer, WebGPUDevice, WebGPURequest, WebGPUResponse,
|
||||
};
|
||||
|
||||
// https://gpuweb.github.io/gpuweb/#buffer-state
|
||||
#[derive(Clone, MallocSizeOf)]
|
||||
#[derive(Clone, Copy, MallocSizeOf, PartialEq)]
|
||||
pub enum GPUBufferState {
|
||||
MappedForReading,
|
||||
MappedForWriting,
|
||||
MappedPendingForReading,
|
||||
MappedPendingForWriting,
|
||||
Mapped,
|
||||
MappedAtCreation,
|
||||
MappingPending,
|
||||
Unmapped,
|
||||
Destroyed,
|
||||
}
|
||||
|
@ -37,14 +44,15 @@ pub struct GPUBuffer {
|
|||
#[ignore_malloc_size_of = "defined in webgpu"]
|
||||
channel: WebGPU,
|
||||
label: DomRefCell<Option<DOMString>>,
|
||||
size: GPUSize64,
|
||||
usage: u32,
|
||||
state: DomRefCell<GPUBufferState>,
|
||||
state: Cell<GPUBufferState>,
|
||||
buffer: WebGPUBuffer,
|
||||
device: WebGPUDevice,
|
||||
valid: Cell<bool>,
|
||||
#[ignore_malloc_size_of = "defined in mozjs"]
|
||||
mapping: RootedTraceableBox<Heap<*mut JSObject>>,
|
||||
mapping_range: (u64, u64),
|
||||
size: u64,
|
||||
map_mode: Cell<Option<u32>>,
|
||||
}
|
||||
|
||||
impl GPUBuffer {
|
||||
|
@ -53,22 +61,23 @@ impl GPUBuffer {
|
|||
buffer: WebGPUBuffer,
|
||||
device: WebGPUDevice,
|
||||
state: GPUBufferState,
|
||||
size: GPUSize64,
|
||||
usage: u32,
|
||||
size: u64,
|
||||
valid: bool,
|
||||
mapping: RootedTraceableBox<Heap<*mut JSObject>>,
|
||||
mapping_range: (u64, u64),
|
||||
) -> Self {
|
||||
Self {
|
||||
reflector_: Reflector::new(),
|
||||
channel,
|
||||
label: DomRefCell::new(None),
|
||||
state: DomRefCell::new(state),
|
||||
size: size,
|
||||
usage: usage,
|
||||
state: Cell::new(state),
|
||||
valid: Cell::new(valid),
|
||||
device,
|
||||
buffer,
|
||||
mapping,
|
||||
size,
|
||||
mapping_range,
|
||||
map_mode: Cell::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,14 +88,21 @@ impl GPUBuffer {
|
|||
buffer: WebGPUBuffer,
|
||||
device: WebGPUDevice,
|
||||
state: GPUBufferState,
|
||||
size: GPUSize64,
|
||||
usage: u32,
|
||||
size: u64,
|
||||
valid: bool,
|
||||
mapping: RootedTraceableBox<Heap<*mut JSObject>>,
|
||||
mapping_range: (u64, u64),
|
||||
) -> DomRoot<Self> {
|
||||
reflect_dom_object(
|
||||
Box::new(GPUBuffer::new_inherited(
|
||||
channel, buffer, device, state, size, usage, valid, mapping,
|
||||
channel,
|
||||
buffer,
|
||||
device,
|
||||
state,
|
||||
size,
|
||||
valid,
|
||||
mapping,
|
||||
mapping_range,
|
||||
)),
|
||||
global,
|
||||
)
|
||||
|
@ -98,16 +114,8 @@ impl GPUBuffer {
|
|||
self.buffer
|
||||
}
|
||||
|
||||
pub fn size(&self) -> GPUSize64 {
|
||||
self.size
|
||||
}
|
||||
|
||||
pub fn usage(&self) -> u32 {
|
||||
self.usage
|
||||
}
|
||||
|
||||
pub fn state(&self) -> Ref<GPUBufferState> {
|
||||
self.state.borrow()
|
||||
pub fn state(&self) -> GPUBufferState {
|
||||
self.state.get()
|
||||
}
|
||||
|
||||
pub fn is_valid(&self) -> bool {
|
||||
|
@ -127,54 +135,64 @@ impl GPUBufferMethods for GPUBuffer {
|
|||
fn Unmap(&self) {
|
||||
let cx = self.global().get_cx();
|
||||
// Step 1
|
||||
match *self.state.borrow() {
|
||||
match self.state.get() {
|
||||
GPUBufferState::Unmapped | GPUBufferState::Destroyed => {
|
||||
// TODO: Record validation error on the current scope
|
||||
return;
|
||||
},
|
||||
GPUBufferState::MappedForWriting => {
|
||||
// Step 3.1
|
||||
// Step 3
|
||||
GPUBufferState::Mapped | GPUBufferState::MappedAtCreation => {
|
||||
match ArrayBuffer::from(self.mapping.get()) {
|
||||
Ok(array_buffer) => {
|
||||
self.channel
|
||||
.0
|
||||
.send(WebGPURequest::UnmapBuffer {
|
||||
device_id: self.device.0,
|
||||
buffer_id: self.id().0,
|
||||
array_buffer: array_buffer.to_vec(),
|
||||
})
|
||||
.unwrap();
|
||||
// Step 3.2
|
||||
if Some(GPUMapModeConstants::READ) != self.map_mode.get() {
|
||||
self.channel
|
||||
.0
|
||||
.send(WebGPURequest::UnmapBuffer {
|
||||
device_id: self.device.0,
|
||||
buffer_id: self.id().0,
|
||||
array_buffer: array_buffer.to_vec(),
|
||||
mapped_at_creation: self.map_mode.get() == None,
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
// Step 3.3
|
||||
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());
|
||||
};
|
||||
}
|
||||
Err(_) => {
|
||||
warn!(
|
||||
"Could not find ArrayBuffer of Mapped buffer ({:?})",
|
||||
self.buffer.0
|
||||
);
|
||||
},
|
||||
};
|
||||
},
|
||||
_ => {},
|
||||
// Step 2
|
||||
GPUBufferState::MappingPending => unsafe {
|
||||
if IsPromiseObject(self.mapping.handle()) {
|
||||
let err = Error::Operation;
|
||||
rooted!(in(*cx) let mut undef = UndefinedValue());
|
||||
err.to_jsval(*cx, &self.global(), undef.handle_mut());
|
||||
RejectPromise(*cx, self.mapping.handle(), undef.handle());
|
||||
} else {
|
||||
warn!("No promise object for pending mapping found");
|
||||
}
|
||||
},
|
||||
};
|
||||
// Step 3.3
|
||||
self.mapping.set(ptr::null_mut());
|
||||
// Step 4
|
||||
*self.state.borrow_mut() = GPUBufferState::Unmapped;
|
||||
self.state.set(GPUBufferState::Unmapped);
|
||||
self.map_mode.set(None);
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpubuffer-destroy
|
||||
fn Destroy(&self) {
|
||||
let state = self.state.borrow().clone();
|
||||
let state = self.state.get();
|
||||
match state {
|
||||
GPUBufferState::MappedForReading | GPUBufferState::MappedForWriting => {
|
||||
GPUBufferState::Mapped | GPUBufferState::MappedAtCreation => {
|
||||
self.Unmap();
|
||||
},
|
||||
_ => {},
|
||||
|
@ -189,7 +207,56 @@ impl GPUBufferMethods for GPUBuffer {
|
|||
self.buffer.0, e
|
||||
);
|
||||
};
|
||||
*self.state.borrow_mut() = GPUBufferState::Destroyed;
|
||||
self.state.set(GPUBufferState::Destroyed);
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpubuffer-mapasync-offset-size
|
||||
fn MapAsync(&self, mode: u32, offset: u64, size: u64, comp: InRealm) -> Rc<Promise> {
|
||||
let promise = Promise::new_in_current_realm(&self.global(), comp);
|
||||
let map_range = if size == 0 {
|
||||
offset..self.size
|
||||
} else {
|
||||
offset..size
|
||||
};
|
||||
let host_map = match mode {
|
||||
GPUMapModeConstants::READ => {
|
||||
self.map_mode.set(Some(mode));
|
||||
HostMap::Read
|
||||
},
|
||||
GPUMapModeConstants::WRITE => {
|
||||
self.map_mode.set(Some(mode));
|
||||
HostMap::Write
|
||||
},
|
||||
_ => {
|
||||
promise.reject_error(Error::Abort);
|
||||
return promise;
|
||||
},
|
||||
};
|
||||
if self.state.get() != GPUBufferState::Unmapped {
|
||||
promise.reject_error(Error::Abort);
|
||||
return promise;
|
||||
}
|
||||
self.mapping.set(*promise.promise_obj());
|
||||
self.state.set(GPUBufferState::MappingPending);
|
||||
|
||||
let sender = response_async(&promise, self);
|
||||
|
||||
if let Err(e) = self.channel.0.send(WebGPURequest::BufferMapAsync {
|
||||
sender,
|
||||
buffer_id: self.buffer.0,
|
||||
host_map,
|
||||
map_range,
|
||||
}) {
|
||||
warn!(
|
||||
"Failed to send BufferMapAsync ({:?}) ({})",
|
||||
self.buffer.0, e
|
||||
);
|
||||
promise.reject_error(Error::Operation);
|
||||
return promise;
|
||||
}
|
||||
|
||||
promise
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
|
||||
|
@ -202,3 +269,40 @@ impl GPUBufferMethods for GPUBuffer {
|
|||
*self.label.borrow_mut() = value;
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncWGPUListener for GPUBuffer {
|
||||
#[allow(unsafe_code)]
|
||||
fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>) {
|
||||
match response {
|
||||
WebGPUResponse::BufferMapAsync(bytes) => {
|
||||
if unsafe {
|
||||
ArrayBuffer::create(
|
||||
*self.global().get_cx(),
|
||||
CreateWith::Slice(&bytes),
|
||||
MutableHandle::from_raw(self.mapping.handle_mut()),
|
||||
)
|
||||
}
|
||||
.is_err()
|
||||
{
|
||||
promise.reject_error(Error::Operation);
|
||||
}
|
||||
self.state.set(GPUBufferState::Mapped);
|
||||
promise.resolve_native(&());
|
||||
},
|
||||
_ => {
|
||||
warn!("Wrong WebGPUResponse received");
|
||||
promise.reject_error(Error::Operation);
|
||||
},
|
||||
}
|
||||
if let Err(e) = self
|
||||
.channel
|
||||
.0
|
||||
.send(WebGPURequest::BufferMapComplete(self.buffer.0))
|
||||
{
|
||||
warn!(
|
||||
"Failed to send BufferMapComplete({:?}) ({})",
|
||||
self.buffer.0, e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,13 +24,10 @@ use dom_struct::dom_struct;
|
|||
use std::cell::Cell;
|
||||
use std::collections::HashSet;
|
||||
use webgpu::wgpu::command::{
|
||||
RawPass, RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor,
|
||||
RenderPassDescriptor,
|
||||
ColorAttachmentDescriptor, DepthStencilAttachmentDescriptor, RenderPass, RenderPassDescriptor,
|
||||
};
|
||||
use webgpu::{self, wgt, WebGPU, WebGPUDevice, WebGPURequest};
|
||||
|
||||
const BUFFER_COPY_ALIGN_MASK: u64 = 3;
|
||||
|
||||
// https://gpuweb.github.io/gpuweb/#enumdef-encoder-state
|
||||
#[derive(MallocSizeOf, PartialEq)]
|
||||
pub enum GPUCommandEncoderState {
|
||||
|
@ -126,7 +123,6 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
|
|||
GPUComputePassEncoder::new(&self.global(), self.channel.clone(), &self)
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-beginrenderpass
|
||||
fn BeginRenderPass(
|
||||
&self,
|
||||
|
@ -141,7 +137,7 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
|
|||
.colorAttachments
|
||||
.iter()
|
||||
.map(|color| {
|
||||
let (load_op, clear_color) = match color.loadValue {
|
||||
let (load_op, clear_value) = match color.loadValue {
|
||||
GPUColorLoad::GPULoadOp(_) => (wgt::LoadOp::Load, wgt::Color::TRANSPARENT),
|
||||
GPUColorLoad::DoubleSequence(ref s) => (
|
||||
wgt::LoadOp::Clear,
|
||||
|
@ -162,15 +158,19 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
|
|||
},
|
||||
),
|
||||
};
|
||||
RenderPassColorAttachmentDescriptor {
|
||||
attachment: color.attachment.id().0,
|
||||
resolve_target: color.resolveTarget.as_ref().map(|t| t.id().0),
|
||||
let channel = wgt::PassChannel {
|
||||
load_op,
|
||||
store_op: match color.storeOp {
|
||||
GPUStoreOp::Store => wgt::StoreOp::Store,
|
||||
GPUStoreOp::Clear => wgt::StoreOp::Clear,
|
||||
},
|
||||
clear_color,
|
||||
clear_value,
|
||||
read_only: false,
|
||||
};
|
||||
ColorAttachmentDescriptor {
|
||||
attachment: color.attachment.id().0,
|
||||
resolve_target: color.resolveTarget.as_ref().map(|t| t.id().0),
|
||||
channel,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
@ -184,34 +184,39 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
|
|||
GPUStencilLoadValue::GPULoadOp(_) => (wgt::LoadOp::Load, 0u32),
|
||||
GPUStencilLoadValue::RangeEnforcedUnsignedLong(l) => (wgt::LoadOp::Clear, l),
|
||||
};
|
||||
RenderPassDepthStencilAttachmentDescriptor {
|
||||
let depth_channel = wgt::PassChannel {
|
||||
load_op: depth_load_op,
|
||||
store_op: match depth.depthStoreOp {
|
||||
GPUStoreOp::Store => wgt::StoreOp::Store,
|
||||
GPUStoreOp::Clear => wgt::StoreOp::Clear,
|
||||
},
|
||||
clear_value: clear_depth,
|
||||
read_only: depth.depthReadOnly,
|
||||
};
|
||||
let stencil_channel = wgt::PassChannel {
|
||||
load_op: stencil_load_op,
|
||||
store_op: match depth.stencilStoreOp {
|
||||
GPUStoreOp::Store => wgt::StoreOp::Store,
|
||||
GPUStoreOp::Clear => wgt::StoreOp::Clear,
|
||||
},
|
||||
clear_value: clear_stencil,
|
||||
read_only: depth.stencilReadOnly,
|
||||
};
|
||||
DepthStencilAttachmentDescriptor {
|
||||
attachment: depth.attachment.id().0,
|
||||
depth_load_op,
|
||||
depth_store_op: match depth.depthStoreOp {
|
||||
GPUStoreOp::Store => wgt::StoreOp::Store,
|
||||
GPUStoreOp::Clear => wgt::StoreOp::Clear,
|
||||
},
|
||||
clear_depth,
|
||||
depth_read_only: depth.depthReadOnly,
|
||||
stencil_load_op,
|
||||
stencil_store_op: match depth.stencilStoreOp {
|
||||
GPUStoreOp::Store => wgt::StoreOp::Store,
|
||||
GPUStoreOp::Clear => wgt::StoreOp::Clear,
|
||||
},
|
||||
clear_stencil,
|
||||
stencil_read_only: depth.stencilReadOnly,
|
||||
depth: depth_channel,
|
||||
stencil: stencil_channel,
|
||||
}
|
||||
});
|
||||
|
||||
let desc = RenderPassDescriptor {
|
||||
color_attachments: colors.as_ptr(),
|
||||
color_attachments_length: colors.len(),
|
||||
color_attachments: colors.as_slice(),
|
||||
depth_stencil_attachment: depth_stencil.as_ref(),
|
||||
};
|
||||
|
||||
let raw_pass = unsafe { RawPass::new_render(self.id().0, &desc) };
|
||||
let render_pass = RenderPass::new(self.encoder.0, desc);
|
||||
|
||||
GPURenderPassEncoder::new(&self.global(), self.channel.clone(), raw_pass, &self)
|
||||
GPURenderPassEncoder::new(&self.global(), self.channel.clone(), render_pass, &self)
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-copybuffertobuffer
|
||||
|
@ -223,36 +228,9 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
|
|||
destination_offset: GPUSize64,
|
||||
size: GPUSize64,
|
||||
) {
|
||||
let mut valid = match source_offset.checked_add(size) {
|
||||
Some(_) => true,
|
||||
None => false,
|
||||
};
|
||||
valid &= match destination_offset.checked_add(size) {
|
||||
Some(_) => true,
|
||||
None => false,
|
||||
};
|
||||
valid &= match wgt::BufferUsage::from_bits(source.usage()) {
|
||||
Some(usage) => usage.contains(wgt::BufferUsage::COPY_SRC),
|
||||
None => false,
|
||||
};
|
||||
valid &= match wgt::BufferUsage::from_bits(destination.usage()) {
|
||||
Some(usage) => usage.contains(wgt::BufferUsage::COPY_DST),
|
||||
None => false,
|
||||
};
|
||||
valid &= (*self.state.borrow() == GPUCommandEncoderState::Open) &&
|
||||
source.is_valid() &&
|
||||
destination.is_valid() &
|
||||
!(size & BUFFER_COPY_ALIGN_MASK == 0) &
|
||||
!(source_offset & BUFFER_COPY_ALIGN_MASK == 0) &
|
||||
!(destination_offset & BUFFER_COPY_ALIGN_MASK == 0) &
|
||||
(source.size() >= source_offset + size) &
|
||||
(destination.size() >= destination_offset + size);
|
||||
|
||||
if source.id().0 == destination.id().0 {
|
||||
//TODO: maybe forbid this case based on https://github.com/gpuweb/gpuweb/issues/783
|
||||
valid &= source_offset > destination_offset + size ||
|
||||
source_offset + size < destination_offset;
|
||||
}
|
||||
let valid = source.is_valid() &&
|
||||
destination.is_valid() &&
|
||||
*self.state.borrow() == GPUCommandEncoderState::Open;
|
||||
|
||||
if !valid {
|
||||
// TODO: Record an error in the current scope.
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#![allow(unsafe_code)]
|
||||
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::GPUComputePassEncoderBinding::GPUComputePassEncoderMethods;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
||||
|
@ -11,18 +9,12 @@ use crate::dom::bindings::root::{Dom, DomRoot};
|
|||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::gpubindgroup::GPUBindGroup;
|
||||
use crate::dom::gpubuffer::GPUBuffer;
|
||||
use crate::dom::gpucommandencoder::{GPUCommandEncoder, GPUCommandEncoderState};
|
||||
use crate::dom::gpucomputepipeline::GPUComputePipeline;
|
||||
use dom_struct::dom_struct;
|
||||
use webgpu::{
|
||||
wgpu::command::{
|
||||
compute_ffi::{
|
||||
wgpu_compute_pass_dispatch, wgpu_compute_pass_set_bind_group,
|
||||
wgpu_compute_pass_set_pipeline,
|
||||
},
|
||||
RawPass,
|
||||
},
|
||||
wgpu::id,
|
||||
wgpu::command::{compute_ffi as wgpu_comp, ComputePass},
|
||||
WebGPU, WebGPURequest,
|
||||
};
|
||||
|
||||
|
@ -33,7 +25,7 @@ pub struct GPUComputePassEncoder {
|
|||
channel: WebGPU,
|
||||
label: DomRefCell<Option<DOMString>>,
|
||||
#[ignore_malloc_size_of = "defined in wgpu-core"]
|
||||
raw_pass: DomRefCell<Option<RawPass<id::CommandEncoderId>>>,
|
||||
compute_pass: DomRefCell<Option<ComputePass>>,
|
||||
command_encoder: Dom<GPUCommandEncoder>,
|
||||
}
|
||||
|
||||
|
@ -43,7 +35,7 @@ impl GPUComputePassEncoder {
|
|||
channel,
|
||||
reflector_: Reflector::new(),
|
||||
label: DomRefCell::new(None),
|
||||
raw_pass: DomRefCell::new(Some(unsafe { RawPass::new_compute(parent.id().0) })),
|
||||
compute_pass: DomRefCell::new(Some(ComputePass::new(parent.id().0))),
|
||||
command_encoder: Dom::from_ref(parent),
|
||||
}
|
||||
}
|
||||
|
@ -69,21 +61,30 @@ impl GPUComputePassEncoderMethods for GPUComputePassEncoder {
|
|||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpucomputepassencoder-dispatch
|
||||
fn Dispatch(&self, x: u32, y: u32, z: u32) {
|
||||
if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() {
|
||||
unsafe { wgpu_compute_pass_dispatch(raw_pass, x, y, z) };
|
||||
if let Some(compute_pass) = self.compute_pass.borrow_mut().as_mut() {
|
||||
wgpu_comp::wgpu_compute_pass_dispatch(compute_pass, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpucomputepassencoder-dispatchindirect
|
||||
fn DispatchIndirect(&self, indirect_buffer: &GPUBuffer, indirect_offset: u64) {
|
||||
if let Some(compute_pass) = self.compute_pass.borrow_mut().as_mut() {
|
||||
wgpu_comp::wgpu_compute_pass_dispatch_indirect(
|
||||
compute_pass,
|
||||
indirect_buffer.id().0,
|
||||
indirect_offset,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-endpass
|
||||
fn EndPass(&self) {
|
||||
if let Some(raw_pass) = self.raw_pass.borrow_mut().take() {
|
||||
let (pass_data, command_encoder_id) = unsafe { raw_pass.finish_compute() };
|
||||
|
||||
if let Some(compute_pass) = self.compute_pass.borrow_mut().take() {
|
||||
self.channel
|
||||
.0
|
||||
.send(WebGPURequest::RunComputePass {
|
||||
command_encoder_id,
|
||||
pass_data,
|
||||
command_encoder_id: self.command_encoder.id().0,
|
||||
compute_pass,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
|
@ -95,11 +96,12 @@ impl GPUComputePassEncoderMethods for GPUComputePassEncoder {
|
|||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpuprogrammablepassencoder-setbindgroup
|
||||
#[allow(unsafe_code)]
|
||||
fn SetBindGroup(&self, index: u32, bind_group: &GPUBindGroup, dynamic_offsets: Vec<u32>) {
|
||||
if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() {
|
||||
if let Some(compute_pass) = self.compute_pass.borrow_mut().as_mut() {
|
||||
unsafe {
|
||||
wgpu_compute_pass_set_bind_group(
|
||||
raw_pass,
|
||||
wgpu_comp::wgpu_compute_pass_set_bind_group(
|
||||
compute_pass,
|
||||
index,
|
||||
bind_group.id().0,
|
||||
dynamic_offsets.as_ptr(),
|
||||
|
@ -111,8 +113,8 @@ impl GPUComputePassEncoderMethods for GPUComputePassEncoder {
|
|||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpucomputepassencoder-setpipeline
|
||||
fn SetPipeline(&self, pipeline: &GPUComputePipeline) {
|
||||
if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() {
|
||||
unsafe { wgpu_compute_pass_set_pipeline(raw_pass, pipeline.id().0) };
|
||||
if let Some(compute_pass) = self.compute_pass.borrow_mut().as_mut() {
|
||||
wgpu_comp::wgpu_compute_pass_set_pipeline(compute_pass, pipeline.id().0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,10 +54,9 @@ use crate::script_runtime::JSContext as SafeJSContext;
|
|||
use arrayvec::ArrayVec;
|
||||
use dom_struct::dom_struct;
|
||||
use js::jsapi::{Heap, JSObject};
|
||||
use js::jsval::{JSVal, ObjectValue};
|
||||
use js::rust::MutableHandle;
|
||||
use js::typedarray::{ArrayBuffer, CreateWith};
|
||||
use std::num::NonZeroU64;
|
||||
use std::ptr::{self, NonNull};
|
||||
use std::ptr::NonNull;
|
||||
use webgpu::wgpu::binding_model::BufferBinding;
|
||||
use webgpu::{self, wgt, WebGPU, WebGPUBindings, WebGPURequest};
|
||||
|
||||
|
@ -120,38 +119,6 @@ impl GPUDevice {
|
|||
pub fn id(&self) -> webgpu::WebGPUDevice {
|
||||
self.device
|
||||
}
|
||||
|
||||
fn validate_buffer_descriptor(
|
||||
&self,
|
||||
descriptor: &GPUBufferDescriptor,
|
||||
mapped_at_creation: bool,
|
||||
) -> (bool, wgt::BufferDescriptor<std::string::String>) {
|
||||
// TODO: Record a validation error in the current scope if the descriptor is invalid.
|
||||
let wgpu_usage = wgt::BufferUsage::from_bits(descriptor.usage);
|
||||
let valid = wgpu_usage.is_some() && descriptor.size > 0;
|
||||
|
||||
if valid {
|
||||
(
|
||||
true,
|
||||
wgt::BufferDescriptor {
|
||||
size: descriptor.size,
|
||||
usage: wgpu_usage.unwrap(),
|
||||
mapped_at_creation,
|
||||
label: Default::default(),
|
||||
},
|
||||
)
|
||||
} else {
|
||||
(
|
||||
false,
|
||||
wgt::BufferDescriptor {
|
||||
size: 0,
|
||||
usage: wgt::BufferUsage::empty(),
|
||||
mapped_at_creation,
|
||||
label: Default::default(),
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GPUDeviceMethods for GPUDevice {
|
||||
|
@ -187,7 +154,15 @@ impl GPUDeviceMethods for GPUDevice {
|
|||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbuffer
|
||||
fn CreateBuffer(&self, descriptor: &GPUBufferDescriptor) -> DomRoot<GPUBuffer> {
|
||||
let (valid, wgpu_descriptor) = self.validate_buffer_descriptor(descriptor, false);
|
||||
let wgpu_descriptor = wgt::BufferDescriptor {
|
||||
label: Default::default(),
|
||||
size: descriptor.size,
|
||||
usage: match wgt::BufferUsage::from_bits(descriptor.usage) {
|
||||
Some(u) => u,
|
||||
None => wgt::BufferUsage::empty(),
|
||||
},
|
||||
mapped_at_creation: descriptor.mappedAtCreation,
|
||||
};
|
||||
let id = self
|
||||
.global()
|
||||
.wgpu_id_hub()
|
||||
|
@ -203,70 +178,38 @@ impl GPUDeviceMethods for GPUDevice {
|
|||
.expect("Failed to create WebGPU buffer");
|
||||
|
||||
let buffer = webgpu::WebGPUBuffer(id);
|
||||
let mapping = RootedTraceableBox::new(Heap::default());
|
||||
let state;
|
||||
let mapping_range;
|
||||
if descriptor.mappedAtCreation {
|
||||
unsafe {
|
||||
assert!(ArrayBuffer::create(
|
||||
*self.global().get_cx(),
|
||||
CreateWith::Length(descriptor.size as u32),
|
||||
MutableHandle::from_raw(mapping.handle_mut()),
|
||||
)
|
||||
.is_ok());
|
||||
}
|
||||
state = GPUBufferState::MappedAtCreation;
|
||||
mapping_range = (0, descriptor.size);
|
||||
} else {
|
||||
state = GPUBufferState::Unmapped;
|
||||
mapping_range = (0, 0);
|
||||
}
|
||||
|
||||
GPUBuffer::new(
|
||||
&self.global(),
|
||||
self.channel.clone(),
|
||||
buffer,
|
||||
self.device,
|
||||
GPUBufferState::Unmapped,
|
||||
state,
|
||||
descriptor.size,
|
||||
descriptor.usage,
|
||||
valid,
|
||||
RootedTraceableBox::new(Heap::default()),
|
||||
true,
|
||||
mapping,
|
||||
mapping_range,
|
||||
)
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbuffermapped
|
||||
fn CreateBufferMapped(
|
||||
&self,
|
||||
cx: SafeJSContext,
|
||||
descriptor: &GPUBufferDescriptor,
|
||||
) -> Vec<JSVal> {
|
||||
let (valid, wgpu_descriptor) = self.validate_buffer_descriptor(descriptor, true);
|
||||
let buffer_id = self
|
||||
.global()
|
||||
.wgpu_id_hub()
|
||||
.lock()
|
||||
.create_buffer_id(self.device.0.backend());
|
||||
self.channel
|
||||
.0
|
||||
.send(WebGPURequest::CreateBuffer {
|
||||
device_id: self.device.0,
|
||||
buffer_id,
|
||||
descriptor: wgpu_descriptor.clone(),
|
||||
})
|
||||
.expect("Failed to create WebGPU buffer");
|
||||
|
||||
rooted!(in(*cx) let mut js_array_buffer = ptr::null_mut::<JSObject>());
|
||||
unsafe {
|
||||
assert!(ArrayBuffer::create(
|
||||
*cx,
|
||||
CreateWith::Length(descriptor.size as u32),
|
||||
js_array_buffer.handle_mut(),
|
||||
)
|
||||
.is_ok());
|
||||
}
|
||||
|
||||
let buffer = webgpu::WebGPUBuffer(buffer_id);
|
||||
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
|
||||
#[allow(non_snake_case)]
|
||||
fn CreateBindGroupLayout(
|
||||
|
@ -284,28 +227,16 @@ impl GPUDeviceMethods for GPUDevice {
|
|||
let ty = match bind.type_ {
|
||||
GPUBindingType::Uniform_buffer => wgt::BindingType::UniformBuffer {
|
||||
dynamic: bind.hasDynamicOffset,
|
||||
min_binding_size: if bind.minBufferBindingSize == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(NonZeroU64::new(bind.minBufferBindingSize).unwrap())
|
||||
},
|
||||
min_binding_size: wgt::BufferSize::new(bind.minBufferBindingSize),
|
||||
},
|
||||
GPUBindingType::Storage_buffer => wgt::BindingType::StorageBuffer {
|
||||
dynamic: bind.hasDynamicOffset,
|
||||
min_binding_size: if bind.minBufferBindingSize == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(NonZeroU64::new(bind.minBufferBindingSize).unwrap())
|
||||
},
|
||||
min_binding_size: wgt::BufferSize::new(bind.minBufferBindingSize),
|
||||
readonly: false,
|
||||
},
|
||||
GPUBindingType::Readonly_storage_buffer => wgt::BindingType::StorageBuffer {
|
||||
dynamic: bind.hasDynamicOffset,
|
||||
min_binding_size: if bind.minBufferBindingSize == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(NonZeroU64::new(bind.minBufferBindingSize).unwrap())
|
||||
},
|
||||
min_binding_size: wgt::BufferSize::new(bind.minBufferBindingSize),
|
||||
readonly: true,
|
||||
},
|
||||
GPUBindingType::Sampled_texture => wgt::BindingType::SampledTexture {
|
||||
|
@ -433,11 +364,7 @@ impl GPUDeviceMethods for GPUDevice {
|
|||
WebGPUBindings::Buffer(BufferBinding {
|
||||
buffer_id: b.buffer.id().0,
|
||||
offset: b.offset,
|
||||
size: if let Some(s) = b.size {
|
||||
wgt::BufferSize(s)
|
||||
} else {
|
||||
wgt::BufferSize::WHOLE
|
||||
},
|
||||
size: wgt::BufferSize::new(b.size.unwrap_or(0)),
|
||||
})
|
||||
},
|
||||
},
|
||||
|
|
11
components/script/dom/gpumapmode.rs
Normal file
11
components/script/dom/gpumapmode.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::dom::bindings::reflector::Reflector;
|
||||
use dom_struct::dom_struct;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct GPUMapMode {
|
||||
reflector_: Reflector,
|
||||
}
|
|
@ -51,7 +51,7 @@ impl GPUQueueMethods for GPUQueue {
|
|||
/// https://gpuweb.github.io/gpuweb/#dom-gpuqueue-submit
|
||||
fn Submit(&self, command_buffers: Vec<DomRoot<GPUCommandBuffer>>) {
|
||||
let valid = command_buffers.iter().all(|cb| {
|
||||
cb.buffers().iter().all(|b| match *b.state() {
|
||||
cb.buffers().iter().all(|b| match b.state() {
|
||||
GPUBufferState::Unmapped => true,
|
||||
_ => false,
|
||||
})
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#![allow(unsafe_code)]
|
||||
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::GPUCommandEncoderBinding::GPUColor;
|
||||
use crate::dom::bindings::codegen::Bindings::GPURenderPassEncoderBinding::GPURenderPassEncoderMethods;
|
||||
|
@ -18,8 +16,7 @@ use crate::dom::gpucommandencoder::{GPUCommandEncoder, GPUCommandEncoderState};
|
|||
use crate::dom::gpurenderpipeline::GPURenderPipeline;
|
||||
use dom_struct::dom_struct;
|
||||
use webgpu::{
|
||||
wgpu::command::{render_ffi as wgpu_render, RawPass},
|
||||
wgpu::id,
|
||||
wgpu::command::{render_ffi as wgpu_render, RenderPass},
|
||||
wgt, WebGPU, WebGPURequest,
|
||||
};
|
||||
|
||||
|
@ -30,21 +27,17 @@ pub struct GPURenderPassEncoder {
|
|||
channel: WebGPU,
|
||||
label: DomRefCell<Option<DOMString>>,
|
||||
#[ignore_malloc_size_of = "defined in wgpu-core"]
|
||||
raw_pass: DomRefCell<Option<RawPass<id::CommandEncoderId>>>,
|
||||
render_pass: DomRefCell<Option<RenderPass>>,
|
||||
command_encoder: Dom<GPUCommandEncoder>,
|
||||
}
|
||||
|
||||
impl GPURenderPassEncoder {
|
||||
fn new_inherited(
|
||||
channel: WebGPU,
|
||||
raw_pass: RawPass<id::CommandEncoderId>,
|
||||
parent: &GPUCommandEncoder,
|
||||
) -> Self {
|
||||
fn new_inherited(channel: WebGPU, render_pass: RenderPass, parent: &GPUCommandEncoder) -> Self {
|
||||
Self {
|
||||
channel,
|
||||
reflector_: Reflector::new(),
|
||||
label: DomRefCell::new(None),
|
||||
raw_pass: DomRefCell::new(Some(raw_pass)),
|
||||
render_pass: DomRefCell::new(Some(render_pass)),
|
||||
command_encoder: Dom::from_ref(parent),
|
||||
}
|
||||
}
|
||||
|
@ -52,12 +45,14 @@ impl GPURenderPassEncoder {
|
|||
pub fn new(
|
||||
global: &GlobalScope,
|
||||
channel: WebGPU,
|
||||
raw_pass: RawPass<id::CommandEncoderId>,
|
||||
render_pass: RenderPass,
|
||||
parent: &GPUCommandEncoder,
|
||||
) -> DomRoot<Self> {
|
||||
reflect_dom_object(
|
||||
Box::new(GPURenderPassEncoder::new_inherited(
|
||||
channel, raw_pass, parent,
|
||||
channel,
|
||||
render_pass,
|
||||
parent,
|
||||
)),
|
||||
global,
|
||||
)
|
||||
|
@ -76,11 +71,12 @@ impl GPURenderPassEncoderMethods for GPURenderPassEncoder {
|
|||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpuprogrammablepassencoder-setbindgroup
|
||||
#[allow(unsafe_code)]
|
||||
fn SetBindGroup(&self, index: u32, bind_group: &GPUBindGroup, dynamic_offsets: Vec<u32>) {
|
||||
if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() {
|
||||
if let Some(render_pass) = self.render_pass.borrow_mut().as_mut() {
|
||||
unsafe {
|
||||
wgpu_render::wgpu_render_pass_set_bind_group(
|
||||
raw_pass,
|
||||
render_pass,
|
||||
index,
|
||||
bind_group.id().0,
|
||||
dynamic_offsets.as_ptr(),
|
||||
|
@ -100,24 +96,23 @@ impl GPURenderPassEncoderMethods for GPURenderPassEncoder {
|
|||
min_depth: Finite<f32>,
|
||||
max_depth: Finite<f32>,
|
||||
) {
|
||||
if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() {
|
||||
unsafe {
|
||||
wgpu_render::wgpu_render_pass_set_viewport(
|
||||
raw_pass, *x, *y, *width, *height, *min_depth, *max_depth,
|
||||
)
|
||||
};
|
||||
if let Some(render_pass) = self.render_pass.borrow_mut().as_mut() {
|
||||
wgpu_render::wgpu_render_pass_set_viewport(
|
||||
render_pass,
|
||||
*x,
|
||||
*y,
|
||||
*width,
|
||||
*height,
|
||||
*min_depth,
|
||||
*max_depth,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-setscissorrect
|
||||
fn SetScissorRect(&self, x: u32, y: u32, width: u32, height: u32) {
|
||||
if width <= 0 || height <= 0 {
|
||||
return warn!("Cannot set scissor rect- width and height must greater than 0");
|
||||
}
|
||||
if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() {
|
||||
unsafe {
|
||||
wgpu_render::wgpu_render_pass_set_scissor_rect(raw_pass, x, y, width, height)
|
||||
};
|
||||
if let Some(render_pass) = self.render_pass.borrow_mut().as_mut() {
|
||||
wgpu_render::wgpu_render_pass_set_scissor_rect(render_pass, x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,28 +132,26 @@ impl GPURenderPassEncoderMethods for GPURenderPassEncoder {
|
|||
a: *s[3],
|
||||
},
|
||||
};
|
||||
if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() {
|
||||
unsafe { wgpu_render::wgpu_render_pass_set_blend_color(raw_pass, &colors) };
|
||||
if let Some(render_pass) = self.render_pass.borrow_mut().as_mut() {
|
||||
wgpu_render::wgpu_render_pass_set_blend_color(render_pass, &colors);
|
||||
}
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-setstencilreference
|
||||
fn SetStencilReference(&self, reference: u32) {
|
||||
if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() {
|
||||
unsafe { wgpu_render::wgpu_render_pass_set_stencil_reference(raw_pass, reference) };
|
||||
if let Some(render_pass) = self.render_pass.borrow_mut().as_mut() {
|
||||
wgpu_render::wgpu_render_pass_set_stencil_reference(render_pass, reference);
|
||||
}
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderpassencoder-endpass
|
||||
fn EndPass(&self) {
|
||||
if let Some(raw_pass) = self.raw_pass.borrow_mut().take() {
|
||||
let (pass_data, command_encoder_id) = unsafe { raw_pass.finish_render() };
|
||||
|
||||
if let Some(render_pass) = self.render_pass.borrow_mut().take() {
|
||||
self.channel
|
||||
.0
|
||||
.send(WebGPURequest::RunRenderPass {
|
||||
command_encoder_id,
|
||||
pass_data,
|
||||
command_encoder_id: self.command_encoder.id().0,
|
||||
render_pass,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
|
@ -171,59 +164,46 @@ impl GPURenderPassEncoderMethods for GPURenderPassEncoder {
|
|||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-setpipeline
|
||||
fn SetPipeline(&self, pipeline: &GPURenderPipeline) {
|
||||
if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() {
|
||||
unsafe { wgpu_render::wgpu_render_pass_set_pipeline(raw_pass, pipeline.id().0) };
|
||||
if let Some(render_pass) = self.render_pass.borrow_mut().as_mut() {
|
||||
wgpu_render::wgpu_render_pass_set_pipeline(render_pass, pipeline.id().0);
|
||||
}
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-setindexbuffer
|
||||
fn SetIndexBuffer(&self, buffer: &GPUBuffer, offset: u64, size: u64) {
|
||||
let s = if size == 0 {
|
||||
wgt::BufferSize::WHOLE
|
||||
} else {
|
||||
wgt::BufferSize(size)
|
||||
};
|
||||
|
||||
if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() {
|
||||
unsafe {
|
||||
wgpu_render::wgpu_render_pass_set_index_buffer(raw_pass, buffer.id().0, offset, s)
|
||||
};
|
||||
if let Some(render_pass) = self.render_pass.borrow_mut().as_mut() {
|
||||
wgpu_render::wgpu_render_pass_set_index_buffer(
|
||||
render_pass,
|
||||
buffer.id().0,
|
||||
offset,
|
||||
wgt::BufferSize::new(size),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-setvertexbuffer
|
||||
fn SetVertexBuffer(&self, slot: u32, buffer: &GPUBuffer, offset: u64, size: u64) {
|
||||
let s = if size == 0 {
|
||||
wgt::BufferSize::WHOLE
|
||||
} else {
|
||||
wgt::BufferSize(size)
|
||||
};
|
||||
|
||||
if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() {
|
||||
unsafe {
|
||||
wgpu_render::wgpu_render_pass_set_vertex_buffer(
|
||||
raw_pass,
|
||||
slot,
|
||||
buffer.id().0,
|
||||
offset,
|
||||
s,
|
||||
)
|
||||
};
|
||||
if let Some(render_pass) = self.render_pass.borrow_mut().as_mut() {
|
||||
wgpu_render::wgpu_render_pass_set_vertex_buffer(
|
||||
render_pass,
|
||||
slot,
|
||||
buffer.id().0,
|
||||
offset,
|
||||
wgt::BufferSize::new(size),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-draw
|
||||
fn Draw(&self, vertex_count: u32, instance_count: u32, first_vertex: u32, first_instance: u32) {
|
||||
if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() {
|
||||
unsafe {
|
||||
wgpu_render::wgpu_render_pass_draw(
|
||||
raw_pass,
|
||||
vertex_count,
|
||||
instance_count,
|
||||
first_vertex,
|
||||
first_instance,
|
||||
)
|
||||
};
|
||||
if let Some(render_pass) = self.render_pass.borrow_mut().as_mut() {
|
||||
wgpu_render::wgpu_render_pass_draw(
|
||||
render_pass,
|
||||
vertex_count,
|
||||
instance_count,
|
||||
first_vertex,
|
||||
first_instance,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,43 +216,37 @@ impl GPURenderPassEncoderMethods for GPURenderPassEncoder {
|
|||
base_vertex: i32,
|
||||
first_instance: u32,
|
||||
) {
|
||||
if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() {
|
||||
unsafe {
|
||||
wgpu_render::wgpu_render_pass_draw_indexed(
|
||||
raw_pass,
|
||||
index_count,
|
||||
instance_count,
|
||||
first_index,
|
||||
base_vertex,
|
||||
first_instance,
|
||||
)
|
||||
};
|
||||
if let Some(render_pass) = self.render_pass.borrow_mut().as_mut() {
|
||||
wgpu_render::wgpu_render_pass_draw_indexed(
|
||||
render_pass,
|
||||
index_count,
|
||||
instance_count,
|
||||
first_index,
|
||||
base_vertex,
|
||||
first_instance,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-drawindirect
|
||||
fn DrawIndirect(&self, indirect_buffer: &GPUBuffer, indirect_offset: u64) {
|
||||
if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() {
|
||||
unsafe {
|
||||
wgpu_render::wgpu_render_pass_draw_indirect(
|
||||
raw_pass,
|
||||
indirect_buffer.id().0,
|
||||
indirect_offset,
|
||||
)
|
||||
};
|
||||
if let Some(render_pass) = self.render_pass.borrow_mut().as_mut() {
|
||||
wgpu_render::wgpu_render_pass_draw_indirect(
|
||||
render_pass,
|
||||
indirect_buffer.id().0,
|
||||
indirect_offset,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gpurenderencoderbase-drawindexedindirect
|
||||
fn DrawIndexedIndirect(&self, indirect_buffer: &GPUBuffer, indirect_offset: u64) {
|
||||
if let Some(raw_pass) = self.raw_pass.borrow_mut().as_mut() {
|
||||
unsafe {
|
||||
wgpu_render::wgpu_render_pass_draw_indexed_indirect(
|
||||
raw_pass,
|
||||
indirect_buffer.id().0,
|
||||
indirect_offset,
|
||||
)
|
||||
};
|
||||
if let Some(render_pass) = self.render_pass.borrow_mut().as_mut() {
|
||||
wgpu_render::wgpu_render_pass_draw_indexed_indirect(
|
||||
render_pass,
|
||||
indirect_buffer.id().0,
|
||||
indirect_offset,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -332,6 +332,7 @@ pub mod gpucommandencoder;
|
|||
pub mod gpucomputepassencoder;
|
||||
pub mod gpucomputepipeline;
|
||||
pub mod gpudevice;
|
||||
pub mod gpumapmode;
|
||||
pub mod gpupipelinelayout;
|
||||
pub mod gpuqueue;
|
||||
pub mod gpurenderpassencoder;
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
// https://gpuweb.github.io/gpuweb/#gpubuffer
|
||||
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
|
||||
interface GPUBuffer {
|
||||
//Promise<ArrayBuffer> mapReadAsync();
|
||||
// Promise<ArrayBuffer> mapWriteAsync();
|
||||
Promise<void> mapAsync(GPUMapModeFlags mode, optional GPUSize64 offset = 0, optional GPUSize64 size = 0);
|
||||
//ArrayBuffer getMappedRange(optional GPUSize64 offset = 0, optional GPUSize64 size = 0);
|
||||
void unmap();
|
||||
|
||||
void destroy();
|
||||
|
@ -16,10 +16,9 @@ GPUBuffer includes GPUObjectBase;
|
|||
dictionary GPUBufferDescriptor : GPUObjectDescriptorBase {
|
||||
required GPUSize64 size;
|
||||
required GPUBufferUsageFlags usage;
|
||||
boolean mappedAtCreation = false;
|
||||
};
|
||||
|
||||
typedef unsigned long long GPUSize64;
|
||||
|
||||
typedef unsigned long GPUBufferUsageFlags;
|
||||
|
||||
typedef sequence<any> GPUMappedBuffer;
|
||||
|
|
|
@ -5,13 +5,16 @@
|
|||
// https://gpuweb.github.io/gpuweb/#buffer-usage
|
||||
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
|
||||
interface GPUBufferUsage {
|
||||
const GPUBufferUsageFlags MAP_READ = 0x0001;
|
||||
const GPUBufferUsageFlags MAP_WRITE = 0x0002;
|
||||
const GPUBufferUsageFlags COPY_SRC = 0x0004;
|
||||
const GPUBufferUsageFlags COPY_DST = 0x0008;
|
||||
const GPUBufferUsageFlags INDEX = 0x0010;
|
||||
const GPUBufferUsageFlags VERTEX = 0x0020;
|
||||
const GPUBufferUsageFlags UNIFORM = 0x0040;
|
||||
const GPUBufferUsageFlags STORAGE = 0x0080;
|
||||
const GPUBufferUsageFlags INDIRECT = 0x0100;
|
||||
const GPUBufferUsageFlags MAP_READ = 0x0001;
|
||||
const GPUBufferUsageFlags MAP_WRITE = 0x0002;
|
||||
const GPUBufferUsageFlags COPY_SRC = 0x0004;
|
||||
const GPUBufferUsageFlags COPY_DST = 0x0008;
|
||||
const GPUBufferUsageFlags INDEX = 0x0010;
|
||||
const GPUBufferUsageFlags VERTEX = 0x0020;
|
||||
const GPUBufferUsageFlags UNIFORM = 0x0040;
|
||||
const GPUBufferUsageFlags STORAGE = 0x0080;
|
||||
const GPUBufferUsageFlags INDIRECT = 0x0100;
|
||||
const GPUBufferUsageFlags QUERY_RESOLVE = 0x0200;
|
||||
};
|
||||
|
||||
typedef [EnforceRange] unsigned long GPUBufferUsageFlags;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
interface GPUComputePassEncoder {
|
||||
void setPipeline(GPUComputePipeline pipeline);
|
||||
void dispatch(GPUSize32 x, optional GPUSize32 y = 1, optional GPUSize32 z = 1);
|
||||
// void dispatchIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
|
||||
void dispatchIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
|
||||
|
||||
void endPass();
|
||||
};
|
||||
|
|
|
@ -12,7 +12,6 @@ interface GPUDevice : EventTarget {
|
|||
[SameObject] readonly attribute GPUQueue defaultQueue;
|
||||
|
||||
GPUBuffer createBuffer(GPUBufferDescriptor descriptor);
|
||||
GPUMappedBuffer createBufferMapped(GPUBufferDescriptor descriptor);
|
||||
GPUTexture createTexture(GPUTextureDescriptor descriptor);
|
||||
GPUSampler createSampler(optional GPUSamplerDescriptor descriptor = {});
|
||||
|
||||
|
|
12
components/script/dom/webidls/GPUMapMode.webidl
Normal file
12
components/script/dom/webidls/GPUMapMode.webidl
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// https://gpuweb.github.io/gpuweb/#gpumapmode
|
||||
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
|
||||
interface GPUMapMode {
|
||||
const GPUMapModeFlags READ = 0x0001;
|
||||
const GPUMapModeFlags WRITE = 0x0002;
|
||||
};
|
||||
|
||||
typedef [EnforceRange] unsigned long GPUMapModeFlags;
|
|
@ -21,5 +21,5 @@ servo_config = { path = "../config" }
|
|||
smallvec = { version = "0.6", features = ["serde"] }
|
||||
webrender_api = { git = "https://github.com/servo/webrender" }
|
||||
webrender_traits = { path = "../webrender_traits" }
|
||||
wgpu-core = { version = "0.5.0", git = "https://github.com/gfx-rs/wgpu", features = ["replay", "trace"] }
|
||||
wgpu-core = { version = "0.5.0", git = "https://github.com/gfx-rs/wgpu", features = ["replay", "trace", "serial-pass"] }
|
||||
wgpu-types = { version = "0.5.0", git = "https://github.com/gfx-rs/wgpu", features = ["replay", "trace"] }
|
||||
|
|
|
@ -29,7 +29,7 @@ use webrender_traits::{
|
|||
};
|
||||
use wgpu::{
|
||||
binding_model::{BindGroupDescriptor, BindGroupEntry, BindingResource, BufferBinding},
|
||||
command::{BufferCopyView, TextureCopyView},
|
||||
command::{BufferCopyView, ComputePass, RenderPass, TextureCopyView},
|
||||
device::HostMap,
|
||||
id,
|
||||
instance::RequestAdapterOptions,
|
||||
|
@ -48,12 +48,20 @@ pub enum WebGPUResponse {
|
|||
queue_id: WebGPUQueue,
|
||||
_descriptor: wgt::DeviceDescriptor,
|
||||
},
|
||||
BufferMapAsync(Vec<u8>),
|
||||
}
|
||||
|
||||
pub type WebGPUResponseResult = Result<WebGPUResponse, String>;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub enum WebGPURequest {
|
||||
BufferMapAsync {
|
||||
sender: IpcSender<WebGPUResponseResult>,
|
||||
buffer_id: id::BufferId,
|
||||
host_map: HostMap,
|
||||
map_range: std::ops::Range<u64>,
|
||||
},
|
||||
BufferMapComplete(id::BufferId),
|
||||
CommandEncoderFinish {
|
||||
command_encoder_id: id::CommandEncoderId,
|
||||
// TODO(zakorgy): Serialize CommandBufferDescriptor in wgpu-core
|
||||
|
@ -170,11 +178,11 @@ pub enum WebGPURequest {
|
|||
},
|
||||
RunComputePass {
|
||||
command_encoder_id: id::CommandEncoderId,
|
||||
pass_data: Vec<u8>,
|
||||
compute_pass: ComputePass,
|
||||
},
|
||||
RunRenderPass {
|
||||
command_encoder_id: id::CommandEncoderId,
|
||||
pass_data: Vec<u8>,
|
||||
render_pass: RenderPass,
|
||||
},
|
||||
Submit {
|
||||
queue_id: id::QueueId,
|
||||
|
@ -190,6 +198,7 @@ pub enum WebGPURequest {
|
|||
device_id: id::DeviceId,
|
||||
buffer_id: id::BufferId,
|
||||
array_buffer: Vec<u8>,
|
||||
mapped_at_creation: bool,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -200,6 +209,13 @@ pub enum WebGPUBindings {
|
|||
TextureView(id::TextureViewId),
|
||||
}
|
||||
|
||||
struct BufferMapInfo<'a> {
|
||||
buffer_id: id::BufferId,
|
||||
sender: IpcSender<WebGPUResponseResult>,
|
||||
global: &'a wgpu::hub::Global<IdentityRecyclerFactory>,
|
||||
size: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct WebGPU(pub IpcSender<WebGPURequest>);
|
||||
|
||||
|
@ -264,7 +280,7 @@ impl WebGPU {
|
|||
}
|
||||
}
|
||||
|
||||
struct WGPU {
|
||||
struct WGPU<'a> {
|
||||
receiver: IpcReceiver<WebGPURequest>,
|
||||
sender: IpcSender<WebGPURequest>,
|
||||
script_sender: IpcSender<WebGPUMsg>,
|
||||
|
@ -273,13 +289,15 @@ struct WGPU {
|
|||
devices: Vec<WebGPUDevice>,
|
||||
// Track invalid adapters https://gpuweb.github.io/gpuweb/#invalid
|
||||
_invalid_adapters: Vec<WebGPUAdapter>,
|
||||
// Buffers with pending mapping
|
||||
buffer_maps: HashMap<id::BufferId, BufferMapInfo<'a>>,
|
||||
webrender_api: webrender_api::RenderApi,
|
||||
webrender_document: webrender_api::DocumentId,
|
||||
external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
|
||||
wgpu_image_map: Arc<Mutex<HashMap<u64, PresentationData>>>,
|
||||
}
|
||||
|
||||
impl WGPU {
|
||||
impl<'a> WGPU<'a> {
|
||||
fn new(
|
||||
receiver: IpcReceiver<WebGPURequest>,
|
||||
sender: IpcSender<WebGPURequest>,
|
||||
|
@ -296,10 +314,11 @@ impl WGPU {
|
|||
receiver,
|
||||
sender,
|
||||
script_sender,
|
||||
global: wgpu::hub::Global::new("wgpu-core", factory),
|
||||
global: wgpu::hub::Global::new("wgpu-core", factory, wgt::BackendBit::PRIMARY),
|
||||
adapters: Vec::new(),
|
||||
devices: Vec::new(),
|
||||
_invalid_adapters: Vec::new(),
|
||||
buffer_maps: HashMap::new(),
|
||||
webrender_api: webrender_api_sender.create_api(),
|
||||
webrender_document,
|
||||
external_images,
|
||||
|
@ -307,9 +326,57 @@ impl WGPU {
|
|||
}
|
||||
}
|
||||
|
||||
fn run(mut self) {
|
||||
fn run(&'a mut self) {
|
||||
while let Ok(msg) = self.receiver.recv() {
|
||||
self.devices.iter().for_each(|device| {
|
||||
let global = &self.global;
|
||||
let device_id = device.0;
|
||||
gfx_select!(device_id => global.device_poll(device_id, false));
|
||||
});
|
||||
match msg {
|
||||
WebGPURequest::BufferMapAsync {
|
||||
sender,
|
||||
buffer_id,
|
||||
host_map,
|
||||
map_range,
|
||||
} => {
|
||||
let map_info = BufferMapInfo {
|
||||
buffer_id,
|
||||
sender,
|
||||
global: &self.global,
|
||||
size: (map_range.end - map_range.start) as usize,
|
||||
};
|
||||
self.buffer_maps.insert(buffer_id, map_info);
|
||||
|
||||
unsafe extern "C" fn callback(status: BufferMapAsyncStatus, userdata: *mut u8) {
|
||||
let info = (userdata as *mut BufferMapInfo).as_ref().unwrap();
|
||||
match status {
|
||||
BufferMapAsyncStatus::Success => {
|
||||
let global = info.global;
|
||||
let data_pt = gfx_select!(info.buffer_id =>
|
||||
global.buffer_get_mapped_range(info.buffer_id, 0, None));
|
||||
let data = slice::from_raw_parts(data_pt, info.size).to_vec();
|
||||
if let Err(e) =
|
||||
info.sender.send(Ok(WebGPUResponse::BufferMapAsync(data)))
|
||||
{
|
||||
warn!("Could not send BufferMapAsync Response ({})", e);
|
||||
}
|
||||
},
|
||||
_ => warn!("Could not map buffer({:?})", info.buffer_id),
|
||||
}
|
||||
}
|
||||
|
||||
let operation = BufferMapOperation {
|
||||
host: host_map,
|
||||
callback,
|
||||
user_data: convert_to_pointer(self.buffer_maps.get(&buffer_id).unwrap()),
|
||||
};
|
||||
let global = &self.global;
|
||||
gfx_select!(buffer_id => global.buffer_map_async(buffer_id, map_range, operation));
|
||||
},
|
||||
WebGPURequest::BufferMapComplete(buffer_id) => {
|
||||
self.buffer_maps.remove(&buffer_id);
|
||||
},
|
||||
WebGPURequest::CommandEncoderFinish { command_encoder_id } => {
|
||||
let global = &self.global;
|
||||
let _ = gfx_select!(command_encoder_id => global.command_encoder_finish(
|
||||
|
@ -526,14 +593,9 @@ impl WGPU {
|
|||
program,
|
||||
} => {
|
||||
let global = &self.global;
|
||||
let descriptor = wgpu_core::pipeline::ShaderModuleDescriptor {
|
||||
code: wgpu_core::U32Array {
|
||||
bytes: program.as_ptr(),
|
||||
length: program.len(),
|
||||
},
|
||||
};
|
||||
let source = wgpu_core::pipeline::ShaderModuleSource::SpirV(&program);
|
||||
let _ = gfx_select!(program_id =>
|
||||
global.device_create_shader_module(device_id, &descriptor, program_id));
|
||||
global.device_create_shader_module(device_id, source, program_id));
|
||||
},
|
||||
WebGPURequest::CreateSwapChain {
|
||||
device_id,
|
||||
|
@ -636,7 +698,6 @@ impl WGPU {
|
|||
if let Err(e) = self.script_sender.send(WebGPUMsg::Exit) {
|
||||
warn!("Failed to send WebGPUMsg::Exit to script ({})", e);
|
||||
}
|
||||
drop(self.global);
|
||||
if let Err(e) = sender.send(()) {
|
||||
warn!("Failed to send response to WebGPURequest::Exit ({})", e)
|
||||
}
|
||||
|
@ -712,22 +773,22 @@ impl WGPU {
|
|||
},
|
||||
WebGPURequest::RunComputePass {
|
||||
command_encoder_id,
|
||||
pass_data,
|
||||
compute_pass,
|
||||
} => {
|
||||
let global = &self.global;
|
||||
gfx_select!(command_encoder_id => global.command_encoder_run_compute_pass(
|
||||
command_encoder_id,
|
||||
&pass_data
|
||||
&compute_pass
|
||||
));
|
||||
},
|
||||
WebGPURequest::RunRenderPass {
|
||||
command_encoder_id,
|
||||
pass_data,
|
||||
render_pass,
|
||||
} => {
|
||||
let global = &self.global;
|
||||
gfx_select!(command_encoder_id => global.command_encoder_run_render_pass(
|
||||
command_encoder_id,
|
||||
&pass_data
|
||||
&render_pass
|
||||
));
|
||||
},
|
||||
WebGPURequest::Submit {
|
||||
|
@ -824,7 +885,7 @@ impl WGPU {
|
|||
// TODO: Remove the blocking behaviour
|
||||
gfx_select!(device_id => global.device_poll(device_id, true));
|
||||
let buf_data = gfx_select!(buffer_id =>
|
||||
global.buffer_get_mapped_range(buffer_id, 0, wgt::BufferSize::WHOLE));
|
||||
global.buffer_get_mapped_range(buffer_id, 0, None));
|
||||
if let Some(present_data) =
|
||||
self.wgpu_image_map.lock().unwrap().get_mut(&external_id)
|
||||
{
|
||||
|
@ -849,21 +910,34 @@ impl WGPU {
|
|||
device_id,
|
||||
buffer_id,
|
||||
array_buffer,
|
||||
mapped_at_creation,
|
||||
} => {
|
||||
let global = &self.global;
|
||||
|
||||
gfx_select!(buffer_id => global.device_set_buffer_sub_data(
|
||||
device_id,
|
||||
buffer_id,
|
||||
0,
|
||||
array_buffer.as_slice()
|
||||
));
|
||||
if mapped_at_creation {
|
||||
gfx_select!(device_id => global.queue_write_buffer(
|
||||
device_id,
|
||||
buffer_id,
|
||||
0,
|
||||
array_buffer.as_slice()
|
||||
));
|
||||
} else {
|
||||
gfx_select!(buffer_id => global.device_set_buffer_sub_data(
|
||||
device_id,
|
||||
buffer_id,
|
||||
0,
|
||||
array_buffer.as_slice()
|
||||
));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_to_pointer<T: Sized>(obj: &T) -> *mut u8 {
|
||||
(obj as *const T) as *mut u8
|
||||
}
|
||||
|
||||
macro_rules! webgpu_resource {
|
||||
($name:ident, $id:ty) => {
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Hash, PartialEq, Serialize)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue