Make stencil_usage an Option (#2276)

* Make stencil_usage an Option

* Small doc fixes
This commit is contained in:
Rua 2023-08-09 20:23:24 +02:00 committed by GitHub
parent db0b02a954
commit 6087ae1b1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 185 additions and 203 deletions

View File

@ -969,7 +969,10 @@ impl ClearDepthStencilImageInfo {
}
if subresource_range.aspects.intersects(ImageAspects::STENCIL)
&& !image.stencil_usage().intersects(ImageUsage::TRANSFER_DST)
&& !image
.stencil_usage()
.unwrap_or(image.usage())
.intersects(ImageUsage::TRANSFER_DST)
{
return Err(Box::new(ValidationError {
problem: format!(

View File

@ -3012,6 +3012,7 @@ impl CopyImageInfo {
if src_subresource.aspects.intersects(ImageAspects::STENCIL)
&& !src_image
.stencil_usage()
.unwrap_or(src_image.usage())
.intersects(ImageUsage::TRANSFER_SRC)
{
return Err(Box::new(ValidationError {
@ -3379,6 +3380,7 @@ impl CopyImageInfo {
if dst_subresource.aspects.intersects(ImageAspects::STENCIL)
&& !dst_image
.stencil_usage()
.unwrap_or(dst_image.usage())
.intersects(ImageUsage::TRANSFER_DST)
{
return Err(Box::new(ValidationError {

View File

@ -14,8 +14,8 @@ use crate::{
device::{properties::Properties, DeviceExtensions, Features, FeaturesFfi, PropertiesFfi},
format::{DrmFormatModifierProperties, Format, FormatProperties},
image::{
ImageAspects, ImageDrmFormatModifierInfo, ImageFormatInfo, ImageFormatProperties,
ImageUsage, SparseImageFormatInfo, SparseImageFormatProperties,
ImageDrmFormatModifierInfo, ImageFormatInfo, ImageFormatProperties, ImageUsage,
SparseImageFormatInfo, SparseImageFormatProperties,
},
instance::{Instance, InstanceOwned},
macros::{impl_id_counter, vulkan_bitflags, vulkan_enum},
@ -1017,25 +1017,8 @@ impl PhysicalDevice {
#[inline]
pub unsafe fn image_format_properties_unchecked(
&self,
mut image_format_info: ImageFormatInfo,
image_format_info: ImageFormatInfo,
) -> Result<Option<ImageFormatProperties>, VulkanError> {
{
let ImageFormatInfo {
format,
usage,
stencil_usage,
..
} = &mut image_format_info;
let aspects = format.aspects();
if stencil_usage.is_empty()
|| !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
{
*stencil_usage = *usage;
}
}
self.image_format_properties
.get_or_try_insert(image_format_info, |image_format_info| {
/* Input */
@ -1052,8 +1035,6 @@ impl PhysicalDevice {
_ne: _,
} = image_format_info;
let has_separate_stencil_usage = stencil_usage != usage;
let mut info2_vk = ash::vk::PhysicalDeviceImageFormatInfo2 {
format: format.into(),
ty: image_type.into(),
@ -1121,7 +1102,7 @@ impl PhysicalDevice {
info2_vk.p_next = next as *const _ as *const _;
}
if has_separate_stencil_usage {
if let Some(stencil_usage) = stencil_usage {
let next = stencil_usage_info_vk.insert(ash::vk::ImageStencilUsageCreateInfo {
stencil_usage: stencil_usage.into(),
..Default::default()

View File

@ -217,7 +217,7 @@ impl Image {
samples: SampleCount::Sample1,
tiling: ImageTiling::Optimal,
usage: swapchain.image_usage(),
stencil_usage: swapchain.image_usage(),
stencil_usage: None,
sharing: swapchain.image_sharing().clone(),
initial_layout: ImageLayout::Undefined,
..Default::default()
@ -323,7 +323,7 @@ impl Image {
/// Returns the stencil usage the image was created with.
#[inline]
pub fn stencil_usage(&self) -> ImageUsage {
pub fn stencil_usage(&self) -> Option<ImageUsage> {
self.inner.stencil_usage()
}
@ -1668,18 +1668,14 @@ pub struct ImageFormatInfo {
/// The default value is [`ImageUsage::empty()`], which must be overridden.
pub usage: ImageUsage,
/// The `stencil_usage` that the image will have.
/// The `stencil_usage` that the image will have, if different from the regular `usage`.
///
/// If `stencil_usage` is empty or if `format` does not have both a depth and a stencil aspect,
/// then it is automatically set to equal `usage`.
///
/// If after this, `stencil_usage` does not equal `usage`,
/// then the physical device API version must be at least 1.2, or the
/// If this is `Some`, then the physical device API version must be at least 1.2, or the
/// [`ext_separate_stencil_usage`](crate::device::DeviceExtensions::ext_separate_stencil_usage)
/// extension must be supported by the physical device.
///
/// The default value is [`ImageUsage::empty()`].
pub stencil_usage: ImageUsage,
/// The default value is `None`.
pub stencil_usage: Option<ImageUsage>,
/// An external memory handle type that will be imported to or exported from the image.
///
@ -1724,7 +1720,7 @@ impl Default for ImageFormatInfo {
image_type: ImageType::Dim2d,
tiling: ImageTiling::Optimal,
usage: ImageUsage::empty(),
stencil_usage: ImageUsage::empty(),
stencil_usage: None,
external_memory_handle_type: None,
image_view_type: None,
drm_format_modifier_info: None,
@ -1744,7 +1740,7 @@ impl ImageFormatInfo {
image_type,
tiling,
usage,
mut stencil_usage,
stencil_usage,
external_memory_handle_type,
image_view_type,
ref drm_format_modifier_info,
@ -1800,28 +1796,15 @@ impl ImageFormatInfo {
}));
}
let aspects = format.aspects();
let has_separate_stencil_usage = if aspects
.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
&& !stencil_usage.is_empty()
{
stencil_usage == usage
} else {
stencil_usage = usage;
false
};
if has_separate_stencil_usage {
if let Some(stencil_usage) = stencil_usage {
if !(physical_device.api_version() >= Version::V1_2
|| physical_device
.supported_extensions()
.ext_separate_stencil_usage)
{
return Err(Box::new(ValidationError {
problem: "`stencil_usage` is `Some`, and `format` has both a depth and a \
stencil aspect"
.into(),
context: "stencil_usage".into(),
problem: "is `Some`".into(),
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::APIVersion(Version::V1_2)]),
RequiresAllOf(&[Requires::DeviceExtension("ext_separate_stencil_usage")]),
@ -1846,6 +1829,24 @@ impl ImageFormatInfo {
..Default::default()
}));
}
if stencil_usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT)
&& !(stencil_usage
- (ImageUsage::TRANSIENT_ATTACHMENT
| ImageUsage::DEPTH_STENCIL_ATTACHMENT
| ImageUsage::INPUT_ATTACHMENT))
.is_empty()
{
return Err(Box::new(ValidationError {
context: "stencil_usage".into(),
problem: "contains `ImageUsage::TRANSIENT_ATTACHMENT`, but also contains \
usages other than `ImageUsage::DEPTH_STENCIL_ATTACHMENT` or \
`ImageUsage::INPUT_ATTACHMENT`"
.into(),
vuids: &["VUID-VkImageStencilUsageCreateInfo-stencilUsage-02539"],
..Default::default()
}));
}
}
if let Some(handle_type) = external_memory_handle_type {

View File

@ -69,7 +69,7 @@ pub struct RawImage {
samples: SampleCount,
tiling: ImageTiling,
usage: ImageUsage,
stencil_usage: ImageUsage,
stencil_usage: Option<ImageUsage>,
sharing: Sharing<SmallVec<[u32; 4]>>,
initial_layout: ImageLayout,
drm_format_modifier: Option<(u64, u32)>,
@ -119,7 +119,7 @@ impl RawImage {
samples,
tiling,
usage,
mut stencil_usage,
stencil_usage,
ref sharing,
initial_layout,
external_memory_handle_types,
@ -128,17 +128,6 @@ impl RawImage {
ref drm_format_modifier_plane_layouts,
} = &create_info;
let aspects = format.aspects();
let has_separate_stencil_usage = if stencil_usage.is_empty()
|| !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
{
stencil_usage = usage;
false
} else {
stencil_usage == usage
};
let (sharing_mode, queue_family_index_count, p_queue_family_indices) = match sharing {
Sharing::Exclusive => (ash::vk::SharingMode::EXCLUSIVE, 0, &[] as _),
Sharing::Concurrent(queue_family_indices) => (
@ -232,7 +221,7 @@ impl RawImage {
info_vk.p_next = next as *const _ as *const _;
}
if has_separate_stencil_usage {
if let Some(stencil_usage) = stencil_usage {
let next = stencil_usage_info_vk.insert(ash::vk::ImageStencilUsageCreateInfo {
stencil_usage: stencil_usage.into(),
..Default::default()
@ -286,7 +275,7 @@ impl RawImage {
samples,
tiling,
usage,
mut stencil_usage,
stencil_usage,
sharing,
initial_layout,
external_memory_handle_types,
@ -317,14 +306,6 @@ impl RawImage {
format_properties.format_features(tiling, &drm_format_modifiers)
};
let format_aspects = format.aspects();
if stencil_usage.is_empty()
|| !format_aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
{
stencil_usage = usage;
}
let memory_requirements = if needs_destruction {
if flags.intersects(ImageCreateFlags::DISJOINT) {
// VUID-VkImageMemoryRequirementsInfo2-image-01589
@ -1259,7 +1240,7 @@ impl RawImage {
/// Returns the stencil usage the image was created with.
#[inline]
pub fn stencil_usage(&self) -> ImageUsage {
pub fn stencil_usage(&self) -> Option<ImageUsage> {
self.stencil_usage
}
@ -1680,18 +1661,15 @@ pub struct ImageCreateInfo {
/// The default value is [`ImageUsage::empty()`], which must be overridden.
pub usage: ImageUsage,
/// How the stencil aspect of the image is going to be used, if any.
/// How the stencil aspect of the image is going to be used, if different from the regular
/// `usage`.
///
/// If `stencil_usage` is empty or if `format` does not have both a depth and a stencil aspect,
/// then it is automatically set to equal `usage`.
///
/// If after this, `stencil_usage` does not equal `usage`,
/// then the device API version must be at least 1.2, or the
/// If this is `Some`, then the device API version must be at least 1.2, or the
/// [`ext_separate_stencil_usage`](crate::device::DeviceExtensions::ext_separate_stencil_usage)
/// extension must be enabled on the device.
/// extension must be enabled on the device. `format` must a stencil aspect.
///
/// The default value is [`ImageUsage::empty()`].
pub stencil_usage: ImageUsage,
/// The default value is `None`.
pub stencil_usage: Option<ImageUsage>,
/// Whether the image can be shared across multiple queues, or is limited to a single queue.
///
@ -1753,7 +1731,7 @@ impl Default for ImageCreateInfo {
samples: SampleCount::Sample1,
tiling: ImageTiling::Optimal,
usage: ImageUsage::empty(),
stencil_usage: ImageUsage::empty(),
stencil_usage: None,
sharing: Sharing::Exclusive,
initial_layout: ImageLayout::Undefined,
external_memory_handle_types: ExternalMemoryHandleTypes::empty(),
@ -1776,7 +1754,7 @@ impl ImageCreateInfo {
samples,
tiling,
usage,
mut stencil_usage,
stencil_usage,
ref sharing,
initial_layout,
external_memory_handle_types,
@ -1859,52 +1837,6 @@ impl ImageCreateInfo {
let image_create_format_features =
format_properties.format_features(tiling, drm_format_modifiers);
let aspects = format.aspects();
let has_separate_stencil_usage = if aspects
.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
&& !stencil_usage.is_empty()
{
stencil_usage == usage
} else {
stencil_usage = usage;
false
};
if has_separate_stencil_usage {
if !(device.api_version() >= Version::V1_2
|| device.enabled_extensions().ext_separate_stencil_usage)
{
return Err(Box::new(ValidationError {
problem: "`format` has both a depth and a stencil aspect, and `stencil_usage` \
is not empty or equal to `usage`"
.into(),
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::APIVersion(Version::V1_2)]),
RequiresAllOf(&[Requires::DeviceExtension("ext_separate_stencil_usage")]),
]),
..Default::default()
}));
}
stencil_usage
.validate_device(device)
.map_err(|err| ValidationError {
context: "stencil_usage".into(),
vuids: &["VUID-VkImageStencilUsageCreateInfo-stencilUsage-parameter"],
..ValidationError::from_requirement(err)
})?;
if stencil_usage.is_empty() {
return Err(Box::new(ValidationError {
context: "stencil_usage".into(),
problem: "is empty".into(),
vuids: &["VUID-VkImageStencilUsageCreateInfo-usage-requiredbitmask"],
..Default::default()
}));
}
}
initial_layout
.validate_device(device)
.map_err(|err| ValidationError {
@ -2178,23 +2110,18 @@ impl ImageCreateInfo {
/* Check usage requirements */
let combined_usage = usage | stencil_usage;
if combined_usage.intersects(ImageUsage::STORAGE)
if usage.intersects(ImageUsage::STORAGE)
&& samples != SampleCount::Sample1
&& !device.enabled_features().shader_storage_image_multisample
{
return Err(Box::new(ValidationError {
problem: "`usage` or `stencil_usage` contains \
`ImageUsage::STORAGE`, but `samples` is not `SampleCount::Sample1`"
problem: "`usage` contains `ImageUsage::STORAGE`, but \
`samples` is not `SampleCount::Sample1`"
.into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"shader_storage_image_multisample",
)])]),
vuids: &[
"VUID-VkImageCreateInfo-usage-00968",
"VUID-VkImageCreateInfo-format-02538",
],
vuids: &["VUID-VkImageCreateInfo-usage-00968"],
..Default::default()
}));
}
@ -2235,7 +2162,7 @@ impl ImageCreateInfo {
}
}
if combined_usage.intersects(
if usage.intersects(
ImageUsage::COLOR_ATTACHMENT
| ImageUsage::DEPTH_STENCIL_ATTACHMENT
| ImageUsage::INPUT_ATTACHMENT
@ -2243,7 +2170,7 @@ impl ImageCreateInfo {
) {
if extent[0] > device_properties.max_framebuffer_width {
return Err(Box::new(ValidationError {
problem: "`usage` or `stencil_usage` contains \
problem: "`usage` contains \
`ImageUsage::COLOR_ATTACHMENT`, \
`ImageUsage::DEPTH_STENCIL_ATTACHMENT`, \
`ImageUsage::INPUT_ATTACHMENT`, or \
@ -2260,78 +2187,47 @@ impl ImageCreateInfo {
if extent[1] > device_properties.max_framebuffer_height {
return Err(Box::new(ValidationError {
problem: "`usage` or `stencil_usage` contains \
problem: "`usage` contains \
`ImageUsage::COLOR_ATTACHMENT`, \
`ImageUsage::DEPTH_STENCIL_ATTACHMENT`, \
`ImageUsage::INPUT_ATTACHMENT`, or \
`ImageUsage::TRANSIENT_ATTACHMENT`, but \
`extent[1]` exceeds the `max_framebuffer_height` limit"
.into(),
vuids: &[
"VUID-VkImageCreateInfo-usage-00965",
"VUID-VkImageCreateInfo-format-02537",
],
vuids: &["VUID-VkImageCreateInfo-usage-00965"],
..Default::default()
}));
}
}
if has_separate_stencil_usage {
if usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
&& !stencil_usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
if let Some(stencil_usage) = stencil_usage {
if !(device.api_version() >= Version::V1_2
|| device.enabled_extensions().ext_separate_stencil_usage)
{
return Err(Box::new(ValidationError {
problem: "`format` has both a depth and a stencil aspect, and \
`stencil_usage` is not empty or equal to `usage`, and \
`usage` contains `ImageUsage::DEPTH_STENCIL_ATTACHMENT`, but \
`stencil_usage` does not also contain \
`ImageUsage::DEPTH_STENCIL_ATTACHMENT`"
.into(),
vuids: &["VUID-VkImageCreateInfo-format-02795"],
context: "stencil_usage".into(),
problem: "is `Some`".into(),
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::APIVersion(Version::V1_2)]),
RequiresAllOf(&[Requires::DeviceExtension("ext_separate_stencil_usage")]),
]),
..Default::default()
}));
}
if !usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
&& stencil_usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
{
return Err(Box::new(ValidationError {
problem: "`format` has both a depth and a stencil aspect, and \
`stencil_usage` is not empty or equal to `usage`, and \
`usage` does not contain `ImageUsage::DEPTH_STENCIL_ATTACHMENT`, but \
`stencil_usage` does contain `ImageUsage::DEPTH_STENCIL_ATTACHMENT`"
.into(),
vuids: &["VUID-VkImageCreateInfo-format-02796"],
..Default::default()
}));
}
stencil_usage
.validate_device(device)
.map_err(|err| ValidationError {
context: "stencil_usage".into(),
vuids: &["VUID-VkImageStencilUsageCreateInfo-stencilUsage-parameter"],
..ValidationError::from_requirement(err)
})?;
if usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT)
&& !stencil_usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT)
{
if stencil_usage.is_empty() {
return Err(Box::new(ValidationError {
problem: "`format` has both a depth and a stencil aspect, and \
`stencil_usage` is not empty or equal to `usage`, and \
`usage` contains `ImageUsage::TRANSIENT_ATTACHMENT`, but \
`stencil_usage` does not also contain \
`ImageUsage::TRANSIENT_ATTACHMENT`"
.into(),
vuids: &["VUID-VkImageCreateInfo-format-02797"],
..Default::default()
}));
}
if !usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT)
&& stencil_usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT)
{
return Err(Box::new(ValidationError {
problem: "`format` has both a depth and a stencil aspect, and \
`stencil_usage` is not empty or equal to `usage`, and \
`usage` does not contain `ImageUsage::TRANSIENT_ATTACHMENT`, but \
`stencil_usage` does contain \
`ImageUsage::TRANSIENT_ATTACHMENT`"
.into(),
vuids: &["VUID-VkImageCreateInfo-format-02798"],
context: "stencil_usage".into(),
problem: "is empty".into(),
vuids: &["VUID-VkImageStencilUsageCreateInfo-usage-requiredbitmask"],
..Default::default()
}));
}
@ -2344,16 +2240,115 @@ impl ImageCreateInfo {
.is_empty()
{
return Err(Box::new(ValidationError {
problem: "`format` has both a depth and a stencil aspect, and \
`stencil_usage` is not empty or equal to `usage`, and \
`stencil_usage contains `ImageUsage::TRANSIENT_ATTACHMENT`, but \
also contains usages other than `ImageUsage::DEPTH_STENCIL_ATTACHMENT` or \
context: "stencil_usage".into(),
problem: "contains `ImageUsage::TRANSIENT_ATTACHMENT`, but also contains \
usages other than `ImageUsage::DEPTH_STENCIL_ATTACHMENT` or \
`ImageUsage::INPUT_ATTACHMENT`"
.into(),
vuids: &["VUID-VkImageStencilUsageCreateInfo-stencilUsage-02539"],
..Default::default()
}));
}
if format
.aspects()
.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL)
{
if usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
&& !stencil_usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
{
return Err(Box::new(ValidationError {
problem: "`format` is a depth/stencil format, and \
`usage` contains `ImageUsage::DEPTH_STENCIL_ATTACHMENT`, but \
`stencil_usage` does not also contain \
`ImageUsage::DEPTH_STENCIL_ATTACHMENT`"
.into(),
vuids: &["VUID-VkImageCreateInfo-format-02795"],
..Default::default()
}));
}
if !usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
&& stencil_usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
{
return Err(Box::new(ValidationError {
problem: "`format` is a depth/stencil format, and \
`usage` does not contain `ImageUsage::DEPTH_STENCIL_ATTACHMENT`, but \
`stencil_usage` does contain `ImageUsage::DEPTH_STENCIL_ATTACHMENT`"
.into(),
vuids: &["VUID-VkImageCreateInfo-format-02796"],
..Default::default()
}));
}
if usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT)
&& !stencil_usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT)
{
return Err(Box::new(ValidationError {
problem: "`format` is a depth/stencil format, and \
`usage` contains `ImageUsage::TRANSIENT_ATTACHMENT`, but \
`stencil_usage` does not also contain \
`ImageUsage::TRANSIENT_ATTACHMENT`"
.into(),
vuids: &["VUID-VkImageCreateInfo-format-02797"],
..Default::default()
}));
}
if !usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT)
&& stencil_usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT)
{
return Err(Box::new(ValidationError {
problem: "`format` is a depth/stencil format, and \
`usage` does not contain `ImageUsage::TRANSIENT_ATTACHMENT`, but \
`stencil_usage` does contain \
`ImageUsage::TRANSIENT_ATTACHMENT`"
.into(),
vuids: &["VUID-VkImageCreateInfo-format-02798"],
..Default::default()
}));
}
if stencil_usage.intersects(ImageUsage::INPUT_ATTACHMENT) {
if extent[0] > device_properties.max_framebuffer_width {
return Err(Box::new(ValidationError {
problem: "`stencil_usage` contains \
`ImageUsage::INPUT_ATTACHMENT`, but \
`extent[0]` exceeds the `max_framebuffer_width` limit"
.into(),
vuids: &["VUID-VkImageCreateInfo-Format-02536"],
..Default::default()
}));
}
if extent[1] > device_properties.max_framebuffer_height {
return Err(Box::new(ValidationError {
problem: "`stencil_usage` contains \
`ImageUsage::INPUT_ATTACHMENT`, but \
`extent[1]` exceeds the `max_framebuffer_height` limit"
.into(),
vuids: &["VUID-VkImageCreateInfo-format-02537"],
..Default::default()
}));
}
}
if stencil_usage.intersects(ImageUsage::STORAGE)
&& samples != SampleCount::Sample1
&& !device.enabled_features().shader_storage_image_multisample
{
return Err(Box::new(ValidationError {
problem: "`stencil_usage` contains `ImageUsage::STORAGE`, but \
`samples` is not `SampleCount::Sample1`"
.into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"shader_storage_image_multisample",
)])]),
vuids: &["VUID-VkImageCreateInfo-format-02538"],
..Default::default()
}));
}
}
}
/* Check flags requirements */

View File

@ -1141,9 +1141,9 @@ fn get_implicit_default_usage(aspects: ImageAspects, image: &Image) -> ImageUsag
let has_non_stencil_aspect = !(aspects - ImageAspects::STENCIL).is_empty();
if has_stencil_aspect && has_non_stencil_aspect {
image.usage() & image.stencil_usage()
image.usage() & image.stencil_usage().unwrap_or(image.usage())
} else if has_stencil_aspect {
image.stencil_usage()
image.stencil_usage().unwrap_or(image.usage())
} else if has_non_stencil_aspect {
image.usage()
} else {