Skip to main content

wgpu_3dgs_viewer/selection/
buffer.rs

1use glam::*;
2use wgpu::util::DeviceExt;
3
4use crate::core::{self, BufferWrapper, FixedSizeBufferWrapper};
5
6/// A viewport selection texture for the compute bundle created by
7/// [`selection::create_viewport_bundle`](crate::selection::create_viewport_bundle).
8#[derive(Debug, Clone)]
9pub struct ViewportTexture {
10    texture: wgpu::Texture,
11    view: wgpu::TextureView,
12}
13
14impl ViewportTexture {
15    /// Create a new viewport texture.
16    pub fn new(device: &wgpu::Device, size: UVec2) -> Self {
17        let texture = device.create_texture(&wgpu::TextureDescriptor {
18            label: Some("Viewport Selection Texture"),
19            size: wgpu::Extent3d {
20                width: size.x,
21                height: size.y,
22                depth_or_array_layers: 1,
23            },
24            mip_level_count: 1,
25            sample_count: 1,
26            dimension: wgpu::TextureDimension::D2,
27            view_formats: &[],
28            format: wgpu::TextureFormat::R8Unorm,
29            usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
30        });
31
32        let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
33
34        Self { texture, view }
35    }
36
37    /// Get the texture.
38    pub fn texture(&self) -> &wgpu::Texture {
39        &self.texture
40    }
41
42    /// Get the texture view.
43    pub fn view(&self) -> &wgpu::TextureView {
44        &self.view
45    }
46}
47
48/// The position buffer for [`ViewportTexture`].
49///
50/// This is used for [`ViewportTextureRectangleRenderer`](crate::selection::ViewportTextureRectangleRenderer)
51/// and [`ViewportTextureBrushRenderer`](crate::selection::ViewportTextureBrushRenderer).
52#[derive(Debug, Clone)]
53pub struct ViewportTexturePosBuffer(wgpu::Buffer);
54
55impl ViewportTexturePosBuffer {
56    /// Create a new position buffer.
57    pub fn new(device: &wgpu::Device) -> Self {
58        let buffer = device.create_buffer(&wgpu::BufferDescriptor {
59            label: Some("Viewport Selection Texture Pos Buffer"),
60            size: std::mem::size_of::<Vec2>() as wgpu::BufferAddress,
61            usage: Self::DEFAULT_USAGES,
62            mapped_at_creation: false,
63        });
64
65        Self(buffer)
66    }
67
68    /// Update the position buffer.
69    pub fn update(&self, queue: &wgpu::Queue, pos: Vec2) {
70        queue.write_buffer(&self.0, 0, bytemuck::bytes_of(&pos));
71    }
72}
73
74impl BufferWrapper for ViewportTexturePosBuffer {
75    fn buffer(&self) -> &wgpu::Buffer {
76        &self.0
77    }
78}
79
80impl From<ViewportTexturePosBuffer> for wgpu::Buffer {
81    fn from(wrapper: ViewportTexturePosBuffer) -> Self {
82        wrapper.0
83    }
84}
85
86impl TryFrom<wgpu::Buffer> for ViewportTexturePosBuffer {
87    type Error = core::FixedSizeBufferWrapperError;
88
89    fn try_from(buffer: wgpu::Buffer) -> Result<Self, Self::Error> {
90        Self::verify_buffer_size(&buffer).map(|()| Self(buffer))
91    }
92}
93
94impl FixedSizeBufferWrapper for ViewportTexturePosBuffer {
95    type Pod = Vec2;
96}
97
98/// The f32 buffer for [`ViewportTexture`].
99///
100/// This is used for [`ViewportTextureBrushRenderer`](crate::selection::ViewportTextureBrushRenderer).
101#[derive(Debug, Clone)]
102pub struct ViewportTextureF32Buffer(wgpu::Buffer);
103
104impl ViewportTextureF32Buffer {
105    /// Create a new position buffer.
106    pub fn new(device: &wgpu::Device) -> Self {
107        let buffer = device.create_buffer(&wgpu::BufferDescriptor {
108            label: Some("Viewport Selection Texture Pos Buffer"),
109            size: std::mem::size_of::<f32>() as wgpu::BufferAddress,
110            usage: Self::DEFAULT_USAGES,
111            mapped_at_creation: false,
112        });
113
114        Self(buffer)
115    }
116
117    /// Update the f32 buffer.
118    pub fn update(&self, queue: &wgpu::Queue, value: f32) {
119        queue.write_buffer(&self.0, 0, bytemuck::bytes_of(&value));
120    }
121}
122
123impl BufferWrapper for ViewportTextureF32Buffer {
124    fn buffer(&self) -> &wgpu::Buffer {
125        &self.0
126    }
127}
128
129impl From<ViewportTextureF32Buffer> for wgpu::Buffer {
130    fn from(wrapper: ViewportTextureF32Buffer) -> Self {
131        wrapper.0
132    }
133}
134
135impl TryFrom<wgpu::Buffer> for ViewportTextureF32Buffer {
136    type Error = core::FixedSizeBufferWrapperError;
137
138    fn try_from(buffer: wgpu::Buffer) -> Result<Self, Self::Error> {
139        Self::verify_buffer_size(&buffer).map(|()| Self(buffer))
140    }
141}
142
143impl FixedSizeBufferWrapper for ViewportTextureF32Buffer {
144    type Pod = f32;
145}
146
147/// The invert selection buffer for [`Preprocessor`](crate::Preprocessor).
148///
149/// This is used for inverting the selection in the preprocessor, it is essentially just a boolean.
150#[derive(Debug, Clone)]
151pub struct PreprocessorInvertSelectionBuffer(wgpu::Buffer);
152
153impl PreprocessorInvertSelectionBuffer {
154    /// Create a new invert selection buffer.
155    ///
156    /// Note: the initial value is true.
157    pub fn new(device: &wgpu::Device) -> Self {
158        let buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
159            label: Some("Preprocessor Invert Selection Buffer"),
160            contents: bytemuck::bytes_of(&1u32),
161            usage: Self::DEFAULT_USAGES,
162        });
163
164        Self(buffer)
165    }
166
167    /// Update the invert selection buffer.
168    pub fn update(&self, queue: &wgpu::Queue, invert: bool) {
169        let value: u32 = if invert { 1 } else { 0 };
170        queue.write_buffer(&self.0, 0, bytemuck::bytes_of(&value));
171    }
172}
173
174impl BufferWrapper for PreprocessorInvertSelectionBuffer {
175    fn buffer(&self) -> &wgpu::Buffer {
176        &self.0
177    }
178}
179
180impl From<PreprocessorInvertSelectionBuffer> for wgpu::Buffer {
181    fn from(wrapper: PreprocessorInvertSelectionBuffer) -> Self {
182        wrapper.0
183    }
184}
185
186impl TryFrom<wgpu::Buffer> for PreprocessorInvertSelectionBuffer {
187    type Error = core::FixedSizeBufferWrapperError;
188
189    fn try_from(buffer: wgpu::Buffer) -> Result<Self, Self::Error> {
190        Self::verify_buffer_size(&buffer).map(|()| Self(buffer))
191    }
192}
193
194impl FixedSizeBufferWrapper for PreprocessorInvertSelectionBuffer {
195    type Pod = u32;
196}