rhi: vulkan: Fix multisample resolve with multiview

Task-number: QTBUG-114790
Change-Id: I3afccc3f7ae2d05aa9aa0e0943aeadc080016f0e
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
Laszlo Agocs 2023-06-22 11:23:28 +02:00
parent 003c29511d
commit 2f619c2ddf
2 changed files with 36 additions and 7 deletions

View File

@ -2284,16 +2284,40 @@ QRhiColorAttachment::QRhiColorAttachment(QRhiRenderBuffer *renderBuffer)
\nullptr if there is none.
Setting a non-null resolve texture is applicable when the attachment
references a multisample, color renderbuffer. (i.e., renderBuffer() is set)
The QRhiTexture in the resolveTexture() is then a regular, 2D,
non-multisample texture with the same size (but a sample count of 1). The
multisample content is automatically resolved into this texture at the end
of each render pass.
references a multisample texture or renderbuffer. The QRhiTexture in the
resolveTexture() is then a non-multisample 2D texture (or texture array)
with the same size (but a sample count of 1). The multisample content is
automatically resolved into this texture at the end of each render pass.
*/
/*!
\fn void QRhiColorAttachment::setResolveTexture(QRhiTexture *tex)
Sets the resolve texture \a tex.
\a tex is expected to be a 2D texture or a 2D texture array. In either
case, resolving targets a single mip level of a single layer (array
element) of \a tex. The mip level and array layer are specified by
resolveLevel() and resolveLayer().
An exception is \l{setMultiViewCount()}{multiview}: when the color
attachment is associated with a texture array and multiview is enabled, the
resolve texture must also be a texture array with sufficient elements for
all views. In this case all elements that correspond to views are resolved
automatically; the behavior is similar to the following pseudo-code:
\badcode
for (i = 0; i < multiViewCount(); ++i)
resolve texture's layer() + i into resolveTexture's resolveLayer() + i
\endcode
Setting a non-multisample texture to resolve a multisample texture or
renderbuffer automatically at the end of the render pass is often
preferable to working with multisample textures (and not setting a resolve
texture), because it avoids the need for writing dedicated fragment shaders
that work exclusively with multisample textures (\c sampler2DMS, \c
texelFetch, etc.), and rather allows using the same shader as one would if
the attachment's texture was not multisampled to begin with. This comes at
the expense of an additional resource (the non-multisample \a tex).
*/
/*!

View File

@ -6723,6 +6723,7 @@ bool QVkTextureRenderTarget::create()
QRHI_RES_RHI(QRhiVulkan);
QVarLengthArray<VkImageView, 8> views;
uint32_t multiViewCount = 0;
d.colorAttCount = 0;
int attIndex = 0;
@ -6735,6 +6736,8 @@ bool QVkTextureRenderTarget::create()
Q_ASSERT(texD->flags().testFlag(QRhiTexture::RenderTarget));
const bool is1D = texD->flags().testFlag(QRhiTexture::OneDimensional);
const bool isMultiView = it->multiViewCount() >= 2;
if (isMultiView && multiViewCount == 0)
multiViewCount = uint32_t(it->multiViewCount());
VkImageViewCreateInfo viewInfo = {};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = texD->image;
@ -6795,6 +6798,7 @@ bool QVkTextureRenderTarget::create()
d.resolveAttCount = 0;
attIndex = 0;
Q_ASSERT(multiViewCount == 0 || multiViewCount >= 2);
for (auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
if (it->resolveTexture()) {
QVkTexture *resTexD = QRHI_RES(QVkTexture, it->resolveTexture());
@ -6804,7 +6808,8 @@ bool QVkTextureRenderTarget::create()
VkImageViewCreateInfo viewInfo = {};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = resTexD->image;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.viewType = multiViewCount ? VK_IMAGE_VIEW_TYPE_2D_ARRAY
: VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = resTexD->vkformat;
viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
@ -6814,7 +6819,7 @@ bool QVkTextureRenderTarget::create()
viewInfo.subresourceRange.baseMipLevel = uint32_t(it->resolveLevel());
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = uint32_t(it->resolveLayer());
viewInfo.subresourceRange.layerCount = 1;
viewInfo.subresourceRange.layerCount = qMax(1u, multiViewCount);
VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &resrtv[attIndex]);
if (err != VK_SUCCESS) {
qWarning("Failed to create render target resolve image view: %d", err);