atagen

monolith

public
Star0
Watch0
824bf02b6e554e9c0b86328878fc8eb8caa6926d
1
ssh://brewery@pls.lobotomise.me:33/atagen/monolith.git
crates/render-vk/src/renderer.rsRust698 lines22.6 KB
1
use crate::Error;
2
use crate::device::Shared;
3
use crate::format::{BYTES_PER_PIXEL, SUPPORTED};
4
use crate::frame::{Op, VulkanFrame};
5
use crate::image::{
6
    ImageInner, Staging, VulkanImage, VulkanMapping, VulkanTarget, VulkanTexture, color_range,
7
};
8
use crate::pipeline::Pipelines;
9
use crate::sync::{FenceInner, VkFence};
10
use ash::vk;
11
use gpu_allocator::MemoryLocation;
12
use smithay::backend::allocator::Fourcc;
13
use smithay::backend::renderer::sync::SyncPoint;
14
use smithay::backend::renderer::{
15
    Bind, ContextId, DebugFlags, ExportMem, ImportMem, Offscreen, Renderer, RendererSuper, Texture,
16
    TextureFilter,
17
};
18
use smithay::utils::{Buffer, Physical, Rectangle, Size, Transform};
19
use std::fmt;
20
use std::sync::Arc;
21
22
struct Pending {
23
    fence: Arc<FenceInner>,
24
    cmd: vk::CommandBuffer,
25
    _keep: Vec<VulkanTexture>,
26
}
27
28
pub struct VulkanRenderer {
29
    pending: Vec<Pending>,
30
    pipelines: Pipelines,
31
    pool: vk::CommandPool,
32
    samplers: [vk::Sampler; 4],
33
    min_filter: TextureFilter,
34
    mag_filter: TextureFilter,
35
    debug: DebugFlags,
36
    context: ContextId<VulkanTexture>,
37
    shared: Arc<Shared>,
38
}
39
40
impl fmt::Debug for VulkanRenderer {
41
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42
        f.debug_struct("VulkanRenderer")
43
            .field("device", &self.shared.device.name)
44
            .finish()
45
    }
46
}
47
48
impl VulkanRenderer {
49
    pub fn new() -> Result<Self, Error> {
50
        let shared = Arc::new(Shared::new()?);
51
        let d = &shared.device.device;
52
        let pool = unsafe {
53
            d.create_command_pool(
54
                &vk::CommandPoolCreateInfo::default()
55
                    .queue_family_index(shared.device.queue_family)
56
                    .flags(vk::CommandPoolCreateFlags::TRANSIENT),
57
                None,
58
            )?
59
        };
60
        let filter = |f: TextureFilter| match f {
61
            TextureFilter::Linear => vk::Filter::LINEAR,
62
            TextureFilter::Nearest => vk::Filter::NEAREST,
63
        };
64
        let mut samplers = [vk::Sampler::null(); 4];
65
        for (i, s) in samplers.iter_mut().enumerate() {
66
            let (min, mag) = (sampler_filter(i >> 1), sampler_filter(i & 1));
67
            *s = unsafe {
68
                d.create_sampler(
69
                    &vk::SamplerCreateInfo::default()
70
                        .min_filter(filter(min))
71
                        .mag_filter(filter(mag))
72
                        .address_mode_u(vk::SamplerAddressMode::CLAMP_TO_EDGE)
73
                        .address_mode_v(vk::SamplerAddressMode::CLAMP_TO_EDGE)
74
                        .address_mode_w(vk::SamplerAddressMode::CLAMP_TO_EDGE),
75
                    None,
76
                )?
77
            };
78
        }
79
        Ok(Self {
80
            pending: Vec::new(),
81
            pipelines: Pipelines::new(&shared)?,
82
            pool,
83
            samplers,
84
            min_filter: TextureFilter::Linear,
85
            mag_filter: TextureFilter::Linear,
86
            debug: DebugFlags::empty(),
87
            context: ContextId::new(),
88
            shared,
89
        })
90
    }
91
92
    /// Name of the physical device in use.
93
    pub fn device_name(&self) -> &str {
94
        &self.shared.device.name
95
    }
96
97
    pub(crate) fn shared(&self) -> &Arc<Shared> {
98
        &self.shared
99
    }
100
101
    pub(crate) fn context_id_ref(&self) -> &ContextId<VulkanTexture> {
102
        &self.context
103
    }
104
105
    fn sampler(&self) -> vk::Sampler {
106
        let idx = |f: TextureFilter| usize::from(f == TextureFilter::Nearest);
107
        self.samplers[(idx(self.min_filter) << 1) | idx(self.mag_filter)]
108
    }
109
110
    fn reap(&mut self) {
111
        let d = &self.shared.device.device;
112
        let pool = self.pool;
113
        self.pending.retain(|p| {
114
            if !p.fence.signaled() {
115
                return true;
116
            }
117
            unsafe { d.free_command_buffers(pool, &[p.cmd]) };
118
            false
119
        });
120
    }
121
122
    fn begin(&self) -> Result<vk::CommandBuffer, Error> {
123
        let d = &self.shared.device.device;
124
        let cmd = unsafe {
125
            d.allocate_command_buffers(
126
                &vk::CommandBufferAllocateInfo::default()
127
                    .command_pool(self.pool)
128
                    .level(vk::CommandBufferLevel::PRIMARY)
129
                    .command_buffer_count(1),
130
            )?[0]
131
        };
132
        unsafe {
133
            d.begin_command_buffer(
134
                cmd,
135
                &vk::CommandBufferBeginInfo::default()
136
                    .flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT),
137
            )?
138
        };
139
        Ok(cmd)
140
    }
141
142
    fn end_and_submit(&self, cmd: vk::CommandBuffer) -> Result<Arc<FenceInner>, Error> {
143
        let d = &self.shared.device.device;
144
        unsafe { d.end_command_buffer(cmd)? };
145
        let fence = FenceInner::new(&self.shared)?;
146
        let cmds = [vk::CommandBufferSubmitInfo::default().command_buffer(cmd)];
147
        let submit = vk::SubmitInfo2::default().command_buffer_infos(&cmds);
148
        let queue = self
149
            .shared
150
            .device
151
            .queue
152
            .lock()
153
            .unwrap_or_else(|e| e.into_inner());
154
        unsafe { d.queue_submit2(*queue, &[submit], fence.fence)? };
155
        Ok(fence)
156
    }
157
158
    /// Records, submits and waits for a short command buffer.
159
    fn one_shot(
160
        &mut self,
161
        record: impl FnOnce(&ash::Device, vk::CommandBuffer),
162
    ) -> Result<(), Error> {
163
        let cmd = self.begin()?;
164
        record(&self.shared.device.device, cmd);
165
        let fence = self.end_and_submit(cmd)?;
166
        let res = fence.wait();
167
        unsafe {
168
            self.shared
169
                .device
170
                .device
171
                .free_command_buffers(self.pool, &[cmd])
172
        };
173
        Ok(res?)
174
    }
175
176
    pub(crate) fn submit(
177
        &mut self,
178
        target: &mut VulkanTarget<'_>,
179
        ops: Vec<Op>,
180
    ) -> Result<SyncPoint, Error> {
181
        self.reap();
182
        let image = target.0.0.clone();
183
        let mut keep = vec![VulkanTexture(image.clone())];
184
        let mut transitions = Vec::new();
185
        for op in &ops {
186
            if let Op::Draw {
187
                texture: Some(t), ..
188
            } = op
189
            {
190
                if t.0.layout() != vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL {
191
                    transitions.push(t.clone());
192
                }
193
                keep.push(t.clone());
194
            }
195
        }
196
        let mut pipelines = Vec::with_capacity(ops.len());
197
        for op in &ops {
198
            pipelines.push(match op {
199
                Op::Draw { kind, .. } => Some(self.pipelines.get(image.format, *kind)?),
200
                Op::Clear { .. } => None,
201
            });
202
        }
203
        let cmd = self.begin()?;
204
        let d = &self.shared.device.device;
205
        let push = &self.shared.device.push_descriptor;
206
        let (w, h) = (image.width, image.height);
207
        let sampler = self.sampler();
208
        unsafe {
209
            for t in &transitions {
210
                barrier(
211
                    d,
212
                    cmd,
213
                    t.0.image,
214
                    t.0.layout(),
215
                    vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
216
                );
217
                t.0.set_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL);
218
            }
219
            barrier(
220
                d,
221
                cmd,
222
                image.image,
223
                image.layout(),
224
                vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
225
            );
226
            let attachments = [vk::RenderingAttachmentInfo::default()
227
                .image_view(image.view)
228
                .image_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
229
                .load_op(vk::AttachmentLoadOp::LOAD)
230
                .store_op(vk::AttachmentStoreOp::STORE)];
231
            let area = vk::Rect2D {
232
                offset: vk::Offset2D::default(),
233
                extent: vk::Extent2D {
234
                    width: w,
235
                    height: h,
236
                },
237
            };
238
            d.cmd_begin_rendering(
239
                cmd,
240
                &vk::RenderingInfo::default()
241
                    .render_area(area)
242
                    .layer_count(1)
243
                    .color_attachments(&attachments),
244
            );
245
            d.cmd_set_viewport(
246
                cmd,
247
                0,
248
                &[vk::Viewport {
249
                    x: 0.0,
250
                    y: 0.0,
251
                    width: w as f32,
252
                    height: h as f32,
253
                    min_depth: 0.0,
254
                    max_depth: 1.0,
255
                }],
256
            );
257
            let mut bound = vk::Pipeline::null();
258
            for (op, pipeline) in ops.iter().zip(pipelines) {
259
                match op {
260
                    Op::Clear { color, rects } => {
261
                        let clear = [vk::ClearAttachment {
262
                            aspect_mask: vk::ImageAspectFlags::COLOR,
263
                            color_attachment: 0,
264
                            clear_value: vk::ClearValue {
265
                                color: vk::ClearColorValue { float32: *color },
266
                            },
267
                        }];
268
                        let rects: Vec<_> = rects
269
                            .iter()
270
                            .map(|&rect| vk::ClearRect {
271
                                rect,
272
                                base_array_layer: 0,
273
                                layer_count: 1,
274
                            })
275
                            .collect();
276
                        d.cmd_clear_attachments(cmd, &clear, &rects);
277
                    }
278
                    Op::Draw {
279
                        texture,
280
                        push: constants,
281
                        scissors,
282
                        ..
283
                    } => {
284
                        let pipeline = pipeline.unwrap_or_default();
285
                        if pipeline != bound {
286
                            d.cmd_bind_pipeline(cmd, vk::PipelineBindPoint::GRAPHICS, pipeline);
287
                            bound = pipeline;
288
                        }
289
                        if let Some(t) = texture {
290
                            let info = [vk::DescriptorImageInfo::default()
291
                                .image_view(t.0.view)
292
                                .image_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
293
                                .sampler(sampler)];
294
                            let write = vk::WriteDescriptorSet::default()
295
                                .dst_binding(0)
296
                                .descriptor_type(vk::DescriptorType::COMBINED_IMAGE_SAMPLER)
297
                                .image_info(&info);
298
                            push.cmd_push_descriptor_set(
299
                                cmd,
300
                                vk::PipelineBindPoint::GRAPHICS,
301
                                self.pipelines.layout,
302
                                0,
303
                                &[write],
304
                            );
305
                        }
306
                        d.cmd_push_constants(
307
                            cmd,
308
                            self.pipelines.layout,
309
                            vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::FRAGMENT,
310
                            0,
311
                            constants.bytes(),
312
                        );
313
                        for s in scissors {
314
                            d.cmd_set_scissor(cmd, 0, &[*s]);
315
                            d.cmd_draw(cmd, 4, 1, 0, 0);
316
                        }
317
                    }
318
                }
319
            }
320
            d.cmd_end_rendering(cmd);
321
        }
322
        image.set_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL);
323
        let fence = self.end_and_submit(cmd)?;
324
        self.pending.push(Pending {
325
            fence: fence.clone(),
326
            cmd,
327
            _keep: keep,
328
        });
329
        Ok(SyncPoint::from(VkFence(fence)))
330
    }
331
332
    fn upload(
333
        &mut self,
334
        image: &Arc<ImageInner>,
335
        data: &[u8],
336
        region: Rectangle<i32, Buffer>,
337
        flipped: bool,
338
    ) -> Result<(), Error> {
339
        let width = image.width as usize;
340
        let needed = width * image.height as usize * BYTES_PER_PIXEL;
341
        if data.len() < needed {
342
            return Err(Error::BufferTooSmall {
343
                needed,
344
                got: data.len(),
345
            });
346
        }
347
        let mut staging = Staging::new(
348
            &self.shared,
349
            needed,
350
            vk::BufferUsageFlags::TRANSFER_SRC,
351
            MemoryLocation::CpuToGpu,
352
        )?;
353
        let row = width * BYTES_PER_PIXEL;
354
        let rows = image.height as usize;
355
        let dst = staging.bytes_mut();
356
        for y in 0..rows {
357
            let from = if flipped { rows - 1 - y } else { y };
358
            dst[y * row..(y + 1) * row].copy_from_slice(&data[from * row..(from + 1) * row]);
359
        }
360
        let old = image.layout();
361
        let copy = vk::BufferImageCopy::default()
362
            .buffer_offset(
363
                ((region.loc.y as usize * width + region.loc.x as usize) * BYTES_PER_PIXEL) as u64,
364
            )
365
            .buffer_row_length(image.width)
366
            .image_subresource(
367
                vk::ImageSubresourceLayers::default()
368
                    .aspect_mask(vk::ImageAspectFlags::COLOR)
369
                    .layer_count(1),
370
            )
371
            .image_offset(vk::Offset3D {
372
                x: region.loc.x,
373
                y: region.loc.y,
374
                z: 0,
375
            })
376
            .image_extent(vk::Extent3D {
377
                width: region.size.w as u32,
378
                height: region.size.h as u32,
379
                depth: 1,
380
            });
381
        let (img, buffer) = (image.image, staging.buffer);
382
        self.one_shot(|d, cmd| unsafe {
383
            barrier(d, cmd, img, old, vk::ImageLayout::TRANSFER_DST_OPTIMAL);
384
            d.cmd_copy_buffer_to_image(
385
                cmd,
386
                buffer,
387
                img,
388
                vk::ImageLayout::TRANSFER_DST_OPTIMAL,
389
                &[copy],
390
            );
391
            barrier(
392
                d,
393
                cmd,
394
                img,
395
                vk::ImageLayout::TRANSFER_DST_OPTIMAL,
396
                vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
397
            );
398
        })?;
399
        image.set_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL);
400
        Ok(())
401
    }
402
403
    fn read_back(
404
        &mut self,
405
        image: &Arc<ImageInner>,
406
        region: Rectangle<i32, Buffer>,
407
        fourcc: Fourcc,
408
    ) -> Result<VulkanMapping, Error> {
409
        let region = region
410
            .intersection(Rectangle::from_size(
411
                (image.width as i32, image.height as i32).into(),
412
            ))
413
            .unwrap_or_default();
414
        let (w, h) = (region.size.w.max(0) as u32, region.size.h.max(0) as u32);
415
        let swap = needs_swizzle(image.fourcc, fourcc)?;
416
        let len = (w as usize * h as usize * BYTES_PER_PIXEL).max(BYTES_PER_PIXEL);
417
        let staging = Staging::new(
418
            &self.shared,
419
            len,
420
            vk::BufferUsageFlags::TRANSFER_DST,
421
            MemoryLocation::GpuToCpu,
422
        )?;
423
        if w > 0 && h > 0 {
424
            let old = image.layout();
425
            let copy = vk::BufferImageCopy::default()
426
                .image_subresource(
427
                    vk::ImageSubresourceLayers::default()
428
                        .aspect_mask(vk::ImageAspectFlags::COLOR)
429
                        .layer_count(1),
430
                )
431
                .image_offset(vk::Offset3D {
432
                    x: region.loc.x,
433
                    y: region.loc.y,
434
                    z: 0,
435
                })
436
                .image_extent(vk::Extent3D {
437
                    width: w,
438
                    height: h,
439
                    depth: 1,
440
                });
441
            let (img, buffer) = (image.image, staging.buffer);
442
            self.one_shot(|d, cmd| unsafe {
443
                barrier(d, cmd, img, old, vk::ImageLayout::TRANSFER_SRC_OPTIMAL);
444
                d.cmd_copy_image_to_buffer(
445
                    cmd,
446
                    img,
447
                    vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
448
                    buffer,
449
                    &[copy],
450
                );
451
            })?;
452
            image.set_layout(vk::ImageLayout::TRANSFER_SRC_OPTIMAL);
453
        }
454
        let mut data = staging.bytes()[..w as usize * h as usize * BYTES_PER_PIXEL].to_vec();
455
        if swap {
456
            for px in data.as_chunks_mut::<BYTES_PER_PIXEL>().0 {
457
                px.swap(0, 2);
458
            }
459
        }
460
        Ok(VulkanMapping {
461
            data,
462
            width: w,
463
            height: h,
464
            fourcc,
465
        })
466
    }
