atagen

monolith

public
Star0
Watch0
1d62be4ff79ce38908a8b8a526f4bc96a7721751
1
ssh://brewery@pls.lobotomise.me:33/atagen/monolith.git

Blame: crates/render-vk/src/image.rs

824bf02b6e55atagen2026-10-16 09:15 UTC1
use crate::Error;
824bf02b6e55atagen2026-10-16 09:15 UTC2
use crate::device::Shared;
824bf02b6e55atagen2026-10-16 09:15 UTC3
use crate::format::{components, vk_format};
824bf02b6e55atagen2026-10-16 09:15 UTC4
use ash::vk;
824bf02b6e55atagen2026-10-16 09:15 UTC5
use gpu_allocator::MemoryLocation;
824bf02b6e55atagen2026-10-16 09:15 UTC6
use gpu_allocator::vulkan::{Allocation, AllocationCreateDesc, AllocationScheme};
824bf02b6e55atagen2026-10-16 09:15 UTC7
use smithay::backend::allocator::Fourcc;
824bf02b6e55atagen2026-10-16 09:15 UTC8
use smithay::backend::renderer::{Texture, TextureMapping};
824bf02b6e55atagen2026-10-16 09:15 UTC9
use std::fmt;
7de49c2aa70batagen2026-10-16 09:27 UTC10
use std::marker::PhantomData;
824bf02b6e55atagen2026-10-16 09:15 UTC11
use std::sync::{Arc, Mutex};
cacda79c0faaatagen2026-10-19 06:11 UTC12
use std::time::{Duration, Instant};
824bf02b6e55atagen2026-10-16 09:15 UTC13
7de49c2aa70batagen2026-10-16 09:27 UTC14
pub(crate) enum Memory {
7de49c2aa70batagen2026-10-16 09:27 UTC15
    Allocated(Allocation),
7de49c2aa70batagen2026-10-16 09:27 UTC16
    /// Memory imported from a dmabuf, owned directly.
7de49c2aa70batagen2026-10-16 09:27 UTC17
    Imported(vk::DeviceMemory),
7de49c2aa70batagen2026-10-16 09:27 UTC18
}
7de49c2aa70batagen2026-10-16 09:27 UTC19
824bf02b6e55atagen2026-10-16 09:15 UTC20
pub(crate) struct ImageInner {
824bf02b6e55atagen2026-10-16 09:15 UTC21
    pub shared: Arc<Shared>,
824bf02b6e55atagen2026-10-16 09:15 UTC22
    pub image: vk::Image,
824bf02b6e55atagen2026-10-16 09:15 UTC23
    pub view: vk::ImageView,
7de49c2aa70batagen2026-10-16 09:27 UTC24
    pub memory: Mutex<Option<Memory>>,
824bf02b6e55atagen2026-10-16 09:15 UTC25
    pub fourcc: Fourcc,
824bf02b6e55atagen2026-10-16 09:15 UTC26
    pub format: vk::Format,
824bf02b6e55atagen2026-10-16 09:15 UTC27
    pub width: u32,
824bf02b6e55atagen2026-10-16 09:15 UTC28
    pub height: u32,
824bf02b6e55atagen2026-10-16 09:15 UTC29
    pub layout: Mutex<vk::ImageLayout>,
7de49c2aa70batagen2026-10-16 09:27 UTC30
    /// Shared with other devices or processes through a dmabuf. Every use
7de49c2aa70batagen2026-10-16 09:27 UTC31
    /// acquires the image from the foreign queue family and releases it after.
7de49c2aa70batagen2026-10-16 09:27 UTC32
    pub external: bool,
824bf02b6e55atagen2026-10-16 09:15 UTC33
}
824bf02b6e55atagen2026-10-16 09:15 UTC34
824bf02b6e55atagen2026-10-16 09:15 UTC35
impl fmt::Debug for ImageInner {
824bf02b6e55atagen2026-10-16 09:15 UTC36
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
824bf02b6e55atagen2026-10-16 09:15 UTC37
        f.debug_struct("ImageInner")
824bf02b6e55atagen2026-10-16 09:15 UTC38
            .field("image", &self.image)
824bf02b6e55atagen2026-10-16 09:15 UTC39
            .field("fourcc", &self.fourcc)
824bf02b6e55atagen2026-10-16 09:15 UTC40
            .field("size", &(self.width, self.height))
7de49c2aa70batagen2026-10-16 09:27 UTC41
            .field("external", &self.external)
824bf02b6e55atagen2026-10-16 09:15 UTC42
            .finish()
824bf02b6e55atagen2026-10-16 09:15 UTC43
    }
