vulkan: unconditionally support linear framebuffers
This commit is contained in:
parent
59e4de03d1
commit
62cdd276cf
4 changed files with 309 additions and 67 deletions
|
|
@ -8,6 +8,7 @@
|
|||
- Add support for pointer-gestures-unstable-v1.
|
||||
- Configs can now handle switch events (laptop lid closed/opened).
|
||||
- Add support for tablet-v2.
|
||||
- Add support for linear framebuffers (hardware cursors/screensharing) on NVIDIA if the Vulkan renderer is used. (The OpenGL renderer does not support this.)
|
||||
|
||||
# 1.1.0 (2024-04-22)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use {
|
|||
crate::{
|
||||
format::{Format, FORMATS},
|
||||
gfx_apis::vulkan::{instance::VulkanInstance, VulkanError},
|
||||
video::Modifier,
|
||||
video::{Modifier, LINEAR_MODIFIER},
|
||||
},
|
||||
ahash::AHashMap,
|
||||
ash::{
|
||||
|
|
@ -17,14 +17,14 @@ use {
|
|||
},
|
||||
},
|
||||
isnt::std_1::collections::IsntHashMapExt,
|
||||
std::cmp::min,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VulkanFormat {
|
||||
pub format: &'static Format,
|
||||
pub modifiers: AHashMap<Modifier, VulkanModifier>,
|
||||
pub shm: Option<VulkanShmFormat>,
|
||||
pub features: FormatFeatureFlags,
|
||||
pub shm: Option<VulkanInternalFormat>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -34,6 +34,7 @@ pub struct VulkanModifier {
|
|||
pub features: FormatFeatureFlags,
|
||||
pub render_max_extents: Option<VulkanMaxExtents>,
|
||||
pub texture_max_extents: Option<VulkanMaxExtents>,
|
||||
pub render_needs_bridge: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
|
@ -43,7 +44,7 @@ pub struct VulkanMaxExtents {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VulkanShmFormat {
|
||||
pub struct VulkanInternalFormat {
|
||||
pub max_extents: VulkanMaxExtents,
|
||||
}
|
||||
|
||||
|
|
@ -51,6 +52,7 @@ const FRAMEBUFFER_FEATURES: FormatFeatureFlags = FormatFeatureFlags::from_raw(
|
|||
0 | FormatFeatureFlags::COLOR_ATTACHMENT.as_raw()
|
||||
| FormatFeatureFlags::COLOR_ATTACHMENT_BLEND.as_raw(),
|
||||
);
|
||||
const FRAMEBUFFER_BRIDGED_FEATURES: FormatFeatureFlags = FormatFeatureFlags::TRANSFER_DST;
|
||||
const TEX_FEATURES: FormatFeatureFlags = FormatFeatureFlags::from_raw(
|
||||
0 | FormatFeatureFlags::SAMPLED_IMAGE.as_raw()
|
||||
| FormatFeatureFlags::TRANSFER_SRC.as_raw()
|
||||
|
|
@ -65,6 +67,7 @@ const SHM_FEATURES: FormatFeatureFlags = FormatFeatureFlags::from_raw(
|
|||
const FRAMEBUFFER_USAGE: ImageUsageFlags = ImageUsageFlags::from_raw(
|
||||
0 | ImageUsageFlags::COLOR_ATTACHMENT.as_raw() | ImageUsageFlags::TRANSFER_SRC.as_raw(),
|
||||
);
|
||||
const FRAMEBUFFER_BRIDGED_USAGE: ImageUsageFlags = ImageUsageFlags::TRANSFER_DST;
|
||||
const TEX_USAGE: ImageUsageFlags = ImageUsageFlags::from_raw(
|
||||
0 | ImageUsageFlags::SAMPLED.as_raw() | ImageUsageFlags::TRANSFER_SRC.as_raw(),
|
||||
);
|
||||
|
|
@ -104,7 +107,8 @@ impl VulkanInstance {
|
|||
);
|
||||
}
|
||||
let shm = self.load_shm_format(phy_dev, format, &format_properties)?;
|
||||
let modifiers = self.load_drm_format(phy_dev, format, &modifier_props)?;
|
||||
let modifiers =
|
||||
self.load_drm_format(phy_dev, format, &format_properties, &modifier_props)?;
|
||||
if shm.is_some() || modifiers.is_not_empty() {
|
||||
dst.insert(
|
||||
format.drm,
|
||||
|
|
@ -112,7 +116,6 @@ impl VulkanInstance {
|
|||
format,
|
||||
modifiers,
|
||||
shm,
|
||||
features: format_properties.format_properties.optimal_tiling_features,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -124,14 +127,25 @@ impl VulkanInstance {
|
|||
phy_dev: PhysicalDevice,
|
||||
format: &Format,
|
||||
props: &FormatProperties2,
|
||||
) -> Result<Option<VulkanShmFormat>, VulkanError> {
|
||||
) -> Result<Option<VulkanInternalFormat>, VulkanError> {
|
||||
if format.shm_info.is_none() {
|
||||
return Ok(None);
|
||||
}
|
||||
self.load_internal_format(phy_dev, format, props, SHM_FEATURES, SHM_USAGE)
|
||||
}
|
||||
|
||||
fn load_internal_format(
|
||||
&self,
|
||||
phy_dev: PhysicalDevice,
|
||||
format: &Format,
|
||||
props: &FormatProperties2,
|
||||
features: FormatFeatureFlags,
|
||||
usage: ImageUsageFlags,
|
||||
) -> Result<Option<VulkanInternalFormat>, VulkanError> {
|
||||
if !props
|
||||
.format_properties
|
||||
.optimal_tiling_features
|
||||
.contains(SHM_FEATURES)
|
||||
.contains(features)
|
||||
{
|
||||
return Ok(None);
|
||||
}
|
||||
|
|
@ -139,7 +153,7 @@ impl VulkanInstance {
|
|||
.ty(ImageType::TYPE_2D)
|
||||
.format(format.vk_format)
|
||||
.tiling(ImageTiling::OPTIMAL)
|
||||
.usage(SHM_USAGE);
|
||||
.usage(usage);
|
||||
let mut format_properties = ImageFormatProperties2::builder();
|
||||
let res = unsafe {
|
||||
self.instance.get_physical_device_image_format_properties2(
|
||||
|
|
@ -154,7 +168,7 @@ impl VulkanInstance {
|
|||
_ => Err(VulkanError::LoadImageProperties(e)),
|
||||
};
|
||||
}
|
||||
Ok(Some(VulkanShmFormat {
|
||||
Ok(Some(VulkanInternalFormat {
|
||||
max_extents: VulkanMaxExtents {
|
||||
width: format_properties.image_format_properties.max_extent.width,
|
||||
height: format_properties.image_format_properties.max_extent.height,
|
||||
|
|
@ -166,6 +180,7 @@ impl VulkanInstance {
|
|||
&self,
|
||||
phy_dev: PhysicalDevice,
|
||||
format: &Format,
|
||||
internal_format_properties: &FormatProperties2,
|
||||
props: &DrmFormatModifierPropertiesListEXT,
|
||||
) -> Result<AHashMap<Modifier, VulkanModifier>, VulkanError> {
|
||||
if props.drm_format_modifier_count == 0 {
|
||||
|
|
@ -190,7 +205,7 @@ impl VulkanInstance {
|
|||
};
|
||||
let mut mods = AHashMap::new();
|
||||
for modifier in drm_mods {
|
||||
let render_max_extents = self.get_max_extents(
|
||||
let mut render_max_extents = self.get_max_extents(
|
||||
phy_dev,
|
||||
format,
|
||||
FRAMEBUFFER_FEATURES,
|
||||
|
|
@ -199,6 +214,18 @@ impl VulkanInstance {
|
|||
)?;
|
||||
let texture_max_extents =
|
||||
self.get_max_extents(phy_dev, format, TEX_FEATURES, TEX_USAGE, &modifier)?;
|
||||
let mut render_needs_bridge = false;
|
||||
if render_max_extents.is_none() && modifier.drm_format_modifier == LINEAR_MODIFIER {
|
||||
render_max_extents = self.get_fb_bridged_max_extents(
|
||||
phy_dev,
|
||||
format,
|
||||
internal_format_properties,
|
||||
&modifier,
|
||||
)?;
|
||||
if render_max_extents.is_some() {
|
||||
render_needs_bridge = true;
|
||||
}
|
||||
}
|
||||
mods.insert(
|
||||
modifier.drm_format_modifier,
|
||||
VulkanModifier {
|
||||
|
|
@ -207,12 +234,52 @@ impl VulkanInstance {
|
|||
features: modifier.drm_format_modifier_tiling_features,
|
||||
render_max_extents,
|
||||
texture_max_extents,
|
||||
render_needs_bridge,
|
||||
},
|
||||
);
|
||||
}
|
||||
Ok(mods)
|
||||
}
|
||||
|
||||
fn get_fb_bridged_max_extents(
|
||||
&self,
|
||||
phy_dev: PhysicalDevice,
|
||||
format: &Format,
|
||||
internal_format_properties: &FormatProperties2,
|
||||
modifier: &DrmFormatModifierPropertiesEXT,
|
||||
) -> Result<Option<VulkanMaxExtents>, VulkanError> {
|
||||
let transfer_dst_max_extents = self.get_max_extents(
|
||||
phy_dev,
|
||||
format,
|
||||
FRAMEBUFFER_BRIDGED_FEATURES,
|
||||
FRAMEBUFFER_BRIDGED_USAGE,
|
||||
&modifier,
|
||||
)?;
|
||||
let Some(transfer_dst_max_extents) = transfer_dst_max_extents else {
|
||||
return Ok(None);
|
||||
};
|
||||
let bridge_format = self.load_internal_format(
|
||||
phy_dev,
|
||||
format,
|
||||
internal_format_properties,
|
||||
FRAMEBUFFER_FEATURES,
|
||||
FRAMEBUFFER_USAGE,
|
||||
)?;
|
||||
let Some(bridge_format) = bridge_format else {
|
||||
return Ok(None);
|
||||
};
|
||||
Ok(Some(VulkanMaxExtents {
|
||||
width: min(
|
||||
transfer_dst_max_extents.width,
|
||||
bridge_format.max_extents.width,
|
||||
),
|
||||
height: min(
|
||||
transfer_dst_max_extents.height,
|
||||
bridge_format.max_extents.height,
|
||||
),
|
||||
}))
|
||||
}
|
||||
|
||||
fn get_max_extents(
|
||||
&self,
|
||||
phy_dev: PhysicalDevice,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ pub struct VulkanDmaBufImageTemplate {
|
|||
pub(super) dmabuf: DmaBuf,
|
||||
pub(super) render_max_extents: Option<VulkanMaxExtents>,
|
||||
pub(super) texture_max_extents: Option<VulkanMaxExtents>,
|
||||
pub(super) render_needs_bridge: bool,
|
||||
}
|
||||
|
||||
pub struct VulkanImage {
|
||||
|
|
@ -53,6 +54,7 @@ pub struct VulkanImage {
|
|||
pub(super) is_undefined: Cell<bool>,
|
||||
pub(super) ty: VulkanImageMemory,
|
||||
pub(super) render_ops: CloneCell<Vec<GfxApiOpt>>,
|
||||
pub(super) bridge: Option<VulkanFramebufferBridge>,
|
||||
}
|
||||
|
||||
pub enum VulkanImageMemory {
|
||||
|
|
@ -72,6 +74,11 @@ pub struct VulkanShmImage {
|
|||
pub(super) _allocation: VulkanAllocation,
|
||||
}
|
||||
|
||||
pub struct VulkanFramebufferBridge {
|
||||
pub(super) dmabuf_image: Image,
|
||||
pub(super) _allocation: VulkanAllocation,
|
||||
}
|
||||
|
||||
impl Drop for VulkanDmaBufImage {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
|
|
@ -96,6 +103,12 @@ impl Drop for VulkanImage {
|
|||
.destroy_image_view(render_view, None);
|
||||
}
|
||||
self.renderer.device.device.destroy_image(self.image, None);
|
||||
if let Some(bridge) = &self.bridge {
|
||||
self.renderer
|
||||
.device
|
||||
.device
|
||||
.destroy_image(bridge.dmabuf_image, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -214,6 +227,7 @@ impl VulkanRenderer {
|
|||
is_undefined: Cell::new(true),
|
||||
ty: VulkanImageMemory::Internal(shm),
|
||||
render_ops: Default::default(),
|
||||
bridge: None,
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
@ -264,6 +278,7 @@ impl VulkanRenderer {
|
|||
dmabuf: dmabuf.clone(),
|
||||
render_max_extents: modifier.render_max_extents,
|
||||
texture_max_extents: modifier.texture_max_extents,
|
||||
render_needs_bridge: modifier.render_needs_bridge,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
@ -343,11 +358,13 @@ impl VulkanDmaBufImageTemplate {
|
|||
true => ImageCreateFlags::DISJOINT,
|
||||
false => ImageCreateFlags::empty(),
|
||||
};
|
||||
let usage = ImageUsageFlags::TRANSFER_SRC
|
||||
| match for_rendering {
|
||||
true => ImageUsageFlags::COLOR_ATTACHMENT,
|
||||
false => ImageUsageFlags::SAMPLED,
|
||||
};
|
||||
let usage = match for_rendering {
|
||||
true => match self.render_needs_bridge {
|
||||
true => ImageUsageFlags::TRANSFER_DST,
|
||||
false => ImageUsageFlags::TRANSFER_SRC | ImageUsageFlags::COLOR_ATTACHMENT,
|
||||
},
|
||||
false => ImageUsageFlags::TRANSFER_SRC | ImageUsageFlags::SAMPLED,
|
||||
};
|
||||
let create_info = ImageCreateInfo::builder()
|
||||
.image_type(ImageType::TYPE_2D)
|
||||
.format(self.dmabuf.format.vk_format)
|
||||
|
|
@ -456,15 +473,30 @@ impl VulkanDmaBufImageTemplate {
|
|||
}
|
||||
let res = unsafe { device.device.bind_image_memory2(&bind_image_memory_infos) };
|
||||
res.map_err(VulkanError::BindImageMemory)?;
|
||||
let texture_view = device.create_image_view(image, self.dmabuf.format, false)?;
|
||||
let render_view = device.create_image_view(image, self.dmabuf.format, true)?;
|
||||
let mut primary_image = image;
|
||||
let mut destroy_bridge_image = None;
|
||||
let mut bridge = None;
|
||||
if for_rendering && self.render_needs_bridge {
|
||||
let (bridge_image, allocation) = self.create_bridge()?;
|
||||
primary_image = bridge_image;
|
||||
destroy_bridge_image = Some(OnDrop(|| unsafe {
|
||||
device.device.destroy_image(primary_image, None)
|
||||
}));
|
||||
bridge = Some(VulkanFramebufferBridge {
|
||||
dmabuf_image: image,
|
||||
_allocation: allocation,
|
||||
});
|
||||
}
|
||||
let texture_view = device.create_image_view(primary_image, self.dmabuf.format, false)?;
|
||||
let render_view = device.create_image_view(primary_image, self.dmabuf.format, true)?;
|
||||
free_device_memories.drain(..).for_each(mem::forget);
|
||||
mem::forget(destroy_image);
|
||||
mem::forget(destroy_bridge_image);
|
||||
Ok(Rc::new(VulkanImage {
|
||||
renderer: self.renderer.clone(),
|
||||
texture_view,
|
||||
render_view: Some(render_view),
|
||||
image,
|
||||
image: primary_image,
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
stride: 0,
|
||||
|
|
@ -475,8 +507,53 @@ impl VulkanDmaBufImageTemplate {
|
|||
}),
|
||||
format: self.dmabuf.format,
|
||||
is_undefined: Cell::new(true),
|
||||
bridge,
|
||||
}))
|
||||
}
|
||||
|
||||
fn create_bridge(&self) -> Result<(Image, VulkanAllocation), VulkanError> {
|
||||
let create_info = ImageCreateInfo::builder()
|
||||
.image_type(ImageType::TYPE_2D)
|
||||
.format(self.dmabuf.format.vk_format)
|
||||
.mip_levels(1)
|
||||
.array_layers(1)
|
||||
.tiling(ImageTiling::OPTIMAL)
|
||||
.samples(SampleCountFlags::TYPE_1)
|
||||
.sharing_mode(SharingMode::EXCLUSIVE)
|
||||
.initial_layout(ImageLayout::UNDEFINED)
|
||||
.extent(Extent3D {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
depth: 1,
|
||||
})
|
||||
.usage(ImageUsageFlags::COLOR_ATTACHMENT | ImageUsageFlags::TRANSFER_SRC)
|
||||
.build();
|
||||
let image = unsafe { self.renderer.device.device.create_image(&create_info, None) };
|
||||
let image = image.map_err(VulkanError::CreateImage)?;
|
||||
let destroy_image =
|
||||
OnDrop(|| unsafe { self.renderer.device.device.destroy_image(image, None) });
|
||||
let memory_requirements = unsafe {
|
||||
self.renderer
|
||||
.device
|
||||
.device
|
||||
.get_image_memory_requirements(image)
|
||||
};
|
||||
let allocation = self.renderer.allocator.alloc(
|
||||
&memory_requirements,
|
||||
UsageFlags::FAST_DEVICE_ACCESS,
|
||||
false,
|
||||
)?;
|
||||
let res = unsafe {
|
||||
self.renderer.device.device.bind_image_memory(
|
||||
image,
|
||||
allocation.memory,
|
||||
allocation.offset,
|
||||
)
|
||||
};
|
||||
res.map_err(VulkanError::BindImageMemory)?;
|
||||
destroy_image.forget();
|
||||
Ok((image, allocation))
|
||||
}
|
||||
}
|
||||
|
||||
impl GfxImage for VulkanDmaBufImageTemplate {
|
||||
|
|
|
|||
|
|
@ -33,12 +33,13 @@ use {
|
|||
AccessFlags2, AttachmentLoadOp, AttachmentStoreOp, BufferImageCopy, BufferImageCopy2,
|
||||
BufferMemoryBarrier2, ClearColorValue, ClearValue, CommandBuffer,
|
||||
CommandBufferBeginInfo, CommandBufferSubmitInfo, CommandBufferUsageFlags,
|
||||
CopyBufferToImageInfo2, DependencyInfo, DependencyInfoKHR, DescriptorImageInfo,
|
||||
DescriptorType, Extent2D, Extent3D, Fence, ImageAspectFlags, ImageLayout,
|
||||
ImageMemoryBarrier2, ImageMemoryBarrier2Builder, ImageSubresourceLayers,
|
||||
ImageSubresourceRange, PipelineBindPoint, PipelineStageFlags2, Rect2D,
|
||||
RenderingAttachmentInfo, RenderingInfo, SemaphoreSubmitInfo, SemaphoreSubmitInfoKHR,
|
||||
ShaderStageFlags, SubmitInfo2, Viewport, WriteDescriptorSet, QUEUE_FAMILY_FOREIGN_EXT,
|
||||
CopyBufferToImageInfo2, CopyImageInfo2, DependencyInfo, DependencyInfoKHR,
|
||||
DescriptorImageInfo, DescriptorType, Extent2D, Extent3D, Fence, ImageAspectFlags,
|
||||
ImageCopy2, ImageLayout, ImageMemoryBarrier2, ImageMemoryBarrier2Builder,
|
||||
ImageSubresourceLayers, ImageSubresourceRange, PipelineBindPoint, PipelineStageFlags2,
|
||||
Rect2D, RenderingAttachmentInfo, RenderingInfo, SemaphoreSubmitInfo,
|
||||
SemaphoreSubmitInfoKHR, ShaderStageFlags, SubmitInfo2, Viewport, WriteDescriptorSet,
|
||||
QUEUE_FAMILY_FOREIGN_EXT,
|
||||
},
|
||||
Device,
|
||||
},
|
||||
|
|
@ -266,19 +267,33 @@ impl VulkanRenderer {
|
|||
let memory = &mut *memory;
|
||||
memory.image_barriers.clear();
|
||||
memory.shm_barriers.clear();
|
||||
let fb_image_memory_barrier = image_barrier()
|
||||
.src_queue_family_index(QUEUE_FAMILY_FOREIGN_EXT)
|
||||
.dst_queue_family_index(self.device.graphics_queue_idx)
|
||||
let mut fb_image_memory_barrier = image_barrier()
|
||||
.image(fb.image)
|
||||
.old_layout(if fb.is_undefined.get() {
|
||||
ImageLayout::UNDEFINED
|
||||
} else {
|
||||
ImageLayout::GENERAL
|
||||
})
|
||||
.new_layout(ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
||||
.dst_access_mask(AccessFlags2::COLOR_ATTACHMENT_WRITE)
|
||||
.dst_stage_mask(PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT)
|
||||
.build();
|
||||
.dst_access_mask(
|
||||
AccessFlags2::COLOR_ATTACHMENT_WRITE | AccessFlags2::COLOR_ATTACHMENT_READ,
|
||||
)
|
||||
.dst_stage_mask(PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT);
|
||||
if fb.bridge.is_some() {
|
||||
fb_image_memory_barrier = fb_image_memory_barrier
|
||||
.src_access_mask(AccessFlags2::TRANSFER_READ)
|
||||
.src_stage_mask(PipelineStageFlags2::TRANSFER)
|
||||
.old_layout(if fb.is_undefined.get() {
|
||||
ImageLayout::UNDEFINED
|
||||
} else {
|
||||
ImageLayout::TRANSFER_SRC_OPTIMAL
|
||||
});
|
||||
} else {
|
||||
fb_image_memory_barrier = fb_image_memory_barrier
|
||||
.src_queue_family_index(QUEUE_FAMILY_FOREIGN_EXT)
|
||||
.dst_queue_family_index(self.device.graphics_queue_idx)
|
||||
.old_layout(if fb.is_undefined.get() {
|
||||
ImageLayout::UNDEFINED
|
||||
} else {
|
||||
ImageLayout::GENERAL
|
||||
});
|
||||
}
|
||||
let fb_image_memory_barrier = fb_image_memory_barrier.build();
|
||||
memory.image_barriers.push(fb_image_memory_barrier);
|
||||
for img in &memory.sample {
|
||||
let image_memory_barrier = image_barrier()
|
||||
|
|
@ -542,22 +557,95 @@ impl VulkanRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
fn copy_bridge_to_dmabuf(&self, buf: CommandBuffer, fb: &VulkanImage) {
|
||||
let Some(bridge) = &fb.bridge else {
|
||||
return;
|
||||
};
|
||||
let mut memory = self.memory.borrow_mut();
|
||||
let memory = &mut *memory;
|
||||
memory.image_barriers.clear();
|
||||
let bridge_image_memory_barrier = image_barrier()
|
||||
.image(fb.image)
|
||||
.old_layout(ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
||||
.new_layout(ImageLayout::TRANSFER_SRC_OPTIMAL)
|
||||
.src_access_mask(
|
||||
AccessFlags2::COLOR_ATTACHMENT_WRITE | AccessFlags2::COLOR_ATTACHMENT_READ,
|
||||
)
|
||||
.src_stage_mask(PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT)
|
||||
.dst_access_mask(AccessFlags2::TRANSFER_READ)
|
||||
.dst_stage_mask(PipelineStageFlags2::TRANSFER)
|
||||
.build();
|
||||
memory.image_barriers.push(bridge_image_memory_barrier);
|
||||
let dmabuf_image_memory_barrier = image_barrier()
|
||||
.src_queue_family_index(QUEUE_FAMILY_FOREIGN_EXT)
|
||||
.dst_queue_family_index(self.device.graphics_queue_idx)
|
||||
.image(bridge.dmabuf_image)
|
||||
.old_layout(if fb.is_undefined.get() {
|
||||
ImageLayout::UNDEFINED
|
||||
} else {
|
||||
ImageLayout::GENERAL
|
||||
})
|
||||
.new_layout(ImageLayout::TRANSFER_DST_OPTIMAL)
|
||||
.dst_access_mask(AccessFlags2::TRANSFER_WRITE)
|
||||
.dst_stage_mask(PipelineStageFlags2::TRANSFER)
|
||||
.build();
|
||||
memory.image_barriers.push(dmabuf_image_memory_barrier);
|
||||
let dep_info = DependencyInfoKHR::builder().image_memory_barriers(&memory.image_barriers);
|
||||
unsafe {
|
||||
self.device.device.cmd_pipeline_barrier2(buf, &dep_info);
|
||||
}
|
||||
let image_subresource_layers = ImageSubresourceLayers::builder()
|
||||
.aspect_mask(ImageAspectFlags::COLOR)
|
||||
.layer_count(1)
|
||||
.base_array_layer(0)
|
||||
.mip_level(0)
|
||||
.build();
|
||||
let image_copy = ImageCopy2::builder()
|
||||
.src_subresource(image_subresource_layers)
|
||||
.dst_subresource(image_subresource_layers)
|
||||
.extent(Extent3D {
|
||||
width: fb.width,
|
||||
height: fb.height,
|
||||
depth: 1,
|
||||
})
|
||||
.build();
|
||||
let copy_image_info = CopyImageInfo2::builder()
|
||||
.src_image(fb.image)
|
||||
.src_image_layout(ImageLayout::TRANSFER_SRC_OPTIMAL)
|
||||
.dst_image(bridge.dmabuf_image)
|
||||
.dst_image_layout(ImageLayout::TRANSFER_DST_OPTIMAL)
|
||||
.regions(slice::from_ref(&image_copy))
|
||||
.build();
|
||||
unsafe {
|
||||
self.device.device.cmd_copy_image2(buf, ©_image_info);
|
||||
}
|
||||
}
|
||||
|
||||
fn final_barriers(&self, buf: CommandBuffer, fb: &VulkanImage) {
|
||||
let mut memory = self.memory.borrow_mut();
|
||||
let memory = &mut *memory;
|
||||
memory.image_barriers.clear();
|
||||
memory.shm_barriers.clear();
|
||||
let fb_image_memory_barrier = image_barrier()
|
||||
let mut fb_image_memory_barrier = image_barrier()
|
||||
.src_queue_family_index(self.device.graphics_queue_idx)
|
||||
.dst_queue_family_index(QUEUE_FAMILY_FOREIGN_EXT)
|
||||
.image(fb.image)
|
||||
.old_layout(ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
||||
.new_layout(ImageLayout::GENERAL)
|
||||
.src_access_mask(
|
||||
AccessFlags2::COLOR_ATTACHMENT_WRITE | AccessFlags2::COLOR_ATTACHMENT_READ,
|
||||
)
|
||||
.src_stage_mask(PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT)
|
||||
.build();
|
||||
.new_layout(ImageLayout::GENERAL);
|
||||
if let Some(bridge) = &fb.bridge {
|
||||
fb_image_memory_barrier = fb_image_memory_barrier
|
||||
.image(bridge.dmabuf_image)
|
||||
.old_layout(ImageLayout::TRANSFER_DST_OPTIMAL)
|
||||
.src_access_mask(AccessFlags2::TRANSFER_WRITE)
|
||||
.src_stage_mask(PipelineStageFlags2::TRANSFER);
|
||||
} else {
|
||||
fb_image_memory_barrier = fb_image_memory_barrier
|
||||
.image(fb.image)
|
||||
.old_layout(ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
||||
.src_access_mask(
|
||||
AccessFlags2::COLOR_ATTACHMENT_WRITE | AccessFlags2::COLOR_ATTACHMENT_READ,
|
||||
)
|
||||
.src_stage_mask(PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT);
|
||||
}
|
||||
let fb_image_memory_barrier = fb_image_memory_barrier.build();
|
||||
memory.image_barriers.push(fb_image_memory_barrier);
|
||||
for img in &memory.sample {
|
||||
let image_memory_barrier = image_barrier()
|
||||
|
|
@ -828,31 +916,28 @@ impl VulkanRenderer {
|
|||
})
|
||||
.build();
|
||||
let staging = self.create_staging_buffer(size, false, true, true)?;
|
||||
let initial_tex_barrier = image_barrier()
|
||||
.src_queue_family_index(QUEUE_FAMILY_FOREIGN_EXT)
|
||||
.dst_queue_family_index(self.device.graphics_queue_idx)
|
||||
.image(tex.image)
|
||||
.old_layout(ImageLayout::GENERAL)
|
||||
.new_layout(ImageLayout::TRANSFER_SRC_OPTIMAL)
|
||||
.dst_access_mask(AccessFlags2::TRANSFER_READ)
|
||||
.dst_stage_mask(PipelineStageFlags2::TRANSFER);
|
||||
let initial_tex_barrier;
|
||||
let initial_buffer_barrier = BufferMemoryBarrier2::builder()
|
||||
.buffer(staging.buffer)
|
||||
.offset(0)
|
||||
.size(staging.size)
|
||||
.dst_access_mask(AccessFlags2::TRANSFER_WRITE)
|
||||
.dst_stage_mask(PipelineStageFlags2::TRANSFER);
|
||||
let initial_barriers = DependencyInfo::builder()
|
||||
.buffer_memory_barriers(slice::from_ref(&initial_buffer_barrier))
|
||||
.image_memory_barriers(slice::from_ref(&initial_tex_barrier));
|
||||
let final_tex_barrier = image_barrier()
|
||||
.src_queue_family_index(self.device.graphics_queue_idx)
|
||||
.dst_queue_family_index(QUEUE_FAMILY_FOREIGN_EXT)
|
||||
.image(tex.image)
|
||||
.old_layout(ImageLayout::TRANSFER_SRC_OPTIMAL)
|
||||
.new_layout(ImageLayout::GENERAL)
|
||||
.src_access_mask(AccessFlags2::TRANSFER_READ)
|
||||
.src_stage_mask(PipelineStageFlags2::TRANSFER);
|
||||
let mut initial_barriers = DependencyInfo::builder()
|
||||
.buffer_memory_barriers(slice::from_ref(&initial_buffer_barrier));
|
||||
if tex.bridge.is_none() {
|
||||
initial_tex_barrier = image_barrier()
|
||||
.src_queue_family_index(QUEUE_FAMILY_FOREIGN_EXT)
|
||||
.dst_queue_family_index(self.device.graphics_queue_idx)
|
||||
.image(tex.image)
|
||||
.old_layout(ImageLayout::GENERAL)
|
||||
.new_layout(ImageLayout::TRANSFER_SRC_OPTIMAL)
|
||||
.dst_access_mask(AccessFlags2::TRANSFER_READ)
|
||||
.dst_stage_mask(PipelineStageFlags2::TRANSFER);
|
||||
initial_barriers =
|
||||
initial_barriers.image_memory_barriers(slice::from_ref(&initial_tex_barrier));
|
||||
}
|
||||
let final_tex_barrier;
|
||||
let final_buffer_barrier = BufferMemoryBarrier2::builder()
|
||||
.buffer(staging.buffer)
|
||||
.offset(0)
|
||||
|
|
@ -861,9 +946,20 @@ impl VulkanRenderer {
|
|||
.src_stage_mask(PipelineStageFlags2::TRANSFER)
|
||||
.dst_access_mask(AccessFlags2::HOST_READ)
|
||||
.dst_stage_mask(PipelineStageFlags2::HOST);
|
||||
let final_barriers = DependencyInfo::builder()
|
||||
.buffer_memory_barriers(slice::from_ref(&final_buffer_barrier))
|
||||
.image_memory_barriers(slice::from_ref(&final_tex_barrier));
|
||||
let mut final_barriers = DependencyInfo::builder()
|
||||
.buffer_memory_barriers(slice::from_ref(&final_buffer_barrier));
|
||||
if tex.bridge.is_none() {
|
||||
final_tex_barrier = image_barrier()
|
||||
.src_queue_family_index(self.device.graphics_queue_idx)
|
||||
.dst_queue_family_index(QUEUE_FAMILY_FOREIGN_EXT)
|
||||
.image(tex.image)
|
||||
.old_layout(ImageLayout::TRANSFER_SRC_OPTIMAL)
|
||||
.new_layout(ImageLayout::GENERAL)
|
||||
.src_access_mask(AccessFlags2::TRANSFER_READ)
|
||||
.src_stage_mask(PipelineStageFlags2::TRANSFER);
|
||||
final_barriers =
|
||||
final_barriers.image_memory_barriers(slice::from_ref(&final_tex_barrier));
|
||||
}
|
||||
let buf = self.allocate_command_buffer()?;
|
||||
let mut semaphores = vec![];
|
||||
let mut semaphore_infos = vec![];
|
||||
|
|
@ -985,6 +1081,7 @@ impl VulkanRenderer {
|
|||
self.set_viewport(buf.buffer, fb);
|
||||
self.record_draws(buf.buffer, opts)?;
|
||||
self.end_rendering(buf.buffer);
|
||||
self.copy_bridge_to_dmabuf(buf.buffer, fb);
|
||||
self.final_barriers(buf.buffer, fb);
|
||||
self.end_command_buffer(buf.buffer)?;
|
||||
self.create_wait_semaphores(fb)?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue