From 8c0c19c003b6747002a7337479d572c3a41fec51 Mon Sep 17 00:00:00 2001 From: Alexander Gauggel <agauggel@uni-koblenz.de> Date: Fri, 18 Jun 2021 16:30:09 +0200 Subject: [PATCH] [#55] Add ability to create image with mip chain --- include/vkcv/Core.hpp | 9 +- include/vkcv/Image.hpp | 10 +- projects/voxelization/src/Voxelization.cpp | 4 +- projects/voxelization/src/main.cpp | 10 +- src/vkcv/Core.cpp | 25 ++++- src/vkcv/Image.cpp | 12 ++- src/vkcv/ImageLayoutTransitions.cpp | 2 +- src/vkcv/ImageManager.cpp | 107 ++++++++++++--------- src/vkcv/ImageManager.hpp | 47 +++++---- 9 files changed, 148 insertions(+), 78 deletions(-) diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index 6a428194..1771fba7 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -215,7 +215,14 @@ namespace vkcv * @return Image-Object */ [[nodiscard]] - Image createImage(vk::Format format, uint32_t width, uint32_t height, uint32_t depth = 1, bool supportStorage = false, bool supportColorAttachment = false); + Image createImage( + vk::Format format, + uint32_t width, + uint32_t height, + uint32_t depth = 1, + bool createMipChain = true, + bool supportStorage = false, + bool supportColorAttachment = false); /** TODO: * @param setDescriptions diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp index 1795b63e..ef913306 100644 --- a/include/vkcv/Image.hpp +++ b/include/vkcv/Image.hpp @@ -42,7 +42,15 @@ namespace vkcv { Image(ImageManager* manager, const ImageHandle& handle); - static Image create(ImageManager* manager, vk::Format format, uint32_t width, uint32_t height, uint32_t depth, bool supportStorage, bool supportColorAttachment); + static Image create( + ImageManager* manager, + vk::Format format, + uint32_t width, + uint32_t height, + uint32_t depth, + uint32_t mipCount, + bool supportStorage, + bool supportColorAttachment); }; diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp index a6717744..b04fab9a 100644 --- a/projects/voxelization/src/Voxelization.cpp +++ b/projects/voxelization/src/Voxelization.cpp @@ -65,8 +65,8 @@ const vk::Format voxelizationDummyFormat = vk::Format::eR8Unorm; Voxelization::Voxelization(vkcv::Core* corePtr, const Dependencies& dependencies) : m_corePtr(corePtr), - m_voxelImage(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, true)), - m_dummyRenderTarget(m_corePtr->createImage(voxelizationDummyFormat, voxelResolution, voxelResolution, 1, false, true)), + m_voxelImage(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, false, true)), + m_dummyRenderTarget(m_corePtr->createImage(voxelizationDummyFormat, voxelResolution, voxelResolution, 1, false, false, true)), m_voxelInfoBuffer(m_corePtr->createBuffer<VoxelizationInfo>(vkcv::BufferType::UNIFORM, 1)), m_voxelBuffer(m_corePtr->createBuffer<VoxelBufferContent>(vkcv::BufferType::STORAGE, voxelCount)){ diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index 81d99f8a..88c55b43 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -151,7 +151,7 @@ int main(int argc, const char** argv) { ); const vk::Format shadowMapFormat = vk::Format::eD16Unorm; const uint32_t shadowMapResolution = 1024; - const vkcv::Image shadowMap = core.createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1); + const vkcv::Image shadowMap = core.createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1, false); // light info buffer struct LightInfo { @@ -225,8 +225,8 @@ int main(int argc, const char** argv) { return EXIT_FAILURE; } - vkcv::ImageHandle depthBuffer = core.createImage(depthBufferFormat, windowWidth, windowHeight).getHandle(); - vkcv::ImageHandle colorBuffer = core.createImage(colorBufferFormat, windowWidth, windowHeight, 1, true, true).getHandle(); + vkcv::ImageHandle depthBuffer = core.createImage(depthBufferFormat, windowWidth, windowHeight, 1, false).getHandle(); + vkcv::ImageHandle colorBuffer = core.createImage(colorBufferFormat, windowWidth, windowHeight, 1, false, true, true).getHandle(); const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle(); @@ -323,8 +323,8 @@ int main(int argc, const char** argv) { } if ((swapchainWidth != windowWidth) || ((swapchainHeight != windowHeight))) { - depthBuffer = core.createImage(depthBufferFormat, swapchainWidth, swapchainHeight).getHandle(); - colorBuffer = core.createImage(colorBufferFormat, swapchainWidth, swapchainHeight, 1, true, true).getHandle(); + depthBuffer = core.createImage(depthBufferFormat, swapchainWidth, swapchainHeight, 1, false).getHandle(); + colorBuffer = core.createImage(colorBufferFormat, swapchainWidth, swapchainHeight, 1, false, true, true).getHandle(); windowWidth = swapchainWidth; windowHeight = swapchainHeight; diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 4b718db1..a32be983 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -442,9 +442,30 @@ namespace vkcv return m_SamplerManager->createSampler(magFilter, minFilter, mipmapMode, addressMode); } - Image Core::createImage(vk::Format format, uint32_t width, uint32_t height, uint32_t depth, bool supportStorage, bool supportColorAttachment) + Image Core::createImage( + vk::Format format, + uint32_t width, + uint32_t height, + uint32_t depth, + bool createMipChain, + bool supportStorage, + bool supportColorAttachment) { - return Image::create(m_ImageManager.get(), format, width, height, depth, supportStorage, supportColorAttachment); + + uint32_t mipCount = 1; + if (createMipChain) { + mipCount = 1 + (uint32_t)std::floor(std::log2(std::max(width, std::max(height, depth)))); + } + + return Image::create( + m_ImageManager.get(), + format, + width, + height, + depth, + mipCount, + supportStorage, + supportColorAttachment); } DescriptorSetHandle Core::createDescriptorSet(const std::vector<DescriptorBinding>& bindings) diff --git a/src/vkcv/Image.cpp b/src/vkcv/Image.cpp index 9f7fdadc..34feec44 100644 --- a/src/vkcv/Image.cpp +++ b/src/vkcv/Image.cpp @@ -19,9 +19,17 @@ namespace vkcv{ } } - Image Image::create(ImageManager* manager, vk::Format format, uint32_t width, uint32_t height, uint32_t depth, bool supportStorage, bool supportColorAttachment) + Image Image::create( + ImageManager* manager, + vk::Format format, + uint32_t width, + uint32_t height, + uint32_t depth, + uint32_t mipCount, + bool supportStorage, + bool supportColorAttachment) { - return Image(manager, manager->createImage(width, height, depth, format, supportStorage, supportColorAttachment)); + return Image(manager, manager->createImage(width, height, depth, format, mipCount, supportStorage, supportColorAttachment)); } vk::Format Image::getFormat() const { diff --git a/src/vkcv/ImageLayoutTransitions.cpp b/src/vkcv/ImageLayoutTransitions.cpp index cb0f90a7..8d31c64c 100644 --- a/src/vkcv/ImageLayoutTransitions.cpp +++ b/src/vkcv/ImageLayoutTransitions.cpp @@ -15,7 +15,7 @@ namespace vkcv { vk::ImageSubresourceRange imageSubresourceRange( aspectFlags, 0, - image.m_levels, + image.m_viewPerMip.size(), 0, image.m_layers ); diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp index fff98dc5..2064b912 100644 --- a/src/vkcv/ImageManager.cpp +++ b/src/vkcv/ImageManager.cpp @@ -13,25 +13,23 @@ namespace vkcv { ImageManager::Image::Image( - vk::Image handle, - vk::DeviceMemory memory, - vk::ImageView view, - uint32_t width, - uint32_t height, - uint32_t depth, - vk::Format format, - uint32_t layers, - uint32_t levels) + vk::Image handle, + vk::DeviceMemory memory, + std::vector<vk::ImageView> views, + uint32_t width, + uint32_t height, + uint32_t depth, + vk::Format format, + uint32_t layers) : m_handle(handle), m_memory(memory), - m_view(view), + m_viewPerMip(views), m_width(width), m_height(height), m_depth(depth), m_format(format), - m_layers(layers), - m_levels(levels) + m_layers(layers) {} /** @@ -69,8 +67,11 @@ namespace vkcv { for (uint64_t id = 0; id < m_images.size(); id++) { destroyImageById(id); } - for (const auto swapchainImage : m_swapchainImages) - m_core->getContext().getDevice().destroy(swapchainImage.m_view); + for (const auto swapchainImage : m_swapchainImages) { + for (const auto view : swapchainImage.m_viewPerMip) { + m_core->getContext().getDevice().destroy(view); + } + } } bool isDepthImageFormat(vk::Format format) { @@ -83,7 +84,14 @@ namespace vkcv { } } - ImageHandle ImageManager::createImage(uint32_t width, uint32_t height, uint32_t depth, vk::Format format, bool supportStorage, bool supportColorAttachment) + ImageHandle ImageManager::createImage( + uint32_t width, + uint32_t height, + uint32_t depth, + vk::Format format, + uint32_t mipCount, + bool supportStorage, + bool supportColorAttachment) { const vk::PhysicalDevice& physicalDevice = m_core->getContext().getPhysicalDevice(); @@ -135,11 +143,9 @@ namespace vkcv { imageTiling = vk::ImageTiling::eLinear; } - const vk::ImageFormatProperties imageFormatProperties = physicalDevice.getImageFormatProperties( - format, imageType, imageTiling, imageUsageFlags - ); + const vk::ImageFormatProperties imageFormatProperties = + physicalDevice.getImageFormatProperties(format, imageType, imageTiling, imageUsageFlags); - const uint32_t mipLevels = std::min<uint32_t>(1, imageFormatProperties.maxMipLevels); const uint32_t arrayLayers = std::min<uint32_t>(1, imageFormatProperties.maxArrayLayers); const vk::ImageCreateInfo imageCreateInfo( @@ -147,7 +153,7 @@ namespace vkcv { imageType, format, vk::Extent3D(width, height, depth), - mipLevels, + mipCount, arrayLayers, vk::SampleCountFlagBits::e1, imageTiling, @@ -180,30 +186,33 @@ namespace vkcv { aspectFlags = vk::ImageAspectFlagBits::eColor; } - const vk::ImageViewCreateInfo imageViewCreateInfo ( + std::vector<vk::ImageView> views; + for (int mip = 0; mip < mipCount; mip++) { + const vk::ImageViewCreateInfo imageViewCreateInfo( {}, image, imageViewType, format, vk::ComponentMapping( - vk::ComponentSwizzle::eIdentity, - vk::ComponentSwizzle::eIdentity, - vk::ComponentSwizzle::eIdentity, - vk::ComponentSwizzle::eIdentity + vk::ComponentSwizzle::eIdentity, + vk::ComponentSwizzle::eIdentity, + vk::ComponentSwizzle::eIdentity, + vk::ComponentSwizzle::eIdentity ), vk::ImageSubresourceRange( - aspectFlags, - 0, - mipLevels, - 0, - arrayLayers + aspectFlags, + mip, + 1, + 0, + arrayLayers ) - ); - - vk::ImageView view = device.createImageView(imageViewCreateInfo); + ); + + views.push_back(device.createImageView(imageViewCreateInfo)); + } const uint64_t id = m_images.size(); - m_images.push_back(Image(image, memory, view, width, height, depth, format, arrayLayers, mipLevels)); + m_images.push_back(Image(image, memory, views, width, height, depth, format, arrayLayers)); return ImageHandle(id, [&](uint64_t id) { destroyImageById(id); }); } @@ -246,10 +255,10 @@ namespace vkcv { return image.m_memory; } - vk::ImageView ImageManager::getVulkanImageView(const ImageHandle &handle) const { + vk::ImageView ImageManager::getVulkanImageView(const ImageHandle &handle, const size_t mipLevel) const { if (handle.isSwapchainImage()) { - return m_swapchainImages[m_currentSwapchainInputImage].m_view; + return m_swapchainImages[m_currentSwapchainInputImage].m_viewPerMip[0]; } const uint64_t id = handle.getId(); @@ -258,7 +267,14 @@ namespace vkcv { return nullptr; } - return m_images[id].m_view; + const auto& image = m_images[id]; + + if (mipLevel >= m_images.size()) { + vkcv_log(LogLevel::ERROR, "Image does not have requested mipLevel"); + return nullptr; + } + + return image.m_viewPerMip[mipLevel]; } void ImageManager::switchImageLayoutImmediate(const ImageHandle& handle, vk::ImageLayout newLayout) { @@ -475,9 +491,11 @@ namespace vkcv { const vk::Device& device = m_core->getContext().getDevice(); - if (image.m_view) { - device.destroyImageView(image.m_view); - image.m_view = nullptr; + for (auto& view : image.m_viewPerMip) { + if (view) { + device.destroyImageView(view); + view = nullptr; + } } if (image.m_memory) { @@ -512,13 +530,16 @@ namespace vkcv { uint32_t width, uint32_t height, vk::Format format) { // destroy old views - for (auto image : m_swapchainImages) - m_core->getContext().getDevice().destroyImageView(image.m_view); + for (auto image : m_swapchainImages) { + for (const auto& view : image.m_viewPerMip) { + m_core->getContext().getDevice().destroyImageView(view); + } + } assert(images.size() == views.size()); m_swapchainImages.clear(); for (int i = 0; i < images.size(); i++) { - m_swapchainImages.push_back(Image(images[i], nullptr, views[i], width, height, 1, format, 1, 1)); + m_swapchainImages.push_back(Image(images[i], nullptr, { views[i] }, width, height, 1, format, 1)); } } diff --git a/src/vkcv/ImageManager.hpp b/src/vkcv/ImageManager.hpp index 7bb4cc7e..f860470e 100644 --- a/src/vkcv/ImageManager.hpp +++ b/src/vkcv/ImageManager.hpp @@ -18,29 +18,27 @@ namespace vkcv { public: struct Image { - vk::Image m_handle; - vk::DeviceMemory m_memory; - vk::ImageView m_view; - uint32_t m_width = 0; - uint32_t m_height = 0; - uint32_t m_depth = 0; - vk::Format m_format; - uint32_t m_layers = 1; - uint32_t m_levels = 1; - vk::ImageLayout m_layout = vk::ImageLayout::eUndefined; + vk::Image m_handle; + vk::DeviceMemory m_memory; + std::vector<vk::ImageView> m_viewPerMip; + uint32_t m_width = 0; + uint32_t m_height = 0; + uint32_t m_depth = 0; + vk::Format m_format; + uint32_t m_layers = 1; + vk::ImageLayout m_layout = vk::ImageLayout::eUndefined; private: // struct is public so utility functions can access members, but only ImageManager can create Image friend ImageManager; Image( - vk::Image handle, - vk::DeviceMemory memory, - vk::ImageView view, - uint32_t width, - uint32_t height, - uint32_t depth, - vk::Format format, - uint32_t layers, - uint32_t levels); + vk::Image handle, + vk::DeviceMemory memory, + std::vector<vk::ImageView> views, + uint32_t width, + uint32_t height, + uint32_t depth, + vk::Format format, + uint32_t layers); Image(); }; @@ -71,7 +69,14 @@ namespace vkcv { ImageManager& operator=(ImageManager&& other) = delete; ImageManager& operator=(const ImageManager& other) = delete; - ImageHandle createImage(uint32_t width, uint32_t height, uint32_t depth, vk::Format format, bool supportStorage, bool supportColorAttachment); + ImageHandle createImage( + uint32_t width, + uint32_t height, + uint32_t depth, + vk::Format format, + uint32_t mipCount, + bool supportStorage, + bool supportColorAttachment); ImageHandle createSwapchainImage(); @@ -82,7 +87,7 @@ namespace vkcv { vk::DeviceMemory getVulkanDeviceMemory(const ImageHandle& handle) const; [[nodiscard]] - vk::ImageView getVulkanImageView(const ImageHandle& handle) const; + vk::ImageView getVulkanImageView(const ImageHandle& handle, const size_t mipLevel = 0) const; void switchImageLayoutImmediate(const ImageHandle& handle, vk::ImageLayout newLayout); void recordImageLayoutTransition( -- GitLab