824bf02b6e55atagen2026-10-16 09:15 UTC44
}
824bf02b6e55atagen2026-10-16 09:15 UTC45
824bf02b6e55atagen2026-10-16 09:15 UTC46
impl Drop for ImageInner {
824bf02b6e55atagen2026-10-16 09:15 UTC47
    fn drop(&mut self) {
824bf02b6e55atagen2026-10-16 09:15 UTC48
        let d = &self.shared.device.device;
824bf02b6e55atagen2026-10-16 09:15 UTC49
        unsafe {
824bf02b6e55atagen2026-10-16 09:15 UTC50
            d.destroy_image_view(self.view, None);
824bf02b6e55atagen2026-10-16 09:15 UTC51
            d.destroy_image(self.image, None);
824bf02b6e55atagen2026-10-16 09:15 UTC52
        }
7de49c2aa70batagen2026-10-16 09:27 UTC53
        match self.memory.lock().unwrap_or_else(|e| e.into_inner()).take() {
7de49c2aa70batagen2026-10-16 09:27 UTC54
            Some(Memory::Allocated(a)) => {
7de49c2aa70batagen2026-10-16 09:27 UTC55
                let _ = self
7de49c2aa70batagen2026-10-16 09:27 UTC56
                    .shared
7de49c2aa70batagen2026-10-16 09:27 UTC57
                    .allocator
7de49c2aa70batagen2026-10-16 09:27 UTC58
                    .lock()
7de49c2aa70batagen2026-10-16 09:27 UTC59
                    .unwrap_or_else(|e| e.into_inner())
7de49c2aa70batagen2026-10-16 09:27 UTC60
                    .free(a);
7de49c2aa70batagen2026-10-16 09:27 UTC61
            }
7de49c2aa70batagen2026-10-16 09:27 UTC62
            Some(Memory::Imported(m)) => unsafe { d.free_memory(m, None) },
7de49c2aa70batagen2026-10-16 09:27 UTC63
            None => {}
824bf02b6e55atagen2026-10-16 09:15 UTC64
        }
824bf02b6e55atagen2026-10-16 09:15 UTC65
    }
824bf02b6e55atagen2026-10-16 09:15 UTC66
}
824bf02b6e55atagen2026-10-16 09:15 UTC67
824bf02b6e55atagen2026-10-16 09:15 UTC68
impl ImageInner {
824bf02b6e55atagen2026-10-16 09:15 UTC69
    pub fn create(
824bf02b6e55atagen2026-10-16 09:15 UTC70
        shared: &Arc<Shared>,
824bf02b6e55atagen2026-10-16 09:15 UTC71
        fourcc: Fourcc,
824bf02b6e55atagen2026-10-16 09:15 UTC72
        width: u32,
824bf02b6e55atagen2026-10-16 09:15 UTC73
        height: u32,
824bf02b6e55atagen2026-10-16 09:15 UTC74
        usage: vk::ImageUsageFlags,
824bf02b6e55atagen2026-10-16 09:15 UTC75
    ) -> Result<Arc<Self>, Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC76
        let fmt = vk_format(fourcc).ok_or(Error::UnsupportedFormat(fourcc))?;
824bf02b6e55atagen2026-10-16 09:15 UTC77
        if width == 0 || height == 0 {
824bf02b6e55atagen2026-10-16 09:15 UTC78
            return Err(Error::InvalidSize(width as i32, height as i32));
824bf02b6e55atagen2026-10-16 09:15 UTC79
        }
824bf02b6e55atagen2026-10-16 09:15 UTC80
        let d = &shared.device.device;
824bf02b6e55atagen2026-10-16 09:15 UTC81
        let info = vk::ImageCreateInfo::default()
824bf02b6e55atagen2026-10-16 09:15 UTC82
            .image_type(vk::ImageType::TYPE_2D)
824bf02b6e55atagen2026-10-16 09:15 UTC83
            .format(fmt.format)
824bf02b6e55atagen2026-10-16 09:15 UTC84
            .extent(vk::Extent3D {
824bf02b6e55atagen2026-10-16 09:15 UTC85
                width,
824bf02b6e55atagen2026-10-16 09:15 UTC86
                height,
824bf02b6e55atagen2026-10-16 09:15 UTC87
                depth: 1,
824bf02b6e55atagen2026-10-16 09:15 UTC88
            })
824bf02b6e55atagen2026-10-16 09:15 UTC89
            .mip_levels(1)
824bf02b6e55atagen2026-10-16 09:15 UTC90
            .array_layers(1)
824bf02b6e55atagen2026-10-16 09:15 UTC91
            .samples(vk::SampleCountFlags::TYPE_1)
824bf02b6e55atagen2026-10-16 09:15 UTC92
            .tiling(vk::ImageTiling::OPTIMAL)
824bf02b6e55atagen2026-10-16 09:15 UTC93
            .usage(usage)
824bf02b6e55atagen2026-10-16 09:15 UTC94
            .initial_layout(vk::ImageLayout::UNDEFINED);
824bf02b6e55atagen2026-10-16 09:15 UTC95
        let image = unsafe { d.create_image(&info, None)? };
824bf02b6e55atagen2026-10-16 09:15 UTC96
        let requirements = unsafe { d.get_image_memory_requirements(image) };
824bf02b6e55atagen2026-10-16 09:15 UTC97
        let allocation = shared
824bf02b6e55atagen2026-10-16 09:15 UTC98
            .allocator
824bf02b6e55atagen2026-10-16 09:15 UTC99
            .lock()
824bf02b6e55atagen2026-10-16 09:15 UTC100
            .unwrap_or_else(|e| e.into_inner())
824bf02b6e55atagen2026-10-16 09:15 UTC101
            .allocate(&AllocationCreateDesc {
824bf02b6e55atagen2026-10-16 09:15 UTC102
                name: "image",
824bf02b6e55atagen2026-10-16 09:15 UTC103
                requirements,
824bf02b6e55atagen2026-10-16 09:15 UTC104
                location: MemoryLocation::GpuOnly,
824bf02b6e55atagen2026-10-16 09:15 UTC105
                linear: false,
824bf02b6e55atagen2026-10-16 09:15 UTC106
                allocation_scheme: AllocationScheme::GpuAllocatorManaged,
824bf02b6e55atagen2026-10-16 09:15 UTC107
            });
824bf02b6e55atagen2026-10-16 09:15 UTC108
        let allocation = match allocation {
824bf02b6e55atagen2026-10-16 09:15 UTC109
            Ok(a) => a,
824bf02b6e55atagen2026-10-16 09:15 UTC110
            Err(e) => {
824bf02b6e55atagen2026-10-16 09:15 UTC111
                unsafe { d.destroy_image(image, None) };
824bf02b6e55atagen2026-10-16 09:15 UTC112
                return Err(e.into());
824bf02b6e55atagen2026-10-16 09:15 UTC113
            }
824bf02b6e55atagen2026-10-16 09:15 UTC114
        };
7de49c2aa70batagen2026-10-16 09:27 UTC115
        let memory = Memory::Allocated(allocation);
7de49c2aa70batagen2026-10-16 09:27 UTC116
        let (mem, offset) = match &memory {
7de49c2aa70batagen2026-10-16 09:27 UTC117
            Memory::Allocated(a) => (unsafe { a.memory() }, a.offset()),
7de49c2aa70batagen2026-10-16 09:27 UTC118
            Memory::Imported(m) => (*m, 0),
7de49c2aa70batagen2026-10-16 09:27 UTC119
        };
7de49c2aa70batagen2026-10-16 09:27 UTC120
        Self::finish(
7de49c2aa70batagen2026-10-16 09:27 UTC121
            shared, image, memory, mem, offset, fourcc, width, height, false,
7de49c2aa70batagen2026-10-16 09:27 UTC122
        )
7de49c2aa70batagen2026-10-16 09:27 UTC123
    }
7de49c2aa70batagen2026-10-16 09:27 UTC124
7de49c2aa70batagen2026-10-16 09:27 UTC125
    /// Binds memory, creates the view and wraps everything up. Takes
7de49c2aa70batagen2026-10-16 09:27 UTC126
    /// ownership of `image` and `memory`, releasing both on failure.
7de49c2aa70batagen2026-10-16 09:27 UTC127
    #[expect(clippy::too_many_arguments)]
7de49c2aa70batagen2026-10-16 09:27 UTC128
    pub fn finish(
7de49c2aa70batagen2026-10-16 09:27 UTC129
        shared: &Arc<Shared>,
7de49c2aa70batagen2026-10-16 09:27 UTC130
        image: vk::Image,
7de49c2aa70batagen2026-10-16 09:27 UTC131
        memory: Memory,
7de49c2aa70batagen2026-10-16 09:27 UTC132
        mem: vk::DeviceMemory,
7de49c2aa70batagen2026-10-16 09:27 UTC133
        offset: u64,
7de49c2aa70batagen2026-10-16 09:27 UTC134
        fourcc: Fourcc,
7de49c2aa70batagen2026-10-16 09:27 UTC135
        width: u32,
7de49c2aa70batagen2026-10-16 09:27 UTC136
        height: u32,
7de49c2aa70batagen2026-10-16 09:27 UTC137
        external: bool,
7de49c2aa70batagen2026-10-16 09:27 UTC138
    ) -> Result<Arc<Self>, Error> {
7de49c2aa70batagen2026-10-16 09:27 UTC139
        let fmt = vk_format(fourcc).ok_or(Error::UnsupportedFormat(fourcc))?;
7de49c2aa70batagen2026-10-16 09:27 UTC140
        let d = &shared.device.device;
7de49c2aa70batagen2026-10-16 09:27 UTC141
        let mut inner = Self {
824bf02b6e55atagen2026-10-16 09:15 UTC142
            shared: shared.clone(),
824bf02b6e55atagen2026-10-16 09:15 UTC143
            image,
7de49c2aa70batagen2026-10-16 09:27 UTC144
            view: vk::ImageView::null(),
7de49c2aa70batagen2026-10-16 09:27 UTC145
            memory: Mutex::new(Some(memory)),
824bf02b6e55atagen2026-10-16 09:15 UTC146
            fourcc,
824bf02b6e55atagen2026-10-16 09:15 UTC147
            format: fmt.format,
824bf02b6e55atagen2026-10-16 09:15 UTC148
            width,
824bf02b6e55atagen2026-10-16 09:15 UTC149
            height,
7de49c2aa70batagen2026-10-16 09:27 UTC150
            layout: Mutex::new(if external {
7de49c2aa70batagen2026-10-16 09:27 UTC151
                vk::ImageLayout::GENERAL
7de49c2aa70batagen2026-10-16 09:27 UTC152
            } else {
7de49c2aa70batagen2026-10-16 09:27 UTC153
                vk::ImageLayout::UNDEFINED
7de49c2aa70batagen2026-10-16 09:27 UTC154
            }),
7de49c2aa70batagen2026-10-16 09:27 UTC155
            external,
7de49c2aa70batagen2026-10-16 09:27 UTC156
        };
7de49c2aa70batagen2026-10-16 09:27 UTC157
        unsafe { d.bind_image_memory(image, mem, offset)? };
7de49c2aa70batagen2026-10-16 09:27 UTC158
        let view_info = vk::ImageViewCreateInfo::default()
7de49c2aa70batagen2026-10-16 09:27 UTC159
            .image(image)
7de49c2aa70batagen2026-10-16 09:27 UTC160
            .view_type(vk::ImageViewType::TYPE_2D)
7de49c2aa70batagen2026-10-16 09:27 UTC161
            .format(fmt.format)
7de49c2aa70batagen2026-10-16 09:27 UTC162
            .components(components(fmt.opaque))
7de49c2aa70batagen2026-10-16 09:27 UTC163
            .subresource_range(color_range());
7de49c2aa70batagen2026-10-16 09:27 UTC164
        inner.view = unsafe { d.create_image_view(&view_info, None)? };
7de49c2aa70batagen2026-10-16 09:27 UTC165
        Ok(Arc::new(inner))
824bf02b6e55atagen2026-10-16 09:15 UTC166
    }
