vulkan: don't try to export non-exportable images
This commit is contained in:
parent
588fce4832
commit
591867ffbd
6 changed files with 68 additions and 61 deletions
|
|
@ -718,19 +718,21 @@ fn validate_modifier(
|
|||
return false;
|
||||
}
|
||||
}
|
||||
let Some(max_extents) = modifier.transfer_max_extents else {
|
||||
let Some(limits) = modifier.transfer_limits else {
|
||||
return false;
|
||||
};
|
||||
let mut max_width = max_extents.width;
|
||||
let mut max_height = max_extents.height;
|
||||
let mut max_width = limits.max_width;
|
||||
let mut max_height = limits.max_height;
|
||||
let mut exportable = limits.exportable;
|
||||
if usage.contains(BO_USE_RENDERING) {
|
||||
let Some(max_extents) = modifier.render_max_extents else {
|
||||
let Some(limits) = modifier.render_limits else {
|
||||
return false;
|
||||
};
|
||||
max_width = max_width.min(max_extents.width);
|
||||
max_height = max_height.min(max_extents.height);
|
||||
max_width = max_width.min(limits.max_width);
|
||||
max_height = max_height.min(limits.max_height);
|
||||
exportable &= limits.exportable;
|
||||
}
|
||||
if width > max_width || height > max_height {
|
||||
if !exportable || width > max_width || height > max_height {
|
||||
return false;
|
||||
}
|
||||
true
|
||||
|
|
|
|||
|
|
@ -262,8 +262,8 @@ impl VulkanInstance {
|
|||
let mut supports_rendering = false;
|
||||
let mut supports_texturing = false;
|
||||
f.modifiers.values().for_each(|v| {
|
||||
supports_rendering |= v.render_max_extents.is_some();
|
||||
supports_texturing |= v.texture_max_extents.is_some();
|
||||
supports_rendering |= v.render_limits.is_some();
|
||||
supports_texturing |= v.texture_limits.is_some();
|
||||
});
|
||||
supports_rendering && supports_texturing
|
||||
})
|
||||
|
|
|
|||
|
|
@ -32,21 +32,22 @@ pub struct VulkanModifier {
|
|||
pub modifier: Modifier,
|
||||
pub planes: usize,
|
||||
pub features: FormatFeatureFlags,
|
||||
pub render_max_extents: Option<VulkanMaxExtents>,
|
||||
pub texture_max_extents: Option<VulkanMaxExtents>,
|
||||
pub transfer_max_extents: Option<VulkanMaxExtents>,
|
||||
pub render_limits: Option<VulkanModifierLimits>,
|
||||
pub texture_limits: Option<VulkanModifierLimits>,
|
||||
pub transfer_limits: Option<VulkanModifierLimits>,
|
||||
pub render_needs_bridge: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct VulkanMaxExtents {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
pub struct VulkanModifierLimits {
|
||||
pub max_width: u32,
|
||||
pub max_height: u32,
|
||||
pub exportable: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VulkanInternalFormat {
|
||||
pub max_extents: VulkanMaxExtents,
|
||||
pub limits: VulkanModifierLimits,
|
||||
}
|
||||
|
||||
const FRAMEBUFFER_FEATURES: FormatFeatureFlags = FormatFeatureFlags::from_raw(
|
||||
|
|
@ -168,9 +169,10 @@ impl VulkanInstance {
|
|||
};
|
||||
}
|
||||
Ok(Some(VulkanInternalFormat {
|
||||
max_extents: VulkanMaxExtents {
|
||||
width: format_properties.image_format_properties.max_extent.width,
|
||||
height: format_properties.image_format_properties.max_extent.height,
|
||||
limits: VulkanModifierLimits {
|
||||
max_width: format_properties.image_format_properties.max_extent.width,
|
||||
max_height: format_properties.image_format_properties.max_extent.height,
|
||||
exportable: false,
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
|
@ -201,16 +203,16 @@ impl VulkanInstance {
|
|||
};
|
||||
let mut mods = AHashMap::new();
|
||||
for modifier in drm_mods {
|
||||
let mut render_max_extents = self.get_max_extents(
|
||||
let mut render_limits = self.get_max_extents(
|
||||
phy_dev,
|
||||
format,
|
||||
FRAMEBUFFER_FEATURES,
|
||||
FRAMEBUFFER_USAGE,
|
||||
&modifier,
|
||||
)?;
|
||||
let texture_max_extents =
|
||||
let texture_limits =
|
||||
self.get_max_extents(phy_dev, format, TEX_FEATURES, TEX_USAGE, &modifier)?;
|
||||
let transfer_max_extents = self.get_max_extents(
|
||||
let transfer_limits = self.get_max_extents(
|
||||
phy_dev,
|
||||
format,
|
||||
TRANSFER_FEATURES,
|
||||
|
|
@ -218,14 +220,14 @@ impl VulkanInstance {
|
|||
&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(
|
||||
if render_limits.is_none() && modifier.drm_format_modifier == LINEAR_MODIFIER {
|
||||
render_limits = self.get_fb_bridged_max_extents(
|
||||
phy_dev,
|
||||
format,
|
||||
internal_format_properties,
|
||||
&modifier,
|
||||
)?;
|
||||
if render_max_extents.is_some() {
|
||||
if render_limits.is_some() {
|
||||
render_needs_bridge = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -235,9 +237,9 @@ impl VulkanInstance {
|
|||
modifier: modifier.drm_format_modifier,
|
||||
planes: modifier.drm_format_modifier_plane_count as _,
|
||||
features: modifier.drm_format_modifier_tiling_features,
|
||||
render_max_extents,
|
||||
texture_max_extents,
|
||||
transfer_max_extents,
|
||||
render_limits,
|
||||
texture_limits,
|
||||
transfer_limits,
|
||||
render_needs_bridge,
|
||||
},
|
||||
);
|
||||
|
|
@ -251,7 +253,7 @@ impl VulkanInstance {
|
|||
format: &Format,
|
||||
internal_format_properties: &FormatProperties,
|
||||
modifier: &DrmFormatModifierPropertiesEXT,
|
||||
) -> Result<Option<VulkanMaxExtents>, VulkanError> {
|
||||
) -> Result<Option<VulkanModifierLimits>, VulkanError> {
|
||||
let transfer_dst_max_extents = self.get_max_extents(
|
||||
phy_dev,
|
||||
format,
|
||||
|
|
@ -272,15 +274,16 @@ impl VulkanInstance {
|
|||
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,
|
||||
Ok(Some(VulkanModifierLimits {
|
||||
max_width: min(
|
||||
transfer_dst_max_extents.max_width,
|
||||
bridge_format.limits.max_width,
|
||||
),
|
||||
height: min(
|
||||
transfer_dst_max_extents.height,
|
||||
bridge_format.max_extents.height,
|
||||
max_height: min(
|
||||
transfer_dst_max_extents.max_height,
|
||||
bridge_format.limits.max_height,
|
||||
),
|
||||
exportable: transfer_dst_max_extents.exportable,
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
@ -291,7 +294,7 @@ impl VulkanInstance {
|
|||
features: FormatFeatureFlags,
|
||||
usage: ImageUsageFlags,
|
||||
props: &DrmFormatModifierPropertiesEXT,
|
||||
) -> Result<Option<VulkanMaxExtents>, VulkanError> {
|
||||
) -> Result<Option<VulkanModifierLimits>, VulkanError> {
|
||||
if !props.drm_format_modifier_tiling_features.contains(features) {
|
||||
return Ok(None);
|
||||
}
|
||||
|
|
@ -327,17 +330,19 @@ impl VulkanInstance {
|
|||
};
|
||||
}
|
||||
let image_format_props = &image_format_props.image_format_properties;
|
||||
let importable = external_image_format_props
|
||||
let external_memory_features = &external_image_format_props
|
||||
.external_memory_properties
|
||||
.external_memory_features
|
||||
.contains(ExternalMemoryFeatureFlags::IMPORTABLE);
|
||||
.external_memory_features;
|
||||
let importable = external_memory_features.contains(ExternalMemoryFeatureFlags::IMPORTABLE);
|
||||
if !importable {
|
||||
return Ok(None);
|
||||
}
|
||||
let exportable = external_memory_features.contains(ExternalMemoryFeatureFlags::EXPORTABLE);
|
||||
|
||||
Ok(Some(VulkanMaxExtents {
|
||||
width: image_format_props.max_extent.width,
|
||||
height: image_format_props.max_extent.height,
|
||||
Ok(Some(VulkanModifierLimits {
|
||||
max_width: image_format_props.max_extent.width,
|
||||
max_height: image_format_props.max_extent.height,
|
||||
exportable,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use {
|
|||
format::Format,
|
||||
gfx_api::{GfxApiOpt, GfxError, GfxFramebuffer, GfxImage, GfxTexture, SyncFile},
|
||||
gfx_apis::vulkan::{
|
||||
allocator::VulkanAllocation, device::VulkanDevice, format::VulkanMaxExtents,
|
||||
allocator::VulkanAllocation, device::VulkanDevice, format::VulkanModifierLimits,
|
||||
renderer::VulkanRenderer, shm_image::VulkanShmImage, util::OnDrop, VulkanError,
|
||||
},
|
||||
theme::Color,
|
||||
|
|
@ -36,8 +36,8 @@ pub struct VulkanDmaBufImageTemplate {
|
|||
pub(super) height: u32,
|
||||
pub(super) disjoint: bool,
|
||||
pub(super) dmabuf: DmaBuf,
|
||||
pub(super) render_max_extents: Option<VulkanMaxExtents>,
|
||||
pub(super) texture_max_extents: Option<VulkanMaxExtents>,
|
||||
pub(super) render_limits: Option<VulkanModifierLimits>,
|
||||
pub(super) texture_limits: Option<VulkanModifierLimits>,
|
||||
pub(super) render_needs_bridge: bool,
|
||||
}
|
||||
|
||||
|
|
@ -124,16 +124,16 @@ impl VulkanRenderer {
|
|||
}
|
||||
let width = dmabuf.width as u32;
|
||||
let height = dmabuf.height as u32;
|
||||
let can_render = match &modifier.render_max_extents {
|
||||
let can_render = match &modifier.render_limits {
|
||||
None => false,
|
||||
Some(t) => width <= t.width && height <= t.height,
|
||||
Some(t) => width <= t.max_width && height <= t.max_height,
|
||||
};
|
||||
let can_texture = match &modifier.texture_max_extents {
|
||||
let can_texture = match &modifier.texture_limits {
|
||||
None => false,
|
||||
Some(t) => width <= t.width && height <= t.height,
|
||||
Some(t) => width <= t.max_width && height <= t.max_height,
|
||||
};
|
||||
if !can_render && !can_texture {
|
||||
if modifier.render_max_extents.is_none() && modifier.texture_max_extents.is_none() {
|
||||
if modifier.render_limits.is_none() && modifier.texture_limits.is_none() {
|
||||
return Err(VulkanError::ModifierUseNotSupported);
|
||||
}
|
||||
return Err(VulkanError::ImageTooLarge);
|
||||
|
|
@ -151,8 +151,8 @@ impl VulkanRenderer {
|
|||
height,
|
||||
disjoint,
|
||||
dmabuf: dmabuf.clone(),
|
||||
render_max_extents: modifier.render_max_extents,
|
||||
texture_max_extents: modifier.texture_max_extents,
|
||||
render_limits: modifier.render_limits,
|
||||
texture_limits: modifier.texture_limits,
|
||||
render_needs_bridge: modifier.render_needs_bridge,
|
||||
}))
|
||||
}
|
||||
|
|
@ -201,12 +201,12 @@ impl VulkanDmaBufImageTemplate {
|
|||
|
||||
fn create_image(self: &Rc<Self>, for_rendering: bool) -> Result<Rc<VulkanImage>, VulkanError> {
|
||||
let device = &self.renderer.device;
|
||||
let max_extents = match for_rendering {
|
||||
true => self.render_max_extents,
|
||||
false => self.texture_max_extents,
|
||||
let limits = match for_rendering {
|
||||
true => self.render_limits,
|
||||
false => self.texture_limits,
|
||||
};
|
||||
let max_extents = max_extents.ok_or(VulkanError::ModifierUseNotSupported)?;
|
||||
if self.width > max_extents.width || self.height > max_extents.height {
|
||||
let limits = limits.ok_or(VulkanError::ModifierUseNotSupported)?;
|
||||
if self.width > limits.max_width || self.height > limits.max_height {
|
||||
return Err(VulkanError::ImageTooLarge);
|
||||
}
|
||||
let image = {
|
||||
|
|
|
|||
|
|
@ -151,13 +151,13 @@ impl VulkanDevice {
|
|||
read_modifiers: vk
|
||||
.modifiers
|
||||
.values()
|
||||
.filter(|m| m.texture_max_extents.is_some())
|
||||
.filter(|m| m.texture_limits.is_some())
|
||||
.map(|m| m.modifier)
|
||||
.collect(),
|
||||
write_modifiers: vk
|
||||
.modifiers
|
||||
.values()
|
||||
.filter(|m| m.render_max_extents.is_some())
|
||||
.filter(|m| m.render_limits.is_some())
|
||||
.map(|m| m.modifier)
|
||||
.collect(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ impl VulkanRenderer {
|
|||
.get(&format.drm)
|
||||
.ok_or(VulkanError::FormatNotSupported)?;
|
||||
let shm = vk_format.shm.as_ref().ok_or(VulkanError::ShmNotSupported)?;
|
||||
if width > shm.max_extents.width || height > shm.max_extents.height {
|
||||
if width > shm.limits.max_width || height > shm.limits.max_height {
|
||||
return Err(VulkanError::ImageTooLarge);
|
||||
}
|
||||
let size = stride.checked_mul(height).ok_or(VulkanError::ShmOverflow)?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue