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:
Sam 2025-09-09 05:35:12 +02:00 committed by GitHub
parent 8d2723b2c9
commit 1f0f079203
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 1023 additions and 935 deletions

View file

@ -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()
},
}
}
}