aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/webgpu/gputexture.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/webgpu/gputexture.rs')
-rw-r--r--components/script/dom/webgpu/gputexture.rs285
1 files changed, 285 insertions, 0 deletions
diff --git a/components/script/dom/webgpu/gputexture.rs b/components/script/dom/webgpu/gputexture.rs
new file mode 100644
index 00000000000..b37197f4a90
--- /dev/null
+++ b/components/script/dom/webgpu/gputexture.rs
@@ -0,0 +1,285 @@
+/* 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 std::string::String;
+
+use dom_struct::dom_struct;
+use webgpu::wgc::resource;
+use webgpu::{wgt, WebGPU, WebGPURequest, WebGPUTexture, WebGPUTextureView};
+
+use super::gpuconvert::convert_texture_descriptor;
+use crate::dom::bindings::cell::DomRefCell;
+use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
+ GPUTextureAspect, GPUTextureDescriptor, GPUTextureDimension, GPUTextureFormat,
+ GPUTextureMethods, GPUTextureViewDescriptor,
+};
+use crate::dom::bindings::error::Fallible;
+use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
+use crate::dom::bindings::root::{Dom, DomRoot};
+use crate::dom::bindings::str::USVString;
+use crate::dom::globalscope::GlobalScope;
+use crate::dom::gpudevice::GPUDevice;
+use crate::dom::gputextureview::GPUTextureView;
+
+#[dom_struct]
+pub struct GPUTexture {
+ reflector_: Reflector,
+ #[no_trace]
+ texture: WebGPUTexture,
+ label: DomRefCell<USVString>,
+ device: Dom<GPUDevice>,
+ #[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
+ channel: WebGPU,
+ #[ignore_malloc_size_of = "defined in wgpu"]
+ #[no_trace]
+ texture_size: wgt::Extent3d,
+ mip_level_count: u32,
+ sample_count: u32,
+ dimension: GPUTextureDimension,
+ format: GPUTextureFormat,
+ texture_usage: u32,
+}
+
+impl GPUTexture {
+ #[allow(clippy::too_many_arguments)]
+ fn new_inherited(
+ texture: WebGPUTexture,
+ device: &GPUDevice,
+ channel: WebGPU,
+ texture_size: wgt::Extent3d,
+ mip_level_count: u32,
+ sample_count: u32,
+ dimension: GPUTextureDimension,
+ format: GPUTextureFormat,
+ texture_usage: u32,
+ label: USVString,
+ ) -> Self {
+ Self {
+ reflector_: Reflector::new(),
+ texture,
+ label: DomRefCell::new(label),
+ device: Dom::from_ref(device),
+ channel,
+ texture_size,
+ mip_level_count,
+ sample_count,
+ dimension,
+ format,
+ texture_usage,
+ }
+ }
+
+ #[allow(clippy::too_many_arguments)]
+ pub fn new(
+ global: &GlobalScope,
+ texture: WebGPUTexture,
+ device: &GPUDevice,
+ channel: WebGPU,
+ texture_size: wgt::Extent3d,
+ mip_level_count: u32,
+ sample_count: u32,
+ dimension: GPUTextureDimension,
+ format: GPUTextureFormat,
+ texture_usage: u32,
+ label: USVString,
+ ) -> DomRoot<Self> {
+ reflect_dom_object(
+ Box::new(GPUTexture::new_inherited(
+ texture,
+ device,
+ channel,
+ texture_size,
+ mip_level_count,
+ sample_count,
+ dimension,
+ format,
+ texture_usage,
+ label,
+ )),
+ global,
+ )
+ }
+}
+
+impl Drop for GPUTexture {
+ fn drop(&mut self) {
+ if let Err(e) = self
+ .channel
+ .0
+ .send(WebGPURequest::DropTexture(self.texture.0))
+ {
+ warn!(
+ "Failed to send WebGPURequest::DropTexture({:?}) ({})",
+ self.texture.0, e
+ );
+ };
+ }
+}
+
+impl GPUTexture {
+ pub fn id(&self) -> WebGPUTexture {
+ self.texture
+ }
+
+ /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createtexture>
+ pub fn create(
+ device: &GPUDevice,
+ descriptor: &GPUTextureDescriptor,
+ ) -> Fallible<DomRoot<GPUTexture>> {
+ let (desc, size) = convert_texture_descriptor(descriptor, device)?;
+
+ let texture_id = device.global().wgpu_id_hub().create_texture_id();
+
+ device
+ .channel()
+ .0
+ .send(WebGPURequest::CreateTexture {
+ device_id: device.id().0,
+ texture_id,
+ descriptor: desc,
+ })
+ .expect("Failed to create WebGPU Texture");
+
+ let texture = WebGPUTexture(texture_id);
+
+ Ok(GPUTexture::new(
+ &device.global(),
+ texture,
+ device,
+ device.channel().clone(),
+ size,
+ descriptor.mipLevelCount,
+ descriptor.sampleCount,
+ descriptor.dimension,
+ descriptor.format,
+ descriptor.usage,
+ descriptor.parent.label.clone(),
+ ))
+ }
+}
+
+impl GPUTextureMethods<crate::DomTypeHolder> for GPUTexture {
+ /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label>
+ fn Label(&self) -> USVString {
+ self.label.borrow().clone()
+ }
+
+ /// <https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label>
+ fn SetLabel(&self, value: USVString) {
+ *self.label.borrow_mut() = value;
+ }
+
+ /// <https://gpuweb.github.io/gpuweb/#dom-gputexture-createview>
+ fn CreateView(
+ &self,
+ descriptor: &GPUTextureViewDescriptor,
+ ) -> Fallible<DomRoot<GPUTextureView>> {
+ let desc = if !matches!(descriptor.mipLevelCount, Some(0)) &&
+ !matches!(descriptor.arrayLayerCount, Some(0))
+ {
+ Some(resource::TextureViewDescriptor {
+ label: (&descriptor.parent).into(),
+ format: descriptor
+ .format
+ .map(|f| self.device.validate_texture_format_required_features(&f))
+ .transpose()?,
+ dimension: descriptor.dimension.map(|dimension| dimension.into()),
+ range: wgt::ImageSubresourceRange {
+ aspect: match descriptor.aspect {
+ GPUTextureAspect::All => wgt::TextureAspect::All,
+ GPUTextureAspect::Stencil_only => wgt::TextureAspect::StencilOnly,
+ GPUTextureAspect::Depth_only => wgt::TextureAspect::DepthOnly,
+ },
+ base_mip_level: descriptor.baseMipLevel,
+ mip_level_count: descriptor.mipLevelCount,
+ base_array_layer: descriptor.baseArrayLayer,
+ array_layer_count: descriptor.arrayLayerCount,
+ },
+ })
+ } else {
+ self.device
+ .dispatch_error(webgpu::Error::Validation(String::from(
+ "arrayLayerCount and mipLevelCount cannot be 0",
+ )));
+ None
+ };
+
+ let texture_view_id = self.global().wgpu_id_hub().create_texture_view_id();
+
+ self.channel
+ .0
+ .send(WebGPURequest::CreateTextureView {
+ texture_id: self.texture.0,
+ texture_view_id,
+ device_id: self.device.id().0,
+ descriptor: desc,
+ })
+ .expect("Failed to create WebGPU texture view");
+
+ let texture_view = WebGPUTextureView(texture_view_id);
+
+ Ok(GPUTextureView::new(
+ &self.global(),
+ self.channel.clone(),
+ texture_view,
+ self,
+ descriptor.parent.label.clone(),
+ ))
+ }
+
+ /// <https://gpuweb.github.io/gpuweb/#dom-gputexture-destroy>
+ fn Destroy(&self) {
+ if let Err(e) = self
+ .channel
+ .0
+ .send(WebGPURequest::DestroyTexture(self.texture.0))
+ {
+ warn!(
+ "Failed to send WebGPURequest::DestroyTexture({:?}) ({})",
+ self.texture.0, e
+ );
+ };
+ }
+
+ /// <https://gpuweb.github.io/gpuweb/#dom-gputexture-width>
+ fn Width(&self) -> u32 {
+ self.texture_size.width
+ }
+
+ /// <https://gpuweb.github.io/gpuweb/#dom-gputexture-height>
+ fn Height(&self) -> u32 {
+ self.texture_size.height
+ }
+
+ /// <https://gpuweb.github.io/gpuweb/#dom-gputexture-depthorarraylayers>
+ fn DepthOrArrayLayers(&self) -> u32 {
+ self.texture_size.depth_or_array_layers
+ }
+
+ /// <https://gpuweb.github.io/gpuweb/#dom-gputexture-miplevelcount>
+ fn MipLevelCount(&self) -> u32 {
+ self.mip_level_count
+ }
+
+ /// <https://gpuweb.github.io/gpuweb/#dom-gputexture-samplecount>
+ fn SampleCount(&self) -> u32 {
+ self.sample_count
+ }
+
+ /// <https://gpuweb.github.io/gpuweb/#dom-gputexture-dimension>
+ fn Dimension(&self) -> GPUTextureDimension {
+ self.dimension
+ }
+
+ /// <https://gpuweb.github.io/gpuweb/#dom-gputexture-format>
+ fn Format(&self) -> GPUTextureFormat {
+ self.format
+ }
+
+ /// <https://gpuweb.github.io/gpuweb/#dom-gputexture-usage>
+ fn Usage(&self) -> u32 {
+ self.texture_usage
+ }
+}