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