mirror of
https://github.com/servo/servo.git
synced 2025-09-27 23:30:08 +01:00
webgpu: Simplify presentation and handle cleared in script (#38717)
There are many important changes here: - Generalize the presentation buffer into standalone staging buffers that hold their own state. This allow them to be used by getImage. - Move all clear handling to the ScriptThread and send the configuration on each request present/getimage, thus avoiding any recreate/clearing messages. This means that we prepare staging buffers lazily, on the first request. Try run for this change: https://github.com/sagudev/servo/actions/runs/17341982368 Testing: This is covered by existing WebGPU CTS tests. There are some bad expectations updates, but they are also on main (presumably from last update the rendering work) although I think CTS is actually wrong (see https://github.com/gpuweb/cts/issues/4440). Fixes: #36820 Fixes: #37705 Fixes: #33368 (we now keep reference alive in hashmap) --------- Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This commit is contained in:
parent
8d2723b2c9
commit
1f0f079203
29 changed files with 1023 additions and 935 deletions
|
@ -523,13 +523,9 @@ impl ExternalImageHandler for WebrenderExternalImageHandlers {
|
|||
},
|
||||
WebrenderImageHandlerType::WebGPU => {
|
||||
let (source, size) = self.webgpu_handler.as_mut().unwrap().lock(key.0);
|
||||
let buffer = match source {
|
||||
ExternalImageSource::RawData(b) => b,
|
||||
_ => panic!("Wrong type"),
|
||||
};
|
||||
ExternalImage {
|
||||
uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
|
||||
source: ExternalImageSource::RawData(buffer),
|
||||
source,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ use std::ops::Range;
|
|||
|
||||
use ipc_channel::ipc::{IpcSender, IpcSharedMemory};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use webrender_api::ImageFormat;
|
||||
use webrender_api::euclid::default::Size2D;
|
||||
use webrender_api::{ImageDescriptor, ImageDescriptorFlags, ImageFormat};
|
||||
use wgpu_core::device::HostMap;
|
||||
pub use wgpu_core::id::markers::{
|
||||
ComputePassEncoder as ComputePass, RenderPassEncoder as RenderPass,
|
||||
|
@ -22,7 +23,7 @@ pub use wgpu_core::id::{
|
|||
use wgpu_core::id::{ComputePipelineId, DeviceId, QueueId, RenderPipelineId};
|
||||
use wgpu_core::instance::FailedLimit;
|
||||
use wgpu_core::pipeline::CreateShaderModuleError;
|
||||
use wgpu_types::{AdapterInfo, DeviceDescriptor, Features, Limits, TextureFormat};
|
||||
use wgpu_types::{AdapterInfo, COPY_BYTES_PER_ROW_ALIGNMENT, DeviceDescriptor, Features, Limits};
|
||||
|
||||
pub use crate::error::*;
|
||||
pub use crate::ids::*;
|
||||
|
@ -60,17 +61,34 @@ pub struct Adapter {
|
|||
pub struct ContextConfiguration {
|
||||
pub device_id: DeviceId,
|
||||
pub queue_id: QueueId,
|
||||
pub format: TextureFormat,
|
||||
pub format: ImageFormat,
|
||||
pub is_opaque: bool,
|
||||
pub size: Size2D<u32>,
|
||||
}
|
||||
|
||||
impl ContextConfiguration {
|
||||
pub fn format(&self) -> ImageFormat {
|
||||
match self.format {
|
||||
TextureFormat::Rgba8Unorm => ImageFormat::RGBA8,
|
||||
TextureFormat::Bgra8Unorm => ImageFormat::BGRA8,
|
||||
// TODO: wgt::TextureFormat::Rgba16Float
|
||||
_ => unreachable!("Unsupported canvas context format in configuration"),
|
||||
pub fn stride(&self) -> u32 {
|
||||
(self.size.width * self.format.bytes_per_pixel() as u32)
|
||||
.next_multiple_of(COPY_BYTES_PER_ROW_ALIGNMENT)
|
||||
}
|
||||
|
||||
pub fn buffer_size(&self) -> u64 {
|
||||
self.stride() as u64 * self.size.height as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ContextConfiguration> for ImageDescriptor {
|
||||
fn from(config: ContextConfiguration) -> Self {
|
||||
ImageDescriptor {
|
||||
format: config.format,
|
||||
size: config.size.cast().cast_unit(),
|
||||
stride: Some(config.stride() as i32),
|
||||
offset: 0,
|
||||
flags: if config.is_opaque {
|
||||
ImageDescriptorFlags::IS_OPAQUE
|
||||
} else {
|
||||
ImageDescriptorFlags::empty()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ use ipc_channel::ipc::{IpcSender, IpcSharedMemory};
|
|||
use pixels::IpcSnapshot;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use webrender_api::ImageKey;
|
||||
use webrender_api::euclid::default::Size2D;
|
||||
use webrender_api::units::DeviceIntSize;
|
||||
use wgpu_core::Label;
|
||||
use wgpu_core::binding_model::{
|
||||
|
@ -52,6 +53,13 @@ use crate::{
|
|||
WebGPURenderPipelineResponse,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct PendingTexture {
|
||||
pub texture_id: TextureId,
|
||||
pub encoder_id: CommandEncoderId,
|
||||
pub configuration: ContextConfiguration,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub enum WebGPURequest {
|
||||
BufferMapAsync {
|
||||
|
@ -152,22 +160,18 @@ pub enum WebGPURequest {
|
|||
size: DeviceIntSize,
|
||||
sender: IpcSender<(WebGPUContextId, ImageKey)>,
|
||||
},
|
||||
/// Recreates swapchain (if needed)
|
||||
UpdateContext {
|
||||
/// Present texture to WebRender
|
||||
Present {
|
||||
context_id: WebGPUContextId,
|
||||
size: DeviceIntSize,
|
||||
configuration: Option<ContextConfiguration>,
|
||||
pending_texture: Option<PendingTexture>,
|
||||
size: Size2D<u32>,
|
||||
canvas_epoch: Epoch,
|
||||
},
|
||||
/// Reads texture to swapchains buffer and maps it
|
||||
SwapChainPresent {
|
||||
context_id: WebGPUContextId,
|
||||
texture_id: TextureId,
|
||||
encoder_id: CommandEncoderId,
|
||||
canvas_epoch: Option<Epoch>,
|
||||
},
|
||||
/// Obtains image from latest presentation buffer (same as wr update)
|
||||
/// Create [`pixels::Snapshot`] with contents of the last present operation
|
||||
/// or provided pending texture and send it over provided [`IpcSender`].
|
||||
GetImage {
|
||||
context_id: WebGPUContextId,
|
||||
pending_texture: Option<PendingTexture>,
|
||||
sender: IpcSender<IpcSnapshot>,
|
||||
},
|
||||
ValidateTextureDescriptor {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue