Commit d2f26399309b
tarball2 files changed+147-112
@@ -24,97 +24,142 @@ impl LayoutLog {
2424
}2525
}2626
27
-/// A full barrier between all earlier and later work on the image, optionally28
-/// transferring ownership between queue families. Coarse, but correct for29
-/// every transition the renderer makes.30
-pub(crate) unsafe fn barrier(31
- d: &ash::Device,32
- cmd: vk::CommandBuffer,33
- image: vk::Image,34
- old: vk::ImageLayout,35
- new: vk::ImageLayout,36
- src_family: u32,37
- dst_family: u32,38
-) {39
- let b = [vk::ImageMemoryBarrier2::default()40
- .src_stage_mask(vk::PipelineStageFlags2::ALL_COMMANDS)41
- .src_access_mask(vk::AccessFlags2::MEMORY_WRITE)42
- .dst_stage_mask(vk::PipelineStageFlags2::ALL_COMMANDS)43
- .dst_access_mask(vk::AccessFlags2::MEMORY_READ | vk::AccessFlags2::MEMORY_WRITE)44
- .old_layout(old)45
- .new_layout(new)46
- .src_queue_family_index(src_family)47
- .dst_queue_family_index(dst_family)48
- .image(image)49
- .subresource_range(color_range())];50
- unsafe {51
- d.cmd_pipeline_barrier2(52
- cmd,53
- &vk::DependencyInfo::default().image_memory_barriers(&b),54
- )27
+struct Scope {28
+ stage: vk::PipelineStageFlags2,29
+ access: vk::AccessFlags2,30
+}31
+32
+/// What an image may still be doing when it leaves `layout`. Layouts the33
+/// renderer does not use itself, the general layout of dmabufs among them,34
+/// wait for everything.35
+fn leaving(layout: vk::ImageLayout) -> Scope {36
+ let (stage, access) = match layout {37
+ vk::ImageLayout::UNDEFINED => (vk::PipelineStageFlags2::NONE, vk::AccessFlags2::NONE),38
+ vk::ImageLayout::TRANSFER_DST_OPTIMAL => (39
+ vk::PipelineStageFlags2::TRANSFER,40
+ vk::AccessFlags2::TRANSFER_WRITE,41
+ ),42
+ vk::ImageLayout::TRANSFER_SRC_OPTIMAL => {43
+ (vk::PipelineStageFlags2::TRANSFER, vk::AccessFlags2::NONE)44
+ }45
+ vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL => (46
+ vk::PipelineStageFlags2::FRAGMENT_SHADER,47
+ vk::AccessFlags2::NONE,48
+ ),49
+ vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL => (50
+ vk::PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT,51
+ vk::AccessFlags2::COLOR_ATTACHMENT_WRITE,52
+ ),53
+ _ => (54
+ vk::PipelineStageFlags2::ALL_COMMANDS,55
+ vk::AccessFlags2::MEMORY_WRITE,56
+ ),5557
};58
+ Scope { stage, access }5659
}5760
58
-/// Moves an image into `layout` for use on this queue. Dmabuf images come59
-/// from the foreign queue family in the general layout, others continue from60
-/// their tracked layout.61
-pub(crate) unsafe fn acquire(62
- d: &ash::Device,63
- cmd: vk::CommandBuffer,64
- family: u32,65
- image: &Arc<ImageInner>,66
- layout: vk::ImageLayout,67
- log: &mut LayoutLog,68
-) {69
- if image.external {70
- unsafe {71
- barrier(72
- d,73
- cmd,61
+/// What an image does once it is in `layout`.62
+fn entering(layout: vk::ImageLayout) -> Scope {63
+ let (stage, access) = match layout {64
+ vk::ImageLayout::TRANSFER_DST_OPTIMAL => (65
+ vk::PipelineStageFlags2::TRANSFER,66
+ vk::AccessFlags2::TRANSFER_WRITE,67
+ ),68
+ vk::ImageLayout::TRANSFER_SRC_OPTIMAL => (69
+ vk::PipelineStageFlags2::TRANSFER,70
+ vk::AccessFlags2::TRANSFER_READ,71
+ ),72
+ vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL => (73
+ vk::PipelineStageFlags2::FRAGMENT_SHADER,74
+ vk::AccessFlags2::SHADER_SAMPLED_READ,75
+ ),76
+ vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL => (77
+ vk::PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT,78
+ vk::AccessFlags2::COLOR_ATTACHMENT_READ | vk::AccessFlags2::COLOR_ATTACHMENT_WRITE,79
+ ),80
+ _ => (81
+ vk::PipelineStageFlags2::ALL_COMMANDS,82
+ vk::AccessFlags2::MEMORY_READ | vk::AccessFlags2::MEMORY_WRITE,83
+ ),84
+ };85
+ Scope { stage, access }86
+}87
+88
+/// The image barriers of one phase of a command buffer, recorded together.89
+#[derive(Default)]90
+pub(crate) struct Barriers(Vec<vk::ImageMemoryBarrier2<'static>>);91
+92
+impl Barriers {93
+ fn push(94
+ &mut self,95
+ image: vk::Image,96
+ (old, src_family): (vk::ImageLayout, u32),97
+ (new, dst_family): (vk::ImageLayout, u32),98
+ ) {99
+ let (from, to) = (leaving(old), entering(new));100
+ self.0.push(101
+ vk::ImageMemoryBarrier2::default()102
+ .src_stage_mask(from.stage)103
+ .src_access_mask(from.access)104
+ .dst_stage_mask(to.stage)105
+ .dst_access_mask(to.access)106
+ .old_layout(old)107
+ .new_layout(new)108
+ .src_queue_family_index(src_family)109
+ .dst_queue_family_index(dst_family)110
+ .image(image)111
+ .subresource_range(color_range()),112
+ );113
+ }114
+115
+ /// Moves an image into `layout` for use on this queue. Dmabuf images come116
+ /// from the foreign queue family in the general layout, others continue117
+ /// from their tracked layout.118
+ pub fn acquire(119
+ &mut self,120
+ family: u32,121
+ image: &Arc<ImageInner>,122
+ layout: vk::ImageLayout,123
+ log: &mut LayoutLog,124
+ ) {125
+ if image.external {126
+ self.push(74127
image.image,75
- vk::ImageLayout::GENERAL,76
- layout,77
- vk::QUEUE_FAMILY_FOREIGN_EXT,78
- family,79
- )80
- };81
- } else {82
- let old = log.current(image);83
- if old != layout {84
- unsafe {85
- barrier(86
- d,87
- cmd,128
+ (vk::ImageLayout::GENERAL, vk::QUEUE_FAMILY_FOREIGN_EXT),129
+ (layout, family),130
+ );131
+ } else {132
+ let old = log.current(image);133
+ if old != layout {134
+ self.push(88135
image.image,89
- old,90
- layout,91
- vk::QUEUE_FAMILY_IGNORED,92
- vk::QUEUE_FAMILY_IGNORED,93
- )94
- };95
- log.0.push((image.clone(), layout));136
+ (old, vk::QUEUE_FAMILY_IGNORED),137
+ (layout, vk::QUEUE_FAMILY_IGNORED),138
+ );139
+ log.0.push((image.clone(), layout));140
+ }141
+ }142
+ }143
+144
+ /// Hands a dmabuf image back to the foreign queue family after use.145
+ pub fn release(&mut self, family: u32, image: &ImageInner, layout: vk::ImageLayout) {146
+ if image.external {147
+ self.push(148
+ image.image,149
+ (layout, family),150
+ (vk::ImageLayout::GENERAL, vk::QUEUE_FAMILY_FOREIGN_EXT),151
+ );96152
}97153
}98
-}99154
100
-/// Hands a dmabuf image back to the foreign queue family after use.101
-pub(crate) unsafe fn release(102
- d: &ash::Device,103
- cmd: vk::CommandBuffer,104
- family: u32,105
- image: &ImageInner,106
- layout: vk::ImageLayout,107
-) {108
- if image.external {155
+ pub unsafe fn record(self, d: &ash::Device, cmd: vk::CommandBuffer) {156
+ if self.0.is_empty() {157
+ return;158
+ }109159
unsafe {110
- barrier(111
- d,160
+ d.cmd_pipeline_barrier2(112161
cmd,113
- image.image,114
- layout,115
- vk::ImageLayout::GENERAL,116
- family,117
- vk::QUEUE_FAMILY_FOREIGN_EXT,162
+ &vk::DependencyInfo::default().image_memory_barriers(&self.0),118163
)119164
};120165
}@@ -5,7 +5,7 @@ use shm::stage_rows;
55
use stall::{STALL, StallPhase};66
77
use crate::Error;8
-use crate::barrier::{LayoutLog, acquire, release};8
+use crate::barrier::{Barriers, LayoutLog};99
use crate::device::Shared;1010
use crate::dmabuf::{self, DmabufCaps, RENDER_USAGE, SAMPLE_USAGE, VulkanAllocator};1111
use crate::format::{BYTES_PER_PIXEL, SUPPORTED};@@ -352,16 +352,16 @@ impl VulkanRenderer {
352352
let d = &self.shared.device.device;353353
let family = self.shared.device.queue_family;354354
unsafe {355
+ let mut barriers = Barriers::default();355356
for u in &uploads {356
- acquire(357
- d,358
- cmd,357
+ barriers.acquire(359358
family,360359
&u.image,361360
vk::ImageLayout::TRANSFER_DST_OPTIMAL,362361
&mut layouts,363362
);364363
}364
+ barriers.record(d, cmd);365365
for (i, u) in uploads.iter().enumerate() {366366
if uploads[..i].iter().any(|e| Arc::ptr_eq(&e.image, &u.image)) {367367
let order = [vk::MemoryBarrier2::default()@@ -382,16 +382,16 @@ impl VulkanRenderer {
382382
&[u.copy],383383
);384384
}385
+ let mut barriers = Barriers::default();385386
for u in &uploads {386
- acquire(387
- d,388
- cmd,387
+ barriers.acquire(389388
family,390389
&u.image,391390
vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,392391
&mut layouts,393392
);394393
}394
+ barriers.record(d, cmd);395395
}396396
Recorded { uploads, layouts }397397
}@@ -439,24 +439,22 @@ impl VulkanRenderer {
439439
let (w, h) = (image.width, image.height);440440
let sampler = self.sampler();441441
unsafe {442
+ let mut barriers = Barriers::default();442443
for t in &sampled {443
- acquire(444
- d,445
- cmd,444
+ barriers.acquire(446445
family,447446
t,448447
vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,449448
&mut recorded.layouts,450449
);451450
}452
- acquire(453
- d,454
- cmd,451
+ barriers.acquire(455452
family,456453
&image,457454
vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,458455
&mut recorded.layouts,459456
);457
+ barriers.record(d, cmd);460458
let attachments = [vk::RenderingAttachmentInfo::default()461459
.image_view(image.view)462460
.image_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)@@ -552,16 +550,12 @@ impl VulkanRenderer {
552550
}553551
}554552
d.cmd_end_rendering(cmd);555
- release(556
- d,557
- cmd,558
- family,559
- &image,560
- vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,561
- );553
+ let mut barriers = Barriers::default();554
+ barriers.release(family, &image, vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL);562555
for t in &sampled {563
- release(d, cmd, family, t, vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL);556
+ barriers.release(family, t, vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL);564557
}558
+ barriers.record(d, cmd);565559
}566560
sampled.push(image);567561
let fence = self.finish(cmd, recorded, sampled)?;@@ -693,14 +687,14 @@ impl VulkanRenderer {
693687
let buffer = staging.buffer;694688
let source = image.clone();695689
self.one_shot(|d, cmd, family, layouts| unsafe {696
- acquire(697
- d,698
- cmd,690
+ let mut barriers = Barriers::default();691
+ barriers.acquire(699692
family,700693
&source,701694
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,702695
layouts,703696
);697
+ barriers.record(d, cmd);704698
d.cmd_copy_image_to_buffer(705699
cmd,706700
source.image,@@ -708,13 +702,9 @@ impl VulkanRenderer {
708702
buffer,709703
&[copy],710704
);711
- release(712
- d,713
- cmd,714
- family,715
- &source,716
- vk::ImageLayout::TRANSFER_SRC_OPTIMAL,717
- );705
+ let mut barriers = Barriers::default();706
+ barriers.release(family, &source, vk::ImageLayout::TRANSFER_SRC_OPTIMAL);707
+ barriers.record(d, cmd);718708
})?;719709
}720710
let mut data = staging.bytes()?[..w as usize * h as usize * BYTES_PER_PIXEL].to_vec();