atagen

monolith

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

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

824bf02b6e55atagen2026-10-16 09:15 UTC1
use crate::Error;
824bf02b6e55atagen2026-10-16 09:15 UTC2
use crate::device::Shared;
7de49c2aa70batagen2026-10-16 09:27 UTC3
use crate::dmabuf::{self, DmabufCaps, RENDER_USAGE, SAMPLE_USAGE, VulkanAllocator};
824bf02b6e55atagen2026-10-16 09:15 UTC4
use crate::format::{BYTES_PER_PIXEL, SUPPORTED};
824bf02b6e55atagen2026-10-16 09:15 UTC5
use crate::frame::{Op, VulkanFrame};
824bf02b6e55atagen2026-10-16 09:15 UTC6
use crate::image::{
824bf02b6e55atagen2026-10-16 09:15 UTC7
    ImageInner, Staging, VulkanImage, VulkanMapping, VulkanTarget, VulkanTexture, color_range,
824bf02b6e55atagen2026-10-16 09:15 UTC8
};
824bf02b6e55atagen2026-10-16 09:15 UTC9
use crate::pipeline::Pipelines;
824bf02b6e55atagen2026-10-16 09:15 UTC10
use crate::sync::{FenceInner, VkFence};
824bf02b6e55atagen2026-10-16 09:15 UTC11
use ash::vk;
824bf02b6e55atagen2026-10-16 09:15 UTC12
use gpu_allocator::MemoryLocation;
824bf02b6e55atagen2026-10-16 09:15 UTC13
use smithay::backend::allocator::Fourcc;
7de49c2aa70batagen2026-10-16 09:27 UTC14
use smithay::backend::allocator::dmabuf::{Dmabuf, WeakDmabuf};
7de49c2aa70batagen2026-10-16 09:27 UTC15
use smithay::backend::allocator::format::FormatSet;
d4a64ce87164atagen2026-10-16 09:34 UTC16
use smithay::backend::renderer::ImportMemWl;
824bf02b6e55atagen2026-10-16 09:15 UTC17
use smithay::backend::renderer::sync::SyncPoint;
824bf02b6e55atagen2026-10-16 09:15 UTC18
use smithay::backend::renderer::{
7de49c2aa70batagen2026-10-16 09:27 UTC19
    Bind, ContextId, DebugFlags, ExportMem, ImportDma, ImportDmaWl, ImportMem, Offscreen, Renderer,
7de49c2aa70batagen2026-10-16 09:27 UTC20
    RendererSuper, Texture, TextureFilter,
824bf02b6e55atagen2026-10-16 09:15 UTC21
};
d4a64ce87164atagen2026-10-16 09:34 UTC22
use smithay::reexports::wayland_server::protocol::wl_buffer::WlBuffer;
824bf02b6e55atagen2026-10-16 09:15 UTC23
use smithay::utils::{Buffer, Physical, Rectangle, Size, Transform};
d4a64ce87164atagen2026-10-16 09:34 UTC24
use smithay::wayland::compositor::SurfaceData;
d4a64ce87164atagen2026-10-16 09:34 UTC25
use smithay::wayland::shm::{shm_format_to_fourcc, with_buffer_contents};
5cd954fce34batagen2026-10-16 22:42 UTC26
use std::cell::Cell;
7de49c2aa70batagen2026-10-16 09:27 UTC27
use std::collections::HashMap;
824bf02b6e55atagen2026-10-16 09:15 UTC28
use std::fmt;
7de49c2aa70batagen2026-10-16 09:27 UTC29
use std::marker::PhantomData;
48af562d968batagen2026-10-16 12:39 UTC30
use std::sync::{Arc, Mutex};
5cd954fce34batagen2026-10-16 22:42 UTC31
use std::time::{Duration, Instant};
824bf02b6e55atagen2026-10-16 09:15 UTC32
824bf02b6e55atagen2026-10-16 09:15 UTC33
struct Pending {
824bf02b6e55atagen2026-10-16 09:15 UTC34
    fence: Arc<FenceInner>,
824bf02b6e55atagen2026-10-16 09:15 UTC35
    cmd: vk::CommandBuffer,
7de49c2aa70batagen2026-10-16 09:27 UTC36
    _keep: Vec<Arc<ImageInner>>,
48af562d968batagen2026-10-16 12:39 UTC37
    _staging: Option<Staging>,
824bf02b6e55atagen2026-10-16 09:15 UTC38
}
824bf02b6e55atagen2026-10-16 09:15 UTC39
824bf02b6e55atagen2026-10-16 09:15 UTC40
pub struct VulkanRenderer {
824bf02b6e55atagen2026-10-16 09:15 UTC41
    pending: Vec<Pending>,
7de49c2aa70batagen2026-10-16 09:27 UTC42
    dmabuf_textures: HashMap<WeakDmabuf, VulkanTexture>,
7de49c2aa70batagen2026-10-16 09:27 UTC43
    dmabuf_targets: HashMap<WeakDmabuf, Arc<ImageInner>>,
824bf02b6e55atagen2026-10-16 09:15 UTC44
    pipelines: Pipelines,
824bf02b6e55atagen2026-10-16 09:15 UTC45
    pool: vk::CommandPool,
d5eca1c82213atagen2026-10-16 13:56 UTC46
    /// Command buffers whose work finished, reset and reused by `begin`.
d5eca1c82213atagen2026-10-16 13:56 UTC47
    spare_cmds: Vec<vk::CommandBuffer>,
824bf02b6e55atagen2026-10-16 09:15 UTC48
    samplers: [vk::Sampler; 4],
824bf02b6e55atagen2026-10-16 09:15 UTC49
    min_filter: TextureFilter,
824bf02b6e55atagen2026-10-16 09:15 UTC50
    mag_filter: TextureFilter,
824bf02b6e55atagen2026-10-16 09:15 UTC51
    debug: DebugFlags,
824bf02b6e55atagen2026-10-16 09:15 UTC52
    context: ContextId<VulkanTexture>,
7de49c2aa70batagen2026-10-16 09:27 UTC53
    caps: Arc<DmabufCaps>,
824bf02b6e55atagen2026-10-16 09:15 UTC54
    shared: Arc<Shared>,
5cd954fce34batagen2026-10-16 22:42 UTC55
    submissions: Cell<u64>,
5cd954fce34batagen2026-10-16 22:42 UTC56
    stall: Cell<StallPhase>,
824bf02b6e55atagen2026-10-16 09:15 UTC57
}
824bf02b6e55atagen2026-10-16 09:15 UTC58
5cd954fce34batagen2026-10-16 22:42 UTC59
/// Where in every 1024 submissions the driver stalls. A phase is trusted
5cd954fce34batagen2026-10-16 22:42 UTC60
/// once two stalls land on it.
5cd954fce34batagen2026-10-16 22:42 UTC61
#[derive(Clone, Copy, Default)]
5cd954fce34batagen2026-10-16 22:42 UTC62
struct StallPhase {
5cd954fce34batagen2026-10-16 22:42 UTC63
    phase: Option<u64>,
5cd954fce34batagen2026-10-16 22:42 UTC64
    seen: Option<u64>,
5cd954fce34batagen2026-10-16 22:42 UTC65
}
5cd954fce34batagen2026-10-16 22:42 UTC66
5cd954fce34batagen2026-10-16 22:42 UTC67
impl StallPhase {
5cd954fce34batagen2026-10-16 22:42 UTC68
    fn saw(self, at: u64) -> Self {
5cd954fce34batagen2026-10-16 22:42 UTC69
        if self.seen == Some(at) {
5cd954fce34batagen2026-10-16 22:42 UTC70
            if self.phase != Some(at) {
5cd954fce34batagen2026-10-16 22:42 UTC71
                tracing::debug!(phase = at, "queue submissions stall periodically");
5cd954fce34batagen2026-10-16 22:42 UTC72
            }
5cd954fce34batagen2026-10-16 22:42 UTC73
            Self {
5cd954fce34batagen2026-10-16 22:42 UTC74
                phase: Some(at),
5cd954fce34batagen2026-10-16 22:42 UTC75
                seen: Some(at),
5cd954fce34batagen2026-10-16 22:42 UTC76
            }
5cd954fce34batagen2026-10-16 22:42 UTC77
        } else {
5cd954fce34batagen2026-10-16 22:42 UTC78
            Self {
5cd954fce34batagen2026-10-16 22:42 UTC79
                seen: Some(at),
5cd954fce34batagen2026-10-16 22:42 UTC80
                ..self
5cd954fce34batagen2026-10-16 22:42 UTC81
            }
5cd954fce34batagen2026-10-16 22:42 UTC82
        }
5cd954fce34batagen2026-10-16 22:42 UTC83
    }
5cd954fce34batagen2026-10-16 22:42 UTC84
}
5cd954fce34batagen2026-10-16 22:42 UTC85
5cd954fce34batagen2026-10-16 22:42 UTC86
/// A submission this slow is a driver stall rather than work.
5cd954fce34batagen2026-10-16 22:42 UTC87
const STALL: Duration = Duration::from_micros(1500);
5cd954fce34batagen2026-10-16 22:42 UTC88
/// How many submissions early a stall is absorbed. Each empty one costs
5cd954fce34batagen2026-10-16 22:42 UTC89
/// tens of microseconds.
5cd954fce34batagen2026-10-16 22:42 UTC90
const ABSORB_AHEAD: u64 = 8;
5cd954fce34batagen2026-10-16 22:42 UTC91
824bf02b6e55atagen2026-10-16 09:15 UTC92
impl fmt::Debug for VulkanRenderer {
824bf02b6e55atagen2026-10-16 09:15 UTC93
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
824bf02b6e55atagen2026-10-16 09:15 UTC94
        f.debug_struct("VulkanRenderer")
824bf02b6e55atagen2026-10-16 09:15 UTC95
            .field("device", &self.shared.device.name)
824bf02b6e55atagen2026-10-16 09:15 UTC96
            .finish()
824bf02b6e55atagen2026-10-16 09:15 UTC97
    }
