Skip to main content

pebble/wgpu/
texture_view.rs

1use crate::wgpu::backend::WGPUBackend;
2use crate::wgpu::flags::TextureUsages;
3use crate::wgpu::texture_format::TextureFormat;
4
5/// A `wgpu::TextureView`, opaque — the [`FrameOperations::Attachment`](crate::rendering::backend::FrameOperations::Attachment)/
6/// [`DepthAttachment`](crate::rendering::backend::FrameOperations::DepthAttachment)
7/// type for [`WGPUBackend`], and [`TextureBuilder::build`]'s return type.
8/// Bundles the backing `wgpu::Texture` alongside the view (kept alive,
9/// never otherwise accessed) — the view alone isn't enough to keep the
10/// underlying resource alive for as long as it's needed.
11pub struct TextureView {
12    view: wgpu::TextureView,
13    _texture: wgpu::Texture,
14}
15
16impl TextureView {
17    pub(crate) fn raw(&self) -> &wgpu::TextureView {
18        &self.view
19    }
20
21    /// Wraps an already-created `wgpu::TextureView` onto an existing
22    /// texture (a `wgpu::Texture` is a cheap, `Arc`-backed handle, so
23    /// `texture` is typically `.clone()`d off whatever already owns it) —
24    /// used by [`GPUCubemap::face_attachment`](super::cubemap::GPUCubemap::face_attachment)
25    /// for a render target into one face of an existing texture, as
26    /// opposed to [`TextureBuilder::build`] which allocates a brand new one.
27    pub(crate) fn from_raw(view: wgpu::TextureView, texture: wgpu::Texture) -> Self {
28        Self { view, _texture: texture }
29    }
30}
31
32/// Builds a one-off GPU-side texture with no source data — a depth buffer,
33/// an off-screen render target — and hands back its
34/// [`TextureView`]. Unlike [`TextureDescriptor`](super::textures::TextureDescriptor),
35/// which loads pixel data from a file/bytes through the asset pipeline,
36/// this allocates an empty texture directly; there's nothing to upload.
37///
38/// ```ignore
39/// let depth_view = TextureBuilder::new(backend.surface_width(), backend.surface_height(), TextureFormat::Depth16Unorm)
40///     .usage(TextureUsages::RENDER_ATTACHMENT)
41///     .build(backend);
42/// ```
43pub struct TextureBuilder<'a> {
44    label: Option<&'a str>,
45    width: u32,
46    height: u32,
47    format: TextureFormat,
48    usage: TextureUsages,
49    mip_level_count: u32,
50    sample_count: u32,
51}
52
53impl<'a> TextureBuilder<'a> {
54    pub fn new(width: u32, height: u32, format: TextureFormat) -> Self {
55        Self {
56            label: None,
57            width,
58            height,
59            format,
60            usage: TextureUsages::empty(),
61            mip_level_count: 1,
62            sample_count: 1,
63        }
64    }
65
66    pub fn label(mut self, label: impl Into<Option<&'a str>>) -> Self {
67        self.label = label.into();
68        self
69    }
70
71    pub fn usage(mut self, usage: TextureUsages) -> Self {
72        self.usage = usage;
73        self
74    }
75
76    pub fn mip_level_count(mut self, count: u32) -> Self {
77        self.mip_level_count = count;
78        self
79    }
80
81    /// Multisample count — must match whatever this texture is used
82    /// alongside (a depth attachment paired with an MSAA color target needs
83    /// the same count as [`WGPUBackend::sample_count`], say). `1` (no
84    /// multisampling) by default.
85    pub fn sample_count(mut self, count: u32) -> Self {
86        self.sample_count = count;
87        self
88    }
89
90    pub fn build(self, backend: &WGPUBackend) -> TextureView {
91        let texture = backend.device.create_texture(&wgpu::TextureDescriptor {
92            label: self.label,
93            size: wgpu::Extent3d { width: self.width, height: self.height, depth_or_array_layers: 1 },
94            mip_level_count: self.mip_level_count,
95            sample_count: self.sample_count,
96            dimension: wgpu::TextureDimension::D2,
97            format: self.format.into(),
98            usage: self.usage.into(),
99            view_formats: &[],
100        });
101        let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
102        TextureView { view, _texture: texture }
103    }
104}