wgpu/api/texture.rs
1#[cfg(wgpu_core)]
2use core::ops::Deref;
3
4use crate::*;
5
6/// Handle to a texture on the GPU.
7///
8/// It can be created with [`Device::create_texture`].
9///
10/// Corresponds to [WebGPU `GPUTexture`](https://gpuweb.github.io/gpuweb/#texture-interface).
11#[derive(Debug, Clone)]
12pub struct Texture {
13 pub(crate) inner: dispatch::DispatchTexture,
14}
15#[cfg(send_sync)]
16static_assertions::assert_impl_all!(Texture: Send, Sync);
17
18crate::cmp::impl_eq_ord_hash_proxy!(Texture => .inner);
19
20impl Texture {
21 /// Get the [`wgpu_hal`] texture from this `Texture`.
22 ///
23 /// Find the Api struct corresponding to the active backend in [`wgpu_hal::api`],
24 /// and pass that struct to the to the `A` type parameter.
25 ///
26 /// Returns a guard that dereferences to the type of the hal backend
27 /// which implements [`A::Texture`].
28 ///
29 /// # Types
30 ///
31 /// The returned type depends on the backend:
32 ///
33 #[doc = crate::macros::hal_type_vulkan!("Texture")]
34 #[doc = crate::macros::hal_type_metal!("Texture")]
35 #[doc = crate::macros::hal_type_dx12!("Texture")]
36 #[doc = crate::macros::hal_type_gles!("Texture")]
37 ///
38 /// # Deadlocks
39 ///
40 /// - The returned guard holds a read-lock on a device-local "destruction"
41 /// lock, which will cause all calls to `destroy` to block until the
42 /// guard is released.
43 ///
44 /// # Errors
45 ///
46 /// This method will return None if:
47 /// - The texture is not from the backend specified by `A`.
48 /// - The texture is from [`Backend::BrowserWebGpu`].
49 /// (Use `Texture::as_webgpu()` instead.)
50 /// - The texture is from a custom backend.
51 ///
52 /// # Safety
53 ///
54 /// - The returned resource must not be destroyed unless the guard
55 /// is the last reference to it and it is not in use by the GPU.
56 /// The guard and handle may be dropped at any time however.
57 /// - All the safety requirements of wgpu-hal must be upheld.
58 ///
59 /// [`A::Texture`]: hal::Api::Texture
60 #[cfg(wgpu_core)]
61 pub unsafe fn as_hal<A: hal::Api>(&self) -> Option<impl Deref<Target = A::Texture>> {
62 let texture = self.inner.as_core_opt()?;
63 unsafe { texture.as_hal::<A>() }
64 }
65
66 /// Returns the underlying [`webgpu::GpuTexture`] handle if this `Texture`
67 /// is on the WebGPU backend.
68 ///
69 /// Use this on the WebGPU backend instead of [`Self::as_hal`].
70 ///
71 /// The returned handle is the same JS object wgpu uses internally; it can
72 /// be passed to other WebGPU-aware JS APIs, used for identity comparison,
73 /// or fed back into [`Device::create_texture_from_webgpu_handle`].
74 #[cfg(webgpu)]
75 pub fn as_webgpu(&self) -> Option<&webgpu::GpuTexture> {
76 self.inner.as_webgpu_opt().map(|wt| &wt.inner)
77 }
78
79 #[cfg(custom)]
80 /// Returns custom implementation of Texture (if custom backend and is internally T)
81 pub fn as_custom<T: custom::TextureInterface>(&self) -> Option<&T> {
82 self.inner.as_custom()
83 }
84
85 #[cfg(custom)]
86 /// Creates a texture from already created custom implementation with the given description
87 pub fn from_custom<T: custom::TextureInterface>(texture: T) -> Self {
88 Self {
89 inner: dispatch::DispatchTexture::custom(texture),
90 }
91 }
92
93 /// Creates a view of this texture, specifying an interpretation of its texels and
94 /// possibly a subset of its layers and mip levels.
95 ///
96 /// Texture views are needed to use a texture as a binding in a [`BindGroup`]
97 /// or as an attachment in a [`RenderPass`].
98 pub fn create_view(&self, desc: &TextureViewDescriptor<'_>) -> TextureView {
99 let view = self.inner.create_view(desc);
100
101 TextureView {
102 inner: view,
103 texture: self.clone(),
104 }
105 }
106
107 /// Destroy the associated native resources as soon as possible.
108 pub fn destroy(&self) {
109 self.inner.destroy();
110 }
111
112 /// Make an `TexelCopyTextureInfo` representing the whole texture.
113 pub fn as_image_copy(&self) -> TexelCopyTextureInfo<'_> {
114 TexelCopyTextureInfo {
115 texture: self,
116 mip_level: 0,
117 origin: Origin3d::ZERO,
118 aspect: TextureAspect::All,
119 }
120 }
121
122 /// Returns the size of this `Texture`.
123 ///
124 /// This is always equal to the `size` that was specified when creating the texture.
125 pub fn size(&self) -> Extent3d {
126 self.inner.size()
127 }
128
129 /// Returns the width of this `Texture`.
130 ///
131 /// This is always equal to the `size.width` that was specified when creating the texture.
132 pub fn width(&self) -> u32 {
133 self.inner.size().width
134 }
135
136 /// Returns the height of this `Texture`.
137 ///
138 /// This is always equal to the `size.height` that was specified when creating the texture.
139 pub fn height(&self) -> u32 {
140 self.inner.size().height
141 }
142
143 /// Returns the depth or layer count of this `Texture`.
144 ///
145 /// This is always equal to the `size.depth_or_array_layers` that was specified when creating the texture.
146 pub fn depth_or_array_layers(&self) -> u32 {
147 self.inner.size().depth_or_array_layers
148 }
149
150 /// Returns the mip_level_count of this `Texture`.
151 ///
152 /// This is always equal to the `mip_level_count` that was specified when creating the texture.
153 pub fn mip_level_count(&self) -> u32 {
154 self.inner.mip_level_count()
155 }
156
157 /// Returns the sample_count of this `Texture`.
158 ///
159 /// This is always equal to the `sample_count` that was specified when creating the texture.
160 pub fn sample_count(&self) -> u32 {
161 self.inner.sample_count()
162 }
163
164 /// Returns the dimension of this `Texture`.
165 ///
166 /// This is always equal to the `dimension` that was specified when creating the texture.
167 pub fn dimension(&self) -> TextureDimension {
168 self.inner.dimension()
169 }
170
171 /// Returns the format of this `Texture`.
172 ///
173 /// This is always equal to the `format` that was specified when creating the texture.
174 pub fn format(&self) -> TextureFormat {
175 self.inner.format()
176 }
177
178 /// Returns the allowed usages of this `Texture`.
179 ///
180 /// This is always equal to the `usage` that was specified when creating the texture.
181 pub fn usage(&self) -> TextureUsages {
182 self.inner.usage()
183 }
184
185 /// Marks this texture's contents as already initialized, skipping wgpu's
186 /// lazy zero-initialization of it.
187 ///
188 /// This is a no-op on backends without a concept of lazy
189 /// zero-initialization, such as WebGPU.
190 ///
191 /// # Safety
192 ///
193 /// The entire contents of the texture must already be initialized, e.g. by
194 /// writing to it through the handle returned by [`Texture::as_hal`].
195 pub unsafe fn mark_externally_initialized(&self) {
196 unsafe { self.inner.mark_externally_initialized() }
197 }
198}
199
200/// Describes a [`Texture`].
201///
202/// For use with [`Device::create_texture`].
203///
204/// Corresponds to [WebGPU `GPUTextureDescriptor`](
205/// https://gpuweb.github.io/gpuweb/#dictdef-gputexturedescriptor).
206pub type TextureDescriptor<'a> = wgt::TextureDescriptor<Label<'a>, &'a [TextureFormat]>;
207static_assertions::assert_impl_all!(TextureDescriptor<'_>: Send, Sync);