824bf02b6e55atagen2026-10-16 09:15 UTC98
}
824bf02b6e55atagen2026-10-16 09:15 UTC99
824bf02b6e55atagen2026-10-16 09:15 UTC100
impl VulkanRenderer {
824bf02b6e55atagen2026-10-16 09:15 UTC101
    pub fn new() -> Result<Self, Error> {
f27fa4c2ade9atagen2026-10-16 12:59 UTC102
        Self::with_node(None)
f27fa4c2ade9atagen2026-10-16 12:59 UTC103
    }
f27fa4c2ade9atagen2026-10-16 12:59 UTC104
f27fa4c2ade9atagen2026-10-16 12:59 UTC105
    /// A renderer on the GPU behind DRM device number `node`, so it can
f27fa4c2ade9atagen2026-10-16 12:59 UTC106
    /// render into buffers that GPU scans out.
f27fa4c2ade9atagen2026-10-16 12:59 UTC107
    pub fn for_node(node: u64) -> Result<Self, Error> {
f27fa4c2ade9atagen2026-10-16 12:59 UTC108
        Self::with_node(Some(node))
f27fa4c2ade9atagen2026-10-16 12:59 UTC109
    }
f27fa4c2ade9atagen2026-10-16 12:59 UTC110
f27fa4c2ade9atagen2026-10-16 12:59 UTC111
    fn with_node(node: Option<u64>) -> Result<Self, Error> {
f27fa4c2ade9atagen2026-10-16 12:59 UTC112
        let shared = Arc::new(Shared::new(node)?);
824bf02b6e55atagen2026-10-16 09:15 UTC113
        let d = &shared.device.device;
824bf02b6e55atagen2026-10-16 09:15 UTC114
        let pool = unsafe {
824bf02b6e55atagen2026-10-16 09:15 UTC115
            d.create_command_pool(
824bf02b6e55atagen2026-10-16 09:15 UTC116
                &vk::CommandPoolCreateInfo::default()
824bf02b6e55atagen2026-10-16 09:15 UTC117
                    .queue_family_index(shared.device.queue_family)
d5eca1c82213atagen2026-10-16 13:56 UTC118
                    .flags(
d5eca1c82213atagen2026-10-16 13:56 UTC119
                        vk::CommandPoolCreateFlags::TRANSIENT
d5eca1c82213atagen2026-10-16 13:56 UTC120
                            | vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER,
d5eca1c82213atagen2026-10-16 13:56 UTC121
                    ),
824bf02b6e55atagen2026-10-16 09:15 UTC122
                None,
824bf02b6e55atagen2026-10-16 09:15 UTC123
            )?
824bf02b6e55atagen2026-10-16 09:15 UTC124
        };
824bf02b6e55atagen2026-10-16 09:15 UTC125
        let filter = |f: TextureFilter| match f {
824bf02b6e55atagen2026-10-16 09:15 UTC126
            TextureFilter::Linear => vk::Filter::LINEAR,
824bf02b6e55atagen2026-10-16 09:15 UTC127
            TextureFilter::Nearest => vk::Filter::NEAREST,
824bf02b6e55atagen2026-10-16 09:15 UTC128
        };
824bf02b6e55atagen2026-10-16 09:15 UTC129
        let mut samplers = [vk::Sampler::null(); 4];
824bf02b6e55atagen2026-10-16 09:15 UTC130
        for (i, s) in samplers.iter_mut().enumerate() {
824bf02b6e55atagen2026-10-16 09:15 UTC131
            let (min, mag) = (sampler_filter(i >> 1), sampler_filter(i & 1));
824bf02b6e55atagen2026-10-16 09:15 UTC132
            *s = unsafe {
824bf02b6e55atagen2026-10-16 09:15 UTC133
                d.create_sampler(
824bf02b6e55atagen2026-10-16 09:15 UTC134
                    &vk::SamplerCreateInfo::default()
824bf02b6e55atagen2026-10-16 09:15 UTC135
                        .min_filter(filter(min))
824bf02b6e55atagen2026-10-16 09:15 UTC136
                        .mag_filter(filter(mag))
824bf02b6e55atagen2026-10-16 09:15 UTC137
                        .address_mode_u(vk::SamplerAddressMode::CLAMP_TO_EDGE)
824bf02b6e55atagen2026-10-16 09:15 UTC138
                        .address_mode_v(vk::SamplerAddressMode::CLAMP_TO_EDGE)
824bf02b6e55atagen2026-10-16 09:15 UTC139
                        .address_mode_w(vk::SamplerAddressMode::CLAMP_TO_EDGE),
824bf02b6e55atagen2026-10-16 09:15 UTC140
                    None,
824bf02b6e55atagen2026-10-16 09:15 UTC141
                )?
824bf02b6e55atagen2026-10-16 09:15 UTC142
            };
824bf02b6e55atagen2026-10-16 09:15 UTC143
        }
824bf02b6e55atagen2026-10-16 09:15 UTC144
        Ok(Self {
824bf02b6e55atagen2026-10-16 09:15 UTC145
            pending: Vec::new(),
7de49c2aa70batagen2026-10-16 09:27 UTC146
            dmabuf_textures: HashMap::new(),
7de49c2aa70batagen2026-10-16 09:27 UTC147
            dmabuf_targets: HashMap::new(),
824bf02b6e55atagen2026-10-16 09:15 UTC148
            pipelines: Pipelines::new(&shared)?,
824bf02b6e55atagen2026-10-16 09:15 UTC149
            pool,
d5eca1c82213atagen2026-10-16 13:56 UTC150
            spare_cmds: Vec::new(),
5cd954fce34batagen2026-10-16 22:42 UTC151
            submissions: Cell::new(0),
5cd954fce34batagen2026-10-16 22:42 UTC152
            stall: Cell::new(StallPhase {
5cd954fce34batagen2026-10-16 22:42 UTC153
                // Measured on an RTX 3060, see research/nvidia.md.
5cd954fce34batagen2026-10-16 22:42 UTC154
                phase: shared.device.name.contains("NVIDIA").then_some(1015),
5cd954fce34batagen2026-10-16 22:42 UTC155
                seen: None,
5cd954fce34batagen2026-10-16 22:42 UTC156
            }),
824bf02b6e55atagen2026-10-16 09:15 UTC157
            samplers,
824bf02b6e55atagen2026-10-16 09:15 UTC158
            min_filter: TextureFilter::Linear,
824bf02b6e55atagen2026-10-16 09:15 UTC159
            mag_filter: TextureFilter::Linear,
824bf02b6e55atagen2026-10-16 09:15 UTC160
            debug: DebugFlags::empty(),
824bf02b6e55atagen2026-10-16 09:15 UTC161
            context: ContextId::new(),
7de49c2aa70batagen2026-10-16 09:27 UTC162
            caps: Arc::new(DmabufCaps::query(&shared)),
824bf02b6e55atagen2026-10-16 09:15 UTC163
            shared,
824bf02b6e55atagen2026-10-16 09:15 UTC164
        })
824bf02b6e55atagen2026-10-16 09:15 UTC165
    }
824bf02b6e55atagen2026-10-16 09:15 UTC166
824bf02b6e55atagen2026-10-16 09:15 UTC167
    /// Name of the physical device in use.
824bf02b6e55atagen2026-10-16 09:15 UTC168
    pub fn device_name(&self) -> &str {
824bf02b6e55atagen2026-10-16 09:15 UTC169
        &self.shared.device.name
824bf02b6e55atagen2026-10-16 09:15 UTC170
    }
824bf02b6e55atagen2026-10-16 09:15 UTC171
7de49c2aa70batagen2026-10-16 09:27 UTC172
    /// Whether dmabufs can be imported, rendered into and allocated.
7de49c2aa70batagen2026-10-16 09:27 UTC173
    pub fn supports_dmabuf(&self) -> bool {
7de49c2aa70batagen2026-10-16 09:27 UTC174
        self.caps.render.iter().next().is_some()
7de49c2aa70batagen2026-10-16 09:27 UTC175
    }
7de49c2aa70batagen2026-10-16 09:27 UTC176
7de49c2aa70batagen2026-10-16 09:27 UTC177
    /// Formats and modifiers this renderer can render into as dmabufs.
7de49c2aa70batagen2026-10-16 09:27 UTC178
    pub fn render_formats(&self) -> FormatSet {
7de49c2aa70batagen2026-10-16 09:27 UTC179
        self.caps.render.clone()
7de49c2aa70batagen2026-10-16 09:27 UTC180
    }
7de49c2aa70batagen2026-10-16 09:27 UTC181
7de49c2aa70batagen2026-10-16 09:27 UTC182
    /// An allocator for render-capable dmabufs on this device.
7de49c2aa70batagen2026-10-16 09:27 UTC183
    pub fn allocator(&self) -> VulkanAllocator {
7de49c2aa70batagen2026-10-16 09:27 UTC184
        VulkanAllocator {
7de49c2aa70batagen2026-10-16 09:27 UTC185
            shared: self.shared.clone(),
7de49c2aa70batagen2026-10-16 09:27 UTC186
            caps: self.caps.clone(),
7de49c2aa70batagen2026-10-16 09:27 UTC187
        }
7de49c2aa70batagen2026-10-16 09:27 UTC188
    }
7de49c2aa70batagen2026-10-16 09:27 UTC189
824bf02b6e55atagen2026-10-16 09:15 UTC190
    pub(crate) fn shared(&self) -> &Arc<Shared> {
824bf02b6e55atagen2026-10-16 09:15 UTC191
        &self.shared
824bf02b6e55atagen2026-10-16 09:15 UTC192
    }
824bf02b6e55atagen2026-10-16 09:15 UTC193
824bf02b6e55atagen2026-10-16 09:15 UTC194
    pub(crate) fn context_id_ref(&self) -> &ContextId<VulkanTexture> {
824bf02b6e55atagen2026-10-16 09:15 UTC195
        &self.context
824bf02b6e55atagen2026-10-16 09:15 UTC196
    }
824bf02b6e55atagen2026-10-16 09:15 UTC197
824bf02b6e55atagen2026-10-16 09:15 UTC198
    fn sampler(&self) -> vk::Sampler {
824bf02b6e55atagen2026-10-16 09:15 UTC199
        let idx = |f: TextureFilter| usize::from(f == TextureFilter::Nearest);
824bf02b6e55atagen2026-10-16 09:15 UTC200
        self.samplers[(idx(self.min_filter) << 1) | idx(self.mag_filter)]
824bf02b6e55atagen2026-10-16 09:15 UTC201
    }
824bf02b6e55atagen2026-10-16 09:15 UTC202
824bf02b6e55atagen2026-10-16 09:15 UTC203
    fn reap(&mut self) {
d5eca1c82213atagen2026-10-16 13:56 UTC204
        let spare = &mut self.spare_cmds;
824bf02b6e55atagen2026-10-16 09:15 UTC205
        self.pending.retain(|p| {
824bf02b6e55atagen2026-10-16 09:15 UTC206
            if !p.fence.signaled() {
824bf02b6e55atagen2026-10-16 09:15 UTC207
                return true;
824bf02b6e55atagen2026-10-16 09:15 UTC208
            }
d5eca1c82213atagen2026-10-16 13:56 UTC209
            spare.push(p.cmd);
824bf02b6e55atagen2026-10-16 09:15 UTC210
            false
824bf02b6e55atagen2026-10-16 09:15 UTC211
        });
7de49c2aa70batagen2026-10-16 09:27 UTC212
        self.dmabuf_textures.retain(|k, _| !k.is_gone());
7de49c2aa70batagen2026-10-16 09:27 UTC213
        self.dmabuf_targets.retain(|k, _| !k.is_gone());
824bf02b6e55atagen2026-10-16 09:15 UTC214
    }
824bf02b6e55atagen2026-10-16 09:15 UTC215
d5eca1c82213atagen2026-10-16 13:56 UTC216
    fn begin(&mut self) -> Result<vk::CommandBuffer, Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC217
        let d = &self.shared.device.device;
d5eca1c82213atagen2026-10-16 13:56 UTC218
        let cmd = match self.spare_cmds.pop() {
d5eca1c82213atagen2026-10-16 13:56 UTC219
            Some(cmd) => {
d5eca1c82213atagen2026-10-16 13:56 UTC220
                unsafe { d.reset_command_buffer(cmd, vk::CommandBufferResetFlags::empty())? };
d5eca1c82213atagen2026-10-16 13:56 UTC221
                cmd
d5eca1c82213atagen2026-10-16 13:56 UTC222
            }
d5eca1c82213atagen2026-10-16 13:56 UTC223
            None => unsafe {
d5eca1c82213atagen2026-10-16 13:56 UTC224
                d.allocate_command_buffers(
d5eca1c82213atagen2026-10-16 13:56 UTC225
                    &vk::CommandBufferAllocateInfo::default()
d5eca1c82213atagen2026-10-16 13:56 UTC226
                        .command_pool(self.pool)
d5eca1c82213atagen2026-10-16 13:56 UTC227
                        .level(vk::CommandBufferLevel::PRIMARY)
d5eca1c82213atagen2026-10-16 13:56 UTC228
                        .command_buffer_count(1),
d5eca1c82213atagen2026-10-16 13:56 UTC229
                )?[0]
d5eca1c82213atagen2026-10-16 13:56 UTC230
            },
824bf02b6e55atagen2026-10-16 09:15 UTC231
        };
824bf02b6e55atagen2026-10-16 09:15 UTC232
        unsafe {
824bf02b6e55atagen2026-10-16 09:15 UTC233
            d.begin_command_buffer(
824bf02b6e55atagen2026-10-16 09:15 UTC234
                cmd,
824bf02b6e55atagen2026-10-16 09:15 UTC235
                &vk::CommandBufferBeginInfo::default()
824bf02b6e55atagen2026-10-16 09:15 UTC236
                    .flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT),
824bf02b6e55atagen2026-10-16 09:15 UTC237
            )?
824bf02b6e55atagen2026-10-16 09:15 UTC238
        };
824bf02b6e55atagen2026-10-16 09:15 UTC239
        Ok(cmd)
824bf02b6e55atagen2026-10-16 09:15 UTC240
    }
824bf02b6e55atagen2026-10-16 09:15 UTC241
30aece3a63ceatagen2026-10-16 13:48 UTC242
    #[profiling::function]
824bf02b6e55atagen2026-10-16 09:15 UTC243
    fn end_and_submit(&self, cmd: vk::CommandBuffer) -> Result<Arc<FenceInner>, Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC244
        let d = &self.shared.device.device;
d5eca1c82213atagen2026-10-16 13:56 UTC245
        {
d5eca1c82213atagen2026-10-16 13:56 UTC246
            profiling::scope!("end_command_buffer");
d5eca1c82213atagen2026-10-16 13:56 UTC247
            unsafe { d.end_command_buffer(cmd)? };
d5eca1c82213atagen2026-10-16 13:56 UTC248
        }
d5eca1c82213atagen2026-10-16 13:56 UTC249
        let fence = {
d5eca1c82213atagen2026-10-16 13:56 UTC250
            profiling::scope!("create_fence");
d5eca1c82213atagen2026-10-16 13:56 UTC251
            FenceInner::new(&self.shared)?
d5eca1c82213atagen2026-10-16 13:56 UTC252
        };
824bf02b6e55atagen2026-10-16 09:15 UTC253
        let cmds = [vk::CommandBufferSubmitInfo::default().command_buffer(cmd)];
824bf02b6e55atagen2026-10-16 09:15 UTC254
        let submit = vk::SubmitInfo2::default().command_buffer_infos(&cmds);
824bf02b6e55atagen2026-10-16 09:15 UTC255
        let queue = self
824bf02b6e55atagen2026-10-16 09:15 UTC256
            .shared
824bf02b6e55atagen2026-10-16 09:15 UTC257
            .device
824bf02b6e55atagen2026-10-16 09:15 UTC258
            .queue
824bf02b6e55atagen2026-10-16 09:15 UTC259
            .lock()
824bf02b6e55atagen2026-10-16 09:15 UTC260
            .unwrap_or_else(|e| e.into_inner());
5cd954fce34batagen2026-10-16 22:42 UTC261
        let began = Instant::now();
d5eca1c82213atagen2026-10-16 13:56 UTC262
        {
d5eca1c82213atagen2026-10-16 13:56 UTC263
            profiling::scope!("queue_submit");
d5eca1c82213atagen2026-10-16 13:56 UTC264
            unsafe { d.queue_submit2(*queue, &[submit], fence.fence())? };
d5eca1c82213atagen2026-10-16 13:56 UTC265
        }
5cd954fce34batagen2026-10-16 22:42 UTC266
        let n = self.submissions.get();
5cd954fce34batagen2026-10-16 22:42 UTC267
        self.submissions.set(n + 1);