824bf02b6e55atagen2026-10-16 09:15 UTC167
824bf02b6e55atagen2026-10-16 09:15 UTC168
    pub fn layout(&self) -> vk::ImageLayout {
824bf02b6e55atagen2026-10-16 09:15 UTC169
        *self.layout.lock().unwrap_or_else(|e| e.into_inner())
824bf02b6e55atagen2026-10-16 09:15 UTC170
    }
824bf02b6e55atagen2026-10-16 09:15 UTC171
824bf02b6e55atagen2026-10-16 09:15 UTC172
    pub fn set_layout(&self, layout: vk::ImageLayout) {
824bf02b6e55atagen2026-10-16 09:15 UTC173
        *self.layout.lock().unwrap_or_else(|e| e.into_inner()) = layout;
824bf02b6e55atagen2026-10-16 09:15 UTC174
    }
824bf02b6e55atagen2026-10-16 09:15 UTC175
}
824bf02b6e55atagen2026-10-16 09:15 UTC176
824bf02b6e55atagen2026-10-16 09:15 UTC177
pub(crate) fn color_range() -> vk::ImageSubresourceRange {
824bf02b6e55atagen2026-10-16 09:15 UTC178
    vk::ImageSubresourceRange::default()
824bf02b6e55atagen2026-10-16 09:15 UTC179
        .aspect_mask(vk::ImageAspectFlags::COLOR)
824bf02b6e55atagen2026-10-16 09:15 UTC180
        .level_count(1)
824bf02b6e55atagen2026-10-16 09:15 UTC181
        .layer_count(1)
824bf02b6e55atagen2026-10-16 09:15 UTC182
}
824bf02b6e55atagen2026-10-16 09:15 UTC183
04f0de436841atagen2026-10-17 04:23 UTC184
/// A host-visible buffer for uploads and readbacks. Dropped ones go back to
04f0de436841atagen2026-10-17 04:23 UTC185
/// a pool on `Shared` instead of being freed. Allocating and freeing large
04f0de436841atagen2026-10-17 04:23 UTC186
/// host-visible memory takes a driver lock on NVIDIA that `vkQueueSubmit`
04f0de436841atagen2026-10-17 04:23 UTC187
/// also waits on, so a staging buffer made per upload on the import worker
04f0de436841atagen2026-10-17 04:23 UTC188
/// stalled the main thread's submits for 1 to 3 ms.
824bf02b6e55atagen2026-10-16 09:15 UTC189
pub(crate) struct Staging {
824bf02b6e55atagen2026-10-16 09:15 UTC190
    pub shared: Arc<Shared>,
824bf02b6e55atagen2026-10-16 09:15 UTC191
    pub buffer: vk::Buffer,
824bf02b6e55atagen2026-10-16 09:15 UTC192
    pub allocation: Option<Allocation>,
04f0de436841atagen2026-10-17 04:23 UTC193
    size: usize,
04f0de436841atagen2026-10-17 04:23 UTC194
    usage: vk::BufferUsageFlags,
04f0de436841atagen2026-10-17 04:23 UTC195
    location: MemoryLocation,
824bf02b6e55atagen2026-10-16 09:15 UTC196
}
824bf02b6e55atagen2026-10-16 09:15 UTC197
04f0de436841atagen2026-10-17 04:23 UTC198
pub(crate) struct Pooled {
04f0de436841atagen2026-10-17 04:23 UTC199
    pub buffer: vk::Buffer,
04f0de436841atagen2026-10-17 04:23 UTC200
    pub allocation: Allocation,
04f0de436841atagen2026-10-17 04:23 UTC201
    size: usize,
04f0de436841atagen2026-10-17 04:23 UTC202
    usage: vk::BufferUsageFlags,
04f0de436841atagen2026-10-17 04:23 UTC203
    location: MemoryLocation,
cacda79c0faaatagen2026-10-19 06:11 UTC204
    returned: Instant,
04f0de436841atagen2026-10-17 04:23 UTC205
}
04f0de436841atagen2026-10-17 04:23 UTC206
04f0de436841atagen2026-10-17 04:23 UTC207
/// Pooled staging memory kept at most, past which dropped buffers are freed.
cacda79c0faaatagen2026-10-19 06:11 UTC208
const POOL_BYTES: usize = 32 * 1024 * 1024;
cacda79c0faaatagen2026-10-19 06:11 UTC209
cacda79c0faaatagen2026-10-19 06:11 UTC210
/// How long a pooled buffer may go unused before it is freed.
cacda79c0faaatagen2026-10-19 06:11 UTC211
const POOL_IDLE: Duration = Duration::from_secs(2);
cacda79c0faaatagen2026-10-19 06:11 UTC212
cacda79c0faaatagen2026-10-19 06:11 UTC213
/// Frees pooled staging buffers that have sat unused for [`POOL_IDLE`].
cacda79c0faaatagen2026-10-19 06:11 UTC214
pub(crate) fn trim_staging(shared: &Shared) {
cacda79c0faaatagen2026-10-19 06:11 UTC215
    let now = Instant::now();
7e34874b2bd1atagen2026-10-19 06:54 UTC216
    let expired: Vec<Pooled> = shared
7e34874b2bd1atagen2026-10-19 06:54 UTC217
        .staging_pool
7e34874b2bd1atagen2026-10-19 06:54 UTC218
        .lock()
7e34874b2bd1atagen2026-10-19 06:54 UTC219
        .unwrap_or_else(|e| e.into_inner())
7e34874b2bd1atagen2026-10-19 06:54 UTC220
        .extract_if(.., |p| now - p.returned >= POOL_IDLE)
7e34874b2bd1atagen2026-10-19 06:54 UTC221
        .collect();
cacda79c0faaatagen2026-10-19 06:11 UTC222
    if expired.is_empty() {
cacda79c0faaatagen2026-10-19 06:11 UTC223
        return;
cacda79c0faaatagen2026-10-19 06:11 UTC224
    }
cacda79c0faaatagen2026-10-19 06:11 UTC225
    let mut allocator = shared.allocator.lock().unwrap_or_else(|e| e.into_inner());
cacda79c0faaatagen2026-10-19 06:11 UTC226
    for p in expired {
cacda79c0faaatagen2026-10-19 06:11 UTC227
        unsafe { shared.device.device.destroy_buffer(p.buffer, None) };
cacda79c0faaatagen2026-10-19 06:11 UTC228
        let _ = allocator.free(p.allocation);
cacda79c0faaatagen2026-10-19 06:11 UTC229
    }
cacda79c0faaatagen2026-10-19 06:11 UTC230
}
04f0de436841atagen2026-10-17 04:23 UTC231
824bf02b6e55atagen2026-10-16 09:15 UTC232
impl Staging {
824bf02b6e55atagen2026-10-16 09:15 UTC233
    pub fn new(
824bf02b6e55atagen2026-10-16 09:15 UTC234
        shared: &Arc<Shared>,
824bf02b6e55atagen2026-10-16 09:15 UTC235
        size: usize,
824bf02b6e55atagen2026-10-16 09:15 UTC236
        usage: vk::BufferUsageFlags,
824bf02b6e55atagen2026-10-16 09:15 UTC237
        location: MemoryLocation,
824bf02b6e55atagen2026-10-16 09:15 UTC238
    ) -> Result<Self, Error> {
04f0de436841atagen2026-10-17 04:23 UTC239
        let reused = {
04f0de436841atagen2026-10-17 04:23 UTC240
            let mut pool = shared
04f0de436841atagen2026-10-17 04:23 UTC241
                .staging_pool
04f0de436841atagen2026-10-17 04:23 UTC242
                .lock()
04f0de436841atagen2026-10-17 04:23 UTC243
                .unwrap_or_else(|e| e.into_inner());
04f0de436841atagen2026-10-17 04:23 UTC244
            let fits = |p: &Pooled| {
04f0de436841atagen2026-10-17 04:23 UTC245
                p.usage == usage && p.location == location && p.size >= size && p.size <= size * 2
04f0de436841atagen2026-10-17 04:23 UTC246
            };
04f0de436841atagen2026-10-17 04:23 UTC247
            pool.iter().position(fits).map(|i| pool.swap_remove(i))
04f0de436841atagen2026-10-17 04:23 UTC248
        };
04f0de436841atagen2026-10-17 04:23 UTC249
        if let Some(p) = reused {
04f0de436841atagen2026-10-17 04:23 UTC250
            return Ok(Self {
04f0de436841atagen2026-10-17 04:23 UTC251
                shared: shared.clone(),
04f0de436841atagen2026-10-17 04:23 UTC252
                buffer: p.buffer,
04f0de436841atagen2026-10-17 04:23 UTC253
                allocation: Some(p.allocation),
04f0de436841atagen2026-10-17 04:23 UTC254
                size: p.size,
04f0de436841atagen2026-10-17 04:23 UTC255
                usage,
04f0de436841atagen2026-10-17 04:23 UTC256
                location,
04f0de436841atagen2026-10-17 04:23 UTC257
            });
04f0de436841atagen2026-10-17 04:23 UTC258
        }
824bf02b6e55atagen2026-10-16 09:15 UTC259
        let d = &shared.device.device;
824bf02b6e55atagen2026-10-16 09:15 UTC260
        let buffer = unsafe {
824bf02b6e55atagen2026-10-16 09:15 UTC261
            d.create_buffer(
824bf02b6e55atagen2026-10-16 09:15 UTC262
                &vk::BufferCreateInfo::default()
824bf02b6e55atagen2026-10-16 09:15 UTC263
                    .size(size as u64)
824bf02b6e55atagen2026-10-16 09:15 UTC264
                    .usage(usage),
824bf02b6e55atagen2026-10-16 09:15 UTC265
                None,
824bf02b6e55atagen2026-10-16 09:15 UTC266
            )?
824bf02b6e55atagen2026-10-16 09:15 UTC267
        };
824bf02b6e55atagen2026-10-16 09:15 UTC268
        let requirements = unsafe { d.get_buffer_memory_requirements(buffer) };
824bf02b6e55atagen2026-10-16 09:15 UTC269
        let allocation = shared
824bf02b6e55atagen2026-10-16 09:15 UTC270
            .allocator
824bf02b6e55atagen2026-10-16 09:15 UTC271
            .lock()
824bf02b6e55atagen2026-10-16 09:15 UTC272
            .unwrap_or_else(|e| e.into_inner())
824bf02b6e55atagen2026-10-16 09:15 UTC273
            .allocate(&AllocationCreateDesc {
824bf02b6e55atagen2026-10-16 09:15 UTC274
                name: "staging",
824bf02b6e55atagen2026-10-16 09:15 UTC275
                requirements,
824bf02b6e55atagen2026-10-16 09:15 UTC276
                location,
824bf02b6e55atagen2026-10-16 09:15 UTC277
                linear: true,
824bf02b6e55atagen2026-10-16 09:15 UTC278
                allocation_scheme: AllocationScheme::GpuAllocatorManaged,
824bf02b6e55atagen2026-10-16 09:15 UTC279
            });
824bf02b6e55atagen2026-10-16 09:15 UTC280
        let allocation = match allocation {
824bf02b6e55atagen2026-10-16 09:15 UTC281
            Ok(a) => a,
824bf02b6e55atagen2026-10-16 09:15 UTC282
            Err(e) => {
824bf02b6e55atagen2026-10-16 09:15 UTC283
                unsafe { d.destroy_buffer(buffer, None) };
824bf02b6e55atagen2026-10-16 09:15 UTC284
                return Err(e.into());
824bf02b6e55atagen2026-10-16 09:15 UTC285
            }
824bf02b6e55atagen2026-10-16 09:15 UTC286
        };
824bf02b6e55atagen2026-10-16 09:15 UTC287
        unsafe { d.bind_buffer_memory(buffer, allocation.memory(), allocation.offset())? };
824bf02b6e55atagen2026-10-16 09:15 UTC288
        Ok(Self {
824bf02b6e55atagen2026-10-16 09:15 UTC289
            shared: shared.clone(),
824bf02b6e55atagen2026-10-16 09:15 UTC290
            buffer,
824bf02b6e55atagen2026-10-16 09:15 UTC291
            allocation: Some(allocation),
04f0de436841atagen2026-10-17 04:23 UTC292
            size,
04f0de436841atagen2026-10-17 04:23 UTC293
            usage,
04f0de436841atagen2026-10-17 04:23 UTC294
            location,
824bf02b6e55atagen2026-10-16 09:15 UTC295
        })
824bf02b6e55atagen2026-10-16 09:15 UTC296
    }
824bf02b6e55atagen2026-10-16 09:15 UTC297
824bf02b6e55atagen2026-10-16 09:15 UTC298
    pub fn bytes(&self) -> &[u8] {
824bf02b6e55atagen2026-10-16 09:15 UTC299
        self.allocation
824bf02b6e55atagen2026-10-16 09:15 UTC300
            .as_ref()
824bf02b6e55atagen2026-10-16 09:15 UTC301
            .and_then(|a| a.mapped_slice())
824bf02b6e55atagen2026-10-16 09:15 UTC302
            .unwrap_or(&[])
824bf02b6e55atagen2026-10-16 09:15 UTC303
    }
824bf02b6e55atagen2026-10-16 09:15 UTC304
824bf02b6e55atagen2026-10-16 09:15 UTC305
    pub fn bytes_mut(&mut self) -> &mut [u8] {
824bf02b6e55atagen2026-10-16 09:15 UTC306
        self.allocation
824bf02b6e55atagen2026-10-16 09:15 UTC307
            .as_mut()
824bf02b6e55atagen2026-10-16 09:15 UTC308
            .and_then(|a| a.mapped_slice_mut())
824bf02b6e55atagen2026-10-16 09:15 UTC309
            .unwrap_or(&mut [])
824bf02b6e55atagen2026-10-16 09:15 UTC310
    }
824bf02b6e55atagen2026-10-16 09:15 UTC311
}
824bf02b6e55atagen2026-10-16 09:15 UTC312
824bf02b6e55atagen2026-10-16 09:15 UTC313
impl Drop for Staging {
824bf02b6e55atagen2026-10-16 09:15 UTC314
    fn drop(&mut self) {
04f0de436841atagen2026-10-17 04:23 UTC315
        let Some(allocation) = self.allocation.take() else {
04f0de436841atagen2026-10-17 04:23 UTC316
            return;
04f0de436841atagen2026-10-17 04:23 UTC317
        };
04f0de436841atagen2026-10-17 04:23 UTC318
        let mut pool = self
04f0de436841atagen2026-10-17 04:23 UTC319
            .shared
04f0de436841atagen2026-10-17 04:23 UTC320
            .staging_pool
04f0de436841atagen2026-10-17 04:23 UTC321
            .lock()
04f0de436841atagen2026-10-17 04:23 UTC322
            .unwrap_or_else(|e| e.into_inner());
04f0de436841atagen2026-10-17 04:23 UTC323
        let pooled: usize = pool.iter().map(|p| p.size).sum();
04f0de436841atagen2026-10-17 04:23 UTC324
        if pooled + self.size <= POOL_BYTES {
04f0de436841atagen2026-10-17 04:23 UTC325
            pool.push(Pooled {
04f0de436841atagen2026-10-17 04:23 UTC326
                buffer: self.buffer,
04f0de436841atagen2026-10-17 04:23 UTC327
                allocation,
04f0de436841atagen2026-10-17 04:23 UTC328
                size: self.size,
04f0de436841atagen2026-10-17 04:23 UTC329
                usage: self.usage,
04f0de436841atagen2026-10-17 04:23 UTC330
                location: self.location,
cacda79c0faaatagen2026-10-19 06:11 UTC331
                returned: Instant::now(),
04f0de436841atagen2026-10-17 04:23 UTC332
            });
04f0de436841atagen2026-10-17 04:23 UTC333
            return;
824bf02b6e55atagen2026-10-16 09:15 UTC334
        }
04f0de436841atagen2026-10-17 04:23 UTC335
        drop(pool);
04f0de436841atagen2026-10-17 04:23 UTC336
        unsafe { self.shared.device.device.destroy_buffer(self.buffer, None) };
04f0de436841atagen2026-10-17 04:23 UTC337
        let _ = self
04f0de436841atagen2026-10-17 04:23 UTC338
            .shared
04f0de436841atagen2026-10-17 04:23 UTC339
            .allocator
04f0de436841atagen2026-10-17 04:23 UTC340
            .lock()
04f0de436841atagen2026-10-17 04:23 UTC341
            .unwrap_or_else(|e| e.into_inner())
04f0de436841atagen2026-10-17 04:23 UTC342
            .free(allocation);
824bf02b6e55atagen2026-10-16 09:15 UTC343
    }
824bf02b6e55atagen2026-10-16 09:15 UTC344
}
824bf02b6e55atagen2026-10-16 09:15 UTC345
824bf02b6e55atagen2026-10-16 09:15 UTC346
/// A sampled texture.
824bf02b6e55atagen2026-10-16 09:15 UTC347
#[derive(Clone, Debug)]
824bf02b6e55atagen2026-10-16 09:15 UTC348
pub struct VulkanTexture(pub(crate) Arc<ImageInner>);
824bf02b6e55atagen2026-10-16 09:15 UTC349
824bf02b6e55atagen2026-10-16 09:15 UTC350
/// An image the renderer can draw into, from [`smithay::backend::renderer::Offscreen`].
824bf02b6e55atagen2026-10-16 09:15 UTC351
#[derive(Debug)]
824bf02b6e55atagen2026-10-16 09:15 UTC352
pub struct VulkanImage(pub(crate) Arc<ImageInner>);
824bf02b6e55atagen2026-10-16 09:15 UTC353
824bf02b6e55atagen2026-10-16 09:15 UTC354
impl VulkanImage {
824bf02b6e55atagen2026-10-16 09:15 UTC355
    /// The image's contents as a texture, for drawing it elsewhere.
824bf02b6e55atagen2026-10-16 09:15 UTC356
    pub fn texture(&self) -> VulkanTexture {
824bf02b6e55atagen2026-10-16 09:15 UTC357
        VulkanTexture(self.0.clone())
824bf02b6e55atagen2026-10-16 09:15 UTC358
    }
824bf02b6e55atagen2026-10-16 09:15 UTC359
}
824bf02b6e55atagen2026-10-16 09:15 UTC360
7de49c2aa70batagen2026-10-16 09:27 UTC361
/// A bound render target, borrowing whatever it was bound from.
824bf02b6e55atagen2026-10-16 09:15 UTC362
#[derive(Debug)]
7de49c2aa70batagen2026-10-16 09:27 UTC363
pub struct VulkanTarget<'a>(
7de49c2aa70batagen2026-10-16 09:27 UTC364
    pub(crate) Arc<ImageInner>,
