From ccd8aa7e6de5e97c44f98ea378f5daff4a1ee445 Mon Sep 17 00:00:00 2001 From: Tobias Frisch <tfrisch@uni-koblenz.de> Date: Sun, 29 Aug 2021 17:18:54 +0200 Subject: [PATCH] [#101] Added class to store feature and extension requirements before core creation Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de> --- config/Sources.cmake | 3 + include/vkcv/Context.hpp | 6 +- include/vkcv/Core.hpp | 20 +++--- include/vkcv/FeatureManager.hpp | 6 +- include/vkcv/Features.hpp | 80 +++++++++++++++++++++++ projects/first_mesh/src/main.cpp | 6 +- projects/first_scene/src/main.cpp | 6 +- projects/first_triangle/src/main.cpp | 6 +- projects/mesh_shader/src/main.cpp | 11 +++- projects/particle_simulation/src/main.cpp | 6 +- projects/voxelization/src/main.cpp | 10 ++- src/vkcv/Context.cpp | 18 ++--- src/vkcv/Core.cpp | 8 +-- src/vkcv/FeatureManager.cpp | 17 ++--- src/vkcv/Features.cpp | 56 ++++++++++++++++ 15 files changed, 204 insertions(+), 55 deletions(-) create mode 100644 include/vkcv/Features.hpp create mode 100644 src/vkcv/Features.cpp diff --git a/config/Sources.cmake b/config/Sources.cmake index bdcbc1c6..ea95d152 100644 --- a/config/Sources.cmake +++ b/config/Sources.cmake @@ -1,6 +1,9 @@ # adding all source files and header files of the framework: set(vkcv_sources + ${vkcv_include}/vkcv/Features.hpp + ${vkcv_source}/vkcv/Features.cpp + ${vkcv_include}/vkcv/FeatureManager.hpp ${vkcv_source}/vkcv/FeatureManager.cpp diff --git a/include/vkcv/Context.hpp b/include/vkcv/Context.hpp index 76d60525..1160857c 100644 --- a/include/vkcv/Context.hpp +++ b/include/vkcv/Context.hpp @@ -5,7 +5,7 @@ #include "QueueManager.hpp" #include "DrawcallRecording.hpp" -#include "FeatureManager.hpp" +#include "Features.hpp" namespace vkcv { @@ -45,8 +45,8 @@ namespace vkcv static Context create(const char *applicationName, uint32_t applicationVersion, const std::vector<vk::QueueFlagBits>& queueFlags, - const std::vector<const char *>& instanceExtensions, - const std::vector<const char *>& deviceExtensions); + const Features& features, + const std::vector<const char*>& instanceExtensions = {}); private: /** diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index 7f23c384..e7f6688b 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -7,14 +7,14 @@ #include <memory> #include <vulkan/vulkan.hpp> -#include "vkcv/Context.hpp" -#include "vkcv/Swapchain.hpp" -#include "vkcv/Window.hpp" -#include "vkcv/PassConfig.hpp" -#include "vkcv/Handles.hpp" -#include "vkcv/Buffer.hpp" -#include "vkcv/Image.hpp" -#include "vkcv/PipelineConfig.hpp" +#include "Context.hpp" +#include "Swapchain.hpp" +#include "Window.hpp" +#include "PassConfig.hpp" +#include "Handles.hpp" +#include "Buffer.hpp" +#include "Image.hpp" +#include "PipelineConfig.hpp" #include "CommandResources.hpp" #include "SyncResources.hpp" #include "Result.hpp" @@ -139,8 +139,8 @@ namespace vkcv const char *applicationName, uint32_t applicationVersion, const std::vector<vk::QueueFlagBits>& queueFlags = {}, - const std::vector<const char*>& instanceExtensions = {}, - const std::vector<const char*>& deviceExtensions = {}); + const Features& features = {}, + const std::vector<const char *>& instanceExtensions = {}); /** * Creates a basic vulkan graphics pipeline using @p config from the pipeline config class and returns it using the @p handle. diff --git a/include/vkcv/FeatureManager.hpp b/include/vkcv/FeatureManager.hpp index 9e472a38..cf945d74 100644 --- a/include/vkcv/FeatureManager.hpp +++ b/include/vkcv/FeatureManager.hpp @@ -93,12 +93,12 @@ namespace vkcv { FeatureManager& operator=(FeatureManager&& other) noexcept; [[nodiscard]] - bool isExtensionSupported(const char *extension) const; + bool isExtensionSupported(const std::string& extension) const; - bool useExtension(const char *extension, bool required = true); + bool useExtension(const std::string& extension, bool required = true); [[nodiscard]] - bool isExtensionActive(const char *extension) const; + bool isExtensionActive(const std::string& extension) const; [[nodiscard]] const std::vector<const char*>& getActiveExtensions() const; diff --git a/include/vkcv/Features.hpp b/include/vkcv/Features.hpp new file mode 100644 index 00000000..f1329106 --- /dev/null +++ b/include/vkcv/Features.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include <functional> +#include <vector> + +#include "FeatureManager.hpp" + +namespace vkcv { + + typedef std::function<bool(FeatureManager&)> Feature; + + class Features { + private: + std::vector<Feature> m_features; + + public: + Features() = default; + Features(const Features& other) = default; + Features(Features&& other) = default; + ~Features() = default; + + Features& operator=(const Features& other) = default; + Features& operator=(Features&& other) = default; + + void requireExtension(const std::string& extension); + + void requireExtensionFeature(const std::string& extension, + const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction); + + template<typename T> + void requireExtensionFeature(const std::string& extension, const std::function<void(T&)>& featureFunction) { + m_features.emplace_back([extension, &featureFunction](FeatureManager& featureManager) { + if (featureManager.useExtension(extension, true)) { + return featureManager.template useFeatures<T>(featureFunction, true); + } else { + return false; + } + }); + } + + void requireFeature(const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction); + + template<typename T> + void requireFeature(const std::function<void(T&)>& featureFunction) { + m_features.emplace_back([&featureFunction](FeatureManager& featureManager) { + return featureManager.template useFeatures<T>(featureFunction, true); + }); + } + + void tryExtension(const std::string& extension); + + void tryExtensionFeature(const std::string& extension, + const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction); + + template<typename T> + void tryExtensionFeature(const std::string& extension, const std::function<void(T&)>& featureFunction) { + m_features.emplace_back([extension, &featureFunction](FeatureManager& featureManager) { + if (featureManager.useExtension(extension, false)) { + return featureManager.template useFeatures<T>(featureFunction, false); + } else { + return false; + } + }); + } + + void tryFeature(const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction); + + template<typename T> + void tryFeature(const std::function<void(T&)>& featureFunction) { + m_features.emplace_back([&featureFunction](FeatureManager& featureManager) { + return featureManager.template useFeatures<T>(featureFunction, false); + }); + } + + [[nodiscard]] + const std::vector<Feature>& getList() const; + + }; + +} diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index 731d3e56..f784c130 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -18,14 +18,16 @@ int main(int argc, const char** argv) { windowHeight, true ); + + vkcv::Features features; + features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); vkcv::Core core = vkcv::Core::create( window, applicationName, VK_MAKE_VERSION(0, 0, 1), { vk::QueueFlagBits::eGraphics ,vk::QueueFlagBits::eCompute , vk::QueueFlagBits::eTransfer }, - {}, - { "VK_KHR_swapchain" } + features ); vkcv::asset::Scene mesh; diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp index 527eba8c..6ac367e4 100644 --- a/projects/first_scene/src/main.cpp +++ b/projects/first_scene/src/main.cpp @@ -29,13 +29,15 @@ int main(int argc, const char** argv) { cameraManager.getCamera(camIndex1).setNearFar(0.1f, 30.0f); + vkcv::Features features; + features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); + vkcv::Core core = vkcv::Core::create( window, applicationName, VK_MAKE_VERSION(0, 0, 1), { vk::QueueFlagBits::eGraphics ,vk::QueueFlagBits::eCompute , vk::QueueFlagBits::eTransfer }, - {}, - { "VK_KHR_swapchain" } + features ); vkcv::scene::Scene scene = vkcv::scene::Scene::load(core, std::filesystem::path( diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index 253efad4..de5d345f 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -16,14 +16,16 @@ int main(int argc, const char** argv) { windowHeight, false ); + + vkcv::Features features; + features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); vkcv::Core core = vkcv::Core::create( window, applicationName, VK_MAKE_VERSION(0, 0, 1), { vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute }, - {}, - { "VK_KHR_swapchain" } + features ); const auto& context = core.getContext(); diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp index 3a94de58..18d705ec 100644 --- a/projects/mesh_shader/src/main.cpp +++ b/projects/mesh_shader/src/main.cpp @@ -86,14 +86,21 @@ int main(int argc, const char** argv) { windowHeight, false ); + + vkcv::Features features; + features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); + features.requireExtensionFeature<vk::PhysicalDeviceMeshShaderFeaturesNV>( + VK_NV_MESH_SHADER_EXTENSION_NAME, [](vk::PhysicalDeviceMeshShaderFeaturesNV& features) { + features.setTaskShader(true); + features.setMeshShader(true); + }); vkcv::Core core = vkcv::Core::create( window, applicationName, VK_MAKE_VERSION(0, 0, 1), { vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute }, - {}, - { "VK_KHR_swapchain", VK_NV_MESH_SHADER_EXTENSION_NAME } + features ); vkcv::gui::GUI gui (core, window); diff --git a/projects/particle_simulation/src/main.cpp b/projects/particle_simulation/src/main.cpp index 07ba6b19..1aafa57f 100644 --- a/projects/particle_simulation/src/main.cpp +++ b/projects/particle_simulation/src/main.cpp @@ -24,13 +24,15 @@ int main(int argc, const char **argv) { vkcv::camera::CameraManager cameraManager(window); + vkcv::Features features; + features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); + vkcv::Core core = vkcv::Core::create( window, applicationName, VK_MAKE_VERSION(0, 0, 1), {vk::QueueFlagBits::eTransfer, vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute}, - {}, - {"VK_KHR_swapchain"} + features ); auto particleIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3, diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index e7f9caa4..3c23c7ea 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -80,14 +80,18 @@ int main(int argc, const char** argv) { cameraManager.getCamera(camIndex).setFov(glm::radians(37.8)); // fov of a 35mm lens cameraManager.getCamera(camIndex2).setNearFar(0.1f, 30.0f); - + + vkcv::Features features; + features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); + features.requireExtension(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); + features.requireExtension(VK_KHR_16BIT_STORAGE_EXTENSION_NAME); + vkcv::Core core = vkcv::Core::create( window, applicationName, VK_MAKE_VERSION(0, 0, 1), { vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute }, - {}, - { "VK_KHR_swapchain", "VK_KHR_shader_float16_int8", "VK_KHR_16bit_storage" } + features ); vkcv::asset::Scene mesh; diff --git a/src/vkcv/Context.cpp b/src/vkcv/Context.cpp index 75d409d7..f48fad1a 100644 --- a/src/vkcv/Context.cpp +++ b/src/vkcv/Context.cpp @@ -190,8 +190,8 @@ namespace vkcv Context Context::create(const char *applicationName, uint32_t applicationVersion, const std::vector<vk::QueueFlagBits>& queueFlags, - const std::vector<const char *>& instanceExtensions, - const std::vector<const char *>& deviceExtensions) { + const Features& features, + const std::vector<const char*>& instanceExtensions) { // check for layer support const std::vector<vk::LayerProperties>& layerProperties = vk::enumerateInstanceLayerProperties(); @@ -282,8 +282,8 @@ namespace vkcv features.setShaderInt16(true); }); - for (const auto& extension : deviceExtensions) { - featureManager.useExtension(extension); + for (const auto& feature : features.getList()) { + feature(featureManager); } const auto& extensions = featureManager.getActiveExtensions(); @@ -313,16 +313,6 @@ namespace vkcv deviceCreateInfo.ppEnabledLayerNames = validationLayers.data(); #endif - for (const auto& extension : deviceExtensions) { - if (0 == strcmp(extension, VK_NV_MESH_SHADER_EXTENSION_NAME)) { - featureManager.useFeatures<vk::PhysicalDeviceMeshShaderFeaturesNV>( - [](vk::PhysicalDeviceMeshShaderFeaturesNV& features) { - features.setTaskShader(true); - features.setMeshShader(true); - }); - } - } - deviceCreateInfo.setPNext(&(featureManager.getFeatures())); vk::Device device = physicalDevice.createDevice(deviceCreateInfo); diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 69da1106..1ae1c316 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -54,14 +54,14 @@ namespace vkcv const char *applicationName, uint32_t applicationVersion, const std::vector<vk::QueueFlagBits>& queueFlags, - const std::vector<const char *>& instanceExtensions, - const std::vector<const char *>& deviceExtensions) + const Features& features, + const std::vector<const char *>& instanceExtensions) { Context context = Context::create( applicationName, applicationVersion, queueFlags, - instanceExtensions, - deviceExtensions + features, + instanceExtensions ); Swapchain swapChain = Swapchain::create(window, context); diff --git a/src/vkcv/FeatureManager.cpp b/src/vkcv/FeatureManager.cpp index 416858c8..18307999 100644 --- a/src/vkcv/FeatureManager.cpp +++ b/src/vkcv/FeatureManager.cpp @@ -372,9 +372,9 @@ m_physicalDevice.getFeatures2(&query) return *this; } - bool FeatureManager::isExtensionSupported(const char *extension) const { + bool FeatureManager::isExtensionSupported(const std::string& extension) const { for (const auto& supported : m_supportedExtensions) { - if (0 == strcmp(supported, extension)) { + if (0 == strcmp(supported, extension.c_str())) { return true; } } @@ -382,16 +382,17 @@ m_physicalDevice.getFeatures2(&query) return false; } - bool FeatureManager::useExtension(const char *extension, bool required) { - const char* clone = strclone(extension); + bool FeatureManager::useExtension(const std::string& extension, bool required) { + const char* clone = strclone(extension.c_str()); if (!clone) { - vkcv_log(LogLevel::WARNING, "Extension '%s' is not valid", extension); + vkcv_log(LogLevel::WARNING, "Extension '%s' is not valid", extension.c_str()); return false; } if (!isExtensionSupported(extension)) { - vkcv_log((required? LogLevel::ERROR : LogLevel::WARNING), "Extension '%s' is not supported", extension); + vkcv_log((required? LogLevel::ERROR : LogLevel::WARNING), "Extension '%s' is not supported", + extension.c_str()); delete[] clone; return false; @@ -401,9 +402,9 @@ m_physicalDevice.getFeatures2(&query) return true; } - bool FeatureManager::isExtensionActive(const char *extension) const { + bool FeatureManager::isExtensionActive(const std::string& extension) const { for (const auto& supported : m_activeExtensions) { - if (0 == strcmp(supported, extension)) { + if (0 == strcmp(supported, extension.c_str())) { return true; } } diff --git a/src/vkcv/Features.cpp b/src/vkcv/Features.cpp new file mode 100644 index 00000000..cdfbcabb --- /dev/null +++ b/src/vkcv/Features.cpp @@ -0,0 +1,56 @@ + +#include "vkcv/Features.hpp" + +namespace vkcv { + + void Features::requireExtension(const std::string& extension) { + m_features.emplace_back([extension](FeatureManager& featureManager) { + return featureManager.useExtension(extension, true); + }); + } + + void Features::requireExtensionFeature(const std::string &extension, + const std::function<void(vk::PhysicalDeviceFeatures &)> &featureFunction) { + m_features.emplace_back([extension, &featureFunction](FeatureManager& featureManager) { + if (featureManager.useExtension(extension, true)) { + return featureManager.useFeatures(featureFunction, true); + } else { + return false; + } + }); + } + + void Features::requireFeature(const std::function<void(vk::PhysicalDeviceFeatures &)> &featureFunction) { + m_features.emplace_back([&featureFunction](FeatureManager& featureManager) { + return featureManager.useFeatures(featureFunction, true); + }); + } + + void Features::tryExtension(const std::string& extension) { + m_features.emplace_back([extension](FeatureManager& featureManager) { + return featureManager.useExtension(extension, false); + }); + } + + void Features::tryExtensionFeature(const std::string &extension, + const std::function<void(vk::PhysicalDeviceFeatures &)> &featureFunction) { + m_features.emplace_back([extension, &featureFunction](FeatureManager& featureManager) { + if (featureManager.useExtension(extension, false)) { + return featureManager.useFeatures(featureFunction, false); + } else { + return false; + } + }); + } + + void Features::tryFeature(const std::function<void(vk::PhysicalDeviceFeatures &)> &featureFunction) { + m_features.emplace_back([&featureFunction](FeatureManager& featureManager) { + return featureManager.useFeatures(featureFunction, false); + }); + } + + const std::vector<Feature>& Features::getList() const { + return m_features; + } + +} -- GitLab