5cd954fce34batagen2026-10-16 22:42 UTC268
        if began.elapsed() > STALL {
5cd954fce34batagen2026-10-16 22:42 UTC269
            self.stall.set(self.stall.get().saw(n % 1024));
5cd954fce34batagen2026-10-16 22:42 UTC270
        }
824bf02b6e55atagen2026-10-16 09:15 UTC271
        Ok(fence)
824bf02b6e55atagen2026-10-16 09:15 UTC272
    }
824bf02b6e55atagen2026-10-16 09:15 UTC273
5cd954fce34batagen2026-10-16 22:42 UTC274
    /// Spends an upcoming stalling submission on empty command buffers, so
5cd954fce34batagen2026-10-16 22:42 UTC275
    /// the stall lands now, in idle time, instead of in a frame. Call it
5cd954fce34batagen2026-10-16 22:42 UTC276
    /// right after a flip. NVIDIA stalls for milliseconds on every 1024th
5cd954fce34batagen2026-10-16 22:42 UTC277
    /// submission, see research/nvidia.md.
5cd954fce34batagen2026-10-16 22:42 UTC278
    pub fn absorb_submit_stall(&mut self) -> Result<(), Error> {
5cd954fce34batagen2026-10-16 22:42 UTC279
        self.reap();
5cd954fce34batagen2026-10-16 22:42 UTC280
        let Some(phase) = self.stall.get().phase else {
5cd954fce34batagen2026-10-16 22:42 UTC281
            return Ok(());
5cd954fce34batagen2026-10-16 22:42 UTC282
        };
5cd954fce34batagen2026-10-16 22:42 UTC283
        let ahead = (phase + 1024 - self.submissions.get() % 1024) % 1024;
5cd954fce34batagen2026-10-16 22:42 UTC284
        if ahead >= ABSORB_AHEAD {
5cd954fce34batagen2026-10-16 22:42 UTC285
            return Ok(());
5cd954fce34batagen2026-10-16 22:42 UTC286
        }
5cd954fce34batagen2026-10-16 22:42 UTC287
        for _ in 0..=ahead {
5cd954fce34batagen2026-10-16 22:42 UTC288
            let cmd = self.begin()?;
5cd954fce34batagen2026-10-16 22:42 UTC289
            let fence = self.end_and_submit(cmd)?;
5cd954fce34batagen2026-10-16 22:42 UTC290
            self.pending.push(Pending {
5cd954fce34batagen2026-10-16 22:42 UTC291
                fence,
5cd954fce34batagen2026-10-16 22:42 UTC292
                cmd,
5cd954fce34batagen2026-10-16 22:42 UTC293
                _keep: Vec::new(),
5cd954fce34batagen2026-10-16 22:42 UTC294
                _staging: None,
5cd954fce34batagen2026-10-16 22:42 UTC295
            });
5cd954fce34batagen2026-10-16 22:42 UTC296
        }
5cd954fce34batagen2026-10-16 22:42 UTC297
        Ok(())
5cd954fce34batagen2026-10-16 22:42 UTC298
    }
5cd954fce34batagen2026-10-16 22:42 UTC299
824bf02b6e55atagen2026-10-16 09:15 UTC300
    /// Records, submits and waits for a short command buffer.
824bf02b6e55atagen2026-10-16 09:15 UTC301
    fn one_shot(
824bf02b6e55atagen2026-10-16 09:15 UTC302
        &mut self,
7de49c2aa70batagen2026-10-16 09:27 UTC303
        record: impl FnOnce(&ash::Device, vk::CommandBuffer, u32),
824bf02b6e55atagen2026-10-16 09:15 UTC304
    ) -> Result<(), Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC305
        let cmd = self.begin()?;
7de49c2aa70batagen2026-10-16 09:27 UTC306
        record(
7de49c2aa70batagen2026-10-16 09:27 UTC307
            &self.shared.device.device,
7de49c2aa70batagen2026-10-16 09:27 UTC308
            cmd,
7de49c2aa70batagen2026-10-16 09:27 UTC309
            self.shared.device.queue_family,
7de49c2aa70batagen2026-10-16 09:27 UTC310
        );
824bf02b6e55atagen2026-10-16 09:15 UTC311
        let fence = self.end_and_submit(cmd)?;
824bf02b6e55atagen2026-10-16 09:15 UTC312
        let res = fence.wait();
d5eca1c82213atagen2026-10-16 13:56 UTC313
        self.spare_cmds.push(cmd);
824bf02b6e55atagen2026-10-16 09:15 UTC314
        Ok(res?)
824bf02b6e55atagen2026-10-16 09:15 UTC315
    }
824bf02b6e55atagen2026-10-16 09:15 UTC316
30aece3a63ceatagen2026-10-16 13:48 UTC317
    #[profiling::function]
824bf02b6e55atagen2026-10-16 09:15 UTC318
    pub(crate) fn submit(
824bf02b6e55atagen2026-10-16 09:15 UTC319
        &mut self,
824bf02b6e55atagen2026-10-16 09:15 UTC320
        target: &mut VulkanTarget<'_>,
824bf02b6e55atagen2026-10-16 09:15 UTC321
        ops: Vec<Op>,
824bf02b6e55atagen2026-10-16 09:15 UTC322
    ) -> Result<SyncPoint, Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC323
        self.reap();
7de49c2aa70batagen2026-10-16 09:27 UTC324
        let image = target.0.clone();
7de49c2aa70batagen2026-10-16 09:27 UTC325
        let mut sampled: Vec<Arc<ImageInner>> = Vec::new();
824bf02b6e55atagen2026-10-16 09:15 UTC326
        for op in &ops {
824bf02b6e55atagen2026-10-16 09:15 UTC327
            if let Op::Draw {
824bf02b6e55atagen2026-10-16 09:15 UTC328
                texture: Some(t), ..
824bf02b6e55atagen2026-10-16 09:15 UTC329
            } = op
7de49c2aa70batagen2026-10-16 09:27 UTC330
                && !sampled.iter().any(|s| Arc::ptr_eq(s, &t.0))
824bf02b6e55atagen2026-10-16 09:15 UTC331
            {
7de49c2aa70batagen2026-10-16 09:27 UTC332
                sampled.push(t.0.clone());
824bf02b6e55atagen2026-10-16 09:15 UTC333
            }
824bf02b6e55atagen2026-10-16 09:15 UTC334
        }
824bf02b6e55atagen2026-10-16 09:15 UTC335
        let mut pipelines = Vec::with_capacity(ops.len());
824bf02b6e55atagen2026-10-16 09:15 UTC336
        for op in &ops {
824bf02b6e55atagen2026-10-16 09:15 UTC337
            pipelines.push(match op {
824bf02b6e55atagen2026-10-16 09:15 UTC338
                Op::Draw { kind, .. } => Some(self.pipelines.get(image.format, *kind)?),
824bf02b6e55atagen2026-10-16 09:15 UTC339
                Op::Clear { .. } => None,
824bf02b6e55atagen2026-10-16 09:15 UTC340
            });
824bf02b6e55atagen2026-10-16 09:15 UTC341
        }
824bf02b6e55atagen2026-10-16 09:15 UTC342
        let cmd = self.begin()?;
824bf02b6e55atagen2026-10-16 09:15 UTC343
        let d = &self.shared.device.device;
7de49c2aa70batagen2026-10-16 09:27 UTC344
        let family = self.shared.device.queue_family;
824bf02b6e55atagen2026-10-16 09:15 UTC345
        let push = &self.shared.device.push_descriptor;
824bf02b6e55atagen2026-10-16 09:15 UTC346
        let (w, h) = (image.width, image.height);
824bf02b6e55atagen2026-10-16 09:15 UTC347
        let sampler = self.sampler();
824bf02b6e55atagen2026-10-16 09:15 UTC348
        unsafe {
7de49c2aa70batagen2026-10-16 09:27 UTC349
            for t in &sampled {
7de49c2aa70batagen2026-10-16 09:27 UTC350
                acquire(d, cmd, family, t, vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL);
824bf02b6e55atagen2026-10-16 09:15 UTC351
            }
7de49c2aa70batagen2026-10-16 09:27 UTC352
            acquire(
824bf02b6e55atagen2026-10-16 09:15 UTC353
                d,
824bf02b6e55atagen2026-10-16 09:15 UTC354
                cmd,
7de49c2aa70batagen2026-10-16 09:27 UTC355
                family,
7de49c2aa70batagen2026-10-16 09:27 UTC356
                &image,
824bf02b6e55atagen2026-10-16 09:15 UTC357
                vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
824bf02b6e55atagen2026-10-16 09:15 UTC358
            );
824bf02b6e55atagen2026-10-16 09:15 UTC359
            let attachments = [vk::RenderingAttachmentInfo::default()
824bf02b6e55atagen2026-10-16 09:15 UTC360
                .image_view(image.view)
824bf02b6e55atagen2026-10-16 09:15 UTC361
                .image_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
824bf02b6e55atagen2026-10-16 09:15 UTC362
                .load_op(vk::AttachmentLoadOp::LOAD)
824bf02b6e55atagen2026-10-16 09:15 UTC363
                .store_op(vk::AttachmentStoreOp::STORE)];
824bf02b6e55atagen2026-10-16 09:15 UTC364
            let area = vk::Rect2D {
824bf02b6e55atagen2026-10-16 09:15 UTC365
                offset: vk::Offset2D::default(),
824bf02b6e55atagen2026-10-16 09:15 UTC366
                extent: vk::Extent2D {
824bf02b6e55atagen2026-10-16 09:15 UTC367
                    width: w,
824bf02b6e55atagen2026-10-16 09:15 UTC368
                    height: h,
824bf02b6e55atagen2026-10-16 09:15 UTC369
                },
824bf02b6e55atagen2026-10-16 09:15 UTC370
            };
824bf02b6e55atagen2026-10-16 09:15 UTC371
            d.cmd_begin_rendering(
824bf02b6e55atagen2026-10-16 09:15 UTC372
                cmd,
824bf02b6e55atagen2026-10-16 09:15 UTC373
                &vk::RenderingInfo::default()
824bf02b6e55atagen2026-10-16 09:15 UTC374
                    .render_area(area)
824bf02b6e55atagen2026-10-16 09:15 UTC375
                    .layer_count(1)
824bf02b6e55atagen2026-10-16 09:15 UTC376
                    .color_attachments(&attachments),
824bf02b6e55atagen2026-10-16 09:15 UTC377
            );
824bf02b6e55atagen2026-10-16 09:15 UTC378
            d.cmd_set_viewport(
824bf02b6e55atagen2026-10-16 09:15 UTC379
                cmd,
824bf02b6e55atagen2026-10-16 09:15 UTC380
                0,
824bf02b6e55atagen2026-10-16 09:15 UTC381
                &[vk::Viewport {
824bf02b6e55atagen2026-10-16 09:15 UTC382
                    x: 0.0,
824bf02b6e55atagen2026-10-16 09:15 UTC383
                    y: 0.0,
824bf02b6e55atagen2026-10-16 09:15 UTC384
                    width: w as f32,
824bf02b6e55atagen2026-10-16 09:15 UTC385
                    height: h as f32,
824bf02b6e55atagen2026-10-16 09:15 UTC386
                    min_depth: 0.0,
824bf02b6e55atagen2026-10-16 09:15 UTC387
                    max_depth: 1.0,
824bf02b6e55atagen2026-10-16 09:15 UTC388
                }],
824bf02b6e55atagen2026-10-16 09:15 UTC389
            );
824bf02b6e55atagen2026-10-16 09:15 UTC390
            let mut bound = vk::Pipeline::null();
824bf02b6e55atagen2026-10-16 09:15 UTC391
            for (op, pipeline) in ops.iter().zip(pipelines) {
824bf02b6e55atagen2026-10-16 09:15 UTC392
                match op {
824bf02b6e55atagen2026-10-16 09:15 UTC393
                    Op::Clear { color, rects } => {
824bf02b6e55atagen2026-10-16 09:15 UTC394
                        let clear = [vk::ClearAttachment {
824bf02b6e55atagen2026-10-16 09:15 UTC395
                            aspect_mask: vk::ImageAspectFlags::COLOR,
824bf02b6e55atagen2026-10-16 09:15 UTC396
                            color_attachment: 0,
824bf02b6e55atagen2026-10-16 09:15 UTC397
                            clear_value: vk::ClearValue {
824bf02b6e55atagen2026-10-16 09:15 UTC398
                                color: vk::ClearColorValue { float32: *color },
824bf02b6e55atagen2026-10-16 09:15 UTC399
                            },
824bf02b6e55atagen2026-10-16 09:15 UTC400
                        }];
824bf02b6e55atagen2026-10-16 09:15 UTC401
                        let rects: Vec<_> = rects
824bf02b6e55atagen2026-10-16 09:15 UTC402
                            .iter()
824bf02b6e55atagen2026-10-16 09:15 UTC403
                            .map(|&rect| vk::ClearRect {
824bf02b6e55atagen2026-10-16 09:15 UTC404
                                rect,
824bf02b6e55atagen2026-10-16 09:15 UTC405
                                base_array_layer: 0,
824bf02b6e55atagen2026-10-16 09:15 UTC406
                                layer_count: 1,
824bf02b6e55atagen2026-10-16 09:15 UTC407
                            })
824bf02b6e55atagen2026-10-16 09:15 UTC408
                            .collect();
824bf02b6e55atagen2026-10-16 09:15 UTC409
                        d.cmd_clear_attachments(cmd, &clear, &rects);
824bf02b6e55atagen2026-10-16 09:15 UTC410
                    }
824bf02b6e55atagen2026-10-16 09:15 UTC411
                    Op::Draw {
824bf02b6e55atagen2026-10-16 09:15 UTC412
                        texture,
824bf02b6e55atagen2026-10-16 09:15 UTC413
                        push: constants,
824bf02b6e55atagen2026-10-16 09:15 UTC414
                        scissors,
824bf02b6e55atagen2026-10-16 09:15 UTC415
                        ..
824bf02b6e55atagen2026-10-16 09:15 UTC416
                    } => {
824bf02b6e55atagen2026-10-16 09:15 UTC417
                        let pipeline = pipeline.unwrap_or_default();
824bf02b6e55atagen2026-10-16 09:15 UTC418
                        if pipeline != bound {
824bf02b6e55atagen2026-10-16 09:15 UTC419
                            d.cmd_bind_pipeline(cmd, vk::PipelineBindPoint::GRAPHICS, pipeline);
824bf02b6e55atagen2026-10-16 09:15 UTC420
                            bound = pipeline;
824bf02b6e55atagen2026-10-16 09:15 UTC421
                        }
824bf02b6e55atagen2026-10-16 09:15 UTC422
                        if let Some(t) = texture {
824bf02b6e55atagen2026-10-16 09:15 UTC423
                            let info = [vk::DescriptorImageInfo::default()
824bf02b6e55atagen2026-10-16 09:15 UTC424
                                .image_view(t.0.view)
824bf02b6e55atagen2026-10-16 09:15 UTC425
                                .image_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
824bf02b6e55atagen2026-10-16 09:15 UTC426
                                .sampler(sampler)];
824bf02b6e55atagen2026-10-16 09:15 UTC427
                            let write = vk::WriteDescriptorSet::default()
824bf02b6e55atagen2026-10-16 09:15 UTC428
                                .dst_binding(0)
824bf02b6e55atagen2026-10-16 09:15 UTC429
                                .descriptor_type(vk::DescriptorType::COMBINED_IMAGE_SAMPLER)
824bf02b6e55atagen2026-10-16 09:15 UTC430
                                .image_info(&info);
824bf02b6e55atagen2026-10-16 09:15 UTC431
                            push.cmd_push_descriptor_set(
824bf02b6e55atagen2026-10-16 09:15 UTC432
                                cmd,
824bf02b6e55atagen2026-10-16 09:15 UTC433
                                vk::PipelineBindPoint::GRAPHICS,
824bf02b6e55atagen2026-10-16 09:15 UTC434
                                self.pipelines.layout,
824bf02b6e55atagen2026-10-16 09:15 UTC435
                                0,
824bf02b6e55atagen2026-10-16 09:15 UTC436
                                &[write],
824bf02b6e55atagen2026-10-16 09:15 UTC437
                            );
824bf02b6e55atagen2026-10-16 09:15 UTC438
                        }
824bf02b6e55atagen2026-10-16 09:15 UTC439
                        d.cmd_push_constants(
824bf02b6e55atagen2026-10-16 09:15 UTC440
                            cmd,
824bf02b6e55atagen2026-10-16 09:15 UTC441
                            self.pipelines.layout,
824bf02b6e55atagen2026-10-16 09:15 UTC442
                            vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::FRAGMENT,
824bf02b6e55atagen2026-10-16 09:15 UTC443
                            0,
824bf02b6e55atagen2026-10-16 09:15 UTC444
                            constants.bytes(),
824bf02b6e55atagen2026-10-16 09:15 UTC445
                        );
824bf02b6e55atagen2026-10-16 09:15 UTC446
                        for s in scissors {
824bf02b6e55atagen2026-10-16 09:15 UTC447
                            d.cmd_set_scissor(cmd, 0, &[*s]);
824bf02b6e55atagen2026-10-16 09:15 UTC448
                            d.cmd_draw(cmd, 4, 1, 0, 0);
824bf02b6e55atagen2026-10-16 09:15 UTC449
                        }
824bf02b6e55atagen2026-10-16 09:15 UTC450
                    }
824bf02b6e55atagen2026-10-16 09:15 UTC451
                }
824bf02b6e55atagen2026-10-16 09:15 UTC452
            }
824bf02b6e55atagen2026-10-16 09:15 UTC453
            d.cmd_end_rendering(cmd);
7de49c2aa70batagen2026-10-16 09:27 UTC454
            release(
7de49c2aa70batagen2026-10-16 09:27 UTC455
                d,
7de49c2aa70batagen2026-10-16 09:27 UTC456
                cmd,
7de49c2aa70batagen2026-10-16 09:27 UTC457
                family,
7de49c2aa70batagen2026-10-16 09:27 UTC458
                &image,
7de49c2aa70batagen2026-10-16 09:27 UTC459
                vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
7de49c2aa70batagen2026-10-16 09:27 UTC460
            );
7de49c2aa70batagen2026-10-16 09:27 UTC461
            for t in &sampled {
7de49c2aa70batagen2026-10-16 09:27 UTC462
                release(d, cmd, family, t, vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL);
7de49c2aa70batagen2026-10-16 09:27 UTC463
            }
824bf02b6e55atagen2026-10-16 09:15 UTC464
        }
