mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
webgpu: renovate gpucanvascontext and webgpu presentation to match the spec (#33521)
* Reimpl gpucanvascontext Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> * ValidateTextureDescriptorAndCreateSwapChain Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> * reconfigure Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> * resize Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> * work around deadlocks in wgpu core Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> * match spec even more by moving all swapchain operations into one updatecontext Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> * error handling Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> * enable one test Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> * label dummy texture Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> * update expect Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> * clean some expectation (they are not flaky anymore) Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> * one more Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> * change for configuration change in update_wr_image Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> * DEFAULT_IMAGE_FORMAT Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> * fixup Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> * introduce WebGPUImageDescriptor Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> --------- Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This commit is contained in:
parent
0b2549f4cb
commit
05ecb8eddb
30 changed files with 795 additions and 483 deletions
|
@ -2951,7 +2951,7 @@ impl Document {
|
|||
self.dirty_webgpu_contexts
|
||||
.borrow_mut()
|
||||
.drain()
|
||||
.for_each(|(_, context)| context.send_swap_chain_present());
|
||||
.for_each(|(_, context)| context.update_rendering_of_webgpu_canvas());
|
||||
}
|
||||
|
||||
pub fn id_map(&self) -> Ref<HashMapTracedValues<Atom, Vec<Dom<Element>>>> {
|
||||
|
|
|
@ -2,6 +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 std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use dom_struct::dom_struct;
|
||||
use euclid::default::Size2D;
|
||||
|
@ -9,20 +12,25 @@ use ipc_channel::ipc;
|
|||
use script_layout_interface::HTMLCanvasDataSource;
|
||||
use webgpu::swapchain::WebGPUContextId;
|
||||
use webgpu::wgc::id;
|
||||
use webgpu::{WebGPU, WebGPURequest, WebGPUTexture, PRESENTATION_BUFFER_COUNT};
|
||||
use webrender_api::{units, ImageFormat, ImageKey};
|
||||
use webgpu::{
|
||||
ContextConfiguration, WebGPU, WebGPURequest, WebGPUTexture, PRESENTATION_BUFFER_COUNT,
|
||||
};
|
||||
use webrender_api::units::DeviceIntSize;
|
||||
use webrender_api::ImageKey;
|
||||
|
||||
use super::bindings::codegen::Bindings::WebGPUBinding::GPUTextureUsageConstants;
|
||||
use super::bindings::codegen::Bindings::WebGPUBinding::{
|
||||
GPUCanvasAlphaMode, GPUTextureUsageConstants,
|
||||
};
|
||||
use super::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas;
|
||||
use super::bindings::error::{Error, Fallible};
|
||||
use super::bindings::root::MutNullableDom;
|
||||
use super::bindings::str::USVString;
|
||||
use super::gpuconvert::convert_texture_descriptor;
|
||||
use super::gputexture::GPUTexture;
|
||||
use crate::dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElement_Binding::HTMLCanvasElementMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUTexture_Binding::GPUTextureMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
|
||||
GPUCanvasConfiguration, GPUCanvasContextMethods, GPUDeviceMethods, GPUExtent3D,
|
||||
GPUExtent3DDict, GPUObjectDescriptorBase, GPUTextureDescriptor, GPUTextureDimension,
|
||||
GPUTextureFormat,
|
||||
};
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
||||
|
@ -85,6 +93,29 @@ impl malloc_size_of::MallocSizeOf for HTMLCanvasElementOrOffscreenCanvas {
|
|||
}
|
||||
}
|
||||
|
||||
impl HTMLCanvasElementOrOffscreenCanvas {
|
||||
fn size(&self) -> Size2D<u64> {
|
||||
match self {
|
||||
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => {
|
||||
canvas.get_size().cast()
|
||||
},
|
||||
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => canvas.get_size(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, JSTraceable, MallocSizeOf)]
|
||||
/// Helps observe changes on swapchain
|
||||
struct DrawingBuffer {
|
||||
#[no_trace]
|
||||
size: DeviceIntSize,
|
||||
/// image is transparent black
|
||||
cleared: bool,
|
||||
#[ignore_malloc_size_of = "Defined in wgpu"]
|
||||
#[no_trace]
|
||||
config: Option<ContextConfiguration>,
|
||||
}
|
||||
|
||||
#[dom_struct]
|
||||
pub struct GPUCanvasContext {
|
||||
reflector_: Reflector,
|
||||
|
@ -99,14 +130,34 @@ pub struct GPUCanvasContext {
|
|||
webrender_image: ImageKey,
|
||||
#[no_trace]
|
||||
context_id: WebGPUContextId,
|
||||
#[ignore_malloc_size_of = "manual writing is hard"]
|
||||
/// <https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-configuration-slot>
|
||||
configuration: RefCell<Option<GPUCanvasConfiguration>>,
|
||||
/// <https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-texturedescriptor-slot>
|
||||
texture_descriptor: RefCell<Option<GPUTextureDescriptor>>,
|
||||
/// Conceptually <https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-drawingbuffer-slot>
|
||||
drawing_buffer: RefCell<DrawingBuffer>,
|
||||
/// <https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-currenttexture-slot>
|
||||
texture: MutNullableDom<GPUTexture>,
|
||||
current_texture: MutNullableDom<GPUTexture>,
|
||||
}
|
||||
|
||||
impl GPUCanvasContext {
|
||||
fn new_inherited(canvas: HTMLCanvasElementOrOffscreenCanvas, channel: WebGPU) -> Self {
|
||||
fn new_inherited(
|
||||
global: &GlobalScope,
|
||||
canvas: HTMLCanvasElementOrOffscreenCanvas,
|
||||
channel: WebGPU,
|
||||
) -> Self {
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
if let Err(e) = channel.0.send(WebGPURequest::CreateContext(sender)) {
|
||||
let size = canvas.size().cast().cast_unit();
|
||||
let mut buffer_ids = ArrayVec::<id::BufferId, PRESENTATION_BUFFER_COUNT>::new();
|
||||
for _ in 0..PRESENTATION_BUFFER_COUNT {
|
||||
buffer_ids.push(global.wgpu_id_hub().create_buffer_id());
|
||||
}
|
||||
if let Err(e) = channel.0.send(WebGPURequest::CreateContext {
|
||||
buffer_ids,
|
||||
size,
|
||||
sender,
|
||||
}) {
|
||||
warn!("Failed to send CreateContext ({:?})", e);
|
||||
}
|
||||
let (external_id, webrender_image) = receiver.recv().unwrap();
|
||||
|
@ -116,13 +167,21 @@ impl GPUCanvasContext {
|
|||
canvas,
|
||||
webrender_image,
|
||||
context_id: WebGPUContextId(external_id.0),
|
||||
texture: MutNullableDom::default(),
|
||||
drawing_buffer: RefCell::new(DrawingBuffer {
|
||||
size,
|
||||
cleared: true,
|
||||
..Default::default()
|
||||
}),
|
||||
configuration: RefCell::new(None),
|
||||
texture_descriptor: RefCell::new(None),
|
||||
current_texture: MutNullableDom::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(global: &GlobalScope, canvas: &HTMLCanvasElement, channel: WebGPU) -> DomRoot<Self> {
|
||||
reflect_dom_object(
|
||||
Box::new(GPUCanvasContext::new_inherited(
|
||||
global,
|
||||
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(canvas)),
|
||||
channel,
|
||||
)),
|
||||
|
@ -131,17 +190,93 @@ impl GPUCanvasContext {
|
|||
}
|
||||
}
|
||||
|
||||
// Abstract ops from spec
|
||||
impl GPUCanvasContext {
|
||||
fn layout_handle(&self) -> HTMLCanvasDataSource {
|
||||
HTMLCanvasDataSource::WebGPU(self.webrender_image)
|
||||
/// <https://gpuweb.github.io/gpuweb/#abstract-opdef-gputexturedescriptor-for-the-canvas-and-configuration>
|
||||
fn texture_descriptor_for_canvas(
|
||||
&self,
|
||||
configuration: &GPUCanvasConfiguration,
|
||||
) -> GPUTextureDescriptor {
|
||||
let size = self.size();
|
||||
GPUTextureDescriptor {
|
||||
format: configuration.format,
|
||||
// We need to add `COPY_SRC` so we can copy texture to presentation buffer
|
||||
// causes FAIL on webgpu:web_platform,canvas,configure:usage:*
|
||||
usage: configuration.usage | GPUTextureUsageConstants::COPY_SRC,
|
||||
size: GPUExtent3D::GPUExtent3DDict(GPUExtent3DDict {
|
||||
width: size.width as u32,
|
||||
height: size.height as u32,
|
||||
depthOrArrayLayers: 1,
|
||||
}),
|
||||
viewFormats: configuration.viewFormats.clone(),
|
||||
// other members to default
|
||||
mipLevelCount: 1,
|
||||
sampleCount: 1,
|
||||
parent: GPUObjectDescriptorBase {
|
||||
label: USVString::default(),
|
||||
},
|
||||
dimension: GPUTextureDimension::_2d,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_swap_chain_present(&self) {
|
||||
let texture_id = self.texture_id().unwrap().0;
|
||||
/// <https://gpuweb.github.io/gpuweb/#abstract-opdef-expire-the-current-texture>
|
||||
fn expire_current_texture(&self) {
|
||||
if let Some(current_texture) = self.current_texture.take() {
|
||||
// Make copy of texture content
|
||||
self.send_swap_chain_present(current_texture.id());
|
||||
// Step 1
|
||||
current_texture.Destroy()
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://gpuweb.github.io/gpuweb/#abstract-opdef-replace-the-drawing-buffer>
|
||||
fn replace_drawing_buffer(&self) {
|
||||
// Step 1
|
||||
self.expire_current_texture();
|
||||
// Step 2
|
||||
let configuration = self.configuration.borrow();
|
||||
// Step 3
|
||||
let mut drawing_buffer = self.drawing_buffer.borrow_mut();
|
||||
drawing_buffer.size = self.size().cast().cast_unit();
|
||||
drawing_buffer.cleared = true;
|
||||
if let Some(configuration) = configuration.as_ref() {
|
||||
drawing_buffer.config = Some(ContextConfiguration {
|
||||
device_id: configuration.device.id().0,
|
||||
queue_id: configuration.device.queue_id().0,
|
||||
format: configuration.format.into(),
|
||||
is_opaque: matches!(configuration.alphaMode, GPUCanvasAlphaMode::Opaque),
|
||||
});
|
||||
} else {
|
||||
drawing_buffer.config.take();
|
||||
};
|
||||
// TODO: send less
|
||||
self.channel
|
||||
.0
|
||||
.send(WebGPURequest::UpdateContext {
|
||||
context_id: self.context_id,
|
||||
size: drawing_buffer.size,
|
||||
configuration: drawing_buffer.config.clone(),
|
||||
})
|
||||
.expect("Failed to update webgpu context");
|
||||
}
|
||||
}
|
||||
|
||||
// Internal helper methods
|
||||
impl GPUCanvasContext {
|
||||
fn layout_handle(&self) -> HTMLCanvasDataSource {
|
||||
if self.drawing_buffer.borrow().cleared {
|
||||
HTMLCanvasDataSource::Empty
|
||||
} else {
|
||||
HTMLCanvasDataSource::WebGPU(self.webrender_image)
|
||||
}
|
||||
}
|
||||
|
||||
fn send_swap_chain_present(&self, texture_id: WebGPUTexture) {
|
||||
self.drawing_buffer.borrow_mut().cleared = false;
|
||||
let encoder_id = self.global().wgpu_id_hub().create_command_encoder_id();
|
||||
if let Err(e) = self.channel.0.send(WebGPURequest::SwapChainPresent {
|
||||
context_id: self.context_id,
|
||||
texture_id,
|
||||
texture_id: texture_id.0,
|
||||
encoder_id,
|
||||
}) {
|
||||
warn!(
|
||||
|
@ -151,29 +286,42 @@ impl GPUCanvasContext {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn context_id(&self) -> WebGPUContextId {
|
||||
fn size(&self) -> Size2D<u64> {
|
||||
self.canvas.size()
|
||||
}
|
||||
}
|
||||
|
||||
// public methods for canvas handling
|
||||
// these methods should probably be behind trait for all canvases
|
||||
impl GPUCanvasContext {
|
||||
pub(crate) fn context_id(&self) -> WebGPUContextId {
|
||||
self.context_id
|
||||
}
|
||||
|
||||
pub fn texture_id(&self) -> Option<WebGPUTexture> {
|
||||
self.texture.get().map(|t| t.id())
|
||||
}
|
||||
|
||||
pub fn mark_as_dirty(&self) {
|
||||
pub(crate) fn mark_as_dirty(&self) {
|
||||
if let HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) = &self.canvas {
|
||||
canvas.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
let document = document_from_node(&**canvas);
|
||||
document.add_dirty_webgpu_canvas(self);
|
||||
}
|
||||
// TODO(sagudev): offscreen canvas also dirty?
|
||||
}
|
||||
|
||||
fn size(&self) -> Size2D<u64> {
|
||||
match &self.canvas {
|
||||
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => {
|
||||
Size2D::new(canvas.Width() as u64, canvas.Height() as u64)
|
||||
},
|
||||
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => canvas.get_size(),
|
||||
/// <https://gpuweb.github.io/gpuweb/#abstract-opdef-updating-the-rendering-of-a-webgpu-canvas>
|
||||
pub(crate) fn update_rendering_of_webgpu_canvas(&self) {
|
||||
// Step 1
|
||||
self.expire_current_texture();
|
||||
}
|
||||
|
||||
/// <https://gpuweb.github.io/gpuweb/#abstract-opdef-update-the-canvas-size>
|
||||
pub(crate) fn resize(&self) {
|
||||
// Step 1
|
||||
self.replace_drawing_buffer();
|
||||
// Step 2
|
||||
let configuration = self.configuration.borrow();
|
||||
// Step 3
|
||||
if let Some(configuration) = configuration.as_ref() {
|
||||
self.texture_descriptor
|
||||
.replace(Some(self.texture_descriptor_for_canvas(configuration)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -192,110 +340,84 @@ impl GPUCanvasContextMethods for GPUCanvasContext {
|
|||
|
||||
/// <https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-configure>
|
||||
fn Configure(&self, configuration: &GPUCanvasConfiguration) -> Fallible<()> {
|
||||
// Step 1 is let
|
||||
// Step 2
|
||||
configuration
|
||||
.device
|
||||
.validate_texture_format_required_features(&configuration.format)?;
|
||||
// Mapping between wr and wgpu can be determined by inspecting
|
||||
// https://github.com/gfx-rs/wgpu/blob/9b36a3e129da04b018257564d5129caff240cb75/wgpu-hal/src/gles/conv.rs#L10
|
||||
// https://github.com/servo/webrender/blob/1e73f384a7a86e413f91e9e430436a9bd83381cd/webrender/src/device/gl.rs#L4064
|
||||
let format = match configuration.format {
|
||||
GPUTextureFormat::R8unorm => ImageFormat::R8,
|
||||
GPUTextureFormat::Bgra8unorm | GPUTextureFormat::Bgra8unorm_srgb => ImageFormat::BGRA8,
|
||||
GPUTextureFormat::Rgba8unorm | GPUTextureFormat::Rgba8unorm_srgb => ImageFormat::RGBA8,
|
||||
GPUTextureFormat::Rgba32float => ImageFormat::RGBAF32,
|
||||
GPUTextureFormat::Rgba32sint => ImageFormat::RGBAI32,
|
||||
GPUTextureFormat::Rg8unorm => ImageFormat::RG8,
|
||||
_ => {
|
||||
return Err(Error::Type(format!(
|
||||
"SwapChain format({:?}) not supported",
|
||||
configuration.format
|
||||
)))
|
||||
},
|
||||
};
|
||||
|
||||
// Step 3
|
||||
for view_format in &configuration.viewFormats {
|
||||
configuration
|
||||
.device
|
||||
.validate_texture_format_required_features(view_format)?;
|
||||
}
|
||||
|
||||
// Step 4
|
||||
let size = self.size();
|
||||
let text_desc = GPUTextureDescriptor {
|
||||
format: configuration.format,
|
||||
mipLevelCount: 1,
|
||||
sampleCount: 1,
|
||||
// We need to add `COPY_SRC` so we can copy texture to presentation buffer
|
||||
usage: configuration.usage | GPUTextureUsageConstants::COPY_SRC,
|
||||
size: GPUExtent3D::GPUExtent3DDict(GPUExtent3DDict {
|
||||
width: size.width as u32,
|
||||
height: size.height as u32,
|
||||
depthOrArrayLayers: 1,
|
||||
}),
|
||||
viewFormats: configuration.viewFormats.clone(),
|
||||
// other members to default
|
||||
parent: GPUObjectDescriptorBase {
|
||||
label: USVString::default(),
|
||||
},
|
||||
dimension: GPUTextureDimension::_2d,
|
||||
};
|
||||
let descriptor = self.texture_descriptor_for_canvas(configuration);
|
||||
|
||||
// Step 8
|
||||
let mut buffer_ids = ArrayVec::<id::BufferId, PRESENTATION_BUFFER_COUNT>::new();
|
||||
for _ in 0..PRESENTATION_BUFFER_COUNT {
|
||||
buffer_ids.push(self.global().wgpu_id_hub().create_buffer_id());
|
||||
}
|
||||
// Step 2&3
|
||||
let (mut desc, _) = convert_texture_descriptor(&descriptor, &configuration.device)?;
|
||||
desc.label = Some(Cow::Borrowed(
|
||||
"dummy texture for texture descriptor validation",
|
||||
));
|
||||
|
||||
// Step 5
|
||||
self.configuration.replace(Some(configuration.clone()));
|
||||
|
||||
// Step 6
|
||||
self.texture_descriptor.replace(Some(descriptor));
|
||||
|
||||
// Step 7
|
||||
self.replace_drawing_buffer();
|
||||
|
||||
// Step 8: Validate texture descriptor
|
||||
let texture_id = self.global().wgpu_id_hub().create_texture_id();
|
||||
self.channel
|
||||
.0
|
||||
.send(WebGPURequest::CreateSwapChain {
|
||||
.send(WebGPURequest::ValidateTextureDescriptor {
|
||||
device_id: configuration.device.id().0,
|
||||
queue_id: configuration.device.GetQueue().id().0,
|
||||
buffer_ids,
|
||||
context_id: self.context_id,
|
||||
image_key: self.webrender_image,
|
||||
format,
|
||||
size: units::DeviceIntSize::new(size.width as i32, size.height as i32),
|
||||
texture_id,
|
||||
descriptor: desc,
|
||||
})
|
||||
.expect("Failed to create WebGPU SwapChain");
|
||||
|
||||
self.texture.set(Some(
|
||||
&configuration.device.CreateTexture(&text_desc).unwrap(),
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// <https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-unconfigure>
|
||||
fn Unconfigure(&self) {
|
||||
if let Some(texture) = self.texture.take() {
|
||||
if let Err(e) = self.channel.0.send(WebGPURequest::DestroySwapChain {
|
||||
context_id: self.context_id,
|
||||
image_key: self.webrender_image,
|
||||
}) {
|
||||
warn!(
|
||||
"Failed to send DestroySwapChain-ImageKey({:?}) ({})",
|
||||
self.webrender_image, e
|
||||
);
|
||||
}
|
||||
drop(texture);
|
||||
}
|
||||
// Step 1
|
||||
self.configuration.take();
|
||||
// Step 2
|
||||
self.current_texture.take();
|
||||
// Step 3
|
||||
self.replace_drawing_buffer();
|
||||
}
|
||||
|
||||
/// <https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-getcurrenttexture>
|
||||
fn GetCurrentTexture(&self) -> Fallible<DomRoot<GPUTexture>> {
|
||||
// Step 5.
|
||||
// Step 1
|
||||
let configuration = self.configuration.borrow();
|
||||
let Some(configuration) = configuration.as_ref() else {
|
||||
return Err(Error::InvalidState);
|
||||
};
|
||||
// Step 2
|
||||
let texture_descriptor = self.texture_descriptor.borrow();
|
||||
let texture_descriptor = texture_descriptor.as_ref().unwrap();
|
||||
// Step 6
|
||||
let current_texture = if let Some(current_texture) = self.current_texture.get() {
|
||||
current_texture
|
||||
} else {
|
||||
// Step 3&4
|
||||
self.replace_drawing_buffer();
|
||||
let current_texture = configuration.device.CreateTexture(&texture_descriptor)?;
|
||||
self.current_texture.set(Some(¤t_texture));
|
||||
current_texture
|
||||
};
|
||||
// Step 5
|
||||
self.mark_as_dirty();
|
||||
// Step 6.
|
||||
self.texture.get().ok_or(Error::InvalidState)
|
||||
// Step 6
|
||||
Ok(current_texture)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for GPUCanvasContext {
|
||||
fn drop(&mut self) {
|
||||
self.Unconfigure()
|
||||
if let Err(e) = self.channel.0.send(WebGPURequest::DestroyContext {
|
||||
context_id: self.context_id,
|
||||
}) {
|
||||
warn!(
|
||||
"Failed to send DestroySwapChain-ImageKey({:?}) ({})",
|
||||
self.webrender_image, e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,10 +8,11 @@ use std::num::NonZeroU64;
|
|||
use webgpu::wgc::binding_model::{BindGroupEntry, BindingResource, BufferBinding};
|
||||
use webgpu::wgc::command as wgpu_com;
|
||||
use webgpu::wgc::pipeline::ProgrammableStageDescriptor;
|
||||
use webgpu::wgc::resource::TextureDescriptor;
|
||||
use webgpu::wgt::{self, AstcBlock, AstcChannel};
|
||||
|
||||
use super::bindings::codegen::Bindings::WebGPUBinding::{
|
||||
GPUProgrammableStage, GPUTextureDimension,
|
||||
GPUProgrammableStage, GPUTextureDescriptor, GPUTextureDimension,
|
||||
};
|
||||
use super::bindings::error::Error;
|
||||
use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
|
||||
|
@ -506,6 +507,7 @@ impl<'a> From<&GPUObjectDescriptorBase> for Option<Cow<'a, str>> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert_bind_group_layout_entry(
|
||||
bgle: &GPUBindGroupLayoutEntry,
|
||||
device: &GPUDevice,
|
||||
|
@ -581,6 +583,28 @@ pub fn convert_bind_group_layout_entry(
|
|||
}))
|
||||
}
|
||||
|
||||
pub fn convert_texture_descriptor(
|
||||
descriptor: &GPUTextureDescriptor,
|
||||
device: &GPUDevice,
|
||||
) -> Fallible<(TextureDescriptor<'static>, wgt::Extent3d)> {
|
||||
let size = (&descriptor.size).try_into()?;
|
||||
let desc = TextureDescriptor {
|
||||
label: (&descriptor.parent).into(),
|
||||
size,
|
||||
mip_level_count: descriptor.mipLevelCount,
|
||||
sample_count: descriptor.sampleCount,
|
||||
dimension: descriptor.dimension.into(),
|
||||
format: device.validate_texture_format_required_features(&descriptor.format)?,
|
||||
usage: wgt::TextureUsages::from_bits_retain(descriptor.usage),
|
||||
view_formats: descriptor
|
||||
.viewFormats
|
||||
.iter()
|
||||
.map(|tf| device.validate_texture_format_required_features(tf))
|
||||
.collect::<Fallible<_>>()?,
|
||||
};
|
||||
Ok((desc, size))
|
||||
}
|
||||
|
||||
impl TryFrom<&GPUColor> for wgt::Color {
|
||||
type Error = Error;
|
||||
|
||||
|
|
|
@ -153,6 +153,10 @@ impl GPUDevice {
|
|||
self.device
|
||||
}
|
||||
|
||||
pub fn queue_id(&self) -> webgpu::WebGPUQueue {
|
||||
self.default_queue.id()
|
||||
}
|
||||
|
||||
pub fn channel(&self) -> WebGPU {
|
||||
self.channel.clone()
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ use webgpu::wgc::resource;
|
|||
use webgpu::{wgt, WebGPU, WebGPURequest, WebGPUTexture, WebGPUTextureView};
|
||||
|
||||
use super::bindings::error::Fallible;
|
||||
use super::gpuconvert::convert_texture_descriptor;
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
|
||||
GPUTextureAspect, GPUTextureDescriptor, GPUTextureDimension, GPUTextureFormat,
|
||||
|
@ -127,21 +128,7 @@ impl GPUTexture {
|
|||
device: &GPUDevice,
|
||||
descriptor: &GPUTextureDescriptor,
|
||||
) -> Fallible<DomRoot<GPUTexture>> {
|
||||
let size = (&descriptor.size).try_into()?;
|
||||
let desc = wgt::TextureDescriptor {
|
||||
label: (&descriptor.parent).into(),
|
||||
size,
|
||||
mip_level_count: descriptor.mipLevelCount,
|
||||
sample_count: descriptor.sampleCount,
|
||||
dimension: descriptor.dimension.into(),
|
||||
format: device.validate_texture_format_required_features(&descriptor.format)?,
|
||||
usage: wgt::TextureUsages::from_bits_retain(descriptor.usage),
|
||||
view_formats: descriptor
|
||||
.viewFormats
|
||||
.iter()
|
||||
.map(|tf| device.validate_texture_format_required_features(tf))
|
||||
.collect::<Fallible<_>>()?,
|
||||
};
|
||||
let (desc, size) = convert_texture_descriptor(descriptor, device)?;
|
||||
|
||||
let texture_id = device.global().wgpu_id_hub().create_texture_id();
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ impl HTMLCanvasElement {
|
|||
},
|
||||
CanvasContext::WebGL(ref context) => context.recreate(size),
|
||||
CanvasContext::WebGL2(ref context) => context.recreate(size),
|
||||
CanvasContext::WebGPU(_) => unimplemented!(),
|
||||
CanvasContext::WebGPU(ref context) => context.resize(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue