aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorSamson <16504129+sagudev@users.noreply.github.com>2024-09-13 15:32:00 +0200
committerGitHub <noreply@github.com>2024-09-13 13:32:00 +0000
commit261d60e456b678939b8a0ceff4d8eafcd44e582e (patch)
treeff65c4bf4dd9c855ce501fe47198397867c231b1 /components
parentf76692035b841661e9f0c4afa7f3651f2bfe91b8 (diff)
downloadservo-261d60e456b678939b8a0ceff4d8eafcd44e582e.tar.gz
servo-261d60e456b678939b8a0ceff4d8eafcd44e582e.zip
webgpu: Do one allocation less on presentation by keeping GPUBuffer mapped (#33387)
* `GPUPresentationBuffer` in `WGPUExternalImages` Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> * mv presentation_buffer in if let Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> * docs Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> --------- Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Diffstat (limited to 'components')
-rw-r--r--components/webgpu/swapchain.rs105
1 files changed, 74 insertions, 31 deletions
diff --git a/components/webgpu/swapchain.rs b/components/webgpu/swapchain.rs
index 145155b4145..695d8d91b86 100644
--- a/components/webgpu/swapchain.rs
+++ b/components/webgpu/swapchain.rs
@@ -4,6 +4,7 @@
use std::collections::HashMap;
use std::ops::ControlFlow;
+use std::ptr::NonNull;
use std::slice;
use std::sync::{Arc, Mutex, MutexGuard};
@@ -39,6 +40,41 @@ impl MallocSizeOf for WebGPUContextId {
pub type WGPUImageMap = Arc<Mutex<HashMap<WebGPUContextId, PresentationData>>>;
+struct GPUPresentationBuffer {
+ global: Arc<Global>,
+ buffer_id: id::BufferId,
+ data: NonNull<u8>,
+ size: usize,
+}
+
+// This is safe because `GPUPresentationBuffer` holds exclusive access to ptr
+unsafe impl Send for GPUPresentationBuffer {}
+unsafe impl Sync for GPUPresentationBuffer {}
+
+impl GPUPresentationBuffer {
+ fn new(global: Arc<Global>, buffer_id: id::BufferId, buffer_size: u64) -> Self {
+ let (data, size) = global
+ .buffer_get_mapped_range(buffer_id, 0, Some(buffer_size))
+ .unwrap();
+ GPUPresentationBuffer {
+ global,
+ buffer_id,
+ data,
+ size: size as usize,
+ }
+ }
+
+ fn slice(&self) -> &[u8] {
+ unsafe { slice::from_raw_parts(self.data.as_ptr(), self.size) }
+ }
+}
+
+impl Drop for GPUPresentationBuffer {
+ fn drop(&mut self) {
+ let _ = self.global.buffer_unmap(self.buffer_id);
+ }
+}
+
#[derive(Default)]
pub struct WGPUExternalImages {
pub images: WGPUImageMap,
@@ -52,7 +88,11 @@ impl WebrenderExternalImageApi for WGPUExternalImages {
let data;
if let Some(present_data) = self.images.lock().unwrap().get(&id) {
size = present_data.image_desc.size.cast_unit();
- data = present_data.data.clone();
+ data = if let Some(present_data) = &present_data.data {
+ present_data.slice().to_vec()
+ } else {
+ present_data.dummy_data()
+ };
} else {
size = Size2D::new(0, 0);
data = Vec::new();
@@ -71,15 +111,15 @@ impl WebrenderExternalImageApi for WGPUExternalImages {
}
pub struct PresentationData {
- pub device_id: id::DeviceId,
- pub queue_id: id::QueueId,
- pub data: Vec<u8>,
- pub unassigned_buffer_ids: ArrayVec<id::BufferId, PRESENTATION_BUFFER_COUNT>,
- pub available_buffer_ids: ArrayVec<id::BufferId, PRESENTATION_BUFFER_COUNT>,
- pub queued_buffer_ids: ArrayVec<id::BufferId, PRESENTATION_BUFFER_COUNT>,
- pub image_key: ImageKey,
- pub image_desc: ImageDescriptor,
- pub image_data: ImageData,
+ device_id: id::DeviceId,
+ queue_id: id::QueueId,
+ data: Option<GPUPresentationBuffer>,
+ unassigned_buffer_ids: ArrayVec<id::BufferId, PRESENTATION_BUFFER_COUNT>,
+ available_buffer_ids: ArrayVec<id::BufferId, PRESENTATION_BUFFER_COUNT>,
+ queued_buffer_ids: ArrayVec<id::BufferId, PRESENTATION_BUFFER_COUNT>,
+ image_key: ImageKey,
+ image_desc: ImageDescriptor,
+ image_data: ImageData,
}
impl PresentationData {
@@ -91,18 +131,10 @@ impl PresentationData {
image_desc: ImageDescriptor,
image_data: ImageData,
) -> Self {
- let height = image_desc.size.height;
Self {
device_id,
queue_id,
- // TODO: transparent black image
- data: vec![
- 255;
- (image_desc
- .stride
- .expect("Stride should be set when creating swapchain") *
- height) as usize
- ],
+ data: None,
unassigned_buffer_ids: buffer_ids,
available_buffer_ids: ArrayVec::<id::BufferId, PRESENTATION_BUFFER_COUNT>::new(),
queued_buffer_ids: ArrayVec::<id::BufferId, PRESENTATION_BUFFER_COUNT>::new(),
@@ -111,6 +143,23 @@ impl PresentationData {
image_data,
}
}
+
+ fn dummy_data(&self) -> Vec<u8> {
+ let size = (self
+ .image_desc
+ .stride
+ .expect("Stride should be set when creating swapchain") *
+ self.image_desc.size.height) as usize;
+ vec![0; size]
+ }
+
+ fn unmap_old_buffer(&mut self, presentation_buffer: GPUPresentationBuffer) {
+ self.queued_buffer_ids
+ .retain(|b_id| *b_id != presentation_buffer.buffer_id);
+ self.available_buffer_ids
+ .push(presentation_buffer.buffer_id);
+ drop(presentation_buffer);
+ }
}
impl crate::WGPU {
@@ -304,14 +353,10 @@ fn update_wr_image(
) {
match result {
Ok(()) => {
- let (slice_pointer, range_size) = global
- .buffer_get_mapped_range(buffer_id, 0, Some(buffer_size as u64))
- .unwrap();
- let data =
- unsafe { slice::from_raw_parts(slice_pointer.as_ptr(), range_size as usize) }
- .to_vec();
if let Some(present_data) = wgpu_image_map.lock().unwrap().get_mut(&context_id) {
- present_data.data = data;
+ let presentation_buffer =
+ GPUPresentationBuffer::new(global, buffer_id, buffer_size);
+ let old_presentation_buffer = present_data.data.replace(presentation_buffer);
let mut txn = Transaction::new();
txn.update_image(
present_data.image_key,
@@ -323,14 +368,12 @@ fn update_wr_image(
.lock()
.unwrap()
.send_transaction(webrender_document, txn);
- present_data
- .queued_buffer_ids
- .retain(|b_id| *b_id != buffer_id);
- present_data.available_buffer_ids.push(buffer_id);
+ if let Some(old_presentation_buffer) = old_presentation_buffer {
+ present_data.unmap_old_buffer(old_presentation_buffer)
+ }
} else {
error!("Data not found for {:?}", context_id);
}
- let _ = global.buffer_unmap(buffer_id);
},
_ => error!("Could not map buffer({:?})", buffer_id),
}