824bf02b6e55atagen2026-10-16 09:15 UTC465
        let fence = self.end_and_submit(cmd)?;
7de49c2aa70batagen2026-10-16 09:27 UTC466
        sampled.push(image);
824bf02b6e55atagen2026-10-16 09:15 UTC467
        self.pending.push(Pending {
824bf02b6e55atagen2026-10-16 09:15 UTC468
            fence: fence.clone(),
824bf02b6e55atagen2026-10-16 09:15 UTC469
            cmd,
7de49c2aa70batagen2026-10-16 09:27 UTC470
            _keep: sampled,
48af562d968batagen2026-10-16 12:39 UTC471
            _staging: None,
824bf02b6e55atagen2026-10-16 09:15 UTC472
        });
824bf02b6e55atagen2026-10-16 09:15 UTC473
        Ok(SyncPoint::from(VkFence(fence)))
824bf02b6e55atagen2026-10-16 09:15 UTC474
    }
824bf02b6e55atagen2026-10-16 09:15 UTC475
48af562d968batagen2026-10-16 12:39 UTC476
    /// Copies `region` of a full-image `data` into `image`, rows top-down or
48af562d968batagen2026-10-16 12:39 UTC477
    /// flipped.
824bf02b6e55atagen2026-10-16 09:15 UTC478
    fn upload(
824bf02b6e55atagen2026-10-16 09:15 UTC479
        &mut self,
824bf02b6e55atagen2026-10-16 09:15 UTC480
        image: &Arc<ImageInner>,
824bf02b6e55atagen2026-10-16 09:15 UTC481
        data: &[u8],
824bf02b6e55atagen2026-10-16 09:15 UTC482
        region: Rectangle<i32, Buffer>,
824bf02b6e55atagen2026-10-16 09:15 UTC483
        flipped: bool,
824bf02b6e55atagen2026-10-16 09:15 UTC484
    ) -> Result<(), Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC485
        let width = image.width as usize;
48af562d968batagen2026-10-16 12:39 UTC486
        let rows = image.height as usize;
48af562d968batagen2026-10-16 12:39 UTC487
        let needed = width * rows * BYTES_PER_PIXEL;
824bf02b6e55atagen2026-10-16 09:15 UTC488
        if data.len() < needed {
824bf02b6e55atagen2026-10-16 09:15 UTC489
            return Err(Error::BufferTooSmall {
824bf02b6e55atagen2026-10-16 09:15 UTC490
                needed,
824bf02b6e55atagen2026-10-16 09:15 UTC491
                got: data.len(),
824bf02b6e55atagen2026-10-16 09:15 UTC492
            });
824bf02b6e55atagen2026-10-16 09:15 UTC493
        }
48af562d968batagen2026-10-16 12:39 UTC494
        let stride = width * BYTES_PER_PIXEL;
48af562d968batagen2026-10-16 12:39 UTC495
        self.upload_with(image, region, |y| {
48af562d968batagen2026-10-16 12:39 UTC496
            let from = if flipped { rows - 1 - y } else { y };
48af562d968batagen2026-10-16 12:39 UTC497
            let start = from * stride + region.loc.x as usize * BYTES_PER_PIXEL;
48af562d968batagen2026-10-16 12:39 UTC498
            &data[start..start + region.size.w as usize * BYTES_PER_PIXEL]
48af562d968batagen2026-10-16 12:39 UTC499
        })
48af562d968batagen2026-10-16 12:39 UTC500
    }
48af562d968batagen2026-10-16 12:39 UTC501
48af562d968batagen2026-10-16 12:39 UTC502
    /// Uploads `region` of `image`, taking each image row `y` in the region
48af562d968batagen2026-10-16 12:39 UTC503
    /// from `row(y)`. The CPU does not wait: the copy is ordered before later
48af562d968batagen2026-10-16 12:39 UTC504
    /// frames by its barrier, and its staging memory lives until its fence.
30aece3a63ceatagen2026-10-16 13:48 UTC505
    #[profiling::function]
48af562d968batagen2026-10-16 12:39 UTC506
    fn upload_with<'a>(
48af562d968batagen2026-10-16 12:39 UTC507
        &mut self,
48af562d968batagen2026-10-16 12:39 UTC508
        image: &Arc<ImageInner>,
48af562d968batagen2026-10-16 12:39 UTC509
        region: Rectangle<i32, Buffer>,
48af562d968batagen2026-10-16 12:39 UTC510
        row: impl Fn(usize) -> &'a [u8],
48af562d968batagen2026-10-16 12:39 UTC511
    ) -> Result<(), Error> {
48af562d968batagen2026-10-16 12:39 UTC512
        if image.external {
48af562d968batagen2026-10-16 12:39 UTC513
            return Err(Error::ForeignTexture);
48af562d968batagen2026-10-16 12:39 UTC514
        }
48af562d968batagen2026-10-16 12:39 UTC515
        self.reap();
48af562d968batagen2026-10-16 12:39 UTC516
        let (w, h) = (region.size.w as usize, region.size.h as usize);
48af562d968batagen2026-10-16 12:39 UTC517
        if w == 0 || h == 0 {
48af562d968batagen2026-10-16 12:39 UTC518
            return Ok(());
48af562d968batagen2026-10-16 12:39 UTC519
        }
48af562d968batagen2026-10-16 12:39 UTC520
        let line = w * BYTES_PER_PIXEL;
824bf02b6e55atagen2026-10-16 09:15 UTC521
        let mut staging = Staging::new(
824bf02b6e55atagen2026-10-16 09:15 UTC522
            &self.shared,
48af562d968batagen2026-10-16 12:39 UTC523
            line * h,
824bf02b6e55atagen2026-10-16 09:15 UTC524
            vk::BufferUsageFlags::TRANSFER_SRC,
824bf02b6e55atagen2026-10-16 09:15 UTC525
            MemoryLocation::CpuToGpu,
824bf02b6e55atagen2026-10-16 09:15 UTC526
        )?;
824bf02b6e55atagen2026-10-16 09:15 UTC527
        let dst = staging.bytes_mut();
48af562d968batagen2026-10-16 12:39 UTC528
        for i in 0..h {
48af562d968batagen2026-10-16 12:39 UTC529
            dst[i * line..(i + 1) * line].copy_from_slice(row(region.loc.y as usize + i));
824bf02b6e55atagen2026-10-16 09:15 UTC530
        }
824bf02b6e55atagen2026-10-16 09:15 UTC531
        let copy = vk::BufferImageCopy::default()
48af562d968batagen2026-10-16 12:39 UTC532
            .buffer_row_length(w as u32)
824bf02b6e55atagen2026-10-16 09:15 UTC533
            .image_subresource(
824bf02b6e55atagen2026-10-16 09:15 UTC534
                vk::ImageSubresourceLayers::default()
824bf02b6e55atagen2026-10-16 09:15 UTC535
                    .aspect_mask(vk::ImageAspectFlags::COLOR)
824bf02b6e55atagen2026-10-16 09:15 UTC536
                    .layer_count(1),
824bf02b6e55atagen2026-10-16 09:15 UTC537
            )
824bf02b6e55atagen2026-10-16 09:15 UTC538
            .image_offset(vk::Offset3D {
824bf02b6e55atagen2026-10-16 09:15 UTC539
                x: region.loc.x,
824bf02b6e55atagen2026-10-16 09:15 UTC540
                y: region.loc.y,
824bf02b6e55atagen2026-10-16 09:15 UTC541
                z: 0,
824bf02b6e55atagen2026-10-16 09:15 UTC542
            })
824bf02b6e55atagen2026-10-16 09:15 UTC543
            .image_extent(vk::Extent3D {
48af562d968batagen2026-10-16 12:39 UTC544
                width: w as u32,
48af562d968batagen2026-10-16 12:39 UTC545
                height: h as u32,
824bf02b6e55atagen2026-10-16 09:15 UTC546
                depth: 1,
824bf02b6e55atagen2026-10-16 09:15 UTC547
            });
d5eca1c82213atagen2026-10-16 13:56 UTC548
        let cmd = self.begin()?;
48af562d968batagen2026-10-16 12:39 UTC549
        let d = &self.shared.device.device;
48af562d968batagen2026-10-16 12:39 UTC550
        let family = self.shared.device.queue_family;
48af562d968batagen2026-10-16 12:39 UTC551
        unsafe {
48af562d968batagen2026-10-16 12:39 UTC552
            acquire(d, cmd, family, image, vk::ImageLayout::TRANSFER_DST_OPTIMAL);
824bf02b6e55atagen2026-10-16 09:15 UTC553
            d.cmd_copy_buffer_to_image(
824bf02b6e55atagen2026-10-16 09:15 UTC554
                cmd,
48af562d968batagen2026-10-16 12:39 UTC555
                staging.buffer,
48af562d968batagen2026-10-16 12:39 UTC556
                image.image,
824bf02b6e55atagen2026-10-16 09:15 UTC557
                vk::ImageLayout::TRANSFER_DST_OPTIMAL,
824bf02b6e55atagen2026-10-16 09:15 UTC558
                &[copy],
824bf02b6e55atagen2026-10-16 09:15 UTC559
            );
7de49c2aa70batagen2026-10-16 09:27 UTC560
            acquire(
824bf02b6e55atagen2026-10-16 09:15 UTC561
                d,
824bf02b6e55atagen2026-10-16 09:15 UTC562
                cmd,
7de49c2aa70batagen2026-10-16 09:27 UTC563
                family,
48af562d968batagen2026-10-16 12:39 UTC564
                image,
824bf02b6e55atagen2026-10-16 09:15 UTC565
                vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
824bf02b6e55atagen2026-10-16 09:15 UTC566
            );
48af562d968batagen2026-10-16 12:39 UTC567
        }
48af562d968batagen2026-10-16 12:39 UTC568
        let fence = self.end_and_submit(cmd)?;
48af562d968batagen2026-10-16 12:39 UTC569
        self.pending.push(Pending {
48af562d968batagen2026-10-16 12:39 UTC570
            fence,
48af562d968batagen2026-10-16 12:39 UTC571
            cmd,
48af562d968batagen2026-10-16 12:39 UTC572
            _keep: vec![image.clone()],
48af562d968batagen2026-10-16 12:39 UTC573
            _staging: Some(staging),
48af562d968batagen2026-10-16 12:39 UTC574
        });
48af562d968batagen2026-10-16 12:39 UTC575
        Ok(())
824bf02b6e55atagen2026-10-16 09:15 UTC576
    }
