diff options
author | bors-servo <servo-ops@mozilla.com> | 2020-06-27 14:29:08 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-27 14:29:08 -0400 |
commit | af110ac21fcf1e108c919f5e9d724b2441996ed6 (patch) | |
tree | 6c233f8d39d2144d24a55fa71c5c4a828700cc40 /components/script | |
parent | 223b6843dbe31dacd945ba9a21b4023224add5e9 (diff) | |
parent | db2d313a1b76886c656a90280bfe4f44b909d977 (diff) | |
download | servo-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.conf | 2 | ||||
-rw-r--r-- | components/script/dom/bindings/trace.rs | 15 | ||||
-rw-r--r-- | components/script/dom/gpubuffer.rs | 202 | ||||
-rw-r--r-- | components/script/dom/gpucommandencoder.rs | 86 | ||||
-rw-r--r-- | components/script/dom/gpucomputepassencoder.rs | 50 | ||||
-rw-r--r-- | components/script/dom/gpudevice.rs | 147 | ||||
-rw-r--r-- | components/script/dom/gpumapmode.rs | 11 | ||||
-rw-r--r-- | components/script/dom/gpuqueue.rs | 2 | ||||
-rw-r--r-- | components/script/dom/gpurenderpassencoder.rs | 178 | ||||
-rw-r--r-- | components/script/dom/mod.rs | 1 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUBuffer.webidl | 7 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUBufferUsage.webidl | 21 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUComputePassEncoder.webidl | 2 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUDevice.webidl | 1 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUMapMode.webidl | 12 |
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; |