diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index cd001d9ed0..f7785b7196 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -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). */ /*! diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index 484f304858..8f40ac192d 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -6723,6 +6723,7 @@ bool QVkTextureRenderTarget::create() QRHI_RES_RHI(QRhiVulkan); QVarLengthArray 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);