From 83bbb20066ce6072a9c43ce993b1771e4fac324a Mon Sep 17 00:00:00 2001 From: Tobias Frisch <tfrisch@uni-koblenz.de> Date: Sun, 12 Jun 2022 13:04:59 +0200 Subject: [PATCH] Implemented SPD into scene module Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de> --- include/vkcv/Core.hpp | 41 ++++++++++++------- .../vkcv/algorithm/SinglePassDownsampler.cpp | 2 +- .../material/src/vkcv/material/Material.cpp | 6 +-- modules/scene/CMakeLists.txt | 15 ++++++- modules/scene/src/vkcv/scene/Scene.cpp | 30 +++++++++++++- projects/first_scene/src/main.cpp | 12 +++++- projects/voxelization/src/main.cpp | 2 +- src/vkcv/Core.cpp | 8 +++- src/vkcv/ImageManager.cpp | 25 ++++++++++- src/vkcv/ImageManager.hpp | 4 ++ 10 files changed, 117 insertions(+), 28 deletions(-) diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index e8ce984d..a11db52f 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -300,41 +300,54 @@ namespace vkcv Swapchain& getSwapchain(const WindowHandle &handle); /** - * Returns the image width - * @param image handle + * @brief Returns the image width. + * + * @param image Image handle * @return imageWidth */ [[nodiscard]] uint32_t getImageWidth(const ImageHandle &image); /** - * Returns the image height - * @param image handle + * @brief Returns the image height. + * + * @param[in] image Image handle * @return imageHeight */ [[nodiscard]] uint32_t getImageHeight(const ImageHandle &image); /** - * Returns the image depth - * @param image handle + * @brief Returns the image depth. + * + * @param[in] image Image handle * @return imageDepth */ [[nodiscard]] uint32_t getImageDepth(const ImageHandle &image); /** - * Returns the image format of the image - * @param image handle + * @brief Returns the image format of the image. + * + * @param[in] image Image handle * @return imageFormat */ [[nodiscard]] vk::Format getImageFormat(const ImageHandle &image); + + /** + * @brief Returns whether the image supports storage or not. + * + * @param[in] image Image handle + * @return True, if the image supports storage, otherwise false. + */ + [[nodiscard]] + bool isImageSupportingStorage(const ImageHandle& image); /** * @brief Returns the images amount of mip levels. * - * @param image Image handle + * @param[in] image Image handle * @return Amount of mip levels */ [[nodiscard]] @@ -343,7 +356,7 @@ namespace vkcv /** * @brief Returns the images amount of array layers. * - * @param image Image handle + * @param[in] image Image handle * @return Amount of array layers */ [[nodiscard]] @@ -352,7 +365,7 @@ namespace vkcv /** * @brief Creates a descriptor set layout handle by a set of descriptor bindings. * - * @param bindings Descriptor bindings + * @param[in] bindings Descriptor bindings * @return Descriptor set layout handle */ [[nodiscard]] @@ -361,7 +374,7 @@ namespace vkcv /** * @brief Returns the descriptor set layout of a descriptor set layout handle. * - * @param handle Descriptor set layout handle + * @param[in] handle Descriptor set layout handle * @return Descriptor set layout */ DescriptorSetLayout getDescriptorSetLayout(const DescriptorSetLayoutHandle handle) const; @@ -369,11 +382,11 @@ namespace vkcv /** * @brief Creates a new descriptor set * - * @param layoutHandle Handle to the layout that the descriptor set will use + * @param[in] layout Handle to the layout that the descriptor set will use * @return Handle that represents the descriptor set */ [[nodiscard]] - DescriptorSetHandle createDescriptorSet(const DescriptorSetLayoutHandle &layoutHandle); + DescriptorSetHandle createDescriptorSet(const DescriptorSetLayoutHandle &layout); /** * @brief Writes resources bindings to a descriptor set diff --git a/modules/algorithm/src/vkcv/algorithm/SinglePassDownsampler.cpp b/modules/algorithm/src/vkcv/algorithm/SinglePassDownsampler.cpp index fb078cc9..ea6331b0 100644 --- a/modules/algorithm/src/vkcv/algorithm/SinglePassDownsampler.cpp +++ b/modules/algorithm/src/vkcv/algorithm/SinglePassDownsampler.cpp @@ -234,7 +234,7 @@ namespace vkcv::algorithm { m_core.prepareImageForSampling(cmdStream, image); - if ((mipLevels < 4) || (depth > 1)) { + if ((mipLevels < 4) || (depth > 1) || (!m_core.isImageSupportingStorage(image))) { m_core.getDownsampler().recordDownsampling(cmdStream, image); return; } diff --git a/modules/material/src/vkcv/material/Material.cpp b/modules/material/src/vkcv/material/Material.cpp index a6a16f80..8c3f3099 100644 --- a/modules/material/src/vkcv/material/Material.cpp +++ b/modules/material/src/vkcv/material/Material.cpp @@ -119,21 +119,21 @@ namespace vkcv::material { } if (!normalImg) { - vkcv::Image defaultNormal = core.createImage(vk::Format::eR8G8B8A8Srgb, 2, 2); + vkcv::Image defaultNormal = core.createImage(vk::Format::eR8G8B8A8Unorm, 2, 2); float normalData [4] = { 0, 0, 1, 0 }; fillImage(defaultNormal, normalData); images[1] = defaultNormal.getHandle(); } if (!metRoughImg) { - vkcv::Image defaultRough = core.createImage(vk::Format::eR8G8B8A8Srgb, 2, 2); + vkcv::Image defaultRough = core.createImage(vk::Format::eR8G8B8A8Unorm, 2, 2); float roughData [4] = { 228, 51, 255, 1 }; fillImage(defaultRough, roughData); images[2] = defaultRough.getHandle(); } if (!occlusionImg) { - vkcv::Image defaultOcclusion = core.createImage(vk::Format::eR8G8B8A8Srgb, 2, 2); + vkcv::Image defaultOcclusion = core.createImage(vk::Format::eR8G8B8A8Unorm, 2, 2); float occlusionData [4] = { 228, 51, 255, 1 }; fillImage(defaultOcclusion, occlusionData); images[3] = defaultOcclusion.getHandle(); diff --git a/modules/scene/CMakeLists.txt b/modules/scene/CMakeLists.txt index 08a7e590..39effd0f 100644 --- a/modules/scene/CMakeLists.txt +++ b/modules/scene/CMakeLists.txt @@ -36,13 +36,24 @@ add_library(vkcv_scene ${vkcv_build_attribute} ${vkcv_scene_sources}) target_link_libraries(vkcv_scene vkcv) # including headers of dependencies and the VkCV framework -target_include_directories(vkcv_scene SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include} ${vkcv_material_include} ${vkcv_camera_include}) +target_include_directories(vkcv_scene SYSTEM BEFORE PRIVATE + ${vkcv_include} + ${vkcv_includes} + ${vkcv_asset_loader_include} + ${vkcv_material_include} + ${vkcv_camera_include} + ${vkcv_algorithm_include}) # add the own include directory for public headers target_include_directories(vkcv_scene BEFORE PUBLIC ${vkcv_scene_include}) # linking with libraries from all dependencies and the VkCV framework -target_link_libraries(vkcv_scene vkcv vkcv_asset_loader vkcv_material vkcv_camera) +target_link_libraries(vkcv_scene + vkcv + vkcv_asset_loader + vkcv_material + vkcv_camera + vkcv_algorithm) if (vkcv_parent_scope) list(APPEND vkcv_modules_includes ${vkcv_scene_include}) diff --git a/modules/scene/src/vkcv/scene/Scene.cpp b/modules/scene/src/vkcv/scene/Scene.cpp index bb21807d..cb819370 100644 --- a/modules/scene/src/vkcv/scene/Scene.cpp +++ b/modules/scene/src/vkcv/scene/Scene.cpp @@ -4,6 +4,8 @@ #include <vkcv/Logger.hpp> #include <vkcv/asset/asset_loader.hpp> +#include <vkcv/algorithm/SinglePassDownsampler.hpp> + namespace vkcv::scene { Scene::Scene(Core* core) : @@ -274,10 +276,34 @@ namespace vkcv::scene { scene.getNode(root).loadMesh(asset_scene, mesh); } + vkcv::SamplerHandle sampler = core.createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::REPEAT + ); + + const vkcv::FeatureManager& featureManager = core.getContext().getFeatureManager(); + const bool partialBound = featureManager.checkFeatures<vk::PhysicalDeviceDescriptorIndexingFeatures>( + vk::StructureType::ePhysicalDeviceDescriptorIndexingFeatures, + [](const vk::PhysicalDeviceDescriptorIndexingFeatures& features) { + return features.descriptorBindingPartiallyBound; + } + ); + + vkcv::Downsampler& downsampler = core.getDownsampler(); + vkcv::algorithm::SinglePassDownsampler spdDownsampler (core, sampler); + auto mipStream = core.createCommandStream(vkcv::QueueType::Graphics); - for (auto& material : scene.m_materials) { - material.m_data.recordMipChainGeneration(mipStream, core.getDownsampler()); + if (partialBound) { + for (auto& material : scene.m_materials) { + material.m_data.recordMipChainGeneration(mipStream, spdDownsampler); + } + } else { + for (auto& material : scene.m_materials) { + material.m_data.recordMipChainGeneration(mipStream, downsampler); + } } core.submitCommandStream(mipStream, false); diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp index 3c4f51bb..b09943e4 100644 --- a/projects/first_scene/src/main.cpp +++ b/projects/first_scene/src/main.cpp @@ -7,18 +7,28 @@ #include <vkcv/asset/asset_loader.hpp> #include <vkcv/shader/GLSLCompiler.hpp> #include <vkcv/scene/Scene.hpp> +#include <vkcv/Features.hpp> int main(int argc, const char** argv) { const char* applicationName = "First Scene"; uint32_t windowWidth = 800; uint32_t windowHeight = 600; + + vkcv::Features features; + features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); + features.requireExtensionFeature<vk::PhysicalDeviceDescriptorIndexingFeatures>( + VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME, + [](vk::PhysicalDeviceDescriptorIndexingFeatures& features) { + features.setDescriptorBindingPartiallyBound(true); + } + ); vkcv::Core core = vkcv::Core::create( applicationName, VK_MAKE_VERSION(0, 0, 1), {vk::QueueFlagBits::eTransfer, vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute}, - { VK_KHR_SWAPCHAIN_EXTENSION_NAME } + features ); vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, true); vkcv::Window& window = core.getWindow(windowHandle); diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index 4aa285de..fe096114 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -291,7 +291,7 @@ int main(int argc, const char** argv) { // albedo texture sceneImages.push_back(core.createImage(vk::Format::eR8G8B8A8Srgb, albedoTexture.w, albedoTexture.h, 1, true)); sceneImages.back().fill(albedoTexture.data.data()); - sceneImages.back().recordMipChainGeneration(mipStream, downsampler); + sceneImages.back().recordMipChainGeneration(mipStream, spdDownsampler); const vkcv::ImageHandle albedoHandle = sceneImages.back().getHandle(); // normal texture diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 808e0c68..06942b87 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -900,6 +900,10 @@ namespace vkcv return m_ImageManager->getImageFormat(image); } + bool Core::isImageSupportingStorage(const ImageHandle &image) { + return m_ImageManager->isImageSupportingStorage(image); + } + uint32_t Core::getImageMipLevels(const ImageHandle &image) { return m_ImageManager->getImageMipCount(image); } @@ -931,9 +935,9 @@ namespace vkcv return m_DescriptorManager->getDescriptorSetLayout(handle); } - DescriptorSetHandle Core::createDescriptorSet(const DescriptorSetLayoutHandle &layoutHandle) + DescriptorSetHandle Core::createDescriptorSet(const DescriptorSetLayoutHandle &layout) { - return m_DescriptorManager->createDescriptorSet(layoutHandle); + return m_DescriptorManager->createDescriptorSet(layout); } void Core::writeDescriptorSet(DescriptorSetHandle handle, const DescriptorWrites &writes) { diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp index b58fe3c5..d37e293b 100644 --- a/src/vkcv/ImageManager.cpp +++ b/src/vkcv/ImageManager.cpp @@ -92,6 +92,9 @@ namespace vkcv { if (!(formatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eStorageImage)) { imageTiling = vk::ImageTiling::eLinear; + + if (!(formatProperties.linearTilingFeatures & vk::FormatFeatureFlagBits::eStorageImage)) + return ImageHandle(); } } @@ -253,7 +256,8 @@ namespace vkcv { format, arrayLayers, - vk::ImageLayout::eUndefined + vk::ImageLayout::eUndefined, + supportStorage }); return ImageHandle(id, [&](uint64_t id) { destroyImageById(id); }); @@ -750,6 +754,22 @@ namespace vkcv { return isSwapchainFormat ? m_swapchainImages[m_currentSwapchainInputImage].m_format : m_images[id].m_format; } + + bool ImageManager::isImageSupportingStorage(const ImageHandle& handle) const { + const uint64_t id = handle.getId(); + const bool isSwapchainFormat = handle.isSwapchainImage(); + + if (isSwapchainFormat) { + return false; + } + + if (id >= m_images.size()) { + vkcv_log(LogLevel::ERROR, "Invalid handle"); + return false; + } + + return m_images[id].m_storage; + } uint32_t ImageManager::getImageMipCount(const ImageHandle& handle) const { const uint64_t id = handle.getId(); @@ -808,7 +828,8 @@ namespace vkcv { 1, format, 1, - vk::ImageLayout::eUndefined + vk::ImageLayout::eUndefined, + false }); } } diff --git a/src/vkcv/ImageManager.hpp b/src/vkcv/ImageManager.hpp index 84d41d34..3e577fd9 100644 --- a/src/vkcv/ImageManager.hpp +++ b/src/vkcv/ImageManager.hpp @@ -46,6 +46,7 @@ namespace vkcv { vk::Format m_format; uint32_t m_layers; vk::ImageLayout m_layout; + bool m_storage; private: friend ImageManager; }; @@ -130,6 +131,9 @@ namespace vkcv { [[nodiscard]] vk::Format getImageFormat(const ImageHandle& handle) const; + + [[nodiscard]] + bool isImageSupportingStorage(const ImageHandle& handle) const; [[nodiscard]] uint32_t getImageMipCount(const ImageHandle& handle) const; -- GitLab