824bf02b6e55atagen2026-10-16 09:15 UTC577
824bf02b6e55atagen2026-10-16 09:15 UTC578
    fn read_back(
824bf02b6e55atagen2026-10-16 09:15 UTC579
        &mut self,
824bf02b6e55atagen2026-10-16 09:15 UTC580
        image: &Arc<ImageInner>,
824bf02b6e55atagen2026-10-16 09:15 UTC581
        region: Rectangle<i32, Buffer>,
824bf02b6e55atagen2026-10-16 09:15 UTC582
        fourcc: Fourcc,
824bf02b6e55atagen2026-10-16 09:15 UTC583
    ) -> Result<VulkanMapping, Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC584
        let region = region
824bf02b6e55atagen2026-10-16 09:15 UTC585
            .intersection(Rectangle::from_size(
824bf02b6e55atagen2026-10-16 09:15 UTC586
                (image.width as i32, image.height as i32).into(),
824bf02b6e55atagen2026-10-16 09:15 UTC587
            ))
824bf02b6e55atagen2026-10-16 09:15 UTC588
            .unwrap_or_default();
824bf02b6e55atagen2026-10-16 09:15 UTC589
        let (w, h) = (region.size.w.max(0) as u32, region.size.h.max(0) as u32);
824bf02b6e55atagen2026-10-16 09:15 UTC590
        let swap = needs_swizzle(image.fourcc, fourcc)?;
824bf02b6e55atagen2026-10-16 09:15 UTC591
        let len = (w as usize * h as usize * BYTES_PER_PIXEL).max(BYTES_PER_PIXEL);
824bf02b6e55atagen2026-10-16 09:15 UTC592
        let staging = Staging::new(
824bf02b6e55atagen2026-10-16 09:15 UTC593
            &self.shared,
824bf02b6e55atagen2026-10-16 09:15 UTC594
            len,
824bf02b6e55atagen2026-10-16 09:15 UTC595
            vk::BufferUsageFlags::TRANSFER_DST,
824bf02b6e55atagen2026-10-16 09:15 UTC596
            MemoryLocation::GpuToCpu,
824bf02b6e55atagen2026-10-16 09:15 UTC597
        )?;
824bf02b6e55atagen2026-10-16 09:15 UTC598
        if w > 0 && h > 0 {
824bf02b6e55atagen2026-10-16 09:15 UTC599
            let copy = vk::BufferImageCopy::default()
824bf02b6e55atagen2026-10-16 09:15 UTC600
                .image_subresource(
824bf02b6e55atagen2026-10-16 09:15 UTC601
                    vk::ImageSubresourceLayers::default()
824bf02b6e55atagen2026-10-16 09:15 UTC602
                        .aspect_mask(vk::ImageAspectFlags::COLOR)
824bf02b6e55atagen2026-10-16 09:15 UTC603
                        .layer_count(1),
824bf02b6e55atagen2026-10-16 09:15 UTC604
                )
824bf02b6e55atagen2026-10-16 09:15 UTC605
                .image_offset(vk::Offset3D {
824bf02b6e55atagen2026-10-16 09:15 UTC606
                    x: region.loc.x,
824bf02b6e55atagen2026-10-16 09:15 UTC607
                    y: region.loc.y,
824bf02b6e55atagen2026-10-16 09:15 UTC608
                    z: 0,
824bf02b6e55atagen2026-10-16 09:15 UTC609
                })
824bf02b6e55atagen2026-10-16 09:15 UTC610
                .image_extent(vk::Extent3D {
824bf02b6e55atagen2026-10-16 09:15 UTC611
                    width: w,
824bf02b6e55atagen2026-10-16 09:15 UTC612
                    height: h,
824bf02b6e55atagen2026-10-16 09:15 UTC613
                    depth: 1,
824bf02b6e55atagen2026-10-16 09:15 UTC614
                });
7de49c2aa70batagen2026-10-16 09:27 UTC615
            let buffer = staging.buffer;
7de49c2aa70batagen2026-10-16 09:27 UTC616
            let source = image.clone();
7de49c2aa70batagen2026-10-16 09:27 UTC617
            self.one_shot(|d, cmd, family| unsafe {
7de49c2aa70batagen2026-10-16 09:27 UTC618
                acquire(
7de49c2aa70batagen2026-10-16 09:27 UTC619
                    d,
7de49c2aa70batagen2026-10-16 09:27 UTC620
                    cmd,
7de49c2aa70batagen2026-10-16 09:27 UTC621
                    family,
7de49c2aa70batagen2026-10-16 09:27 UTC622
                    &source,
7de49c2aa70batagen2026-10-16 09:27 UTC623
                    vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
7de49c2aa70batagen2026-10-16 09:27 UTC624
                );
824bf02b6e55atagen2026-10-16 09:15 UTC625
                d.cmd_copy_image_to_buffer(
824bf02b6e55atagen2026-10-16 09:15 UTC626
                    cmd,
7de49c2aa70batagen2026-10-16 09:27 UTC627
                    source.image,
824bf02b6e55atagen2026-10-16 09:15 UTC628
                    vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
824bf02b6e55atagen2026-10-16 09:15 UTC629
                    buffer,
824bf02b6e55atagen2026-10-16 09:15 UTC630
                    &[copy],
824bf02b6e55atagen2026-10-16 09:15 UTC631
                );
7de49c2aa70batagen2026-10-16 09:27 UTC632
                release(
7de49c2aa70batagen2026-10-16 09:27 UTC633
                    d,
7de49c2aa70batagen2026-10-16 09:27 UTC634
                    cmd,
7de49c2aa70batagen2026-10-16 09:27 UTC635
                    family,
7de49c2aa70batagen2026-10-16 09:27 UTC636
                    &source,
7de49c2aa70batagen2026-10-16 09:27 UTC637
                    vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
7de49c2aa70batagen2026-10-16 09:27 UTC638
                );
824bf02b6e55atagen2026-10-16 09:15 UTC639
            })?;
824bf02b6e55atagen2026-10-16 09:15 UTC640
        }
824bf02b6e55atagen2026-10-16 09:15 UTC641
        let mut data = staging.bytes()[..w as usize * h as usize * BYTES_PER_PIXEL].to_vec();
824bf02b6e55atagen2026-10-16 09:15 UTC642
        if swap {
824bf02b6e55atagen2026-10-16 09:15 UTC643
            for px in data.as_chunks_mut::<BYTES_PER_PIXEL>().0 {
824bf02b6e55atagen2026-10-16 09:15 UTC644
                px.swap(0, 2);
824bf02b6e55atagen2026-10-16 09:15 UTC645
            }
824bf02b6e55atagen2026-10-16 09:15 UTC646
        }
824bf02b6e55atagen2026-10-16 09:15 UTC647
        Ok(VulkanMapping {
824bf02b6e55atagen2026-10-16 09:15 UTC648
            data,
824bf02b6e55atagen2026-10-16 09:15 UTC649
            width: w,
824bf02b6e55atagen2026-10-16 09:15 UTC650
            height: h,
824bf02b6e55atagen2026-10-16 09:15 UTC651
            fourcc,
824bf02b6e55atagen2026-10-16 09:15 UTC652
        })
824bf02b6e55atagen2026-10-16 09:15 UTC653
    }
824bf02b6e55atagen2026-10-16 09:15 UTC654
824bf02b6e55atagen2026-10-16 09:15 UTC655
    fn own(&self, image: &Arc<ImageInner>) -> Result<(), Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC656
        if Arc::ptr_eq(&image.shared, &self.shared) {
824bf02b6e55atagen2026-10-16 09:15 UTC657
            Ok(())
824bf02b6e55atagen2026-10-16 09:15 UTC658
        } else {
824bf02b6e55atagen2026-10-16 09:15 UTC659
            Err(Error::ForeignTexture)
824bf02b6e55atagen2026-10-16 09:15 UTC660
        }
824bf02b6e55atagen2026-10-16 09:15 UTC661
    }