7de49c2aa70batagen2026-10-16 09:27 UTC365
    pub(crate) PhantomData<&'a mut ()>,
7de49c2aa70batagen2026-10-16 09:27 UTC366
);
824bf02b6e55atagen2026-10-16 09:15 UTC367
824bf02b6e55atagen2026-10-16 09:15 UTC368
/// Pixels read back from the GPU.
824bf02b6e55atagen2026-10-16 09:15 UTC369
#[derive(Debug)]
824bf02b6e55atagen2026-10-16 09:15 UTC370
pub struct VulkanMapping {
824bf02b6e55atagen2026-10-16 09:15 UTC371
    pub(crate) data: Vec<u8>,
824bf02b6e55atagen2026-10-16 09:15 UTC372
    pub(crate) width: u32,
824bf02b6e55atagen2026-10-16 09:15 UTC373
    pub(crate) height: u32,
824bf02b6e55atagen2026-10-16 09:15 UTC374
    pub(crate) fourcc: Fourcc,
824bf02b6e55atagen2026-10-16 09:15 UTC375
}
824bf02b6e55atagen2026-10-16 09:15 UTC376
824bf02b6e55atagen2026-10-16 09:15 UTC377
macro_rules! texture_impl {
824bf02b6e55atagen2026-10-16 09:15 UTC378
    ($t:ty, |$s:ident| $inner:expr) => {
824bf02b6e55atagen2026-10-16 09:15 UTC379
        impl Texture for $t {
824bf02b6e55atagen2026-10-16 09:15 UTC380
            fn width(&self) -> u32 {
824bf02b6e55atagen2026-10-16 09:15 UTC381
                let $s = self;
824bf02b6e55atagen2026-10-16 09:15 UTC382
                $inner.width
824bf02b6e55atagen2026-10-16 09:15 UTC383
            }
824bf02b6e55atagen2026-10-16 09:15 UTC384
            fn height(&self) -> u32 {
824bf02b6e55atagen2026-10-16 09:15 UTC385
                let $s = self;
824bf02b6e55atagen2026-10-16 09:15 UTC386
                $inner.height
824bf02b6e55atagen2026-10-16 09:15 UTC387
            }
824bf02b6e55atagen2026-10-16 09:15 UTC388
            fn format(&self) -> Option<Fourcc> {
824bf02b6e55atagen2026-10-16 09:15 UTC389
                let $s = self;
824bf02b6e55atagen2026-10-16 09:15 UTC390
                Some($inner.fourcc)
824bf02b6e55atagen2026-10-16 09:15 UTC391
            }
824bf02b6e55atagen2026-10-16 09:15 UTC392
        }
824bf02b6e55atagen2026-10-16 09:15 UTC393
    };
824bf02b6e55atagen2026-10-16 09:15 UTC394
}
824bf02b6e55atagen2026-10-16 09:15 UTC395
824bf02b6e55atagen2026-10-16 09:15 UTC396
texture_impl!(VulkanTexture, |s| s.0);
824bf02b6e55atagen2026-10-16 09:15 UTC397
texture_impl!(VulkanImage, |s| s.0);
7de49c2aa70batagen2026-10-16 09:27 UTC398
texture_impl!(VulkanTarget<'_>, |s| s.0);
824bf02b6e55atagen2026-10-16 09:15 UTC399
texture_impl!(VulkanMapping, |s| s);
824bf02b6e55atagen2026-10-16 09:15 UTC400
824bf02b6e55atagen2026-10-16 09:15 UTC401
impl TextureMapping for VulkanMapping {
824bf02b6e55atagen2026-10-16 09:15 UTC402
    fn flipped(&self) -> bool {
824bf02b6e55atagen2026-10-16 09:15 UTC403
        false
824bf02b6e55atagen2026-10-16 09:15 UTC404
    }
824bf02b6e55atagen2026-10-16 09:15 UTC405
}