From 5e4c175395f305e684db6017502c0a43b8df48cc Mon Sep 17 00:00:00 2001 From: SirLynix Date: Fri, 14 Jul 2023 14:25:08 +0200 Subject: [PATCH] VulkanRenderer: Implement CommandBufferBuilder::BuildMipmaps --- .../VulkanCommandBufferBuilder.cpp | 49 ++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/src/Nazara/VulkanRenderer/VulkanCommandBufferBuilder.cpp b/src/Nazara/VulkanRenderer/VulkanCommandBufferBuilder.cpp index a3804cb35..9939d3bd6 100644 --- a/src/Nazara/VulkanRenderer/VulkanCommandBufferBuilder.cpp +++ b/src/Nazara/VulkanRenderer/VulkanCommandBufferBuilder.cpp @@ -181,9 +181,54 @@ namespace Nz void VulkanCommandBufferBuilder::BuildMipmaps(Texture& texture, UInt8 baseLevel, UInt8 maxLevel) { - VulkanTexture& vkTexture = static_cast(texture); + NazaraAssert(maxLevel >= baseLevel, "maxLevel must be greater than baseLevel"); - // TODO + VulkanTexture& vkTexture = static_cast(texture); + VkImage vkImage = vkTexture.GetImage(); + + const TextureInfo& textureInfo = vkTexture.GetTextureInfo(); + + Vector3i32 mipSize(SafeCast(textureInfo.width), SafeCast(textureInfo.height), SafeCast(textureInfo.depth)); + Vector3i32 prevMipSize = mipSize; + + std::size_t levelCount = maxLevel - baseLevel + 1; + + if (baseLevel != 0) + { + mipSize.x >>= baseLevel; + mipSize.y >>= baseLevel; + mipSize.z >>= baseLevel; + mipSize.Maximize({ 1, 1, 1 }); + } + + for (std::size_t i = 0; i < levelCount; ++i) + { + mipSize /= 2; + mipSize.Maximize({ 1, 1, 1 }); + + VkImageBlit blitRegion = { + vkTexture.BuildSubresourceLayers(i - 1), + { //< srcOffsets + { 0, 0, 0 }, + { prevMipSize.x, prevMipSize.y, prevMipSize.z } + }, + vkTexture.BuildSubresourceLayers(i), + { //< dstOffsets + { 0, 0, 0 }, + { mipSize.x, mipSize.y, mipSize.z } + }, + }; + + VkImageSubresourceRange prevMipmapRange = vkTexture.BuildSubresourceRange(i - 1, 1, 0, textureInfo.layerCount); + + m_commandBuffer.SetImageLayout(vkImage, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, prevMipmapRange); + + m_commandBuffer.BlitImage(vkImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, vkImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, blitRegion, VK_FILTER_LINEAR); + + m_commandBuffer.SetImageLayout(vkImage, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, prevMipmapRange); + + prevMipSize = mipSize; + } } void VulkanCommandBufferBuilder::CopyBuffer(const RenderBufferView& source, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset, UInt64 targetOffset)