824bf02b6e55atagen2026-10-16 09:15 UTC662
}
824bf02b6e55atagen2026-10-16 09:15 UTC663
824bf02b6e55atagen2026-10-16 09:15 UTC664
impl Drop for VulkanRenderer {
824bf02b6e55atagen2026-10-16 09:15 UTC665
    fn drop(&mut self) {
824bf02b6e55atagen2026-10-16 09:15 UTC666
        let d = &self.shared.device.device;
824bf02b6e55atagen2026-10-16 09:15 UTC667
        unsafe {
824bf02b6e55atagen2026-10-16 09:15 UTC668
            let _ = d.device_wait_idle();
824bf02b6e55atagen2026-10-16 09:15 UTC669
            for p in self.pending.drain(..) {
824bf02b6e55atagen2026-10-16 09:15 UTC670
                d.free_command_buffers(self.pool, &[p.cmd]);
824bf02b6e55atagen2026-10-16 09:15 UTC671
            }
824bf02b6e55atagen2026-10-16 09:15 UTC672
            for s in self.samplers {
824bf02b6e55atagen2026-10-16 09:15 UTC673
                d.destroy_sampler(s, None);
824bf02b6e55atagen2026-10-16 09:15 UTC674
            }
824bf02b6e55atagen2026-10-16 09:15 UTC675
            d.destroy_command_pool(self.pool, None);
824bf02b6e55atagen2026-10-16 09:15 UTC676
        }
824bf02b6e55atagen2026-10-16 09:15 UTC677
    }
824bf02b6e55atagen2026-10-16 09:15 UTC678
}
824bf02b6e55atagen2026-10-16 09:15 UTC679
824bf02b6e55atagen2026-10-16 09:15 UTC680
fn sampler_filter(bit: usize) -> TextureFilter {
824bf02b6e55atagen2026-10-16 09:15 UTC681
    if bit == 0 {
824bf02b6e55atagen2026-10-16 09:15 UTC682
        TextureFilter::Linear
824bf02b6e55atagen2026-10-16 09:15 UTC683
    } else {
824bf02b6e55atagen2026-10-16 09:15 UTC684
        TextureFilter::Nearest
824bf02b6e55atagen2026-10-16 09:15 UTC685
    }
824bf02b6e55atagen2026-10-16 09:15 UTC686
}
824bf02b6e55atagen2026-10-16 09:15 UTC687
7de49c2aa70batagen2026-10-16 09:27 UTC688
/// A full barrier between all earlier and later work on the image, optionally
7de49c2aa70batagen2026-10-16 09:27 UTC689
/// transferring ownership between queue families. Coarse, but correct for
7de49c2aa70batagen2026-10-16 09:27 UTC690
/// every transition the renderer makes.
824bf02b6e55atagen2026-10-16 09:15 UTC691
unsafe fn barrier(
824bf02b6e55atagen2026-10-16 09:15 UTC692
    d: &ash::Device,
824bf02b6e55atagen2026-10-16 09:15 UTC693
    cmd: vk::CommandBuffer,
824bf02b6e55atagen2026-10-16 09:15 UTC694
    image: vk::Image,
824bf02b6e55atagen2026-10-16 09:15 UTC695
    old: vk::ImageLayout,
824bf02b6e55atagen2026-10-16 09:15 UTC696
    new: vk::ImageLayout,
7de49c2aa70batagen2026-10-16 09:27 UTC697
    src_family: u32,
7de49c2aa70batagen2026-10-16 09:27 UTC698
    dst_family: u32,
824bf02b6e55atagen2026-10-16 09:15 UTC699
) {
824bf02b6e55atagen2026-10-16 09:15 UTC700
    let b = [vk::ImageMemoryBarrier2::default()
824bf02b6e55atagen2026-10-16 09:15 UTC701
        .src_stage_mask(vk::PipelineStageFlags2::ALL_COMMANDS)
824bf02b6e55atagen2026-10-16 09:15 UTC702
        .src_access_mask(vk::AccessFlags2::MEMORY_WRITE)
824bf02b6e55atagen2026-10-16 09:15 UTC703
        .dst_stage_mask(vk::PipelineStageFlags2::ALL_COMMANDS)
824bf02b6e55atagen2026-10-16 09:15 UTC704
        .dst_access_mask(vk::AccessFlags2::MEMORY_READ | vk::AccessFlags2::MEMORY_WRITE)
824bf02b6e55atagen2026-10-16 09:15 UTC705
        .old_layout(old)
824bf02b6e55atagen2026-10-16 09:15 UTC706
        .new_layout(new)
7de49c2aa70batagen2026-10-16 09:27 UTC707
        .src_queue_family_index(src_family)
7de49c2aa70batagen2026-10-16 09:27 UTC708
        .dst_queue_family_index(dst_family)
824bf02b6e55atagen2026-10-16 09:15 UTC709
        .image(image)
824bf02b6e55atagen2026-10-16 09:15 UTC710
        .subresource_range(color_range())];
824bf02b6e55atagen2026-10-16 09:15 UTC711
    unsafe {
824bf02b6e55atagen2026-10-16 09:15 UTC712
        d.cmd_pipeline_barrier2(
824bf02b6e55atagen2026-10-16 09:15 UTC713
            cmd,
824bf02b6e55atagen2026-10-16 09:15 UTC714
            &vk::DependencyInfo::default().image_memory_barriers(&b),
824bf02b6e55atagen2026-10-16 09:15 UTC715
        )
824bf02b6e55atagen2026-10-16 09:15 UTC716
    };
824bf02b6e55atagen2026-10-16 09:15 UTC717
}
824bf02b6e55atagen2026-10-16 09:15 UTC718
7de49c2aa70batagen2026-10-16 09:27 UTC719
/// Moves an image into `layout` for use on this queue. Dmabuf images come
7de49c2aa70batagen2026-10-16 09:27 UTC720
/// from the foreign queue family in the general layout, others continue from
7de49c2aa70batagen2026-10-16 09:27 UTC721
/// their tracked layout.
7de49c2aa70batagen2026-10-16 09:27 UTC722
unsafe fn acquire(
7de49c2aa70batagen2026-10-16 09:27 UTC723
    d: &ash::Device,
7de49c2aa70batagen2026-10-16 09:27 UTC724
    cmd: vk::CommandBuffer,
7de49c2aa70batagen2026-10-16 09:27 UTC725
    family: u32,
7de49c2aa70batagen2026-10-16 09:27 UTC726
    image: &ImageInner,
7de49c2aa70batagen2026-10-16 09:27 UTC727
    layout: vk::ImageLayout,
7de49c2aa70batagen2026-10-16 09:27 UTC728
) {
7de49c2aa70batagen2026-10-16 09:27 UTC729
    if image.external {
7de49c2aa70batagen2026-10-16 09:27 UTC730
        unsafe {
7de49c2aa70batagen2026-10-16 09:27 UTC731
            barrier(
7de49c2aa70batagen2026-10-16 09:27 UTC732
                d,
7de49c2aa70batagen2026-10-16 09:27 UTC733
                cmd,
7de49c2aa70batagen2026-10-16 09:27 UTC734
                image.image,
7de49c2aa70batagen2026-10-16 09:27 UTC735
                vk::ImageLayout::GENERAL,
7de49c2aa70batagen2026-10-16 09:27 UTC736
                layout,
7de49c2aa70batagen2026-10-16 09:27 UTC737
                vk::QUEUE_FAMILY_FOREIGN_EXT,
7de49c2aa70batagen2026-10-16 09:27 UTC738
                family,
7de49c2aa70batagen2026-10-16 09:27 UTC739
            )
7de49c2aa70batagen2026-10-16 09:27 UTC740
        };
7de49c2aa70batagen2026-10-16 09:27 UTC741
    } else {
7de49c2aa70batagen2026-10-16 09:27 UTC742
        let old = image.layout();
7de49c2aa70batagen2026-10-16 09:27 UTC743
        if old != layout {
7de49c2aa70batagen2026-10-16 09:27 UTC744
            unsafe {
7de49c2aa70batagen2026-10-16 09:27 UTC745
                barrier(
7de49c2aa70batagen2026-10-16 09:27 UTC746
                    d,
7de49c2aa70batagen2026-10-16 09:27 UTC747
                    cmd,
7de49c2aa70batagen2026-10-16 09:27 UTC748
                    image.image,
7de49c2aa70batagen2026-10-16 09:27 UTC749
                    old,
7de49c2aa70batagen2026-10-16 09:27 UTC750
                    layout,
7de49c2aa70batagen2026-10-16 09:27 UTC751
                    vk::QUEUE_FAMILY_IGNORED,
7de49c2aa70batagen2026-10-16 09:27 UTC752
                    vk::QUEUE_FAMILY_IGNORED,
7de49c2aa70batagen2026-10-16 09:27 UTC753
                )
7de49c2aa70batagen2026-10-16 09:27 UTC754
            };
7de49c2aa70batagen2026-10-16 09:27 UTC755
            image.set_layout(layout);
7de49c2aa70batagen2026-10-16 09:27 UTC756
        }
7de49c2aa70batagen2026-10-16 09:27 UTC757
    }
7de49c2aa70batagen2026-10-16 09:27 UTC758
}
7de49c2aa70batagen2026-10-16 09:27 UTC759
7de49c2aa70batagen2026-10-16 09:27 UTC760
/// Hands a dmabuf image back to the foreign queue family after use.
7de49c2aa70batagen2026-10-16 09:27 UTC761
unsafe fn release(
7de49c2aa70batagen2026-10-16 09:27 UTC762
    d: &ash::Device,
7de49c2aa70batagen2026-10-16 09:27 UTC763
    cmd: vk::CommandBuffer,
7de49c2aa70batagen2026-10-16 09:27 UTC764
    family: u32,
7de49c2aa70batagen2026-10-16 09:27 UTC765
    image: &ImageInner,
7de49c2aa70batagen2026-10-16 09:27 UTC766
    layout: vk::ImageLayout,
7de49c2aa70batagen2026-10-16 09:27 UTC767
) {
7de49c2aa70batagen2026-10-16 09:27 UTC768
    if image.external {
7de49c2aa70batagen2026-10-16 09:27 UTC769
        unsafe {
7de49c2aa70batagen2026-10-16 09:27 UTC770
            barrier(
7de49c2aa70batagen2026-10-16 09:27 UTC771
                d,
7de49c2aa70batagen2026-10-16 09:27 UTC772
                cmd,
7de49c2aa70batagen2026-10-16 09:27 UTC773
                image.image,
7de49c2aa70batagen2026-10-16 09:27 UTC774
                layout,
7de49c2aa70batagen2026-10-16 09:27 UTC775
                vk::ImageLayout::GENERAL,
7de49c2aa70batagen2026-10-16 09:27 UTC776
                family,
7de49c2aa70batagen2026-10-16 09:27 UTC777
                vk::QUEUE_FAMILY_FOREIGN_EXT,
7de49c2aa70batagen2026-10-16 09:27 UTC778
            )
7de49c2aa70batagen2026-10-16 09:27 UTC779
        };
7de49c2aa70batagen2026-10-16 09:27 UTC780
    }
7de49c2aa70batagen2026-10-16 09:27 UTC781
}
7de49c2aa70batagen2026-10-16 09:27 UTC782
824bf02b6e55atagen2026-10-16 09:15 UTC783
/// Whether reading `from` as `to` needs red and blue swapped.
824bf02b6e55atagen2026-10-16 09:15 UTC784
fn needs_swizzle(from: Fourcc, to: Fourcc) -> Result<bool, Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC785
    let bgr = |f: Fourcc| match f {
824bf02b6e55atagen2026-10-16 09:15 UTC786
        Fourcc::Argb8888 | Fourcc::Xrgb8888 => Ok(true),
824bf02b6e55atagen2026-10-16 09:15 UTC787
        Fourcc::Abgr8888 | Fourcc::Xbgr8888 => Ok(false),
824bf02b6e55atagen2026-10-16 09:15 UTC788
        f => Err(Error::UnsupportedFormat(f)),
824bf02b6e55atagen2026-10-16 09:15 UTC789
    };
824bf02b6e55atagen2026-10-16 09:15 UTC790
    Ok(bgr(from)? != bgr(to)?)
824bf02b6e55atagen2026-10-16 09:15 UTC791
}
824bf02b6e55atagen2026-10-16 09:15 UTC792
824bf02b6e55atagen2026-10-16 09:15 UTC793
impl RendererSuper for VulkanRenderer {
824bf02b6e55atagen2026-10-16 09:15 UTC794
    type Error = Error;
824bf02b6e55atagen2026-10-16 09:15 UTC795
    type TextureId = VulkanTexture;
824bf02b6e55atagen2026-10-16 09:15 UTC796
    type Framebuffer<'buffer> = VulkanTarget<'buffer>;
824bf02b6e55atagen2026-10-16 09:15 UTC797
    type Frame<'frame, 'buffer>
824bf02b6e55atagen2026-10-16 09:15 UTC798
        = VulkanFrame<'frame, 'buffer>
824bf02b6e55atagen2026-10-16 09:15 UTC799
    where
824bf02b6e55atagen2026-10-16 09:15 UTC800
        'buffer: 'frame,
824bf02b6e55atagen2026-10-16 09:15 UTC801
        Self: 'frame;
824bf02b6e55atagen2026-10-16 09:15 UTC802
}
824bf02b6e55atagen2026-10-16 09:15 UTC803
824bf02b6e55atagen2026-10-16 09:15 UTC804
impl Renderer for VulkanRenderer {
824bf02b6e55atagen2026-10-16 09:15 UTC805
    fn context_id(&self) -> ContextId<VulkanTexture> {
824bf02b6e55atagen2026-10-16 09:15 UTC806
        self.context.clone()
824bf02b6e55atagen2026-10-16 09:15 UTC807
    }
824bf02b6e55atagen2026-10-16 09:15 UTC808
824bf02b6e55atagen2026-10-16 09:15 UTC809
    fn downscale_filter(&mut self, filter: TextureFilter) -> Result<(), Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC810
        self.min_filter = filter;
824bf02b6e55atagen2026-10-16 09:15 UTC811
        Ok(())
824bf02b6e55atagen2026-10-16 09:15 UTC812
    }
824bf02b6e55atagen2026-10-16 09:15 UTC813
824bf02b6e55atagen2026-10-16 09:15 UTC814
    fn upscale_filter(&mut self, filter: TextureFilter) -> Result<(), Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC815
        self.mag_filter = filter;
824bf02b6e55atagen2026-10-16 09:15 UTC816
        Ok(())
824bf02b6e55atagen2026-10-16 09:15 UTC817
    }
824bf02b6e55atagen2026-10-16 09:15 UTC818
824bf02b6e55atagen2026-10-16 09:15 UTC819
    fn set_debug_flags(&mut self, flags: DebugFlags) {
824bf02b6e55atagen2026-10-16 09:15 UTC820
        self.debug = flags;
824bf02b6e55atagen2026-10-16 09:15 UTC821
    }
824bf02b6e55atagen2026-10-16 09:15 UTC822
824bf02b6e55atagen2026-10-16 09:15 UTC823
    fn debug_flags(&self) -> DebugFlags {
824bf02b6e55atagen2026-10-16 09:15 UTC824
        self.debug
824bf02b6e55atagen2026-10-16 09:15 UTC825
    }
824bf02b6e55atagen2026-10-16 09:15 UTC826
824bf02b6e55atagen2026-10-16 09:15 UTC827
    fn render<'frame, 'buffer>(
824bf02b6e55atagen2026-10-16 09:15 UTC828
        &'frame mut self,
824bf02b6e55atagen2026-10-16 09:15 UTC829
        framebuffer: &'frame mut VulkanTarget<'buffer>,
824bf02b6e55atagen2026-10-16 09:15 UTC830
        output_size: Size<i32, Physical>,
824bf02b6e55atagen2026-10-16 09:15 UTC831
        dst_transform: Transform,
824bf02b6e55atagen2026-10-16 09:15 UTC832
    ) -> Result<VulkanFrame<'frame, 'buffer>, Error>
824bf02b6e55atagen2026-10-16 09:15 UTC833
    where
824bf02b6e55atagen2026-10-16 09:15 UTC834
        'buffer: 'frame,
824bf02b6e55atagen2026-10-16 09:15 UTC835
    {
7de49c2aa70batagen2026-10-16 09:27 UTC836
        self.own(&framebuffer.0)?;
824bf02b6e55atagen2026-10-16 09:15 UTC837
        self.reap();
824bf02b6e55atagen2026-10-16 09:15 UTC838
        Ok(VulkanFrame::new(
824bf02b6e55atagen2026-10-16 09:15 UTC839
            self,
824bf02b6e55atagen2026-10-16 09:15 UTC840
            framebuffer,
824bf02b6e55atagen2026-10-16 09:15 UTC841
            output_size,
824bf02b6e55atagen2026-10-16 09:15 UTC842
            dst_transform,
824bf02b6e55atagen2026-10-16 09:15 UTC843
        ))
824bf02b6e55atagen2026-10-16 09:15 UTC844
    }
