rhi: vulkan: remove the VK_IMAGE_ASPECT_STENCIL_BIT for depth textures

Never set the VK_IMAGE_ASPECT_STENCIL_BIT aspect mask when creating
texture ImageViews.

If both the depth and stencil aspects are needed in the descriptor set,
we would probably need to create two separate image views, e.g.:
    // Depth
    vkCreateImageView(rhiD->dev, &depthViewInfo, nullptr, &dv);
    views.append(dv);
    // Stencil
    VkImageViewCreateInfo stencilViewInfo = depthViewInfo;
    stencilViewInfo.subresourceRange.aspectMask =
VK_IMAGE_ASPECT_STENCIL_BIT;
    vkCreateImageView(rhiD->dev, &stencilViewInfo, nullptr, &sv);
    views.append(sv);

These are the two errors faced with a D32 and D24S8 texture:

vkCreateImageView():  Using format (VK_FORMAT_D32_SFLOAT) with aspect
flags (VK_IMAGE_ASPECT_DEPTH_BIT|VK_IMAGE_ASPECT_STENCIL_BIT) but depth-
only image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT set. The
Vulkan spec states: subresourceRange.aspectMask must be valid for the
format the image was created with (https://www.khronos.org/registry/
vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkImageViewCreateInfo-
subresourceRange-09594)

vkUpdateDescriptorSets(): pDescriptorWrites[2].pImageInfo[0].imageView
use layout VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL and the image format
(VK_FORMAT_D24_UNORM_S8_UINT), but it has both STENCIL and DEPTH aspects
set. The Vulkan spec states: If imageView is created from a depth/
stencil image, the aspectMask used to create the imageView must include
either VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT but not
both (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/
vkspec.html#VUID-VkDescriptorImageInfo-imageView-01976) The doc indeed
states that: When using an image view of a depth/stencil image to
populate a descriptor set (e.g. for sampling in the shader, or for use
as an input attachment), the aspectMask must only include one bit, which
selects whether the image view is used for depth reads (i.e. using a
floating-point sampler or input attachment in the shader) or stencil
reads (i.e. using an unsigned integer sampler or input attachment in the
shader).

Pick-to: 6.7 6.8
Change-Id: Ic35ead318fb1130eaa8f9ff3585da38e32566b95
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
Aurélien Brooke 2024-07-11 15:09:36 +02:00 committed by Laszlo Agocs
parent 8a27c310b1
commit afe38ba7ab

View File

@ -1302,9 +1302,28 @@ static constexpr inline bool isDepthTextureFormat(QRhiTexture::Format format)
}
}
static constexpr inline bool isStencilTextureFormat(QRhiTexture::Format format)
{
switch (format) {
case QRhiTexture::Format::D24S8:
case QRhiTexture::Format::D32FS8:
return true;
default:
return false;
}
}
static constexpr inline VkImageAspectFlags aspectMaskForTextureFormat(QRhiTexture::Format format)
{
return isDepthTextureFormat(format) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
if (isDepthTextureFormat(format)) {
if (isStencilTextureFormat(format))
return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
else
return VK_IMAGE_ASPECT_DEPTH_BIT;
} else {
return VK_IMAGE_ASPECT_COLOR_BIT;
}
}
// Transient images ("render buffers") backed by lazily allocated memory are
@ -6991,6 +7010,9 @@ bool QVkTexture::finishCreate()
viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
viewInfo.subresourceRange.aspectMask = aspectMask;
// Force-remove the VK_IMAGE_ASPECT_STENCIL_BIT
// Another view with this bit is probably needed for stencil
viewInfo.subresourceRange.aspectMask &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
viewInfo.subresourceRange.levelCount = mipLevelCount;
if (isArray && m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
viewInfo.subresourceRange.baseArrayLayer = uint32_t(m_arrayRangeStart);
@ -7695,7 +7717,7 @@ bool QVkTextureRenderTarget::create()
viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
viewInfo.subresourceRange.aspectMask = aspectMaskForTextureFormat(depthTexD->format());
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.layerCount = qMax<uint32_t>(1, d.multiViewCount);
VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &dsv);
@ -7768,7 +7790,7 @@ bool QVkTextureRenderTarget::create()
viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
viewInfo.subresourceRange.aspectMask = aspectMaskForTextureFormat(resTexD->format());
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0;