467
468
    fn own(&self, image: &Arc<ImageInner>) -> Result<(), Error> {
469
        if Arc::ptr_eq(&image.shared, &self.shared) {
470
            Ok(())
471
        } else {
472
            Err(Error::ForeignTexture)
473
        }
474
    }
475
}
476
477
impl Drop for VulkanRenderer {
478
    fn drop(&mut self) {
479
        let d = &self.shared.device.device;
480
        unsafe {
481
            let _ = d.device_wait_idle();
482
            for p in self.pending.drain(..) {
483
                d.free_command_buffers(self.pool, &[p.cmd]);
484
            }
485
            for s in self.samplers {
486
                d.destroy_sampler(s, None);
487
            }
488
            d.destroy_command_pool(self.pool, None);
489
        }
490
    }
491
}
492
493
fn sampler_filter(bit: usize) -> TextureFilter {
494
    if bit == 0 {
495
        TextureFilter::Linear
496
    } else {
497
        TextureFilter::Nearest
498
    }
499
}
500
501
/// A full barrier between all earlier and later work on the image. Coarse,
502
/// but correct for every transition the renderer makes.
503
unsafe fn barrier(
504
    d: &ash::Device,
505
    cmd: vk::CommandBuffer,
506
    image: vk::Image,
507
    old: vk::ImageLayout,
508
    new: vk::ImageLayout,
509
) {
510
    let b = [vk::ImageMemoryBarrier2::default()
511
        .src_stage_mask(vk::PipelineStageFlags2::ALL_COMMANDS)
512
        .src_access_mask(vk::AccessFlags2::MEMORY_WRITE)
513
        .dst_stage_mask(vk::PipelineStageFlags2::ALL_COMMANDS)
514
        .dst_access_mask(vk::AccessFlags2::MEMORY_READ | vk::AccessFlags2::MEMORY_WRITE)
515
        .old_layout(old)
516
        .new_layout(new)
517
        .image(image)
518
        .subresource_range(color_range())];
519
    unsafe {
520
        d.cmd_pipeline_barrier2(
521
            cmd,
522
            &vk::DependencyInfo::default().image_memory_barriers(&b),
523
        )
524
    };
525
}
526
527
/// Whether reading `from` as `to` needs red and blue swapped.
528
fn needs_swizzle(from: Fourcc, to: Fourcc) -> Result<bool, Error> {
529
    let bgr = |f: Fourcc| match f {
530
        Fourcc::Argb8888 | Fourcc::Xrgb8888 => Ok(true),
531
        Fourcc::Abgr8888 | Fourcc::Xbgr8888 => Ok(false),
532
        f => Err(Error::UnsupportedFormat(f)),
533
    };
534
    Ok(bgr(from)? != bgr(to)?)
535
}
536
537
impl RendererSuper for VulkanRenderer {
538
    type Error = Error;
539
    type TextureId = VulkanTexture;
540
    type Framebuffer<'buffer> = VulkanTarget<'buffer>;
541
    type Frame<'frame, 'buffer>
542
        = VulkanFrame<'frame, 'buffer>
543
    where
544
        'buffer: 'frame,
545
        Self: 'frame;
546
}
547
548
impl Renderer for VulkanRenderer {
549
    fn context_id(&self) -> ContextId<VulkanTexture> {
550
        self.context.clone()
551
    }
552
553
    fn downscale_filter(&mut self, filter: TextureFilter) -> Result<(), Error> {
554
        self.min_filter = filter;
555
        Ok(())
556
    }
557
558
    fn upscale_filter(&mut self, filter: TextureFilter) -> Result<(), Error> {
559
        self.mag_filter = filter;
560
        Ok(())
561
    }
562
563
    fn set_debug_flags(&mut self, flags: DebugFlags) {
564
        self.debug = flags;
565
    }
566
567
    fn debug_flags(&self) -> DebugFlags {
568
        self.debug
569
    }
570
571
    fn render<'frame, 'buffer>(
572
        &'frame mut self,
573
        framebuffer: &'frame mut VulkanTarget<'buffer>,
574
        output_size: Size<i32, Physical>,
575
        dst_transform: Transform,
576
    ) -> Result<VulkanFrame<'frame, 'buffer>, Error>
577
    where
578
        'buffer: 'frame,
579
    {
580
        self.own(&framebuffer.0.0)?;
581
        self.reap();
582
        Ok(VulkanFrame::new(
583
            self,
584
            framebuffer,
585
            output_size,
586
            dst_transform,
587
        ))
588
    }
589
590
    fn wait(&mut self, sync: &SyncPoint) -> Result<(), Error> {
591
        sync.wait().map_err(|_| Error::Interrupted)
592
    }
593
594
    fn cleanup_texture_cache(&mut self) -> Result<(), Error> {
595
        self.reap();
596
        Ok(())
597
    }
598
}
599
600
impl Bind<VulkanImage> for VulkanRenderer {
601
    fn bind<'a>(&mut self, target: &'a mut VulkanImage) -> Result<VulkanTarget<'a>, Error> {
602
        self.own(&target.0)?;
603
        Ok(VulkanTarget(target))
604
    }
605
}
606
607
impl Offscreen<VulkanImage> for VulkanRenderer {
608
    fn create_buffer(
609
        &mut self,
610
        format: Fourcc,
611
        size: Size<i32, Buffer>,
612
    ) -> Result<VulkanImage, Error> {
613
        if size.w <= 0 || size.h <= 0 {
614
            return Err(Error::InvalidSize(size.w, size.h));
615
        }
616
        let usage = vk::ImageUsageFlags::COLOR_ATTACHMENT
617
            | vk::ImageUsageFlags::SAMPLED
618
            | vk::ImageUsageFlags::TRANSFER_SRC
619
            | vk::ImageUsageFlags::TRANSFER_DST;
620
        Ok(VulkanImage(ImageInner::create(
621
            &self.shared,
622
            format,
623
            size.w as u32,
624
            size.h as u32,
625
            usage,
626
        )?))
627
    }
628
}
629
630
impl ImportMem for VulkanRenderer {
631
    fn import_memory(
632
        &mut self,
633
        data: &[u8],
634
        format: Fourcc,
635
        size: Size<i32, Buffer>,
636
        flipped: bool,
637
    ) -> Result<VulkanTexture, Error> {
638
        if size.w <= 0 || size.h <= 0 {
639
            return Err(Error::InvalidSize(size.w, size.h));
640
        }
641
        let usage = vk::ImageUsageFlags::SAMPLED
642
            | vk::ImageUsageFlags::TRANSFER_DST
643
            | vk::ImageUsageFlags::TRANSFER_SRC;
644
        let image = ImageInner::create(&self.shared, format, size.w as u32, size.h as u32, usage)?;
645
        self.upload(&image, data, Rectangle::from_size(size), flipped)?;
646
        Ok(VulkanTexture(image))
647
    }
648
649
    fn update_memory(
650
        &mut self,
651
        texture: &VulkanTexture,
652
        data: &[u8],
653
        region: Rectangle<i32, Buffer>,
654
    ) -> Result<(), Error> {
655
        self.own(&texture.0)?;
656
        let Some(region) = region.intersection(Rectangle::from_size(texture.size())) else {
657
            return Ok(());
658
        };
659
        self.upload(&texture.0, data, region, false)
660
    }
661
662
    fn mem_formats(&self) -> Box<dyn Iterator<Item = Fourcc>> {
663
        Box::new(SUPPORTED.into_iter())
664
    }
665
}
666
667
impl ExportMem for VulkanRenderer {
668
    type TextureMapping = VulkanMapping;
669
670
    fn copy_framebuffer(
671
        &mut self,
672
        target: &VulkanTarget<'_>,
673
        region: Rectangle<i32, Buffer>,
674
        format: Fourcc,
675
    ) -> Result<VulkanMapping, Error> {
676
        self.own(&target.0.0)?;
677
        let image = target.0.0.clone();
678
        self.read_back(&image, region, format)
679
    }
680
681
    fn copy_texture(
682
        &mut self,
683
        texture: &VulkanTexture,
684
        region: Rectangle<i32, Buffer>,
685
        format: Fourcc,
686
    ) -> Result<VulkanMapping, Error> {
687
        self.own(&texture.0)?;
688
        self.read_back(&texture.0, region, format)
689
    }
690
691
    fn can_read_texture(&mut self, _texture: &VulkanTexture) -> Result<bool, Error> {
692
        Ok(true)
693
    }
694
695
    fn map_texture<'a>(&mut self, mapping: &'a VulkanMapping) -> Result<&'a [u8], Error> {
696
        Ok(&mapping.data)
697
    }
698
}