824bf02b6e55atagen2026-10-16 09:15 UTC845
824bf02b6e55atagen2026-10-16 09:15 UTC846
    fn wait(&mut self, sync: &SyncPoint) -> Result<(), Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC847
        sync.wait().map_err(|_| Error::Interrupted)
824bf02b6e55atagen2026-10-16 09:15 UTC848
    }
824bf02b6e55atagen2026-10-16 09:15 UTC849
824bf02b6e55atagen2026-10-16 09:15 UTC850
    fn cleanup_texture_cache(&mut self) -> Result<(), Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC851
        self.reap();
824bf02b6e55atagen2026-10-16 09:15 UTC852
        Ok(())
824bf02b6e55atagen2026-10-16 09:15 UTC853
    }
7de49c2aa70batagen2026-10-16 09:27 UTC854
7de49c2aa70batagen2026-10-16 09:27 UTC855
    fn invalidate_caches(&mut self) -> Result<(), Error> {
7de49c2aa70batagen2026-10-16 09:27 UTC856
        self.reap();
7de49c2aa70batagen2026-10-16 09:27 UTC857
        self.dmabuf_textures.clear();
7de49c2aa70batagen2026-10-16 09:27 UTC858
        self.dmabuf_targets.clear();
7de49c2aa70batagen2026-10-16 09:27 UTC859
        Ok(())
7de49c2aa70batagen2026-10-16 09:27 UTC860
    }
824bf02b6e55atagen2026-10-16 09:15 UTC861
}
824bf02b6e55atagen2026-10-16 09:15 UTC862
824bf02b6e55atagen2026-10-16 09:15 UTC863
impl Bind<VulkanImage> for VulkanRenderer {
824bf02b6e55atagen2026-10-16 09:15 UTC864
    fn bind<'a>(&mut self, target: &'a mut VulkanImage) -> Result<VulkanTarget<'a>, Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC865
        self.own(&target.0)?;
7de49c2aa70batagen2026-10-16 09:27 UTC866
        Ok(VulkanTarget(target.0.clone(), PhantomData))
7de49c2aa70batagen2026-10-16 09:27 UTC867
    }
7de49c2aa70batagen2026-10-16 09:27 UTC868
}
7de49c2aa70batagen2026-10-16 09:27 UTC869
7de49c2aa70batagen2026-10-16 09:27 UTC870
impl Bind<Dmabuf> for VulkanRenderer {
30aece3a63ceatagen2026-10-16 13:48 UTC871
    #[profiling::function]
7de49c2aa70batagen2026-10-16 09:27 UTC872
    fn bind<'a>(&mut self, target: &'a mut Dmabuf) -> Result<VulkanTarget<'a>, Error> {
7de49c2aa70batagen2026-10-16 09:27 UTC873
        let key = target.weak();
7de49c2aa70batagen2026-10-16 09:27 UTC874
        let image = match self.dmabuf_targets.get(&key) {
7de49c2aa70batagen2026-10-16 09:27 UTC875
            Some(image) => image.clone(),
7de49c2aa70batagen2026-10-16 09:27 UTC876
            None => {
7de49c2aa70batagen2026-10-16 09:27 UTC877
                let image = dmabuf::import(&self.shared, &self.caps, target, RENDER_USAGE)?;
7de49c2aa70batagen2026-10-16 09:27 UTC878
                self.dmabuf_targets.insert(key, image.clone());
7de49c2aa70batagen2026-10-16 09:27 UTC879
                image
7de49c2aa70batagen2026-10-16 09:27 UTC880
            }
7de49c2aa70batagen2026-10-16 09:27 UTC881
        };
7de49c2aa70batagen2026-10-16 09:27 UTC882
        Ok(VulkanTarget(image, PhantomData))
7de49c2aa70batagen2026-10-16 09:27 UTC883
    }
7de49c2aa70batagen2026-10-16 09:27 UTC884
7de49c2aa70batagen2026-10-16 09:27 UTC885
    fn supported_formats(&self) -> Option<FormatSet> {
7de49c2aa70batagen2026-10-16 09:27 UTC886
        Some(self.caps.render.clone())
824bf02b6e55atagen2026-10-16 09:15 UTC887
    }
824bf02b6e55atagen2026-10-16 09:15 UTC888
}
824bf02b6e55atagen2026-10-16 09:15 UTC889
824bf02b6e55atagen2026-10-16 09:15 UTC890
impl Offscreen<VulkanImage> for VulkanRenderer {
824bf02b6e55atagen2026-10-16 09:15 UTC891
    fn create_buffer(
824bf02b6e55atagen2026-10-16 09:15 UTC892
        &mut self,
824bf02b6e55atagen2026-10-16 09:15 UTC893
        format: Fourcc,
824bf02b6e55atagen2026-10-16 09:15 UTC894
        size: Size<i32, Buffer>,
824bf02b6e55atagen2026-10-16 09:15 UTC895
    ) -> Result<VulkanImage, Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC896
        if size.w <= 0 || size.h <= 0 {
824bf02b6e55atagen2026-10-16 09:15 UTC897
            return Err(Error::InvalidSize(size.w, size.h));
824bf02b6e55atagen2026-10-16 09:15 UTC898
        }
824bf02b6e55atagen2026-10-16 09:15 UTC899
        let usage = vk::ImageUsageFlags::COLOR_ATTACHMENT
824bf02b6e55atagen2026-10-16 09:15 UTC900
            | vk::ImageUsageFlags::SAMPLED
824bf02b6e55atagen2026-10-16 09:15 UTC901
            | vk::ImageUsageFlags::TRANSFER_SRC
824bf02b6e55atagen2026-10-16 09:15 UTC902
            | vk::ImageUsageFlags::TRANSFER_DST;
824bf02b6e55atagen2026-10-16 09:15 UTC903
        Ok(VulkanImage(ImageInner::create(
824bf02b6e55atagen2026-10-16 09:15 UTC904
            &self.shared,
824bf02b6e55atagen2026-10-16 09:15 UTC905
            format,
824bf02b6e55atagen2026-10-16 09:15 UTC906
            size.w as u32,
824bf02b6e55atagen2026-10-16 09:15 UTC907
            size.h as u32,
824bf02b6e55atagen2026-10-16 09:15 UTC908
            usage,
824bf02b6e55atagen2026-10-16 09:15 UTC909
        )?))
824bf02b6e55atagen2026-10-16 09:15 UTC910
    }
824bf02b6e55atagen2026-10-16 09:15 UTC911
}
824bf02b6e55atagen2026-10-16 09:15 UTC912
824bf02b6e55atagen2026-10-16 09:15 UTC913
impl ImportMem for VulkanRenderer {
824bf02b6e55atagen2026-10-16 09:15 UTC914
    fn import_memory(
824bf02b6e55atagen2026-10-16 09:15 UTC915
        &mut self,
824bf02b6e55atagen2026-10-16 09:15 UTC916
        data: &[u8],
824bf02b6e55atagen2026-10-16 09:15 UTC917
        format: Fourcc,
824bf02b6e55atagen2026-10-16 09:15 UTC918
        size: Size<i32, Buffer>,
824bf02b6e55atagen2026-10-16 09:15 UTC919
        flipped: bool,
824bf02b6e55atagen2026-10-16 09:15 UTC920
    ) -> Result<VulkanTexture, Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC921
        if size.w <= 0 || size.h <= 0 {
824bf02b6e55atagen2026-10-16 09:15 UTC922
            return Err(Error::InvalidSize(size.w, size.h));
824bf02b6e55atagen2026-10-16 09:15 UTC923
        }
824bf02b6e55atagen2026-10-16 09:15 UTC924
        let usage = vk::ImageUsageFlags::SAMPLED
824bf02b6e55atagen2026-10-16 09:15 UTC925
            | vk::ImageUsageFlags::TRANSFER_DST
824bf02b6e55atagen2026-10-16 09:15 UTC926
            | vk::ImageUsageFlags::TRANSFER_SRC;
824bf02b6e55atagen2026-10-16 09:15 UTC927
        let image = ImageInner::create(&self.shared, format, size.w as u32, size.h as u32, usage)?;
824bf02b6e55atagen2026-10-16 09:15 UTC928
        self.upload(&image, data, Rectangle::from_size(size), flipped)?;
824bf02b6e55atagen2026-10-16 09:15 UTC929
        Ok(VulkanTexture(image))
824bf02b6e55atagen2026-10-16 09:15 UTC930
    }
824bf02b6e55atagen2026-10-16 09:15 UTC931
824bf02b6e55atagen2026-10-16 09:15 UTC932
    fn update_memory(
824bf02b6e55atagen2026-10-16 09:15 UTC933
        &mut self,
824bf02b6e55atagen2026-10-16 09:15 UTC934
        texture: &VulkanTexture,
824bf02b6e55atagen2026-10-16 09:15 UTC935
        data: &[u8],
824bf02b6e55atagen2026-10-16 09:15 UTC936
        region: Rectangle<i32, Buffer>,
824bf02b6e55atagen2026-10-16 09:15 UTC937
    ) -> Result<(), Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC938
        self.own(&texture.0)?;
824bf02b6e55atagen2026-10-16 09:15 UTC939
        let Some(region) = region.intersection(Rectangle::from_size(texture.size())) else {
824bf02b6e55atagen2026-10-16 09:15 UTC940
            return Ok(());
824bf02b6e55atagen2026-10-16 09:15 UTC941
        };
824bf02b6e55atagen2026-10-16 09:15 UTC942
        self.upload(&texture.0, data, region, false)
824bf02b6e55atagen2026-10-16 09:15 UTC943
    }
824bf02b6e55atagen2026-10-16 09:15 UTC944
824bf02b6e55atagen2026-10-16 09:15 UTC945
    fn mem_formats(&self) -> Box<dyn Iterator<Item = Fourcc>> {
824bf02b6e55atagen2026-10-16 09:15 UTC946
        Box::new(SUPPORTED.into_iter())
824bf02b6e55atagen2026-10-16 09:15 UTC947
    }
824bf02b6e55atagen2026-10-16 09:15 UTC948
}
824bf02b6e55atagen2026-10-16 09:15 UTC949
7de49c2aa70batagen2026-10-16 09:27 UTC950
impl ImportDma for VulkanRenderer {
7de49c2aa70batagen2026-10-16 09:27 UTC951
    fn dmabuf_formats(&self) -> FormatSet {
7de49c2aa70batagen2026-10-16 09:27 UTC952
        self.caps.sample.clone()
7de49c2aa70batagen2026-10-16 09:27 UTC953
    }
7de49c2aa70batagen2026-10-16 09:27 UTC954
30aece3a63ceatagen2026-10-16 13:48 UTC955
    #[profiling::function]
7de49c2aa70batagen2026-10-16 09:27 UTC956
    fn import_dmabuf(
7de49c2aa70batagen2026-10-16 09:27 UTC957
        &mut self,
7de49c2aa70batagen2026-10-16 09:27 UTC958
        buffer: &Dmabuf,
7de49c2aa70batagen2026-10-16 09:27 UTC959
        _damage: Option<&[Rectangle<i32, Buffer>]>,
7de49c2aa70batagen2026-10-16 09:27 UTC960
    ) -> Result<VulkanTexture, Error> {
7de49c2aa70batagen2026-10-16 09:27 UTC961
        let key = buffer.weak();
7de49c2aa70batagen2026-10-16 09:27 UTC962
        if let Some(t) = self.dmabuf_textures.get(&key) {
7de49c2aa70batagen2026-10-16 09:27 UTC963
            return Ok(t.clone());
7de49c2aa70batagen2026-10-16 09:27 UTC964
        }
7de49c2aa70batagen2026-10-16 09:27 UTC965
        let texture = VulkanTexture(dmabuf::import(
7de49c2aa70batagen2026-10-16 09:27 UTC966
            &self.shared,
7de49c2aa70batagen2026-10-16 09:27 UTC967
            &self.caps,
7de49c2aa70batagen2026-10-16 09:27 UTC968
            buffer,
7de49c2aa70batagen2026-10-16 09:27 UTC969
            SAMPLE_USAGE,
7de49c2aa70batagen2026-10-16 09:27 UTC970
        )?);
7de49c2aa70batagen2026-10-16 09:27 UTC971
        self.dmabuf_textures.insert(key, texture.clone());
7de49c2aa70batagen2026-10-16 09:27 UTC972
        Ok(texture)
7de49c2aa70batagen2026-10-16 09:27 UTC973
    }
7de49c2aa70batagen2026-10-16 09:27 UTC974
}
7de49c2aa70batagen2026-10-16 09:27 UTC975
7de49c2aa70batagen2026-10-16 09:27 UTC976
impl ImportDmaWl for VulkanRenderer {}
7de49c2aa70batagen2026-10-16 09:27 UTC977
8956d017e879atagen2026-10-16 22:50 UTC978
/// Imports dmabufs on another thread. The textures it makes belong to the
8956d017e879atagen2026-10-16 22:50 UTC979
/// renderer it came from, which takes them back with `adopt_dmabuf`.
8956d017e879atagen2026-10-16 22:50 UTC980
#[derive(Clone)]
8956d017e879atagen2026-10-16 22:50 UTC981
pub struct DmabufImporter {
8956d017e879atagen2026-10-16 22:50 UTC982
    shared: Arc<Shared>,
8956d017e879atagen2026-10-16 22:50 UTC983
    caps: Arc<DmabufCaps>,
8956d017e879atagen2026-10-16 22:50 UTC984
}
8956d017e879atagen2026-10-16 22:50 UTC985
8956d017e879atagen2026-10-16 22:50 UTC986
impl DmabufImporter {
8956d017e879atagen2026-10-16 22:50 UTC987
    pub fn import(&self, buffer: &Dmabuf) -> Result<VulkanTexture, Error> {
8956d017e879atagen2026-10-16 22:50 UTC988
        dmabuf::import(&self.shared, &self.caps, buffer, SAMPLE_USAGE).map(VulkanTexture)
8956d017e879atagen2026-10-16 22:50 UTC989
    }
8956d017e879atagen2026-10-16 22:50 UTC990
}
8956d017e879atagen2026-10-16 22:50 UTC991
8956d017e879atagen2026-10-16 22:50 UTC992
impl VulkanRenderer {
8956d017e879atagen2026-10-16 22:50 UTC993
    pub fn dmabuf_importer(&self) -> DmabufImporter {
8956d017e879atagen2026-10-16 22:50 UTC994
        DmabufImporter {
8956d017e879atagen2026-10-16 22:50 UTC995
            shared: self.shared.clone(),
8956d017e879atagen2026-10-16 22:50 UTC996
            caps: self.caps.clone(),
8956d017e879atagen2026-10-16 22:50 UTC997
        }
8956d017e879atagen2026-10-16 22:50 UTC998
    }
8956d017e879atagen2026-10-16 22:50 UTC999
8956d017e879atagen2026-10-16 22:50 UTC1000
    pub fn has_dmabuf(&self, buffer: &Dmabuf) -> bool {
8956d017e879atagen2026-10-16 22:50 UTC1001
        self.dmabuf_textures.contains_key(&buffer.weak())
8956d017e879atagen2026-10-16 22:50 UTC1002
    }
8956d017e879atagen2026-10-16 22:50 UTC1003
8956d017e879atagen2026-10-16 22:50 UTC1004
    pub fn adopt_dmabuf(&mut self, buffer: &Dmabuf, texture: VulkanTexture) -> Result<(), Error> {
8956d017e879atagen2026-10-16 22:50 UTC1005
        self.own(&texture.0)?;
8956d017e879atagen2026-10-16 22:50 UTC1006
        self.dmabuf_textures.insert(buffer.weak(), texture);
8956d017e879atagen2026-10-16 22:50 UTC1007
        Ok(())
8956d017e879atagen2026-10-16 22:50 UTC1008
    }
8956d017e879atagen2026-10-16 22:50 UTC1009
}
8956d017e879atagen2026-10-16 22:50 UTC1010
824bf02b6e55atagen2026-10-16 09:15 UTC1011
impl ExportMem for VulkanRenderer {
824bf02b6e55atagen2026-10-16 09:15 UTC1012
    type TextureMapping = VulkanMapping;
824bf02b6e55atagen2026-10-16 09:15 UTC1013
824bf02b6e55atagen2026-10-16 09:15 UTC1014
    fn copy_framebuffer(
824bf02b6e55atagen2026-10-16 09:15 UTC1015
        &mut self,
824bf02b6e55atagen2026-10-16 09:15 UTC1016
        target: &VulkanTarget<'_>,
824bf02b6e55atagen2026-10-16 09:15 UTC1017
        region: Rectangle<i32, Buffer>,
824bf02b6e55atagen2026-10-16 09:15 UTC1018
        format: Fourcc,
824bf02b6e55atagen2026-10-16 09:15 UTC1019
    ) -> Result<VulkanMapping, Error> {
7de49c2aa70batagen2026-10-16 09:27 UTC1020
        self.own(&target.0)?;
7de49c2aa70batagen2026-10-16 09:27 UTC1021
        let image = target.0.clone();
824bf02b6e55atagen2026-10-16 09:15 UTC1022
        self.read_back(&image, region, format)
824bf02b6e55atagen2026-10-16 09:15 UTC1023
    }
824bf02b6e55atagen2026-10-16 09:15 UTC1024
824bf02b6e55atagen2026-10-16 09:15 UTC1025
    fn copy_texture(
824bf02b6e55atagen2026-10-16 09:15 UTC1026
        &mut self,
824bf02b6e55atagen2026-10-16 09:15 UTC1027
        texture: &VulkanTexture,
824bf02b6e55atagen2026-10-16 09:15 UTC1028
        region: Rectangle<i32, Buffer>,
824bf02b6e55atagen2026-10-16 09:15 UTC1029
        format: Fourcc,
824bf02b6e55atagen2026-10-16 09:15 UTC1030
    ) -> Result<VulkanMapping, Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC1031
        self.own(&texture.0)?;
824bf02b6e55atagen2026-10-16 09:15 UTC1032
        self.read_back(&texture.0, region, format)
824bf02b6e55atagen2026-10-16 09:15 UTC1033
    }
824bf02b6e55atagen2026-10-16 09:15 UTC1034
7de49c2aa70batagen2026-10-16 09:27 UTC1035
    fn can_read_texture(&mut self, texture: &VulkanTexture) -> Result<bool, Error> {
7de49c2aa70batagen2026-10-16 09:27 UTC1036
        Ok(texture.0.external || texture.0.layout() != vk::ImageLayout::UNDEFINED)
824bf02b6e55atagen2026-10-16 09:15 UTC1037
    }
824bf02b6e55atagen2026-10-16 09:15 UTC1038
824bf02b6e55atagen2026-10-16 09:15 UTC1039
    fn map_texture<'a>(&mut self, mapping: &'a VulkanMapping) -> Result<&'a [u8], Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC1040
        Ok(&mapping.data)
824bf02b6e55atagen2026-10-16 09:15 UTC1041
    }
824bf02b6e55atagen2026-10-16 09:15 UTC1042
}
d4a64ce87164atagen2026-10-16 09:34 UTC1043
d4a64ce87164atagen2026-10-16 09:34 UTC1044
impl ImportMemWl for VulkanRenderer {
48af562d968batagen2026-10-16 12:39 UTC1045
    /// Keeps one texture per surface and uploads only the damaged rows into
48af562d968batagen2026-10-16 12:39 UTC1046
    /// it, straight from the client's shm pool.
d4a64ce87164atagen2026-10-16 09:34 UTC1047
    fn import_shm_buffer(
d4a64ce87164atagen2026-10-16 09:34 UTC1048
        &mut self,
d4a64ce87164atagen2026-10-16 09:34 UTC1049
        buffer: &WlBuffer,
48af562d968batagen2026-10-16 12:39 UTC1050
        surface: Option<&SurfaceData>,
48af562d968batagen2026-10-16 12:39 UTC1051
        damage: &[Rectangle<i32, Buffer>],
d4a64ce87164atagen2026-10-16 09:34 UTC1052
    ) -> Result<VulkanTexture, Error> {
48af562d968batagen2026-10-16 12:39 UTC1053
        let cache = surface.map(|s| {
48af562d968batagen2026-10-16 12:39 UTC1054
            s.data_map
48af562d968batagen2026-10-16 12:39 UTC1055
                .insert_if_missing_threadsafe(|| ShmCache(Mutex::new(None)));
48af562d968batagen2026-10-16 12:39 UTC1056
            s.data_map.get::<ShmCache>().expect("just inserted")
48af562d968batagen2026-10-16 12:39 UTC1057
        });
48af562d968batagen2026-10-16 12:39 UTC1058
        with_buffer_contents(buffer, |ptr, len, data| {
d4a64ce87164atagen2026-10-16 09:34 UTC1059
            let fourcc = shm_format_to_fourcc(data.format).ok_or(Error::ShmAccess)?;
d4a64ce87164atagen2026-10-16 09:34 UTC1060
            let (w, h, stride, offset) = (
d4a64ce87164atagen2026-10-16 09:34 UTC1061
                data.width as usize,
d4a64ce87164atagen2026-10-16 09:34 UTC1062
                data.height as usize,
d4a64ce87164atagen2026-10-16 09:34 UTC1063
                data.stride as usize,
d4a64ce87164atagen2026-10-16 09:34 UTC1064
                data.offset as usize,
d4a64ce87164atagen2026-10-16 09:34 UTC1065
            );
48af562d968batagen2026-10-16 12:39 UTC1066
            let line = w * BYTES_PER_PIXEL;
48af562d968batagen2026-10-16 12:39 UTC1067
            if w == 0 || h == 0 || stride < line || offset + stride * (h - 1) + line > len {
d4a64ce87164atagen2026-10-16 09:34 UTC1068
                return Err(Error::ShmAccess);
d4a64ce87164atagen2026-10-16 09:34 UTC1069
            }
48af562d968batagen2026-10-16 12:39 UTC1070
            let size = Size::from((data.width, data.height));
48af562d968batagen2026-10-16 12:39 UTC1071
            let full = Rectangle::from_size(size);
48af562d968batagen2026-10-16 12:39 UTC1072
            let reused = cache
48af562d968batagen2026-10-16 12:39 UTC1073
                .and_then(|c| c.0.lock().unwrap_or_else(|e| e.into_inner()).clone())
48af562d968batagen2026-10-16 12:39 UTC1074
                .filter(|t| {
48af562d968batagen2026-10-16 12:39 UTC1075
                    t.0.fourcc == fourcc
48af562d968batagen2026-10-16 12:39 UTC1076
                        && t.size() == size
48af562d968batagen2026-10-16 12:39 UTC1077
                        && Arc::ptr_eq(&t.0.shared, &self.shared)
48af562d968batagen2026-10-16 12:39 UTC1078
                });
48af562d968batagen2026-10-16 12:39 UTC1079
            let (texture, region) = match reused {
48af562d968batagen2026-10-16 12:39 UTC1080
                Some(t) => {
48af562d968batagen2026-10-16 12:39 UTC1081
                    let dirty = damage
48af562d968batagen2026-10-16 12:39 UTC1082
                        .iter()
48af562d968batagen2026-10-16 12:39 UTC1083
                        .filter_map(|d| d.intersection(full))
48af562d968batagen2026-10-16 12:39 UTC1084
                        .reduce(|a, b| a.merge(b));
48af562d968batagen2026-10-16 12:39 UTC1085
                    (t, if damage.is_empty() { Some(full) } else { dirty })
48af562d968batagen2026-10-16 12:39 UTC1086
                }
48af562d968batagen2026-10-16 12:39 UTC1087
                None => {
48af562d968batagen2026-10-16 12:39 UTC1088
                    let usage = vk::ImageUsageFlags::SAMPLED
48af562d968batagen2026-10-16 12:39 UTC1089
                        | vk::ImageUsageFlags::TRANSFER_DST
48af562d968batagen2026-10-16 12:39 UTC1090
                        | vk::ImageUsageFlags::TRANSFER_SRC;
48af562d968batagen2026-10-16 12:39 UTC1091
                    let image =
48af562d968batagen2026-10-16 12:39 UTC1092
                        ImageInner::create(&self.shared, fourcc, w as u32, h as u32, usage)?;
48af562d968batagen2026-10-16 12:39 UTC1093
                    (VulkanTexture(image), Some(full))
48af562d968batagen2026-10-16 12:39 UTC1094
                }
48af562d968batagen2026-10-16 12:39 UTC1095
            };
48af562d968batagen2026-10-16 12:39 UTC1096
            if let Some(region) = region {
48af562d968batagen2026-10-16 12:39 UTC1097
                let x = region.loc.x as usize * BYTES_PER_PIXEL;
48af562d968batagen2026-10-16 12:39 UTC1098
                let rw = region.size.w as usize * BYTES_PER_PIXEL;
48af562d968batagen2026-10-16 12:39 UTC1099
                self.upload_with(&texture.0, region, |y| unsafe {
48af562d968batagen2026-10-16 12:39 UTC1100
                    std::slice::from_raw_parts(ptr.add(offset + y * stride + x), rw)
48af562d968batagen2026-10-16 12:39 UTC1101
                })?;
d4a64ce87164atagen2026-10-16 09:34 UTC1102
            }
48af562d968batagen2026-10-16 12:39 UTC1103
            if let Some(c) = cache {
48af562d968batagen2026-10-16 12:39 UTC1104
                *c.0.lock().unwrap_or_else(|e| e.into_inner()) = Some(texture.clone());
48af562d968batagen2026-10-16 12:39 UTC1105
            }
48af562d968batagen2026-10-16 12:39 UTC1106
            Ok(texture)
d4a64ce87164atagen2026-10-16 09:34 UTC1107
        })
48af562d968batagen2026-10-16 12:39 UTC1108
        .map_err(|_| Error::ShmAccess)?
d4a64ce87164atagen2026-10-16 09:34 UTC1109
    }
d4a64ce87164atagen2026-10-16 09:34 UTC1110
}
48af562d968batagen2026-10-16 12:39 UTC1111
48af562d968batagen2026-10-16 12:39 UTC1112
/// The texture last imported for a surface's shm buffers.
48af562d968batagen2026-10-16 12:39 UTC1113
struct ShmCache(Mutex<Option<VulkanTexture>>);