aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
authorbors-servo <servo-ops@mozilla.com>2020-06-27 14:29:08 -0400
committerGitHub <noreply@github.com>2020-06-27 14:29:08 -0400
commitaf110ac21fcf1e108c919f5e9d724b2441996ed6 (patch)
tree6c233f8d39d2144d24a55fa71c5c4a828700cc40 /components/script
parent223b6843dbe31dacd945ba9a21b4023224add5e9 (diff)
parentdb2d313a1b76886c656a90280bfe4f44b909d977 (diff)
downloadservo-af110ac21fcf1e108c919f5e9d724b2441996ed6.tar.gz
servo-af110ac21fcf1e108c919f5e9d724b2441996ed6.zip
Auto merge of #27084 - kunalmohan:gpu-buffer-mapping, r=kvark
Implement GPUBuffer.mapAsync and update wgpu-core <!-- Please describe your changes on the following line: --> This PR covers the following- 1. update wgpu-core to use serializable `RenderPass` and `ComputePass`. Implement `DispatchIndirect`. 2. Implement `GPUBuffer.mapAsync()`. The `mapAsync()` methods has the following flow- 1. A new promise is created in `mapAsync()` and a message sent to the server-side. This returns a promise. 2. On the server-side, a `struct BufferMapInfo` object stores the relevant info required to send data to the client-side on completion of mapping. This object is stored in a `buffer_maps: HashMap<id::BufferId, BufferMapInfo<'a>>,` in `WGPU`. `buffers_maps` basically stores the data for buffers with pending mapping. 3. `buffer_map_async()` command is issued with a callback responsible to send the data back to the client. 4. All the devices are polled every time the server receives a new message. 5. The data is sent back on completion and promise resolved through `AsyncWGPUListener` (similar to how the `requestDevice()` and `RequestAdapter` are processed). 6. On receiving the data, the client sends back a `BufferMapComplete` message to the server to remove the entry from `buffer_maps` hashmap. I intended to implement `getMappedRange()`, too, in this PR but it's quite a task in itself (implementing intersecting ArrayBuffers). This already being a 500+ line PR, I thought it best to get this model approved first (also it will probably be easier to review this and `getMappedRange` separately). `getMappedRange` would come up in the next one. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #___ (GitHub issue number if applicable) <!-- Either: --> - [ ] There are tests for these changes OR - [ ] These changes do not require tests because ___ <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/bindings/codegen/Bindings.conf2
-rw-r--r--components/script/dom/bindings/trace.rs15
-rw-r--r--components/script/dom/gpubuffer.rs202
-rw-r--r--components/script/dom/gpucommandencoder.rs86
-rw-r--r--components/script/dom/gpucomputepassencoder.rs50
-rw-r--r--components/script/dom/gpudevice.rs147
-rw-r--r--components/script/dom/gpumapmode.rs11
-rw-r--r--components/script/dom/gpuqueue.rs2
-rw-r--r--components/script/dom/gpurenderpassencoder.rs178
-rw-r--r--components/script/dom/mod.rs1
-rw-r--r--components/script/dom/webidls/GPUBuffer.webidl7
-rw-r--r--components/script/dom/webidls/GPUBufferUsage.webidl21
-rw-r--r--components/script/dom/webidls/GPUComputePassEncoder.webidl2
-rw-r--r--components/script/dom/webidls/GPUDevice.webidl1
-rw-r--r--components/script/dom/webidls/GPUMapMode.webidl12
15 files changed, 378 insertions, 359 deletions
diff --git a/components/script/dom/bindings/codegen/Bindings.conf b/components/script/dom/bindings/codegen/Bindings.conf
index 7aa8ffa4c8b..e4d4c234262 100644
--- a/components/script/dom/bindings/codegen/Bindings.conf
+++ b/components/script/dom/bindings/codegen/Bindings.conf
@@ -153,7 +153,7 @@ DOMInterfaces = {
},
'GPUBuffer': {
- 'inRealms': ['MapReadAsync'],
+ 'inRealms': ['MapAsync'],
}
}
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index 6208a7bc1ba..d6216cdad48 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -135,7 +135,7 @@ use std::borrow::Cow;
use std::cell::{Cell, RefCell, UnsafeCell};
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
use std::hash::{BuildHasher, Hash};
-use std::ops::{Deref, DerefMut};
+use std::ops::{Deref, DerefMut, Range};
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::atomic::{AtomicBool, AtomicUsize};
@@ -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,9 +582,11 @@ 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!(Range<u64>);
unsafe_no_jsmanaged_fields!(WebXRSwapChainId);
unsafe_no_jsmanaged_fields!(MediaList);
unsafe_no_jsmanaged_fields!(
diff --git a/components/script/dom/gpubuffer.rs b/components/script/dom/gpubuffer.rs
index a23a30a4b11..474c30dba0f 100644
--- a/components/script/dom/gpubuffer.rs
+++ b/components/script/dom/gpubuffer.rs
@@ -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::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::{GPUBufferMethods, GPUSize64};
+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::typedarray::{ArrayBuffer, CreateWith};
use std::cell::Cell;
+use std::ops::Range;
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: DomRefCell<Range<u64>>,
+ size: GPUSize64,
+ map_mode: Cell<Option<u32>>,
}
impl GPUBuffer {
@@ -54,21 +62,22 @@ impl GPUBuffer {
device: WebGPUDevice,
state: GPUBufferState,
size: GPUSize64,
- usage: u32,
valid: bool,
mapping: RootedTraceableBox<Heap<*mut JSObject>>,
+ mapping_range: Range<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: DomRefCell::new(mapping_range),
+ map_mode: Cell::new(None),
}
}
@@ -80,13 +89,20 @@ impl GPUBuffer {
device: WebGPUDevice,
state: GPUBufferState,
size: GPUSize64,
- usage: u32,
valid: bool,
mapping: RootedTraceableBox<Heap<*mut JSObject>>,
+ mapping_range: Range<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,65 @@ 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) => {
+ // Step 3.2
self.channel
.0
.send(WebGPURequest::UnmapBuffer {
- device_id: self.device.0,
buffer_id: self.id().0,
array_buffer: array_buffer.to_vec(),
+ is_map_read: self.map_mode.get() == Some(GPUMapModeConstants::READ),
+ offset: self.mapping_range.borrow().start,
+ size: self.mapping_range.borrow().end -
+ self.mapping_range.borrow().start,
})
.unwrap();
- // Step 3.2
+ // 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);
+ *self.mapping_range.borrow_mut() = 0..0;
}
/// 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 +208,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 {
+ if offset + size > self.size {
+ warn!("Requested mapping size is greated than buffer size");
+ promise.reject_error(Error::Abort);
+ return promise;
+ }
+ offset..offset + size
+ };
+ let host_map = match mode {
+ GPUMapModeConstants::READ => HostMap::Read,
+ GPUMapModeConstants::WRITE => 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());
+
+ 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: map_range.clone(),
+ }) {
+ warn!(
+ "Failed to send BufferMapAsync ({:?}) ({})",
+ self.buffer.0, e
+ );
+ promise.reject_error(Error::Operation);
+ return promise;
+ }
+
+ self.state.set(GPUBufferState::MappingPending);
+ self.map_mode.set(Some(mode));
+ *self.mapping_range.borrow_mut() = map_range;
+ promise
}
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
@@ -202,3 +270,43 @@ 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) => {
+ let cx = self.global().get_cx();
+ rooted!(in(*cx) let mut array_buffer = ptr::null_mut::<JSObject>());
+ match unsafe {
+ ArrayBuffer::create(*cx, CreateWith::Slice(&bytes), array_buffer.handle_mut())
+ } {
+ Ok(_) => promise.resolve_native(&()),
+ Err(()) => {
+ warn!(
+ "Failed to create ArrayBuffer for buffer({:?})",
+ self.buffer.0
+ );
+ promise.reject_error(Error::Operation);
+ },
+ }
+ self.mapping.set(array_buffer.get());
+ self.state.set(GPUBufferState::Mapped);
+ },
+ _ => {
+ 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
+ );
+ }
+ }
+}
diff --git a/components/script/dom/gpucommandencoder.rs b/components/script/dom/gpucommandencoder.rs
index 0615492dec6..4f41daccfa2 100644
--- a/components/script/dom/gpucommandencoder.rs
+++ b/components/script/dom/gpucommandencoder.rs
@@ -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 {
- attachment: depth.attachment.id().0,
- depth_load_op,
- depth_store_op: match depth.depthStoreOp {
+ 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_depth,
- depth_read_only: depth.depthReadOnly,
- stencil_load_op,
- stencil_store_op: match depth.stencilStoreOp {
+ 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_stencil,
- stencil_read_only: depth.stencilReadOnly,
+ clear_value: clear_stencil,
+ read_only: depth.stencilReadOnly,
+ };
+ DepthStencilAttachmentDescriptor {
+ attachment: depth.attachment.id().0,
+ 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.
diff --git a/components/script/dom/gpucomputepassencoder.rs b/components/script/dom/gpucomputepassencoder.rs
index 68fb641bd25..ac2a5b0dc90 100644
--- a/components/script/dom/gpucomputepassencoder.rs
+++ b/components/script/dom/gpucomputepassencoder.rs
@@ -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);
}
}
}
diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs
index b67c6e696e3..0eb5771baac 100644
--- a/components/script/dom/gpudevice.rs
+++ b/components/script/dom/gpudevice.rs
@@ -54,9 +54,7 @@ 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::typedarray::{ArrayBuffer, CreateWith};
-use std::num::NonZeroU64;
use std::ptr::{self, NonNull};
use webgpu::wgpu::binding_model::BufferBinding;
use webgpu::{self, wgt, WebGPU, WebGPUBindings, WebGPURequest};
@@ -120,38 +118,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 +153,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 +177,41 @@ 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 {
+ let cx = self.global().get_cx();
+ rooted!(in(*cx) let mut array_buffer = ptr::null_mut::<JSObject>());
+ unsafe {
+ assert!(ArrayBuffer::create(
+ *cx,
+ CreateWith::Length(descriptor.size as u32),
+ array_buffer.handle_mut(),
+ )
+ .is_ok());
+ }
+ mapping.set(array_buffer.get());
+ 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 +229,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 +366,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: b.size.and_then(wgt::BufferSize::new),
})
},
},
diff --git a/components/script/dom/gpumapmode.rs b/components/script/dom/gpumapmode.rs
new file mode 100644
index 00000000000..b216d3f839d
--- /dev/null
+++ b/components/script/dom/gpumapmode.rs
@@ -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,
+}
diff --git a/components/script/dom/gpuqueue.rs b/components/script/dom/gpuqueue.rs
index 5b533a8d32c..fa79dc6fd44 100644
--- a/components/script/dom/gpuqueue.rs
+++ b/components/script/dom/gpuqueue.rs
@@ -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,
})
diff --git a/components/script/dom/gpurenderpassencoder.rs b/components/script/dom/gpurenderpassencoder.rs
index a2d223b6f5d..cf25734eeda 100644
--- a/components/script/dom/gpurenderpassencoder.rs
+++ b/components/script/dom/gpurenderpassencoder.rs
@@ -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,
+ );
}
}
}
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs
index 2ee17f3e74b..0265c6b9bcd 100644
--- a/components/script/dom/mod.rs
+++ b/components/script/dom/mod.rs
@@ -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;
diff --git a/components/script/dom/webidls/GPUBuffer.webidl b/components/script/dom/webidls/GPUBuffer.webidl
index 4896caf46c1..f3e9e29a577 100644
--- a/components/script/dom/webidls/GPUBuffer.webidl
+++ b/components/script/dom/webidls/GPUBuffer.webidl
@@ -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;
diff --git a/components/script/dom/webidls/GPUBufferUsage.webidl b/components/script/dom/webidls/GPUBufferUsage.webidl
index 549f6652d1f..6db1d029f18 100644
--- a/components/script/dom/webidls/GPUBufferUsage.webidl
+++ b/components/script/dom/webidls/GPUBufferUsage.webidl
@@ -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;
diff --git a/components/script/dom/webidls/GPUComputePassEncoder.webidl b/components/script/dom/webidls/GPUComputePassEncoder.webidl
index 0b19cf98134..2aecf685f2e 100644
--- a/components/script/dom/webidls/GPUComputePassEncoder.webidl
+++ b/components/script/dom/webidls/GPUComputePassEncoder.webidl
@@ -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();
};
diff --git a/components/script/dom/webidls/GPUDevice.webidl b/components/script/dom/webidls/GPUDevice.webidl
index 738c8f076fd..24ee59b54a9 100644
--- a/components/script/dom/webidls/GPUDevice.webidl
+++ b/components/script/dom/webidls/GPUDevice.webidl
@@ -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 = {});
diff --git a/components/script/dom/webidls/GPUMapMode.webidl b/components/script/dom/webidls/GPUMapMode.webidl
new file mode 100644
index 00000000000..0dc52c4b448
--- /dev/null
+++ b/components/script/dom/webidls/GPUMapMode.webidl
@@ -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;