diff --git a/src/dxvk/dxvk_image.h b/src/dxvk/dxvk_image.h index cb181012..37c462b6 100644 --- a/src/dxvk/dxvk_image.h +++ b/src/dxvk/dxvk_image.h @@ -212,6 +212,16 @@ namespace dxvk { return util::computeMipLevelExtent(m_info.extent, level); } + /** + * \brief Size of a mipmap level + * + * \param [in] level Mip level + * \returns Size of that level + */ + VkExtent3D mipLevelExtent(uint32_t level, VkImageAspectFlags aspect) const { + return util::computeMipLevelExtent(m_info.extent, level, m_info.format, aspect); + } + /** * \brief Queries memory layout of a subresource * @@ -402,7 +412,7 @@ namespace dxvk { * \returns Size of that level */ VkExtent3D mipLevelExtent(uint32_t level) const { - return m_image->mipLevelExtent(level + m_info.minLevel); + return m_image->mipLevelExtent(level + m_info.minLevel, m_info.aspect); } /** diff --git a/src/dxvk/dxvk_util.h b/src/dxvk/dxvk_util.h index 06715570..11a513f2 100644 --- a/src/dxvk/dxvk_util.h +++ b/src/dxvk/dxvk_util.h @@ -101,6 +101,29 @@ namespace dxvk::util { return size; } + /** + * \brief Computes mip level extent + * + * This function variant takes into account planar formats. + * \param [in] size Base mip level extent + * \param [in] level Mip level to compute + * \param [in] format Image format + * \param [in] aspect Image aspect to consider + * \returns Extent of the given mip level + */ + inline VkExtent3D computeMipLevelExtent(VkExtent3D size, uint32_t level, VkFormat format, VkImageAspectFlags aspect) { + if (unlikely(!(aspect & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)))) { + auto plane = &imageFormatInfo(format)->planes[vk::getPlaneIndex(aspect)]; + size.width /= plane->blockSize.width; + size.height /= plane->blockSize.height; + } + + size.width = std::max(1u, size.width >> level); + size.height = std::max(1u, size.height >> level); + size.depth = std::max(1u, size.depth >> level); + return size; + } + /** * \brief Computes block offset for compressed images * diff --git a/src/vulkan/vulkan_util.h b/src/vulkan/vulkan_util.h index 2cbd20be..1d517b14 100644 --- a/src/vulkan/vulkan_util.h +++ b/src/vulkan/vulkan_util.h @@ -97,6 +97,29 @@ namespace dxvk::vk { } } + inline uint32_t getPlaneCount(VkImageAspectFlags aspects) { + // Use a 16-bit integer as a lookup table. This works because + // plane aspects use consecutive bits in the image aspect enum. + const uint32_t shift = (aspects / VK_IMAGE_ASPECT_PLANE_0_BIT) * 2; + const uint32_t counts = 0xffa5; + return (counts >> shift) & 0x3; + } + + inline uint32_t getPlaneIndex(VkImageAspectFlags aspect) { + // Works for up to PLANE_2_BIT due to enum poperties + return aspect / VK_IMAGE_ASPECT_PLANE_1_BIT; + } + + inline VkImageAspectFlagBits getPlaneAspect(uint32_t plane) { + return VkImageAspectFlagBits(VK_IMAGE_ASPECT_PLANE_0_BIT << plane); + } + + inline VkImageAspectFlags getNextAspect(VkImageAspectFlags& mask) { + VkImageAspectFlags result = mask & -mask; + mask &= ~result; + return result; + } + }