diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index 6a4281943778ee21f72ed27d615c5821758ab822..c7512346c9137b77c365e807b679b3950925f535 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -41,7 +41,6 @@ namespace vkcv QueueType queueType; std::vector<vk::Semaphore> waitSemaphores; std::vector<vk::Semaphore> signalSemaphores; - vk::Fence fence; }; class Core final @@ -215,7 +214,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 = false, + bool supportStorage = false, + bool supportColorAttachment = false); /** TODO: * @param setDescriptions @@ -261,7 +267,7 @@ namespace vkcv * @param record Record-command-function * @param finish Finish-command-function or nullptr */ - void recordAndSubmitCommands( + void recordAndSubmitCommandsImmediate( const SubmitInfo &submitInfo, const RecordCommandFunction &record, const FinishCommandFunction &finish); diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp index 1795b63e844a002564932f5d7ef839746e32fae5..98a0943bcb253142c836cdfd13623a13f18c2871 100644 --- a/include/vkcv/Image.hpp +++ b/include/vkcv/Image.hpp @@ -36,13 +36,22 @@ namespace vkcv { void switchLayout(vk::ImageLayout newLayout); void fill(void* data, size_t size = SIZE_MAX); + void generateMipChainImmediate(); private: ImageManager* const m_manager; const ImageHandle m_handle; 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/modules/gui/src/vkcv/gui/GUI.cpp b/modules/gui/src/vkcv/gui/GUI.cpp index 6a08cb4f02551cae2fd5d1e3ea4e6ff0bd2b2e04..a9a8bd01df379a0f4615c2c53aee09082d107b1c 100644 --- a/modules/gui/src/vkcv/gui/GUI.cpp +++ b/modules/gui/src/vkcv/gui/GUI.cpp @@ -141,7 +141,7 @@ namespace vkcv::gui { const SubmitInfo submitInfo { QueueType::Graphics, {}, {} }; - m_core.recordAndSubmitCommands(submitInfo, [](const vk::CommandBuffer& commandBuffer) { + m_core.recordAndSubmitCommandsImmediate(submitInfo, [](const vk::CommandBuffer& commandBuffer) { ImGui_ImplVulkan_CreateFontsTexture(commandBuffer); }, []() { ImGui_ImplVulkan_DestroyFontUploadObjects(); @@ -214,7 +214,7 @@ namespace vkcv::gui { SubmitInfo submitInfo; submitInfo.queueType = QueueType::Graphics; - m_core.recordAndSubmitCommands(submitInfo, [&](const vk::CommandBuffer& commandBuffer) { + m_core.recordAndSubmitCommandsImmediate(submitInfo, [&](const vk::CommandBuffer& commandBuffer) { const vk::Rect2D renderArea ( vk::Offset2D(0, 0), extent diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index d9650f3577cf5633ac915f435b59367a9f993d62..74e6de3ff6d9f80d764b774fea5dc55b4b53b2f8 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -123,6 +123,8 @@ int main(int argc, const char** argv) { vkcv::asset::Texture &tex = mesh.textures[0]; vkcv::Image texture = core.createImage(vk::Format::eR8G8B8A8Srgb, tex.w, tex.h); texture.fill(tex.data.data()); + texture.generateMipChainImmediate(); + texture.switchLayout(vk::ImageLayout::eShaderReadOnlyOptimal); vkcv::SamplerHandle sampler = core.createSampler( vkcv::SamplerFilterType::LINEAR, @@ -142,7 +144,7 @@ int main(int argc, const char** argv) { core.writeDescriptorSet(descriptorSet, setWrites); - vkcv::ImageHandle depthBuffer = core.createImage(vk::Format::eD32Sfloat, windowWidth, windowHeight).getHandle(); + vkcv::ImageHandle depthBuffer = core.createImage(vk::Format::eD32Sfloat, windowWidth, windowHeight, 1, false).getHandle(); const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle(); diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp index a67177447ec3b795c3c65476e6881b067a33df84..b04fab9a2b61430d24bd7171d9fd3637dd428699 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 81d99f8af37722735742c697171219e012f6b339..1899a3b1e439e67a5ccee7bc21bf7366c1db8b2e 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); // light info buffer struct LightInfo { @@ -194,8 +194,10 @@ int main(int argc, const char** argv) { vkcv::asset::Texture& sceneTexture = scene.textures[baseColorIndex]; - sceneImages.push_back(core.createImage(vk::Format::eR8G8B8A8Srgb, sceneTexture.w, sceneTexture.h)); + sceneImages.push_back(core.createImage(vk::Format::eR8G8B8A8Srgb, sceneTexture.w, sceneTexture.h, 1, true)); sceneImages.back().fill(sceneTexture.data.data()); + sceneImages.back().generateMipChainImmediate(); + sceneImages.back().switchLayout(vk::ImageLayout::eShaderReadOnlyOptimal); vkcv::DescriptorWrites setWrites; setWrites.sampledImageWrites = { @@ -226,7 +228,7 @@ int main(int argc, const char** argv) { } vkcv::ImageHandle depthBuffer = core.createImage(depthBufferFormat, windowWidth, windowHeight).getHandle(); - vkcv::ImageHandle colorBuffer = core.createImage(colorBufferFormat, windowWidth, windowHeight, 1, true, true).getHandle(); + vkcv::ImageHandle colorBuffer = core.createImage(colorBufferFormat, windowWidth, windowHeight, 1, false, true, true).getHandle(); const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle(); @@ -324,7 +326,7 @@ 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(); + colorBuffer = core.createImage(colorBufferFormat, swapchainWidth, swapchainHeight, 1, false, true, true).getHandle(); windowWidth = swapchainWidth; windowHeight = swapchainHeight; diff --git a/src/vkcv/BufferManager.cpp b/src/vkcv/BufferManager.cpp index 4df411c193acffa42401e4f5932d97f531cac9c9..aec96411c5d9e07f200b24fbdcf9fa69e2af53d5 100644 --- a/src/vkcv/BufferManager.cpp +++ b/src/vkcv/BufferManager.cpp @@ -159,7 +159,7 @@ namespace vkcv { SubmitInfo submitInfo; submitInfo.queueType = QueueType::Transfer; - core->recordAndSubmitCommands( + core->recordAndSubmitCommandsImmediate( submitInfo, [&info, &mapped_size](const vk::CommandBuffer& commandBuffer) { const vk::BufferCopy region ( diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 4b718db186432f4130f373a67c563c30c48af6a2..1492b1afa563543e6a9eef380295bcb71fef58b8 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -15,7 +15,7 @@ #include "DescriptorManager.hpp" #include "ImageLayoutTransitions.hpp" #include "vkcv/CommandStreamManager.hpp" - +#include <cmath> #include "vkcv/Logger.hpp" namespace vkcv @@ -375,7 +375,7 @@ namespace vkcv } } - void Core::recordAndSubmitCommands( + void Core::recordAndSubmitCommandsImmediate( const SubmitInfo &submitInfo, const RecordCommandFunction &record, const FinishCommandFunction &finish) @@ -390,18 +390,12 @@ namespace vkcv record(cmdBuffer); cmdBuffer.end(); - vk::Fence waitFence; - - if (!submitInfo.fence) { - waitFence = createFence(device); - } - + vk::Fence waitFence = createFence(device); + submitCommandBufferToQueue(queue.handle, cmdBuffer, waitFence, submitInfo.waitSemaphores, submitInfo.signalSemaphores); waitForFence(device, waitFence); - if (!submitInfo.fence) { - device.destroyFence(waitFence); - } + device.destroyFence(waitFence); device.freeCommandBuffers(cmdPool, cmdBuffer); @@ -442,9 +436,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 9f7fdadc7400fd3e63061f1e40cd494db63a7869..dca6358b84aa7bcd0f38e78d3fa7aa49fd11395d 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 { @@ -52,6 +60,10 @@ namespace vkcv{ void Image::fill(void *data, size_t size) { m_manager->fillImage(m_handle, data, size); } + + void Image::generateMipChainImmediate() { + m_manager->generateImageMipChainImmediate(m_handle); + } Image::Image(ImageManager* manager, const ImageHandle& handle) : m_manager(manager), diff --git a/src/vkcv/ImageLayoutTransitions.cpp b/src/vkcv/ImageLayoutTransitions.cpp index cb0f90a79d188cd80a5744d8c6ad7718e542d473..8d31c64ccbcbf33e259714f8c581c920738190b4 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 fff98dc5b56d0ad085c6ebc68acf7230223d9cd1..dd54da39cfe1d832e006e4f673e6aa8e1eb7ee18 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(); @@ -91,7 +99,7 @@ namespace vkcv { vk::ImageCreateFlags createFlags; vk::ImageUsageFlags imageUsageFlags = ( - vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst + vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eTransferSrc ); if (supportStorage) { imageUsageFlags |= vk::ImageUsageFlagBits::eStorage; @@ -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, + mipCount - mip, + 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) { @@ -277,7 +293,7 @@ namespace vkcv { SubmitInfo submitInfo; submitInfo.queueType = QueueType::Graphics; - m_core->recordAndSubmitCommands( + m_core->recordAndSubmitCommandsImmediate( submitInfo, [transitionBarrier](const vk::CommandBuffer& commandBuffer) { // TODO: precise PipelineStageFlagBits, will require a lot of context @@ -380,7 +396,7 @@ namespace vkcv { SubmitInfo submitInfo; submitInfo.queueType = QueueType::Transfer; - m_core->recordAndSubmitCommands( + m_core->recordAndSubmitCommandsImmediate( submitInfo, [&image, &stagingBuffer](const vk::CommandBuffer& commandBuffer) { vk::ImageAspectFlags aspectFlags; @@ -421,7 +437,75 @@ namespace vkcv { } ); } - + + void ImageManager::generateImageMipChainImmediate(const ImageHandle& handle) { + + const auto& device = m_core->getContext().getDevice(); + + SubmitInfo submitInfo; + submitInfo.queueType = QueueType::Graphics; + + if (handle.isSwapchainImage()) { + vkcv_log(vkcv::LogLevel::ERROR, "You cannot generate a mip chain for the swapchain, what are you smoking?"); + 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); + } + }; + + m_core->recordAndSubmitCommandsImmediate(submitInfo, record, nullptr); + } + uint32_t ImageManager::getImageWidth(const ImageHandle &handle) const { const uint64_t id = handle.getId(); const bool isSwapchainImage = handle.isSwapchainImage(); @@ -475,9 +559,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 +598,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 7bb4cc7ef7951a8677c19f589bd7948dbcedb25d..69ab7943f34bcf3579a4384cbd59e78e5b7aacdf 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( @@ -95,6 +100,7 @@ namespace vkcv { vk::CommandBuffer cmdBuffer); void fillImage(const ImageHandle& handle, void* data, size_t size); + void generateImageMipChainImmediate(const ImageHandle& handle); [[nodiscard]] uint32_t getImageWidth(const ImageHandle& handle) const; diff --git a/src/vkcv/SamplerManager.cpp b/src/vkcv/SamplerManager.cpp index eb44356f2cbee1caaf4cb0635c8c8937890b06f9..a6ebb95b5e237dcd06ed8041b3f16489f7339d6a 100644 --- a/src/vkcv/SamplerManager.cpp +++ b/src/vkcv/SamplerManager.cpp @@ -87,7 +87,7 @@ namespace vkcv { false, vk::CompareOp::eAlways, 0.0f, - 1.0f, + 16.0f, vk::BorderColor::eIntOpaqueBlack, false );