diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp index 98a0943bcb253142c836cdfd13623a13f18c2871..f8e35ccbfa6eda1143c1293eb3a0ae947b6760d7 100644 --- a/include/vkcv/Image.hpp +++ b/include/vkcv/Image.hpp @@ -32,11 +32,15 @@ namespace vkcv { [[nodiscard]] vkcv::ImageHandle getHandle() const; - + + [[nodiscard]] + uint32_t getMipCount(); + void switchLayout(vk::ImageLayout newLayout); void fill(void* data, size_t size = SIZE_MAX); void generateMipChainImmediate(); + void recordMipChainGeneration(const vkcv::CommandStreamHandle& cmdStream); private: ImageManager* const m_manager; const ImageHandle m_handle; diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp index e471eea637093e746181e1895ec90df3876edae2..a101a03aae245701fcc097b677cd486fa4445561 100644 --- a/projects/voxelization/src/Voxelization.cpp +++ b/projects/voxelization/src/Voxelization.cpp @@ -70,7 +70,7 @@ Voxelization::Voxelization( vkcv::SamplerHandle shadowSampler) : m_corePtr(corePtr), - m_voxelImage(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, false, true)), + m_voxelImage(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, true, 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)){ @@ -272,6 +272,8 @@ void Voxelization::voxelizeMeshes( vkcv::PushConstantData(nullptr, 0)); m_corePtr->recordImageMemoryBarrier(cmdStream, m_voxelImage.getHandle()); + + m_voxelImage.recordMipChainGeneration(cmdStream); } void Voxelization::renderVoxelVisualisation( diff --git a/src/vkcv/Image.cpp b/src/vkcv/Image.cpp index dca6358b84aa7bcd0f38e78d3fa7aa49fd11395d..0a3353f7248fc417c9f49701be7d5f81455ad667 100644 --- a/src/vkcv/Image.cpp +++ b/src/vkcv/Image.cpp @@ -64,6 +64,10 @@ namespace vkcv{ void Image::generateMipChainImmediate() { m_manager->generateImageMipChainImmediate(m_handle); } + + void Image::recordMipChainGeneration(const vkcv::CommandStreamHandle& cmdStream) { + m_manager->recordImageMipChainGenerationToCmdStream(cmdStream, m_handle); + } Image::Image(ImageManager* manager, const ImageHandle& handle) : m_manager(manager), diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp index dd54da39cfe1d832e006e4f673e6aa8e1eb7ee18..14d7c506a526634a894163e387a8504b0d48241b 100644 --- a/src/vkcv/ImageManager.cpp +++ b/src/vkcv/ImageManager.cpp @@ -438,6 +438,60 @@ namespace vkcv { ); } + void ImageManager::recordImageMipGenerationToCmdBuffer(vk::CommandBuffer cmdBuffer, const ImageHandle& handle) { + + const auto id = handle.getId(); + if (id >= m_images.size()) { + vkcv_log(vkcv::LogLevel::ERROR, "Invalid image handle"); + return; + } + + auto& image = m_images[id]; + recordImageLayoutTransition(handle, vk::ImageLayout::eGeneral, cmdBuffer); + + vk::ImageAspectFlags aspectMask = isDepthImageFormat(image.m_format) ? + vk::ImageAspectFlagBits::eDepth : vk::ImageAspectFlagBits::eColor; + + uint32_t srcWidth = image.m_width; + uint32_t srcHeight = image.m_height; + uint32_t srcDepth = image.m_depth; + + auto half = [](uint32_t in) { + return std::max<uint32_t>(in / 2, 1); + }; + + uint32_t dstWidth = half(srcWidth); + uint32_t dstHeight = half(srcHeight); + uint32_t dstDepth = half(srcDepth); + + for (uint32_t srcMip = 0; srcMip < image.m_viewPerMip.size() - 1; srcMip++) { + uint32_t dstMip = srcMip + 1; + vk::ImageBlit region( + vk::ImageSubresourceLayers(aspectMask, srcMip, 0, 1), + { vk::Offset3D(0, 0, 0), vk::Offset3D(srcWidth, srcHeight, srcDepth) }, + vk::ImageSubresourceLayers(aspectMask, dstMip, 0, 1), + { vk::Offset3D(0, 0, 0), vk::Offset3D(dstWidth, dstHeight, dstDepth) }); + + cmdBuffer.blitImage( + image.m_handle, + vk::ImageLayout::eGeneral, + image.m_handle, + vk::ImageLayout::eGeneral, + region, + vk::Filter::eLinear); + + srcWidth = dstWidth; + srcHeight = dstHeight; + srcDepth = dstDepth; + + dstWidth = half(dstWidth); + dstHeight = half(dstHeight); + dstDepth = half(dstDepth); + + recordImageMemoryBarrier(handle, cmdBuffer); + } + } + void ImageManager::generateImageMipChainImmediate(const ImageHandle& handle) { const auto& device = m_core->getContext().getDevice(); @@ -450,62 +504,23 @@ namespace vkcv { return; } - const auto id = handle.getId(); - if (id >= m_images.size()) { - vkcv_log(vkcv::LogLevel::ERROR, "Invalid image handle"); - return; - } - auto& image = m_images[id]; - switchImageLayoutImmediate(handle, vk::ImageLayout::eGeneral); - - const auto record = [&image, this, handle](const vk::CommandBuffer cmdBuffer) { - - vk::ImageAspectFlags aspectMask = isDepthImageFormat(image.m_format) ? - vk::ImageAspectFlagBits::eDepth : vk::ImageAspectFlagBits::eColor; - - uint32_t srcWidth = image.m_width; - uint32_t srcHeight = image.m_height; - uint32_t srcDepth = image.m_depth; - - auto half = [](uint32_t in) { - return std::max<uint32_t>(in / 2, 1); - }; - - uint32_t dstWidth = half(image.m_width); - uint32_t dstHeight = half(image.m_height); - uint32_t dstDepth = half(image.m_depth); - - for (uint32_t srcMip = 0; srcMip < image.m_viewPerMip.size() - 1; srcMip++) { - uint32_t dstMip = srcMip + 1; - vk::ImageBlit region( - vk::ImageSubresourceLayers(aspectMask, srcMip, 0, 1), - { vk::Offset3D(0, 0, 0), vk::Offset3D(srcWidth, srcHeight, srcDepth) }, - vk::ImageSubresourceLayers(aspectMask, dstMip, 0, 1), - { vk::Offset3D(0, 0, 0), vk::Offset3D(dstWidth, dstHeight, dstDepth) }); - - cmdBuffer.blitImage( - image.m_handle, - vk::ImageLayout::eGeneral, - image.m_handle, - vk::ImageLayout::eGeneral, - region, - vk::Filter::eLinear); - - srcWidth = dstWidth; - srcHeight = dstHeight; - srcDepth = dstDepth; - - dstWidth = half(dstWidth); - dstHeight = half(dstHeight); - dstDepth = half(dstDepth); - - recordImageMemoryBarrier(handle, cmdBuffer); - } + const auto record = [this, handle](const vk::CommandBuffer cmdBuffer) { + recordImageMipGenerationToCmdBuffer(cmdBuffer, handle); }; m_core->recordAndSubmitCommandsImmediate(submitInfo, record, nullptr); } + void ImageManager::recordImageMipChainGenerationToCmdStream( + const vkcv::CommandStreamHandle& cmdStream, + const ImageHandle& handle) { + + const auto record = [this, handle](const vk::CommandBuffer cmdBuffer) { + recordImageMipGenerationToCmdBuffer(cmdBuffer, handle); + }; + m_core->recordCommandsToStream(cmdStream, record, nullptr); + } + uint32_t ImageManager::getImageWidth(const ImageHandle &handle) const { const uint64_t id = handle.getId(); const bool isSwapchainImage = handle.isSwapchainImage(); diff --git a/src/vkcv/ImageManager.hpp b/src/vkcv/ImageManager.hpp index 69ab7943f34bcf3579a4384cbd59e78e5b7aacdf..9cd1a8dec6d37af7e01273993cc6a38c06b68ce6 100644 --- a/src/vkcv/ImageManager.hpp +++ b/src/vkcv/ImageManager.hpp @@ -60,7 +60,9 @@ namespace vkcv { * @param id Image handle id */ void destroyImageById(uint64_t id); - + + void recordImageMipGenerationToCmdBuffer(vk::CommandBuffer cmdBuffer, const ImageHandle& handle); + public: ~ImageManager() noexcept; ImageManager(ImageManager&& other) = delete; @@ -101,6 +103,7 @@ namespace vkcv { void fillImage(const ImageHandle& handle, void* data, size_t size); void generateImageMipChainImmediate(const ImageHandle& handle); + void recordImageMipChainGenerationToCmdStream(const vkcv::CommandStreamHandle& cmdStream, const ImageHandle& handle); [[nodiscard]] uint32_t getImageWidth(const ImageHandle& handle) const;