vulkano_taskgraph/command_buffer/commands/
clear.rs

1use crate::{
2    command_buffer::{RecordingCommandBuffer, Result},
3    resource::{AccessTypes, ImageLayoutType},
4    Id,
5};
6use smallvec::SmallVec;
7use std::{ffi::c_void, mem};
8use vulkano::{
9    buffer::{Buffer, BufferContents},
10    device::DeviceOwned,
11    format::{ClearColorValue, ClearDepthStencilValue},
12    image::{Image, ImageSubresourceRange},
13    DeviceSize, VulkanObject,
14};
15
16/// # Commands to fill resources with new data
17impl RecordingCommandBuffer<'_> {
18    /// Clears a color image with a specific value.
19    pub unsafe fn clear_color_image(
20        &mut self,
21        clear_info: &ClearColorImageInfo<'_>,
22    ) -> Result<&mut Self> {
23        Ok(unsafe { self.clear_color_image_unchecked(clear_info) })
24    }
25
26    pub unsafe fn clear_color_image_unchecked(
27        &mut self,
28        clear_info: &ClearColorImageInfo<'_>,
29    ) -> &mut Self {
30        let &ClearColorImageInfo {
31            image,
32            image_layout,
33            clear_value,
34            regions,
35            _ne: _,
36        } = clear_info;
37
38        let image = unsafe { self.accesses.image_unchecked(image) };
39        let image_layout = AccessTypes::CLEAR_TRANSFER_WRITE.image_layout(image_layout);
40
41        let fns = self.device().fns();
42        let cmd_clear_color_image = fns.v1_0.cmd_clear_color_image;
43
44        if regions.is_empty() {
45            let region_vk = image.subresource_range().to_vk();
46
47            unsafe {
48                cmd_clear_color_image(
49                    self.handle(),
50                    image.handle(),
51                    image_layout.into(),
52                    &clear_value.to_vk(),
53                    1,
54                    &region_vk,
55                )
56            };
57        } else {
58            let regions_vk = regions
59                .iter()
60                .map(ImageSubresourceRange::to_vk)
61                .collect::<SmallVec<[_; 8]>>();
62
63            unsafe {
64                cmd_clear_color_image(
65                    self.handle(),
66                    image.handle(),
67                    image_layout.into(),
68                    &clear_value.to_vk(),
69                    regions_vk.len() as u32,
70                    regions_vk.as_ptr(),
71                )
72            };
73        }
74
75        self
76    }
77
78    /// Clears a depth/stencil image with a specific value.
79    pub unsafe fn clear_depth_stencil_image(
80        &mut self,
81        clear_info: &ClearDepthStencilImageInfo<'_>,
82    ) -> Result<&mut Self> {
83        Ok(unsafe { self.clear_depth_stencil_image_unchecked(clear_info) })
84    }
85
86    pub unsafe fn clear_depth_stencil_image_unchecked(
87        &mut self,
88        clear_info: &ClearDepthStencilImageInfo<'_>,
89    ) -> &mut Self {
90        let &ClearDepthStencilImageInfo {
91            image,
92            image_layout,
93            clear_value,
94            regions,
95            _ne: _,
96        } = clear_info;
97
98        let image = unsafe { self.accesses.image_unchecked(image) };
99        let image_layout = AccessTypes::CLEAR_TRANSFER_WRITE.image_layout(image_layout);
100
101        let fns = self.device().fns();
102        let cmd_clear_depth_stencil_image = fns.v1_0.cmd_clear_depth_stencil_image;
103
104        if regions.is_empty() {
105            let region_vk = image.subresource_range().to_vk();
106
107            unsafe {
108                cmd_clear_depth_stencil_image(
109                    self.handle(),
110                    image.handle(),
111                    image_layout.into(),
112                    &clear_value.to_vk(),
113                    1,
114                    &region_vk,
115                )
116            };
117        } else {
118            let regions_vk = regions
119                .iter()
120                .map(ImageSubresourceRange::to_vk)
121                .collect::<SmallVec<[_; 8]>>();
122
123            unsafe {
124                cmd_clear_depth_stencil_image(
125                    self.handle(),
126                    image.handle(),
127                    image_layout.into(),
128                    &clear_value.to_vk(),
129                    regions_vk.len() as u32,
130                    regions_vk.as_ptr(),
131                )
132            };
133        }
134
135        self
136    }
137
138    /// Fills a region of a buffer with repeated copies of a value.
139    ///
140    /// This function is similar to the `memset` function in C. The `data` parameter is a number
141    /// that will be repeatedly written through the entire buffer.
142    pub unsafe fn fill_buffer(&mut self, fill_info: &FillBufferInfo<'_>) -> Result<&mut Self> {
143        Ok(unsafe { self.fill_buffer_unchecked(fill_info) })
144    }
145
146    pub unsafe fn fill_buffer_unchecked(&mut self, fill_info: &FillBufferInfo<'_>) -> &mut Self {
147        let &FillBufferInfo {
148            dst_buffer,
149            dst_offset,
150            mut size,
151            data,
152            _ne: _,
153        } = fill_info;
154
155        let dst_buffer = unsafe { self.accesses.buffer_unchecked(dst_buffer) };
156
157        if size == 0 {
158            size = dst_buffer.size() & !3;
159        }
160
161        let fns = self.device().fns();
162        let cmd_fill_buffer = fns.v1_0.cmd_fill_buffer;
163        unsafe { cmd_fill_buffer(self.handle(), dst_buffer.handle(), dst_offset, size, data) };
164
165        self
166    }
167
168    /// Writes data to a region of a buffer.
169    pub unsafe fn update_buffer(
170        &mut self,
171        dst_buffer: Id<Buffer>,
172        dst_offset: DeviceSize,
173        data: &(impl BufferContents + ?Sized),
174    ) -> Result<&mut Self> {
175        Ok(unsafe { self.update_buffer_unchecked(dst_buffer, dst_offset, data) })
176    }
177
178    pub unsafe fn update_buffer_unchecked(
179        &mut self,
180        dst_buffer: Id<Buffer>,
181        dst_offset: DeviceSize,
182        data: &(impl BufferContents + ?Sized),
183    ) -> &mut Self {
184        unsafe {
185            self.update_buffer_inner(
186                dst_buffer,
187                dst_offset,
188                <*const _>::cast(data),
189                mem::size_of_val(data) as DeviceSize,
190            )
191        }
192    }
193
194    unsafe fn update_buffer_inner(
195        &mut self,
196        dst_buffer: Id<Buffer>,
197        dst_offset: DeviceSize,
198        data: *const c_void,
199        data_size: DeviceSize,
200    ) -> &mut Self {
201        if data_size == 0 {
202            return self;
203        }
204
205        let dst_buffer = unsafe { self.accesses.buffer_unchecked(dst_buffer) };
206
207        let fns = self.device().fns();
208        let cmd_update_buffer = fns.v1_0.cmd_update_buffer;
209        unsafe {
210            cmd_update_buffer(
211                self.handle(),
212                dst_buffer.handle(),
213                dst_offset,
214                data_size,
215                data,
216            )
217        };
218
219        self
220    }
221}
222
223/// Parameters to clear a color image.
224#[derive(Clone, Debug)]
225pub struct ClearColorImageInfo<'a> {
226    /// The image to clear.
227    ///
228    /// The default value is [`Id::INVALID`], which must be overridden.
229    pub image: Id<Image>,
230
231    /// The layout used for `image` during the clear operation.
232    ///
233    /// The default value is [`ImageLayoutType::Optimal`].
234    pub image_layout: ImageLayoutType,
235
236    /// The color value to clear the image to.
237    ///
238    /// The default value is `ClearColorValue::Float([0.0; 4])`.
239    pub clear_value: ClearColorValue,
240
241    /// The subresource ranges of `image` to clear.
242    ///
243    /// The default value is a single region, covering the whole image.
244    pub regions: &'a [ImageSubresourceRange],
245
246    pub _ne: crate::NonExhaustive<'a>,
247}
248
249impl Default for ClearColorImageInfo<'_> {
250    #[inline]
251    fn default() -> Self {
252        ClearColorImageInfo {
253            image: Id::INVALID,
254            image_layout: ImageLayoutType::Optimal,
255            clear_value: ClearColorValue::Float([0.0; 4]),
256            regions: &[],
257            _ne: crate::NE,
258        }
259    }
260}
261
262/// Parameters to clear a depth/stencil image.
263#[derive(Clone, Debug)]
264pub struct ClearDepthStencilImageInfo<'a> {
265    /// The image to clear.
266    ///
267    /// The default value is [`Id::INVALID`], which must be overridden.
268    pub image: Id<Image>,
269
270    /// The layout used for `image` during the clear operation.
271    ///
272    /// The default value is [`ImageLayoutType::Optimal`].
273    pub image_layout: ImageLayoutType,
274
275    /// The depth/stencil values to clear the image to.
276    ///
277    /// The default value is zero for both.
278    pub clear_value: ClearDepthStencilValue,
279
280    /// The subresource ranges of `image` to clear.
281    ///
282    /// The default value is a single region, covering the whole image.
283    pub regions: &'a [ImageSubresourceRange],
284
285    pub _ne: crate::NonExhaustive<'a>,
286}
287
288impl Default for ClearDepthStencilImageInfo<'_> {
289    #[inline]
290    fn default() -> Self {
291        ClearDepthStencilImageInfo {
292            image: Id::INVALID,
293            image_layout: ImageLayoutType::Optimal,
294            clear_value: ClearDepthStencilValue::default(),
295            regions: &[],
296            _ne: crate::NE,
297        }
298    }
299}
300
301/// Parameters to fill a region of a buffer with repeated copies of a value.
302#[derive(Clone, Debug)]
303pub struct FillBufferInfo<'a> {
304    /// The buffer to fill.
305    ///
306    /// The default value is [`Id::INVALID`], which must be overridden.
307    pub dst_buffer: Id<Buffer>,
308
309    /// The offset in bytes from the start of `dst_buffer` that filling will start from.
310    ///
311    /// This must be a multiple of 4.
312    ///
313    /// The default value is `0`.
314    pub dst_offset: DeviceSize,
315
316    /// The number of bytes to fill.
317    ///
318    /// This must be a multiple of 4.
319    ///
320    /// The default value is the size of `dst_buffer`, rounded down to the nearest multiple of 4.
321    pub size: DeviceSize,
322
323    /// The data to fill with.
324    ///
325    /// The default value is `0`.
326    pub data: u32,
327
328    pub _ne: crate::NonExhaustive<'a>,
329}
330
331impl Default for FillBufferInfo<'_> {
332    #[inline]
333    fn default() -> Self {
334        FillBufferInfo {
335            dst_buffer: Id::INVALID,
336            dst_offset: 0,
337            size: 0,
338            data: 0,
339            _ne: crate::NE,
340        }
341    }
342}