diff --git a/include/vkcv/BlitDownsampler.hpp b/include/vkcv/BlitDownsampler.hpp index 380e16e5e98fe6f9f17902ce1f18be11cfec15a9..d5b7d1008bafa7e7d636e4d498fcaba997ed0da4 100644 --- a/include/vkcv/BlitDownsampler.hpp +++ b/include/vkcv/BlitDownsampler.hpp @@ -3,29 +3,29 @@ #include "Downsampler.hpp" namespace vkcv { - + class ImageManager; - + /** * @brief A class to handle downsampling via blit from a graphics queue. */ class BlitDownsampler : public Downsampler { friend class Core; + private: /** - * Reference to the image manager. - */ - ImageManager& m_imageManager; - + * Reference to the image manager. + */ + ImageManager &m_imageManager; + /** * @brief Constructor to create a blit downsampler instance. * * @param[in,out] core Reference to a Core instance * @param[in,out] imageManager Reference to an image manager */ - BlitDownsampler(Core& core, - ImageManager& imageManager); - + BlitDownsampler(Core &core, ImageManager &imageManager); + public: /** * @brief Record the commands of the downsampling instance to @@ -35,8 +35,8 @@ namespace vkcv { * @param[in] cmdStream Command stream handle * @param[in] image Image handle */ - void recordDownsampling(const CommandStreamHandle& cmdStream, - const ImageHandle& image) override; + void recordDownsampling(const CommandStreamHandle &cmdStream, + const ImageHandle &image) override; }; - -} + +} // namespace vkcv diff --git a/include/vkcv/Buffer.hpp b/include/vkcv/Buffer.hpp index 5a4afb060c8ae9048fbd2edb65c6d8167976f810..1fa30d261deb805cfafa02bc23bf8b201357525f 100644 --- a/include/vkcv/Buffer.hpp +++ b/include/vkcv/Buffer.hpp @@ -18,63 +18,58 @@ namespace vkcv { * * @tparam T Buffer content type */ - template<typename T> + template <typename T> class Buffer { public: Buffer() : m_core(nullptr), m_handle() {} - - Buffer(Core* core, const BufferHandle& handle) : m_core(core), m_handle(handle) {} - - Buffer(const Buffer& other) = default; - Buffer(Buffer&& other) noexcept = default; - + + Buffer(Core* core, const BufferHandle &handle) : m_core(core), m_handle(handle) {} + + Buffer(const Buffer &other) = default; + Buffer(Buffer &&other) noexcept = default; + ~Buffer() = default; - - Buffer& operator=(const Buffer& other) = default; - Buffer& operator=(Buffer&& other) noexcept = default; - + + Buffer &operator=(const Buffer &other) = default; + Buffer &operator=(Buffer &&other) noexcept = default; + /** * @brief Returns the buffers handle. * * @return The #BufferHandle to be used with the #Core */ - [[nodiscard]] - const BufferHandle& getHandle() const { + [[nodiscard]] const BufferHandle &getHandle() const { return m_handle; } - + /** * @brief Returns the type of the buffer. * * @return The #BufferType of the #Buffer */ - [[nodiscard]] - BufferType getType() const { + [[nodiscard]] BufferType getType() const { return m_core->getBufferType(m_handle); }; - - [[nodiscard]] - BufferMemoryType getMemoryType() const { + + [[nodiscard]] BufferMemoryType getMemoryType() const { return m_core->getBufferMemoryType(m_handle); } - + /** * @brief Returns the count of elements in the buffer. * * @return The number of objects of type T the #Buffer holds */ - [[nodiscard]] - size_t getCount() const { + [[nodiscard]] size_t getCount() const { return m_core->getBufferSize(m_handle) / sizeof(T); } - + /** * @brief Returns the size of the buffer in bytes. * * @return The size of the #Buffer in bytes */ - [[nodiscard]] - size_t getSize() const { + [[nodiscard]] size_t getSize() const { return m_core->getBufferSize(m_handle); } @@ -83,35 +78,31 @@ namespace vkcv { * * @return The vulkan handle of the #Buffer to be used for manual vulkan commands */ - [[nodiscard]] - vk::Buffer getVulkanHandle() const { - return m_core->getBuffer(m_handle); - } + [[nodiscard]] vk::Buffer getVulkanHandle() const { + return m_core->getBuffer(m_handle); + } /** * @brief Fills the #Buffer with data of type T. - * + * * @param[in] data Pointer to the array of object type T * @param[in] count The number of objects to copy from the data array * @param[in] offset The offset into the #Buffer where the data is copied into */ - void fill(const T* data, - size_t count = 0, - size_t offset = 0) { - m_core->fillBuffer(m_handle, data, count * sizeof(T), offset * sizeof(T)); + void fill(const T* data, size_t count = 0, size_t offset = 0) { + m_core->fillBuffer(m_handle, data, count * sizeof(T), offset * sizeof(T)); } - + /** * @brief Fills the #Buffer with data from a vector of type T. - * + * * @param vector Vector of type T to be copied into the #Buffer * @param offset The offset into the #Buffer where the data is copied into */ - void fill(const std::vector<T>& vector, - size_t offset = 0) { + void fill(const std::vector<T> &vector, size_t offset = 0) { fill(static_cast<const T*>(vector.data()), static_cast<size_t>(vector.size()), offset); } - + /** * @brief Reads the #Buffer directly into a data pointer of type T. * @@ -119,23 +110,20 @@ namespace vkcv { * @param[in] count The number of objects to copy from the buffer * @param[in] offset The offset into the #Buffer where the data is copied from */ - void read(T* data, - size_t count = 0, - size_t offset = 0) { + void read(T* data, size_t count = 0, size_t offset = 0) { m_core->readBuffer(m_handle, data, count * sizeof(T), offset * sizeof(T)); } - + /** * @brief Reads the #Buffer directly to a vector of type T. * * @param vector Vector of type T to be copied into from the #Buffer * @param offset The offset into the #Buffer where the data is copied from */ - void read(std::vector<T>& vector, - size_t offset = 0) { + void read(std::vector<T> &vector, size_t offset = 0) { read(static_cast<T*>(vector.data()), static_cast<size_t>(vector.size()), offset); } - + /** * @brief Maps memory to the #Buffer and returns it. * @@ -143,10 +131,9 @@ namespace vkcv { * @param[in] count Count of objects of type T that are mapped * @return Pointer to mapped memory as type T */ - [[nodiscard]] - T* map(size_t offset = 0, - size_t count = 0) { - return reinterpret_cast<T*>(m_core->mapBuffer(m_handle, offset * sizeof(T), count * sizeof(T))); + [[nodiscard]] T* map(size_t offset = 0, size_t count = 0) { + return reinterpret_cast<T*>( + m_core->mapBuffer(m_handle, offset * sizeof(T), count * sizeof(T))); } /** @@ -159,16 +146,14 @@ namespace vkcv { private: Core* m_core; BufferHandle m_handle; - }; - - template<typename T> - Buffer<T> buffer(Core& core, - BufferType type, - size_t count, + + template <typename T> + Buffer<T> buffer(Core &core, BufferType type, size_t count, BufferMemoryType memoryType = BufferMemoryType::DEVICE_LOCAL, bool readable = false) { - return Buffer<T>(&core, core.createBuffer(type, typeGuard<T>(), count, memoryType, readable)); + return Buffer<T>(&core, + core.createBuffer(type, typeGuard<T>(), count, memoryType, readable)); } - -} + +} // namespace vkcv diff --git a/include/vkcv/BufferTypes.hpp b/include/vkcv/BufferTypes.hpp index 8d2938af50efd1b57ddd131837cc2e1198edab4f..85bc0f2a1b7af5d1351bb6aae396e052743572dd 100644 --- a/include/vkcv/BufferTypes.hpp +++ b/include/vkcv/BufferTypes.hpp @@ -6,7 +6,7 @@ */ namespace vkcv { - + /** * @brief Enum class to specify types of buffers. */ @@ -17,18 +17,18 @@ namespace vkcv { STORAGE, STAGING, INDIRECT, - + UNKNOWN }; - + /** * @brief Enum class to specify types of buffer memory. */ enum class BufferMemoryType { DEVICE_LOCAL, HOST_VISIBLE, - + UNKNOWN }; - -} + +} // namespace vkcv diff --git a/include/vkcv/ComputePipelineConfig.hpp b/include/vkcv/ComputePipelineConfig.hpp index 82f3eedf54bb80f11576a2aafcc7ba3b244e61ce..8a030ba9c1a66c1b7ffcb74e283ce95e06d93243 100644 --- a/include/vkcv/ComputePipelineConfig.hpp +++ b/include/vkcv/ComputePipelineConfig.hpp @@ -8,12 +8,12 @@ #include "PipelineConfig.hpp" namespace vkcv { - + /** * @brief Class to configure a compute pipeline before its creation. */ - class ComputePipelineConfig : public PipelineConfig { + class ComputePipelineConfig : public PipelineConfig { using PipelineConfig::PipelineConfig; }; - -} \ No newline at end of file + +} // namespace vkcv \ No newline at end of file diff --git a/include/vkcv/Context.hpp b/include/vkcv/Context.hpp index 5bdd354dcecd6375054537bdb4b4fc127b98d02e..9146c59102b9e7e2cc51132f92e59274168c806e 100644 --- a/include/vkcv/Context.hpp +++ b/include/vkcv/Context.hpp @@ -5,16 +5,16 @@ * @brief Class to handle the instance, device, allocator and features of the current context. */ -#include <vulkan/vulkan.hpp> +#include <string> #include <vk_mem_alloc.hpp> +#include <vulkan/vulkan.hpp> +#include "Features.hpp" #include "Handles.hpp" #include "QueueManager.hpp" -#include "Features.hpp" -namespace vkcv -{ - +namespace vkcv { + /** * @brief Class to manage core resources for vulkan callbacks. * @@ -23,69 +23,63 @@ namespace vkcv * instances of this class will hold the feature manager and the * queue manager. */ - class Context - { - friend class Core; - public: - // explicit destruction of default constructor - Context() = delete; - // is never called directly - ~Context() noexcept; + class Context { + friend class Core; - Context(const Context &other) = delete; // copy-ctor - Context(Context &&other) noexcept; // move-ctor + public: + // explicit destruction of default constructor + Context() = delete; + // is never called directly + ~Context() noexcept; - Context & operator=(const Context &other) = delete; // copy assignment - Context & operator=(Context &&other) noexcept; // move assignment + Context(const Context &other) = delete; // copy-ctor + Context(Context &&other) noexcept; // move-ctor + + Context &operator=(const Context &other) = delete; // copy assignment + Context &operator=(Context &&other) noexcept; // move assignment /** * @brief Returns the vulkan instance of the context. * * @return Vulkan instance */ - [[nodiscard]] - const vk::Instance &getInstance() const; - + [[nodiscard]] const vk::Instance &getInstance() const; + /** * @brief Returns the vulkan physical device of the context. * * @return Vulkan physical device */ - [[nodiscard]] - const vk::PhysicalDevice &getPhysicalDevice() const; - + [[nodiscard]] const vk::PhysicalDevice &getPhysicalDevice() const; + /** * @brief Returns the vulkan device of the context. * * @return Vulkan device */ - [[nodiscard]] - const vk::Device &getDevice() const; - + [[nodiscard]] const vk::Device &getDevice() const; + /** * @brief Returns the feature manager of the context. * * @return Feature manager */ - [[nodiscard]] - const FeatureManager& getFeatureManager() const; - + [[nodiscard]] const FeatureManager &getFeatureManager() const; + /** * @brief Returns the queue manager of the context. * * @return Queue manager */ - [[nodiscard]] - const QueueManager& getQueueManager() const; - + [[nodiscard]] const QueueManager &getQueueManager() const; + /** * @brief Returns the VMA allocator of the context. * * @return VMA allocator */ - [[nodiscard]] - const vma::Allocator& getAllocator() const; - + [[nodiscard]] const vma::Allocator &getAllocator() const; + /** * @brief Creates a context for a given application with * a specific name, version, queue requirements, features and @@ -98,35 +92,30 @@ namespace vkcv * @param instanceExtensions Instance extensions * @return New context */ - static Context create(const char *applicationName, - uint32_t applicationVersion, - const std::vector<vk::QueueFlagBits>& queueFlags, - const Features& features, - const std::vector<const char*>& instanceExtensions = {}); - - private: - /** - * @brief Constructor of #Context requires an @p instance, - * a @p physicalDevice and a @p device. - * - * @param instance Vulkan-Instance - * @param physicalDevice Vulkan-PhysicalDevice - * @param device Vulkan-Device - */ - Context(vk::Instance instance, - vk::PhysicalDevice physicalDevice, - vk::Device device, - FeatureManager &&featureManager, - QueueManager &&queueManager, + static Context create(const std::string &applicationName, uint32_t applicationVersion, + const std::vector<vk::QueueFlagBits> &queueFlags, + const Features &features, + const std::vector<const char*> &instanceExtensions = {}); + + private: + /** + * @brief Constructor of #Context requires an @p instance, + * a @p physicalDevice and a @p device. + * + * @param instance Vulkan-Instance + * @param physicalDevice Vulkan-PhysicalDevice + * @param device Vulkan-Device + */ + Context(vk::Instance instance, vk::PhysicalDevice physicalDevice, vk::Device device, + FeatureManager &&featureManager, QueueManager &&queueManager, vma::Allocator &&allocator) noexcept; - - vk::Instance m_Instance; - vk::PhysicalDevice m_PhysicalDevice; - vk::Device m_Device; - FeatureManager m_FeatureManager; - QueueManager m_QueueManager; - vma::Allocator m_Allocator; - - }; - -} + + vk::Instance m_Instance; + vk::PhysicalDevice m_PhysicalDevice; + vk::Device m_Device; + FeatureManager m_FeatureManager; + QueueManager m_QueueManager; + vma::Allocator m_Allocator; + }; + +} // namespace vkcv diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index 2f158b4bd4a1e73d0933145a76686db2c6bca659..1a4ce7c8ca203661d6bb21fdfbde0beb8ac02b12 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -7,40 +7,40 @@ */ #include <memory> +#include <string> #include <vulkan/vulkan.hpp> -#include "BufferTypes.hpp" -#include "Context.hpp" -#include "Window.hpp" -#include "PassConfig.hpp" -#include "Handles.hpp" #include "BlitDownsampler.hpp" -#include "GraphicsPipelineConfig.hpp" +#include "BufferTypes.hpp" #include "ComputePipelineConfig.hpp" -#include "Result.hpp" -#include "SamplerTypes.hpp" +#include "Context.hpp" #include "DescriptorWrites.hpp" -#include "Event.hpp" +#include "DispatchSize.hpp" #include "Drawcall.hpp" -#include "PushConstants.hpp" +#include "Event.hpp" #include "EventFunctionTypes.hpp" -#include "DispatchSize.hpp" +#include "GraphicsPipelineConfig.hpp" +#include "Handles.hpp" +#include "PassConfig.hpp" +#include "PushConstants.hpp" +#include "Result.hpp" +#include "SamplerTypes.hpp" +#include "Window.hpp" #define VKCV_FRAMEWORK_NAME "VkCV" #define VKCV_FRAMEWORK_VERSION (VK_MAKE_VERSION(0, 1, 0)) -namespace vkcv -{ +namespace vkcv { - // forward declarations - class PassManager; - class GraphicsPipelineManager; - class ComputePipelineManager; - class DescriptorSetLayoutManager; + // forward declarations + class PassManager; + class GraphicsPipelineManager; + class ComputePipelineManager; + class DescriptorSetLayoutManager; class DescriptorSetManager; - class BufferManager; - class SamplerManager; - class ImageManager; + class BufferManager; + class SamplerManager; + class ImageManager; class CommandStreamManager; class WindowManager; class SwapchainManager; @@ -51,40 +51,39 @@ namespace vkcv * The class handles the core functionality of the framework with most * calls addressing resource management via more simplified abstraction. */ - class Core final { - private: - - /** - * Constructor of #Core requires an @p context. - * - * @param context encapsulates various Vulkan objects - */ - explicit Core(Context &&context) noexcept; - - // explicit destruction of default constructor - Core() = delete; + class Core final { + private: + /** + * Constructor of #Core requires an @p context. + * + * @param context encapsulates various Vulkan objects + */ + explicit Core(Context &&context) noexcept; + + // explicit destruction of default constructor + Core() = delete; Result acquireSwapchainImage(const SwapchainHandle &swapchainHandle); - Context m_Context; - - std::unique_ptr<PassManager> m_PassManager; - std::unique_ptr<GraphicsPipelineManager> m_GraphicsPipelineManager; - std::unique_ptr<ComputePipelineManager> m_ComputePipelineManager; - std::unique_ptr<DescriptorSetLayoutManager> m_DescriptorSetLayoutManager; - std::unique_ptr<DescriptorSetManager> m_DescriptorSetManager; - std::unique_ptr<BufferManager> m_BufferManager; - std::unique_ptr<SamplerManager> m_SamplerManager; - std::unique_ptr<ImageManager> m_ImageManager; - std::unique_ptr<CommandStreamManager> m_CommandStreamManager; - std::unique_ptr<WindowManager> m_WindowManager; - std::unique_ptr<SwapchainManager> m_SwapchainManager; - + Context m_Context; + + std::unique_ptr<PassManager> m_PassManager; + std::unique_ptr<GraphicsPipelineManager> m_GraphicsPipelineManager; + std::unique_ptr<ComputePipelineManager> m_ComputePipelineManager; + std::unique_ptr<DescriptorSetLayoutManager> m_DescriptorSetLayoutManager; + std::unique_ptr<DescriptorSetManager> m_DescriptorSetManager; + std::unique_ptr<BufferManager> m_BufferManager; + std::unique_ptr<SamplerManager> m_SamplerManager; + std::unique_ptr<ImageManager> m_ImageManager; + std::unique_ptr<CommandStreamManager> m_CommandStreamManager; + std::unique_ptr<WindowManager> m_WindowManager; + std::unique_ptr<SwapchainManager> m_SwapchainManager; + std::vector<vk::CommandPool> m_CommandPools; vk::Semaphore m_RenderFinished; vk::Semaphore m_SwapchainImageAcquired; uint32_t m_currentSwapchainImageIndex; - + std::unique_ptr<Downsampler> m_downsampler; /** @@ -93,55 +92,56 @@ namespace vkcv */ void setSwapchainImages(SwapchainHandle handle); - public: - /** - * Destructor of #Core destroys the Vulkan objects contained in the core's context. - */ - ~Core() noexcept; - - /** - * Copy-constructor of #Core is deleted! - * - * @param other Other instance of #Context - */ - Core(const Core& other) = delete; - - /** - * Move-constructor of #Core uses default behavior! - * - * @param other Other instance of #Context - */ - Core(Core &&other) = delete; // move-ctor - - /** - * Copy assignment operator of #Core is deleted! - * - * @param other Other instance of Context - * @return Reference to itself - */ - Core & operator=(const Core &other) = delete; - - /** - * Move assignment operator of #Core uses default behavior! - * - * @param other Other instance of Context - * @return Reference to itself - */ - Core & operator=(Core &&other) = delete; + public: + /** + * Destructor of #Core destroys the Vulkan objects contained in the core's context. + */ + ~Core() noexcept; + + /** + * Copy-constructor of #Core is deleted! + * + * @param other Other instance of #Context + */ + Core(const Core &other) = delete; + + /** + * Move-constructor of #Core uses default behavior! + * + * @param other Other instance of #Context + */ + Core(Core &&other) = delete; // move-ctor + + /** + * Copy assignment operator of #Core is deleted! + * + * @param other Other instance of Context + * @return Reference to itself + */ + Core &operator=(const Core &other) = delete; + + /** + * Move assignment operator of #Core uses default behavior! + * + * @param other Other instance of Context + * @return Reference to itself + */ + Core &operator=(Core &&other) = delete; /** * Returns the context of a Core instance. * * @return Current Context */ - [[nodiscard]] - const Context &getContext() const; + [[nodiscard]] const Context &getContext() const; - /** - * Creates a #Core with given @p applicationName and @p applicationVersion for your application. + /** + * Creates a #Core with given @p applicationName and @p applicationVersion for your + * application. * - * It is also possible to require a specific amount of queues, ask for specific queue-flags or - * extensions. This function will take care of the required arguments as best as possible. + * It is also possible to require a specific amount of queues, ask for specific queue-flags + * or extensions. This function will take care of the required arguments as best as + * possible. * * To pass a valid version for your application, you should use #VK_MAKE_VERSION(). * @@ -152,43 +152,43 @@ namespace vkcv * @param[in] deviceExtensions (optional) Requested device extensions * @return New instance of #Context */ - static Core create(const char *applicationName, - uint32_t applicationVersion, - const std::vector<vk::QueueFlagBits>& queueFlags = {}, - 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. - * Fixed Functions for pipeline are set with standard values. - * - * @param config a pipeline config object from the pipeline config class - * @param handle a handle to return the created vulkan handle - * @return True if pipeline creation was successful, False if not - */ - [[nodiscard]] - GraphicsPipelineHandle createGraphicsPipeline(const GraphicsPipelineConfig &config); - - /** - * Creates a basic vulkan compute pipeline using @p shader program and returns it using the @p handle. - * Fixed Functions for pipeline are set with standard values. - * - * @param config Contains the compiles compute shader and the corresponding descriptor set layout - * @return True if pipeline creation was successful, False if not - */ - [[nodiscard]] - ComputePipelineHandle createComputePipeline(const ComputePipelineConfig &config); - - /** - * Creates a basic vulkan render pass using @p config from the render pass config class and returns it. - * Fixed Functions for pipeline are set with standard values. - * - * @param[in] config a render pass config object from the render pass config class - * @return A handle to represent the created pass - */ - [[nodiscard]] - PassHandle createPass(const PassConfig &config); - + static Core create(const std::string &applicationName, uint32_t applicationVersion, + const std::vector<vk::QueueFlagBits> &queueFlags = {}, + 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. Fixed Functions for pipeline are set with standard + * values. + * + * @param config a pipeline config object from the pipeline config class + * @param handle a handle to return the created vulkan handle + * @return True if pipeline creation was successful, False if not + */ + [[nodiscard]] GraphicsPipelineHandle + createGraphicsPipeline(const GraphicsPipelineConfig &config); + + /** + * Creates a basic vulkan compute pipeline using @p shader program and returns it using the + * @p handle. Fixed Functions for pipeline are set with standard values. + * + * @param config Contains the compiles compute shader and the corresponding descriptor set + * layout + * @return True if pipeline creation was successful, False if not + */ + [[nodiscard]] ComputePipelineHandle + createComputePipeline(const ComputePipelineConfig &config); + + /** + * Creates a basic vulkan render pass using @p config from the render pass config class and + * returns it. Fixed Functions for pipeline are set with standard values. + * + * @param[in] config a render pass config object from the render pass config class + * @return A handle to represent the created pass + */ + [[nodiscard]] PassHandle createPass(const PassConfig &config); + /** * Returns the used configuration for a created render pass which is * represented by the given handle. @@ -196,9 +196,8 @@ namespace vkcv * @param[in] pass Pass handle * @return Pass configuration */ - [[nodiscard]] - const PassConfig& getPassConfiguration(const PassHandle &pass); - + [[nodiscard]] const PassConfig &getPassConfiguration(const PassHandle &pass); + /** * @brief Creates a buffer with given parameters and returns its handle. * @@ -209,12 +208,10 @@ namespace vkcv * @param[in] readable Flag whether the buffer supports reading from it * @return A handle to represent the created buffer */ - BufferHandle createBuffer(BufferType type, - const TypeGuard& typeGuard, - size_t count, + BufferHandle createBuffer(BufferType type, const TypeGuard &typeGuard, size_t count, BufferMemoryType memoryType = BufferMemoryType::DEVICE_LOCAL, bool readable = false); - + /** * @brief Creates a buffer with given parameters and returns its handle. * @@ -224,19 +221,18 @@ namespace vkcv * @param[in] readable Flag whether the buffer supports reading from it * @return A handle to represent the created buffer */ - BufferHandle createBuffer(BufferType type, - size_t size, + BufferHandle createBuffer(BufferType type, size_t size, BufferMemoryType memoryType = BufferMemoryType::DEVICE_LOCAL, bool readable = false); - + /** * @brief Returns the vulkan buffer of a given buffer handle. * * @param[in] buffer Buffer handle * @return Vulkan buffer */ - vk::Buffer getBuffer(const BufferHandle& buffer) const; - + vk::Buffer getBuffer(const BufferHandle &buffer) const; + /** * @brief Returns the buffer type of a buffer represented * by a given buffer handle. @@ -244,9 +240,8 @@ namespace vkcv * @param[in] buffer Buffer handle * @return Buffer type */ - [[nodiscard]] - BufferType getBufferType(const BufferHandle& buffer) const; - + [[nodiscard]] BufferType getBufferType(const BufferHandle &buffer) const; + /** * @brief Returns the buffer memory type of a buffer * represented by a given buffer handle. @@ -254,9 +249,8 @@ namespace vkcv * @param[in] buffer Buffer handle * @return Buffer memory type */ - [[nodiscard]] - BufferMemoryType getBufferMemoryType(const BufferHandle& buffer) const; - + [[nodiscard]] BufferMemoryType getBufferMemoryType(const BufferHandle &buffer) const; + /** * @brief Returns the size of a buffer represented * by a given buffer handle. @@ -264,9 +258,8 @@ namespace vkcv * @param[in] buffer Buffer handle * @return Size of the buffer */ - [[nodiscard]] - size_t getBufferSize(const BufferHandle& buffer) const; - + [[nodiscard]] size_t getBufferSize(const BufferHandle &buffer) const; + /** * @brief Fills a buffer represented by a given buffer * handle with custom data. @@ -276,11 +269,8 @@ namespace vkcv * @param[in] size Size of data in bytes * @param[in] offset Offset to fill in data in bytes */ - void fillBuffer(const BufferHandle& buffer, - const void* data, - size_t size, - size_t offset); - + void fillBuffer(const BufferHandle &buffer, const void* data, size_t size, size_t offset); + /** * @brief Reads from a buffer represented by a given * buffer handle to some data pointer. @@ -290,11 +280,8 @@ namespace vkcv * @param[in] size Size of data to read in bytes * @param[in] offset Offset to read from buffer in bytes */ - void readBuffer(const BufferHandle& buffer, - void* data, - size_t size, - size_t offset); - + void readBuffer(const BufferHandle &buffer, void* data, size_t size, size_t offset); + /** * @brief Maps memory to a buffer represented by a given * buffer handle and returns it. @@ -304,57 +291,52 @@ namespace vkcv * @param[in] size Size of mapping in bytes * @return Pointer to mapped memory */ - void* mapBuffer(const BufferHandle& buffer, - size_t offset, - size_t size); - + void* mapBuffer(const BufferHandle &buffer, size_t offset, size_t size); + /** * @brief Unmaps memory from a buffer represented by a given * buffer handle. * * @param[in] buffer Buffer handle */ - void unmapBuffer(const BufferHandle& buffer); - - /** - * Creates a Sampler with given attributes. - * - * @param[in] magFilter Magnifying filter - * @param[in] minFilter Minimizing filter - * @param[in] mipmapMode Mipmapping filter - * @param[in] addressMode Address mode - * @param[in] mipLodBias Mip level of detail bias - * @return Sampler handle - */ - [[nodiscard]] - SamplerHandle createSampler(SamplerFilterType magFilter, SamplerFilterType minFilter, - SamplerMipmapMode mipmapMode, SamplerAddressMode addressMode, - float mipLodBias = 0.0f, SamplerBorderColor borderColor = SamplerBorderColor::INT_ZERO_OPAQUE); - - /** - * Creates an #Image with a given format, width, height, depth - * and a lot more optional parameters. - * - * @param[in] format Image format - * @param[in] width Image width - * @param[in] height Image height - * @param[in] depth Image depth - * @param[in] createMipChain Flag to create a mip chain - * @param[in] supportStorage Flag whether support storage - * @param[in] supportColorAttachment Flag whether attachment is supported - * @param[in] multisampling Multisampling - * @return Image handle - */ - [[nodiscard]] - ImageHandle createImage(vk::Format format, - uint32_t width, - uint32_t height, - uint32_t depth=1, - bool createMipChain=false, - bool supportStorage=false, - bool supportColorAttachment=false, - Multisampling multisampling=Multisampling::None); - + void unmapBuffer(const BufferHandle &buffer); + + /** + * Creates a Sampler with given attributes. + * + * @param[in] magFilter Magnifying filter + * @param[in] minFilter Minimizing filter + * @param[in] mipmapMode Mipmapping filter + * @param[in] addressMode Address mode + * @param[in] mipLodBias Mip level of detail bias + * @return Sampler handle + */ + [[nodiscard]] SamplerHandle + createSampler(SamplerFilterType magFilter, SamplerFilterType minFilter, + SamplerMipmapMode mipmapMode, SamplerAddressMode addressMode, + float mipLodBias = 0.0f, + SamplerBorderColor borderColor = SamplerBorderColor::INT_ZERO_OPAQUE); + + /** + * Creates an #Image with a given format, width, height, depth + * and a lot more optional parameters. + * + * @param[in] format Image format + * @param[in] width Image width + * @param[in] height Image height + * @param[in] depth Image depth + * @param[in] createMipChain Flag to create a mip chain + * @param[in] supportStorage Flag whether support storage + * @param[in] supportColorAttachment Flag whether attachment is supported + * @param[in] multisampling Multisampling + * @return Image handle + */ + [[nodiscard]] ImageHandle createImage(vk::Format format, uint32_t width, uint32_t height, + uint32_t depth = 1, bool createMipChain = false, + bool supportStorage = false, + bool supportColorAttachment = false, + Multisampling multisampling = Multisampling::None); + /** * @brief Fills the image with given data of a specified size * in bytes. @@ -363,78 +345,67 @@ namespace vkcv * @param[in] data Image data pointer * @param[in] size Size of data */ - void fillImage(const ImageHandle& image, - const void *data, - size_t size); - + void fillImage(const ImageHandle &image, const void* data, size_t size); + /** * @brief Switches the images layout synchronously if possible. * * @param[in] image Image handle * @param[in] layout New image layout */ - void switchImageLayout(const ImageHandle &image, - vk::ImageLayout layout); - + void switchImageLayout(const ImageHandle &image, vk::ImageLayout layout); + /** * @brief Returns the default blit-downsampler. * * @return Blit-downsampler */ - [[nodiscard]] - Downsampler& getDownsampler(); - - /** - * Creates a new window and returns it's handle - * @param[in] applicationName Window title - * @param[in] windowWidth Window width - * @param[in] windowHeight Window height - * @param[in] resizeable resizeability bool - * @return windowHandle - */ - [[nodiscard]] - WindowHandle createWindow( - const char *applicationName, - uint32_t windowWidth, - uint32_t windowHeight, - bool resizeable); + [[nodiscard]] Downsampler &getDownsampler(); + + /** + * Creates a new window and returns it's handle + * @param[in] applicationName Window title + * @param[in] windowWidth Window width + * @param[in] windowHeight Window height + * @param[in] resizeable resizeability bool + * @return windowHandle + */ + [[nodiscard]] WindowHandle createWindow(const std::string &applicationName, + uint32_t windowWidth, uint32_t windowHeight, + bool resizeable); /** * Getter for window reference * @param[in] handle of the window * @return the window */ - [[nodiscard]] - Window& getWindow(const WindowHandle& handle); - + [[nodiscard]] Window &getWindow(const WindowHandle &handle); + /** - * @brief Returns the image format for the current surface - * of the swapchain. - * - * @param[in] handle Swapchain handle - * @return Swapchain image format - */ - [[nodiscard]] - vk::Format getSwapchainFormat(const SwapchainHandle& swapchain) const; - + * @brief Returns the image format for the current surface + * of the swapchain. + * + * @param[in] handle Swapchain handle + * @return Swapchain image format + */ + [[nodiscard]] vk::Format getSwapchainFormat(const SwapchainHandle &swapchain) const; + /** * @brief Returns the amount of images for the swapchain. * * @param[in] handle Swapchain handle * @return Number of images - */ - [[nodiscard]] - uint32_t getSwapchainImageCount(const SwapchainHandle& swapchain) const; - + */ + [[nodiscard]] uint32_t getSwapchainImageCount(const SwapchainHandle &swapchain) const; + /** - * @brief Returns the extent from the current surface of - * the swapchain. - * - * @param[in] handle Swapchain handle - * @return Extent of the swapchains surface - */ - [[nodiscard]] - vk::Extent2D getSwapchainExtent(const SwapchainHandle& swapchain) const; + * @brief Returns the extent from the current surface of + * the swapchain. + * + * @param[in] handle Swapchain handle + * @return Extent of the swapchains surface + */ + [[nodiscard]] vk::Extent2D getSwapchainExtent(const SwapchainHandle &swapchain) const; /** * @brief Returns the image width. @@ -442,62 +413,55 @@ namespace vkcv * @param[in] image Image handle * @return imageWidth */ - [[nodiscard]] - uint32_t getImageWidth(const ImageHandle &image); - - /** - * @brief Returns the image height. - * - * @param[in] image Image handle - * @return imageHeight - */ - [[nodiscard]] - uint32_t getImageHeight(const ImageHandle &image); - - /** - * @brief Returns the image depth. - * - * @param[in] image Image handle - * @return imageDepth - */ - [[nodiscard]] - uint32_t getImageDepth(const ImageHandle &image); - - /** - * @brief Returns the image format of the image. - * - * @param[in] image Image handle - * @return imageFormat - */ - [[nodiscard]] - vk::Format getImageFormat(const ImageHandle &image); - + [[nodiscard]] uint32_t getImageWidth(const ImageHandle &image); + + /** + * @brief Returns the image height. + * + * @param[in] image Image handle + * @return imageHeight + */ + [[nodiscard]] uint32_t getImageHeight(const ImageHandle &image); + + /** + * @brief Returns the image depth. + * + * @param[in] image Image handle + * @return imageDepth + */ + [[nodiscard]] uint32_t getImageDepth(const ImageHandle &image); + + /** + * @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); - + [[nodiscard]] bool isImageSupportingStorage(const ImageHandle &image); + /** * @brief Returns the images amount of mip levels. * * @param[in] image Image handle * @return Amount of mip levels */ - [[nodiscard]] - uint32_t getImageMipLevels(const ImageHandle &image); - + [[nodiscard]] uint32_t getImageMipLevels(const ImageHandle &image); + /** * @brief Returns the images amount of array layers. * * @param[in] image Image handle * @return Amount of array layers */ - [[nodiscard]] - uint32_t getImageArrayLayers(const ImageHandle &image); + [[nodiscard]] uint32_t getImageArrayLayers(const ImageHandle &image); /** * @brief Creates a descriptor set layout handle by a set of descriptor bindings. @@ -505,145 +469,145 @@ namespace vkcv * @param[in] bindings Descriptor bindings * @return Descriptor set layout handle */ - [[nodiscard]] - DescriptorSetLayoutHandle createDescriptorSetLayout(const DescriptorBindings &bindings); + [[nodiscard]] DescriptorSetLayoutHandle + createDescriptorSetLayout(const DescriptorBindings &bindings); /** * @brief Creates a new descriptor set - * + * * @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 &layout); + [[nodiscard]] DescriptorSetHandle + createDescriptorSet(const DescriptorSetLayoutHandle &layout); /** * @brief Writes resources bindings to a descriptor set - * + * * @param handle Handle of the descriptor set * @param writes Struct containing the resource bindings to be written * must be compatible with the descriptor set's layout - */ - void writeDescriptorSet(DescriptorSetHandle handle, const DescriptorWrites& writes); - + */ + void writeDescriptorSet(DescriptorSetHandle handle, const DescriptorWrites &writes); /** * @brief Start recording command buffers and increment frame index - */ - bool beginFrame(uint32_t& width, uint32_t& height, const WindowHandle &windowHandle); + */ + bool beginFrame(uint32_t &width, uint32_t &height, const WindowHandle &windowHandle); /** * @brief Records drawcalls to a command stream - * + * * @param cmdStreamHandle Handle of the command stream that the drawcalls are recorded into * @param pipelineHandle Handle of the pipeline that is used for the drawcalls - * @param pushConstants Push constants that are used for the drawcalls, ignored if constant size is set to 0 - * @param drawcalls Information about each drawcall, consisting of mesh handle, descriptor set bindings and instance count + * @param pushConstants Push constants that are used for the drawcalls, ignored if constant + * size is set to 0 + * @param drawcalls Information about each drawcall, consisting of mesh handle, descriptor + * set bindings and instance count * @param renderTargets Image handles that are used as render targets * @param windowHandle Window handle that is used to retrieve the corresponding swapchain - */ - void recordDrawcallsToCmdStream( - const CommandStreamHandle &cmdStreamHandle, - const GraphicsPipelineHandle &pipelineHandle, - const PushConstants &pushConstants, - const std::vector<InstanceDrawcall> &drawcalls, - const std::vector<ImageHandle> &renderTargets, - const WindowHandle &windowHandle); - + */ + void recordDrawcallsToCmdStream(const CommandStreamHandle &cmdStreamHandle, + const GraphicsPipelineHandle &pipelineHandle, + const PushConstants &pushConstants, + const std::vector<InstanceDrawcall> &drawcalls, + const std::vector<ImageHandle> &renderTargets, + const WindowHandle &windowHandle); + /** * @brief Records indirect drawcalls to a command stream * * @param cmdStreamHandle Handle of the command stream that the drawcalls are recorded into * @param pipelineHandle Handle of the pipeline that is used for the drawcalls - * @param pushConstantData Push constants that are used for the drawcalls, ignored if constant size is set to 0 - * @param drawcalls Information about each drawcall, consisting of mesh handle, descriptor set bindings and draw count + * @param pushConstantData Push constants that are used for the drawcalls, ignored if + * constant size is set to 0 + * @param drawcalls Information about each drawcall, consisting of mesh handle, descriptor + * set bindings and draw count * @param renderTargets Image handles that are used as render targets * @param windowHandle Window handle that is used to retrieve the corresponding swapchain - */ - void recordIndirectDrawcallsToCmdStream( - const CommandStreamHandle cmdStreamHandle, - const GraphicsPipelineHandle &pipelineHandle, - const PushConstants &pushConstantData, - const std::vector<IndirectDrawcall> &drawcalls, - const std::vector<ImageHandle> &renderTargets, - const WindowHandle &windowHandle); - + */ + void recordIndirectDrawcallsToCmdStream(const CommandStreamHandle cmdStreamHandle, + const GraphicsPipelineHandle &pipelineHandle, + const PushConstants &pushConstantData, + const std::vector<IndirectDrawcall> &drawcalls, + const std::vector<ImageHandle> &renderTargets, + const WindowHandle &windowHandle); + /** * @brief Records mesh shader drawcalls to a command stream * * @param cmdStreamHandle Handle of the command stream that the drawcalls are recorded into * @param pipelineHandle Handle of the pipeline that is used for the drawcalls - * @param pushConstantData Push constants that are used for the drawcalls, ignored if constant size is set to 0 - * @param drawcalls Information about each drawcall, consisting of descriptor set bindings and task shader task count + * @param pushConstantData Push constants that are used for the drawcalls, ignored if + * constant size is set to 0 + * @param drawcalls Information about each drawcall, consisting of descriptor set bindings + * and task shader task count * @param renderTargets Image handles that are used as render targets * @param windowHandle Window handle that is used to retrieve the corresponding swapchain - */ - void recordMeshShaderDrawcalls( - const CommandStreamHandle &cmdStreamHandle, - const GraphicsPipelineHandle &pipelineHandle, - const PushConstants &pushConstantData, - const std::vector<TaskDrawcall> &drawcalls, - const std::vector<ImageHandle> &renderTargets, - const WindowHandle &windowHandle); - - /** - * Records the rtx ray generation to the @p cmdStreamHandle. - * Currently only supports @p closestHit, @p rayGen and @c miss shaderstages @c. - * - * @param cmdStreamHandle The command stream handle which receives relevant commands for drawing. - * @param rtxPipeline The raytracing pipeline from the RTXModule. - * @param rtxPipelineLayout The raytracing pipeline layout from the RTXModule. - * @param rgenRegion The shader binding table region for ray generation shaders. - * @param rmissRegion The shader binding table region for ray miss shaders. - * @param rchitRegion The shader binding table region for ray closest hit shaders. - * @param rcallRegion The shader binding table region for callable shaders. - * @param descriptorSetUsages The descriptor set usages. - * @param pushConstants The push constants. - * @param windowHandle The window handle defining in which window to render. - */ - void recordRayGenerationToCmdStream( - CommandStreamHandle cmdStreamHandle, - vk::Pipeline rtxPipeline, - vk::PipelineLayout rtxPipelineLayout, - vk::StridedDeviceAddressRegionKHR rgenRegion, - vk::StridedDeviceAddressRegionKHR rmissRegion, - vk::StridedDeviceAddressRegionKHR rchitRegion, - vk::StridedDeviceAddressRegionKHR rcallRegion, - const std::vector<DescriptorSetUsage>& descriptorSetUsages, - const PushConstants& pushConstants, - const WindowHandle& windowHandle); + */ + void recordMeshShaderDrawcalls(const CommandStreamHandle &cmdStreamHandle, + const GraphicsPipelineHandle &pipelineHandle, + const PushConstants &pushConstantData, + const std::vector<TaskDrawcall> &drawcalls, + const std::vector<ImageHandle> &renderTargets, + const WindowHandle &windowHandle); + + /** + * Records the rtx ray generation to the @p cmdStreamHandle. + * Currently only supports @p closestHit, @p rayGen and @c miss shaderstages @c. + * + * @param cmdStreamHandle The command stream handle which receives relevant commands for + * drawing. + * @param rtxPipeline The raytracing pipeline from the RTXModule. + * @param rtxPipelineLayout The raytracing pipeline layout from the RTXModule. + * @param rgenRegion The shader binding table region for ray generation shaders. + * @param rmissRegion The shader binding table region for ray miss shaders. + * @param rchitRegion The shader binding table region for ray closest hit shaders. + * @param rcallRegion The shader binding table region for callable shaders. + * @param descriptorSetUsages The descriptor set usages. + * @param pushConstants The push constants. + * @param windowHandle The window handle defining in which window to render. + */ + void recordRayGenerationToCmdStream( + CommandStreamHandle cmdStreamHandle, vk::Pipeline rtxPipeline, + vk::PipelineLayout rtxPipelineLayout, vk::StridedDeviceAddressRegionKHR rgenRegion, + vk::StridedDeviceAddressRegionKHR rmissRegion, + vk::StridedDeviceAddressRegionKHR rchitRegion, + vk::StridedDeviceAddressRegionKHR rcallRegion, + const std::vector<DescriptorSetUsage> &descriptorSetUsages, + const PushConstants &pushConstants, const WindowHandle &windowHandle); /** * @brief Record a compute shader dispatch into a command stream - * + * * @param cmdStream Handle of the command stream that the dispatch is recorded into * @param computePipeline Handle of the pipeline that is used for the dispatch * @param dispatchSize How many work groups are dispatched * @param descriptorSetUsages Descriptor set usages of the dispatch * @param pushConstants Push constant data for the dispatch */ - void recordComputeDispatchToCmdStream(const CommandStreamHandle& cmdStream, - const ComputePipelineHandle& computePipeline, - const DispatchSize& dispatchSize, - const std::vector<DescriptorSetUsage> &descriptorSetUsages, - const PushConstants& pushConstants); - + void + recordComputeDispatchToCmdStream(const CommandStreamHandle &cmdStream, + const ComputePipelineHandle &computePipeline, + const DispatchSize &dispatchSize, + const std::vector<DescriptorSetUsage> &descriptorSetUsages, + const PushConstants &pushConstants); + /** - * @brief Record the start of a debug label into a command stream. + * @brief Record the start of a debug label into a command stream. * Debug labels are displayed in GPU debuggers, such as RenderDoc - * + * * @param cmdStream Handle of the command stream that the label start is recorded into * @param label Label name, which is displayed in a debugger * @param color Display color for the label in a debugger - */ - void recordBeginDebugLabel(const CommandStreamHandle &cmdStream, - const std::string& label, - const std::array<float, 4>& color); - + */ + void recordBeginDebugLabel(const CommandStreamHandle &cmdStream, const std::string &label, + const std::array<float, 4> &color); + /** * @brief Record the end of a debug label into a command stream * @param cmdStream Handle of the command stream that the label end is recorded into - */ + */ void recordEndDebugLabel(const CommandStreamHandle &cmdStream); /** @@ -657,21 +621,19 @@ namespace vkcv * @param pushConstants Push constant data for the indirect dispatch */ void recordComputeIndirectDispatchToCmdStream( - const CommandStreamHandle cmdStream, - const ComputePipelineHandle computePipeline, - const vkcv::BufferHandle buffer, - const size_t bufferArgOffset, - const std::vector<DescriptorSetUsage>& descriptorSetUsages, - const PushConstants& pushConstants); + const CommandStreamHandle cmdStream, const ComputePipelineHandle computePipeline, + const vkcv::BufferHandle buffer, const size_t bufferArgOffset, + const std::vector<DescriptorSetUsage> &descriptorSetUsages, + const PushConstants &pushConstants); /** * @brief End recording and present image */ - void endFrame( const WindowHandle& windowHandle ); + void endFrame(const WindowHandle &windowHandle); /** * @brief Create a new command stream - * + * * @param queueType The type of queue to which the command stream will be submitted to * @return Handle which represents the command stream */ @@ -679,46 +641,42 @@ namespace vkcv /** * @brief Record commands to a command stream by providing a function - * + * * @param cmdStreamHandle Handle of the command stream to record to * @param record Recording function * @param finish Finish function, called after execution of commands is finished */ - void recordCommandsToStream( - const CommandStreamHandle &stream, - const RecordCommandFunction &record, - const FinishCommandFunction &finish); + void recordCommandsToStream(const CommandStreamHandle &stream, + const RecordCommandFunction &record, + const FinishCommandFunction &finish); /** * @brief Submit command stream to GPU for actual execution - * + * * @param[in] handle Command stream to submit * @param[in] signalRendering Flag to specify if the command stream finishes rendering */ - void submitCommandStream(const CommandStreamHandle& stream, - bool signalRendering = true); + void submitCommandStream(const CommandStreamHandle &stream, bool signalRendering = true); /** * @brief Prepare swapchain image for presentation to screen. * Handles internal state such as image format, also acts as a memory barrier - * + * * @param handle Handle of the command stream to record the preparation commands to */ - void prepareSwapchainImageForPresent(const CommandStreamHandle& handle); + void prepareSwapchainImageForPresent(const CommandStreamHandle &handle); /** * @brief Prepare image for use as a sampled image. * Handles internal state such as image format, also acts as a memory barrier - * + * * @param[in] cmdStream Handle of the command stream to record the preparation commands to * @param[in] image Handle of the image to prepare * @param[in] mipLevelCount Count of mip levels to prepare * @param[in] mipLevelOffset Offset to start preparing mip levels */ - void prepareImageForSampling(const CommandStreamHandle& cmdStream, - const ImageHandle& image, - uint32_t mipLevelCount = 0, - uint32_t mipLevelOffset = 0); + void prepareImageForSampling(const CommandStreamHandle &cmdStream, const ImageHandle &image, + uint32_t mipLevelCount = 0, uint32_t mipLevelOffset = 0); /** * @brief Prepare image for use as a storage image. @@ -729,84 +687,86 @@ namespace vkcv * @param[in] mipLevelCount Count of mip levels to prepare * @param[in] mipLevelOffset Offset to start preparing mip levels */ - void prepareImageForStorage(const CommandStreamHandle& cmdStream, - const ImageHandle& image, - uint32_t mipLevelCount = 0, - uint32_t mipLevelOffset = 0); - + void prepareImageForStorage(const CommandStreamHandle &cmdStream, const ImageHandle &image, + uint32_t mipLevelCount = 0, uint32_t mipLevelOffset = 0); + /** * @brief Manual trigger to record commands to prepare an image for use as an attachment * * normally layout transitions for attachments are handled by the core * however for manual vulkan use, e.g. ImGui integration, this function is exposed - * this is also why the command buffer is passed directly, instead of the command stream handle - * + * this is also why the command buffer is passed directly, instead of the command stream + * handle + * * @param cmdBuffer The vulkan command buffer to record to * @param image Handle of the image to prepare */ - void prepareImageForAttachmentManually(const vk::CommandBuffer& cmdBuffer, const ImageHandle& image); + void prepareImageForAttachmentManually(const vk::CommandBuffer &cmdBuffer, + const ImageHandle &image); /** * @brief Indicate an external change of an image's layout - * - * if manual vulkan work, e.g. ImGui integration, changes an image layout this function must be used - * to update the internal image state - * + * + * if manual vulkan work, e.g. ImGui integration, changes an image layout this function must + * be used to update the internal image state + * * @param image Handle of the image whose layout was changed * @param layout The current layout of the image - */ - void updateImageLayoutManual(const vkcv::ImageHandle& image, const vk::ImageLayout layout); + */ + void updateImageLayoutManual(const vkcv::ImageHandle &image, const vk::ImageLayout layout); /** * @brief Records a memory barrier to synchronize subsequent accesses to the image's data - * + * * @param cmdStream Handle of the command stream to record the barrier to * @param image Handle of the image the barrier belongs to */ - void recordImageMemoryBarrier(const CommandStreamHandle& cmdStream, const ImageHandle& image); + void recordImageMemoryBarrier(const CommandStreamHandle &cmdStream, + const ImageHandle &image); /** * @brief Records a buffer barrier to synchronize subsequent accesses to the buffer's data - * + * * @param cmdStream Handle of the command stream to record the barrier to * @param buffer Handle of the buffer the barrier belongs to */ - void recordBufferMemoryBarrier(const CommandStreamHandle& cmdStream, const BufferHandle& buffer); + void recordBufferMemoryBarrier(const CommandStreamHandle &cmdStream, + const BufferHandle &buffer); /** * @brief Resolve a source MSAA image into a destination image for further use - * + * * @param cmdStream Handle of the command stream to record the resolve to * @param src The MSAA image that is resolved * @param dst The target non-MSAA image that is resolved into */ - void resolveMSAAImage(const CommandStreamHandle& cmdStream, const ImageHandle& src, const ImageHandle& dst); + void resolveMSAAImage(const CommandStreamHandle &cmdStream, const ImageHandle &src, + const ImageHandle &dst); /** * @return Vulkan image view of the current swapchain image */ - [[nodiscard]] - vk::ImageView getSwapchainImageView() const; - + [[nodiscard]] vk::ImageView getSwapchainImageView() const; + /** * @brief Records a generic memory barrier to a command stream - * + * * @param cmdStream Handle of the command stream the barrier is recorded to */ - void recordMemoryBarrier(const CommandStreamHandle& cmdStream); - + void recordMemoryBarrier(const CommandStreamHandle &cmdStream); + /** - * @brief Record a blit (bit block image transfer) of a source image into a destination image, - * mip 0 is used for both - * + * @brief Record a blit (bit block image transfer) of a source image into a destination + * image, mip 0 is used for both + * * @param cmdStream Handle of the command stream the blit operation is recorded into * @param src The source image that is read from * @param dst The destination image that is written into * @param filterType The type of interpolation that is used */ - void recordBlitImage(const CommandStreamHandle& cmdStream, const ImageHandle& src, const ImageHandle& dst, - SamplerFilterType filterType); - + void recordBlitImage(const CommandStreamHandle &cmdStream, const ImageHandle &src, + const ImageHandle &dst, SamplerFilterType filterType); + /** * @brief Sets a debug label to a buffer handle. * @@ -814,7 +774,7 @@ namespace vkcv * @param[in] label Debug label */ void setDebugLabel(const BufferHandle &handle, const std::string &label); - + /** * @brief Sets a debug label to a pass handle. * @@ -822,7 +782,7 @@ namespace vkcv * @param[in] label Debug label */ void setDebugLabel(const PassHandle &handle, const std::string &label); - + /** * @brief Sets a debug label to a graphics pipeline handle. * @@ -830,7 +790,7 @@ namespace vkcv * @param[in] label Debug label */ void setDebugLabel(const GraphicsPipelineHandle &handle, const std::string &label); - + /** * @brief Sets a debug label to a compute pipeline handle. * @@ -838,7 +798,7 @@ namespace vkcv * @param[in] label Debug label */ void setDebugLabel(const ComputePipelineHandle &handle, const std::string &label); - + /** * @brief Sets a debug label to a descriptor set handle. * @@ -846,7 +806,7 @@ namespace vkcv * @param[in] label Debug label */ void setDebugLabel(const DescriptorSetHandle &handle, const std::string &label); - + /** * @brief Sets a debug label to a sampler handle. * @@ -854,7 +814,7 @@ namespace vkcv * @param[in] label Debug label */ void setDebugLabel(const SamplerHandle &handle, const std::string &label); - + /** * @brief Sets a debug label to an image handle. * @@ -862,7 +822,7 @@ namespace vkcv * @param[in] label Debug label */ void setDebugLabel(const ImageHandle &handle, const std::string &label); - + /** * @brief Sets a debug label to a command stream handle. * @@ -870,7 +830,7 @@ namespace vkcv * @param[in] label Debug label */ void setDebugLabel(const CommandStreamHandle &handle, const std::string &label); - + /** * @brief Runs the application in the current until all windows get closed. * @@ -879,7 +839,7 @@ namespace vkcv * @param[in] frame Frame callback */ void run(const WindowFrameFunction &frame); - + /** * @brief Return the underlying vulkan handle for a render pass * by its given pass handle. @@ -887,9 +847,8 @@ namespace vkcv * @param[in] handle Pass handle * @return Vulkan render pass */ - [[nodiscard]] - vk::RenderPass getVulkanRenderPass(const PassHandle &handle) const; - + [[nodiscard]] vk::RenderPass getVulkanRenderPass(const PassHandle &handle) const; + /** * @brief Return the underlying vulkan handle for a pipeline * by its given graphics pipeline handle. @@ -897,9 +856,8 @@ namespace vkcv * @param[in] handle Graphics pipeline handle * @return Vulkan pipeline */ - [[nodiscard]] - vk::Pipeline getVulkanPipeline(const GraphicsPipelineHandle &handle) const; - + [[nodiscard]] vk::Pipeline getVulkanPipeline(const GraphicsPipelineHandle &handle) const; + /** * @brief Return the underlying vulkan handle for a pipeline * by its given compute pipeline handle. @@ -907,9 +865,8 @@ namespace vkcv * @param[in] handle Compute pipeline handle * @return Vulkan pipeline */ - [[nodiscard]] - vk::Pipeline getVulkanPipeline(const ComputePipelineHandle &handle) const; - + [[nodiscard]] vk::Pipeline getVulkanPipeline(const ComputePipelineHandle &handle) const; + /** * @brief Return the underlying vulkan handle for a descriptor set layout * by its given descriptor set layout handle. @@ -917,9 +874,9 @@ namespace vkcv * @param[in] handle Descriptor set layout handle * @return Vulkan descriptor set layout */ - [[nodiscard]] - vk::DescriptorSetLayout getVulkanDescriptorSetLayout(const DescriptorSetLayoutHandle &handle) const; - + [[nodiscard]] vk::DescriptorSetLayout + getVulkanDescriptorSetLayout(const DescriptorSetLayoutHandle &handle) const; + /** * @brief Return the underlying vulkan handle for a descriptor set * by its given descriptor set handle. @@ -927,9 +884,9 @@ namespace vkcv * @param[in] handle Descriptor set handle * @return Vulkan descriptor set */ - [[nodiscard]] - vk::DescriptorSet getVulkanDescriptorSet(const DescriptorSetHandle &handle) const; - + [[nodiscard]] vk::DescriptorSet + getVulkanDescriptorSet(const DescriptorSetHandle &handle) const; + /** * @brief Return the underlying vulkan handle for a buffer * by its given buffer handle. @@ -937,9 +894,8 @@ namespace vkcv * @param[in] handle Buffer handle * @return Vulkan buffer */ - [[nodiscard]] - vk::Buffer getVulkanBuffer(const BufferHandle &handle) const; - + [[nodiscard]] vk::Buffer getVulkanBuffer(const BufferHandle &handle) const; + /** * @brief Return the underlying vulkan handle for a sampler * by its given sampler handle. @@ -947,9 +903,8 @@ namespace vkcv * @param[in] handle Sampler handle * @return Vulkan sampler */ - [[nodiscard]] - vk::Sampler getVulkanSampler(const SamplerHandle &handle) const; - + [[nodiscard]] vk::Sampler getVulkanSampler(const SamplerHandle &handle) const; + /** * @brief Return the underlying vulkan handle for a image * by its given image handle. @@ -957,9 +912,8 @@ namespace vkcv * @param[in] handle Image handle * @return Vulkan image */ - [[nodiscard]] - vk::Image getVulkanImage(const ImageHandle &handle) const; - + [[nodiscard]] vk::Image getVulkanImage(const ImageHandle &handle) const; + /** * @brief Return the underlying vulkan handle for a image view * by its given image handle. @@ -967,9 +921,8 @@ namespace vkcv * @param[in] handle Image handle * @return Vulkan image view */ - [[nodiscard]] - vk::ImageView getVulkanImageView(const ImageHandle &handle) const; - + [[nodiscard]] vk::ImageView getVulkanImageView(const ImageHandle &handle) const; + /** * @brief Return the underlying vulkan handle for a device memory * by its given buffer handle. @@ -977,9 +930,8 @@ namespace vkcv * @param[in] handle Buffer handle * @return Vulkan device memory */ - [[nodiscard]] - vk::DeviceMemory getVulkanDeviceMemory(const BufferHandle &handle) const; - + [[nodiscard]] vk::DeviceMemory getVulkanDeviceMemory(const BufferHandle &handle) const; + /** * @brief Return the underlying vulkan handle for a device memory * by its given image handle. @@ -987,8 +939,6 @@ namespace vkcv * @param[in] handle Image handle * @return Vulkan device memory */ - [[nodiscard]] - vk::DeviceMemory getVulkanDeviceMemory(const ImageHandle &handle) const; - - }; -} + [[nodiscard]] vk::DeviceMemory getVulkanDeviceMemory(const ImageHandle &handle) const; + }; +} // namespace vkcv diff --git a/include/vkcv/DescriptorBinding.hpp b/include/vkcv/DescriptorBinding.hpp index c0a8a670779bd8342995f9287770b857f3373bc8..c97d1dfebc6d4415c04f51a761ddcdbc34ba6d68 100644 --- a/include/vkcv/DescriptorBinding.hpp +++ b/include/vkcv/DescriptorBinding.hpp @@ -11,7 +11,7 @@ #include "ShaderStage.hpp" namespace vkcv { - + /** * @brief Structure to store details from a descriptor binding. */ @@ -22,10 +22,10 @@ namespace vkcv { ShaderStages shaderStages; bool variableCount; bool partialBinding; - - bool operator ==(const DescriptorBinding &other) const; + + bool operator==(const DescriptorBinding &other) const; }; - + typedef std::unordered_map<uint32_t, DescriptorBinding> DescriptorBindings; - -} + +} // namespace vkcv diff --git a/include/vkcv/DescriptorSetUsage.hpp b/include/vkcv/DescriptorSetUsage.hpp index 8bbf2c9625ae029665b20890a7978be867a81152..098d1846c35b3724fb2540ebb41a1b6cd61d62fc 100644 --- a/include/vkcv/DescriptorSetUsage.hpp +++ b/include/vkcv/DescriptorSetUsage.hpp @@ -10,7 +10,7 @@ #include "Handles.hpp" namespace vkcv { - + /** * @brief Structure to configure a descriptor set usage. */ @@ -19,9 +19,8 @@ namespace vkcv { DescriptorSetHandle descriptorSet; std::vector<uint32_t> dynamicOffsets; }; - - DescriptorSetUsage useDescriptorSet(uint32_t location, - const DescriptorSetHandle &descriptorSet, + + DescriptorSetUsage useDescriptorSet(uint32_t location, const DescriptorSetHandle &descriptorSet, const std::vector<uint32_t> &dynamicOffsets = {}); - -} + +} // namespace vkcv diff --git a/include/vkcv/DescriptorTypes.hpp b/include/vkcv/DescriptorTypes.hpp index eaa739d6d33359b7306254677e323fb1827ca5f0..75035b2071554e8b2fe7c8309b5b8269c0c0ca72 100644 --- a/include/vkcv/DescriptorTypes.hpp +++ b/include/vkcv/DescriptorTypes.hpp @@ -4,11 +4,11 @@ * @file vkcv/DescriptorConfig.hpp * @brief Enum classes to handle descriptor types. */ - + #include <vulkan/vulkan.hpp> - + namespace vkcv { - + /** * @brief Enum class to specify the type of a descriptor set binding. */ @@ -22,36 +22,35 @@ namespace vkcv { STORAGE_BUFFER_DYNAMIC, ACCELERATION_STRUCTURE_KHR }; - + /** - * @brief Converts the descriptor type from the frameworks enumeration - * to the Vulkan type specifier. - * - * @param[in] type Descriptor type - * @return Vulkan descriptor type - */ + * @brief Converts the descriptor type from the frameworks enumeration + * to the Vulkan type specifier. + * + * @param[in] type Descriptor type + * @return Vulkan descriptor type + */ constexpr vk::DescriptorType getVkDescriptorType(DescriptorType type) noexcept { - switch (type) - { - case DescriptorType::UNIFORM_BUFFER: - return vk::DescriptorType::eUniformBuffer; - case DescriptorType::UNIFORM_BUFFER_DYNAMIC: - return vk::DescriptorType::eUniformBufferDynamic; - case DescriptorType::STORAGE_BUFFER: - return vk::DescriptorType::eStorageBuffer; - case DescriptorType::STORAGE_BUFFER_DYNAMIC: - return vk::DescriptorType::eStorageBufferDynamic; - case DescriptorType::SAMPLER: - return vk::DescriptorType::eSampler; - case DescriptorType::IMAGE_SAMPLED: - return vk::DescriptorType::eSampledImage; - case DescriptorType::IMAGE_STORAGE: - return vk::DescriptorType::eStorageImage; - case DescriptorType::ACCELERATION_STRUCTURE_KHR: - return vk::DescriptorType::eAccelerationStructureKHR; - default: - return vk::DescriptorType::eMutableVALVE; + switch (type) { + case DescriptorType::UNIFORM_BUFFER: + return vk::DescriptorType::eUniformBuffer; + case DescriptorType::UNIFORM_BUFFER_DYNAMIC: + return vk::DescriptorType::eUniformBufferDynamic; + case DescriptorType::STORAGE_BUFFER: + return vk::DescriptorType::eStorageBuffer; + case DescriptorType::STORAGE_BUFFER_DYNAMIC: + return vk::DescriptorType::eStorageBufferDynamic; + case DescriptorType::SAMPLER: + return vk::DescriptorType::eSampler; + case DescriptorType::IMAGE_SAMPLED: + return vk::DescriptorType::eSampledImage; + case DescriptorType::IMAGE_STORAGE: + return vk::DescriptorType::eStorageImage; + case DescriptorType::ACCELERATION_STRUCTURE_KHR: + return vk::DescriptorType::eAccelerationStructureKHR; + default: + return vk::DescriptorType::eMutableVALVE; } } -} +} // namespace vkcv diff --git a/include/vkcv/DescriptorWrites.hpp b/include/vkcv/DescriptorWrites.hpp index 869b1061af8f8da217978f962fd68d41ba289cad..cfadbde29b31edf0fc5c2df1e5dcbff0cdf897f2 100644 --- a/include/vkcv/DescriptorWrites.hpp +++ b/include/vkcv/DescriptorWrites.hpp @@ -11,7 +11,7 @@ #include "Handles.hpp" namespace vkcv { - + /** * @brief Structure to store details writing a sampled image to a descriptor set. */ @@ -24,7 +24,7 @@ namespace vkcv { uint32_t mipCount; bool arrayView; }; - + /** * @brief Structure to store details writing a storage image to a descriptor set. */ @@ -35,7 +35,7 @@ namespace vkcv { uint32_t mipCount; bool arrayView; }; - + /** * @brief Structure to store details writing a buffer to a descriptor set. */ @@ -46,7 +46,7 @@ namespace vkcv { uint32_t offset; uint32_t size; }; - + /** * @brief Structure to store details writing a sampler to a descriptor set. */ @@ -54,13 +54,13 @@ namespace vkcv { uint32_t binding; SamplerHandle sampler; }; - + /** * @brief Structure to store details writing an acceleration structure to * a descriptor set. */ struct AccelerationDescriptorWrite { - uint32_t binding; + uint32_t binding; std::vector<vk::AccelerationStructureKHR> structures; }; @@ -76,7 +76,7 @@ namespace vkcv { std::vector<BufferDescriptorWrite> m_storageBufferWrites; std::vector<SamplerDescriptorWrite> m_samplerWrites; std::vector<AccelerationDescriptorWrite> m_accelerationWrites; - + public: /** * @brief Adds an entry to write an image to a given binding @@ -90,14 +90,11 @@ namespace vkcv { * @param[in] mipCount Mip level count * @return Instance of descriptor writes */ - DescriptorWrites& writeSampledImage(uint32_t binding, - ImageHandle image, - uint32_t mipLevel = 0, - bool useGeneralLayout = false, - uint32_t arrayIndex = 0, - uint32_t mipCount = 1, + DescriptorWrites &writeSampledImage(uint32_t binding, ImageHandle image, + uint32_t mipLevel = 0, bool useGeneralLayout = false, + uint32_t arrayIndex = 0, uint32_t mipCount = 1, bool arrayView = false); - + /** * @brief Adds an entry to write an image to a given binding * of a descriptor set to store into it using specific details. @@ -108,12 +105,10 @@ namespace vkcv { * @param[in] mipCount Mip level count * @return Instance of descriptor writes */ - DescriptorWrites& writeStorageImage(uint32_t binding, - ImageHandle image, - uint32_t mipLevel = 0, - uint32_t mipCount = 1, + DescriptorWrites &writeStorageImage(uint32_t binding, ImageHandle image, + uint32_t mipLevel = 0, uint32_t mipCount = 1, bool arrayView = false); - + /** * @brief Adds an entry to write a buffer to a given binding * of a descriptor set as uniform buffer using specific details. @@ -125,12 +120,10 @@ namespace vkcv { * @param[in] size Size of the buffer access range * @return Instance of descriptor writes */ - DescriptorWrites& writeUniformBuffer(uint32_t binding, - BufferHandle buffer, - bool dynamic = false, - uint32_t offset = 0, + DescriptorWrites &writeUniformBuffer(uint32_t binding, BufferHandle buffer, + bool dynamic = false, uint32_t offset = 0, uint32_t size = 0); - + /** * @brief Adds an entry to write a buffer to a given binding * of a descriptor set as storage buffer using specific details. @@ -142,12 +135,10 @@ namespace vkcv { * @param[in] size Size of the buffer access range * @return Instance of descriptor writes */ - DescriptorWrites& writeStorageBuffer(uint32_t binding, - BufferHandle buffer, - bool dynamic = false, - uint32_t offset = 0, + DescriptorWrites &writeStorageBuffer(uint32_t binding, BufferHandle buffer, + bool dynamic = false, uint32_t offset = 0, uint32_t size = 0); - + /** * @brief Adds an entry to write a sampler to a given binding * of a descriptor set. @@ -156,9 +147,8 @@ namespace vkcv { * @param[in] sampler Sampler handle * @return Instance of descriptor writes */ - DescriptorWrites& writeSampler(uint32_t binding, - SamplerHandle sampler); - + DescriptorWrites &writeSampler(uint32_t binding, SamplerHandle sampler); + /** * @brief Adds an entry for acceleration to a given binding * of a descriptor set. @@ -167,57 +157,51 @@ namespace vkcv { * @param[in] structures Acceleration structures * @return Instance of descriptor writes */ - DescriptorWrites& writeAcceleration(uint32_t binding, - const std::vector<vk::AccelerationStructureKHR> &structures); - + DescriptorWrites & + writeAcceleration(uint32_t binding, + const std::vector<vk::AccelerationStructureKHR> &structures); + /** * @brief Returns the list of stored write entries for sampled images. * * @return Sampled image write details */ - [[nodiscard]] - const std::vector<SampledImageDescriptorWrite>& getSampledImageWrites() const; - + [[nodiscard]] const std::vector<SampledImageDescriptorWrite> &getSampledImageWrites() const; + /** * @brief Returns the list of stored write entries for storage images. * * @return Storage image write details */ - [[nodiscard]] - const std::vector<StorageImageDescriptorWrite>& getStorageImageWrites() const; - + [[nodiscard]] const std::vector<StorageImageDescriptorWrite> &getStorageImageWrites() const; + /** * @brief Returns the list of stored write entries for uniform buffers. * * @return Uniform buffers write details */ - [[nodiscard]] - const std::vector<BufferDescriptorWrite>& getUniformBufferWrites() const; - + [[nodiscard]] const std::vector<BufferDescriptorWrite> &getUniformBufferWrites() const; + /** * @brief Returns the list of stored write entries for storage buffers. * * @return Storage buffers write details */ - [[nodiscard]] - const std::vector<BufferDescriptorWrite>& getStorageBufferWrites() const; - + [[nodiscard]] const std::vector<BufferDescriptorWrite> &getStorageBufferWrites() const; + /** * @brief Returns the list of stored write entries for samplers. * * @return Samplers write details */ - [[nodiscard]] - const std::vector<SamplerDescriptorWrite>& getSamplerWrites() const; - + [[nodiscard]] const std::vector<SamplerDescriptorWrite> &getSamplerWrites() const; + /** * @brief Returns the list of stored write entries for accelerations. * * @return Accelerations write details */ - [[nodiscard]] - const std::vector<AccelerationDescriptorWrite>& getAccelerationWrites() const; - + [[nodiscard]] const std::vector<AccelerationDescriptorWrite> &getAccelerationWrites() const; }; - -} \ No newline at end of file + +} // namespace vkcv \ No newline at end of file diff --git a/include/vkcv/DispatchSize.hpp b/include/vkcv/DispatchSize.hpp index 39f1195046dc2d7c47c9994f5beb34b732ffd218..7f8a27feef9262968cb62bc451c8a0169d0ca9e2 100644 --- a/include/vkcv/DispatchSize.hpp +++ b/include/vkcv/DispatchSize.hpp @@ -4,19 +4,19 @@ * @file vkcv/DispatchSize.hpp * @brief Class to handle dispatch sizes. */ - + #include <array> #include <vulkan/vulkan.hpp> namespace vkcv { - + /** * @brief Class representing a dispatch size to invoke a compute pipeline with. */ class DispatchSize final { private: std::array<uint32_t, 3> m_Dispatch; - + public: /** * Implicit constructor to convert an unsigned integer to a @@ -25,7 +25,7 @@ namespace vkcv { * @param[in] count Count of invocations */ DispatchSize(uint32_t count); - + /** * Explicit constructor to create a dispatch size with two or * three dimensions setting each value specifically. @@ -35,57 +35,52 @@ namespace vkcv { * @param[in] dimensionZ Size of Z dimension (optional) */ DispatchSize(uint32_t dimensionX, uint32_t dimentionY, uint32_t dimensionZ = 1); - - DispatchSize(const DispatchSize& other) = default; - DispatchSize(DispatchSize&& other) = default; - + + DispatchSize(const DispatchSize &other) = default; + DispatchSize(DispatchSize &&other) = default; + ~DispatchSize() = default; - - DispatchSize& operator=(const DispatchSize& other) = default; - DispatchSize& operator=(DispatchSize&& other) = default; - + + DispatchSize &operator=(const DispatchSize &other) = default; + DispatchSize &operator=(DispatchSize &&other) = default; + /** * Returns the raw data of the dispatch size as readonly unsigned * integer pointer. * * @return Pointer to data */ - [[nodiscard]] - const uint32_t* data() const; - + [[nodiscard]] const uint32_t* data() const; + /** * Returns the size value of the dispatch size by a given index. * * @param[in] index Size index * @return Size value by index */ - [[nodiscard]] - uint32_t operator[](size_t index) const; - + [[nodiscard]] uint32_t operator[](size_t index) const; + /** * Returns the value for the X dimension of the dispatch size. * * @return Size of X dimension */ - [[nodiscard]] - uint32_t x() const; - + [[nodiscard]] uint32_t x() const; + /** * Returns the value for the Y dimension of the dispatch size. * * @return Size of Y dimension */ - [[nodiscard]] - uint32_t y() const; - + [[nodiscard]] uint32_t y() const; + /** * Returns the value for the Z dimension of the dispatch size. * * @return Size of Z dimension */ - [[nodiscard]] - uint32_t z() const; - + [[nodiscard]] uint32_t z() const; + /** * Checks whether the dispatch size is valid for compute shader * invocations and returns the result as boolean value. @@ -93,9 +88,8 @@ namespace vkcv { * @return True if the dispatch size is valid, otherwise false. */ bool check() const; - }; - + /** * Returns the proper dispatch size by dividing a global amount of invocations * as three dimensional dispatch size into invocations of a fixed group size @@ -109,7 +103,7 @@ namespace vkcv { * @param[in] groupSize Size of work group in compute stage * @return Dispatch size respecting the actual work group size */ - [[nodiscard]] - DispatchSize dispatchInvocations(DispatchSize globalInvocations, DispatchSize groupSize); - -} + [[nodiscard]] DispatchSize dispatchInvocations(DispatchSize globalInvocations, + DispatchSize groupSize); + +} // namespace vkcv diff --git a/include/vkcv/Downsampler.hpp b/include/vkcv/Downsampler.hpp index e2ee75ea6f4c94a89bedcfc2a1c4454dc16b3678..1617c721fa0976711f9e553ae3214222999c516c 100644 --- a/include/vkcv/Downsampler.hpp +++ b/include/vkcv/Downsampler.hpp @@ -3,39 +3,38 @@ #include "Handles.hpp" namespace vkcv { - + class Core; - + /** * @brief An abstract class to handle downsampling of images for mip generation. */ class Downsampler { protected: /** - * Reference to the current Core instance. - */ - Core& m_core; - + * Reference to the current Core instance. + */ + Core &m_core; + public: /** - * @brief Constructor to create a downsampler instance. - * - * @param[in,out] core Reference to a Core instance - */ - explicit Downsampler(Core& core); - + * @brief Constructor to create a downsampler instance. + * + * @param[in,out] core Reference to a Core instance + */ + explicit Downsampler(Core &core); + ~Downsampler() = default; - + /** * @brief Record the commands of the given downsampler instance to - * scale the image down on its own mip levels. + * scale the image down on its own mip levels. * * @param[in] cmdStream Command stream handle * @param[in] image Image handle */ - virtual void recordDownsampling(const CommandStreamHandle& cmdStream, - const ImageHandle& image) = 0; - + virtual void recordDownsampling(const CommandStreamHandle &cmdStream, + const ImageHandle &image) = 0; }; - -} \ No newline at end of file + +} // namespace vkcv \ No newline at end of file diff --git a/include/vkcv/Drawcall.hpp b/include/vkcv/Drawcall.hpp index 50ba78d223faaaafee51b9a0a0af0650babfa341..08e436ae52d44c3514b504ae2d573d7c447fab80 100644 --- a/include/vkcv/Drawcall.hpp +++ b/include/vkcv/Drawcall.hpp @@ -12,34 +12,31 @@ #include "VertexData.hpp" namespace vkcv { - + /** * @brief Base class to store details for a general drawcall. */ class Drawcall { private: std::vector<DescriptorSetUsage> m_usages; - + public: Drawcall() = default; - - Drawcall(const Drawcall& other) = default; - Drawcall(Drawcall&& other) noexcept = default; - + + Drawcall(const Drawcall &other) = default; + Drawcall(Drawcall &&other) noexcept = default; + ~Drawcall() = default; - - Drawcall& operator=(const Drawcall& other) = default; - Drawcall& operator=(Drawcall&& other) noexcept = default; - - [[nodiscard]] - const std::vector<DescriptorSetUsage>& getDescriptorSetUsages() const; - - void useDescriptorSet(uint32_t location, - const DescriptorSetHandle &descriptorSet, + + Drawcall &operator=(const Drawcall &other) = default; + Drawcall &operator=(Drawcall &&other) noexcept = default; + + [[nodiscard]] const std::vector<DescriptorSetUsage> &getDescriptorSetUsages() const; + + void useDescriptorSet(uint32_t location, const DescriptorSetHandle &descriptorSet, const std::vector<uint32_t> &dynamicOffsets = {}); - }; - + /** * @brief Class to store details for an instance drawcall. */ @@ -47,19 +44,15 @@ namespace vkcv { private: VertexData m_vertexData; uint32_t m_instanceCount; - + public: - explicit InstanceDrawcall(const VertexData& vertexData, - uint32_t instanceCount = 1); - - [[nodiscard]] - const VertexData& getVertexData() const; - - [[nodiscard]] - uint32_t getInstanceCount() const; - + explicit InstanceDrawcall(const VertexData &vertexData, uint32_t instanceCount = 1); + + [[nodiscard]] const VertexData &getVertexData() const; + + [[nodiscard]] uint32_t getInstanceCount() const; }; - + /** * @brief Class to store details for an indirect drawcall. */ @@ -68,36 +61,29 @@ namespace vkcv { BufferHandle m_indirectDrawBuffer; VertexData m_vertexData; uint32_t m_drawCount; - + public: explicit IndirectDrawcall(const BufferHandle &indirectDrawBuffer, - const VertexData& vertexData, - uint32_t drawCount = 1); - - [[nodiscard]] - BufferHandle getIndirectDrawBuffer() const; - - [[nodiscard]] - const VertexData& getVertexData() const; - - [[nodiscard]] - uint32_t getDrawCount() const; - + const VertexData &vertexData, uint32_t drawCount = 1); + + [[nodiscard]] BufferHandle getIndirectDrawBuffer() const; + + [[nodiscard]] const VertexData &getVertexData() const; + + [[nodiscard]] uint32_t getDrawCount() const; }; - + /** * @brief Class to store details for a task drawcall. */ class TaskDrawcall : public Drawcall { private: uint32_t m_taskCount; - + public: explicit TaskDrawcall(uint32_t taskCount = 1); - - [[nodiscard]] - uint32_t getTaskCount() const; - + + [[nodiscard]] uint32_t getTaskCount() const; }; - -} + +} // namespace vkcv diff --git a/include/vkcv/Event.hpp b/include/vkcv/Event.hpp index c4a05d0e126c2a44a67cfb4e1aad7d07ad6efaa5..3bba94b20afb56dd185751e8cafc787076822c2a 100644 --- a/include/vkcv/Event.hpp +++ b/include/vkcv/Event.hpp @@ -18,13 +18,13 @@ #include <vector> namespace vkcv { - + /** * @brief Template for a function handle to an event * * @tparam T Event parameter type list */ - template<typename... T> + template <typename... T> struct event_handle { uint32_t id; }; @@ -34,25 +34,25 @@ namespace vkcv { * * @tparam T Event parameter type list */ - template<typename... T> - struct event_function { - typedef std::function<void(T...)> type; - + template <typename... T> + struct event_function { + typedef std::function<void(T...)> type; + event_handle<T...> handle; - type callback; - }; - - /** - * @brief Template for event handling - * - * @tparam T Event parameter type list - */ - template<typename... T> - struct event { - private: - std::vector< event_function<T...> > m_functions; - uint32_t m_id_counter; - + type callback; + }; + + /** + * @brief Template for event handling + * + * @tparam T Event parameter type list + */ + template <typename... T> + struct event { + private: + std::vector< event_function<T...> > m_functions; + uint32_t m_id_counter; + #ifndef __MINGW32__ #ifdef __NO_SEMAPHORES__ std::mutex m_mutex; @@ -61,56 +61,55 @@ namespace vkcv { #endif #endif - public: - - /** - * @brief Calls all function handles with the given arguments. - * - * @param[in,out] arguments Arguments of the given event - */ - void operator()(T... arguments) { + public: + /** + * @brief Calls all function handles with the given arguments. + * + * @param[in,out] arguments Arguments of the given event + */ + void operator()(T... arguments) { lock(); - for (auto &function : this->m_functions) { + for (auto &function : this->m_functions) { function.callback(arguments...); } - - unlock(); - } - - /** - * @brief Adds a function handle to the event to be called. - * - * @param[in] callback Event callback - * @return Handle of the function - */ + + unlock(); + } + + /** + * @brief Adds a function handle to the event to be called. + * + * @param[in] callback Event callback + * @return Handle of the function + */ event_handle<T...> add(typename event_function<T...>::type callback) { event_function<T...> function; function.handle = { m_id_counter++ }; function.callback = callback; - this->m_functions.push_back(function); - return function.handle; - } - - /** - * @brief Removes a function handle of the event. - * - * @param handle Handle of the function - */ - void remove(event_handle<T...> handle) { - this->m_functions.erase( - std::remove_if(this->m_functions.begin(), this->m_functions.end(), [&handle](auto function){ - return (handle.id == function.handle.id); - }), - this->m_functions.end() - ); - } - - /** - * @brief Locks the event so its function handles won't - * be called until unlocked. - */ - void lock() { + this->m_functions.push_back(function); + return function.handle; + } + + /** + * @brief Removes a function handle of the event. + * + * @param handle Handle of the function + */ + void remove(event_handle<T...> handle) { + this->m_functions.erase(std::remove_if(this->m_functions.begin(), + this->m_functions.end(), + [&handle](auto function) { + return (handle.id == function.handle.id); + }), + this->m_functions.end()); + } + + /** + * @brief Locks the event so its function handles won't + * be called until unlocked. + */ + void lock() { #ifndef __MINGW32__ #ifdef __NO_SEMAPHORES__ m_mutex.lock(); @@ -118,13 +117,13 @@ namespace vkcv { m_semaphore.acquire(); #endif #endif - } - + } + /** * @brief Unlocks the event so its function handles can * be called after locking. */ - void unlock() { + void unlock() { #ifndef __MINGW32__ #ifdef __NO_SEMAPHORES__ m_mutex.unlock(); @@ -132,32 +131,33 @@ namespace vkcv { m_semaphore.release(); #endif #endif - } + } - explicit event(bool locked = false) + explicit event(bool locked = false) #ifndef __MINGW32__ #ifndef __NO_SEMAPHORES__ - : m_semaphore(locked? 1 : 0) + : + m_semaphore(locked ? 1 : 0) #endif #endif { #ifndef __MINGW32__ #ifdef __NO_SEMAPHORES__ - if (locked) m_mutex.lock(); + if (locked) + m_mutex.lock(); #endif #endif } - event(const event &other) = delete; + event(const event &other) = delete; + + event(event &&other) = delete; - event(event &&other) = delete; + ~event() = default; - ~event() = default; + event &operator=(const event &other) = delete; - event &operator=(const event &other) = delete; + event &operator=(event &&other) = delete; + }; - event &operator=(event &&other) = delete; - - }; - -} +} // namespace vkcv diff --git a/include/vkcv/EventFunctionTypes.hpp b/include/vkcv/EventFunctionTypes.hpp index 5bfb29d6570c4666c13125fab0774ed264e20cb9..12871cbce3b6d06c1849cdf3a90956a91dad724d 100644 --- a/include/vkcv/EventFunctionTypes.hpp +++ b/include/vkcv/EventFunctionTypes.hpp @@ -11,21 +11,21 @@ #include "Handles.hpp" namespace vkcv { - + /** * @brief Function to be called for recording a command buffer. */ - typedef typename event_function<const vk::CommandBuffer&>::type RecordCommandFunction; - + typedef typename event_function<const vk::CommandBuffer &>::type RecordCommandFunction; + /** * @brief Function to be called after finishing a given process. */ typedef typename event_function<>::type FinishCommandFunction; - + /** * @brief Function to be called each frame for every open window. */ - typedef typename event_function<const WindowHandle&, double, double, uint32_t, uint32_t>::type - WindowFrameFunction; - -} \ No newline at end of file + typedef typename event_function<const WindowHandle &, double, double, uint32_t, uint32_t>::type + WindowFrameFunction; + +} // namespace vkcv \ No newline at end of file diff --git a/include/vkcv/FeatureManager.hpp b/include/vkcv/FeatureManager.hpp index 0ed0d440e144032ec69f84f12d742d82a6849b8b..f465d6740c20014ca880fce5e881d5e6c99b32d9 100644 --- a/include/vkcv/FeatureManager.hpp +++ b/include/vkcv/FeatureManager.hpp @@ -22,228 +22,235 @@ namespace vkcv { /** * Physical device to check feature support against. */ - vk::PhysicalDevice& m_physicalDevice; - + vk::PhysicalDevice &m_physicalDevice; + /** * List of supported extensions. */ std::vector<const char*> m_supportedExtensions; - + /** * List of activated extensions for usage. */ std::vector<const char*> m_activeExtensions; - + /** * Feature structure chain to request activated features. */ vk::PhysicalDeviceFeatures2 m_featuresBase; - + /** * List of base structures allocated to request extension specific features. */ std::vector<vk::BaseOutStructure*> m_featuresExtensions; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceFeatures. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceFeatures& features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDevice16BitStorageFeatures. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDevice16BitStorageFeatures& features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDevice8BitStorageFeatures. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDevice8BitStorageFeatures &features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceBufferDeviceAddressFeatures. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceBufferDeviceAddressFeatures &features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceDescriptorIndexingFeatures. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceDescriptorIndexingFeatures &features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceHostQueryResetFeatures. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceHostQueryResetFeatures &features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceImagelessFramebufferFeatures. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceImagelessFramebufferFeatures &features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceMultiviewFeatures. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceMultiviewFeatures &features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceProtectedMemoryFeatures. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceProtectedMemoryFeatures &features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceSamplerYcbcrConversionFeatures. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceSamplerYcbcrConversionFeatures &features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceScalarBlockLayoutFeatures. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceScalarBlockLayoutFeatures &features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceSeparateDepthStencilLayoutsFeatures. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceSeparateDepthStencilLayoutsFeatures &features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceShaderAtomicInt64Features. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceShaderAtomicInt64Features &features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceShaderFloat16Int8Features. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceShaderFloat16Int8Features& features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceShaderSubgroupExtendedTypesFeatures. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceShaderSubgroupExtendedTypesFeatures &features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceTimelineSemaphoreFeatures. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceTimelineSemaphoreFeatures &features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceUniformBufferStandardLayoutFeatures. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceUniformBufferStandardLayoutFeatures &features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceVariablePointersFeatures. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceVariablePointersFeatures &features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceVulkanMemoryModelFeatures. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceVulkanMemoryModelFeatures &features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceMeshShaderFeaturesNV. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceMeshShaderFeaturesNV& features, bool required) const; - + + /** + * @brief Checks support of the @p vk::PhysicalDeviceFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceFeatures &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDevice16BitStorageFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDevice16BitStorageFeatures &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDevice8BitStorageFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDevice8BitStorageFeatures &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceBufferDeviceAddressFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool + checkSupport(const vk::PhysicalDeviceBufferDeviceAddressFeatures &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceDescriptorIndexingFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool + checkSupport(const vk::PhysicalDeviceDescriptorIndexingFeatures &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceHostQueryResetFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceHostQueryResetFeatures &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceImagelessFramebufferFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool + checkSupport(const vk::PhysicalDeviceImagelessFramebufferFeatures &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceMultiviewFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceMultiviewFeatures &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceProtectedMemoryFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceProtectedMemoryFeatures &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceSamplerYcbcrConversionFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool + checkSupport(const vk::PhysicalDeviceSamplerYcbcrConversionFeatures &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceScalarBlockLayoutFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceScalarBlockLayoutFeatures &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceSeparateDepthStencilLayoutsFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool + checkSupport(const vk::PhysicalDeviceSeparateDepthStencilLayoutsFeatures &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceShaderAtomicInt64Features. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceShaderAtomicInt64Features &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceShaderFloat16Int8Features. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceShaderFloat16Int8Features &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceShaderSubgroupExtendedTypesFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool + checkSupport(const vk::PhysicalDeviceShaderSubgroupExtendedTypesFeatures &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceTimelineSemaphoreFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceTimelineSemaphoreFeatures &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceUniformBufferStandardLayoutFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool + checkSupport(const vk::PhysicalDeviceUniformBufferStandardLayoutFeatures &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceVariablePointersFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceVariablePointersFeatures &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceVulkanMemoryModelFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceVulkanMemoryModelFeatures &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceMeshShaderFeaturesNV. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceMeshShaderFeaturesNV &features, + bool required) const; + /** * @brief Checks support of the @p vk::PhysicalDeviceShaderAtomicFloatFeaturesEXT. * @@ -251,9 +258,10 @@ namespace vkcv { * @param[in] required True, if the @p features are required, else false * @return @p True, if the @p features are supported, else @p false */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceShaderAtomicFloatFeaturesEXT& features, bool required) const; - + [[nodiscard]] bool + checkSupport(const vk::PhysicalDeviceShaderAtomicFloatFeaturesEXT &features, + bool required) const; + /** * @brief Checks support of the @p vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT. * @@ -261,28 +269,29 @@ namespace vkcv { * @param[in] required True, if the @p features are required, else false * @return @p True, if the @p features are supported, else @p false */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT& features, bool required) const; - + [[nodiscard]] bool + checkSupport(const vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT &features, + bool required) const; + /** - * @brief Checks support of the @p vk::PhysicalDeviceVulkan12Features. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceVulkan12Features& features, bool required) const; + * @brief Checks support of the @p vk::PhysicalDeviceVulkan12Features. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceVulkan12Features &features, + bool required) const; /** - * @brief Checks support of the @p vk::PhysicalDeviceVulkan11Features. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceVulkan11Features& features, bool required) const; + * @brief Checks support of the @p vk::PhysicalDeviceVulkan11Features. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceVulkan11Features &features, + bool required) const; /** * @brief Checks support of the @p vk::PhysicalDeviceAccelerationStructureFeaturesKHR. @@ -291,79 +300,79 @@ namespace vkcv { * @param[in] required True, if the @p features are required, else false * @return @p True, if the @p features are supported, else @p false */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceAccelerationStructureFeaturesKHR& features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceRayTracingPipelineFeaturesKHR. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceRayTracingPipelineFeaturesKHR& features, bool required) const; - - /** - * @brief Checks support of the @p vk::PhysicalDeviceVulkan13Features. - * - * @param[in] features The features - * @param[in] required True, if the @p features are required, else false - * @return @p True, if the @p features are supported, else @p false - */ - [[nodiscard]] - bool checkSupport(const vk::PhysicalDeviceVulkan13Features& features, bool required) const; - + [[nodiscard]] bool + checkSupport(const vk::PhysicalDeviceAccelerationStructureFeaturesKHR &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceRayTracingPipelineFeaturesKHR. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool + checkSupport(const vk::PhysicalDeviceRayTracingPipelineFeaturesKHR &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceVulkan13Features. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceVulkan13Features &features, + bool required) const; + /** * @brief Searches for a base structure of a given structure type. * * @param[in] type Structure type * @return Pointer to first matching base structure or nullptr */ - [[nodiscard]] - vk::BaseOutStructure* findFeatureStructure(vk::StructureType type) const; - + [[nodiscard]] vk::BaseOutStructure* findFeatureStructure(vk::StructureType type) const; + public: /** * @brief Constructor of a feature manager with a given physical device. * * @param[in,out] physicalDevice Physical device */ - explicit FeatureManager(vk::PhysicalDevice& physicalDevice); - - FeatureManager(const FeatureManager& other) = delete; - + explicit FeatureManager(vk::PhysicalDevice &physicalDevice); + + FeatureManager(const FeatureManager &other) = delete; + /** * @brief Move-constructor of a feature manager. * * @param[in,out] other Other feature manager instance */ - FeatureManager(FeatureManager&& other) noexcept; - + FeatureManager(FeatureManager &&other) noexcept; + /** * @brief Destructor of a feature manager. */ ~FeatureManager(); - - FeatureManager& operator=(const FeatureManager& other) = delete; - + + FeatureManager &operator=(const FeatureManager &other) = delete; + /** * @brief Move-operator of a feature manager. * * @param[in,out] other Other feature manager instance * @return Reference to the feature manager itself */ - FeatureManager& operator=(FeatureManager&& other) noexcept; - + FeatureManager &operator=(FeatureManager &&other) noexcept; + /** * @brief Check if a specific extension is supported by the managers physical device. * * @param[in] extension Extension identifier string * @return @p True, if the @p extension is supported, else @p false */ - [[nodiscard]] - bool isExtensionSupported(const std::string& extension) const; - + [[nodiscard]] bool isExtensionSupported(const std::string &extension) const; + /** * @brief Activate a specific extension if supported by the managers physical device. * @@ -371,25 +380,23 @@ namespace vkcv { * @param[in] required True, if the @p extension is required, else false * @return @p True, if the @p extension could be activated, else @p false */ - bool useExtension(const std::string& extension, bool required = true); - + bool useExtension(const std::string &extension, bool required = true); + /** * @brief Check if a specific extension is activated by the manager. * * @param[in] extension Extension identifier string * @return @p True, if the @p extension is activated, else @p false */ - [[nodiscard]] - bool isExtensionActive(const std::string& extension) const; - + [[nodiscard]] bool isExtensionActive(const std::string &extension) const; + /** * @brief Return list of activated extensions for usage. * * @return List of activated extensions */ - [[nodiscard]] - const std::vector<const char*>& getActiveExtensions() const; - + [[nodiscard]] const std::vector<const char*> &getActiveExtensions() const; + /** * @brief Request specific features for optional or required usage ( only core Vulkan 1.0 ). * @@ -397,8 +404,9 @@ namespace vkcv { * @param[in] required True, if the @p features are required, else false * @return @p True, if the requested features could be activated, else @p false */ - bool useFeatures(const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction, bool required = true); - + bool useFeatures(const std::function<void(vk::PhysicalDeviceFeatures &)> &featureFunction, + bool required = true); + /** * @brief Request specific features for optional or required usage. * @@ -408,79 +416,76 @@ namespace vkcv { * @return @p True, if the requested features could be activated, else @p false * @see checkSupport() */ - template<typename T> - bool useFeatures(const std::function<void(T&)>& featureFunction, bool required = true) { + template <typename T> + bool useFeatures(const std::function<void(T &)> &featureFunction, bool required = true) { T features; T* features_ptr = reinterpret_cast<T*>(findFeatureStructure(features.sType)); - + if (features_ptr) { features = *features_ptr; } - + featureFunction(features); - + if (!checkSupport(features, required)) { if (required) { vkcv_log_throw_error("Required feature is not supported!"); } - + return false; } - + if (features_ptr) { *features_ptr = features; return true; } - + features_ptr = new T(features); - + if (m_featuresExtensions.empty()) { m_featuresBase.setPNext(features_ptr); } else { m_featuresExtensions.back()->setPNext( - reinterpret_cast<vk::BaseOutStructure*>(features_ptr) - ); + reinterpret_cast<vk::BaseOutStructure*>(features_ptr)); } - - m_featuresExtensions.push_back( - reinterpret_cast<vk::BaseOutStructure*>(features_ptr) - ); - + + m_featuresExtensions.push_back(reinterpret_cast<vk::BaseOutStructure*>(features_ptr)); + return true; } - + /** * @brief Return feature structure chain to request all activated features. * * @return Head of feature structure chain */ - [[nodiscard]] - const vk::PhysicalDeviceFeatures2& getFeatures() const; - + [[nodiscard]] const vk::PhysicalDeviceFeatures2 &getFeatures() const; + /** * @brief Checks all activated features for a specific feature and returns its state. * * @tparam T Template parameter to use specific base structure types * @param[in] type Vulkan structure type identifier - * @param[in] featureTestFunction Function to test feature structure with for requested attributes + * @param[in] featureTestFunction Function to test feature structure with for requested + * attributes * @return True, if the requested attributes are available, else false */ - template<typename T> + template <typename T> bool checkFeatures(vk::StructureType type, - const std::function<bool(const T&)>& featureTestFunction) const { + const std::function<bool(const T &)> &featureTestFunction) const { const auto* base = reinterpret_cast<const vk::BaseInStructure*>(&getFeatures()); - + while (base) { - if ((base->sType == type) && (featureTestFunction(*reinterpret_cast<const T*>(base)))) { + if ((base->sType == type) + && (featureTestFunction(*reinterpret_cast<const T*>(base)))) { return true; } - + base = base->pNext; } - + return false; } - }; - -} + +} // namespace vkcv diff --git a/include/vkcv/Features.hpp b/include/vkcv/Features.hpp index bb0e88c2b52775f00e5d74804d055fe35ee6bd58..8b39de4f8f1183664f163d8add7f135102dab631 100644 --- a/include/vkcv/Features.hpp +++ b/include/vkcv/Features.hpp @@ -6,18 +6,18 @@ */ #include <functional> -#include <vector> #include <initializer_list> +#include <vector> #include "FeatureManager.hpp" namespace vkcv { - + /** * Abstract function type to request a feature via the feature manager. */ - typedef std::function<bool(FeatureManager&)> Feature; - + typedef std::function<bool(FeatureManager &)> Feature; + /** * @brief Class to manage a list of feature requests at once. */ @@ -27,71 +27,74 @@ namespace vkcv { * List of feature requests. */ std::vector<Feature> m_features; - + public: /** * @brief Constructor of a features instance. */ Features() = default; - + /** - * @brief Constructor of a features instance with a given list of extension identifier strings. + * @brief Constructor of a features instance with a given list of extension identifier + * strings. * * @param[in] list List of extension identifier strings */ - Features(const std::initializer_list<std::string>& list); - + Features(const std::initializer_list<std::string> &list); + /** * @brief Copy-constructor of a features instance. * * @param[in] other Other features instance */ - Features(const Features& other) = default; - + Features(const Features &other) = default; + /** * @brief Move-constructor of a features instance. * * @param[in,out] other Other features instance */ - Features(Features&& other) = default; - + Features(Features &&other) = default; + /** * @brief Destructor of a features instance. */ ~Features() = default; - + /** * @brief Copy-operator of a features instance. * * @param[in] other Other features instance * @return Reference to the features instance itself */ - Features& operator=(const Features& other) = default; - + Features &operator=(const Features &other) = default; + /** * @brief Move-operator of a features instance. * * @param[in,out] other Other features instance * @return Reference to the features instance itself */ - Features& operator=(Features&& other) = default; - + Features &operator=(Features &&other) = default; + /** * @brief Request a specific extension as required. * * @param[in] extension Extension identifier string */ - void requireExtension(const std::string& extension); - + void requireExtension(const std::string &extension); + /** - * @brief Request a specific extension and some of its features as required ( only core Vulkan 1.0 ). + * @brief Request a specific extension and some of its features as required ( only core + * Vulkan 1.0 ). * * @param[in] extension Extension identifier string * @param[in] featureFunction */ - void requireExtensionFeature(const std::string& extension, - const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction); - + void requireExtensionFeature( + const std::string &extension, + const std::function<void(vk::PhysicalDeviceFeatures &)> &featureFunction); + /** * @brief Request a specific extension and some of its features as required. * @@ -99,9 +102,10 @@ namespace vkcv { * @param[in] extension Extension identifier string * @param[in] featureFunction Function or lambda to request specific features */ - template<typename T> - void requireExtensionFeature(const std::string& extension, const std::function<void(T&)>& featureFunction) { - m_features.emplace_back([extension, featureFunction](FeatureManager& featureManager) { + 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 { @@ -109,43 +113,46 @@ namespace vkcv { } }); } - + /** * @brief Request a specific set of features as required ( only core Vulkan 1.0 ). * * @param[in] featureFunction Function or lambda to request specific features */ - void requireFeature(const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction); - + void + requireFeature(const std::function<void(vk::PhysicalDeviceFeatures &)> &featureFunction); + /** * @brief Request a specific set of features as required. * * @tparam T Template parameter to use specific base structure types * @param[in] featureFunction Function or lambda to request specific features */ - template<typename T> - void requireFeature(const std::function<void(T&)>& featureFunction) { - m_features.emplace_back([featureFunction](FeatureManager& featureManager) { + 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); }); } - + /** * @brief Request a specific extension as optional. * * @param[in] extension Extension identifier string */ - void tryExtension(const std::string& extension); - + void tryExtension(const std::string &extension); + /** - * @brief Request a specific extension and some of its features as optional ( only core Vulkan 1.0 ). + * @brief Request a specific extension and some of its features as optional ( only core + * Vulkan 1.0 ). * * @param[in] extension Extension identifier string * @param[in] featureFunction Function or lambda to request specific features */ - void tryExtensionFeature(const std::string& extension, - const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction); - + void tryExtensionFeature( + const std::string &extension, + const std::function<void(vk::PhysicalDeviceFeatures &)> &featureFunction); + /** * @brief Request a specific extension and some of its features as optional. * @@ -153,9 +160,10 @@ namespace vkcv { * @param[in] extension Extension identifier string * @param[in] featureFunction Function or lambda to request specific features */ - template<typename T> - void tryExtensionFeature(const std::string& extension, const std::function<void(T&)>& featureFunction) { - m_features.emplace_back([extension, featureFunction](FeatureManager& featureManager) { + 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 { @@ -163,35 +171,33 @@ namespace vkcv { } }); } - + /** * @brief Request a specific set of features as optional ( only core Vulkan 1.0 ). * * @param[in] featureFunction Function or lambda to request specific features */ - void tryFeature(const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction); - + void tryFeature(const std::function<void(vk::PhysicalDeviceFeatures &)> &featureFunction); + /** * @brief Request a specific set of features as optional. * * @tparam T Template parameter to use specific base structure types * @param[in] featureFunction Function or lambda to request specific features */ - template<typename T> - void tryFeature(const std::function<void(T&)>& featureFunction) { - m_features.emplace_back([featureFunction](FeatureManager& featureManager) { + 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); }); } - + /** * @brief Return list of feature requests. * * @return List of feature requests */ - [[nodiscard]] - const std::vector<Feature>& getList() const; - + [[nodiscard]] const std::vector<Feature> &getList() const; }; - -} + +} // namespace vkcv diff --git a/include/vkcv/File.hpp b/include/vkcv/File.hpp index 4d81f368b03d374fe4f83bf197a76ddd8a6b034a..51491b1b04a2a658f410e4872f7661237ca913b2 100644 --- a/include/vkcv/File.hpp +++ b/include/vkcv/File.hpp @@ -8,19 +8,19 @@ #include <filesystem> namespace vkcv { - + /** * @brief Generate a new temporary file path and return it. * * @return A unique path for a temporary file */ std::filesystem::path generateTemporaryFilePath(); - + /** * @brief Generate a new temporary directory path and return it. * * @return A unique path for a temporary directory */ std::filesystem::path generateTemporaryDirectoryPath(); - -} + +} // namespace vkcv diff --git a/include/vkcv/GraphicsPipelineConfig.hpp b/include/vkcv/GraphicsPipelineConfig.hpp index 91e9fa75cb553ed2b98edfb363192d071ec1bd09..80084cb1408a71ebd2abe12ec12d6a395e9b6d49 100644 --- a/include/vkcv/GraphicsPipelineConfig.hpp +++ b/include/vkcv/GraphicsPipelineConfig.hpp @@ -5,25 +5,25 @@ * @brief Graphics pipeline config struct to hand over required information to pipeline creation. */ -#include <vector> #include <cstdint> +#include <vector> +#include "Multisampling.hpp" #include "PipelineConfig.hpp" #include "VertexLayout.hpp" -#include "Multisampling.hpp" namespace vkcv { /** * @brief Enum class to specify types of primitive topology. */ - enum class PrimitiveTopology { + enum class PrimitiveTopology { PointList, LineList, TriangleList, PatchList }; - + /** * @brief Enum class to specify modes of culling. */ @@ -33,11 +33,11 @@ namespace vkcv { Back, Both }; - + /** * @brief Enum class to specify depth-test modes. */ - enum class DepthTest { + enum class DepthTest { None, Less, LessEqual, @@ -46,115 +46,99 @@ namespace vkcv { Equal }; - // add more as needed - // alternatively we could expose the blend factors directly + // add more as needed + // alternatively we could expose the blend factors directly /** * @brief Enum class to specify blending modes. */ - enum class BlendMode { + enum class BlendMode { None, Additive }; - + /** * @brief Class to configure a graphics pipeline before its creation. */ - class GraphicsPipelineConfig : public PipelineConfig { + class GraphicsPipelineConfig : public PipelineConfig { private: PassHandle m_PassHandle; VertexLayout m_VertexLayout; - - uint32_t m_Width; + + uint32_t m_Width; uint32_t m_Height; - - bool m_UseConservativeRasterization = false; - PrimitiveTopology m_PrimitiveTopology = PrimitiveTopology::TriangleList; - BlendMode m_blendMode = BlendMode::None; - bool m_EnableDepthClamping = false; - CullMode m_Culling = CullMode::None; - DepthTest m_DepthTest = DepthTest::LessEqual; - bool m_DepthWrite = true; - bool m_AlphaToCoverage = false; - uint32_t m_TessellationControlPoints = 0; - + + bool m_UseConservativeRasterization = false; + PrimitiveTopology m_PrimitiveTopology = PrimitiveTopology::TriangleList; + BlendMode m_blendMode = BlendMode::None; + bool m_EnableDepthClamping = false; + CullMode m_Culling = CullMode::None; + DepthTest m_DepthTest = DepthTest::LessEqual; + bool m_DepthWrite = true; + bool m_AlphaToCoverage = false; + uint32_t m_TessellationControlPoints = 0; + public: GraphicsPipelineConfig(); - - GraphicsPipelineConfig(const ShaderProgram& program, - const PassHandle& pass, - const VertexLayout& vertexLayout, - const std::vector<DescriptorSetLayoutHandle>& layouts); - + + GraphicsPipelineConfig(const ShaderProgram &program, const PassHandle &pass, + const VertexLayout &vertexLayout, + const std::vector<DescriptorSetLayoutHandle> &layouts); + GraphicsPipelineConfig(const GraphicsPipelineConfig &other) = default; GraphicsPipelineConfig(GraphicsPipelineConfig &&other) = default; - + ~GraphicsPipelineConfig() = default; - - GraphicsPipelineConfig& operator=(const GraphicsPipelineConfig &other) = default; - GraphicsPipelineConfig& operator=(GraphicsPipelineConfig &&other) = default; - - [[nodiscard]] - const PassHandle& getPass() const; - - [[nodiscard]] - const VertexLayout& getVertexLayout() const; - - [[nodiscard]] - uint32_t getWidth() const; - - [[nodiscard]] - uint32_t getHeight() const; - + + GraphicsPipelineConfig &operator=(const GraphicsPipelineConfig &other) = default; + GraphicsPipelineConfig &operator=(GraphicsPipelineConfig &&other) = default; + + [[nodiscard]] const PassHandle &getPass() const; + + [[nodiscard]] const VertexLayout &getVertexLayout() const; + + [[nodiscard]] uint32_t getWidth() const; + + [[nodiscard]] uint32_t getHeight() const; + void setResolution(uint32_t width, uint32_t height); - - [[nodiscard]] - bool isViewportDynamic() const; - - [[nodiscard]] - bool isUsingConservativeRasterization() const; - + + [[nodiscard]] bool isViewportDynamic() const; + + [[nodiscard]] bool isUsingConservativeRasterization() const; + void setUsingConservativeRasterization(bool conservativeRasterization); - - [[nodiscard]] - PrimitiveTopology getPrimitiveTopology() const; - + + [[nodiscard]] PrimitiveTopology getPrimitiveTopology() const; + void setPrimitiveTopology(PrimitiveTopology primitiveTopology); - - [[nodiscard]] - BlendMode getBlendMode() const; - + + [[nodiscard]] BlendMode getBlendMode() const; + void setBlendMode(BlendMode blendMode); - - [[nodiscard]] - bool isDepthClampingEnabled() const; - + + [[nodiscard]] bool isDepthClampingEnabled() const; + void setDepthClampingEnabled(bool depthClamping); - - [[nodiscard]] - CullMode getCulling() const; - + + [[nodiscard]] CullMode getCulling() const; + void setCulling(CullMode cullMode); - - [[nodiscard]] - DepthTest getDepthTest() const; - + + [[nodiscard]] DepthTest getDepthTest() const; + void setDepthTest(DepthTest depthTest); - - [[nodiscard]] - bool isWritingDepth() const; - + + [[nodiscard]] bool isWritingDepth() const; + void setWritingDepth(bool writingDepth); - - [[nodiscard]] - bool isWritingAlphaToCoverage() const; - + + [[nodiscard]] bool isWritingAlphaToCoverage() const; + void setWritingAlphaToCoverage(bool alphaToCoverage); - - [[nodiscard]] - uint32_t getTesselationControlPoints() const; - + + [[nodiscard]] uint32_t getTesselationControlPoints() const; + void setTesselationControlPoints(uint32_t tessellationControlPoints); - - }; + }; -} \ No newline at end of file +} // namespace vkcv \ No newline at end of file diff --git a/include/vkcv/Handles.hpp b/include/vkcv/Handles.hpp index 52ccb7a84a5d82bf51c3285c6536d6ce9aa0bc48..3e92ee1557bac4be5b03f8b74cab1319c501d707 100644 --- a/include/vkcv/Handles.hpp +++ b/include/vkcv/Handles.hpp @@ -9,32 +9,31 @@ #include "Event.hpp" -namespace vkcv -{ - +namespace vkcv { + /** * @brief Function to be called when a handles resources can be destroyed. */ typedef typename event_function<uint64_t>::type HandleDestroyFunction; - /** - * @brief Class for general memory management via handles. - */ + /** + * @brief Class for general memory management via handles. + */ class Handle { - friend std::ostream& operator << (std::ostream& out, const Handle& handle); - + friend std::ostream &operator<<(std::ostream &out, const Handle &handle); + private: uint64_t m_id; uint64_t* m_rc; - + HandleDestroyFunction m_destroy; - + protected: /** * @brief Constructor of an invalid handle */ Handle(); - + /** * @brief Constructor of a valid handle with an * unique id and an optional destroy callback. @@ -42,49 +41,46 @@ namespace vkcv * @param[in] id Unique handle id * @param[in] destroy Destroy callback (optional) */ - explicit Handle(uint64_t id, const HandleDestroyFunction& destroy = nullptr); - + explicit Handle(uint64_t id, const HandleDestroyFunction &destroy = nullptr); + /** * @brief Returns the actual handle id of a handle. * * @return Handle id */ - [[nodiscard]] - uint64_t getId() const; - + [[nodiscard]] uint64_t getId() const; + /** * @brief Returns the reference counter of a handle * * @return Reference counter */ - [[nodiscard]] - uint64_t getRC() const; - + [[nodiscard]] uint64_t getRC() const; + public: virtual ~Handle(); - - Handle(const Handle& other); - Handle(Handle&& other) noexcept; - - Handle& operator=(const Handle& other); - Handle& operator=(Handle&& other) noexcept; - + + Handle(const Handle &other); + Handle(Handle &&other) noexcept; + + Handle &operator=(const Handle &other); + Handle &operator=(Handle &&other) noexcept; + /** * @brief Returns whether a handle is valid to use. * * @return True, if the handle is valid, else false. */ explicit operator bool() const; - + /** * @brief Returns whether a handle is invalid to use. * * @return True, if the handle is invalid, else false. */ bool operator!() const; - }; - + /** * @brief Stream operator to print a handle into an output * stream. @@ -93,87 +89,95 @@ namespace vkcv * @param[in] handle * @return Output stream after printing */ - std::ostream& operator << (std::ostream& out, const Handle& handle); + std::ostream &operator<<(std::ostream &out, const Handle &handle); + + /** + * @brief Handle class for buffers. + */ + class BufferHandle : public Handle { + friend class BufferManager; - /** - * @brief Handle class for buffers. - */ - class BufferHandle : public Handle { - friend class BufferManager; private: using Handle::Handle; - }; + }; - /** - * @brief Handle class for render passes. - */ + /** + * @brief Handle class for render passes. + */ class PassHandle : public Handle { friend class PassManager; + private: using Handle::Handle; }; - /** - * @brief Handle class for graphics pipelines. - */ + /** + * @brief Handle class for graphics pipelines. + */ class GraphicsPipelineHandle : public Handle { friend class GraphicsPipelineManager; + + private: + using Handle::Handle; + }; + + /** + * @brief Handle class for compute pipelines. + */ + class ComputePipelineHandle : public Handle { + friend class ComputePipelineManager; + private: using Handle::Handle; }; - /** - * @brief Handle class for compute pipelines. - */ - class ComputePipelineHandle : public Handle { - friend class ComputePipelineManager; - private: - using Handle::Handle; - }; - /** - * @brief Handle class for descriptor set layouts. - */ + * @brief Handle class for descriptor set layouts. + */ class DescriptorSetLayoutHandle : public Handle { friend class DescriptorSetLayoutManager; + private: using Handle::Handle; }; - /** - * @brief Handle class for descriptor sets. - */ + /** + * @brief Handle class for descriptor sets. + */ class DescriptorSetHandle : public Handle { friend class DescriptorSetManager; + private: using Handle::Handle; }; - /** - * @brief Handle class for samplers. - */ + /** + * @brief Handle class for samplers. + */ class SamplerHandle : public Handle { friend class SamplerManager; + private: using Handle::Handle; }; - /** - * @brief Handle class for images. - */ + /** + * @brief Handle class for images. + */ class ImageHandle : public Handle { friend class ImageManager; + private: using Handle::Handle; + public: /** * @brief Returns whether the handle represents an swapchain image. * * @return True, if the handle represents a swapchain image, else false. */ - [[nodiscard]] - bool isSwapchainImage() const; - + [[nodiscard]] bool isSwapchainImage() const; + /** * @brief Creates a valid image handle to represent a swapchain image * using an optional destroy callback. @@ -181,35 +185,38 @@ namespace vkcv * @param[in] destroy Destroy callback (optional) * @return New swapchain image handle */ - static ImageHandle createSwapchainImageHandle(const HandleDestroyFunction& destroy = nullptr); - + static ImageHandle + createSwapchainImageHandle(const HandleDestroyFunction &destroy = nullptr); }; - /** - * @brief Handle class for windows. - */ + /** + * @brief Handle class for windows. + */ class WindowHandle : public Handle { friend class WindowManager; + private: using Handle::Handle; }; - /** - * @brief Handle class for swapchains. - */ + /** + * @brief Handle class for swapchains. + */ class SwapchainHandle : public Handle { friend class SwapchainManager; + + private: + using Handle::Handle; + }; + + /** + * @brief Handle class for command streams. + */ + class CommandStreamHandle : public Handle { + friend class CommandStreamManager; + private: using Handle::Handle; }; - /** - * @brief Handle class for command streams. - */ - class CommandStreamHandle : public Handle { - friend class CommandStreamManager; - private: - using Handle::Handle; - }; - -} +} // namespace vkcv diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp index 542658ae6aeb56b5221ca5f97504e955eaf0e478..69d4bc07e7f40af3d5d2802dd06576f166329427 100644 --- a/include/vkcv/Image.hpp +++ b/include/vkcv/Image.hpp @@ -4,7 +4,7 @@ * @file vkcv/Image.hpp * @brief Class for image handling. */ - + #include <vulkan/vulkan.hpp> #include "BufferTypes.hpp" @@ -13,7 +13,7 @@ #include "Multisampling.hpp" namespace vkcv { - + class Downsampler; /** @@ -24,7 +24,7 @@ namespace vkcv { * otherwise false. */ bool isDepthFormat(const vk::Format format); - + /** * @brief Returns whether an image format is usable as stencil buffer. * @@ -34,83 +34,78 @@ namespace vkcv { */ bool isStencilFormat(const vk::Format format); - /** - * @brief Class for image handling and filling data. - */ + /** + * @brief Class for image handling and filling data. + */ class Image { friend class Core; + public: Image() : m_core(nullptr), m_handle() {}; - - Image(Core* core, const ImageHandle& handle) : m_core(core), m_handle(handle) {} - - Image(const Image& other) = default; - Image(Image&& other) = default; - + + Image(Core* core, const ImageHandle &handle) : m_core(core), m_handle(handle) {} + + Image(const Image &other) = default; + Image(Image &&other) = default; + ~Image() = default; - - Image& operator=(const Image& other) = default; - Image& operator=(Image&& other) = default; - + + Image &operator=(const Image &other) = default; + Image &operator=(Image &&other) = default; + /** * @brief Returns the format of the image. * * @return Vulkan image format */ - [[nodiscard]] - vk::Format getFormat() const; - + [[nodiscard]] vk::Format getFormat() const; + /** * @brief Returns the width of the image. * * @return Width of the image */ - [[nodiscard]] - uint32_t getWidth() const; - + [[nodiscard]] uint32_t getWidth() const; + /** * @brief Returns the height of the image. * * @return Height of the image */ - [[nodiscard]] - uint32_t getHeight() const; - + [[nodiscard]] uint32_t getHeight() const; + /** * @brief Returns the depth of the image. * * @return Depth of the image */ - [[nodiscard]] - uint32_t getDepth() const; + [[nodiscard]] uint32_t getDepth() const; /** * @brief Returns the image handle of the image. * * @return Handle of the image */ - [[nodiscard]] - const vkcv::ImageHandle& getHandle() const; + [[nodiscard]] const vkcv::ImageHandle &getHandle() const; /** * @brief Returns the amount of mip levels of the image. * * @return Number of mip levels */ - [[nodiscard]] - uint32_t getMipLevels() const; + [[nodiscard]] uint32_t getMipLevels() const; /** * @brief Switches the image layout, * returns after operation is finished. - * + * * @param[in] newLayout Layout that image is switched to */ void switchLayout(vk::ImageLayout newLayout); - + /** * @brief Fills the image with data of a given size in bytes. - * + * * @param[in] data Pointer to the source data * @param[in] size Lower limit of the data size to copy in bytes, * the actual number of copied bytes is min(size, imageDataSize) @@ -120,27 +115,21 @@ namespace vkcv { /** * @brief Records mip chain generation to command stream, * mip level zero is used as source - * + * * @param[out] cmdStream Command stream that the commands are recorded into * @param[in,out] downsampler Downsampler to generate mip levels with */ - void recordMipChainGeneration(const vkcv::CommandStreamHandle& cmdStream, + void recordMipChainGeneration(const vkcv::CommandStreamHandle &cmdStream, Downsampler &downsampler); - + private: Core* m_core; ImageHandle m_handle; - }; - - Image image(Core &core, - vk::Format format, - uint32_t width, - uint32_t height, - uint32_t depth=1, - bool createMipChain=false, - bool supportStorage=false, - bool supportColorAttachment=false, - Multisampling multisampling=Multisampling::None); - -} + + Image image(Core &core, vk::Format format, uint32_t width, uint32_t height, uint32_t depth = 1, + bool createMipChain = false, bool supportStorage = false, + bool supportColorAttachment = false, + Multisampling multisampling = Multisampling::None); + +} // namespace vkcv diff --git a/include/vkcv/Logger.hpp b/include/vkcv/Logger.hpp index a1805651323f8c9200d16a6a7e999c82c3dc3c90..8a366b265bfb029ccc0f379b8e193834c54343df 100644 --- a/include/vkcv/Logger.hpp +++ b/include/vkcv/Logger.hpp @@ -9,7 +9,7 @@ #include <exception> namespace vkcv { - + /** * @brief Enum class to specify the level of logging. */ @@ -19,7 +19,7 @@ namespace vkcv { WARNING, ERROR }; - + /** * @brief Return the fitting output stream to print messages * of a given level of logging. @@ -29,14 +29,14 @@ namespace vkcv { */ constexpr auto getLogOutput(LogLevel level) { switch (level) { - case LogLevel::RAW_INFO: - case LogLevel::INFO: - return stdout; - default: - return stderr; + case LogLevel::RAW_INFO: + case LogLevel::INFO: + return stdout; + default: + return stderr; } } - + /** * @brief Returns the fitting identifier for messages of * a given level of logging. @@ -46,18 +46,18 @@ namespace vkcv { */ constexpr const char* getLogName(LogLevel level) { switch (level) { - case LogLevel::RAW_INFO: - case LogLevel::INFO: - return "INFO"; - case LogLevel::WARNING: - return "WARNING"; - case LogLevel::ERROR: - return "ERROR"; - default: - return "UNKNOWN"; + case LogLevel::RAW_INFO: + case LogLevel::INFO: + return "INFO"; + case LogLevel::WARNING: + return "WARNING"; + case LogLevel::ERROR: + return "ERROR"; + default: + return "UNKNOWN"; } } - + #ifndef NDEBUG #ifndef VKCV_DEBUG_MESSAGE_LEN #define VKCV_DEBUG_MESSAGE_LEN 1024 @@ -73,36 +73,19 @@ namespace vkcv { * * @param[in] level Level of logging */ -#define vkcv_log(level, ...) { \ - char output_message [ \ - VKCV_DEBUG_MESSAGE_LEN \ - ]; \ - snprintf( \ - output_message, \ - VKCV_DEBUG_MESSAGE_LEN, \ - __VA_ARGS__ \ - ); \ - auto output = getLogOutput(level); \ - if (level != vkcv::LogLevel::RAW_INFO) { \ - fprintf( \ - output, \ - "[%s]: %s [%s, line %d: %s]\n", \ - vkcv::getLogName(level), \ - output_message, \ - __FILE__, \ - __LINE__, \ - __PRETTY_FUNCTION__ \ - ); \ - } else { \ - fprintf( \ - output, \ - "[%s]: %s\n", \ - vkcv::getLogName(level), \ - output_message \ - ); \ - } \ - fflush(output); \ -} +#define vkcv_log(level, ...) \ + { \ + char output_message [VKCV_DEBUG_MESSAGE_LEN]; \ + snprintf(output_message, VKCV_DEBUG_MESSAGE_LEN, __VA_ARGS__); \ + auto output = getLogOutput(level); \ + if (level != vkcv::LogLevel::RAW_INFO) { \ + fprintf(output, "[%s]: %s [%s, line %d: %s]\n", vkcv::getLogName(level), \ + output_message, __FILE__, __LINE__, __PRETTY_FUNCTION__); \ + } else { \ + fprintf(output, "[%s]: %s\n", vkcv::getLogName(level), output_message); \ + } \ + fflush(output); \ + } #else /** @@ -111,7 +94,8 @@ namespace vkcv { * * @param[in] level Level of logging */ -#define vkcv_log(level, ...) {} +#define vkcv_log(level, ...) \ + {} #endif /** @@ -120,9 +104,8 @@ namespace vkcv { * * @param[in] error Error or exception */ -#define vkcv_log_error(error) { \ - vkcv_log(LogLevel::ERROR, "%s", (error).what()); \ -} +#define vkcv_log_error(error) \ + { vkcv_log(LogLevel::ERROR, "%s", (error).what()); } /** * @brief Macro-function to throw and log any error or @@ -130,14 +113,15 @@ namespace vkcv { * * @param[in] error Error or exception */ -#define vkcv_log_throw(error) { \ - try { \ - throw error; \ - } catch (const std::exception& e) { \ - vkcv_log_error(e); \ - throw; \ - } \ -} +#define vkcv_log_throw(error) \ + { \ + try { \ + throw error; \ + } catch (const std::exception &e) { \ + vkcv_log_error(e); \ + throw; \ + } \ + } /** * @brief Macro-function to throw and log an error @@ -145,8 +129,7 @@ namespace vkcv { * * @param[in] message Error message */ -#define vkcv_log_throw_error(message) { \ - vkcv_log_throw(std::runtime_error(message)); \ -} +#define vkcv_log_throw_error(message) \ + { vkcv_log_throw(std::runtime_error(message)); } -} +} // namespace vkcv diff --git a/include/vkcv/Multisampling.hpp b/include/vkcv/Multisampling.hpp index 3bcf5d7b2a8dd838fcb18817a611086f33b06b68..5b285d191875d4e530a6d694241961bf6b19f781 100644 --- a/include/vkcv/Multisampling.hpp +++ b/include/vkcv/Multisampling.hpp @@ -8,7 +8,7 @@ #include <vulkan/vulkan.hpp> namespace vkcv { - + enum class Multisampling { None, MSAA2X, @@ -24,7 +24,7 @@ namespace vkcv { * @return Sample count flag bits */ vk::SampleCountFlagBits msaaToSampleCountFlagBits(Multisampling msaa); - + /** * @brief Returns the amount of samples of a given * multi-sample anti-aliasing mode. @@ -33,5 +33,5 @@ namespace vkcv { * @return Number of samples */ uint32_t msaaToSampleCount(Multisampling msaa); - -} + +} // namespace vkcv diff --git a/include/vkcv/Pass.hpp b/include/vkcv/Pass.hpp index f931eef50d0c78d015ef08472b5513942773edc3..f6f7e32ce40374078721a67c9b1c3560d5ff1426 100644 --- a/include/vkcv/Pass.hpp +++ b/include/vkcv/Pass.hpp @@ -9,23 +9,16 @@ #include "Handles.hpp" #include "PassConfig.hpp" -namespace vkcv -{ +namespace vkcv { - PassHandle passFormats(Core &core, - const std::vector<vk::Format> formats, - bool clear = true, + PassHandle passFormats(Core &core, const std::vector<vk::Format> formats, bool clear = true, Multisampling multisampling = Multisampling::None); - - PassHandle passFormat(Core &core, - vk::Format format, - bool clear = true, + + PassHandle passFormat(Core &core, vk::Format format, bool clear = true, Multisampling multisampling = Multisampling::None); - - PassHandle passSwapchain(Core &core, - const SwapchainHandle &swapchain, - const std::vector<vk::Format> formats, - bool clear = true, + + PassHandle passSwapchain(Core &core, const SwapchainHandle &swapchain, + const std::vector<vk::Format> formats, bool clear = true, Multisampling multisampling = Multisampling::None); - -} + +} // namespace vkcv diff --git a/include/vkcv/PassConfig.hpp b/include/vkcv/PassConfig.hpp index 849a6e837acd6321afed6c99dc3b608ba26766b7..efe741d07fd731a2c71fd6bf706cda7e39d43a50 100644 --- a/include/vkcv/PassConfig.hpp +++ b/include/vkcv/PassConfig.hpp @@ -10,96 +10,85 @@ #include "Multisampling.hpp" -namespace vkcv -{ +namespace vkcv { /** * @brief Enum class to specify types of attachment operations. */ - enum class AttachmentOperation { - LOAD, - CLEAR, - STORE, - DONT_CARE - }; + enum class AttachmentOperation { + LOAD, + CLEAR, + STORE, + DONT_CARE + }; /** * @brief Class to store details about an attachment of a pass. */ - class AttachmentDescription { + class AttachmentDescription { private: vk::Format m_format; - + AttachmentOperation m_load_op; - AttachmentOperation m_store_op; - + AttachmentOperation m_store_op; + vk::ClearValue m_clear_value; + public: - AttachmentDescription(vk::Format format, - AttachmentOperation load, + AttachmentDescription(vk::Format format, AttachmentOperation load, AttachmentOperation store); - - AttachmentDescription(vk::Format format, - AttachmentOperation load, - AttachmentOperation store, - const vk::ClearValue &clear); - + + AttachmentDescription(vk::Format format, AttachmentOperation load, + AttachmentOperation store, const vk::ClearValue &clear); + AttachmentDescription(const AttachmentDescription &other) = default; AttachmentDescription(AttachmentDescription &&other) = default; - + ~AttachmentDescription() = default; - - AttachmentDescription& operator=(const AttachmentDescription &other) = default; - AttachmentDescription& operator=(AttachmentDescription &&other) = default; - - [[nodiscard]] - vk::Format getFormat() const; - - [[nodiscard]] - AttachmentOperation getLoadOperation() const; - - [[nodiscard]] - AttachmentOperation getStoreOperation() const; - + + AttachmentDescription &operator=(const AttachmentDescription &other) = default; + AttachmentDescription &operator=(AttachmentDescription &&other) = default; + + [[nodiscard]] vk::Format getFormat() const; + + [[nodiscard]] AttachmentOperation getLoadOperation() const; + + [[nodiscard]] AttachmentOperation getStoreOperation() const; + void setClearValue(const vk::ClearValue &clear); - - [[nodiscard]] - const vk::ClearValue& getClearValue() const; - - }; - + + [[nodiscard]] const vk::ClearValue &getClearValue() const; + }; + using AttachmentDescriptions = std::vector<AttachmentDescription>; /** * @brief Class to configure a pass for usage. */ - class PassConfig { + class PassConfig { private: AttachmentDescriptions m_attachments; - Multisampling m_multisampling; - + Multisampling m_multisampling; + public: PassConfig(); - + explicit PassConfig(const AttachmentDescriptions &attachments, Multisampling multisampling = Multisampling::None); - + PassConfig(const PassConfig &other) = default; PassConfig(PassConfig &&other) = default; - + ~PassConfig() = default; - - PassConfig& operator=(const PassConfig &other) = default; - PassConfig& operator=(PassConfig &&other) = default; - - [[nodiscard]] - const AttachmentDescriptions& getAttachments() const; - + + PassConfig &operator=(const PassConfig &other) = default; + PassConfig &operator=(PassConfig &&other) = default; + + [[nodiscard]] const AttachmentDescriptions &getAttachments() const; + void setMultisampling(Multisampling multisampling); - - [[nodiscard]] - Multisampling getMultisampling() const; - - }; - -} \ No newline at end of file + + [[nodiscard]] Multisampling getMultisampling() const; + }; + +} // namespace vkcv \ No newline at end of file diff --git a/include/vkcv/PipelineConfig.hpp b/include/vkcv/PipelineConfig.hpp index e53985f77a454891dd4d1fc69abcb2c0eb344912..575f17057ed1f0a8588fcf141a11a0e539aca178 100644 --- a/include/vkcv/PipelineConfig.hpp +++ b/include/vkcv/PipelineConfig.hpp @@ -11,7 +11,7 @@ #include "ShaderProgram.hpp" namespace vkcv { - + /** * @brief Class to configure a general pipeline before its creation. */ @@ -19,33 +19,30 @@ namespace vkcv { private: ShaderProgram m_ShaderProgram; std::vector<DescriptorSetLayoutHandle> m_DescriptorSetLayouts; - + public: PipelineConfig(); - - PipelineConfig(const ShaderProgram& program, - const std::vector<DescriptorSetLayoutHandle>& layouts); - + + PipelineConfig(const ShaderProgram &program, + const std::vector<DescriptorSetLayoutHandle> &layouts); + PipelineConfig(const PipelineConfig &other) = default; PipelineConfig(PipelineConfig &&other) = default; - + ~PipelineConfig() = default; - - PipelineConfig& operator=(const PipelineConfig &other) = default; - PipelineConfig& operator=(PipelineConfig &&other) = default; - - void setShaderProgram(const ShaderProgram& program); - - [[nodiscard]] - const ShaderProgram& getShaderProgram() const; - - void addDescriptorSetLayout(const DescriptorSetLayoutHandle& layout); - - void addDescriptorSetLayouts(const std::vector<DescriptorSetLayoutHandle>& layouts); - - [[nodiscard]] - const std::vector<DescriptorSetLayoutHandle>& getDescriptorSetLayouts() const; - + + PipelineConfig &operator=(const PipelineConfig &other) = default; + PipelineConfig &operator=(PipelineConfig &&other) = default; + + void setShaderProgram(const ShaderProgram &program); + + [[nodiscard]] const ShaderProgram &getShaderProgram() const; + + void addDescriptorSetLayout(const DescriptorSetLayoutHandle &layout); + + void addDescriptorSetLayouts(const std::vector<DescriptorSetLayoutHandle> &layouts); + + [[nodiscard]] const std::vector<DescriptorSetLayoutHandle> &getDescriptorSetLayouts() const; }; - -} + +} // namespace vkcv diff --git a/include/vkcv/PushConstants.hpp b/include/vkcv/PushConstants.hpp index 8d441bfcb57807eedc94d4cf839f6e99729d1cbe..7ba083f698bffdaf17179c0d25891aba4ef881a2 100644 --- a/include/vkcv/PushConstants.hpp +++ b/include/vkcv/PushConstants.hpp @@ -13,93 +13,90 @@ namespace vkcv { - /** - * @brief Class to handle push constants data per drawcall. - */ + /** + * @brief Class to handle push constants data per drawcall. + */ class PushConstants final { private: TypeGuard m_typeGuard; std::vector<uint8_t> m_data; - + public: explicit PushConstants(size_t sizePerDrawcall); explicit PushConstants(const TypeGuard &guard); - - PushConstants(const PushConstants& other) = default; - PushConstants(PushConstants&& other) = default; - + + PushConstants(const PushConstants &other) = default; + PushConstants(PushConstants &&other) = default; + ~PushConstants() = default; - - PushConstants& operator=(const PushConstants& other) = default; - PushConstants& operator=(PushConstants&& other) = default; - + + PushConstants &operator=(const PushConstants &other) = default; + PushConstants &operator=(PushConstants &&other) = default; + /** * @brief Returns the size of the data that is bound * per drawcall in bytes. * * @return Size of data per drawcall */ - [[nodiscard]] - size_t getSizePerDrawcall() const; - + [[nodiscard]] size_t getSizePerDrawcall() const; + /** * @brief Returns the size of total data stored for * push constants in bytes * * @return Total size of data */ - [[nodiscard]] - size_t getFullSize() const; - + [[nodiscard]] size_t getFullSize() const; + /** * @brief Returns the number of drawcalls that data * is stored for. * * @return Number of drawcalls */ - [[nodiscard]] - size_t getDrawcallCount() const; - + [[nodiscard]] size_t getDrawcallCount() const; + /** * @brief Clears the data for all drawcalls currently. * stored. - */ + */ void clear(); - + /** * @brief Appends data for a single drawcall to the * storage with a given type. - * + * * @tparam T Type of data (must match the size per drawcall) * @param[in] value Data to append * @return True, if operation was successfull, otherwise false */ - template<typename T = uint8_t> - bool appendDrawcall(const T& value) { + template <typename T = uint8_t> + bool appendDrawcall(const T &value) { if (!m_typeGuard.template check<T>()) { return false; } - + const size_t offset = m_data.size(); m_data.resize(offset + sizeof(value)); std::memcpy(m_data.data() + offset, &value, sizeof(value)); return true; } - + /** * @brief Returns the data of the drawcall by a given index * as reference. - * + * * @tparam T Type of data * @param[in] index Index of the drawcall * @return Drawcall data */ - template<typename T = uint8_t> - T& getDrawcall(size_t index) { + template <typename T = uint8_t> + T &getDrawcall(size_t index) { const size_t offset = (index * getSizePerDrawcall()); return *reinterpret_cast<T*>(m_data.data() + offset); } - + /** * @brief Returns the data of the drawcall by a given index * as const reference. @@ -108,56 +105,53 @@ namespace vkcv { * @param[in] index Index of the drawcall * @return Drawcall data */ - template<typename T = uint8_t> - const T& getDrawcall(size_t index) const { + template <typename T = uint8_t> + const T &getDrawcall(size_t index) const { const size_t offset = (index * getSizePerDrawcall()); return *reinterpret_cast<const T*>(m_data.data() + offset); } - + /** * @brief Returns the data of the drawcall by a given index * as a pointer. - * + * * @param[in] index Index of the drawcall * @return Drawcall data */ - [[nodiscard]] - const void* getDrawcallData(size_t index) const; - + [[nodiscard]] const void* getDrawcallData(size_t index) const; + /** * @brief Returns the pointer to the entire drawcall data which * might be nullptr if the data is empty. * * @return Pointer to the data */ - [[nodiscard]] - const void* getData() const; - + [[nodiscard]] const void* getData() const; }; - - template<typename T> + + template <typename T> PushConstants pushConstants() { return PushConstants(typeGuard<T>()); } - - template<typename T> - PushConstants pushConstants(const T& value) { + + template <typename T> + PushConstants pushConstants(const T &value) { auto pc = pushConstants<T>(); pc.template appendDrawcall(value); return pc; } - - template<typename T> - PushConstants pushConstants(const std::vector<T>& values) { + + template <typename T> + PushConstants pushConstants(const std::vector<T> &values) { auto pc = pushConstants<T>(); - - for (const T& value : values) { + + for (const T &value : values) { if (!(pc.template appendDrawcall(value))) { break; } } - + return pc; } - -} + +} // namespace vkcv diff --git a/include/vkcv/QueueManager.hpp b/include/vkcv/QueueManager.hpp index 04a5d8a0a59b2655673d073a7a36467df0ab8a17..5bdf64dd2ac10f9cbfb4a03d58a3ed27d827a755 100644 --- a/include/vkcv/QueueManager.hpp +++ b/include/vkcv/QueueManager.hpp @@ -4,7 +4,7 @@ * @file vkcv/QueueManager.hpp * @brief Types to manage queues of a device. */ - + #include <vulkan/vulkan.hpp> namespace vkcv { @@ -25,10 +25,10 @@ namespace vkcv { struct Queue { int familyIndex; int queueIndex; - + vk::Queue handle; }; - + /** * @brief Class to manage queues of a device. */ @@ -47,40 +47,36 @@ namespace vkcv { const std::vector<std::pair<int, int>> &queuePairsGraphics, const std::vector<std::pair<int, int>> &queuePairsCompute, const std::vector<std::pair<int, int>> &queuePairsTransfer); - + /** * @brief Returns the default queue with present support. * Recommended to use the present queue in the swapchain. * * @return Default present queue */ - [[nodiscard]] - const Queue &getPresentQueue() const; + [[nodiscard]] const Queue &getPresentQueue() const; /** * @brief Returns all queues with the graphics flag. * * @return Vector of graphics queues */ - [[nodiscard]] - const std::vector<Queue> &getGraphicsQueues() const; + [[nodiscard]] const std::vector<Queue> &getGraphicsQueues() const; /** * @brief Returns all queues with the compute flag. * * @return Vector of compute queues */ - [[nodiscard]] - const std::vector<Queue> &getComputeQueues() const; + [[nodiscard]] const std::vector<Queue> &getComputeQueues() const; /** * @brief Returns all queues with the transfer flag. * * @return Vector of transfer queues */ - [[nodiscard]] - const std::vector<Queue> &getTransferQueues() const; - + [[nodiscard]] const std::vector<Queue> &getTransferQueues() const; + /** * @brief Checks for presenting support of a given surface * in the queues and returns the queue family index of the @@ -93,16 +89,14 @@ namespace vkcv { static uint32_t checkSurfaceSupport(const vk::PhysicalDevice &physicalDevice, const vk::SurfaceKHR &surface); - private: - std::vector<Queue> m_graphicsQueues; - std::vector<Queue> m_computeQueues; - std::vector<Queue> m_transferQueues; - + private: + std::vector<Queue> m_graphicsQueues; + std::vector<Queue> m_computeQueues; + std::vector<Queue> m_transferQueues; + size_t m_presentIndex; - QueueManager(std::vector<Queue>&& graphicsQueues, - std::vector<Queue>&& computeQueues, - std::vector<Queue>&& transferQueues, - size_t presentIndex); + QueueManager(std::vector<Queue> &&graphicsQueues, std::vector<Queue> &&computeQueues, + std::vector<Queue> &&transferQueues, size_t presentIndex); }; -} +} // namespace vkcv diff --git a/include/vkcv/Result.hpp b/include/vkcv/Result.hpp index 328a44fa58c9b6303af872d7787cc1bcb7230256..7a11031913cd4c0604f4023f5e8c5d9be6abba2f 100644 --- a/include/vkcv/Result.hpp +++ b/include/vkcv/Result.hpp @@ -7,12 +7,12 @@ namespace vkcv { - /** - * @brief Enum class to specify the result of a function call. - */ + /** + * @brief Enum class to specify the result of a function call. + */ enum class Result { SUCCESS = 0, ERROR = 1 }; - -} + +} // namespace vkcv diff --git a/include/vkcv/Sampler.hpp b/include/vkcv/Sampler.hpp index 601370c71bfaa3a8eaad023cae532b083d78fa90..c4dc00e6e6178edeb8e056ac21838a268d60a66c 100644 --- a/include/vkcv/Sampler.hpp +++ b/include/vkcv/Sampler.hpp @@ -6,17 +6,13 @@ */ #include "Core.hpp" -#include "SamplerTypes.hpp" #include "Handles.hpp" +#include "SamplerTypes.hpp" namespace vkcv { - - [[nodiscard]] - SamplerHandle samplerLinear(Core &core, - bool clampToEdge = false); - - [[nodiscard]] - SamplerHandle samplerNearest(Core &core, - bool clampToEdge = false); -} + [[nodiscard]] SamplerHandle samplerLinear(Core &core, bool clampToEdge = false); + + [[nodiscard]] SamplerHandle samplerNearest(Core &core, bool clampToEdge = false); + +} // namespace vkcv diff --git a/include/vkcv/SamplerTypes.hpp b/include/vkcv/SamplerTypes.hpp index 4dc68930050ff955a251f701657462a8b5ebbb1f..2c64da27acb6c5a2b689ef56e242303917f2f03a 100644 --- a/include/vkcv/SamplerTypes.hpp +++ b/include/vkcv/SamplerTypes.hpp @@ -6,15 +6,15 @@ */ namespace vkcv { - + /** - * @brief Enum class to specify a samplers type to filter during access. - */ + * @brief Enum class to specify a samplers type to filter during access. + */ enum class SamplerFilterType { NEAREST = 1, LINEAR = 2 }; - + /** * @brief Enum class to specify a samplers mode to access mipmaps. */ @@ -22,7 +22,7 @@ namespace vkcv { NEAREST = 1, LINEAR = 2 }; - + /** * @brief Enum class to specify a samplers mode to access via address space. */ @@ -33,19 +33,19 @@ namespace vkcv { MIRROR_CLAMP_TO_EDGE = 4, CLAMP_TO_BORDER = 5 }; - + /** * @brief Enum class to specify a samplers color beyond a textures border. */ enum class SamplerBorderColor { INT_ZERO_OPAQUE = 1, INT_ZERO_TRANSPARENT = 2, - + FLOAT_ZERO_OPAQUE = 3, FLOAT_ZERO_TRANSPARENT = 4, - + INT_ONE_OPAQUE = 5, FLOAT_ONE_OPAQUE = 6 }; - -} + +} // namespace vkcv diff --git a/include/vkcv/ShaderProgram.hpp b/include/vkcv/ShaderProgram.hpp index 0cc4fed0d87195dec3b0eae345e206724d2f4060..11156fdb5111da53df53ba7cbe80fa130d45b060 100644 --- a/include/vkcv/ShaderProgram.hpp +++ b/include/vkcv/ShaderProgram.hpp @@ -1,57 +1,57 @@ #pragma once /** - * @authors Artur Wasmut, Leonie Franken, Tobias Frisch, Simeon Hermann, Alexander Gauggel, Mark Mints + * @authors Artur Wasmut, Leonie Franken, Tobias Frisch, Simeon Hermann, Alexander Gauggel, Mark + * Mints * @file vkcv/ShaderProgram.hpp * @brief ShaderProgram class to handle and prepare the shader stages for a graphics pipeline. */ -#include <unordered_map> -#include <fstream> -#include <iostream> #include <algorithm> #include <filesystem> -#include <vulkan/vulkan.hpp> +#include <fstream> +#include <iostream> #include <spirv_cross.hpp> +#include <unordered_map> +#include <vulkan/vulkan.hpp> #include "DescriptorBinding.hpp" -#include "VertexLayout.hpp" #include "ShaderStage.hpp" +#include "VertexLayout.hpp" namespace vkcv { - /** - * @brief Class to manage and reflect shaders as a program. - */ - class ShaderProgram - { - public: - ShaderProgram() noexcept; // ctor - ~ShaderProgram() = default; // dtor + /** + * @brief Class to manage and reflect shaders as a program. + */ + class ShaderProgram { + public: + ShaderProgram() noexcept; // ctor + ~ShaderProgram() = default; // dtor - /** - * @brief Adds a shader into the shader program. - * The shader is only added if the shader program does not contain - * the particular shader stage already. - * Contains: - * (1) reading the SPIR-V file, - * (2) creating a shader module, - * (3) creating a shader stage, - * (4) adding to the shader stage list, - * (5) destroying of the shader module - * - * @param[in] stage The stage of the shader - * @param[in] path Path to the SPIR-V shader file - */ - bool addShader(ShaderStage stage, const std::filesystem::path &path); + /** + * @brief Adds a shader into the shader program. + * The shader is only added if the shader program does not contain + * the particular shader stage already. + * Contains: + * (1) reading the SPIR-V file, + * (2) creating a shader module, + * (3) creating a shader stage, + * (4) adding to the shader stage list, + * (5) destroying of the shader module + * + * @param[in] stage The stage of the shader + * @param[in] path Path to the SPIR-V shader file + */ + bool addShader(ShaderStage stage, const std::filesystem::path &path); - /** - * @brief Returns the shader binary of a specified stage from the program. - * Needed for the transfer to the pipeline. - * - * @param[in] stage The stage of the shader - * @return Shader code binary of the given stage - */ - const std::vector<uint32_t> &getShaderBinary(ShaderStage stage) const; + /** + * @brief Returns the shader binary of a specified stage from the program. + * Needed for the transfer to the pipeline. + * + * @param[in] stage The stage of the shader + * @return Shader code binary of the given stage + */ + const std::vector<uint32_t> &getShaderBinary(ShaderStage stage) const; /** * @brief Returns whether a shader exists in the program for a @@ -60,7 +60,7 @@ namespace vkcv { * @param[in] stage The stage of the shader * @return True, if a shader exists for the stage, else false */ - bool existsShader(ShaderStage stage) const; + bool existsShader(ShaderStage stage) const; /** * @brief Returns the vertex attachments for the program and its @@ -68,8 +68,8 @@ namespace vkcv { * * @return Vertex attachments */ - const std::vector<VertexAttachment> &getVertexAttachments() const; - + const std::vector<VertexAttachment> &getVertexAttachments() const; + /** * @brief Returns the size of the programs push constants. * @@ -83,24 +83,23 @@ namespace vkcv { * * @return Reflected descriptor set bindings */ - const std::unordered_map<uint32_t, DescriptorBindings>& getReflectedDescriptors() const; + const std::unordered_map<uint32_t, DescriptorBindings> &getReflectedDescriptors() const; private: - /** - * @brief Called after successfully adding a shader to the program. - * Fills vertex input attachments and descriptor sets (if present). - * - * @param[in] shaderStage the stage to reflect data from - */ - void reflectShader(ShaderStage shaderStage); + /** + * @brief Called after successfully adding a shader to the program. + * Fills vertex input attachments and descriptor sets (if present). + * + * @param[in] shaderStage the stage to reflect data from + */ + void reflectShader(ShaderStage shaderStage); - std::unordered_map<ShaderStage, std::vector<uint32_t> > m_Shaders; + std::unordered_map<ShaderStage, std::vector<uint32_t> > m_Shaders; - // contains all vertex input attachments used in the vertex buffer - VertexAttachments m_VertexAttachments; - std::unordered_map<uint32_t, DescriptorBindings> m_DescriptorSets; + // contains all vertex input attachments used in the vertex buffer + VertexAttachments m_VertexAttachments; + std::unordered_map<uint32_t, DescriptorBindings> m_DescriptorSets; size_t m_pushConstantsSize = 0; - }; -} +} // namespace vkcv diff --git a/include/vkcv/ShaderStage.hpp b/include/vkcv/ShaderStage.hpp index d143b776c876f9a5cf6e298e485acc354fdf2b12..2b6ab23ca623bb837d3e4fd3c5b22ca3b187fd43 100644 --- a/include/vkcv/ShaderStage.hpp +++ b/include/vkcv/ShaderStage.hpp @@ -1,6 +1,7 @@ #pragma once /** - * @authors Artur Wasmut, Simeon Hermann, Tobias Frisch, Vanessa Karolek, Alexander Gauggel, Lars Hoerttrich + * @authors Artur Wasmut, Simeon Hermann, Tobias Frisch, Vanessa Karolek, Alexander Gauggel, Lars + * Hoerttrich * @file vkcv/ShaderStage.hpp * @brief Enum and struct to operate with multiple shader stages. */ @@ -8,14 +9,16 @@ #include <vulkan/vulkan.hpp> namespace vkcv { - + /** * @brief Enum class to specify the stage of a shader. */ enum class ShaderStage : VkShaderStageFlags { VERTEX = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eVertex), - TESS_CONTROL = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eTessellationControl), - TESS_EVAL = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eTessellationEvaluation), + TESS_CONTROL = + static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eTessellationControl), + TESS_EVAL = + static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eTessellationEvaluation), GEOMETRY = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eGeometry), FRAGMENT = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eFragment), COMPUTE = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eCompute), @@ -25,66 +28,61 @@ namespace vkcv { RAY_ANY_HIT = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eAnyHitKHR), RAY_CLOSEST_HIT = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eClosestHitKHR), RAY_MISS = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eMissKHR), - RAY_INTERSECTION = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eIntersectionKHR), + RAY_INTERSECTION = + static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eIntersectionKHR), RAY_CALLABLE = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eCallableKHR) }; - + using ShaderStages = vk::Flags<ShaderStage>; - -} + +} // namespace vkcv /** * @cond VULKAN_TYPES */ namespace vk { - - template<> + + template <> struct [[maybe_unused]] FlagTraits<vkcv::ShaderStage> { enum : VkFlags { - allFlags [[maybe_unused]] = ( - VkFlags( vkcv::ShaderStage::VERTEX ) | - VkFlags( vkcv::ShaderStage::TESS_CONTROL ) | - VkFlags( vkcv::ShaderStage::TESS_EVAL ) | - VkFlags( vkcv::ShaderStage::GEOMETRY ) | - VkFlags( vkcv::ShaderStage::FRAGMENT ) | - VkFlags( vkcv::ShaderStage::COMPUTE ) | - VkFlags( vkcv::ShaderStage::TASK ) | - VkFlags( vkcv::ShaderStage::MESH ) | - VkFlags( vkcv::ShaderStage::RAY_GEN ) | - VkFlags( vkcv::ShaderStage::RAY_ANY_HIT ) | - VkFlags( vkcv::ShaderStage::RAY_CLOSEST_HIT ) | - VkFlags( vkcv::ShaderStage::RAY_MISS ) | - VkFlags( vkcv::ShaderStage::RAY_INTERSECTION ) | - VkFlags( vkcv::ShaderStage::RAY_CALLABLE ) - ) + allFlags [[maybe_unused]] = + (VkFlags(vkcv::ShaderStage::VERTEX) | VkFlags(vkcv::ShaderStage::TESS_CONTROL) + | VkFlags(vkcv::ShaderStage::TESS_EVAL) | VkFlags(vkcv::ShaderStage::GEOMETRY) + | VkFlags(vkcv::ShaderStage::FRAGMENT) | VkFlags(vkcv::ShaderStage::COMPUTE) + | VkFlags(vkcv::ShaderStage::TASK) | VkFlags(vkcv::ShaderStage::MESH) + | VkFlags(vkcv::ShaderStage::RAY_GEN) | VkFlags(vkcv::ShaderStage::RAY_ANY_HIT) + | VkFlags(vkcv::ShaderStage::RAY_CLOSEST_HIT) + | VkFlags(vkcv::ShaderStage::RAY_MISS) + | VkFlags(vkcv::ShaderStage::RAY_INTERSECTION) + | VkFlags(vkcv::ShaderStage::RAY_CALLABLE)) }; }; - -} + +} // namespace vk /** * @endcond */ namespace vkcv { - + constexpr vk::ShaderStageFlags getShaderStageFlags(ShaderStages shaderStages) noexcept { return vk::ShaderStageFlags(static_cast<VkShaderStageFlags>(shaderStages)); } - + constexpr ShaderStages operator|(ShaderStage stage0, ShaderStage stage1) noexcept { return ShaderStages(stage0) | stage1; } - + constexpr ShaderStages operator&(ShaderStage stage0, ShaderStage stage1) noexcept { return ShaderStages(stage0) & stage1; } - + constexpr ShaderStages operator^(ShaderStage stage0, ShaderStage stage1) noexcept { return ShaderStages(stage0) ^ stage1; } - + constexpr ShaderStages operator~(ShaderStage stage) noexcept { return ~(ShaderStages(stage)); } - -} + +} // namespace vkcv diff --git a/include/vkcv/TypeGuard.hpp b/include/vkcv/TypeGuard.hpp index cac170c0105c24c2c00758423e5c723758761ac7..a5312b161d4ded7b061d351608e269b04f20807a 100644 --- a/include/vkcv/TypeGuard.hpp +++ b/include/vkcv/TypeGuard.hpp @@ -9,7 +9,7 @@ #include <typeinfo> namespace vkcv { - + /** * @brief Class bringing type safety during runtime to other classes. */ @@ -18,15 +18,13 @@ namespace vkcv { #ifndef NDEBUG const char* m_typeName; size_t m_typeHash; - - [[nodiscard]] - bool checkType(const char* name, size_t hash, size_t size) const; + + [[nodiscard]] bool checkType(const char* name, size_t hash, size_t size) const; #endif size_t m_typeSize; - - [[nodiscard]] - bool checkTypeSize(size_t size) const; - + + [[nodiscard]] bool checkTypeSize(size_t size) const; + public: /** * Explicit constructor to create a type guard by a specific @@ -36,7 +34,7 @@ namespace vkcv { * @param[in] size Size of type */ explicit TypeGuard(size_t size = 0); - + /** * Explicit constructor to create a type guard by a types * ID information and its size. The guard will verify a type @@ -46,15 +44,15 @@ namespace vkcv { * @param[in] size Size of type */ TypeGuard(const std::type_info &info, size_t size); - + TypeGuard(const TypeGuard &other) = default; TypeGuard(TypeGuard &&other) noexcept = default; - + ~TypeGuard() = default; - - TypeGuard& operator=(const TypeGuard &other) = default; - TypeGuard& operator=(TypeGuard &&other) noexcept = default; - + + TypeGuard &operator=(const TypeGuard &other) = default; + TypeGuard &operator=(TypeGuard &&other) noexcept = default; + /** * Operator to compare two type guards and returns * whether their stored type information and size @@ -64,7 +62,7 @@ namespace vkcv { * @return True if the details match, otherwise false. */ bool operator==(const TypeGuard &other) const; - + /** * Operator to compare two type guards and returns * whether their stored type information and size @@ -74,7 +72,7 @@ namespace vkcv { * @return True if the details differ, otherwise false. */ bool operator!=(const TypeGuard &other) const; - + /** * Checks whether a type from a template parameter * matches with the used type by the given guard. @@ -82,26 +80,23 @@ namespace vkcv { * @tparam T Type to check against * @return True if both types match, otherwise false. */ - template<typename T> - [[nodiscard]] - bool check() const { + template <typename T> + [[nodiscard]] bool check() const { #ifndef NDEBUG return checkType(typeid(T).name(), typeid(T).hash_code(), sizeof(T)); #else return checkTypeSize(sizeof(T)); #endif } - + /** * Returns the size of this guards type in bytes. * * @return Size of type */ - [[nodiscard]] - size_t typeSize() const; - + [[nodiscard]] size_t typeSize() const; }; - + /** * Creates a new type guard with a given type specified * as template parameter. @@ -109,12 +104,12 @@ namespace vkcv { * @tparam T Type * @return New type guard */ - template<typename T> + template <typename T> TypeGuard typeGuard() { - static TypeGuard guard (typeid(T), sizeof(T)); + static TypeGuard guard(typeid(T), sizeof(T)); return guard; } - + /** * Creates a new type guard with a given type specified * as template parameter by the passed parameter. @@ -122,11 +117,11 @@ namespace vkcv { * @tparam T Type * @return New type guard */ - template<typename T> + template <typename T> TypeGuard typeGuard(T) { return typeGuard<T>(); } - + /** * Creates a new type guard with a given type specified * as template parameter by the passed parameter. @@ -134,11 +129,11 @@ namespace vkcv { * @tparam T Type * @return New type guard */ - template<typename T> - TypeGuard typeGuard(const T&) { + template <typename T> + TypeGuard typeGuard(const T &) { return typeGuard<T>(); } - + /** * Creates a new type guard with a given type specified * as template parameter by the passed parameter. @@ -146,9 +141,9 @@ namespace vkcv { * @tparam T Type * @return New type guard */ - template<typename T> - TypeGuard typeGuard(T&&) { + template <typename T> + TypeGuard typeGuard(T &&) { return typeGuard<T>(); } -} +} // namespace vkcv diff --git a/include/vkcv/VertexData.hpp b/include/vkcv/VertexData.hpp index 001dcfcf6e96f1e356316ef56bd7810583531239..4ee015db3d0765bc667ef7caf74cf5b2d64a6f45 100644 --- a/include/vkcv/VertexData.hpp +++ b/include/vkcv/VertexData.hpp @@ -10,7 +10,7 @@ #include "Handles.hpp" namespace vkcv { - + /** * @brief Structure to store details about a vertex buffer binding. */ @@ -18,12 +18,11 @@ namespace vkcv { BufferHandle buffer; size_t offset; }; - - VertexBufferBinding vertexBufferBinding(const BufferHandle &buffer, - size_t offset = 0); - + + VertexBufferBinding vertexBufferBinding(const BufferHandle &buffer, size_t offset = 0); + typedef std::vector<VertexBufferBinding> VertexBufferBindings; - + /** * @brief Enum class to specify the size of indexes. */ @@ -32,42 +31,37 @@ namespace vkcv { Bit16, Bit32 }; - + class VertexData { private: VertexBufferBindings m_bindings; BufferHandle m_indices; IndexBitCount m_indexBitCount; size_t m_count; - + public: explicit VertexData(const VertexBufferBindings &bindings = {}); - - VertexData(const VertexData& other) = default; - VertexData(VertexData&& other) noexcept = default; - + + VertexData(const VertexData &other) = default; + VertexData(VertexData &&other) noexcept = default; + ~VertexData() = default; - - VertexData& operator=(const VertexData& other) = default; - VertexData& operator=(VertexData&& other) noexcept = default; - - [[nodiscard]] - const VertexBufferBindings& getVertexBufferBindings() const; - - void setIndexBuffer(const BufferHandle& indices, + + VertexData &operator=(const VertexData &other) = default; + VertexData &operator=(VertexData &&other) noexcept = default; + + [[nodiscard]] const VertexBufferBindings &getVertexBufferBindings() const; + + void setIndexBuffer(const BufferHandle &indices, IndexBitCount indexBitCount = IndexBitCount::Bit16); - - [[nodiscard]] - const BufferHandle& getIndexBuffer() const; - - [[nodiscard]] - IndexBitCount getIndexBitCount() const; - + + [[nodiscard]] const BufferHandle &getIndexBuffer() const; + + [[nodiscard]] IndexBitCount getIndexBitCount() const; + void setCount(size_t count); - - [[nodiscard]] - size_t getCount() const; - + + [[nodiscard]] size_t getCount() const; }; -} +} // namespace vkcv diff --git a/include/vkcv/VertexLayout.hpp b/include/vkcv/VertexLayout.hpp index 8e677d11dc49594416f7eedda9d2ef00edae830a..88638261483e870418a4e7af86424e6798b1c1e7 100644 --- a/include/vkcv/VertexLayout.hpp +++ b/include/vkcv/VertexLayout.hpp @@ -6,25 +6,25 @@ * @brief Structures to handle vertex layout, bindings and attachments. */ -#include <vector> #include <iostream> #include <string> +#include <vector> namespace vkcv { - + /** * @brief Enum class to specify the format of vertex attributes. */ - enum class VertexAttachmentFormat { - FLOAT, - FLOAT2, - FLOAT3, - FLOAT4, - INT, - INT2, - INT3, - INT4 - }; + enum class VertexAttachmentFormat { + FLOAT, + FLOAT2, + FLOAT3, + FLOAT4, + INT, + INT2, + INT3, + INT4 + }; /** * @brief Returns the size in bytes of a vertex with a @@ -41,15 +41,15 @@ namespace vkcv { * Describes an individual vertex input attribute/attachment. The offset * is calculated when a collection of attachments forms a binding. */ - struct VertexAttachment { - uint32_t inputLocation; - std::string name; - VertexAttachmentFormat format; - uint32_t offset; - }; - + struct VertexAttachment { + uint32_t inputLocation; + std::string name; + VertexAttachmentFormat format; + uint32_t offset; + }; + typedef std::vector<VertexAttachment> VertexAttachments; - + /** * @brief Structure to store the details of a vertex buffer binding. * @@ -58,12 +58,12 @@ namespace vkcv { * various (mutually exclusive) vertex input attachments to form one * complete vertex buffer binding! */ - struct VertexBinding { - uint32_t bindingLocation; - uint32_t stride; + struct VertexBinding { + uint32_t bindingLocation; + uint32_t stride; VertexAttachments vertexAttachments; - }; - + }; + /** * Creates a vertex binding with given parameters and calculates its strides * depending on its attachments. @@ -72,10 +72,11 @@ namespace vkcv { * @param[in] attachments The vertex input attachments this specific buffer layout contains. * @return Vertex binding with calculated stride */ - VertexBinding createVertexBinding(uint32_t bindingLocation, const VertexAttachments &attachments); - + VertexBinding createVertexBinding(uint32_t bindingLocation, + const VertexAttachments &attachments); + typedef std::vector<VertexBinding> VertexBindings; - + /** * Creates vertex bindings in a very simplified way with one vertex binding for * each attachment. @@ -92,8 +93,8 @@ namespace vkcv { * attachments used, and all of the buffer bindings that refer to the attachments * (for when multiple buffers are used). */ - struct VertexLayout { + struct VertexLayout { VertexBindings vertexBindings; - }; - -} + }; + +} // namespace vkcv diff --git a/include/vkcv/Window.hpp b/include/vkcv/Window.hpp index e7a27730140c50c791cd72b94d56488732770265..3d157b98220f17752d6b109401c3d21899299f18 100644 --- a/include/vkcv/Window.hpp +++ b/include/vkcv/Window.hpp @@ -19,61 +19,61 @@ struct GLFWwindow; namespace vkcv { - /** - * @brief Class to handle a window. - */ - class Window { + /** + * @brief Class to handle a window. + */ + class Window { friend class WindowManager; friend class SwapchainManager; - + private: - std::string m_title; - bool m_resizable; + std::string m_title; + bool m_resizable; bool m_shouldClose; - GLFWwindow *m_window; + GLFWwindow* m_window; SwapchainHandle m_swapchainHandle; event_handle<int, int> m_resizeHandle; - public: - /** - * @brief Constructor of an uninitialized #Window - */ - Window(); - - /** - * @brief Constructor of a #Window with an optional width, - * height and resizable attribute. - * - * @param[in] title title of the window - * @param[in] width width of the window (optional) - * @param[in] height height of the window (optional) - * @param[in] resizable resize ability of the window (optional) - */ - explicit Window(const char* title, int width = -1, int height = -1, bool resizable = false); - - /** - * @brief Copy-constructor of a #Window - * - * @param[in] other Other instance of #Window - */ - Window(const Window& other) = delete; - - /** - * @brief Copy-operator of a #Window - * - * @param[in] other Other instance of #Window - * @return Reference to itself - */ + public: + /** + * @brief Constructor of an uninitialized #Window + */ + Window(); + + /** + * @brief Constructor of a #Window with an optional width, + * height and resizable attribute. + * + * @param[in] title title of the window + * @param[in] width width of the window (optional) + * @param[in] height height of the window (optional) + * @param[in] resizable resize ability of the window (optional) + */ + explicit Window(const std::string &title, int width = -1, int height = -1, + bool resizable = false); + + /** + * @brief Copy-constructor of a #Window + * + * @param[in] other Other instance of #Window + */ + Window(const Window &other) = delete; + + /** + * @brief Copy-operator of a #Window + * + * @param[in] other Other instance of #Window + * @return Reference to itself + */ Window &operator=(const Window &other) = delete; - - /** - * @brief Checks if the window is still open, or the close event was called. - * TODO: This function should be changed/removed later on - * - * @return True, if the window is still open, else false - */ - [[nodiscard]] - bool isOpen() const; + + /** + * @brief Checks if the window is still open, or the close event was called. + * TODO: This function should be changed/removed later on + * + * @return True, if the window is still open, else false + */ + [[nodiscard]] bool isOpen() const; /** * @brief Returns the currently focused window. @@ -81,8 +81,8 @@ namespace vkcv { * * @return Current window in focus */ - static Window& getFocusedWindow(); - + static Window &getFocusedWindow(); + /** * @brief Checks if any windows are active and open. * @@ -90,87 +90,81 @@ namespace vkcv { */ static bool hasOpenWindow(); - /** - * @brief Polls all events on the active windows. - */ - static void pollEvents(); - + /** + * @brief Polls all events on the active windows. + */ + static void pollEvents(); + /** * @brief Returns the required extensions to use GLFW windows with Vulkan. * * @return Required surface extensions */ - static const std::vector<std::string>& getExtensions(); - - event< int, int, int> e_mouseButton; - event< double, double > e_mouseMove; - event< double, double > e_mouseScroll; - event< int, int > e_resize; - event< int, int, int, int > e_key; - event< unsigned int > e_char; - event< int > e_gamepad; - - /** - * @brief Returns the GLFW window handle. - * - * @return GLFW window handle - */ - [[nodiscard]] - GLFWwindow *getWindow() const; - - /** - * @brief Returns the title of the window. - * - * @return Window title - */ - [[nodiscard]] - const std::string& getTitle() const; - - /** - * @brief Returns the width of the window. - * - * @return Window width - */ - [[nodiscard]] - int getWidth() const; - - /** - * @brief Returns the height of the window. - * - * @return Window height - */ - [[nodiscard]] - int getHeight() const; - - /** - * @brief Returns whether the window is resizable or not. - * - * @return True, if the window is resizable, else false - */ - [[nodiscard]] - bool isResizable() const; - - /** - * @brief Destructor of the window which terminates GLFW in case - * of the last window got destroyed. - */ - virtual ~Window(); - - /** - * @brief Requests the windows framebuffer size. - * - * @param[out] width - * @param[out] height - */ - void getFramebufferSize(int& width, int& height) const; - - /** - * @brief Retruns the handle of the swapchain in use by the window. - * - * @return Swapchain handle - */ - SwapchainHandle getSwapchain() const; - - }; - -} + static const std::vector<std::string> &getExtensions(); + + event< int, int, int> e_mouseButton; + event< double, double > e_mouseMove; + event< double, double > e_mouseScroll; + event< int, int > e_resize; + event< int, int, int, int > e_key; + event< unsigned int > e_char; + event< int > e_gamepad; + + /** + * @brief Returns the GLFW window handle. + * + * @return GLFW window handle + */ + [[nodiscard]] GLFWwindow* getWindow() const; + + /** + * @brief Returns the title of the window. + * + * @return Window title + */ + [[nodiscard]] const std::string &getTitle() const; + + /** + * @brief Returns the width of the window. + * + * @return Window width + */ + [[nodiscard]] int getWidth() const; + + /** + * @brief Returns the height of the window. + * + * @return Window height + */ + [[nodiscard]] int getHeight() const; + + /** + * @brief Returns whether the window is resizable or not. + * + * @return True, if the window is resizable, else false + */ + [[nodiscard]] bool isResizable() const; + + /** + * @brief Destructor of the window which terminates GLFW in case + * of the last window got destroyed. + */ + virtual ~Window(); + + /** + * @brief Requests the windows framebuffer size. + * + * @param[out] width + * @param[out] height + */ + void getFramebufferSize(int &width, int &height) const; + + /** + * @brief Retruns the handle of the swapchain in use by the window. + * + * @return Swapchain handle + */ + SwapchainHandle getSwapchain() const; + }; + +} // namespace vkcv diff --git a/projects/bindless_textures/src/main.cpp b/projects/bindless_textures/src/main.cpp index e4dd4916b6a83a35abb809ed30f38cec67a01062..d4cb8d68ed783ccdac10f87311813d1b7d9f0959 100644 --- a/projects/bindless_textures/src/main.cpp +++ b/projects/bindless_textures/src/main.cpp @@ -11,7 +11,7 @@ #include <vkcv/shader/GLSLCompiler.hpp> int main(int argc, const char** argv) { - const char* applicationName = "Bindless Textures"; + const std::string applicationName = "Bindless Textures"; vkcv::Features features; features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); @@ -62,9 +62,8 @@ int main(int argc, const char** argv) { "resources/cube/Grass001_1K_Normal.jpg", "resources/cube/Grass001_1K_Roughness.jpg" }; - for (uint32_t i = 0; i < 5; i++) - { - std::filesystem::path grassPath(grassPaths[i]); + for (const auto &path : grassPaths) { + std::filesystem::path grassPath(path); vkcv::asset::Texture grassTexture = vkcv::asset::loadTexture(grassPath); vkcv::Image texture = vkcv::image( diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index 88ab4b70d72f30a3e622d8579cb75929039bc2cf..e043494492ab65b529d17e97ce6ccafbc5a71b8d 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -9,7 +9,7 @@ #include <vkcv/shader/GLSLCompiler.hpp> int main(int argc, const char** argv) { - const char* applicationName = "First Mesh"; + const std::string applicationName = "First Mesh"; vkcv::Core core = vkcv::Core::create( applicationName, diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp index 6b29b14bd92725af9439796c42012ba1d6bd4c80..bcd6b6ae0ec16346bcbd6cb5ba53631b3cdbde88 100644 --- a/projects/first_scene/src/main.cpp +++ b/projects/first_scene/src/main.cpp @@ -11,7 +11,7 @@ #include <vkcv/Features.hpp> int main(int argc, const char** argv) { - const char* applicationName = "First Scene"; + const std::string applicationName = "First Scene"; uint32_t windowWidth = 800; uint32_t windowHeight = 600; diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index 18c62285959775b2097f4b72fb13bf789480c914..b97136bd4c9e4a887b02c6ab2bb6199b58bfb054 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -7,7 +7,7 @@ #include <vkcv/shader/GLSLCompiler.hpp> int main(int argc, const char** argv) { - const char* applicationName = "First Triangle"; + const std::string applicationName = "First Triangle"; const int windowWidth = 800; const int windowHeight = 600; diff --git a/projects/head_demo/src/main.cpp b/projects/head_demo/src/main.cpp index 69daa8ba7c98523f9b287b210d5144cb154ec40b..de0cfdbb12e0177aa9ec1cfacd5a4040772e232e 100644 --- a/projects/head_demo/src/main.cpp +++ b/projects/head_demo/src/main.cpp @@ -13,7 +13,7 @@ #include <vkcv/upscaling/FSRUpscaling.hpp> int main(int argc, const char** argv) { - const char* applicationName = "First Scene"; + const std::string applicationName = "First Scene"; uint32_t windowWidth = 800; uint32_t windowHeight = 600; diff --git a/projects/indirect_draw/src/main.cpp b/projects/indirect_draw/src/main.cpp index 39c5621e2d1a062d86adbf77bef49cb3f639fdae..5519ac41cdd0793b846438658a5ebd0f31a18499 100644 --- a/projects/indirect_draw/src/main.cpp +++ b/projects/indirect_draw/src/main.cpp @@ -268,7 +268,7 @@ void compileMeshForIndirectDraw(vkcv::Core &core, } int main(int argc, const char** argv) { - const char* applicationName = "Indirect draw"; + const std::string applicationName = "Indirect draw"; vkcv::Features features; features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp index 034ae3c0de96d6ac434e3340cd6e4539626fbdba..1c743d168eeefa8531c18cf64dae23c71f6f7893 100644 --- a/projects/mesh_shader/src/main.cpp +++ b/projects/mesh_shader/src/main.cpp @@ -78,7 +78,7 @@ CameraPlanes computeCameraPlanes(const vkcv::camera::Camera& camera) { } int main(int argc, const char** argv) { - const char* applicationName = "Mesh shader"; + const std::string applicationName = "Mesh shader"; vkcv::Features features; features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); diff --git a/projects/particle_simulation/src/main.cpp b/projects/particle_simulation/src/main.cpp index 62a61806b26b9cfea89ab453b2c2291bd55cacef..0c581f2c086cf78e082cf8cb75c0f784109e6f4b 100644 --- a/projects/particle_simulation/src/main.cpp +++ b/projects/particle_simulation/src/main.cpp @@ -13,7 +13,7 @@ #include <vkcv/effects/BloomAndFlaresEffect.hpp> int main(int argc, const char **argv) { - const char *applicationName = "Particlesystem"; + const std::string applicationName = "Particlesystem"; uint32_t windowWidth = 800; uint32_t windowHeight = 600; @@ -175,7 +175,7 @@ int main(int argc, const char **argv) { vertexData.setIndexBuffer(particleIndexBuffer.getHandle()); vertexData.setCount(particleIndexBuffer.getCount()); - vkcv::DescriptorSetUsage descriptorUsage(0, descriptorSet); + auto descriptorUsage = vkcv::useDescriptorSet(0, descriptorSet); auto pos = glm::vec2(0.f); auto spawnPosition = glm::vec3(0.f); @@ -270,7 +270,7 @@ int main(int argc, const char **argv) { cmdStream, computePipeline, vkcv::dispatchInvocations(particleSystem.getParticles().size(), 256), - {vkcv::DescriptorSetUsage(0, computeDescriptorSet)}, + {vkcv::useDescriptorSet(0, computeDescriptorSet)}, pushConstantsCompute ); diff --git a/projects/path_tracer/src/main.cpp b/projects/path_tracer/src/main.cpp index 9a89696e82cf39bbb7281b6a489adc4afe66280a..1ce693997a8c4f75978705194edc0f9ba527f725 100644 --- a/projects/path_tracer/src/main.cpp +++ b/projects/path_tracer/src/main.cpp @@ -45,7 +45,7 @@ int main(int argc, const char** argv) { glm::vec2 padding3; }; - const char* applicationName = "Path Tracer"; + const std::string applicationName = "Path Tracer"; vkcv::Core core = vkcv::Core::create( applicationName, diff --git a/projects/rtx_ambient_occlusion/src/main.cpp b/projects/rtx_ambient_occlusion/src/main.cpp index d3d29049b8f64df1e00523c7beb55bd65dd46496..b04a39350165481e78c34e2083f3c4b7434a2972 100644 --- a/projects/rtx_ambient_occlusion/src/main.cpp +++ b/projects/rtx_ambient_occlusion/src/main.cpp @@ -11,7 +11,7 @@ */ int main(int argc, const char** argv) { - const char* applicationName = "RTX Ambient Occlusion"; + const std::string applicationName = "RTX Ambient Occlusion"; // prepare raytracing extensions. IMPORTANT: configure compiler to build in 64 bit mode vkcv::rtx::RTXExtensions rtxExtensions; diff --git a/projects/saf_r/src/main.cpp b/projects/saf_r/src/main.cpp index 1f446a8f5a4cd1bf5946328b5fe7e144f12f0d5f..5f95aa9a0607eb723143d4bdf07784cb41a5862e 100644 --- a/projects/saf_r/src/main.cpp +++ b/projects/saf_r/src/main.cpp @@ -29,7 +29,7 @@ void createQuadraticLightCluster(std::vector<safrScene::Light>& lights, int coun } int main(int argc, const char** argv) { - const char* applicationName = "SAF_R"; + const std::string applicationName = "SAF_R"; //window creation const int windowWidth = 800; diff --git a/projects/sph/src/main.cpp b/projects/sph/src/main.cpp index 4989b037375c3ca251411e957ea43030bba536c1..bb729bcd5cd5f01e4cf3fe12d400e42703fe8504 100644 --- a/projects/sph/src/main.cpp +++ b/projects/sph/src/main.cpp @@ -12,7 +12,7 @@ #include "Particle.hpp" int main(int argc, const char **argv) { - const char *applicationName = "SPH"; + const std::string applicationName = "SPH"; // creating core object that will handle all vulkan objects vkcv::Core core = vkcv::Core::create( diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index da2be34b3e174467392817efb6a4d4d0437b2257..38a582ae6ad2511a94642f86ebb96f70be1f64bb 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -17,7 +17,7 @@ #include <vkcv/algorithm/SinglePassDownsampler.hpp> int main(int argc, const char** argv) { - const char* applicationName = "Voxelization"; + const std::string applicationName = "Voxelization"; const vkcv::Multisampling msaa = vkcv::Multisampling::MSAA4X; const bool usingMsaa = msaa != vkcv::Multisampling::None; diff --git a/projects/wobble_bobble/src/main.cpp b/projects/wobble_bobble/src/main.cpp index e4f02691f9a7d97c355b276c389296e486221f4a..b361f68cdb67c74ae8aea69e39c00bbf54b46470 100644 --- a/projects/wobble_bobble/src/main.cpp +++ b/projects/wobble_bobble/src/main.cpp @@ -281,7 +281,7 @@ vkcv::BufferHandle resetParticles(vkcv::Core& core, size_t count, const glm::vec } int main(int argc, const char **argv) { - const char* applicationName = "Wobble Bobble"; + const std::string applicationName = "Wobble Bobble"; uint32_t windowWidth = 800; uint32_t windowHeight = 600; diff --git a/src/vkcv/BlitDownsampler.cpp b/src/vkcv/BlitDownsampler.cpp index 38e4812981b07451b4ee19d700b74a713e9ddc30..956c3079e683f3326b6085ca314d5c7081a74e0d 100644 --- a/src/vkcv/BlitDownsampler.cpp +++ b/src/vkcv/BlitDownsampler.cpp @@ -1,20 +1,18 @@ #include "vkcv/BlitDownsampler.hpp" -#include "vkcv/Core.hpp" #include "ImageManager.hpp" +#include "vkcv/Core.hpp" namespace vkcv { - - BlitDownsampler::BlitDownsampler(Core &core, - ImageManager& imageManager) : - Downsampler(core), - m_imageManager(imageManager) {} - + + BlitDownsampler::BlitDownsampler(Core &core, ImageManager &imageManager) : + Downsampler(core), m_imageManager(imageManager) {} + void BlitDownsampler::recordDownsampling(const CommandStreamHandle &cmdStream, const ImageHandle &image) { m_imageManager.recordImageMipChainGenerationToCmdStream(cmdStream, image); m_core.prepareImageForSampling(cmdStream, image); } - -} + +} // namespace vkcv diff --git a/src/vkcv/BufferManager.cpp b/src/vkcv/BufferManager.cpp index da2a370fac7a6d72c762ef47f8316519264a8457..567041bb602493196512b554014cf39277926bdc 100644 --- a/src/vkcv/BufferManager.cpp +++ b/src/vkcv/BufferManager.cpp @@ -8,150 +8,126 @@ #include <vkcv/Logger.hpp> namespace vkcv { - - bool BufferManager::init(Core& core) { + + bool BufferManager::init(Core &core) { if (!HandleManager<BufferEntry, BufferHandle>::init(core)) { return false; } - - m_stagingBuffer = createBuffer( - TypeGuard(1), - BufferType::STAGING, - BufferMemoryType::HOST_VISIBLE, - 1024 * 1024, - false - ); - + + m_stagingBuffer = createBuffer(TypeGuard(1), BufferType::STAGING, + BufferMemoryType::HOST_VISIBLE, 1024 * 1024, false); + return true; } - + uint64_t BufferManager::getIdFrom(const BufferHandle &handle) const { return handle.getId(); } - + BufferHandle BufferManager::createById(uint64_t id, const HandleDestroyFunction &destroy) { return BufferHandle(id, destroy); } - + void BufferManager::destroyById(uint64_t id) { - auto& buffer = getById(id); - - const vma::Allocator& allocator = getCore().getContext().getAllocator(); - + auto &buffer = getById(id); + + const vma::Allocator &allocator = getCore().getContext().getAllocator(); + if (buffer.m_handle) { allocator.destroyBuffer(buffer.m_handle, buffer.m_allocation); - + buffer.m_handle = nullptr; buffer.m_allocation = nullptr; } } - + BufferManager::BufferManager() noexcept : - HandleManager<BufferEntry, BufferHandle>(), - m_stagingBuffer(BufferHandle()) - {} - + HandleManager<BufferEntry, BufferHandle>(), m_stagingBuffer(BufferHandle()) {} + BufferManager::~BufferManager() noexcept { clear(); } - - BufferHandle BufferManager::createBuffer(const TypeGuard &typeGuard, - BufferType type, - BufferMemoryType memoryType, - size_t size, + + BufferHandle BufferManager::createBuffer(const TypeGuard &typeGuard, BufferType type, + BufferMemoryType memoryType, size_t size, bool readable) { vk::BufferCreateFlags createFlags; vk::BufferUsageFlags usageFlags; - + switch (type) { - case BufferType::VERTEX: - usageFlags = vk::BufferUsageFlagBits::eVertexBuffer; - break; - case BufferType::UNIFORM: - usageFlags = vk::BufferUsageFlagBits::eUniformBuffer; - break; - case BufferType::STORAGE: - usageFlags = vk::BufferUsageFlagBits::eStorageBuffer; - break; - case BufferType::STAGING: - usageFlags = vk::BufferUsageFlagBits::eTransferSrc | - vk::BufferUsageFlagBits::eTransferDst; - break; - case BufferType::INDEX: - usageFlags = vk::BufferUsageFlagBits::eIndexBuffer; - break; - case BufferType::INDIRECT: - usageFlags = vk::BufferUsageFlagBits::eStorageBuffer | - vk::BufferUsageFlagBits::eIndirectBuffer ; - break; - default: - vkcv_log(LogLevel::WARNING, "Unknown buffer type"); - break; + case BufferType::VERTEX: + usageFlags = vk::BufferUsageFlagBits::eVertexBuffer; + break; + case BufferType::UNIFORM: + usageFlags = vk::BufferUsageFlagBits::eUniformBuffer; + break; + case BufferType::STORAGE: + usageFlags = vk::BufferUsageFlagBits::eStorageBuffer; + break; + case BufferType::STAGING: + usageFlags = + vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst; + break; + case BufferType::INDEX: + usageFlags = vk::BufferUsageFlagBits::eIndexBuffer; + break; + case BufferType::INDIRECT: + usageFlags = + vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eIndirectBuffer; + break; + default: + vkcv_log(LogLevel::WARNING, "Unknown buffer type"); + break; } - + if (memoryType == BufferMemoryType::DEVICE_LOCAL) { usageFlags |= vk::BufferUsageFlagBits::eTransferDst; } - + if (readable) { usageFlags |= vk::BufferUsageFlagBits::eTransferSrc; } - - const vma::Allocator& allocator = getCore().getContext().getAllocator(); - + + const vma::Allocator &allocator = getCore().getContext().getAllocator(); + vk::MemoryPropertyFlags memoryTypeFlags; vma::MemoryUsage memoryUsage; bool mappable = false; - + switch (memoryType) { - case BufferMemoryType::DEVICE_LOCAL: - memoryTypeFlags = vk::MemoryPropertyFlagBits::eDeviceLocal; - memoryUsage = vma::MemoryUsage::eGpuOnly; - mappable = false; - break; - case BufferMemoryType::HOST_VISIBLE: - memoryTypeFlags = vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent; - memoryUsage = vma::MemoryUsage::eCpuOnly; - mappable = true; - break; - default: - vkcv_log(LogLevel::WARNING, "Unknown buffer memory type"); - memoryUsage = vma::MemoryUsage::eUnknown; - mappable = false; - break; + case BufferMemoryType::DEVICE_LOCAL: + memoryTypeFlags = vk::MemoryPropertyFlagBits::eDeviceLocal; + memoryUsage = vma::MemoryUsage::eGpuOnly; + mappable = false; + break; + case BufferMemoryType::HOST_VISIBLE: + memoryTypeFlags = vk::MemoryPropertyFlagBits::eHostVisible + | vk::MemoryPropertyFlagBits::eHostCoherent; + memoryUsage = vma::MemoryUsage::eCpuOnly; + mappable = true; + break; + default: + vkcv_log(LogLevel::WARNING, "Unknown buffer memory type"); + memoryUsage = vma::MemoryUsage::eUnknown; + mappable = false; + break; } - + if (type == BufferType::STAGING) { memoryUsage = vma::MemoryUsage::eCpuToGpu; } auto bufferAllocation = allocator.createBuffer( - vk::BufferCreateInfo(createFlags, size, usageFlags), - vma::AllocationCreateInfo( - vma::AllocationCreateFlags(), - memoryUsage, - memoryTypeFlags, - memoryTypeFlags, - 0, - vma::Pool(), - nullptr - ) - ); - + vk::BufferCreateInfo(createFlags, size, usageFlags), + vma::AllocationCreateInfo(vma::AllocationCreateFlags(), memoryUsage, memoryTypeFlags, + memoryTypeFlags, 0, vma::Pool(), nullptr)); + vk::Buffer buffer = bufferAllocation.first; vma::Allocation allocation = bufferAllocation.second; - - return add({ - typeGuard, - type, - memoryType, - size, - buffer, - allocation, - mappable - }); + + return add({ typeGuard, type, memoryType, size, buffer, allocation, mappable }); } - + /** * @brief Structure to store details required for a write staging process. */ @@ -159,15 +135,15 @@ namespace vkcv { const void* data; size_t size; size_t offset; - + vk::Buffer buffer; vk::Buffer stagingBuffer; vma::Allocation stagingAllocation; - + size_t stagingLimit; size_t stagingPosition; }; - + /** * Copies data from CPU to a staging buffer and submits the commands to copy * each part one after another into the actual target buffer. @@ -178,44 +154,37 @@ namespace vkcv { * @param core Core instance * @param info Staging-info structure */ - static void fillFromStagingBuffer(Core& core, StagingWriteInfo& info) { + static void fillFromStagingBuffer(Core &core, StagingWriteInfo &info) { const size_t remaining = info.size - info.stagingPosition; const size_t mapped_size = std::min(remaining, info.stagingLimit); - - const vma::Allocator& allocator = core.getContext().getAllocator(); - + + const vma::Allocator &allocator = core.getContext().getAllocator(); + void* mapped = allocator.mapMemory(info.stagingAllocation); - memcpy(mapped, reinterpret_cast<const char*>(info.data) + info.stagingPosition, mapped_size); + memcpy(mapped, reinterpret_cast<const char*>(info.data) + info.stagingPosition, + mapped_size); allocator.unmapMemory(info.stagingAllocation); - + auto stream = core.createCommandStream(QueueType::Transfer); - + core.recordCommandsToStream( - stream, - [&info, &mapped_size](const vk::CommandBuffer& commandBuffer) { - const vk::BufferCopy region ( - 0, - info.offset + info.stagingPosition, - mapped_size - ); - - commandBuffer.copyBuffer(info.stagingBuffer, info.buffer, 1, ®ion); - }, - [&core, &info, &mapped_size, &remaining]() { - if (mapped_size < remaining) { - info.stagingPosition += mapped_size; - - fillFromStagingBuffer( - core, - info - ); - } + stream, + [&info, &mapped_size](const vk::CommandBuffer &commandBuffer) { + const vk::BufferCopy region(0, info.offset + info.stagingPosition, mapped_size); + + commandBuffer.copyBuffer(info.stagingBuffer, info.buffer, 1, ®ion); + }, + [&core, &info, &mapped_size, &remaining]() { + if (mapped_size < remaining) { + info.stagingPosition += mapped_size; + + fillFromStagingBuffer(core, info); } - ); - + }); + core.submitCommandStream(stream, false); } - + /** * @brief Structure to store details required for a read staging process. */ @@ -223,15 +192,15 @@ namespace vkcv { void* data; size_t size; size_t offset; - + vk::Buffer buffer; vk::Buffer stagingBuffer; vma::Allocation stagingAllocation; - + size_t stagingLimit; size_t stagingPosition; }; - + /** * Copies data from a staging buffer to CPU and submits the commands to copy * each part one after another into the actual target data pointer. @@ -242,211 +211,190 @@ namespace vkcv { * @param core Core instance * @param info Staging-info structure */ - static void readToStagingBuffer(Core& core, StagingReadInfo& info) { + static void readToStagingBuffer(Core &core, StagingReadInfo &info) { const size_t remaining = info.size - info.stagingPosition; const size_t mapped_size = std::min(remaining, info.stagingLimit); - + auto stream = core.createCommandStream(QueueType::Transfer); - + core.recordCommandsToStream( - stream, - [&info, &mapped_size](const vk::CommandBuffer& commandBuffer) { - const vk::BufferCopy region ( - info.offset + info.stagingPosition, - 0, - mapped_size - ); - - commandBuffer.copyBuffer(info.buffer, info.stagingBuffer, 1, ®ion); - }, - [&core, &info, &mapped_size, &remaining]() { - const vma::Allocator& allocator = core.getContext().getAllocator(); - - const void* mapped = allocator.mapMemory(info.stagingAllocation); - memcpy(reinterpret_cast<char*>(info.data) + info.stagingPosition, mapped, mapped_size); - allocator.unmapMemory(info.stagingAllocation); - - if (mapped_size < remaining) { - info.stagingPosition += mapped_size; - - readToStagingBuffer( - core, - info - ); - } + stream, + [&info, &mapped_size](const vk::CommandBuffer &commandBuffer) { + const vk::BufferCopy region(info.offset + info.stagingPosition, 0, mapped_size); + + commandBuffer.copyBuffer(info.buffer, info.stagingBuffer, 1, ®ion); + }, + [&core, &info, &mapped_size, &remaining]() { + const vma::Allocator &allocator = core.getContext().getAllocator(); + + const void* mapped = allocator.mapMemory(info.stagingAllocation); + memcpy(reinterpret_cast<char*>(info.data) + info.stagingPosition, mapped, + mapped_size); + allocator.unmapMemory(info.stagingAllocation); + + if (mapped_size < remaining) { + info.stagingPosition += mapped_size; + + readToStagingBuffer(core, info); } - ); - + }); + core.submitCommandStream(stream, false); } - - vk::Buffer BufferManager::getBuffer(const BufferHandle& handle) const { - auto& buffer = (*this)[handle]; - + + vk::Buffer BufferManager::getBuffer(const BufferHandle &handle) const { + auto &buffer = (*this) [handle]; + return buffer.m_handle; } - + TypeGuard BufferManager::getTypeGuard(const BufferHandle &handle) const { - auto& buffer = (*this)[handle]; - + auto &buffer = (*this) [handle]; + return buffer.m_typeGuard; } - + BufferType BufferManager::getBufferType(const BufferHandle &handle) const { - auto& buffer = (*this)[handle]; - + auto &buffer = (*this) [handle]; + return buffer.m_type; } - + BufferMemoryType BufferManager::getBufferMemoryType(const BufferHandle &handle) const { - auto& buffer = (*this)[handle]; - + auto &buffer = (*this) [handle]; + return buffer.m_memoryType; } - + size_t BufferManager::getBufferSize(const BufferHandle &handle) const { - auto& buffer = (*this)[handle]; - + auto &buffer = (*this) [handle]; + return buffer.m_size; } - - vk::DeviceMemory BufferManager::getDeviceMemory(const BufferHandle& handle) const { - auto& buffer = (*this)[handle]; - - const vma::Allocator& allocator = getCore().getContext().getAllocator(); - - auto info = allocator.getAllocationInfo( - buffer.m_allocation - ); - + + vk::DeviceMemory BufferManager::getDeviceMemory(const BufferHandle &handle) const { + auto &buffer = (*this) [handle]; + + const vma::Allocator &allocator = getCore().getContext().getAllocator(); + + auto info = allocator.getAllocationInfo(buffer.m_allocation); + return info.deviceMemory; } - - void BufferManager::fillBuffer(const BufferHandle& handle, - const void *data, - size_t size, + + void BufferManager::fillBuffer(const BufferHandle &handle, const void* data, size_t size, size_t offset) { - auto& buffer = (*this)[handle]; - + auto &buffer = (*this) [handle]; + if (size == 0) { size = SIZE_MAX; } - - const vma::Allocator& allocator = getCore().getContext().getAllocator(); - + + const vma::Allocator &allocator = getCore().getContext().getAllocator(); + if (offset > buffer.m_size) { return; } - + const size_t max_size = std::min(size, buffer.m_size - offset); - + if (buffer.m_mappable) { void* mapped = allocator.mapMemory(buffer.m_allocation); memcpy(reinterpret_cast<char*>(mapped) + offset, data, max_size); allocator.unmapMemory(buffer.m_allocation); } else { - auto& stagingBuffer = (*this)[ m_stagingBuffer ]; - + auto &stagingBuffer = (*this) [m_stagingBuffer]; + StagingWriteInfo info; info.data = data; info.size = max_size; info.offset = offset; - + info.buffer = buffer.m_handle; info.stagingBuffer = stagingBuffer.m_handle; info.stagingAllocation = stagingBuffer.m_allocation; - + info.stagingLimit = stagingBuffer.m_size; info.stagingPosition = 0; - + fillFromStagingBuffer(getCore(), info); } } - - void BufferManager::readBuffer(const BufferHandle &handle, - void *data, - size_t size, + + void BufferManager::readBuffer(const BufferHandle &handle, void* data, size_t size, size_t offset) { - auto& buffer = (*this)[handle]; - + auto &buffer = (*this) [handle]; + if (size == 0) { size = SIZE_MAX; } - - const vma::Allocator& allocator = getCore().getContext().getAllocator(); - + + const vma::Allocator &allocator = getCore().getContext().getAllocator(); + if (offset > buffer.m_size) { return; } - + const size_t max_size = std::min(size, buffer.m_size - offset); - + if (buffer.m_mappable) { const void* mapped = allocator.mapMemory(buffer.m_allocation); memcpy(data, reinterpret_cast<const char*>(mapped) + offset, max_size); allocator.unmapMemory(buffer.m_allocation); } else { - auto& stagingBuffer = (*this)[ m_stagingBuffer ]; - + auto &stagingBuffer = (*this) [m_stagingBuffer]; + StagingReadInfo info; info.data = data; info.size = max_size; info.offset = offset; - + info.buffer = buffer.m_handle; info.stagingBuffer = stagingBuffer.m_handle; info.stagingAllocation = stagingBuffer.m_allocation; - + info.stagingLimit = stagingBuffer.m_size; info.stagingPosition = 0; - + readToStagingBuffer(getCore(), info); } } - - void* BufferManager::mapBuffer(const BufferHandle& handle, size_t offset, size_t size) { - auto& buffer = (*this)[handle]; - + + void* BufferManager::mapBuffer(const BufferHandle &handle, size_t offset, size_t size) { + auto &buffer = (*this) [handle]; + if (size == 0) { size = SIZE_MAX; } - - const vma::Allocator& allocator = getCore().getContext().getAllocator(); - + + const vma::Allocator &allocator = getCore().getContext().getAllocator(); + if (offset > buffer.m_size) { return nullptr; } - + return reinterpret_cast<char*>(allocator.mapMemory(buffer.m_allocation)) + offset; } - - void BufferManager::unmapBuffer(const BufferHandle& handle) { - auto& buffer = (*this)[handle]; - - const vma::Allocator& allocator = getCore().getContext().getAllocator(); - + + void BufferManager::unmapBuffer(const BufferHandle &handle) { + auto &buffer = (*this) [handle]; + + const vma::Allocator &allocator = getCore().getContext().getAllocator(); + allocator.unmapMemory(buffer.m_allocation); } - void BufferManager ::recordBufferMemoryBarrier(const BufferHandle& handle, vk::CommandBuffer cmdBuffer) { - auto& buffer = (*this)[handle]; - - vk::BufferMemoryBarrier memoryBarrier( - vk::AccessFlagBits::eMemoryWrite, - vk::AccessFlagBits::eMemoryRead, - 0, - 0, - buffer.m_handle, - 0, - buffer.m_size); - - cmdBuffer.pipelineBarrier( - vk::PipelineStageFlagBits::eAllCommands, - vk::PipelineStageFlagBits::eAllCommands, - {}, - nullptr, - memoryBarrier, - nullptr); + void BufferManager ::recordBufferMemoryBarrier(const BufferHandle &handle, + vk::CommandBuffer cmdBuffer) { + auto &buffer = (*this) [handle]; + + vk::BufferMemoryBarrier memoryBarrier(vk::AccessFlagBits::eMemoryWrite, + vk::AccessFlagBits::eMemoryRead, 0, 0, + buffer.m_handle, 0, buffer.m_size); + + cmdBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands, + vk::PipelineStageFlagBits::eAllCommands, {}, nullptr, + memoryBarrier, nullptr); } -} +} // namespace vkcv diff --git a/src/vkcv/BufferManager.hpp b/src/vkcv/BufferManager.hpp index e86438126fd6775c241fbcfb7a0e493d0885c775..6220bb8ecba51fd1e1ae7b982b189cf0227bb6dc 100644 --- a/src/vkcv/BufferManager.hpp +++ b/src/vkcv/BufferManager.hpp @@ -6,8 +6,8 @@ */ #include <vector> -#include <vulkan/vulkan.hpp> #include <vk_mem_alloc.hpp> +#include <vulkan/vulkan.hpp> #include "vkcv/BufferTypes.hpp" #include "vkcv/TypeGuard.hpp" @@ -15,37 +15,37 @@ #include "HandleManager.hpp" namespace vkcv { - + struct BufferEntry { TypeGuard m_typeGuard; - + BufferType m_type; BufferMemoryType m_memoryType; size_t m_size; - + vk::Buffer m_handle; vma::Allocation m_allocation; - + bool m_mappable; }; - + /** * @brief Class to manage the creation, destruction, allocation * and filling of buffers. */ class BufferManager : public HandleManager<BufferEntry, BufferHandle> { friend class Core; + private: BufferHandle m_stagingBuffer; - - bool init(Core& core) override; - - [[nodiscard]] - uint64_t getIdFrom(const BufferHandle& handle) const override; - - [[nodiscard]] - BufferHandle createById(uint64_t id, const HandleDestroyFunction& destroy) override; - + + bool init(Core &core) override; + + [[nodiscard]] uint64_t getIdFrom(const BufferHandle &handle) const override; + + [[nodiscard]] BufferHandle createById(uint64_t id, + const HandleDestroyFunction &destroy) override; + /** * Destroys and deallocates buffer represented by a given * buffer handle id. @@ -53,12 +53,12 @@ namespace vkcv { * @param id Buffer handle id */ void destroyById(uint64_t id) override; - + public: BufferManager() noexcept; - + ~BufferManager() noexcept override; - + /** * @brief Creates and allocates a new buffer and returns its * unique buffer handle. @@ -71,13 +71,10 @@ namespace vkcv { * @param[in] readable Support read functionality * @return New buffer handle */ - [[nodiscard]] - BufferHandle createBuffer(const TypeGuard &typeGuard, - BufferType type, - BufferMemoryType memoryType, - size_t size, - bool readable); - + [[nodiscard]] BufferHandle createBuffer(const TypeGuard &typeGuard, BufferType type, + BufferMemoryType memoryType, size_t size, + bool readable); + /** * @brief Returns the Vulkan buffer handle of a buffer * represented by a given buffer handle. @@ -85,9 +82,8 @@ namespace vkcv { * @param[in] handle Buffer handle * @return Vulkan buffer handle */ - [[nodiscard]] - vk::Buffer getBuffer(const BufferHandle& handle) const; - + [[nodiscard]] vk::Buffer getBuffer(const BufferHandle &handle) const; + /** * @brief Returns the type guard of a buffer represented * by a given buffer handle. @@ -95,9 +91,8 @@ namespace vkcv { * @param[in] handle Buffer handle * @return Type guard */ - [[nodiscard]] - TypeGuard getTypeGuard(const BufferHandle& handle) const; - + [[nodiscard]] TypeGuard getTypeGuard(const BufferHandle &handle) const; + /** * @brief Returns the buffer type of a buffer represented * by a given buffer handle. @@ -105,9 +100,8 @@ namespace vkcv { * @param[in] handle Buffer handle * @return Buffer type */ - [[nodiscard]] - BufferType getBufferType(const BufferHandle& handle) const; - + [[nodiscard]] BufferType getBufferType(const BufferHandle &handle) const; + /** * @brief Returns the buffer memory type of a buffer * represented by a given buffer handle. @@ -115,9 +109,8 @@ namespace vkcv { * @param[in] handle Buffer handle * @return Buffer memory type */ - [[nodiscard]] - BufferMemoryType getBufferMemoryType(const BufferHandle& handle) const; - + [[nodiscard]] BufferMemoryType getBufferMemoryType(const BufferHandle &handle) const; + /** * @brief Returns the size of a buffer represented * by a given buffer handle. @@ -125,9 +118,8 @@ namespace vkcv { * @param[in] handle Buffer handle * @return Size of the buffer */ - [[nodiscard]] - size_t getBufferSize(const BufferHandle& handle) const; - + [[nodiscard]] size_t getBufferSize(const BufferHandle &handle) const; + /** * @brief Returns the Vulkan device memory handle of a buffer * represented by a given buffer handle id. @@ -135,9 +127,8 @@ namespace vkcv { * @param[in] handle Buffer handle * @return Vulkan device memory handle */ - [[nodiscard]] - vk::DeviceMemory getDeviceMemory(const BufferHandle& handle) const; - + [[nodiscard]] vk::DeviceMemory getDeviceMemory(const BufferHandle &handle) const; + /** * @brief Fills a buffer represented by a given buffer * handle with custom data. @@ -147,11 +138,8 @@ namespace vkcv { * @param[in] size Size of data in bytes * @param[in] offset Offset to fill in data in bytes */ - void fillBuffer(const BufferHandle& handle, - const void* data, - size_t size, - size_t offset); - + void fillBuffer(const BufferHandle &handle, const void* data, size_t size, size_t offset); + /** * @brief Reads from a buffer represented by a given * buffer handle to some data pointer. @@ -161,11 +149,8 @@ namespace vkcv { * @param[in] size Size of data to read in bytes * @param[in] offset Offset to read from buffer in bytes */ - void readBuffer(const BufferHandle& handle, - void* data, - size_t size, - size_t offset); - + void readBuffer(const BufferHandle &handle, void* data, size_t size, size_t offset); + /** * @brief Maps memory to a buffer represented by a given * buffer handle and returns it. @@ -175,27 +160,24 @@ namespace vkcv { * @param[in] size Size of mapping in bytes * @return Pointer to mapped memory */ - void* mapBuffer(const BufferHandle& handle, - size_t offset, - size_t size); - + void* mapBuffer(const BufferHandle &handle, size_t offset, size_t size); + /** * @brief Unmaps memory from a buffer represented by a given * buffer handle. * * @param[in] handle Buffer handle */ - void unmapBuffer(const BufferHandle& handle); - + void unmapBuffer(const BufferHandle &handle); + /** * @brief Records a memory barrier for a buffer, * synchronizing subsequent accesses to buffer data * * @param[in] handle BufferHandle of the buffer * @param[in] cmdBuffer Vulkan command buffer to record the barrier into - */ - void recordBufferMemoryBarrier(const BufferHandle& handle, - vk::CommandBuffer cmdBuffer); + */ + void recordBufferMemoryBarrier(const BufferHandle &handle, vk::CommandBuffer cmdBuffer); }; - -} + +} // namespace vkcv diff --git a/src/vkcv/CommandStreamManager.cpp b/src/vkcv/CommandStreamManager.cpp index 5086d0248f87f91778aa7fcbb6f6a22326666227..a776042ffa1d0d5429b93dc02ae1d72a0a2e23ac 100644 --- a/src/vkcv/CommandStreamManager.cpp +++ b/src/vkcv/CommandStreamManager.cpp @@ -4,25 +4,26 @@ #include "vkcv/Logger.hpp" namespace vkcv { - + uint64_t CommandStreamManager::getIdFrom(const CommandStreamHandle &handle) const { return handle.getId(); } - - CommandStreamHandle CommandStreamManager::createById(uint64_t id, const HandleDestroyFunction &destroy) { + + CommandStreamHandle CommandStreamManager::createById(uint64_t id, + const HandleDestroyFunction &destroy) { return CommandStreamHandle(id, destroy); } - + void CommandStreamManager::destroyById(uint64_t id) { - auto& stream = getById(id); - + auto &stream = getById(id); + if (stream.cmdBuffer) { getCore().getContext().getDevice().freeCommandBuffers(stream.cmdPool, stream.cmdBuffer); stream.cmdBuffer = nullptr; stream.callbacks.clear(); } } - + CommandStreamManager::CommandStreamManager() noexcept : HandleManager<CommandStreamEntry, CommandStreamHandle>() {} @@ -32,76 +33,73 @@ namespace vkcv { CommandStreamHandle CommandStreamManager::createCommandStream(const vk::Queue &queue, vk::CommandPool cmdPool) { - const vk::CommandBufferAllocateInfo info (cmdPool, vk::CommandBufferLevel::ePrimary, 1); - auto& device = getCore().getContext().getDevice(); - + const vk::CommandBufferAllocateInfo info(cmdPool, vk::CommandBufferLevel::ePrimary, 1); + auto &device = getCore().getContext().getDevice(); + const vk::CommandBuffer cmdBuffer = device.allocateCommandBuffers(info).front(); - - const vk::CommandBufferBeginInfo beginInfo (vk::CommandBufferUsageFlagBits::eOneTimeSubmit); + + const vk::CommandBufferBeginInfo beginInfo(vk::CommandBufferUsageFlagBits::eOneTimeSubmit); cmdBuffer.begin(beginInfo); - + for (uint64_t id = 0; id < getCount(); id++) { - auto& stream = getById(id); - + auto &stream = getById(id); + if (!(stream.cmdBuffer)) { stream.cmdBuffer = cmdBuffer; stream.cmdPool = cmdPool; stream.queue = queue; - - return createById(id, [&](uint64_t id) { destroyById(id); }); + + return createById(id, [&](uint64_t id) { + destroyById(id); + }); } } - - return add({ cmdBuffer, cmdPool, queue, {} }); - } + + return add({ cmdBuffer, cmdPool, queue, {} }); + } void CommandStreamManager::recordCommandsToStream(const CommandStreamHandle &handle, const RecordCommandFunction &record) { - auto& stream = (*this)[handle]; + auto &stream = (*this) [handle]; record(stream.cmdBuffer); } void CommandStreamManager::addFinishCallbackToStream(const CommandStreamHandle &handle, const FinishCommandFunction &finish) { - auto& stream = (*this)[handle]; + auto &stream = (*this) [handle]; stream.callbacks.push_back(finish); } - void CommandStreamManager::submitCommandStreamSynchronous(const CommandStreamHandle &handle, - std::vector<vk::Semaphore> &waitSemaphores, - std::vector<vk::Semaphore> &signalSemaphores) { - auto& stream = (*this)[handle]; + void CommandStreamManager::submitCommandStreamSynchronous( + const CommandStreamHandle &handle, std::vector<vk::Semaphore> &waitSemaphores, + std::vector<vk::Semaphore> &signalSemaphores) { + auto &stream = (*this) [handle]; stream.cmdBuffer.end(); const auto device = getCore().getContext().getDevice(); const vk::Fence waitFence = device.createFence({}); - - const std::vector<vk::PipelineStageFlags> waitDstStageMasks ( - waitSemaphores.size(), - vk::PipelineStageFlagBits::eAllCommands - ); - - const vk::SubmitInfo queueSubmitInfo( - waitSemaphores, - waitDstStageMasks, - stream.cmdBuffer, - signalSemaphores - ); - + + const std::vector<vk::PipelineStageFlags> waitDstStageMasks( + waitSemaphores.size(), vk::PipelineStageFlagBits::eAllCommands); + + const vk::SubmitInfo queueSubmitInfo(waitSemaphores, waitDstStageMasks, stream.cmdBuffer, + signalSemaphores); + stream.queue.submit(queueSubmitInfo, waitFence); assert(device.waitForFences(waitFence, true, UINT64_MAX) == vk::Result::eSuccess); - + device.destroyFence(waitFence); stream.queue = nullptr; - for (const auto& finishCallback : stream.callbacks) { + for (const auto &finishCallback : stream.callbacks) { finishCallback(); } } - vk::CommandBuffer CommandStreamManager::getStreamCommandBuffer(const CommandStreamHandle &handle) { - auto& stream = (*this)[handle]; + vk::CommandBuffer + CommandStreamManager::getStreamCommandBuffer(const CommandStreamHandle &handle) { + auto &stream = (*this) [handle]; return stream.cmdBuffer; } - -} \ No newline at end of file + +} // namespace vkcv \ No newline at end of file diff --git a/src/vkcv/CommandStreamManager.hpp b/src/vkcv/CommandStreamManager.hpp index 7913ca223ff78fdc3afb1f41f83d1b31728864df..898f170c08494b941f58632443261afee6134f75 100644 --- a/src/vkcv/CommandStreamManager.hpp +++ b/src/vkcv/CommandStreamManager.hpp @@ -1,7 +1,7 @@ #pragma once -#include <vulkan/vulkan.hpp> #include <vector> +#include <vulkan/vulkan.hpp> #include "vkcv/Event.hpp" #include "vkcv/EventFunctionTypes.hpp" @@ -9,85 +9,87 @@ #include "HandleManager.hpp" namespace vkcv { - + /** * @brief Represents one command stream, into which commands can be recorded into. - * Consists of a command buffer, the command buffer's command pool and a queue, as well as some callbacks. + * Consists of a command buffer, the command buffer's command pool and a queue, as well as some + * callbacks. */ struct CommandStreamEntry { - vk::CommandBuffer cmdBuffer; - vk::CommandPool cmdPool; - vk::Queue queue; - std::vector<FinishCommandFunction> callbacks; + vk::CommandBuffer cmdBuffer; + vk::CommandPool cmdPool; + vk::Queue queue; + std::vector<FinishCommandFunction> callbacks; }; /** * @brief Responsible for creation, deletion, callbacks and recording of command streams - */ + */ class CommandStreamManager : public HandleManager<CommandStreamEntry, CommandStreamHandle> { friend class Core; + private: - [[nodiscard]] - uint64_t getIdFrom(const CommandStreamHandle& handle) const override; - - [[nodiscard]] - CommandStreamHandle createById(uint64_t id, const HandleDestroyFunction& destroy) override; - + [[nodiscard]] uint64_t getIdFrom(const CommandStreamHandle &handle) const override; + + [[nodiscard]] CommandStreamHandle createById(uint64_t id, + const HandleDestroyFunction &destroy) override; + void destroyById(uint64_t id) override; public: CommandStreamManager() noexcept; - + ~CommandStreamManager() noexcept override; /** * @brief Creates a new command stream - * + * * @param queue Queue the command buffer will be submitted to * @param cmdPool Command pool the command buffer will be allocated from * @return Handle that represents the #CommandStream - */ - CommandStreamHandle createCommandStream(const vk::Queue &queue, - vk::CommandPool cmdPool); + */ + CommandStreamHandle createCommandStream(const vk::Queue &queue, vk::CommandPool cmdPool); /** * @brief Record vulkan commands to a #CommandStream, using a record function - * + * * @param handle Command stream handle * @param record Function that records the vulkan commands - */ + */ void recordCommandsToStream(const CommandStreamHandle &handle, const RecordCommandFunction &record); /** - * @brief Add a callback to a #CommandStream that is called + * @brief Add a callback to a #CommandStream that is called * every time the command stream is submitted and finished - * + * * @param handle Command stream handle * @param finish Callback that is called when a command stream submission is finished - */ + */ void addFinishCallbackToStream(const CommandStreamHandle &handle, const FinishCommandFunction &finish); /** * @brief Submits a #CommandStream to it's queue and returns after execution is finished - * + * * @param handle Command stream handle - * @param waitSemaphores Semaphores that are waited upon before executing the recorded commands - * @param signalSemaphores Semaphores that are signaled when execution of the recorded commands is finished - */ - void submitCommandStreamSynchronous(const CommandStreamHandle &handle, - std::vector<vk::Semaphore> &waitSemaphores, - std::vector<vk::Semaphore> &signalSemaphores); + * @param waitSemaphores Semaphores that are waited upon before executing the recorded + * commands + * @param signalSemaphores Semaphores that are signaled when execution of the recorded + * commands is finished + */ + void submitCommandStreamSynchronous(const CommandStreamHandle &handle, + std::vector<vk::Semaphore> &waitSemaphores, + std::vector<vk::Semaphore> &signalSemaphores); /** - * @brief Returns the underlying vulkan handle of a #CommandStream to be used for manual command recording - * + * @brief Returns the underlying vulkan handle of a #CommandStream to be used for manual + * command recording + * * @param handle Command stream handle * @return Vulkan handle of the #CommandStream - */ + */ vk::CommandBuffer getStreamCommandBuffer(const CommandStreamHandle &handle); - }; -} \ No newline at end of file +} // namespace vkcv \ No newline at end of file diff --git a/src/vkcv/ComputePipelineManager.cpp b/src/vkcv/ComputePipelineManager.cpp index 68836cdba92e4a28d6edfe4ee4e142043cde2c44..453dddd1baf93337280fe381b7f77e88bd2e3517 100644 --- a/src/vkcv/ComputePipelineManager.cpp +++ b/src/vkcv/ComputePipelineManager.cpp @@ -3,32 +3,33 @@ #include "vkcv/Core.hpp" namespace vkcv { - + uint64_t ComputePipelineManager::getIdFrom(const ComputePipelineHandle &handle) const { return handle.getId(); } - - ComputePipelineHandle ComputePipelineManager::createById(uint64_t id, const HandleDestroyFunction &destroy) { + + ComputePipelineHandle ComputePipelineManager::createById(uint64_t id, + const HandleDestroyFunction &destroy) { return ComputePipelineHandle(id, destroy); } - + void ComputePipelineManager::destroyById(uint64_t id) { - auto& pipeline = getById(id); - + auto &pipeline = getById(id); + if (pipeline.m_handle) { getCore().getContext().getDevice().destroy(pipeline.m_handle); pipeline.m_handle = nullptr; } - + if (pipeline.m_layout) { getCore().getContext().getDevice().destroy(pipeline.m_layout); pipeline.m_layout = nullptr; } } - + ComputePipelineManager::ComputePipelineManager() noexcept : HandleManager<ComputePipelineEntry, ComputePipelineHandle>() {} - + vk::Result ComputePipelineManager::createShaderModule(vk::ShaderModule &module, const ShaderProgram &shaderProgram, const ShaderStage stage) { @@ -37,68 +38,65 @@ namespace vkcv { return getCore().getContext().getDevice().createShaderModule(&moduleInfo, nullptr, &module); } - ComputePipelineManager::~ComputePipelineManager() noexcept { - clear(); - } - - vk::Pipeline ComputePipelineManager::getVkPipeline(const ComputePipelineHandle &handle) const { - auto& pipeline = (*this)[handle]; - return pipeline.m_handle; - } - - vk::PipelineLayout ComputePipelineManager::getVkPipelineLayout(const ComputePipelineHandle &handle) const { - auto& pipeline = (*this)[handle]; - return pipeline.m_layout; - } - - ComputePipelineHandle ComputePipelineManager::createComputePipeline(const ShaderProgram& shaderProgram, - const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts) { - // Temporally handing over the Shader Program instead of a pipeline config - vk::ShaderModule computeModule{}; - if (createShaderModule(computeModule, shaderProgram, ShaderStage::COMPUTE) != vk::Result::eSuccess) - return {}; - - vk::PipelineShaderStageCreateInfo pipelineComputeShaderStageInfo( - {}, - vk::ShaderStageFlagBits::eCompute, - computeModule, - "main", - nullptr - ); - - vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo({}, descriptorSetLayouts); - - const size_t pushConstantsSize = shaderProgram.getPushConstantsSize(); - vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eCompute, 0, pushConstantsSize); - if (pushConstantsSize > 0) { - pipelineLayoutCreateInfo.setPushConstantRangeCount(1); - pipelineLayoutCreateInfo.setPPushConstantRanges(&pushConstantRange); - } - - vk::PipelineLayout vkPipelineLayout{}; - if (getCore().getContext().getDevice().createPipelineLayout(&pipelineLayoutCreateInfo, - nullptr, - &vkPipelineLayout) != vk::Result::eSuccess) { + ComputePipelineManager::~ComputePipelineManager() noexcept { + clear(); + } + + vk::Pipeline ComputePipelineManager::getVkPipeline(const ComputePipelineHandle &handle) const { + auto &pipeline = (*this) [handle]; + return pipeline.m_handle; + } + + vk::PipelineLayout + ComputePipelineManager::getVkPipelineLayout(const ComputePipelineHandle &handle) const { + auto &pipeline = (*this) [handle]; + return pipeline.m_layout; + } + + ComputePipelineHandle ComputePipelineManager::createComputePipeline( + const ShaderProgram &shaderProgram, + const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts) { + // Temporally handing over the Shader Program instead of a pipeline config + vk::ShaderModule computeModule {}; + if (createShaderModule(computeModule, shaderProgram, ShaderStage::COMPUTE) + != vk::Result::eSuccess) + return {}; + + vk::PipelineShaderStageCreateInfo pipelineComputeShaderStageInfo( + {}, vk::ShaderStageFlagBits::eCompute, computeModule, "main", nullptr); + + vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo({}, descriptorSetLayouts); + + const size_t pushConstantsSize = shaderProgram.getPushConstantsSize(); + vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eCompute, 0, + pushConstantsSize); + if (pushConstantsSize > 0) { + pipelineLayoutCreateInfo.setPushConstantRangeCount(1); + pipelineLayoutCreateInfo.setPPushConstantRanges(&pushConstantRange); + } + + vk::PipelineLayout vkPipelineLayout {}; + if (getCore().getContext().getDevice().createPipelineLayout(&pipelineLayoutCreateInfo, + nullptr, &vkPipelineLayout) + != vk::Result::eSuccess) { getCore().getContext().getDevice().destroy(computeModule); - return {}; - } - - vk::ComputePipelineCreateInfo computePipelineCreateInfo{}; - computePipelineCreateInfo.stage = pipelineComputeShaderStageInfo; - computePipelineCreateInfo.layout = vkPipelineLayout; - - vk::Pipeline vkPipeline; - if (getCore().getContext().getDevice().createComputePipelines(nullptr, - 1, - &computePipelineCreateInfo, - nullptr, - &vkPipeline) != vk::Result::eSuccess) { + return {}; + } + + vk::ComputePipelineCreateInfo computePipelineCreateInfo {}; + computePipelineCreateInfo.stage = pipelineComputeShaderStageInfo; + computePipelineCreateInfo.layout = vkPipelineLayout; + + vk::Pipeline vkPipeline; + if (getCore().getContext().getDevice().createComputePipelines( + nullptr, 1, &computePipelineCreateInfo, nullptr, &vkPipeline) + != vk::Result::eSuccess) { getCore().getContext().getDevice().destroy(computeModule); - return ComputePipelineHandle(); - } - + return ComputePipelineHandle(); + } + getCore().getContext().getDevice().destroy(computeModule); - return add({ vkPipeline, vkPipelineLayout }); - } + return add({ vkPipeline, vkPipelineLayout }); + } -} \ No newline at end of file +} // namespace vkcv \ No newline at end of file diff --git a/src/vkcv/ComputePipelineManager.hpp b/src/vkcv/ComputePipelineManager.hpp index 860181c8745756bab37790dadfa37b13d9ac0eab..32fdc57943bff8d6b8194b9167a067de9a61f8b8 100644 --- a/src/vkcv/ComputePipelineManager.hpp +++ b/src/vkcv/ComputePipelineManager.hpp @@ -6,16 +6,16 @@ * @brief Creation and handling of Compute Pipelines */ -#include <vulkan/vulkan.hpp> #include <vector> +#include <vulkan/vulkan.hpp> #include "HandleManager.hpp" -#include "vkcv/ShaderProgram.hpp" #include "vkcv/ComputePipelineConfig.hpp" +#include "vkcv/ShaderProgram.hpp" namespace vkcv { - + struct ComputePipelineEntry { vk::Pipeline m_handle; vk::PipelineLayout m_layout; @@ -24,14 +24,14 @@ namespace vkcv { /** * @brief Class to manage compute pipelines. */ - class ComputePipelineManager : public HandleManager<ComputePipelineEntry, ComputePipelineHandle> { + class ComputePipelineManager : + public HandleManager<ComputePipelineEntry, ComputePipelineHandle> { private: - [[nodiscard]] - uint64_t getIdFrom(const ComputePipelineHandle& handle) const override; - - [[nodiscard]] - ComputePipelineHandle createById(uint64_t id, const HandleDestroyFunction& destroy) override; - + [[nodiscard]] uint64_t getIdFrom(const ComputePipelineHandle &handle) const override; + + [[nodiscard]] ComputePipelineHandle + createById(uint64_t id, const HandleDestroyFunction &destroy) override; + /** * Destroys and deallocates compute pipeline represented by a given * compute pipeline handle id. @@ -39,43 +39,42 @@ namespace vkcv { * @param id Compute pipeline handle id */ void destroyById(uint64_t id) override; - - vk::Result createShaderModule(vk::ShaderModule &module, - const ShaderProgram &shaderProgram, + + vk::Result createShaderModule(vk::ShaderModule &module, const ShaderProgram &shaderProgram, ShaderStage stage); - - public: + + public: ComputePipelineManager() noexcept; - - ~ComputePipelineManager() noexcept override; // dtor - - /** - * Returns a vk::Pipeline object by handle. - * @param handle Directing to the requested pipeline. - * @return vk::Pipeline. - */ - [[nodiscard]] - vk::Pipeline getVkPipeline(const ComputePipelineHandle &handle) const; - - /** - * Returns a vk::PipelineLayout object by handle. - * @param handle Directing to the requested pipeline. - * @return vk::PipelineLayout. - */ - [[nodiscard]] - vk::PipelineLayout getVkPipelineLayout(const ComputePipelineHandle &handle) const; - - /** - * Creates a Compute Pipeline based on the set shader stages in the Config Struct. - * This function is wrapped in /src/vkcv/Core.cpp by Core::createComputePipeline(const ComputePipelineConfig &config). - * On application level it is necessary first to fill a ComputePipelineConfig Struct. - * @param shaderProgram Hands over all needed information for pipeline creation. - * @param descriptorSetLayouts Hands over all needed information for pipeline creation. - * @return A Handler to the created Compute Pipeline Object. - */ - ComputePipelineHandle createComputePipeline(const ShaderProgram& shaderProgram, - const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts); - - }; - -} + + ~ComputePipelineManager() noexcept override; // dtor + + /** + * Returns a vk::Pipeline object by handle. + * @param handle Directing to the requested pipeline. + * @return vk::Pipeline. + */ + [[nodiscard]] vk::Pipeline getVkPipeline(const ComputePipelineHandle &handle) const; + + /** + * Returns a vk::PipelineLayout object by handle. + * @param handle Directing to the requested pipeline. + * @return vk::PipelineLayout. + */ + [[nodiscard]] vk::PipelineLayout + getVkPipelineLayout(const ComputePipelineHandle &handle) const; + + /** + * Creates a Compute Pipeline based on the set shader stages in the Config Struct. + * This function is wrapped in /src/vkcv/Core.cpp by Core::createComputePipeline(const + * ComputePipelineConfig &config). On application level it is necessary first to fill a + * ComputePipelineConfig Struct. + * @param shaderProgram Hands over all needed information for pipeline creation. + * @param descriptorSetLayouts Hands over all needed information for pipeline creation. + * @return A Handler to the created Compute Pipeline Object. + */ + ComputePipelineHandle + createComputePipeline(const ShaderProgram &shaderProgram, + const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts); + }; + +} // namespace vkcv diff --git a/src/vkcv/Context.cpp b/src/vkcv/Context.cpp index d6cc00f964f9f9549ae7d80e61de98932e00e30a..c0458f237151ece361ac066432643d182aaa199e 100644 --- a/src/vkcv/Context.cpp +++ b/src/vkcv/Context.cpp @@ -1,150 +1,135 @@ #include "vkcv/Context.hpp" -#include "vkcv/Window.hpp" #include "vkcv/Core.hpp" +#include "vkcv/Window.hpp" + +namespace vkcv { + Context::Context(Context &&other) noexcept : + m_Instance(other.m_Instance), m_PhysicalDevice(other.m_PhysicalDevice), + m_Device(other.m_Device), m_FeatureManager(std::move(other.m_FeatureManager)), + m_QueueManager(std::move(other.m_QueueManager)), m_Allocator(other.m_Allocator) { + other.m_Instance = nullptr; + other.m_PhysicalDevice = nullptr; + other.m_Device = nullptr; + other.m_Allocator = nullptr; + } + + Context &Context::operator=(Context &&other) noexcept { + m_Instance = other.m_Instance; + m_PhysicalDevice = other.m_PhysicalDevice; + m_Device = other.m_Device; + m_FeatureManager = std::move(other.m_FeatureManager); + m_QueueManager = std::move(other.m_QueueManager); + m_Allocator = other.m_Allocator; + + other.m_Instance = nullptr; + other.m_PhysicalDevice = nullptr; + other.m_Device = nullptr; + other.m_Allocator = nullptr; + + return *this; + } + + Context::Context(vk::Instance instance, vk::PhysicalDevice physicalDevice, vk::Device device, + FeatureManager &&featureManager, QueueManager &&queueManager, + vma::Allocator &&allocator) noexcept : + m_Instance(instance), + m_PhysicalDevice(physicalDevice), m_Device(device), + m_FeatureManager(std::move(featureManager)), m_QueueManager(std::move(queueManager)), + m_Allocator(allocator) {} + + Context::~Context() noexcept { + m_Allocator.destroy(); + m_Device.destroy(); + m_Instance.destroy(); + } + + const vk::Instance &Context::getInstance() const { + return m_Instance; + } + + const vk::PhysicalDevice &Context::getPhysicalDevice() const { + return m_PhysicalDevice; + } + + const vk::Device &Context::getDevice() const { + return m_Device; + } + + const FeatureManager &Context::getFeatureManager() const { + return m_FeatureManager; + } + + const QueueManager &Context::getQueueManager() const { + return m_QueueManager; + } + + const vma::Allocator &Context::getAllocator() const { + return m_Allocator; + } -namespace vkcv -{ - Context::Context(Context &&other) noexcept: - m_Instance(other.m_Instance), - m_PhysicalDevice(other.m_PhysicalDevice), - m_Device(other.m_Device), - m_FeatureManager(std::move(other.m_FeatureManager)), - m_QueueManager(std::move(other.m_QueueManager)), - m_Allocator(other.m_Allocator) - { - other.m_Instance = nullptr; - other.m_PhysicalDevice = nullptr; - other.m_Device = nullptr; - other.m_Allocator = nullptr; - } - - Context & Context::operator=(Context &&other) noexcept - { - m_Instance = other.m_Instance; - m_PhysicalDevice = other.m_PhysicalDevice; - m_Device = other.m_Device; - m_FeatureManager = std::move(other.m_FeatureManager); - m_QueueManager = std::move(other.m_QueueManager); - m_Allocator = other.m_Allocator; - - other.m_Instance = nullptr; - other.m_PhysicalDevice = nullptr; - other.m_Device = nullptr; - other.m_Allocator = nullptr; - - return *this; - } - - Context::Context(vk::Instance instance, - vk::PhysicalDevice physicalDevice, - vk::Device device, - FeatureManager&& featureManager, - QueueManager&& queueManager, - vma::Allocator&& allocator) noexcept : - m_Instance(instance), - m_PhysicalDevice(physicalDevice), - m_Device(device), - m_FeatureManager(std::move(featureManager)), - m_QueueManager(std::move(queueManager)), - m_Allocator(allocator) - {} - - Context::~Context() noexcept - { - m_Allocator.destroy(); - m_Device.destroy(); - m_Instance.destroy(); - } - - const vk::Instance &Context::getInstance() const - { - return m_Instance; - } - - const vk::PhysicalDevice &Context::getPhysicalDevice() const - { - return m_PhysicalDevice; - } - - const vk::Device &Context::getDevice() const - { - return m_Device; - } - - const FeatureManager& Context::getFeatureManager() const { - return m_FeatureManager; - } - - const QueueManager& Context::getQueueManager() const { - return m_QueueManager; - } - - const vma::Allocator& Context::getAllocator() const { - return m_Allocator; - } - /** * @brief All existing physical devices will be evaluated. * @param instance The instance * @param physicalDevice The optimal physical device * @return Returns if a suitable GPU is found as physical device - */ - static bool pickPhysicalDevice(const vk::Instance& instance, vk::PhysicalDevice& physicalDevice) - { - const std::vector<vk::PhysicalDevice>& devices = instance.enumeratePhysicalDevices(); - + */ + static bool pickPhysicalDevice(const vk::Instance &instance, + vk::PhysicalDevice &physicalDevice) { + const std::vector<vk::PhysicalDevice> &devices = instance.enumeratePhysicalDevices(); + if (devices.empty()) { vkcv_log(LogLevel::ERROR, "Failed to find GPUs with Vulkan support"); return false; } - + vk::PhysicalDeviceType type = vk::PhysicalDeviceType::eOther; vk::DeviceSize vramSize = 0; - - for (const auto& device : devices) { - const auto& properties = device.getProperties(); - + + for (const auto &device : devices) { + const auto &properties = device.getProperties(); + if (vk::PhysicalDeviceType::eOther == type) { type = properties.deviceType; physicalDevice = device; continue; } - + if (vk::PhysicalDeviceType::eDiscreteGpu != properties.deviceType) continue; - + if (vk::PhysicalDeviceType::eDiscreteGpu != type) { type = properties.deviceType; physicalDevice = device; continue; } - - vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevice.getMemoryProperties(); + + vk::PhysicalDeviceMemoryProperties memoryProperties = + physicalDevice.getMemoryProperties(); vk::DeviceSize maxSize = 0; - + for (uint32_t i = 0; i < memoryProperties.memoryHeapCount; i++) - if (memoryProperties.memoryHeaps[i].size > maxSize) - maxSize = memoryProperties.memoryHeaps[i].size; - + if (memoryProperties.memoryHeaps [i].size > maxSize) + maxSize = memoryProperties.memoryHeaps [i].size; + if (maxSize > vramSize) { type = properties.deviceType; physicalDevice = device; vramSize = maxSize; } } - + return true; } - + /** * @brief Check whether all string occurrences in "check" are contained in "supported" * @param supported The const vector const char* reference used to compare entries in "check" * @param check The const vector const char* reference elements to be checked by "supported" * @return True, if all elements in "check" are supported (contained in supported) - */ - bool checkSupport(const std::vector<const char*>& supported, const std::vector<const char*>& check) - { + */ + bool checkSupport(const std::vector<const char*> &supported, + const std::vector<const char*> &check) { for (auto checkElem : check) { bool found = false; for (auto supportedElem : supported) { @@ -158,357 +143,331 @@ namespace vkcv } return true; } - + std::vector<std::string> getRequiredExtensions() { std::vector<std::string> extensions = Window::getExtensions(); - + #ifndef NDEBUG extensions.emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); #endif - + return extensions; } - + /** - * Given the @p physicalDevice and the @p queuePriorities, the @p queueCreateInfos are computed. First, the requested - * queues are sorted by priority depending on the availability of queues in the queue families of the given - * @p physicalDevice. Then check, if all requested queues are creatable. If so, the @p queueCreateInfos will be computed. - * Furthermore, lists of index pairs (queueFamilyIndex, queueIndex) for later referencing of the separate queues will - * be computed. + * Given the @p physicalDevice and the @p queuePriorities, the @p queueCreateInfos are computed. + * First, the requested queues are sorted by priority depending on the availability of queues in + * the queue families of the given + * @p physicalDevice. Then check, if all requested queues are creatable. If so, the @p + * queueCreateInfos will be computed. Furthermore, lists of index pairs (queueFamilyIndex, + * queueIndex) for later referencing of the separate queues will be computed. * @param[in] physicalDevice The physical device - * @param[in] queuePriorities The queue priorities used for the computation of @p queueCreateInfos + * @param[in] queuePriorities The queue priorities used for the computation of @p + * queueCreateInfos * @param[in] queueFlags The queue flags requesting the queues * @param[in,out] queueCreateInfos The queue create info structures to be created - * @param[in,out] queuePairsGraphics The list of index pairs (queueFamilyIndex, queueIndex) of queues of type - * vk::QueueFlagBits::eGraphics - * @param[in,out] queuePairsCompute The list of index pairs (queueFamilyIndex, queueIndex) of queues of type - * vk::QueueFlagBits::eCompute - * @param[in,out] queuePairsTransfer The list of index pairs (queueFamilyIndex, queueIndex) of queues of type - * vk::QueueFlagBits::eTransfer - * @throws std::runtime_error If the requested queues from @p queueFlags are not creatable due to insufficient availability. + * @param[in,out] queuePairsGraphics The list of index pairs (queueFamilyIndex, queueIndex) of + * queues of type vk::QueueFlagBits::eGraphics + * @param[in,out] queuePairsCompute The list of index pairs (queueFamilyIndex, queueIndex) of + * queues of type vk::QueueFlagBits::eCompute + * @param[in,out] queuePairsTransfer The list of index pairs (queueFamilyIndex, queueIndex) of + * queues of type vk::QueueFlagBits::eTransfer + * @throws std::runtime_error If the requested queues from @p queueFlags are not creatable due + * to insufficient availability. */ - static void queueCreateInfosQueueHandles(vk::PhysicalDevice &physicalDevice, - const std::vector<float> &queuePriorities, - const std::vector<vk::QueueFlagBits> &queueFlags, - std::vector<vk::DeviceQueueCreateInfo> &queueCreateInfos, - std::vector<std::pair<int, int>> &queuePairsGraphics, - std::vector<std::pair<int, int>> &queuePairsCompute, - std::vector<std::pair<int, int>> &queuePairsTransfer) - { + static void + queueCreateInfosQueueHandles(vk::PhysicalDevice &physicalDevice, + const std::vector<float> &queuePriorities, + const std::vector<vk::QueueFlagBits> &queueFlags, + std::vector<vk::DeviceQueueCreateInfo> &queueCreateInfos, + std::vector<std::pair<int, int>> &queuePairsGraphics, + std::vector<std::pair<int, int>> &queuePairsCompute, + std::vector<std::pair<int, int>> &queuePairsTransfer) { queueCreateInfos = {}; queuePairsGraphics = {}; queuePairsCompute = {}; queuePairsTransfer = {}; - std::vector<vk::QueueFamilyProperties> qFamilyProperties = physicalDevice.getQueueFamilyProperties(); - - //check priorities of flags -> the lower prioCount the higher the priority + std::vector<vk::QueueFamilyProperties> qFamilyProperties = + physicalDevice.getQueueFamilyProperties(); + + // check priorities of flags -> the lower prioCount the higher the priority std::vector<int> prios; - for(auto flag: queueFlags) { + for (auto flag : queueFlags) { int prioCount = 0; for (size_t i = 0; i < qFamilyProperties.size(); i++) { - prioCount += (static_cast<uint32_t>(flag & qFamilyProperties[i].queueFlags) != 0) * qFamilyProperties[i].queueCount; + prioCount += (static_cast<uint32_t>(flag & qFamilyProperties [i].queueFlags) != 0) + * qFamilyProperties [i].queueCount; } prios.push_back(prioCount); } - //resort flags with heighest priority before allocating the queues + // resort flags with heighest priority before allocating the queues std::vector<vk::QueueFlagBits> newFlags; - for(size_t i = 0; i < prios.size(); i++) { + for (size_t i = 0; i < prios.size(); i++) { auto minElem = std::min_element(prios.begin(), prios.end()); int index = minElem - prios.begin(); - newFlags.push_back(queueFlags[index]); - prios[index] = std::numeric_limits<int>::max(); + newFlags.push_back(queueFlags [index]); + prios [index] = std::numeric_limits<int>::max(); } - + // create requested queues and check if more requested queues are supported // herefore: create vector that updates available queues in each queue family // structure: [qFamily_0, ..., qFamily_n] where // - qFamily_i = [GraphicsCount, ComputeCount, TransferCount], 0 <= i <= n std::vector<std::vector<int>> queueFamilyStatus, initialQueueFamilyStatus; - + for (auto qFamily : qFamilyProperties) { - auto graphicsCount = static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eGraphics) != 0? qFamily.queueCount : 0; - auto computeCount = static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eCompute) != 0? qFamily.queueCount : 0; - auto transferCount = static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eTransfer) != 0? qFamily.queueCount : 0; - queueFamilyStatus.push_back({ - static_cast<int>(graphicsCount), - static_cast<int>(computeCount), - static_cast<int>(transferCount) - }); + auto graphicsCount = + static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eGraphics) != 0 ? + qFamily.queueCount : + 0; + auto computeCount = + static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eCompute) != 0 ? + qFamily.queueCount : + 0; + auto transferCount = + static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eTransfer) != 0 ? + qFamily.queueCount : + 0; + queueFamilyStatus.push_back({ static_cast<int>(graphicsCount), + static_cast<int>(computeCount), + static_cast<int>(transferCount) }); } - + initialQueueFamilyStatus = queueFamilyStatus; // check if every queue with the specified queue flag can be created // this automatically checks for queue flag support! for (auto qFlag : newFlags) { bool found; switch (qFlag) { - case vk::QueueFlagBits::eGraphics: - found = false; + case vk::QueueFlagBits::eGraphics: + found = false; + for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { + if (queueFamilyStatus [i][0] > 0) { + queuePairsGraphics.emplace_back(std::pair( + i, initialQueueFamilyStatus [i][0] - queueFamilyStatus [i][0])); + queueFamilyStatus [i][0]--; + queueFamilyStatus [i][1]--; + queueFamilyStatus [i][2]--; + found = true; + } + } + if (!found) { for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { - if (queueFamilyStatus[i][0] > 0) { - queuePairsGraphics.emplace_back(std::pair(i, initialQueueFamilyStatus[i][0] - queueFamilyStatus[i][0])); - queueFamilyStatus[i][0]--; - queueFamilyStatus[i][1]--; - queueFamilyStatus[i][2]--; + if (initialQueueFamilyStatus [i][0] > 0) { + queuePairsGraphics.emplace_back(std::pair(i, 0)); found = true; } } - if (!found) { - for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { - if (initialQueueFamilyStatus[i][0] > 0) { - queuePairsGraphics.emplace_back(std::pair(i, 0)); - found = true; - } - } - - vkcv_log(LogLevel::WARNING, "Not enough %s queues", vk::to_string(qFlag).c_str()); + + vkcv_log(LogLevel::WARNING, "Not enough %s queues", + vk::to_string(qFlag).c_str()); + } + break; + case vk::QueueFlagBits::eCompute: + found = false; + for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { + if (queueFamilyStatus [i][1] > 0) { + queuePairsCompute.emplace_back(std::pair( + i, initialQueueFamilyStatus [i][1] - queueFamilyStatus [i][1])); + queueFamilyStatus [i][0]--; + queueFamilyStatus [i][1]--; + queueFamilyStatus [i][2]--; + found = true; } - break; - case vk::QueueFlagBits::eCompute: - found = false; + } + if (!found) { for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { - if (queueFamilyStatus[i][1] > 0) { - queuePairsCompute.emplace_back(std::pair(i, initialQueueFamilyStatus[i][1] - queueFamilyStatus[i][1])); - queueFamilyStatus[i][0]--; - queueFamilyStatus[i][1]--; - queueFamilyStatus[i][2]--; + if (initialQueueFamilyStatus [i][1] > 0) { + queuePairsCompute.emplace_back(std::pair(i, 0)); found = true; } } - if (!found) { - for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { - if (initialQueueFamilyStatus[i][1] > 0) { - queuePairsCompute.emplace_back(std::pair(i, 0)); - found = true; - } - } - - vkcv_log(LogLevel::WARNING, "Not enough %s queues", vk::to_string(qFlag).c_str()); + + vkcv_log(LogLevel::WARNING, "Not enough %s queues", + vk::to_string(qFlag).c_str()); + } + break; + case vk::QueueFlagBits::eTransfer: + found = false; + for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { + if (queueFamilyStatus [i][2] > 0) { + queuePairsTransfer.emplace_back(std::pair( + i, initialQueueFamilyStatus [i][2] - queueFamilyStatus [i][2])); + queueFamilyStatus [i][0]--; + queueFamilyStatus [i][1]--; + queueFamilyStatus [i][2]--; + found = true; } - break; - case vk::QueueFlagBits::eTransfer: - found = false; + } + if (!found) { for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { - if (queueFamilyStatus[i][2] > 0) { - queuePairsTransfer.emplace_back(std::pair(i, initialQueueFamilyStatus[i][2] - queueFamilyStatus[i][2])); - queueFamilyStatus[i][0]--; - queueFamilyStatus[i][1]--; - queueFamilyStatus[i][2]--; + if (initialQueueFamilyStatus [i][2] > 0) { + queuePairsTransfer.emplace_back(std::pair(i, 0)); found = true; } } - if (!found) { - for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { - if (initialQueueFamilyStatus[i][2] > 0) { - queuePairsTransfer.emplace_back(std::pair(i, 0)); - found = true; - } - } - - vkcv_log(LogLevel::WARNING, "Not enough %s queues", vk::to_string(qFlag).c_str()); - } - break; - default: - vkcv_log(LogLevel::ERROR, "Invalid input for queue flag bits: %s", vk::to_string(qFlag).c_str()); - break; + + vkcv_log(LogLevel::WARNING, "Not enough %s queues", + vk::to_string(qFlag).c_str()); + } + break; + default: + vkcv_log(LogLevel::ERROR, "Invalid input for queue flag bits: %s", + vk::to_string(qFlag).c_str()); + break; } } - + // create all requested queues for (size_t i = 0; i < qFamilyProperties.size(); i++) { - uint32_t create = std::abs(initialQueueFamilyStatus[i][0] - queueFamilyStatus[i][0]); + uint32_t create = std::abs(initialQueueFamilyStatus [i][0] - queueFamilyStatus [i][0]); if (create > 0) { - vk::DeviceQueueCreateInfo qCreateInfo( - vk::DeviceQueueCreateFlags(), - i, - create, - queuePriorities.data() - ); + vk::DeviceQueueCreateInfo qCreateInfo(vk::DeviceQueueCreateFlags(), i, create, + queuePriorities.data()); queueCreateInfos.push_back(qCreateInfo); } } } - Context Context::create(const char *applicationName, - uint32_t applicationVersion, - const std::vector<vk::QueueFlagBits>& queueFlags, - const Features& features, - const std::vector<const char*>& instanceExtensions) { + Context Context::create(const std::string &applicationName, uint32_t applicationVersion, + const std::vector<vk::QueueFlagBits> &queueFlags, + const Features &features, + const std::vector<const char*> &instanceExtensions) { // check for layer support - - const std::vector<vk::LayerProperties>& layerProperties = vk::enumerateInstanceLayerProperties(); - + + const std::vector<vk::LayerProperties> &layerProperties = + vk::enumerateInstanceLayerProperties(); + std::vector<const char*> supportedLayers; supportedLayers.reserve(layerProperties.size()); - - for (auto& elem : layerProperties) { + + for (auto &elem : layerProperties) { supportedLayers.push_back(elem.layerName); } // if in debug mode, check if validation layers are supported. Enable them if supported #ifndef NDEBUG - std::vector<const char*> validationLayers = { - "VK_LAYER_KHRONOS_validation" - }; - + std::vector<const char*> validationLayers = { "VK_LAYER_KHRONOS_validation" }; + if (!checkSupport(supportedLayers, validationLayers)) { vkcv_log_throw_error("Validation layers requested but not available!"); } #endif - + // check for instance extension support - std::vector<vk::ExtensionProperties> instanceExtensionProperties = vk::enumerateInstanceExtensionProperties(); - + std::vector<vk::ExtensionProperties> instanceExtensionProperties = + vk::enumerateInstanceExtensionProperties(); + std::vector<const char*> supportedExtensions; supportedExtensions.reserve(instanceExtensionProperties.size()); - - for (auto& elem : instanceExtensionProperties) { + + for (auto &elem : instanceExtensionProperties) { supportedExtensions.push_back(elem.extensionName); } - + // for GLFW: get all required extensions auto requiredStrings = getRequiredExtensions(); std::vector<const char*> requiredExtensions; - - for (const auto& extension : requiredStrings) { + + for (const auto &extension : requiredStrings) { requiredExtensions.push_back(extension.c_str()); } - - requiredExtensions.insert(requiredExtensions.end(), instanceExtensions.begin(), instanceExtensions.end()); - + + requiredExtensions.insert(requiredExtensions.end(), instanceExtensions.begin(), + instanceExtensions.end()); + if (!checkSupport(supportedExtensions, requiredExtensions)) { vkcv_log_throw_error("The requested instance extensions are not supported!"); } - - const vk::ApplicationInfo applicationInfo( - applicationName, - applicationVersion, - VKCV_FRAMEWORK_NAME, - VKCV_FRAMEWORK_VERSION, - VK_HEADER_VERSION_COMPLETE - ); - + + const vk::ApplicationInfo applicationInfo(applicationName.c_str(), applicationVersion, + VKCV_FRAMEWORK_NAME, VKCV_FRAMEWORK_VERSION, + VK_HEADER_VERSION_COMPLETE); + vk::InstanceCreateInfo instanceCreateInfo( - vk::InstanceCreateFlags(), - &applicationInfo, - 0, - nullptr, - static_cast<uint32_t>(requiredExtensions.size()), - requiredExtensions.data() - ); + vk::InstanceCreateFlags(), &applicationInfo, 0, nullptr, + static_cast<uint32_t>(requiredExtensions.size()), requiredExtensions.data()); #ifndef NDEBUG instanceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size()); instanceCreateInfo.ppEnabledLayerNames = validationLayers.data(); #endif - + vk::Instance instance = vk::createInstance(instanceCreateInfo); std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices(); vk::PhysicalDevice physicalDevice; - + if (!pickPhysicalDevice(instance, physicalDevice)) { vkcv_log_throw_error("Picking suitable GPU as physical device failed!"); } - - FeatureManager featureManager (physicalDevice); - + + FeatureManager featureManager(physicalDevice); + #ifdef __APPLE__ featureManager.useExtension("VK_KHR_portability_subset", true); #endif if (featureManager.useExtension(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, false)) { featureManager.useFeatures<vk::PhysicalDeviceShaderFloat16Int8Features>( - [](vk::PhysicalDeviceShaderFloat16Int8Features& features) { - features.setShaderFloat16(true); - }, false); + [](vk::PhysicalDeviceShaderFloat16Int8Features &features) { + features.setShaderFloat16(true); + }, + false); } - + if (featureManager.useExtension(VK_KHR_16BIT_STORAGE_EXTENSION_NAME, false)) { featureManager.useFeatures<vk::PhysicalDevice16BitStorageFeatures>( - [](vk::PhysicalDevice16BitStorageFeatures& features) { - features.setStorageBuffer16BitAccess(true); - }, false); + [](vk::PhysicalDevice16BitStorageFeatures &features) { + features.setStorageBuffer16BitAccess(true); + }, + false); } - featureManager.useFeatures([](vk::PhysicalDeviceFeatures& features) { + featureManager.useFeatures([](vk::PhysicalDeviceFeatures &features) { features.setFragmentStoresAndAtomics(true); features.setGeometryShader(true); features.setDepthClamp(true); features.setShaderInt16(true); }); - - for (const auto& feature : features.getList()) { + + for (const auto &feature : features.getList()) { feature(featureManager); } - - const auto& extensions = featureManager.getActiveExtensions(); + + const auto &extensions = featureManager.getActiveExtensions(); std::vector<vk::DeviceQueueCreateInfo> qCreateInfos; std::vector<float> qPriorities; qPriorities.resize(queueFlags.size(), 1.f); std::vector<std::pair<int, int>> queuePairsGraphics, queuePairsCompute, queuePairsTransfer; - - queueCreateInfosQueueHandles( - physicalDevice, - qPriorities, - queueFlags, - qCreateInfos, - queuePairsGraphics, - queuePairsCompute, - queuePairsTransfer - ); - + + queueCreateInfosQueueHandles(physicalDevice, qPriorities, queueFlags, qCreateInfos, + queuePairsGraphics, queuePairsCompute, queuePairsTransfer); + vk::DeviceCreateInfo deviceCreateInfo( - vk::DeviceCreateFlags(), - qCreateInfos.size(), - qCreateInfos.data(), - 0, - nullptr, - extensions.size(), - extensions.data(), - nullptr, - &(featureManager.getFeatures()) - ); + vk::DeviceCreateFlags(), qCreateInfos.size(), qCreateInfos.data(), 0, nullptr, + extensions.size(), extensions.data(), nullptr, &(featureManager.getFeatures())); #ifndef NDEBUG deviceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size()); deviceCreateInfo.ppEnabledLayerNames = validationLayers.data(); #endif - + vk::Device device = physicalDevice.createDevice(deviceCreateInfo); - - QueueManager queueManager = QueueManager::create( - device, - queuePairsGraphics, - queuePairsCompute, - queuePairsTransfer - ); + + QueueManager queueManager = + QueueManager::create(device, queuePairsGraphics, queuePairsCompute, queuePairsTransfer); vma::AllocatorCreateFlags vmaFlags; - const vma::AllocatorCreateInfo allocatorCreateInfo ( - vmaFlags, - physicalDevice, - device, - 0, - nullptr, - nullptr, - nullptr, - nullptr, - instance, - VK_HEADER_VERSION_COMPLETE - ); - + const vma::AllocatorCreateInfo allocatorCreateInfo(vmaFlags, physicalDevice, device, 0, + nullptr, nullptr, nullptr, nullptr, + instance, VK_HEADER_VERSION_COMPLETE); + vma::Allocator allocator = vma::createAllocator(allocatorCreateInfo); - - return Context( - instance, - physicalDevice, - device, - std::move(featureManager), - std::move(queueManager), - std::move(allocator) - ); + + return Context(instance, physicalDevice, device, std::move(featureManager), + std::move(queueManager), std::move(allocator)); } - -} + +} // namespace vkcv diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 576ddc4d4126f258b82f008c23635d32ff374922..6ccf1de841996c85905689f0ef45e3dbdcf7c285 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -7,24 +7,23 @@ #include <GLFW/glfw3.h> #include <cmath> -#include "vkcv/Core.hpp" -#include "PassManager.hpp" -#include "GraphicsPipelineManager.hpp" -#include "ComputePipelineManager.hpp" #include "BufferManager.hpp" -#include "SamplerManager.hpp" -#include "ImageManager.hpp" +#include "CommandStreamManager.hpp" +#include "ComputePipelineManager.hpp" #include "DescriptorSetLayoutManager.hpp" #include "DescriptorSetManager.hpp" +#include "GraphicsPipelineManager.hpp" +#include "ImageManager.hpp" +#include "PassManager.hpp" +#include "SamplerManager.hpp" #include "WindowManager.hpp" -#include "CommandStreamManager.hpp" +#include "vkcv/BlitDownsampler.hpp" +#include "vkcv/Core.hpp" #include "vkcv/Image.hpp" #include "vkcv/Logger.hpp" -#include "vkcv/BlitDownsampler.hpp" -namespace vkcv -{ - +namespace vkcv { + /** * @brief Generates a set of the family indices for all different kinds of * queues a given queue manager provides. @@ -34,23 +33,23 @@ namespace vkcv */ static std::unordered_set<int> generateQueueFamilyIndexSet(const QueueManager &queueManager) { std::unordered_set<int> indexSet; - - for (const auto& queue : queueManager.getGraphicsQueues()) { + + for (const auto &queue : queueManager.getGraphicsQueues()) { indexSet.insert(queue.familyIndex); } - - for (const auto& queue : queueManager.getComputeQueues()) { + + for (const auto &queue : queueManager.getComputeQueues()) { indexSet.insert(queue.familyIndex); } - - for (const auto& queue : queueManager.getTransferQueues()) { + + for (const auto &queue : queueManager.getTransferQueues()) { indexSet.insert(queue.familyIndex); } - + indexSet.insert(queueManager.getPresentQueue().familyIndex); return indexSet; } - + /** * @brief Creates and returns a vector of newly allocated command pools * for each different queue family index in a given set. @@ -59,66 +58,53 @@ namespace vkcv * @param[in] familyIndexSet Set of queue family indices * @return New command pools */ - static std::vector<vk::CommandPool> createCommandPools(const vk::Device& device, - const std::unordered_set<int>& familyIndexSet) { + static std::vector<vk::CommandPool> + createCommandPools(const vk::Device &device, const std::unordered_set<int> &familyIndexSet) { std::vector<vk::CommandPool> commandPoolsPerQueueFamily; commandPoolsPerQueueFamily.resize(familyIndexSet.size()); - + const vk::CommandPoolCreateFlags poolFlags = vk::CommandPoolCreateFlagBits::eTransient; for (const int familyIndex : familyIndexSet) { const vk::CommandPoolCreateInfo poolCreateInfo(poolFlags, familyIndex); - commandPoolsPerQueueFamily[familyIndex] = device.createCommandPool(poolCreateInfo, nullptr, {}); + commandPoolsPerQueueFamily [familyIndex] = + device.createCommandPool(poolCreateInfo, nullptr, {}); } - + return commandPoolsPerQueueFamily; } - - Core Core::create(const char *applicationName, - uint32_t applicationVersion, - const std::vector<vk::QueueFlagBits>& queueFlags, - const Features& features, - const std::vector<const char *>& instanceExtensions) - { - Context context = Context::create( - applicationName, applicationVersion, - queueFlags, - features, - instanceExtensions - ); - - return Core(std::move(context)); - } - - const Context &Core::getContext() const { - return m_Context; - } - - Core::Core(Context &&context) noexcept : - m_Context(std::move(context)), - m_PassManager(std::make_unique<PassManager>()), - m_GraphicsPipelineManager(std::make_unique<GraphicsPipelineManager>()), - m_ComputePipelineManager(std::make_unique<ComputePipelineManager>()), - m_DescriptorSetLayoutManager(std::make_unique<DescriptorSetLayoutManager>()), - m_DescriptorSetManager(std::make_unique<DescriptorSetManager>()), - m_BufferManager(std::make_unique<BufferManager>()), - m_SamplerManager(std::make_unique<SamplerManager>()), - m_ImageManager(std::make_unique<ImageManager>()), - m_CommandStreamManager{std::make_unique<CommandStreamManager>()}, - m_WindowManager(std::make_unique<WindowManager>()), - m_SwapchainManager(std::make_unique<SwapchainManager>()), - m_CommandPools(), - m_RenderFinished(), - m_SwapchainImageAcquired(), - m_downsampler(nullptr) - { + + Core Core::create(const std::string &applicationName, uint32_t applicationVersion, + const std::vector<vk::QueueFlagBits> &queueFlags, const Features &features, + const std::vector<const char*> &instanceExtensions) { + Context context = Context::create(applicationName, applicationVersion, queueFlags, features, + instanceExtensions); + + return Core(std::move(context)); + } + + const Context &Core::getContext() const { + return m_Context; + } + + Core::Core(Context &&context) noexcept : + m_Context(std::move(context)), m_PassManager(std::make_unique<PassManager>()), + m_GraphicsPipelineManager(std::make_unique<GraphicsPipelineManager>()), + m_ComputePipelineManager(std::make_unique<ComputePipelineManager>()), + m_DescriptorSetLayoutManager(std::make_unique<DescriptorSetLayoutManager>()), + m_DescriptorSetManager(std::make_unique<DescriptorSetManager>()), + m_BufferManager(std::make_unique<BufferManager>()), + m_SamplerManager(std::make_unique<SamplerManager>()), + m_ImageManager(std::make_unique<ImageManager>()), + m_CommandStreamManager { std::make_unique<CommandStreamManager>() }, + m_WindowManager(std::make_unique<WindowManager>()), + m_SwapchainManager(std::make_unique<SwapchainManager>()), m_CommandPools(), + m_RenderFinished(), m_SwapchainImageAcquired(), m_downsampler(nullptr) { m_CommandPools = createCommandPools( - m_Context.getDevice(), - generateQueueFamilyIndexSet(m_Context.getQueueManager()) - ); - + m_Context.getDevice(), generateQueueFamilyIndexSet(m_Context.getQueueManager())); + m_RenderFinished = m_Context.getDevice().createSemaphore({}); m_SwapchainImageAcquired = m_Context.getDevice().createSemaphore({}); - + m_PassManager->init(*this); m_GraphicsPipelineManager->init(*this); m_ComputePipelineManager->init(*this); @@ -134,188 +120,170 @@ namespace vkcv Core::~Core() noexcept { m_Context.getDevice().waitIdle(); - + for (const vk::CommandPool &pool : m_CommandPools) { m_Context.getDevice().destroyCommandPool(pool); } - + m_Context.getDevice().destroySemaphore(m_RenderFinished); m_Context.getDevice().destroySemaphore(m_SwapchainImageAcquired); } - + GraphicsPipelineHandle Core::createGraphicsPipeline(const GraphicsPipelineConfig &config) { - return m_GraphicsPipelineManager->createPipeline(config, *m_PassManager, *m_DescriptorSetLayoutManager); - } + return m_GraphicsPipelineManager->createPipeline(config, *m_PassManager, + *m_DescriptorSetLayoutManager); + } - ComputePipelineHandle Core::createComputePipeline(const ComputePipelineConfig &config) { + ComputePipelineHandle Core::createComputePipeline(const ComputePipelineConfig &config) { std::vector<vk::DescriptorSetLayout> layouts; layouts.resize(config.getDescriptorSetLayouts().size()); - + for (size_t i = 0; i < layouts.size(); i++) { - layouts[i] = m_DescriptorSetLayoutManager->getDescriptorSetLayout( - config.getDescriptorSetLayouts()[i] - ).vulkanHandle; + layouts [i] = m_DescriptorSetLayoutManager + ->getDescriptorSetLayout(config.getDescriptorSetLayouts() [i]) + .vulkanHandle; } - - return m_ComputePipelineManager->createComputePipeline(config.getShaderProgram(), layouts); - } - - PassHandle Core::createPass(const PassConfig &config) { - return m_PassManager->createPass(config); - } - + + return m_ComputePipelineManager->createComputePipeline(config.getShaderProgram(), layouts); + } + + PassHandle Core::createPass(const PassConfig &config) { + return m_PassManager->createPass(config); + } + const PassConfig &Core::getPassConfiguration(const vkcv::PassHandle &pass) { return m_PassManager->getPassConfig(pass); } - - BufferHandle Core::createBuffer(BufferType type, - const TypeGuard &typeGuard, - size_t count, - BufferMemoryType memoryType, - bool readable) { - return m_BufferManager->createBuffer( - typeGuard, - type, - memoryType, - count * typeGuard.typeSize(), - readable - ); - } - - BufferHandle Core::createBuffer(BufferType type, - size_t size, - BufferMemoryType memoryType, + + BufferHandle Core::createBuffer(BufferType type, const TypeGuard &typeGuard, size_t count, + BufferMemoryType memoryType, bool readable) { + return m_BufferManager->createBuffer(typeGuard, type, memoryType, + count * typeGuard.typeSize(), readable); + } + + BufferHandle Core::createBuffer(BufferType type, size_t size, BufferMemoryType memoryType, bool readable) { - return m_BufferManager->createBuffer( - TypeGuard(1), - type, - memoryType, - size, - readable - ); - } - + return m_BufferManager->createBuffer(TypeGuard(1), type, memoryType, size, readable); + } + vk::Buffer Core::getBuffer(const BufferHandle &buffer) const { return m_BufferManager->getBuffer(buffer); } - + BufferType Core::getBufferType(const BufferHandle &handle) const { return m_BufferManager->getBufferType(handle); } - + BufferMemoryType Core::getBufferMemoryType(const BufferHandle &handle) const { return m_BufferManager->getBufferMemoryType(handle); } - + size_t Core::getBufferSize(const BufferHandle &handle) const { return m_BufferManager->getBufferSize(handle); } - - void Core::fillBuffer(const BufferHandle &handle, const void *data, size_t size, size_t offset) { + + void Core::fillBuffer(const BufferHandle &handle, const void* data, size_t size, + size_t offset) { m_BufferManager->fillBuffer(handle, data, size, offset); } - - void Core::readBuffer(const BufferHandle &handle, void *data, size_t size, size_t offset) { + + void Core::readBuffer(const BufferHandle &handle, void* data, size_t size, size_t offset) { m_BufferManager->readBuffer(handle, data, size, offset); } - + void* Core::mapBuffer(const BufferHandle &handle, size_t offset, size_t size) { return m_BufferManager->mapBuffer(handle, offset, size); } - + void Core::unmapBuffer(const BufferHandle &handle) { m_BufferManager->unmapBuffer(handle); } - + Result Core::acquireSwapchainImage(const SwapchainHandle &swapchainHandle) { - uint32_t imageIndex; - vk::Result result; - + uint32_t imageIndex; + vk::Result result; + try { result = m_Context.getDevice().acquireNextImageKHR( - m_SwapchainManager->getSwapchain(swapchainHandle).m_Swapchain, - std::numeric_limits<uint64_t>::max(), - m_SwapchainImageAcquired, - nullptr, - &imageIndex, {} - ); - } catch (const vk::OutOfDateKHRError& e) { + m_SwapchainManager->getSwapchain(swapchainHandle).m_Swapchain, + std::numeric_limits<uint64_t>::max(), m_SwapchainImageAcquired, nullptr, + &imageIndex, {}); + } catch (const vk::OutOfDateKHRError &e) { result = vk::Result::eErrorOutOfDateKHR; - } catch (const vk::DeviceLostError& e) { + } catch (const vk::DeviceLostError &e) { result = vk::Result::eErrorDeviceLost; } - - if ((result != vk::Result::eSuccess) && - (result != vk::Result::eSuboptimalKHR)) { + + if ((result != vk::Result::eSuccess) && (result != vk::Result::eSuboptimalKHR)) { vkcv_log(LogLevel::ERROR, "%s", vk::to_string(result).c_str()); return Result::ERROR; - } else - if (result == vk::Result::eSuboptimalKHR) { + } else if (result == vk::Result::eSuboptimalKHR) { vkcv_log(LogLevel::WARNING, "Acquired image is suboptimal"); m_SwapchainManager->signalRecreation(swapchainHandle); } - + m_currentSwapchainImageIndex = imageIndex; return Result::SUCCESS; } - bool Core::beginFrame(uint32_t& width, uint32_t& height, const WindowHandle &windowHandle) { - const Window& window = m_WindowManager->getWindow(windowHandle); + bool Core::beginFrame(uint32_t &width, uint32_t &height, const WindowHandle &windowHandle) { + const Window &window = m_WindowManager->getWindow(windowHandle); const SwapchainHandle swapchainHandle = window.getSwapchain(); if (m_SwapchainManager->shouldUpdateSwapchain(swapchainHandle)) { m_Context.getDevice().waitIdle(); m_SwapchainManager->updateSwapchain(swapchainHandle, window); - + if (!m_SwapchainManager->getSwapchain(swapchainHandle).m_Swapchain) { return false; } setSwapchainImages(swapchainHandle); } - - const auto& extent = m_SwapchainManager->getExtent(swapchainHandle); - + + const auto &extent = m_SwapchainManager->getExtent(swapchainHandle); + width = extent.width; height = extent.height; - + if ((width < MIN_SURFACE_SIZE) || (height < MIN_SURFACE_SIZE)) { return false; } - - if (acquireSwapchainImage( swapchainHandle ) != Result::SUCCESS) { + + if (acquireSwapchainImage(swapchainHandle) != Result::SUCCESS) { vkcv_log(LogLevel::ERROR, "Acquire failed"); - - m_currentSwapchainImageIndex = std::numeric_limits<uint32_t>::max(); - } - - m_Context.getDevice().waitIdle(); // TODO: this is a sin against graphics programming, but its getting late - Alex - + + m_currentSwapchainImageIndex = std::numeric_limits<uint32_t>::max(); + } + + m_Context.getDevice().waitIdle(); // TODO: this is a sin against graphics programming, but + // its getting late - Alex + m_ImageManager->setCurrentSwapchainImageIndex(m_currentSwapchainImageIndex); return (m_currentSwapchainImageIndex != std::numeric_limits<uint32_t>::max()); } - static std::array<uint32_t, 2> getWidthHeightFromRenderTargets(const std::vector<ImageHandle>& renderTargets, - const vk::Extent2D& swapchainExtent, - const ImageManager& imageManager) { + static std::array<uint32_t, 2> + getWidthHeightFromRenderTargets(const std::vector<ImageHandle> &renderTargets, + const vk::Extent2D &swapchainExtent, + const ImageManager &imageManager) { std::array<uint32_t, 2> widthHeight; if (renderTargets.size() > 0) { - const vkcv::ImageHandle firstImage = renderTargets[0]; + const vkcv::ImageHandle firstImage = renderTargets [0]; if (firstImage.isSwapchainImage()) { - widthHeight[0] = swapchainExtent.width; - widthHeight[1] = swapchainExtent.height; + widthHeight [0] = swapchainExtent.width; + widthHeight [1] = swapchainExtent.height; } else { - widthHeight[0] = imageManager.getImageWidth(firstImage); - widthHeight[1] = imageManager.getImageHeight(firstImage); + widthHeight [0] = imageManager.getImageWidth(firstImage); + widthHeight [1] = imageManager.getImageHeight(firstImage); } - } - else { - widthHeight[0] = 1; - widthHeight[1] = 1; + } else { + widthHeight [0] = 1; + widthHeight [1] = 1; } // TODO: validate that width/height match for all attachments return widthHeight; @@ -328,39 +296,34 @@ namespace vkcv const vk::Device &device) { std::vector<vk::ImageView> attachmentsViews; - for (const ImageHandle& handle : renderTargets) { + for (const ImageHandle &handle : renderTargets) { attachmentsViews.push_back(imageManager.getVulkanImageView(handle)); } const vk::FramebufferCreateInfo createInfo( - {}, - renderpass, - static_cast<uint32_t>(attachmentsViews.size()), - attachmentsViews.data(), - renderExtent.width, - renderExtent.height, - 1 - ); + {}, renderpass, static_cast<uint32_t>(attachmentsViews.size()), attachmentsViews.data(), + renderExtent.width, renderExtent.height, 1); return device.createFramebuffer(createInfo); } - void transitionRendertargetsToAttachmentLayout( - const std::vector<ImageHandle>& renderTargets, - ImageManager& imageManager, - const vk::CommandBuffer cmdBuffer) { + void transitionRendertargetsToAttachmentLayout(const std::vector<ImageHandle> &renderTargets, + ImageManager &imageManager, + const vk::CommandBuffer cmdBuffer) { - for (const ImageHandle& handle : renderTargets) { + for (const ImageHandle &handle : renderTargets) { const bool isDepthImage = isDepthFormat(imageManager.getImageFormat(handle)); const vk::ImageLayout targetLayout = - isDepthImage ? vk::ImageLayout::eDepthStencilAttachmentOptimal : vk::ImageLayout::eColorAttachmentOptimal; + isDepthImage ? vk::ImageLayout::eDepthStencilAttachmentOptimal : + vk::ImageLayout::eColorAttachmentOptimal; imageManager.recordImageLayoutTransition(handle, 0, 0, targetLayout, cmdBuffer); } } - std::vector<vk::ClearValue> createAttachmentClearValues(const std::vector<AttachmentDescription>& attachments) { + std::vector<vk::ClearValue> + createAttachmentClearValues(const std::vector<AttachmentDescription> &attachments) { std::vector<vk::ClearValue> clearValues; - for (const auto& attachment : attachments) { + for (const auto &attachment : attachments) { if (attachment.getLoadOperation() == AttachmentOperation::CLEAR) { clearValues.push_back(attachment.getClearValue()); } @@ -369,175 +332,145 @@ namespace vkcv } void recordDynamicViewport(vk::CommandBuffer cmdBuffer, uint32_t width, uint32_t height) { - vk::Viewport dynamicViewport( - 0.0f, 0.0f, - static_cast<float>(width), static_cast<float>(height), - 0.0f, 1.0f - ); + vk::Viewport dynamicViewport(0.0f, 0.0f, static_cast<float>(width), + static_cast<float>(height), 0.0f, 1.0f); vk::Rect2D dynamicScissor({ 0, 0 }, { width, height }); cmdBuffer.setViewport(0, 1, &dynamicViewport); cmdBuffer.setScissor(0, 1, &dynamicScissor); } - - vk::IndexType getIndexType(IndexBitCount indexByteCount){ + + vk::IndexType getIndexType(IndexBitCount indexByteCount) { switch (indexByteCount) { - case IndexBitCount::Bit8: - return vk::IndexType::eUint8EXT; - case IndexBitCount::Bit16: - return vk::IndexType::eUint16; - case IndexBitCount::Bit32: - return vk::IndexType::eUint32; - default: - vkcv_log(LogLevel::ERROR, "unknown Enum"); - return vk::IndexType::eNoneKHR; + case IndexBitCount::Bit8: + return vk::IndexType::eUint8EXT; + case IndexBitCount::Bit16: + return vk::IndexType::eUint16; + case IndexBitCount::Bit32: + return vk::IndexType::eUint32; + default: + vkcv_log(LogLevel::ERROR, "unknown Enum"); + return vk::IndexType::eNoneKHR; } } - + static void recordDrawcall(const DescriptorSetManager &descriptorSetManager, - const BufferManager &bufferManager, - const InstanceDrawcall &drawcall, - vk::CommandBuffer cmdBuffer, - vk::PipelineLayout pipelineLayout, - const PushConstants &pushConstants, - size_t drawcallIndex) { - - const auto& vertexData = drawcall.getVertexData(); - + const BufferManager &bufferManager, const InstanceDrawcall &drawcall, + vk::CommandBuffer cmdBuffer, vk::PipelineLayout pipelineLayout, + const PushConstants &pushConstants, size_t drawcallIndex) { + + const auto &vertexData = drawcall.getVertexData(); + for (uint32_t i = 0; i < vertexData.getVertexBufferBindings().size(); i++) { - const auto& vertexBinding = vertexData.getVertexBufferBindings()[i]; - - cmdBuffer.bindVertexBuffers( - i, - bufferManager.getBuffer(vertexBinding.buffer), - vertexBinding.offset - ); + const auto &vertexBinding = vertexData.getVertexBufferBindings() [i]; + + cmdBuffer.bindVertexBuffers(i, bufferManager.getBuffer(vertexBinding.buffer), + vertexBinding.offset); } - - for (const auto& usage : drawcall.getDescriptorSetUsages()) { + + for (const auto &usage : drawcall.getDescriptorSetUsages()) { cmdBuffer.bindDescriptorSets( - vk::PipelineBindPoint::eGraphics, - pipelineLayout, - usage.location, - descriptorSetManager.getDescriptorSet(usage.descriptorSet).vulkanHandle, - usage.dynamicOffsets - ); + vk::PipelineBindPoint::eGraphics, pipelineLayout, usage.location, + descriptorSetManager.getDescriptorSet(usage.descriptorSet).vulkanHandle, + usage.dynamicOffsets); } - + if (pushConstants.getSizePerDrawcall() > 0) { - cmdBuffer.pushConstants( - pipelineLayout, - vk::ShaderStageFlagBits::eAll, - 0, - pushConstants.getSizePerDrawcall(), - pushConstants.getDrawcallData(drawcallIndex) - ); + cmdBuffer.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eAll, 0, + pushConstants.getSizePerDrawcall(), + pushConstants.getDrawcallData(drawcallIndex)); } - + if (vertexData.getIndexBuffer()) { - cmdBuffer.bindIndexBuffer( - bufferManager.getBuffer(vertexData.getIndexBuffer()), - 0, - getIndexType(vertexData.getIndexBitCount()) - ); - + cmdBuffer.bindIndexBuffer(bufferManager.getBuffer(vertexData.getIndexBuffer()), 0, + getIndexType(vertexData.getIndexBitCount())); + cmdBuffer.drawIndexed(vertexData.getCount(), drawcall.getInstanceCount(), 0, 0, {}); } else { cmdBuffer.draw(vertexData.getCount(), drawcall.getInstanceCount(), 0, 0, {}); } } - - static void recordGraphicsPipeline(Core& core, - CommandStreamManager &cmdStreamManager, + + static void recordGraphicsPipeline(Core &core, CommandStreamManager &cmdStreamManager, GraphicsPipelineManager &pipelineManager, - PassManager &passManager, - ImageManager &imageManager, + PassManager &passManager, ImageManager &imageManager, const CommandStreamHandle &cmdStreamHandle, const GraphicsPipelineHandle &pipelineHandle, const PushConstants &pushConstants, const std::vector<ImageHandle> &renderTargets, const WindowHandle &windowHandle, const RecordCommandFunction &record) { - + const SwapchainHandle swapchainHandle = core.getWindow(windowHandle).getSwapchain(); - + const std::array<uint32_t, 2> extent = getWidthHeightFromRenderTargets( - renderTargets, - core.getSwapchainExtent(swapchainHandle), - imageManager - ); - - const auto width = extent[0]; - const auto height = extent[1]; - + renderTargets, core.getSwapchainExtent(swapchainHandle), imageManager); + + const auto width = extent [0]; + const auto height = extent [1]; + const PassHandle &passHandle = pipelineManager.getPipelineConfig(pipelineHandle).getPass(); - + const vk::RenderPass renderPass = passManager.getVkPass(passHandle); const PassConfig passConfig = passManager.getPassConfig(passHandle); - - const auto& attachments = passConfig.getAttachments(); - const auto& layouts = passManager.getLayouts(passHandle); - + + const auto &attachments = passConfig.getAttachments(); + const auto &layouts = passManager.getLayouts(passHandle); + if (renderTargets.size() != layouts.size()) { vkcv_log(LogLevel::ERROR, "Amount of render targets does not match specified pipeline"); return; } - + const vk::Pipeline pipeline = pipelineManager.getVkPipeline(pipelineHandle); - const vk::Rect2D renderArea (vk::Offset2D(0, 0), vk::Extent2D(width, height)); - + const vk::Rect2D renderArea(vk::Offset2D(0, 0), vk::Extent2D(width, height)); + vk::CommandBuffer cmdBuffer = cmdStreamManager.getStreamCommandBuffer(cmdStreamHandle); transitionRendertargetsToAttachmentLayout(renderTargets, imageManager, cmdBuffer); - + for (size_t i = 0; i < layouts.size(); i++) { - imageManager.recordImageLayoutTransition(renderTargets[i], 0, 0, layouts[i], cmdBuffer); + imageManager.recordImageLayoutTransition(renderTargets [i], 0, 0, layouts [i], + cmdBuffer); } - - const vk::Framebuffer framebuffer = createFramebuffer( - renderTargets, - imageManager, - renderArea.extent, - renderPass, - core.getContext().getDevice() - ); - + + const vk::Framebuffer framebuffer = + createFramebuffer(renderTargets, imageManager, renderArea.extent, renderPass, + core.getContext().getDevice()); + if (!framebuffer) { vkcv_log(LogLevel::ERROR, "Failed to create temporary framebuffer"); return; } - + auto submitFunction = [&](const vk::CommandBuffer &cmdBuffer) { - const std::vector<vk::ClearValue> clearValues = createAttachmentClearValues(attachments); - - const vk::RenderPassBeginInfo beginInfo( - renderPass, - framebuffer, - renderArea, - clearValues.size(), - clearValues.data() - ); - + const std::vector<vk::ClearValue> clearValues = + createAttachmentClearValues(attachments); + + const vk::RenderPassBeginInfo beginInfo(renderPass, framebuffer, renderArea, + clearValues.size(), clearValues.data()); + cmdBuffer.beginRenderPass(beginInfo, {}, {}); cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, {}); - - const GraphicsPipelineConfig &pipeConfig = pipelineManager.getPipelineConfig(pipelineHandle); - + + const GraphicsPipelineConfig &pipeConfig = + pipelineManager.getPipelineConfig(pipelineHandle); + if (pipeConfig.isViewportDynamic()) { recordDynamicViewport(cmdBuffer, width, height); } - + if (record) { record(cmdBuffer); } - + cmdBuffer.endRenderPass(); }; - + auto finishFunction = [framebuffer, &core]() { core.getContext().getDevice().destroy(framebuffer); }; - + core.recordCommandsToStream(cmdStreamHandle, submitFunction, finishFunction); } @@ -547,189 +480,120 @@ namespace vkcv const std::vector<InstanceDrawcall> &drawcalls, const std::vector<ImageHandle> &renderTargets, const WindowHandle &windowHandle) { - + if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) { return; } - - const vk::PipelineLayout pipelineLayout = m_GraphicsPipelineManager->getVkPipelineLayout( - pipelineHandle - ); - auto recordFunction = [&](const vk::CommandBuffer& cmdBuffer) { + const vk::PipelineLayout pipelineLayout = + m_GraphicsPipelineManager->getVkPipelineLayout(pipelineHandle); + + auto recordFunction = [&](const vk::CommandBuffer &cmdBuffer) { for (size_t i = 0; i < drawcalls.size(); i++) { - recordDrawcall( - *m_DescriptorSetManager, - *m_BufferManager, - drawcalls[i], - cmdBuffer, - pipelineLayout, - pushConstantData, - i - ); + recordDrawcall(*m_DescriptorSetManager, *m_BufferManager, drawcalls [i], cmdBuffer, + pipelineLayout, pushConstantData, i); } }; - recordGraphicsPipeline( - *this, - *m_CommandStreamManager, - *m_GraphicsPipelineManager, - *m_PassManager, - *m_ImageManager, - cmdStreamHandle, - pipelineHandle, - pushConstantData, - renderTargets, - windowHandle, - recordFunction - ); - } - - static void recordIndirectDrawcall(const Core& core, - const DescriptorSetManager &descriptorSetManager, - const BufferManager &bufferManager, - vk::CommandBuffer cmdBuffer, - vk::PipelineLayout pipelineLayout, - const PushConstants& pushConstantData, - size_t drawcallIndex, - const IndirectDrawcall& drawcall) { - for (const auto& usage : drawcall.getDescriptorSetUsages()) { + recordGraphicsPipeline(*this, *m_CommandStreamManager, *m_GraphicsPipelineManager, + *m_PassManager, *m_ImageManager, cmdStreamHandle, pipelineHandle, + pushConstantData, renderTargets, windowHandle, recordFunction); + } + + static void + recordIndirectDrawcall(const Core &core, const DescriptorSetManager &descriptorSetManager, + const BufferManager &bufferManager, vk::CommandBuffer cmdBuffer, + vk::PipelineLayout pipelineLayout, const PushConstants &pushConstantData, + size_t drawcallIndex, const IndirectDrawcall &drawcall) { + for (const auto &usage : drawcall.getDescriptorSetUsages()) { cmdBuffer.bindDescriptorSets( - vk::PipelineBindPoint::eGraphics, - pipelineLayout, - usage.location, - descriptorSetManager.getDescriptorSet(usage.descriptorSet).vulkanHandle, - usage.dynamicOffsets - ); + vk::PipelineBindPoint::eGraphics, pipelineLayout, usage.location, + descriptorSetManager.getDescriptorSet(usage.descriptorSet).vulkanHandle, + usage.dynamicOffsets); } - - const auto& vertexData = drawcall.getVertexData(); - + + const auto &vertexData = drawcall.getVertexData(); + for (uint32_t i = 0; i < vertexData.getVertexBufferBindings().size(); i++) { - const auto& vertexBinding = vertexData.getVertexBufferBindings()[i]; - - cmdBuffer.bindVertexBuffers( - i, - bufferManager.getBuffer(vertexBinding.buffer), - vertexBinding.offset - ); + const auto &vertexBinding = vertexData.getVertexBufferBindings() [i]; + + cmdBuffer.bindVertexBuffers(i, bufferManager.getBuffer(vertexBinding.buffer), + vertexBinding.offset); } - + if (pushConstantData.getSizePerDrawcall() > 0) { - cmdBuffer.pushConstants( - pipelineLayout, - vk::ShaderStageFlagBits::eAll, - 0, - pushConstantData.getSizePerDrawcall(), - pushConstantData.getDrawcallData(0) - ); + cmdBuffer.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eAll, 0, + pushConstantData.getSizePerDrawcall(), + pushConstantData.getDrawcallData(0)); } - + if (vertexData.getIndexBuffer()) { - cmdBuffer.bindIndexBuffer( - bufferManager.getBuffer(vertexData.getIndexBuffer()), - 0, - getIndexType(vertexData.getIndexBitCount()) - ); - - cmdBuffer.drawIndexedIndirect( - bufferManager.getBuffer(drawcall.getIndirectDrawBuffer()), - 0, - drawcall.getDrawCount(), - sizeof(vk::DrawIndexedIndirectCommand) - ); + cmdBuffer.bindIndexBuffer(bufferManager.getBuffer(vertexData.getIndexBuffer()), 0, + getIndexType(vertexData.getIndexBitCount())); + + cmdBuffer.drawIndexedIndirect(bufferManager.getBuffer(drawcall.getIndirectDrawBuffer()), + 0, drawcall.getDrawCount(), + sizeof(vk::DrawIndexedIndirectCommand)); } else { - cmdBuffer.drawIndirect( - bufferManager.getBuffer(drawcall.getIndirectDrawBuffer()), - 0, - drawcall.getDrawCount(), - sizeof(vk::DrawIndirectCommand) - ); + cmdBuffer.drawIndirect(bufferManager.getBuffer(drawcall.getIndirectDrawBuffer()), 0, + drawcall.getDrawCount(), sizeof(vk::DrawIndirectCommand)); } } - void Core::recordIndirectDrawcallsToCmdStream(const vkcv::CommandStreamHandle cmdStreamHandle, - const vkcv::GraphicsPipelineHandle &pipelineHandle, - const vkcv::PushConstants &pushConstantData, - const std::vector<IndirectDrawcall> &drawcalls, - const std::vector<ImageHandle> &renderTargets, - const vkcv::WindowHandle &windowHandle) { - - if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) { - return; - } - - const vk::PipelineLayout pipelineLayout = m_GraphicsPipelineManager->getVkPipelineLayout( - pipelineHandle - ); - - auto recordFunction = [&](const vk::CommandBuffer& cmdBuffer) { + void Core::recordIndirectDrawcallsToCmdStream( + const vkcv::CommandStreamHandle cmdStreamHandle, + const vkcv::GraphicsPipelineHandle &pipelineHandle, + const vkcv::PushConstants &pushConstantData, const std::vector<IndirectDrawcall> &drawcalls, + const std::vector<ImageHandle> &renderTargets, const vkcv::WindowHandle &windowHandle) { + + if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) { + return; + } + + const vk::PipelineLayout pipelineLayout = + m_GraphicsPipelineManager->getVkPipelineLayout(pipelineHandle); + + auto recordFunction = [&](const vk::CommandBuffer &cmdBuffer) { for (size_t i = 0; i < drawcalls.size(); i++) { - recordIndirectDrawcall( - *this, - *m_DescriptorSetManager, - *m_BufferManager, - cmdBuffer, - pipelineLayout, - pushConstantData, - i, - drawcalls[i] - ); + recordIndirectDrawcall(*this, *m_DescriptorSetManager, *m_BufferManager, cmdBuffer, + pipelineLayout, pushConstantData, i, drawcalls [i]); } }; - - recordGraphicsPipeline( - *this, - *m_CommandStreamManager, - *m_GraphicsPipelineManager, - *m_PassManager, - *m_ImageManager, - cmdStreamHandle, - pipelineHandle, - pushConstantData, - renderTargets, - windowHandle, - recordFunction - ); - } - - static void recordMeshShaderDrawcall(const Core& core, + + recordGraphicsPipeline(*this, *m_CommandStreamManager, *m_GraphicsPipelineManager, + *m_PassManager, *m_ImageManager, cmdStreamHandle, pipelineHandle, + pushConstantData, renderTargets, windowHandle, recordFunction); + } + + static void recordMeshShaderDrawcall(const Core &core, const DescriptorSetManager &descriptorSetManager, vk::CommandBuffer cmdBuffer, vk::PipelineLayout pipelineLayout, - const PushConstants& pushConstantData, - size_t drawcallIndex, - const TaskDrawcall& drawcall) { - - static PFN_vkCmdDrawMeshTasksNV cmdDrawMeshTasks = reinterpret_cast<PFN_vkCmdDrawMeshTasksNV>( - core.getContext().getDevice().getProcAddr("vkCmdDrawMeshTasksNV") - ); - + const PushConstants &pushConstantData, + size_t drawcallIndex, const TaskDrawcall &drawcall) { + + static PFN_vkCmdDrawMeshTasksNV cmdDrawMeshTasks = + reinterpret_cast<PFN_vkCmdDrawMeshTasksNV>( + core.getContext().getDevice().getProcAddr("vkCmdDrawMeshTasksNV")); + if (!cmdDrawMeshTasks) { vkcv_log(LogLevel::ERROR, "Mesh shader drawcalls are not supported"); return; } - - for (const auto& descriptorUsage : drawcall.getDescriptorSetUsages()) { + + for (const auto &descriptorUsage : drawcall.getDescriptorSetUsages()) { cmdBuffer.bindDescriptorSets( - vk::PipelineBindPoint::eGraphics, - pipelineLayout, - descriptorUsage.location, - descriptorSetManager.getDescriptorSet(descriptorUsage.descriptorSet).vulkanHandle, - descriptorUsage.dynamicOffsets - ); + vk::PipelineBindPoint::eGraphics, pipelineLayout, descriptorUsage.location, + descriptorSetManager.getDescriptorSet(descriptorUsage.descriptorSet).vulkanHandle, + descriptorUsage.dynamicOffsets); } - + if (pushConstantData.getData()) { - cmdBuffer.pushConstants( - pipelineLayout, - vk::ShaderStageFlagBits::eAll, - 0, - pushConstantData.getSizePerDrawcall(), - pushConstantData.getDrawcallData(drawcallIndex) - ); + cmdBuffer.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eAll, 0, + pushConstantData.getSizePerDrawcall(), + pushConstantData.getDrawcallData(drawcallIndex)); } - + cmdDrawMeshTasks(VkCommandBuffer(cmdBuffer), drawcall.getTaskCount(), 0); } @@ -739,192 +603,156 @@ namespace vkcv const std::vector<TaskDrawcall> &drawcalls, const std::vector<ImageHandle> &renderTargets, const WindowHandle &windowHandle) { - + if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) { return; } - - const vk::PipelineLayout pipelineLayout = m_GraphicsPipelineManager->getVkPipelineLayout( - pipelineHandle - ); - auto recordFunction = [&](const vk::CommandBuffer& cmdBuffer) { + const vk::PipelineLayout pipelineLayout = + m_GraphicsPipelineManager->getVkPipelineLayout(pipelineHandle); + + auto recordFunction = [&](const vk::CommandBuffer &cmdBuffer) { for (size_t i = 0; i < drawcalls.size(); i++) { - recordMeshShaderDrawcall( - *this, - *m_DescriptorSetManager, - cmdBuffer, - pipelineLayout, - pushConstantData, - i, - drawcalls[i] - ); + recordMeshShaderDrawcall(*this, *m_DescriptorSetManager, cmdBuffer, pipelineLayout, + pushConstantData, i, drawcalls [i]); } }; - - recordGraphicsPipeline( - *this, - *m_CommandStreamManager, - *m_GraphicsPipelineManager, - *m_PassManager, - *m_ImageManager, - cmdStreamHandle, - pipelineHandle, - pushConstantData, - renderTargets, - windowHandle, - recordFunction - ); - } - - - void Core::recordRayGenerationToCmdStream(CommandStreamHandle cmdStreamHandle, - vk::Pipeline rtxPipeline, - vk::PipelineLayout rtxPipelineLayout, - vk::StridedDeviceAddressRegionKHR rgenRegion, - vk::StridedDeviceAddressRegionKHR rmissRegion, - vk::StridedDeviceAddressRegionKHR rchitRegion, - vk::StridedDeviceAddressRegionKHR rcallRegion, - const std::vector<DescriptorSetUsage>& descriptorSetUsages, - const PushConstants& pushConstants, - const WindowHandle& windowHandle) { - - auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) { + + recordGraphicsPipeline(*this, *m_CommandStreamManager, *m_GraphicsPipelineManager, + *m_PassManager, *m_ImageManager, cmdStreamHandle, pipelineHandle, + pushConstantData, renderTargets, windowHandle, recordFunction); + } + + void Core::recordRayGenerationToCmdStream( + CommandStreamHandle cmdStreamHandle, vk::Pipeline rtxPipeline, + vk::PipelineLayout rtxPipelineLayout, vk::StridedDeviceAddressRegionKHR rgenRegion, + vk::StridedDeviceAddressRegionKHR rmissRegion, + vk::StridedDeviceAddressRegionKHR rchitRegion, + vk::StridedDeviceAddressRegionKHR rcallRegion, + const std::vector<DescriptorSetUsage> &descriptorSetUsages, + const PushConstants &pushConstants, const WindowHandle &windowHandle) { + + auto submitFunction = [&](const vk::CommandBuffer &cmdBuffer) { cmdBuffer.bindPipeline(vk::PipelineBindPoint::eRayTracingKHR, rtxPipeline); - for (const auto& usage : descriptorSetUsages) { + for (const auto &usage : descriptorSetUsages) { cmdBuffer.bindDescriptorSets( - vk::PipelineBindPoint::eRayTracingKHR, - rtxPipelineLayout, - usage.location, + vk::PipelineBindPoint::eRayTracingKHR, rtxPipelineLayout, usage.location, { m_DescriptorSetManager->getDescriptorSet(usage.descriptorSet).vulkanHandle }, - usage.dynamicOffsets - ); + usage.dynamicOffsets); } if (pushConstants.getSizePerDrawcall() > 0) { cmdBuffer.pushConstants( rtxPipelineLayout, - (vk::ShaderStageFlagBits::eClosestHitKHR | vk::ShaderStageFlagBits::eMissKHR | vk::ShaderStageFlagBits::eRaygenKHR), // TODO: add Support for eAnyHitKHR, eCallableKHR, eIntersectionKHR - 0, - pushConstants.getSizePerDrawcall(), - pushConstants.getData()); + (vk::ShaderStageFlagBits::eClosestHitKHR | vk::ShaderStageFlagBits::eMissKHR + | vk::ShaderStageFlagBits::eRaygenKHR), // TODO: add Support for eAnyHitKHR, + // eCallableKHR, eIntersectionKHR + 0, pushConstants.getSizePerDrawcall(), pushConstants.getData()); } - - auto m_rtxDispatcher = vk::DispatchLoaderDynamic((PFN_vkGetInstanceProcAddr)m_Context.getInstance().getProcAddr("vkGetInstanceProcAddr")); - m_rtxDispatcher.init(m_Context.getInstance()); - cmdBuffer.traceRaysKHR(&rgenRegion,&rmissRegion,&rchitRegion,&rcallRegion, - getWindow(windowHandle).getWidth(), getWindow(windowHandle).getHeight(),1, m_rtxDispatcher); + auto m_rtxDispatcher = vk::DispatchLoaderDynamic( + (PFN_vkGetInstanceProcAddr)m_Context.getInstance().getProcAddr( + "vkGetInstanceProcAddr")); + m_rtxDispatcher.init(m_Context.getInstance()); + cmdBuffer.traceRaysKHR(&rgenRegion, &rmissRegion, &rchitRegion, &rcallRegion, + getWindow(windowHandle).getWidth(), + getWindow(windowHandle).getHeight(), 1, m_rtxDispatcher); }; recordCommandsToStream(cmdStreamHandle, submitFunction, nullptr); - } - - void Core::recordComputeDispatchToCmdStream(const CommandStreamHandle& cmdStreamHandle, - const ComputePipelineHandle& computePipeline, - const DispatchSize& dispatchSize, - const std::vector<DescriptorSetUsage>& descriptorSetUsages, - const PushConstants& pushConstants) { - auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) { - const auto pipelineLayout = m_ComputePipelineManager->getVkPipelineLayout(computePipeline); - - cmdBuffer.bindPipeline(vk::PipelineBindPoint::eCompute, m_ComputePipelineManager->getVkPipeline(computePipeline)); - for (const auto& usage : descriptorSetUsages) { + } + + void Core::recordComputeDispatchToCmdStream( + const CommandStreamHandle &cmdStreamHandle, const ComputePipelineHandle &computePipeline, + const DispatchSize &dispatchSize, + const std::vector<DescriptorSetUsage> &descriptorSetUsages, + const PushConstants &pushConstants) { + auto submitFunction = [&](const vk::CommandBuffer &cmdBuffer) { + const auto pipelineLayout = + m_ComputePipelineManager->getVkPipelineLayout(computePipeline); + + cmdBuffer.bindPipeline(vk::PipelineBindPoint::eCompute, + m_ComputePipelineManager->getVkPipeline(computePipeline)); + for (const auto &usage : descriptorSetUsages) { cmdBuffer.bindDescriptorSets( - vk::PipelineBindPoint::eCompute, - pipelineLayout, - usage.location, + vk::PipelineBindPoint::eCompute, pipelineLayout, usage.location, { m_DescriptorSetManager->getDescriptorSet(usage.descriptorSet).vulkanHandle }, - usage.dynamicOffsets - ); + usage.dynamicOffsets); } if (pushConstants.getSizePerDrawcall() > 0) { - cmdBuffer.pushConstants( - pipelineLayout, - vk::ShaderStageFlagBits::eCompute, - 0, - pushConstants.getSizePerDrawcall(), - pushConstants.getData()); + cmdBuffer.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, + pushConstants.getSizePerDrawcall(), + pushConstants.getData()); } - + cmdBuffer.dispatch(dispatchSize.x(), dispatchSize.y(), dispatchSize.z()); }; recordCommandsToStream(cmdStreamHandle, submitFunction, nullptr); } - - void Core::recordBeginDebugLabel(const CommandStreamHandle &cmdStream, - const std::string& label, - const std::array<float, 4>& color) { - #ifdef VULKAN_DEBUG_LABELS - static PFN_vkCmdBeginDebugUtilsLabelEXT beginDebugLabel = reinterpret_cast<PFN_vkCmdBeginDebugUtilsLabelEXT>( - m_Context.getDevice().getProcAddr("vkCmdBeginDebugUtilsLabelEXT") - ); - + + void Core::recordBeginDebugLabel(const CommandStreamHandle &cmdStream, const std::string &label, + const std::array<float, 4> &color) { +#ifdef VULKAN_DEBUG_LABELS + static PFN_vkCmdBeginDebugUtilsLabelEXT beginDebugLabel = + reinterpret_cast<PFN_vkCmdBeginDebugUtilsLabelEXT>( + m_Context.getDevice().getProcAddr("vkCmdBeginDebugUtilsLabelEXT")); + if (!beginDebugLabel) { return; } - - auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) { - const vk::DebugUtilsLabelEXT debug ( - label.c_str(), - color - ); - - beginDebugLabel(static_cast<VkCommandBuffer>(cmdBuffer), &(static_cast<const VkDebugUtilsLabelEXT&>(debug))); + + auto submitFunction = [&](const vk::CommandBuffer &cmdBuffer) { + const vk::DebugUtilsLabelEXT debug(label.c_str(), color); + + beginDebugLabel(static_cast<VkCommandBuffer>(cmdBuffer), + &(static_cast<const VkDebugUtilsLabelEXT &>(debug))); }; recordCommandsToStream(cmdStream, submitFunction, nullptr); - #endif +#endif } - + void Core::recordEndDebugLabel(const CommandStreamHandle &cmdStream) { - #ifdef VULKAN_DEBUG_LABELS - static PFN_vkCmdEndDebugUtilsLabelEXT endDebugLabel = reinterpret_cast<PFN_vkCmdEndDebugUtilsLabelEXT>( - m_Context.getDevice().getProcAddr("vkCmdEndDebugUtilsLabelEXT") - ); - +#ifdef VULKAN_DEBUG_LABELS + static PFN_vkCmdEndDebugUtilsLabelEXT endDebugLabel = + reinterpret_cast<PFN_vkCmdEndDebugUtilsLabelEXT>( + m_Context.getDevice().getProcAddr("vkCmdEndDebugUtilsLabelEXT")); + if (!endDebugLabel) { return; } - - auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) { + + auto submitFunction = [&](const vk::CommandBuffer &cmdBuffer) { endDebugLabel(static_cast<VkCommandBuffer>(cmdBuffer)); }; recordCommandsToStream(cmdStream, submitFunction, nullptr); - #endif +#endif } - - void Core::recordComputeIndirectDispatchToCmdStream( - const CommandStreamHandle cmdStream, - const ComputePipelineHandle computePipeline, - const vkcv::BufferHandle buffer, - const size_t bufferArgOffset, - const std::vector<DescriptorSetUsage>& descriptorSetUsages, - const PushConstants& pushConstants) { - auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) { + void Core::recordComputeIndirectDispatchToCmdStream( + const CommandStreamHandle cmdStream, const ComputePipelineHandle computePipeline, + const vkcv::BufferHandle buffer, const size_t bufferArgOffset, + const std::vector<DescriptorSetUsage> &descriptorSetUsages, + const PushConstants &pushConstants) { - const auto pipelineLayout = m_ComputePipelineManager->getVkPipelineLayout(computePipeline); + auto submitFunction = [&](const vk::CommandBuffer &cmdBuffer) { + const auto pipelineLayout = + m_ComputePipelineManager->getVkPipelineLayout(computePipeline); - cmdBuffer.bindPipeline(vk::PipelineBindPoint::eCompute, m_ComputePipelineManager->getVkPipeline(computePipeline)); - for (const auto& usage : descriptorSetUsages) { + cmdBuffer.bindPipeline(vk::PipelineBindPoint::eCompute, + m_ComputePipelineManager->getVkPipeline(computePipeline)); + for (const auto &usage : descriptorSetUsages) { cmdBuffer.bindDescriptorSets( - vk::PipelineBindPoint::eCompute, - pipelineLayout, - usage.location, + vk::PipelineBindPoint::eCompute, pipelineLayout, usage.location, { m_DescriptorSetManager->getDescriptorSet(usage.descriptorSet).vulkanHandle }, - usage.dynamicOffsets - ); + usage.dynamicOffsets); } if (pushConstants.getSizePerDrawcall() > 0) { - cmdBuffer.pushConstants( - pipelineLayout, - vk::ShaderStageFlagBits::eCompute, - 0, - pushConstants.getSizePerDrawcall(), - pushConstants.getData()); + cmdBuffer.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, + pushConstants.getSizePerDrawcall(), + pushConstants.getData()); } cmdBuffer.dispatchIndirect(m_BufferManager->getBuffer(buffer), bufferArgOffset); }; @@ -932,45 +760,42 @@ namespace vkcv recordCommandsToStream(cmdStream, submitFunction, nullptr); } - void Core::endFrame(const WindowHandle& windowHandle) { + void Core::endFrame(const WindowHandle &windowHandle) { SwapchainHandle swapchainHandle = m_WindowManager->getWindow(windowHandle).getSwapchain(); if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) { return; } - - const std::array<vk::Semaphore, 2> waitSemaphores { - m_RenderFinished, - m_SwapchainImageAcquired - }; - const vk::SwapchainKHR& swapchain = m_SwapchainManager->getSwapchain(swapchainHandle).m_Swapchain; - const vk::PresentInfoKHR presentInfo( - waitSemaphores, - swapchain, - m_currentSwapchainImageIndex - ); - + const std::array<vk::Semaphore, 2> waitSemaphores { m_RenderFinished, + m_SwapchainImageAcquired }; + + const vk::SwapchainKHR &swapchain = + m_SwapchainManager->getSwapchain(swapchainHandle).m_Swapchain; + const vk::PresentInfoKHR presentInfo(waitSemaphores, swapchain, + m_currentSwapchainImageIndex); + vk::Result result; - + try { - result = m_Context.getDevice().getQueue(m_SwapchainManager->getPresentQueueIndex(swapchainHandle),0).presentKHR(presentInfo); - } catch (const vk::OutOfDateKHRError& e) { + result = m_Context.getDevice() + .getQueue(m_SwapchainManager->getPresentQueueIndex(swapchainHandle), 0) + .presentKHR(presentInfo); + } catch (const vk::OutOfDateKHRError &e) { result = vk::Result::eErrorOutOfDateKHR; - } catch (const vk::DeviceLostError& e) { + } catch (const vk::DeviceLostError &e) { result = vk::Result::eErrorDeviceLost; } - - if ((result != vk::Result::eSuccess) && - (result != vk::Result::eSuboptimalKHR)) { - vkcv_log(LogLevel::ERROR, "Swapchain presentation failed (%s)", vk::to_string(result).c_str()); - } else - if (result == vk::Result::eSuboptimalKHR) { + + if ((result != vk::Result::eSuccess) && (result != vk::Result::eSuboptimalKHR)) { + vkcv_log(LogLevel::ERROR, "Swapchain presentation failed (%s)", + vk::to_string(result).c_str()); + } else if (result == vk::Result::eSuboptimalKHR) { vkcv_log(LogLevel::WARNING, "Swapchain presentation is suboptimal"); m_SwapchainManager->signalRecreation(swapchainHandle); } } - + /** * @brief Returns a queue of a given type from a queue manager. * @@ -978,569 +803,490 @@ namespace vkcv * @param[in] queueManager Queue manager * @return Queue of a given type */ - static Queue getQueueForSubmit(QueueType type, const QueueManager& queueManager) { + static Queue getQueueForSubmit(QueueType type, const QueueManager &queueManager) { switch (type) { - case QueueType::Graphics: - return queueManager.getGraphicsQueues().front(); - case QueueType::Compute: - return queueManager.getComputeQueues().front(); - case QueueType::Transfer: - return queueManager.getTransferQueues().front(); - case QueueType::Present: - return queueManager.getPresentQueue(); - default: { - vkcv_log(LogLevel::ERROR, "Unknown queue type"); - return queueManager.getGraphicsQueues().front(); // graphics is the most general queue - } + case QueueType::Graphics: + return queueManager.getGraphicsQueues().front(); + case QueueType::Compute: + return queueManager.getComputeQueues().front(); + case QueueType::Transfer: + return queueManager.getTransferQueues().front(); + case QueueType::Present: + return queueManager.getPresentQueue(); + default: { + vkcv_log(LogLevel::ERROR, "Unknown queue type"); + return queueManager.getGraphicsQueues().front(); // graphics is the most general queue + } } } - + CommandStreamHandle Core::createCommandStream(QueueType queueType) { - const vkcv::Queue queue = getQueueForSubmit(queueType, m_Context.getQueueManager()); - const vk::CommandPool cmdPool = m_CommandPools[queue.familyIndex]; + const vkcv::Queue queue = getQueueForSubmit(queueType, m_Context.getQueueManager()); + const vk::CommandPool cmdPool = m_CommandPools [queue.familyIndex]; return m_CommandStreamManager->createCommandStream(queue.handle, cmdPool); } - void Core::recordCommandsToStream(const CommandStreamHandle &stream, + void Core::recordCommandsToStream(const CommandStreamHandle &stream, const RecordCommandFunction &record, const FinishCommandFunction &finish) { if (record) { m_CommandStreamManager->recordCommandsToStream(stream, record); } - + if (finish) { m_CommandStreamManager->addFinishCallbackToStream(stream, finish); } } - void Core::submitCommandStream(const CommandStreamHandle& stream, - bool signalRendering) { + void Core::submitCommandStream(const CommandStreamHandle &stream, bool signalRendering) { std::vector<vk::Semaphore> waitSemaphores; - + // FIXME: add proper user controllable sync std::vector<vk::Semaphore> signalSemaphores; if (signalRendering) { signalSemaphores.push_back(m_RenderFinished); } - - m_CommandStreamManager->submitCommandStreamSynchronous(stream, waitSemaphores, signalSemaphores); + + m_CommandStreamManager->submitCommandStreamSynchronous(stream, waitSemaphores, + signalSemaphores); } SamplerHandle Core::createSampler(SamplerFilterType magFilter, SamplerFilterType minFilter, SamplerMipmapMode mipmapMode, SamplerAddressMode addressMode, float mipLodBias, SamplerBorderColor borderColor) { - return m_SamplerManager->createSampler(magFilter, minFilter, mipmapMode, addressMode, mipLodBias, borderColor); + return m_SamplerManager->createSampler(magFilter, minFilter, mipmapMode, addressMode, + mipLodBias, borderColor); } - ImageHandle Core::createImage(vk::Format format, - uint32_t width, - uint32_t height, - uint32_t depth, - bool createMipChain, - bool supportStorage, - bool supportColorAttachment, - Multisampling multisampling) { + ImageHandle Core::createImage(vk::Format format, uint32_t width, uint32_t height, + uint32_t depth, bool createMipChain, bool supportStorage, + bool supportColorAttachment, Multisampling multisampling) { uint32_t mipCount = 1; if (createMipChain) { - mipCount = 1 + (uint32_t)std::floor(std::log2(std::max(width, std::max(height, depth)))); + mipCount = + 1 + (uint32_t)std::floor(std::log2(std::max(width, std::max(height, depth)))); } - - return m_ImageManager->createImage( - width, - height, - depth, - format, - mipCount, - supportStorage, - supportColorAttachment, - multisampling - ); - } - - void Core::fillImage(const ImageHandle &image, - const void *data, - size_t size) { + + return m_ImageManager->createImage(width, height, depth, format, mipCount, supportStorage, + supportColorAttachment, multisampling); + } + + void Core::fillImage(const ImageHandle &image, const void* data, size_t size) { m_ImageManager->fillImage(image, data, size); } - - void Core::switchImageLayout(const ImageHandle &image, - vk::ImageLayout layout) { + + void Core::switchImageLayout(const ImageHandle &image, vk::ImageLayout layout) { m_ImageManager->switchImageLayoutImmediate(image, layout); } - + Downsampler &Core::getDownsampler() { return *m_downsampler; } - WindowHandle Core::createWindow(const char *applicationName, - uint32_t windowWidth, - uint32_t windowHeight, - bool resizeable) { - WindowHandle windowHandle = m_WindowManager->createWindow(*m_SwapchainManager ,applicationName, windowWidth, windowHeight, resizeable); + WindowHandle Core::createWindow(const std::string &applicationName, uint32_t windowWidth, + uint32_t windowHeight, bool resizeable) { + WindowHandle windowHandle = m_WindowManager->createWindow( + *m_SwapchainManager, applicationName, windowWidth, windowHeight, resizeable); + SwapchainHandle swapchainHandle = m_WindowManager->getWindow(windowHandle).getSwapchain(); - setSwapchainImages( swapchainHandle ); + setSwapchainImages(swapchainHandle); return windowHandle; } - Window& Core::getWindow(const WindowHandle& handle) { + Window &Core::getWindow(const WindowHandle &handle) { return m_WindowManager->getWindow(handle); } - + vk::Format Core::getSwapchainFormat(const SwapchainHandle &swapchain) const { return m_SwapchainManager->getFormat(swapchain); } - + uint32_t Core::getSwapchainImageCount(const SwapchainHandle &swapchain) const { return m_SwapchainManager->getImageCount(swapchain); } - - vk::Extent2D Core::getSwapchainExtent(const SwapchainHandle& swapchain) const { + + vk::Extent2D Core::getSwapchainExtent(const SwapchainHandle &swapchain) const { return m_SwapchainManager->getExtent(swapchain); } - - uint32_t Core::getImageWidth(const ImageHandle& image) - { + + uint32_t Core::getImageWidth(const ImageHandle &image) { return m_ImageManager->getImageWidth(image); } - uint32_t Core::getImageHeight(const ImageHandle& image) - { + uint32_t Core::getImageHeight(const ImageHandle &image) { return m_ImageManager->getImageHeight(image); } - - uint32_t Core::getImageDepth(const ImageHandle& image) - { + + uint32_t Core::getImageDepth(const ImageHandle &image) { return m_ImageManager->getImageDepth(image); } - - vk::Format Core::getImageFormat(const ImageHandle& image) { + + vk::Format Core::getImageFormat(const ImageHandle &image) { 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); } - + uint32_t Core::getImageArrayLayers(const ImageHandle &image) { return m_ImageManager->getImageArrayLayers(image); } DescriptorSetLayoutHandle Core::createDescriptorSetLayout(const DescriptorBindings &bindings) { - return m_DescriptorSetLayoutManager->createDescriptorSetLayout(bindings); + return m_DescriptorSetLayoutManager->createDescriptorSetLayout(bindings); } DescriptorSetHandle Core::createDescriptorSet(const DescriptorSetLayoutHandle &layout) { - return m_DescriptorSetManager->createDescriptorSet(layout); - } + return m_DescriptorSetManager->createDescriptorSet(layout); + } void Core::writeDescriptorSet(DescriptorSetHandle handle, const DescriptorWrites &writes) { - m_DescriptorSetManager->writeDescriptorSet( - handle, - writes, - *m_ImageManager, - *m_BufferManager, - *m_SamplerManager - ); + m_DescriptorSetManager->writeDescriptorSet(handle, writes, *m_ImageManager, + *m_BufferManager, *m_SamplerManager); } - void Core::prepareSwapchainImageForPresent(const CommandStreamHandle& cmdStream) { + void Core::prepareSwapchainImageForPresent(const CommandStreamHandle &cmdStream) { auto swapchainHandle = ImageHandle::createSwapchainImageHandle(); - recordCommandsToStream(cmdStream, [swapchainHandle, this](const vk::CommandBuffer cmdBuffer) { - m_ImageManager->recordImageLayoutTransition( - swapchainHandle, - 0, - 0, - vk::ImageLayout::ePresentSrcKHR, - cmdBuffer - ); - }, nullptr); - } - - void Core::prepareImageForSampling(const CommandStreamHandle& cmdStream, - const ImageHandle& image, - uint32_t mipLevelCount, + recordCommandsToStream( + cmdStream, + [swapchainHandle, this](const vk::CommandBuffer cmdBuffer) { + m_ImageManager->recordImageLayoutTransition( + swapchainHandle, 0, 0, vk::ImageLayout::ePresentSrcKHR, cmdBuffer); + }, + nullptr); + } + + void Core::prepareImageForSampling(const CommandStreamHandle &cmdStream, + const ImageHandle &image, uint32_t mipLevelCount, uint32_t mipLevelOffset) { - recordCommandsToStream(cmdStream, [image, mipLevelCount, mipLevelOffset, this](const vk::CommandBuffer cmdBuffer) { - m_ImageManager->recordImageLayoutTransition( - image, - mipLevelCount, - mipLevelOffset, - vk::ImageLayout::eShaderReadOnlyOptimal, - cmdBuffer - ); - }, nullptr); - } - - void Core::prepareImageForStorage(const CommandStreamHandle& cmdStream, - const ImageHandle& image, - uint32_t mipLevelCount, + recordCommandsToStream( + cmdStream, + [image, mipLevelCount, mipLevelOffset, this](const vk::CommandBuffer cmdBuffer) { + m_ImageManager->recordImageLayoutTransition(image, mipLevelCount, mipLevelOffset, + vk::ImageLayout::eShaderReadOnlyOptimal, + cmdBuffer); + }, + nullptr); + } + + void Core::prepareImageForStorage(const CommandStreamHandle &cmdStream, + const ImageHandle &image, uint32_t mipLevelCount, uint32_t mipLevelOffset) { - recordCommandsToStream(cmdStream, [image, mipLevelCount, mipLevelOffset, this](const vk::CommandBuffer cmdBuffer) { - m_ImageManager->recordImageLayoutTransition( - image, - mipLevelCount, - mipLevelOffset, - vk::ImageLayout::eGeneral, - cmdBuffer - ); - }, nullptr); - } - - void Core::prepareImageForAttachmentManually(const vk::CommandBuffer& cmdBuffer, const ImageHandle& image) { + recordCommandsToStream( + cmdStream, + [image, mipLevelCount, mipLevelOffset, this](const vk::CommandBuffer cmdBuffer) { + m_ImageManager->recordImageLayoutTransition(image, mipLevelCount, mipLevelOffset, + vk::ImageLayout::eGeneral, cmdBuffer); + }, + nullptr); + } + + void Core::prepareImageForAttachmentManually(const vk::CommandBuffer &cmdBuffer, + const ImageHandle &image) { transitionRendertargetsToAttachmentLayout({ image }, *m_ImageManager, cmdBuffer); } - void Core::updateImageLayoutManual(const vkcv::ImageHandle& image, const vk::ImageLayout layout) { + void Core::updateImageLayoutManual(const vkcv::ImageHandle &image, + const vk::ImageLayout layout) { m_ImageManager->updateImageLayoutManual(image, layout); } - void Core::recordImageMemoryBarrier(const CommandStreamHandle& cmdStream, const ImageHandle& image) { - recordCommandsToStream(cmdStream, [image, this](const vk::CommandBuffer cmdBuffer) { - m_ImageManager->recordImageMemoryBarrier(image, cmdBuffer); - }, nullptr); + void Core::recordImageMemoryBarrier(const CommandStreamHandle &cmdStream, + const ImageHandle &image) { + recordCommandsToStream( + cmdStream, + [image, this](const vk::CommandBuffer cmdBuffer) { + m_ImageManager->recordImageMemoryBarrier(image, cmdBuffer); + }, + nullptr); } - void Core::recordBufferMemoryBarrier(const CommandStreamHandle& cmdStream, const BufferHandle& buffer) { - recordCommandsToStream(cmdStream, [buffer, this](const vk::CommandBuffer cmdBuffer) { - m_BufferManager->recordBufferMemoryBarrier(buffer, cmdBuffer); - }, nullptr); + void Core::recordBufferMemoryBarrier(const CommandStreamHandle &cmdStream, + const BufferHandle &buffer) { + recordCommandsToStream( + cmdStream, + [buffer, this](const vk::CommandBuffer cmdBuffer) { + m_BufferManager->recordBufferMemoryBarrier(buffer, cmdBuffer); + }, + nullptr); } - - void Core::resolveMSAAImage(const CommandStreamHandle& cmdStream, const ImageHandle& src, const ImageHandle& dst) { - recordCommandsToStream(cmdStream, [src, dst, this](const vk::CommandBuffer cmdBuffer) { - m_ImageManager->recordMSAAResolve(cmdBuffer, src, dst); - }, nullptr); + + void Core::resolveMSAAImage(const CommandStreamHandle &cmdStream, const ImageHandle &src, + const ImageHandle &dst) { + recordCommandsToStream( + cmdStream, + [src, dst, this](const vk::CommandBuffer cmdBuffer) { + m_ImageManager->recordMSAAResolve(cmdBuffer, src, dst); + }, + nullptr); } vk::ImageView Core::getSwapchainImageView() const { - return m_ImageManager->getVulkanImageView(vkcv::ImageHandle::createSwapchainImageHandle()); - } - - void Core::recordMemoryBarrier(const CommandStreamHandle& cmdStream) { - recordCommandsToStream(cmdStream, [](const vk::CommandBuffer cmdBuffer) { - vk::MemoryBarrier barrier ( + return m_ImageManager->getVulkanImageView(vkcv::ImageHandle::createSwapchainImageHandle()); + } + + void Core::recordMemoryBarrier(const CommandStreamHandle &cmdStream) { + recordCommandsToStream( + cmdStream, + [](const vk::CommandBuffer cmdBuffer) { + vk::MemoryBarrier barrier( vk::AccessFlagBits::eMemoryWrite | vk::AccessFlagBits::eMemoryRead, - vk::AccessFlagBits::eMemoryWrite | vk::AccessFlagBits::eMemoryRead - ); - - cmdBuffer.pipelineBarrier( - vk::PipelineStageFlagBits::eAllCommands, - vk::PipelineStageFlagBits::eAllCommands, - vk::DependencyFlags(), - 1, &barrier, - 0, nullptr, - 0, nullptr - ); - }, nullptr); - } - - void Core::recordBlitImage(const CommandStreamHandle& cmdStream, const ImageHandle& src, const ImageHandle& dst, - SamplerFilterType filterType) { - recordCommandsToStream(cmdStream, [&](const vk::CommandBuffer cmdBuffer) { - m_ImageManager->recordImageLayoutTransition( - src, 0, 0, vk::ImageLayout::eTransferSrcOptimal, cmdBuffer - ); - - m_ImageManager->recordImageLayoutTransition( - dst, 0, 0, vk::ImageLayout::eTransferDstOptimal, cmdBuffer - ); - - const std::array<vk::Offset3D, 2> srcOffsets = { - vk::Offset3D(0, 0, 0), - vk::Offset3D( - m_ImageManager->getImageWidth(src), - m_ImageManager->getImageHeight(src), - 1 - ) - }; - - const std::array<vk::Offset3D, 2> dstOffsets = { - vk::Offset3D(0, 0, 0), - vk::Offset3D( - m_ImageManager->getImageWidth(dst), - m_ImageManager->getImageHeight(dst), - 1 - ) - }; - - const bool srcDepth = isDepthFormat(m_ImageManager->getImageFormat(src)); - const bool dstDepth = isDepthFormat(m_ImageManager->getImageFormat(dst)); - - const vk::ImageBlit blit = vk::ImageBlit( - vk::ImageSubresourceLayers( - srcDepth? - vk::ImageAspectFlagBits::eDepth : - vk::ImageAspectFlagBits::eColor, - 0, 0, 1 - ), + vk::AccessFlagBits::eMemoryWrite | vk::AccessFlagBits::eMemoryRead); + + cmdBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands, + vk::PipelineStageFlagBits::eAllCommands, + vk::DependencyFlags(), 1, &barrier, 0, nullptr, 0, + nullptr); + }, + nullptr); + } + + void Core::recordBlitImage(const CommandStreamHandle &cmdStream, const ImageHandle &src, + const ImageHandle &dst, SamplerFilterType filterType) { + recordCommandsToStream( + cmdStream, + [&](const vk::CommandBuffer cmdBuffer) { + m_ImageManager->recordImageLayoutTransition( + src, 0, 0, vk::ImageLayout::eTransferSrcOptimal, cmdBuffer); + + m_ImageManager->recordImageLayoutTransition( + dst, 0, 0, vk::ImageLayout::eTransferDstOptimal, cmdBuffer); + + const std::array<vk::Offset3D, 2> srcOffsets = { + vk::Offset3D(0, 0, 0), vk::Offset3D(m_ImageManager->getImageWidth(src), + m_ImageManager->getImageHeight(src), 1) + }; + + const std::array<vk::Offset3D, 2> dstOffsets = { + vk::Offset3D(0, 0, 0), vk::Offset3D(m_ImageManager->getImageWidth(dst), + m_ImageManager->getImageHeight(dst), 1) + }; + + const bool srcDepth = isDepthFormat(m_ImageManager->getImageFormat(src)); + const bool dstDepth = isDepthFormat(m_ImageManager->getImageFormat(dst)); + + const vk::ImageBlit blit = vk::ImageBlit( + vk::ImageSubresourceLayers(srcDepth ? vk::ImageAspectFlagBits::eDepth : + vk::ImageAspectFlagBits::eColor, + 0, 0, 1), srcOffsets, - vk::ImageSubresourceLayers( - dstDepth? - vk::ImageAspectFlagBits::eDepth : - vk::ImageAspectFlagBits::eColor, - 0, 0, 1 - ), - dstOffsets - ); - - cmdBuffer.blitImage( - m_ImageManager->getVulkanImage(src), - vk::ImageLayout::eTransferSrcOptimal, - m_ImageManager->getVulkanImage(dst), - vk::ImageLayout::eTransferDstOptimal, - 1, - &blit, - filterType == SamplerFilterType::LINEAR? - vk::Filter::eLinear : - vk::Filter::eNearest - ); - }, nullptr); - } - - void Core::setSwapchainImages( SwapchainHandle handle ) { - const auto& swapchain = m_SwapchainManager->getSwapchain(handle); + vk::ImageSubresourceLayers(dstDepth ? vk::ImageAspectFlagBits::eDepth : + vk::ImageAspectFlagBits::eColor, + 0, 0, 1), + dstOffsets); + + cmdBuffer.blitImage(m_ImageManager->getVulkanImage(src), + vk::ImageLayout::eTransferSrcOptimal, + m_ImageManager->getVulkanImage(dst), + vk::ImageLayout::eTransferDstOptimal, 1, &blit, + filterType == SamplerFilterType::LINEAR ? vk::Filter::eLinear : + vk::Filter::eNearest); + }, + nullptr); + } + + void Core::setSwapchainImages(SwapchainHandle handle) { + const auto &swapchain = m_SwapchainManager->getSwapchain(handle); const auto swapchainImages = m_SwapchainManager->getSwapchainImages(handle); const auto swapchainImageViews = m_SwapchainManager->createSwapchainImageViews(handle); - m_ImageManager->setSwapchainImages( - swapchainImages, - swapchainImageViews, - swapchain.m_Extent.width, - swapchain.m_Extent.height, - swapchain.m_Format - ); - } - - static void setDebugObjectLabel(const vk::Device& device, const vk::ObjectType& type, - uint64_t handle, const std::string& label) { + m_ImageManager->setSwapchainImages(swapchainImages, swapchainImageViews, + swapchain.m_Extent.width, swapchain.m_Extent.height, + swapchain.m_Format); + } + + static void setDebugObjectLabel(const vk::Device &device, const vk::ObjectType &type, + uint64_t handle, const std::string &label) { #ifdef VULKAN_DEBUG_LABELS - static PFN_vkSetDebugUtilsObjectNameEXT setDebugLabel = reinterpret_cast<PFN_vkSetDebugUtilsObjectNameEXT>( - device.getProcAddr("vkSetDebugUtilsObjectNameEXT") - ); - + static PFN_vkSetDebugUtilsObjectNameEXT setDebugLabel = + reinterpret_cast<PFN_vkSetDebugUtilsObjectNameEXT>( + device.getProcAddr("vkSetDebugUtilsObjectNameEXT")); + if (!setDebugLabel) { return; } - - const vk::DebugUtilsObjectNameInfoEXT debug ( - type, - handle, - label.c_str() - ); - - setDebugLabel(static_cast<VkDevice>(device), &(static_cast<const VkDebugUtilsObjectNameInfoEXT&>(debug))); + + const vk::DebugUtilsObjectNameInfoEXT debug(type, handle, label.c_str()); + + setDebugLabel(static_cast<VkDevice>(device), + &(static_cast<const VkDebugUtilsObjectNameInfoEXT &>(debug))); #endif } - + void Core::setDebugLabel(const BufferHandle &handle, const std::string &label) { if (!handle) { vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle"); return; } - - setDebugObjectLabel( - m_Context.getDevice(), - vk::ObjectType::eBuffer, - uint64_t(static_cast<VkBuffer>( - m_BufferManager->getBuffer(handle) - )), - label - ); - } - + + setDebugObjectLabel(m_Context.getDevice(), vk::ObjectType::eBuffer, + uint64_t(static_cast<VkBuffer>(m_BufferManager->getBuffer(handle))), + label); + } + void Core::setDebugLabel(const PassHandle &handle, const std::string &label) { if (!handle) { vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle"); return; } - - setDebugObjectLabel( - m_Context.getDevice(), - vk::ObjectType::eRenderPass, - uint64_t(static_cast<VkRenderPass>( - m_PassManager->getVkPass(handle) - )), - label - ); - } - + + setDebugObjectLabel(m_Context.getDevice(), vk::ObjectType::eRenderPass, + uint64_t(static_cast<VkRenderPass>(m_PassManager->getVkPass(handle))), + label); + } + void Core::setDebugLabel(const GraphicsPipelineHandle &handle, const std::string &label) { if (!handle) { vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle"); return; } - + setDebugObjectLabel( - m_Context.getDevice(), - vk::ObjectType::ePipeline, - uint64_t(static_cast<VkPipeline>( - m_GraphicsPipelineManager->getVkPipeline(handle) - )), - label - ); - } - + m_Context.getDevice(), vk::ObjectType::ePipeline, + uint64_t(static_cast<VkPipeline>(m_GraphicsPipelineManager->getVkPipeline(handle))), + label); + } + void Core::setDebugLabel(const ComputePipelineHandle &handle, const std::string &label) { if (!handle) { vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle"); return; } - + setDebugObjectLabel( - m_Context.getDevice(), - vk::ObjectType::ePipeline, - uint64_t(static_cast<VkPipeline>( - m_ComputePipelineManager->getVkPipeline(handle) - )), - label - ); - } - + m_Context.getDevice(), vk::ObjectType::ePipeline, + uint64_t(static_cast<VkPipeline>(m_ComputePipelineManager->getVkPipeline(handle))), + label); + } + void Core::setDebugLabel(const DescriptorSetHandle &handle, const std::string &label) { if (!handle) { vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle"); return; } - - setDebugObjectLabel( - m_Context.getDevice(), - vk::ObjectType::eDescriptorSet, - uint64_t(static_cast<VkDescriptorSet>( - m_DescriptorSetManager->getDescriptorSet(handle).vulkanHandle - )), - label - ); - } - + + setDebugObjectLabel(m_Context.getDevice(), vk::ObjectType::eDescriptorSet, + uint64_t(static_cast<VkDescriptorSet>( + m_DescriptorSetManager->getDescriptorSet(handle).vulkanHandle)), + label); + } + void Core::setDebugLabel(const SamplerHandle &handle, const std::string &label) { if (!handle) { vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle"); return; } - + setDebugObjectLabel( - m_Context.getDevice(), - vk::ObjectType::eSampler, - uint64_t(static_cast<VkSampler>( - m_SamplerManager->getVulkanSampler(handle) - )), - label - ); - } - + m_Context.getDevice(), vk::ObjectType::eSampler, + uint64_t(static_cast<VkSampler>(m_SamplerManager->getVulkanSampler(handle))), label); + } + void Core::setDebugLabel(const ImageHandle &handle, const std::string &label) { if (!handle) { vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle"); return; - } else - if (handle.isSwapchainImage()) { + } else if (handle.isSwapchainImage()) { vkcv_log(LogLevel::WARNING, "Can't set debug label to swapchain image"); return; } - - setDebugObjectLabel( - m_Context.getDevice(), - vk::ObjectType::eImage, - uint64_t(static_cast<VkImage>( - m_ImageManager->getVulkanImage(handle) - )), - label - ); - } - + + setDebugObjectLabel(m_Context.getDevice(), vk::ObjectType::eImage, + uint64_t(static_cast<VkImage>(m_ImageManager->getVulkanImage(handle))), + label); + } + void Core::setDebugLabel(const CommandStreamHandle &handle, const std::string &label) { if (!handle) { vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle"); return; } - - setDebugObjectLabel( - m_Context.getDevice(), - vk::ObjectType::eCommandBuffer, - uint64_t(static_cast<VkCommandBuffer>( - m_CommandStreamManager->getStreamCommandBuffer(handle) - )), - label - ); - } - + + setDebugObjectLabel(m_Context.getDevice(), vk::ObjectType::eCommandBuffer, + uint64_t(static_cast<VkCommandBuffer>( + m_CommandStreamManager->getStreamCommandBuffer(handle))), + label); + } + void Core::run(const vkcv::WindowFrameFunction &frame) { auto start = std::chrono::system_clock::now(); double t = 0.0; - + if (!frame) return; - + while (Window::hasOpenWindow()) { vkcv::Window::pollEvents(); - + auto end = std::chrono::system_clock::now(); auto deltatime = std::chrono::duration_cast<std::chrono::microseconds>(end - start); start = end; - + double dt = 0.000001 * static_cast<double>(deltatime.count()); - + for (const auto &window : m_WindowManager->getWindowHandles()) { uint32_t swapchainWidth, swapchainHeight; if (!beginFrame(swapchainWidth, swapchainHeight, window)) { continue; } - + frame(window, t, dt, swapchainWidth, swapchainHeight); endFrame(window); } - + t += dt; } } - + vk::RenderPass Core::getVulkanRenderPass(const PassHandle &handle) const { return m_PassManager->getVkPass(handle); } - + vk::Pipeline Core::getVulkanPipeline(const GraphicsPipelineHandle &handle) const { return m_GraphicsPipelineManager->getVkPipeline(handle); } - + vk::Pipeline Core::getVulkanPipeline(const ComputePipelineHandle &handle) const { return m_ComputePipelineManager->getVkPipeline(handle); } - - vk::DescriptorSetLayout Core::getVulkanDescriptorSetLayout(const DescriptorSetLayoutHandle &handle) const { + + vk::DescriptorSetLayout + Core::getVulkanDescriptorSetLayout(const DescriptorSetLayoutHandle &handle) const { return m_DescriptorSetLayoutManager->getDescriptorSetLayout(handle).vulkanHandle; } - + vk::DescriptorSet Core::getVulkanDescriptorSet(const DescriptorSetHandle &handle) const { return m_DescriptorSetManager->getDescriptorSet(handle).vulkanHandle; } - + vk::Buffer Core::getVulkanBuffer(const BufferHandle &handle) const { return m_BufferManager->getBuffer(handle); } - + vk::Sampler Core::getVulkanSampler(const SamplerHandle &handle) const { return m_SamplerManager->getVulkanSampler(handle); } - + vk::Image Core::getVulkanImage(const ImageHandle &handle) const { return m_ImageManager->getVulkanImage(handle); } - + vk::ImageView Core::getVulkanImageView(const vkcv::ImageHandle &handle) const { return m_ImageManager->getVulkanImageView(handle); } - + vk::DeviceMemory Core::getVulkanDeviceMemory(const BufferHandle &handle) const { return m_BufferManager->getDeviceMemory(handle); } - + vk::DeviceMemory Core::getVulkanDeviceMemory(const ImageHandle &handle) const { return m_ImageManager->getVulkanDeviceMemory(handle); } - -} + +} // namespace vkcv diff --git a/src/vkcv/DescriptorBinding.cpp b/src/vkcv/DescriptorBinding.cpp index 0ed0144e29942630bd3627a2eac086e82a8b3da6..251fe45c80e66ac04745621bba79feed8a14eb97 100644 --- a/src/vkcv/DescriptorBinding.cpp +++ b/src/vkcv/DescriptorBinding.cpp @@ -1,14 +1,13 @@ #include "vkcv/DescriptorBinding.hpp" namespace vkcv { - - bool DescriptorBinding::operator==(const DescriptorBinding &other) const - { - return (this->bindingID == other.bindingID) && - (this->descriptorType == other.descriptorType) && - (this->descriptorCount == other.descriptorCount) && - (this->shaderStages == other.shaderStages) && - (this->variableCount == other.variableCount); - } - -} + + bool DescriptorBinding::operator==(const DescriptorBinding &other) const { + return (this->bindingID == other.bindingID) + && (this->descriptorType == other.descriptorType) + && (this->descriptorCount == other.descriptorCount) + && (this->shaderStages == other.shaderStages) + && (this->variableCount == other.variableCount); + } + +} // namespace vkcv diff --git a/src/vkcv/DescriptorSetLayoutManager.cpp b/src/vkcv/DescriptorSetLayoutManager.cpp index f3122964036e793f1f49f23fd56253e7fc3c9464..14fe4d519f0587d6ef3febf256de83f9f5428f42 100644 --- a/src/vkcv/DescriptorSetLayoutManager.cpp +++ b/src/vkcv/DescriptorSetLayoutManager.cpp @@ -3,107 +3,105 @@ #include "vkcv/Core.hpp" namespace vkcv { - + uint64_t DescriptorSetLayoutManager::getIdFrom(const DescriptorSetLayoutHandle &handle) const { return handle.getId(); } - - DescriptorSetLayoutHandle DescriptorSetLayoutManager::createById(uint64_t id, - const HandleDestroyFunction &destroy) { + + DescriptorSetLayoutHandle + DescriptorSetLayoutManager::createById(uint64_t id, const HandleDestroyFunction &destroy) { return DescriptorSetLayoutHandle(id, destroy); } - + void DescriptorSetLayoutManager::destroyById(uint64_t id) { - auto& layout = getById(id); - + auto &layout = getById(id); + if (layout.layoutUsageCount > 1) { layout.layoutUsageCount--; return; } else { layout.layoutUsageCount = 0; } - - if (layout.vulkanHandle){ + + if (layout.vulkanHandle) { getCore().getContext().getDevice().destroy(layout.vulkanHandle); layout.vulkanHandle = nullptr; } } - + DescriptorSetLayoutManager::DescriptorSetLayoutManager() noexcept : - HandleManager<DescriptorSetLayoutEntry, DescriptorSetLayoutHandle>() {} - + HandleManager<DescriptorSetLayoutEntry, DescriptorSetLayoutHandle>() {} + DescriptorSetLayoutManager::~DescriptorSetLayoutManager() noexcept { for (uint64_t id = 0; id < getCount(); id++) { // Resets the usage count to zero for destruction. getById(id).layoutUsageCount = 0; } - + clear(); } - - DescriptorSetLayoutHandle DescriptorSetLayoutManager::createDescriptorSetLayout(const DescriptorBindings &bindings) { + + DescriptorSetLayoutHandle + DescriptorSetLayoutManager::createDescriptorSetLayout(const DescriptorBindings &bindings) { for (uint64_t id = 0; id < getCount(); id++) { - auto& layout = getById(id); - + auto &layout = getById(id); + if (layout.descriptorBindings.size() != bindings.size()) continue; - + if (layout.descriptorBindings == bindings) { layout.layoutUsageCount++; - return createById(id, [&](uint64_t id) { destroyById(id); }); + return createById(id, [&](uint64_t id) { + destroyById(id); + }); } } - - //create the descriptor set's layout and binding flags by iterating over its bindings + + // create the descriptor set's layout and binding flags by iterating over its bindings std::vector<vk::DescriptorSetLayoutBinding> bindingsVector = {}; std::vector<vk::DescriptorBindingFlags> bindingsFlags = {}; - - for (auto bindingElem : bindings) - { + + for (auto bindingElem : bindings) { DescriptorBinding binding = bindingElem.second; uint32_t bindingID = bindingElem.first; - - bindingsVector.emplace_back( - bindingID, - getVkDescriptorType(binding.descriptorType), - binding.descriptorCount, - getShaderStageFlags(binding.shaderStages), - nullptr - ); - + + bindingsVector.emplace_back(bindingID, getVkDescriptorType(binding.descriptorType), + binding.descriptorCount, + getShaderStageFlags(binding.shaderStages), nullptr); + vk::DescriptorBindingFlags flags; - + if (binding.variableCount) flags |= vk::DescriptorBindingFlagBits::eVariableDescriptorCount; - + if (binding.partialBinding) flags |= vk::DescriptorBindingFlagBits::ePartiallyBound; - + bindingsFlags.push_back(flags); } - - vk::DescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsInfo ( - bindingsFlags.size(), bindingsFlags.data() - ); - - //create the descriptor set's layout from the binding data gathered above + + vk::DescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsInfo(bindingsFlags.size(), + bindingsFlags.data()); + + // create the descriptor set's layout from the binding data gathered above vk::DescriptorSetLayout vulkanHandle; - vk::DescriptorSetLayoutCreateInfo layoutInfo(vk::DescriptorSetLayoutCreateFlags(), bindingsVector); + vk::DescriptorSetLayoutCreateInfo layoutInfo(vk::DescriptorSetLayoutCreateFlags(), + bindingsVector); layoutInfo.setPNext(&bindingFlagsInfo); - - auto result = getCore().getContext().getDevice().createDescriptorSetLayout(&layoutInfo, - nullptr, - &vulkanHandle); + + auto result = getCore().getContext().getDevice().createDescriptorSetLayout( + &layoutInfo, nullptr, &vulkanHandle); if (result != vk::Result::eSuccess) { vkcv_log(LogLevel::ERROR, "Failed to create descriptor set layout"); return DescriptorSetLayoutHandle(); }; - + return add({ vulkanHandle, bindings, 1 }); } - - const DescriptorSetLayoutEntry& DescriptorSetLayoutManager::getDescriptorSetLayout(const DescriptorSetLayoutHandle& handle) const { - return (*this)[handle]; + + const DescriptorSetLayoutEntry &DescriptorSetLayoutManager::getDescriptorSetLayout( + const DescriptorSetLayoutHandle &handle) const { + return (*this) [handle]; } - -} + +} // namespace vkcv diff --git a/src/vkcv/DescriptorSetLayoutManager.hpp b/src/vkcv/DescriptorSetLayoutManager.hpp index 0dd2598c70fdeb6aeb3e9da1adc48b1a480e71c5..3e540e9daa74c533eef0f1fe9788abb1496fa008 100644 --- a/src/vkcv/DescriptorSetLayoutManager.hpp +++ b/src/vkcv/DescriptorSetLayoutManager.hpp @@ -11,7 +11,7 @@ #include "HandleManager.hpp" namespace vkcv { - + /** * @brief Structure to store details about a descriptor set layout. */ @@ -20,19 +20,20 @@ namespace vkcv { DescriptorBindings descriptorBindings; size_t layoutUsageCount; }; - + /** * @brief Class to manage descriptor set layouts. */ - class DescriptorSetLayoutManager : public HandleManager<DescriptorSetLayoutEntry, DescriptorSetLayoutHandle> { + class DescriptorSetLayoutManager : + public HandleManager<DescriptorSetLayoutEntry, DescriptorSetLayoutHandle> { friend class Core; + private: - [[nodiscard]] - uint64_t getIdFrom(const DescriptorSetLayoutHandle& handle) const override; - - [[nodiscard]] - DescriptorSetLayoutHandle createById(uint64_t id, const HandleDestroyFunction& destroy) override; - + [[nodiscard]] uint64_t getIdFrom(const DescriptorSetLayoutHandle &handle) const override; + + [[nodiscard]] DescriptorSetLayoutHandle + createById(uint64_t id, const HandleDestroyFunction &destroy) override; + /** * Destroys and deallocates descriptor set layout represented by a given * descriptor set layout handle id. @@ -40,18 +41,18 @@ namespace vkcv { * @param id Descriptor set layout handle id */ void destroyById(uint64_t id) override; - + public: /** * @brief Constructor of the descriptor set layout manager */ DescriptorSetLayoutManager() noexcept; - + /** * @brief Destructor of the descriptor set layout manager */ ~DescriptorSetLayoutManager() noexcept override; - + /** * @brief Creates a descriptor set layout with given descriptor bindings * or returns a matching handle. @@ -59,12 +60,11 @@ namespace vkcv { * @param[in] bindings Descriptor bindings * @return Handle of descriptor set layout */ - [[nodiscard]] - DescriptorSetLayoutHandle createDescriptorSetLayout(const DescriptorBindings &bindings); - - [[nodiscard]] - const DescriptorSetLayoutEntry& getDescriptorSetLayout(const DescriptorSetLayoutHandle& handle) const; - + [[nodiscard]] DescriptorSetLayoutHandle + createDescriptorSetLayout(const DescriptorBindings &bindings); + + [[nodiscard]] const DescriptorSetLayoutEntry & + getDescriptorSetLayout(const DescriptorSetLayoutHandle &handle) const; }; - -} + +} // namespace vkcv diff --git a/src/vkcv/DescriptorSetManager.cpp b/src/vkcv/DescriptorSetManager.cpp index d7d680d9a3d72d694bd1cafa83c7c4f92bf2825f..e6ac1c22c76373c7773a7c242805e41f628f66c7 100644 --- a/src/vkcv/DescriptorSetManager.cpp +++ b/src/vkcv/DescriptorSetManager.cpp @@ -3,129 +3,127 @@ #include "vkcv/Core.hpp" namespace vkcv { - - bool DescriptorSetManager::init(Core &core, DescriptorSetLayoutManager& descriptorSetLayoutManager) { + + bool DescriptorSetManager::init(Core &core, + DescriptorSetLayoutManager &descriptorSetLayoutManager) { if (!HandleManager<DescriptorSetEntry, DescriptorSetHandle>::init(core)) { return false; } - + m_DescriptorSetLayoutManager = &descriptorSetLayoutManager; - + /** - * Allocate the set size for the descriptor pools, namely 1000 units of each descriptor type below. - * Finally, create an initial pool. - */ + * Allocate the set size for the descriptor pools, namely 1000 units of each descriptor type + * below. Finally, create an initial pool. + */ m_PoolSizes = { - vk::DescriptorPoolSize(vk::DescriptorType::eSampler, 1000), - vk::DescriptorPoolSize(vk::DescriptorType::eSampledImage, 1000), - vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, 1000), - vk::DescriptorPoolSize(vk::DescriptorType::eStorageBuffer, 1000), - vk::DescriptorPoolSize(vk::DescriptorType::eUniformBufferDynamic, 1000), - vk::DescriptorPoolSize(vk::DescriptorType::eStorageBufferDynamic, 1000), // for RTX - vk::DescriptorPoolSize(vk::DescriptorType::eAccelerationStructureKHR, 1000) // for RTX + vk::DescriptorPoolSize(vk::DescriptorType::eSampler, 1000), + vk::DescriptorPoolSize(vk::DescriptorType::eSampledImage, 1000), + vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, 1000), + vk::DescriptorPoolSize(vk::DescriptorType::eStorageBuffer, 1000), + vk::DescriptorPoolSize(vk::DescriptorType::eUniformBufferDynamic, 1000), + vk::DescriptorPoolSize(vk::DescriptorType::eStorageBufferDynamic, 1000), // for RTX + vk::DescriptorPoolSize(vk::DescriptorType::eAccelerationStructureKHR, 1000) // for RTX }; - + m_PoolInfo = vk::DescriptorPoolCreateInfo( - vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, - 1000, - static_cast<uint32_t>(m_PoolSizes.size()), - m_PoolSizes.data() - ); - + vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1000, + static_cast<uint32_t>(m_PoolSizes.size()), m_PoolSizes.data()); + return allocateDescriptorPool(); } - + uint64_t DescriptorSetManager::getIdFrom(const DescriptorSetHandle &handle) const { return handle.getId(); } - + DescriptorSetHandle DescriptorSetManager::createById(uint64_t id, const HandleDestroyFunction &destroy) { return DescriptorSetHandle(id, destroy); } - + void DescriptorSetManager::destroyById(uint64_t id) { - auto& set = getById(id); - + auto &set = getById(id); + if (set.vulkanHandle) { - getCore().getContext().getDevice().freeDescriptorSets(m_Pools[set.poolIndex], 1, + getCore().getContext().getDevice().freeDescriptorSets(m_Pools [set.poolIndex], 1, &(set.vulkanHandle)); set.setLayoutHandle = DescriptorSetLayoutHandle(); set.vulkanHandle = nullptr; } } - + vk::DescriptorPool DescriptorSetManager::allocateDescriptorPool() { vk::DescriptorPool pool; - if (getCore().getContext().getDevice().createDescriptorPool(&m_PoolInfo, - nullptr, - &pool) != vk::Result::eSuccess) { + if (getCore().getContext().getDevice().createDescriptorPool(&m_PoolInfo, nullptr, &pool) + != vk::Result::eSuccess) { vkcv_log(LogLevel::WARNING, "Failed to allocate descriptor pool"); pool = nullptr; } else { m_Pools.push_back(pool); } - + return pool; } - + DescriptorSetManager::DescriptorSetManager() noexcept : - HandleManager<DescriptorSetEntry, DescriptorSetHandle>() { - - } - + HandleManager<DescriptorSetEntry, DescriptorSetHandle>() {} + DescriptorSetManager::~DescriptorSetManager() noexcept { clear(); - + for (const auto &pool : m_Pools) { if (pool) { getCore().getContext().getDevice().destroy(pool); } } } - - DescriptorSetHandle DescriptorSetManager::createDescriptorSet(const DescriptorSetLayoutHandle &layout) { - //create and allocate the set based on the layout provided - const auto& setLayout = m_DescriptorSetLayoutManager->getDescriptorSetLayout(layout); - + + DescriptorSetHandle + DescriptorSetManager::createDescriptorSet(const DescriptorSetLayoutHandle &layout) { + // create and allocate the set based on the layout provided + const auto &setLayout = m_DescriptorSetLayoutManager->getDescriptorSetLayout(layout); + vk::DescriptorSet vulkanHandle; vk::DescriptorSetAllocateInfo allocInfo(m_Pools.back(), 1, &setLayout.vulkanHandle); - + uint32_t sumVariableDescriptorCounts = 0; for (auto bindingElem : setLayout.descriptorBindings) { auto binding = bindingElem.second; - - if(binding.variableCount) + + if (binding.variableCount) sumVariableDescriptorCounts += binding.descriptorCount; } - - vk::DescriptorSetVariableDescriptorCountAllocateInfo variableAllocInfo(1, &sumVariableDescriptorCounts); - + + vk::DescriptorSetVariableDescriptorCountAllocateInfo variableAllocInfo( + 1, &sumVariableDescriptorCounts); + if (sumVariableDescriptorCounts > 0) { allocInfo.setPNext(&variableAllocInfo); } - - auto result = getCore().getContext().getDevice().allocateDescriptorSets(&allocInfo, &vulkanHandle); - if(result != vk::Result::eSuccess) - { - //create a new descriptor pool if the previous one ran out of memory + + auto result = + getCore().getContext().getDevice().allocateDescriptorSets(&allocInfo, &vulkanHandle); + if (result != vk::Result::eSuccess) { + // create a new descriptor pool if the previous one ran out of memory if (result == vk::Result::eErrorOutOfPoolMemory) { allocateDescriptorPool(); allocInfo.setDescriptorPool(m_Pools.back()); - result = getCore().getContext().getDevice().allocateDescriptorSets(&allocInfo, &vulkanHandle); + result = getCore().getContext().getDevice().allocateDescriptorSets(&allocInfo, + &vulkanHandle); } - + if (result != vk::Result::eSuccess) { vkcv_log(LogLevel::ERROR, "Failed to create descriptor set (%s)", vk::to_string(result).c_str()); return {}; } }; - + size_t poolIndex = (m_Pools.size() - 1); return add({ vulkanHandle, layout, poolIndex }); } - + /** * @brief Structure to store details to write to a descriptor set. */ @@ -138,210 +136,167 @@ namespace vkcv { uint32_t descriptorCount; vk::DescriptorType type; }; - - void DescriptorSetManager::writeDescriptorSet(const DescriptorSetHandle &handle, - const DescriptorWrites &writes, - const ImageManager &imageManager, - const BufferManager &bufferManager, - const SamplerManager &samplerManager) { - auto& set = (*this)[handle]; - + + void DescriptorSetManager::writeDescriptorSet(const DescriptorSetHandle &handle, + const DescriptorWrites &writes, + const ImageManager &imageManager, + const BufferManager &bufferManager, + const SamplerManager &samplerManager) { + auto &set = (*this) [handle]; + std::vector<vk::DescriptorImageInfo> imageInfos; std::vector<vk::DescriptorBufferInfo> bufferInfos; - + std::vector<vk::WriteDescriptorSetAccelerationStructureKHR> writeStructures; - + std::vector<WriteDescriptorSetInfo> writeInfos; - - for (const auto& write : writes.getSampledImageWrites()) { - const vk::ImageLayout layout = (write.useGeneralLayout? - vk::ImageLayout::eGeneral : - vk::ImageLayout::eShaderReadOnlyOptimal - ); - + + for (const auto &write : writes.getSampledImageWrites()) { + const vk::ImageLayout layout = + (write.useGeneralLayout ? vk::ImageLayout::eGeneral : + vk::ImageLayout::eShaderReadOnlyOptimal); + for (uint32_t i = 0; i < write.mipCount; i++) { const vk::DescriptorImageInfo imageInfo( - nullptr, - imageManager.getVulkanImageView( - write.image, - write.mipLevel + i, - write.arrayView - ), - layout - ); - + nullptr, + imageManager.getVulkanImageView(write.image, write.mipLevel + i, + write.arrayView), + layout); + imageInfos.push_back(imageInfo); } - + WriteDescriptorSetInfo vulkanWrite = { - imageInfos.size() + 1 - write.mipCount, - 0, - 0, - write.binding, - write.arrayIndex, - write.mipCount, - vk::DescriptorType::eSampledImage, + imageInfos.size() + 1 - write.mipCount, + 0, + 0, + write.binding, + write.arrayIndex, + write.mipCount, + vk::DescriptorType::eSampledImage, }; - + writeInfos.push_back(vulkanWrite); } - - for (const auto& write : writes.getStorageImageWrites()) { + + for (const auto &write : writes.getStorageImageWrites()) { for (uint32_t i = 0; i < write.mipCount; i++) { const vk::DescriptorImageInfo imageInfo( - nullptr, - imageManager.getVulkanImageView( - write.image, - write.mipLevel + i, - write.arrayView - ), - vk::ImageLayout::eGeneral - ); - + nullptr, + imageManager.getVulkanImageView(write.image, write.mipLevel + i, + write.arrayView), + vk::ImageLayout::eGeneral); + imageInfos.push_back(imageInfo); } - + WriteDescriptorSetInfo vulkanWrite = { - imageInfos.size() + 1 - write.mipCount, - 0, - 0, - write.binding, - 0, - write.mipCount, - vk::DescriptorType::eStorageImage + imageInfos.size() + 1 - write.mipCount, 0, 0, write.binding, 0, write.mipCount, + vk::DescriptorType::eStorageImage }; - + writeInfos.push_back(vulkanWrite); } - - for (const auto& write : writes.getUniformBufferWrites()) { + + for (const auto &write : writes.getUniformBufferWrites()) { const size_t size = bufferManager.getBufferSize(write.buffer); const uint32_t offset = std::clamp<uint32_t>(write.offset, 0, size); - + const vk::DescriptorBufferInfo bufferInfo( - bufferManager.getBuffer(write.buffer), - offset, - write.size == 0? size : std::min<uint32_t>( - write.size, size - offset - ) - ); - + bufferManager.getBuffer(write.buffer), offset, + write.size == 0 ? size : std::min<uint32_t>(write.size, size - offset)); + bufferInfos.push_back(bufferInfo); - - WriteDescriptorSetInfo vulkanWrite = { - 0, - bufferInfos.size(), - 0, - write.binding, - 0, - 1, - write.dynamic? - vk::DescriptorType::eUniformBufferDynamic : - vk::DescriptorType::eUniformBuffer - }; - + + WriteDescriptorSetInfo vulkanWrite = { 0, + bufferInfos.size(), + 0, + write.binding, + 0, + 1, + write.dynamic ? + vk::DescriptorType::eUniformBufferDynamic : + vk::DescriptorType::eUniformBuffer }; + writeInfos.push_back(vulkanWrite); } - - for (const auto& write : writes.getStorageBufferWrites()) { + + for (const auto &write : writes.getStorageBufferWrites()) { const size_t size = bufferManager.getBufferSize(write.buffer); const uint32_t offset = std::clamp<uint32_t>(write.offset, 0, size); - + const vk::DescriptorBufferInfo bufferInfo( - bufferManager.getBuffer(write.buffer), - offset, - write.size == 0? size : std::min<uint32_t>( - write.size, size - offset - ) - ); - + bufferManager.getBuffer(write.buffer), offset, + write.size == 0 ? size : std::min<uint32_t>(write.size, size - offset)); + bufferInfos.push_back(bufferInfo); - - WriteDescriptorSetInfo vulkanWrite = { - 0, - bufferInfos.size(), - 0, - write.binding, - 0, - 1, - write.dynamic? - vk::DescriptorType::eStorageBufferDynamic : - vk::DescriptorType::eStorageBuffer - }; - + + WriteDescriptorSetInfo vulkanWrite = { 0, + bufferInfos.size(), + 0, + write.binding, + 0, + 1, + write.dynamic ? + vk::DescriptorType::eStorageBufferDynamic : + vk::DescriptorType::eStorageBuffer }; + writeInfos.push_back(vulkanWrite); } - - for (const auto& write : writes.getSamplerWrites()) { - const vk::Sampler& sampler = samplerManager.getVulkanSampler(write.sampler); - - const vk::DescriptorImageInfo imageInfo( - sampler, - nullptr, - vk::ImageLayout::eGeneral - ); - + + for (const auto &write : writes.getSamplerWrites()) { + const vk::Sampler &sampler = samplerManager.getVulkanSampler(write.sampler); + + const vk::DescriptorImageInfo imageInfo(sampler, nullptr, vk::ImageLayout::eGeneral); + imageInfos.push_back(imageInfo); - + WriteDescriptorSetInfo vulkanWrite = { - imageInfos.size(), - 0, - 0, - write.binding, - 0, - 1, - vk::DescriptorType::eSampler + imageInfos.size(), 0, 0, write.binding, 0, 1, vk::DescriptorType::eSampler }; - + writeInfos.push_back(vulkanWrite); } - - for (const auto& write : writes.getAccelerationWrites()) { - const vk::WriteDescriptorSetAccelerationStructureKHR structureWrite ( - write.structures.size(), - write.structures.data() - ); - + + for (const auto &write : writes.getAccelerationWrites()) { + const vk::WriteDescriptorSetAccelerationStructureKHR structureWrite( + write.structures.size(), write.structures.data()); + writeStructures.push_back(structureWrite); - - WriteDescriptorSetInfo vulkanWrite = { - 0, - 0, - writeStructures.size(), - write.binding, - 0, - 1, - vk::DescriptorType::eAccelerationStructureKHR - }; - + + WriteDescriptorSetInfo vulkanWrite = { 0, + 0, + writeStructures.size(), + write.binding, + 0, + 1, + vk::DescriptorType::eAccelerationStructureKHR }; + writeInfos.push_back(vulkanWrite); } - + std::vector<vk::WriteDescriptorSet> vulkanWrites; - - for (const auto& write : writeInfos) { - vk::WriteDescriptorSet vulkanWrite ( - set.vulkanHandle, - write.binding, - write.arrayElementIndex, - write.descriptorCount, - write.type, - (write.imageInfoIndex > 0? &(imageInfos[write.imageInfoIndex - 1]) : nullptr), - (write.bufferInfoIndex > 0? &(bufferInfos[write.bufferInfoIndex - 1]) : nullptr) - ); - + + for (const auto &write : writeInfos) { + vk::WriteDescriptorSet vulkanWrite( + set.vulkanHandle, write.binding, write.arrayElementIndex, write.descriptorCount, + write.type, + (write.imageInfoIndex > 0 ? &(imageInfos [write.imageInfoIndex - 1]) : nullptr), + (write.bufferInfoIndex > 0 ? &(bufferInfos [write.bufferInfoIndex - 1]) : nullptr)); + if (write.structureIndex > 0) { - vulkanWrite.setPNext(&(writeStructures[write.structureIndex - 1])); + vulkanWrite.setPNext(&(writeStructures [write.structureIndex - 1])); } - + vulkanWrites.push_back(vulkanWrite); } - + getCore().getContext().getDevice().updateDescriptorSets(vulkanWrites, nullptr); } - - const DescriptorSetEntry& DescriptorSetManager::getDescriptorSet(const DescriptorSetHandle& handle) const { - return (*this)[handle]; + + const DescriptorSetEntry & + DescriptorSetManager::getDescriptorSet(const DescriptorSetHandle &handle) const { + return (*this) [handle]; } - -} + +} // namespace vkcv diff --git a/src/vkcv/DescriptorSetManager.hpp b/src/vkcv/DescriptorSetManager.hpp index f3c13aff26832888b2f43e33a03feb1ace77fb93..ae3f879ce4ef9d3b16f687bc237060c98591bd65 100644 --- a/src/vkcv/DescriptorSetManager.hpp +++ b/src/vkcv/DescriptorSetManager.hpp @@ -9,14 +9,14 @@ #include "vkcv/DescriptorBinding.hpp" #include "vkcv/DescriptorWrites.hpp" -#include "HandleManager.hpp" #include "BufferManager.hpp" #include "DescriptorSetLayoutManager.hpp" +#include "HandleManager.hpp" #include "ImageManager.hpp" #include "SamplerManager.hpp" namespace vkcv { - + /** * @brief Structure to store details about a descriptor set. */ @@ -25,27 +25,27 @@ namespace vkcv { DescriptorSetLayoutHandle setLayoutHandle; size_t poolIndex; }; - + /** * @brief Class to manage descriptor sets. */ class DescriptorSetManager : public HandleManager<DescriptorSetEntry, DescriptorSetHandle> { friend class Core; + private: DescriptorSetLayoutManager* m_DescriptorSetLayoutManager; - - std::vector<vk::DescriptorPool> m_Pools; + + std::vector<vk::DescriptorPool> m_Pools; std::vector<vk::DescriptorPoolSize> m_PoolSizes; vk::DescriptorPoolCreateInfo m_PoolInfo; - - bool init(Core& core, DescriptorSetLayoutManager& descriptorSetLayoutManager); - - [[nodiscard]] - uint64_t getIdFrom(const DescriptorSetHandle& handle) const override; - - [[nodiscard]] - DescriptorSetHandle createById(uint64_t id, const HandleDestroyFunction& destroy) override; - + + bool init(Core &core, DescriptorSetLayoutManager &descriptorSetLayoutManager); + + [[nodiscard]] uint64_t getIdFrom(const DescriptorSetHandle &handle) const override; + + [[nodiscard]] DescriptorSetHandle createById(uint64_t id, + const HandleDestroyFunction &destroy) override; + /** * Destroys and deallocates descriptor set represented by a given * descriptor set handle id. @@ -53,7 +53,7 @@ namespace vkcv { * @param id Descriptor set handle id */ void destroyById(uint64_t id) override; - + /** * @brief Creates a descriptor pool based on the poolSizes and poolInfo defined in the * constructor is called initially in the constructor and then every time the pool runs @@ -62,27 +62,27 @@ namespace vkcv { * @return a DescriptorPool object */ vk::DescriptorPool allocateDescriptorPool(); - + public: /** * @brief Constructor of the descriptor set manager */ DescriptorSetManager() noexcept; - + /** * @brief Destructor of the descriptor set manager */ ~DescriptorSetManager() noexcept override; - + /** * @brief Creates a descriptor set using a given descriptor set layout. * * @param[in] layout Handle of descriptor set layout * @return Handle of descriptor set */ - [[nodiscard]] - DescriptorSetHandle createDescriptorSet(const DescriptorSetLayoutHandle &layout); - + [[nodiscard]] DescriptorSetHandle + createDescriptorSet(const DescriptorSetLayoutHandle &layout); + /** * @brief Writes to a descriptor set using writes and all required managers. * @@ -92,15 +92,13 @@ namespace vkcv { * @param[in] bufferManager Buffer manager * @param[in] samplerManager Sampler manager */ - void writeDescriptorSet(const DescriptorSetHandle &handle, - const DescriptorWrites &writes, + void writeDescriptorSet(const DescriptorSetHandle &handle, const DescriptorWrites &writes, const ImageManager &imageManager, const BufferManager &bufferManager, const SamplerManager &samplerManager); - - [[nodiscard]] - const DescriptorSetEntry& getDescriptorSet(const DescriptorSetHandle& handle) const; - + + [[nodiscard]] const DescriptorSetEntry & + getDescriptorSet(const DescriptorSetHandle &handle) const; }; - -} + +} // namespace vkcv diff --git a/src/vkcv/DescriptorSetUsage.cpp b/src/vkcv/DescriptorSetUsage.cpp index 4d1ab2ec752dde1047fd736fd6e300bdb586b238..70fc7811791e02d57cb3a4de3d1c2f75db6e9b3a 100644 --- a/src/vkcv/DescriptorSetUsage.cpp +++ b/src/vkcv/DescriptorSetUsage.cpp @@ -2,11 +2,11 @@ #include "vkcv/DescriptorSetUsage.hpp" namespace vkcv { - + DescriptorSetUsage useDescriptorSet(uint32_t location, const DescriptorSetHandle &descriptorSet, const std::vector<uint32_t> &dynamicOffsets) { - DescriptorSetUsage usage (location, descriptorSet, dynamicOffsets); + DescriptorSetUsage usage(location, descriptorSet, dynamicOffsets); return usage; } - -} + +} // namespace vkcv diff --git a/src/vkcv/DescriptorWrites.cpp b/src/vkcv/DescriptorWrites.cpp index 4f9c50ea1ac4628659b18decab6573b73fbdcb38..54db0de3c5c02082d775330d6931960e309f4ba8 100644 --- a/src/vkcv/DescriptorWrites.cpp +++ b/src/vkcv/DescriptorWrites.cpp @@ -2,95 +2,75 @@ #include "vkcv/DescriptorWrites.hpp" namespace vkcv { - - DescriptorWrites &DescriptorWrites::writeSampledImage(uint32_t binding, - ImageHandle image, - uint32_t mipLevel, - bool useGeneralLayout, - uint32_t arrayIndex, - uint32_t mipCount, + + DescriptorWrites &DescriptorWrites::writeSampledImage(uint32_t binding, ImageHandle image, + uint32_t mipLevel, bool useGeneralLayout, + uint32_t arrayIndex, uint32_t mipCount, bool arrayView) { - m_sampledImageWrites.emplace_back( - binding, - image, - mipLevel, - useGeneralLayout, - arrayIndex, - mipCount, - arrayView - ); - + m_sampledImageWrites.emplace_back(binding, image, mipLevel, useGeneralLayout, arrayIndex, + mipCount, arrayView); + return *this; } - - DescriptorWrites &DescriptorWrites::writeStorageImage(uint32_t binding, - ImageHandle image, - uint32_t mipLevel, - uint32_t mipCount, + + DescriptorWrites &DescriptorWrites::writeStorageImage(uint32_t binding, ImageHandle image, + uint32_t mipLevel, uint32_t mipCount, bool arrayView) { - m_storageImageWrites.emplace_back( - binding, - image, - mipLevel, - mipCount, - arrayView - ); - + m_storageImageWrites.emplace_back(binding, image, mipLevel, mipCount, arrayView); + return *this; } - - DescriptorWrites &DescriptorWrites::writeUniformBuffer(uint32_t binding, - BufferHandle buffer, - bool dynamic, - uint32_t offset, + + DescriptorWrites &DescriptorWrites::writeUniformBuffer(uint32_t binding, BufferHandle buffer, + bool dynamic, uint32_t offset, uint32_t size) { m_uniformBufferWrites.emplace_back(binding, buffer, dynamic, offset, size); return *this; } - - DescriptorWrites &DescriptorWrites::writeStorageBuffer(uint32_t binding, - BufferHandle buffer, - bool dynamic, - uint32_t offset, + + DescriptorWrites &DescriptorWrites::writeStorageBuffer(uint32_t binding, BufferHandle buffer, + bool dynamic, uint32_t offset, uint32_t size) { m_storageBufferWrites.emplace_back(binding, buffer, dynamic, offset, size); return *this; } - - DescriptorWrites &DescriptorWrites::writeSampler(uint32_t binding, - SamplerHandle sampler) { + + DescriptorWrites &DescriptorWrites::writeSampler(uint32_t binding, SamplerHandle sampler) { m_samplerWrites.emplace_back(binding, sampler); return *this; } - - DescriptorWrites &DescriptorWrites::writeAcceleration(uint32_t binding, - const std::vector<vk::AccelerationStructureKHR> &structures) { + + DescriptorWrites &DescriptorWrites::writeAcceleration( + uint32_t binding, const std::vector<vk::AccelerationStructureKHR> &structures) { m_accelerationWrites.emplace_back(binding, structures); return *this; } - - const std::vector<SampledImageDescriptorWrite> &DescriptorWrites::getSampledImageWrites() const { + + const std::vector<SampledImageDescriptorWrite> & + DescriptorWrites::getSampledImageWrites() const { return m_sampledImageWrites; } - - const std::vector<StorageImageDescriptorWrite> &DescriptorWrites::getStorageImageWrites() const { + + const std::vector<StorageImageDescriptorWrite> & + DescriptorWrites::getStorageImageWrites() const { return m_storageImageWrites; } - + const std::vector<BufferDescriptorWrite> &DescriptorWrites::getUniformBufferWrites() const { return m_uniformBufferWrites; } - + const std::vector<BufferDescriptorWrite> &DescriptorWrites::getStorageBufferWrites() const { return m_storageBufferWrites; } - + const std::vector<SamplerDescriptorWrite> &DescriptorWrites::getSamplerWrites() const { return m_samplerWrites; } - - const std::vector<AccelerationDescriptorWrite> &DescriptorWrites::getAccelerationWrites() const { + + const std::vector<AccelerationDescriptorWrite> & + DescriptorWrites::getAccelerationWrites() const { return m_accelerationWrites; } - -} + +} // namespace vkcv diff --git a/src/vkcv/DispatchSize.cpp b/src/vkcv/DispatchSize.cpp index bf34d2de9668fb90a61208cce9f10abe57a64682..eb58f2477ac6dfa9fa8db15a3d134698f596ff32 100644 --- a/src/vkcv/DispatchSize.cpp +++ b/src/vkcv/DispatchSize.cpp @@ -5,61 +5,55 @@ #include <cmath> namespace vkcv { - - DispatchSize::DispatchSize(uint32_t count) - : DispatchSize(count, 1, 1) {} - - DispatchSize::DispatchSize(uint32_t dimensionX, uint32_t dimentionY, uint32_t dimensionZ) - : m_Dispatch({ dimensionX, dimentionY, dimensionZ }) { + + DispatchSize::DispatchSize(uint32_t count) : DispatchSize(count, 1, 1) {} + + DispatchSize::DispatchSize(uint32_t dimensionX, uint32_t dimentionY, uint32_t dimensionZ) : + m_Dispatch({ dimensionX, dimentionY, dimensionZ }) { check(); } - - const uint32_t *DispatchSize::data() const { + + const uint32_t* DispatchSize::data() const { return m_Dispatch.data(); } - + uint32_t DispatchSize::operator[](size_t index) const { return m_Dispatch.at(index); } - + uint32_t DispatchSize::x() const { - return m_Dispatch[0]; + return m_Dispatch [0]; } - + uint32_t DispatchSize::y() const { - return m_Dispatch[1]; + return m_Dispatch [1]; } - + uint32_t DispatchSize::z() const { - return m_Dispatch[2]; + return m_Dispatch [2]; } - + bool DispatchSize::check() const { const uint32_t dimensionX = x(); const uint32_t dimensionY = y(); const uint32_t dimensionZ = z(); - + if ((dimensionX <= 0) || (dimensionY <= 0) || (dimensionZ <= 0)) { - vkcv_log( - LogLevel::WARNING, - "Dispatch size invalid: x = %u, y = %u, z = %u", - dimensionX, - dimensionY, - dimensionZ - ); - + vkcv_log(LogLevel::WARNING, "Dispatch size invalid: x = %u, y = %u, z = %u", dimensionX, + dimensionY, dimensionZ); + return false; } else { return true; } } - + DispatchSize dispatchInvocations(DispatchSize globalInvocations, DispatchSize groupSize) { const uint32_t dimensionX = std::ceil(1.0f * globalInvocations.x() / groupSize.x()); const uint32_t dimensionY = std::ceil(1.0f * globalInvocations.y() / groupSize.y()); const uint32_t dimensionZ = std::ceil(1.0f * globalInvocations.z() / groupSize.z()); - + return DispatchSize(dimensionX, dimensionY, dimensionZ); } - -} + +} // namespace vkcv diff --git a/src/vkcv/Downsampler.cpp b/src/vkcv/Downsampler.cpp index a857eec3f12af6fca2d05d598c357988ffce5114..961ade2944618cd1c28f214a61eb4487a2915cf3 100644 --- a/src/vkcv/Downsampler.cpp +++ b/src/vkcv/Downsampler.cpp @@ -2,8 +2,7 @@ #include "vkcv/Downsampler.hpp" namespace vkcv { - - Downsampler::Downsampler(Core& core) - : m_core(core) {} - -} + + Downsampler::Downsampler(Core &core) : m_core(core) {} + +} // namespace vkcv diff --git a/src/vkcv/Drawcall.cpp b/src/vkcv/Drawcall.cpp index 657481eb4648602e81f554292abaeec4a70c509d..b34f81a2059033d0441af2e53612f3685d3c1d11 100644 --- a/src/vkcv/Drawcall.cpp +++ b/src/vkcv/Drawcall.cpp @@ -6,55 +6,49 @@ #include "vkcv/Drawcall.hpp" namespace vkcv { - + const std::vector<DescriptorSetUsage> &Drawcall::getDescriptorSetUsages() const { return m_usages; } - + void Drawcall::useDescriptorSet(uint32_t location, const DescriptorSetHandle &descriptorSet, - const std::vector<uint32_t>& dynamicOffsets) { + const std::vector<uint32_t> &dynamicOffsets) { m_usages.emplace_back(location, descriptorSet, dynamicOffsets); } - - InstanceDrawcall::InstanceDrawcall(const VertexData &vertexData, - uint32_t instanceCount) - : Drawcall(), - m_vertexData(vertexData), - m_instanceCount(instanceCount) {} - + + InstanceDrawcall::InstanceDrawcall(const VertexData &vertexData, uint32_t instanceCount) : + Drawcall(), m_vertexData(vertexData), m_instanceCount(instanceCount) {} + const VertexData &InstanceDrawcall::getVertexData() const { return m_vertexData; } - + uint32_t InstanceDrawcall::getInstanceCount() const { return m_instanceCount; } - + IndirectDrawcall::IndirectDrawcall(const BufferHandle &indirectDrawBuffer, - const VertexData &vertexData, - uint32_t drawCount) - : Drawcall(), - m_indirectDrawBuffer(indirectDrawBuffer), - m_vertexData(vertexData), - m_drawCount(drawCount) {} - + const VertexData &vertexData, uint32_t drawCount) : + Drawcall(), + m_indirectDrawBuffer(indirectDrawBuffer), m_vertexData(vertexData), m_drawCount(drawCount) { + } + BufferHandle IndirectDrawcall::getIndirectDrawBuffer() const { return m_indirectDrawBuffer; } - + const VertexData &IndirectDrawcall::getVertexData() const { return m_vertexData; } - + uint32_t IndirectDrawcall::getDrawCount() const { return m_drawCount; } - - TaskDrawcall::TaskDrawcall(uint32_t taskCount) - : Drawcall(), m_taskCount(taskCount) {} - + + TaskDrawcall::TaskDrawcall(uint32_t taskCount) : Drawcall(), m_taskCount(taskCount) {} + uint32_t TaskDrawcall::getTaskCount() const { return m_taskCount; } - -} + +} // namespace vkcv diff --git a/src/vkcv/FeatureManager.cpp b/src/vkcv/FeatureManager.cpp index 502b07971bf0e20a3f02d94506a55ab0dcfcd5cf..12503a321b4bd7d11e2e453e87d7a8901f968555 100644 --- a/src/vkcv/FeatureManager.cpp +++ b/src/vkcv/FeatureManager.cpp @@ -9,32 +9,36 @@ #endif namespace vkcv { - + #ifdef _MSVC_LANG #define typeof(var) std::decay<decltype((var))>::type #endif - -#define vkcv_check_init_features2(type)\ -type supported; \ -vk::PhysicalDeviceFeatures2 query; \ -query.setPNext(&supported); \ -m_physicalDevice.getFeatures2(&query) - -#define vkcv_check_feature(attribute) { \ - const char *f = reinterpret_cast<const char*>(&(features)); \ - const char *s = reinterpret_cast<const char*>(&(supported)); \ - const vk::Bool32* fb = reinterpret_cast<const vk::Bool32*>(f + offsetof(typeof((features)), attribute)); \ - const vk::Bool32* sb = reinterpret_cast<const vk::Bool32*>(s + offsetof(typeof((features)), attribute)); \ - if ((*fb) && (!*sb)) { \ - vkcv_log(((required)? LogLevel::ERROR : LogLevel::WARNING), \ - "Feature '" #attribute "' is not supported"); \ - return false; \ - } \ -} - - bool FeatureManager::checkSupport(const vk::PhysicalDeviceFeatures &features, bool required) const { - const auto& supported = m_physicalDevice.getFeatures(); - + +#define vkcv_check_init_features2(type) \ + type supported; \ + vk::PhysicalDeviceFeatures2 query; \ + query.setPNext(&supported); \ + m_physicalDevice.getFeatures2(&query) + +#define vkcv_check_feature(attribute) \ + { \ + const char* f = reinterpret_cast<const char*>(&(features)); \ + const char* s = reinterpret_cast<const char*>(&(supported)); \ + const vk::Bool32* fb = \ + reinterpret_cast<const vk::Bool32*>(f + offsetof(typeof((features)), attribute)); \ + const vk::Bool32* sb = \ + reinterpret_cast<const vk::Bool32*>(s + offsetof(typeof((features)), attribute)); \ + if ((*fb) && (!*sb)) { \ + vkcv_log(((required) ? LogLevel::ERROR : LogLevel::WARNING), \ + "Feature '" #attribute "' is not supported"); \ + return false; \ + } \ + } + + bool FeatureManager::checkSupport(const vk::PhysicalDeviceFeatures &features, + bool required) const { + const auto &supported = m_physicalDevice.getFeatures(); + vkcv_check_feature(alphaToOne); vkcv_check_feature(depthBiasClamp); vkcv_check_feature(depthBounds); @@ -90,47 +94,49 @@ m_physicalDevice.getFeatures2(&query) vkcv_check_feature(variableMultisampleRate); vkcv_check_feature(vertexPipelineStoresAndAtomics); vkcv_check_feature(wideLines); - vkcv_check_feature(multiDrawIndirect); - + vkcv_check_feature(multiDrawIndirect); + return true; } - - bool FeatureManager::checkSupport(const vk::PhysicalDevice16BitStorageFeatures &features, bool required) const { + + bool FeatureManager::checkSupport(const vk::PhysicalDevice16BitStorageFeatures &features, + bool required) const { vkcv_check_init_features2(vk::PhysicalDevice16BitStorageFeatures); - + vkcv_check_feature(storageBuffer16BitAccess); vkcv_check_feature(storageInputOutput16); vkcv_check_feature(storagePushConstant16); vkcv_check_feature(uniformAndStorageBuffer16BitAccess); - + return true; } - - bool FeatureManager::checkSupport(const vk::PhysicalDevice8BitStorageFeatures &features, bool required) const { + + bool FeatureManager::checkSupport(const vk::PhysicalDevice8BitStorageFeatures &features, + bool required) const { vkcv_check_init_features2(vk::PhysicalDevice8BitStorageFeatures); - + vkcv_check_feature(storageBuffer8BitAccess); vkcv_check_feature(storagePushConstant8); vkcv_check_feature(uniformAndStorageBuffer8BitAccess); - + return true; } - + bool FeatureManager::checkSupport(const vk::PhysicalDeviceBufferDeviceAddressFeatures &features, bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceBufferDeviceAddressFeatures); - + vkcv_check_feature(bufferDeviceAddress); vkcv_check_feature(bufferDeviceAddressCaptureReplay); vkcv_check_feature(bufferDeviceAddressMultiDevice); - + return true; } - + bool FeatureManager::checkSupport(const vk::PhysicalDeviceDescriptorIndexingFeatures &features, bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceDescriptorIndexingFeatures); - + vkcv_check_feature(shaderInputAttachmentArrayDynamicIndexing); vkcv_check_feature(shaderInputAttachmentArrayNonUniformIndexing); vkcv_check_feature(shaderSampledImageArrayNonUniformIndexing); @@ -151,154 +157,163 @@ m_physicalDevice.getFeatures2(&query) vkcv_check_feature(descriptorBindingUpdateUnusedWhilePending); vkcv_check_feature(descriptorBindingVariableDescriptorCount); vkcv_check_feature(runtimeDescriptorArray); - + return true; } - + bool FeatureManager::checkSupport(const vk::PhysicalDeviceHostQueryResetFeatures &features, bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceHostQueryResetFeatures); - + vkcv_check_feature(hostQueryReset); return true; } - - bool FeatureManager::checkSupport(const vk::PhysicalDeviceImagelessFramebufferFeatures &features, - bool required) const { + + bool + FeatureManager::checkSupport(const vk::PhysicalDeviceImagelessFramebufferFeatures &features, + bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceImagelessFramebufferFeatures); - + vkcv_check_feature(imagelessFramebuffer); - + return true; } - + bool FeatureManager::checkSupport(const vk::PhysicalDeviceMultiviewFeatures &features, bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceMultiviewFeatures); - + vkcv_check_feature(multiview); vkcv_check_feature(multiviewGeometryShader); vkcv_check_feature(multiviewTessellationShader); - + return true; } - + bool FeatureManager::checkSupport(const vk::PhysicalDeviceProtectedMemoryFeatures &features, bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceProtectedMemoryFeatures); - + vkcv_check_feature(protectedMemory); - + return true; } - - bool FeatureManager::checkSupport(const vk::PhysicalDeviceSamplerYcbcrConversionFeatures &features, - bool required) const { + + bool + FeatureManager::checkSupport(const vk::PhysicalDeviceSamplerYcbcrConversionFeatures &features, + bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceSamplerYcbcrConversionFeatures); vkcv_check_feature(samplerYcbcrConversion); - + return true; } - + bool FeatureManager::checkSupport(const vk::PhysicalDeviceScalarBlockLayoutFeatures &features, bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceScalarBlockLayoutFeatures); - + vkcv_check_feature(scalarBlockLayout); - + return true; } - - bool FeatureManager::checkSupport(const vk::PhysicalDeviceSeparateDepthStencilLayoutsFeatures &features, - bool required) const { + + bool FeatureManager::checkSupport( + const vk::PhysicalDeviceSeparateDepthStencilLayoutsFeatures &features, + bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceSeparateDepthStencilLayoutsFeatures); - + vkcv_check_feature(separateDepthStencilLayouts); - + return true; } - + bool FeatureManager::checkSupport(const vk::PhysicalDeviceShaderAtomicInt64Features &features, bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceShaderAtomicInt64Features); - + vkcv_check_feature(shaderBufferInt64Atomics); vkcv_check_feature(shaderSharedInt64Atomics); - + return true; } - - bool FeatureManager::checkSupport(const vk::PhysicalDeviceShaderFloat16Int8Features &features, bool required) const { + + bool FeatureManager::checkSupport(const vk::PhysicalDeviceShaderFloat16Int8Features &features, + bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceShaderFloat16Int8Features); - + vkcv_check_feature(shaderFloat16); vkcv_check_feature(shaderInt8); - + return true; } - - bool FeatureManager::checkSupport(const vk::PhysicalDeviceShaderSubgroupExtendedTypesFeatures &features, - bool required) const { + + bool FeatureManager::checkSupport( + const vk::PhysicalDeviceShaderSubgroupExtendedTypesFeatures &features, + bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceShaderSubgroupExtendedTypesFeatures); - + vkcv_check_feature(shaderSubgroupExtendedTypes); - + return true; } - + bool FeatureManager::checkSupport(const vk::PhysicalDeviceTimelineSemaphoreFeatures &features, bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceTimelineSemaphoreFeatures); - + vkcv_check_feature(timelineSemaphore); - + return true; } - - bool FeatureManager::checkSupport(const vk::PhysicalDeviceUniformBufferStandardLayoutFeatures &features, - bool required) const { + + bool FeatureManager::checkSupport( + const vk::PhysicalDeviceUniformBufferStandardLayoutFeatures &features, + bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceUniformBufferStandardLayoutFeatures); - + vkcv_check_feature(uniformBufferStandardLayout); return true; } - + bool FeatureManager::checkSupport(const vk::PhysicalDeviceVariablePointersFeatures &features, bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceVariablePointersFeatures); - + vkcv_check_feature(variablePointers); vkcv_check_feature(variablePointersStorageBuffer); - + return true; } - + bool FeatureManager::checkSupport(const vk::PhysicalDeviceVulkanMemoryModelFeatures &features, bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceVulkanMemoryModelFeatures); - + vkcv_check_feature(vulkanMemoryModel); vkcv_check_feature(vulkanMemoryModelDeviceScope); vkcv_check_feature(vulkanMemoryModelAvailabilityVisibilityChains); - + return true; } - - bool FeatureManager::checkSupport(const vk::PhysicalDeviceMeshShaderFeaturesNV &features, bool required) const { + + bool FeatureManager::checkSupport(const vk::PhysicalDeviceMeshShaderFeaturesNV &features, + bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceMeshShaderFeaturesNV); - + vkcv_check_feature(taskShader); vkcv_check_feature(meshShader); - + return true; } - - bool FeatureManager::checkSupport(const vk::PhysicalDeviceShaderAtomicFloatFeaturesEXT& features, bool required) const { + + bool + FeatureManager::checkSupport(const vk::PhysicalDeviceShaderAtomicFloatFeaturesEXT &features, + bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceShaderAtomicFloatFeaturesEXT); - + vkcv_check_feature(shaderBufferFloat32Atomics); vkcv_check_feature(shaderBufferFloat32AtomicAdd); vkcv_check_feature(shaderBufferFloat64Atomics); @@ -311,13 +326,15 @@ m_physicalDevice.getFeatures2(&query) vkcv_check_feature(shaderImageFloat32AtomicAdd); vkcv_check_feature(sparseImageFloat32Atomics); vkcv_check_feature(sparseImageFloat32AtomicAdd); - + return true; } - - bool FeatureManager::checkSupport(const vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT& features, bool required) const { + + bool + FeatureManager::checkSupport(const vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT &features, + bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT); - + vkcv_check_feature(shaderBufferFloat16Atomics); vkcv_check_feature(shaderBufferFloat16AtomicAdd); vkcv_check_feature(shaderBufferFloat16AtomicMinMax); @@ -330,110 +347,117 @@ m_physicalDevice.getFeatures2(&query) vkcv_check_feature(shaderSharedFloat64AtomicMinMax); vkcv_check_feature(shaderImageFloat32AtomicMinMax); vkcv_check_feature(sparseImageFloat32AtomicMinMax); - + return true; } - - bool FeatureManager::checkSupport(const vk::PhysicalDeviceVulkan12Features &features, bool required) const { - vkcv_check_init_features2(vk::PhysicalDeviceVulkan12Features); - - vkcv_check_feature(samplerMirrorClampToEdge); - vkcv_check_feature(drawIndirectCount); - vkcv_check_feature(storageBuffer8BitAccess); - vkcv_check_feature(uniformAndStorageBuffer8BitAccess); - vkcv_check_feature(storagePushConstant8); - vkcv_check_feature(shaderBufferInt64Atomics); - vkcv_check_feature(shaderSharedInt64Atomics); - vkcv_check_feature(shaderFloat16); - vkcv_check_feature(shaderInt8); - vkcv_check_feature(descriptorIndexing); - vkcv_check_feature(shaderInputAttachmentArrayDynamicIndexing); - vkcv_check_feature(shaderUniformTexelBufferArrayDynamicIndexing); - vkcv_check_feature(shaderStorageTexelBufferArrayDynamicIndexing); - vkcv_check_feature(shaderUniformBufferArrayNonUniformIndexing); - vkcv_check_feature(shaderSampledImageArrayNonUniformIndexing); - vkcv_check_feature(shaderStorageBufferArrayNonUniformIndexing); - vkcv_check_feature(shaderStorageImageArrayNonUniformIndexing); - vkcv_check_feature(shaderInputAttachmentArrayNonUniformIndexing); - vkcv_check_feature(shaderUniformTexelBufferArrayNonUniformIndexing); - vkcv_check_feature(shaderStorageTexelBufferArrayNonUniformIndexing); - vkcv_check_feature(descriptorBindingUniformBufferUpdateAfterBind); - vkcv_check_feature(descriptorBindingSampledImageUpdateAfterBind); - vkcv_check_feature(descriptorBindingStorageImageUpdateAfterBind); - vkcv_check_feature(descriptorBindingStorageBufferUpdateAfterBind); - vkcv_check_feature(descriptorBindingUniformTexelBufferUpdateAfterBind); - vkcv_check_feature(descriptorBindingStorageTexelBufferUpdateAfterBind); - vkcv_check_feature(descriptorBindingUpdateUnusedWhilePending); - vkcv_check_feature(descriptorBindingPartiallyBound); - vkcv_check_feature(descriptorBindingVariableDescriptorCount); - vkcv_check_feature(runtimeDescriptorArray); - vkcv_check_feature(samplerFilterMinmax); - vkcv_check_feature(scalarBlockLayout); - vkcv_check_feature(imagelessFramebuffer); - vkcv_check_feature(uniformBufferStandardLayout); - vkcv_check_feature(shaderSubgroupExtendedTypes); - vkcv_check_feature(separateDepthStencilLayouts); - vkcv_check_feature(hostQueryReset); - vkcv_check_feature(timelineSemaphore); - vkcv_check_feature(bufferDeviceAddress); - vkcv_check_feature(bufferDeviceAddressCaptureReplay); - vkcv_check_feature(bufferDeviceAddressMultiDevice); - vkcv_check_feature(vulkanMemoryModel); - vkcv_check_feature(vulkanMemoryModelDeviceScope); - vkcv_check_feature(vulkanMemoryModelAvailabilityVisibilityChains); - vkcv_check_feature(shaderOutputViewportIndex); - vkcv_check_feature(shaderOutputLayer); - vkcv_check_feature(subgroupBroadcastDynamicId); - - return true; - } - - bool FeatureManager::checkSupport(const vk::PhysicalDeviceVulkan11Features &features, bool required) const { - vkcv_check_init_features2(vk::PhysicalDeviceVulkan11Features); - - vkcv_check_feature(multiview); - vkcv_check_feature(multiviewGeometryShader); - vkcv_check_feature(multiviewTessellationShader); - vkcv_check_feature(protectedMemory); - vkcv_check_feature(samplerYcbcrConversion); - vkcv_check_feature(shaderDrawParameters); - vkcv_check_feature(storageBuffer16BitAccess); - vkcv_check_feature(storageInputOutput16); - vkcv_check_feature(storagePushConstant16); - vkcv_check_feature(uniformAndStorageBuffer16BitAccess); - vkcv_check_feature(variablePointers); - vkcv_check_feature(variablePointersStorageBuffer); - - return true; - } - - bool FeatureManager::checkSupport(const vk::PhysicalDeviceAccelerationStructureFeaturesKHR &features, bool required) const { - vkcv_check_init_features2(vk::PhysicalDeviceAccelerationStructureFeaturesKHR); - - vkcv_check_feature(accelerationStructure); - vkcv_check_feature(accelerationStructureCaptureReplay); - vkcv_check_feature(accelerationStructureIndirectBuild); - vkcv_check_feature(accelerationStructureHostCommands); - vkcv_check_feature(descriptorBindingAccelerationStructureUpdateAfterBind); - - return true; - } - - bool FeatureManager::checkSupport(const vk::PhysicalDeviceRayTracingPipelineFeaturesKHR &features, bool required) const { - vkcv_check_init_features2(vk::PhysicalDeviceRayTracingPipelineFeaturesKHR); - - vkcv_check_feature(rayTracingPipeline); - vkcv_check_feature(rayTracingPipelineShaderGroupHandleCaptureReplay); - vkcv_check_feature(rayTracingPipelineShaderGroupHandleCaptureReplayMixed); - vkcv_check_feature(rayTracingPipelineTraceRaysIndirect); - vkcv_check_feature(rayTraversalPrimitiveCulling); - - return true; - } - - bool FeatureManager::checkSupport(const vk::PhysicalDeviceVulkan13Features &features, bool required) const { + + bool FeatureManager::checkSupport(const vk::PhysicalDeviceVulkan12Features &features, + bool required) const { + vkcv_check_init_features2(vk::PhysicalDeviceVulkan12Features); + + vkcv_check_feature(samplerMirrorClampToEdge); + vkcv_check_feature(drawIndirectCount); + vkcv_check_feature(storageBuffer8BitAccess); + vkcv_check_feature(uniformAndStorageBuffer8BitAccess); + vkcv_check_feature(storagePushConstant8); + vkcv_check_feature(shaderBufferInt64Atomics); + vkcv_check_feature(shaderSharedInt64Atomics); + vkcv_check_feature(shaderFloat16); + vkcv_check_feature(shaderInt8); + vkcv_check_feature(descriptorIndexing); + vkcv_check_feature(shaderInputAttachmentArrayDynamicIndexing); + vkcv_check_feature(shaderUniformTexelBufferArrayDynamicIndexing); + vkcv_check_feature(shaderStorageTexelBufferArrayDynamicIndexing); + vkcv_check_feature(shaderUniformBufferArrayNonUniformIndexing); + vkcv_check_feature(shaderSampledImageArrayNonUniformIndexing); + vkcv_check_feature(shaderStorageBufferArrayNonUniformIndexing); + vkcv_check_feature(shaderStorageImageArrayNonUniformIndexing); + vkcv_check_feature(shaderInputAttachmentArrayNonUniformIndexing); + vkcv_check_feature(shaderUniformTexelBufferArrayNonUniformIndexing); + vkcv_check_feature(shaderStorageTexelBufferArrayNonUniformIndexing); + vkcv_check_feature(descriptorBindingUniformBufferUpdateAfterBind); + vkcv_check_feature(descriptorBindingSampledImageUpdateAfterBind); + vkcv_check_feature(descriptorBindingStorageImageUpdateAfterBind); + vkcv_check_feature(descriptorBindingStorageBufferUpdateAfterBind); + vkcv_check_feature(descriptorBindingUniformTexelBufferUpdateAfterBind); + vkcv_check_feature(descriptorBindingStorageTexelBufferUpdateAfterBind); + vkcv_check_feature(descriptorBindingUpdateUnusedWhilePending); + vkcv_check_feature(descriptorBindingPartiallyBound); + vkcv_check_feature(descriptorBindingVariableDescriptorCount); + vkcv_check_feature(runtimeDescriptorArray); + vkcv_check_feature(samplerFilterMinmax); + vkcv_check_feature(scalarBlockLayout); + vkcv_check_feature(imagelessFramebuffer); + vkcv_check_feature(uniformBufferStandardLayout); + vkcv_check_feature(shaderSubgroupExtendedTypes); + vkcv_check_feature(separateDepthStencilLayouts); + vkcv_check_feature(hostQueryReset); + vkcv_check_feature(timelineSemaphore); + vkcv_check_feature(bufferDeviceAddress); + vkcv_check_feature(bufferDeviceAddressCaptureReplay); + vkcv_check_feature(bufferDeviceAddressMultiDevice); + vkcv_check_feature(vulkanMemoryModel); + vkcv_check_feature(vulkanMemoryModelDeviceScope); + vkcv_check_feature(vulkanMemoryModelAvailabilityVisibilityChains); + vkcv_check_feature(shaderOutputViewportIndex); + vkcv_check_feature(shaderOutputLayer); + vkcv_check_feature(subgroupBroadcastDynamicId); + + return true; + } + + bool FeatureManager::checkSupport(const vk::PhysicalDeviceVulkan11Features &features, + bool required) const { + vkcv_check_init_features2(vk::PhysicalDeviceVulkan11Features); + + vkcv_check_feature(multiview); + vkcv_check_feature(multiviewGeometryShader); + vkcv_check_feature(multiviewTessellationShader); + vkcv_check_feature(protectedMemory); + vkcv_check_feature(samplerYcbcrConversion); + vkcv_check_feature(shaderDrawParameters); + vkcv_check_feature(storageBuffer16BitAccess); + vkcv_check_feature(storageInputOutput16); + vkcv_check_feature(storagePushConstant16); + vkcv_check_feature(uniformAndStorageBuffer16BitAccess); + vkcv_check_feature(variablePointers); + vkcv_check_feature(variablePointersStorageBuffer); + + return true; + } + + bool + FeatureManager::checkSupport(const vk::PhysicalDeviceAccelerationStructureFeaturesKHR &features, + bool required) const { + vkcv_check_init_features2(vk::PhysicalDeviceAccelerationStructureFeaturesKHR); + + vkcv_check_feature(accelerationStructure); + vkcv_check_feature(accelerationStructureCaptureReplay); + vkcv_check_feature(accelerationStructureIndirectBuild); + vkcv_check_feature(accelerationStructureHostCommands); + vkcv_check_feature(descriptorBindingAccelerationStructureUpdateAfterBind); + + return true; + } + + bool + FeatureManager::checkSupport(const vk::PhysicalDeviceRayTracingPipelineFeaturesKHR &features, + bool required) const { + vkcv_check_init_features2(vk::PhysicalDeviceRayTracingPipelineFeaturesKHR); + + vkcv_check_feature(rayTracingPipeline); + vkcv_check_feature(rayTracingPipelineShaderGroupHandleCaptureReplay); + vkcv_check_feature(rayTracingPipelineShaderGroupHandleCaptureReplayMixed); + vkcv_check_feature(rayTracingPipelineTraceRaysIndirect); + vkcv_check_feature(rayTraversalPrimitiveCulling); + + return true; + } + + bool FeatureManager::checkSupport(const vk::PhysicalDeviceVulkan13Features &features, + bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceVulkan13Features); - + vkcv_check_feature(robustImageAccess); vkcv_check_feature(inlineUniformBlock); vkcv_check_feature(descriptorBindingInlineUniformBlockUpdateAfterBind); @@ -449,154 +473,151 @@ m_physicalDevice.getFeatures2(&query) vkcv_check_feature(dynamicRendering); vkcv_check_feature(shaderIntegerDotProduct); vkcv_check_feature(maintenance4); - + return true; } - + vk::BaseOutStructure* FeatureManager::findFeatureStructure(vk::StructureType type) const { - for (auto& base : m_featuresExtensions) { + for (auto &base : m_featuresExtensions) { if (base->sType == type) { return base; } } - + return nullptr; } - + const char* strclone(const char* str) { if (!str) { return nullptr; } - + const size_t length = strlen(str) + 1; - + if (length <= 1) { return nullptr; } - - char* clone = new char[length]; + + char* clone = new char [length]; strcpy(clone, str); return clone; } - + FeatureManager::FeatureManager(vk::PhysicalDevice &physicalDevice) : - m_physicalDevice(physicalDevice), - m_supportedExtensions(), - m_activeExtensions(), - m_featuresBase(), - m_featuresExtensions() { - for (const auto& extension : m_physicalDevice.enumerateDeviceExtensionProperties()) { + m_physicalDevice(physicalDevice), m_supportedExtensions(), m_activeExtensions(), + m_featuresBase(), m_featuresExtensions() { + for (const auto &extension : m_physicalDevice.enumerateDeviceExtensionProperties()) { const char* clone = strclone(extension.extensionName); - + if (clone) { m_supportedExtensions.push_back(clone); } } } - + FeatureManager::FeatureManager(FeatureManager &&other) noexcept : - m_physicalDevice(other.m_physicalDevice), - m_supportedExtensions(std::move(other.m_supportedExtensions)), - m_activeExtensions(std::move(other.m_activeExtensions)), - m_featuresBase(other.m_featuresBase), - m_featuresExtensions(std::move(other.m_featuresExtensions)) { + m_physicalDevice(other.m_physicalDevice), + m_supportedExtensions(std::move(other.m_supportedExtensions)), + m_activeExtensions(std::move(other.m_activeExtensions)), + m_featuresBase(other.m_featuresBase), + m_featuresExtensions(std::move(other.m_featuresExtensions)) { other.m_featuresExtensions.clear(); other.m_activeExtensions.clear(); other.m_supportedExtensions.clear(); } - + FeatureManager::~FeatureManager() { - for (auto& features : m_featuresExtensions) { + for (auto &features : m_featuresExtensions) { delete features; } - - for (auto& extension : m_activeExtensions) { - delete[] extension; + + for (auto &extension : m_activeExtensions) { + delete [] extension; } - - for (auto& extension : m_supportedExtensions) { - delete[] extension; + + for (auto &extension : m_supportedExtensions) { + delete [] extension; } } - + FeatureManager &FeatureManager::operator=(FeatureManager &&other) noexcept { m_physicalDevice = other.m_physicalDevice; m_supportedExtensions = std::move(other.m_supportedExtensions); m_activeExtensions = std::move(other.m_activeExtensions); m_featuresBase = other.m_featuresBase; m_featuresExtensions = std::move(other.m_featuresExtensions); - + other.m_featuresExtensions.clear(); other.m_activeExtensions.clear(); other.m_supportedExtensions.clear(); - + return *this; } - - bool FeatureManager::isExtensionSupported(const std::string& extension) const { - for (const auto& supported : m_supportedExtensions) { + + bool FeatureManager::isExtensionSupported(const std::string &extension) const { + for (const auto &supported : m_supportedExtensions) { if (0 == strcmp(supported, extension.c_str())) { return true; } } - + return false; } - - bool FeatureManager::useExtension(const std::string& extension, bool required) { + + 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.c_str()); return false; } - + if (!isExtensionSupported(extension)) { - vkcv_log((required? LogLevel::ERROR : LogLevel::WARNING), "Extension '%s' is not supported", - extension.c_str()); - - delete[] clone; + vkcv_log((required ? LogLevel::ERROR : LogLevel::WARNING), + "Extension '%s' is not supported", extension.c_str()); + + delete [] clone; if (required) { vkcv_log_throw_error("Required extension is not supported!"); } - + return false; } - + m_activeExtensions.push_back(clone); return true; } - - bool FeatureManager::isExtensionActive(const std::string& extension) const { - for (const auto& supported : m_activeExtensions) { + + bool FeatureManager::isExtensionActive(const std::string &extension) const { + for (const auto &supported : m_activeExtensions) { if (0 == strcmp(supported, extension.c_str())) { return true; } } - + return false; } - - const std::vector<const char*>& FeatureManager::getActiveExtensions() const { + + const std::vector<const char*> &FeatureManager::getActiveExtensions() const { return m_activeExtensions; } - - bool FeatureManager::useFeatures(const std::function<void(vk::PhysicalDeviceFeatures &)> &featureFunction, - bool required) { + + bool FeatureManager::useFeatures( + const std::function<void(vk::PhysicalDeviceFeatures &)> &featureFunction, bool required) { vk::PhysicalDeviceFeatures features = m_featuresBase.features; - + featureFunction(features); - + if (!checkSupport(features, required)) { return false; } - + m_featuresBase.features = features; return true; } - - const vk::PhysicalDeviceFeatures2& FeatureManager::getFeatures() const { + + const vk::PhysicalDeviceFeatures2 &FeatureManager::getFeatures() const { return m_featuresBase; } - -} + +} // namespace vkcv diff --git a/src/vkcv/Features.cpp b/src/vkcv/Features.cpp index 60616685f67084b6875ce14bf09f524a9127688f..fcfdd7b9435b7f9ab9ad230fa8d77a9a0d66b80e 100644 --- a/src/vkcv/Features.cpp +++ b/src/vkcv/Features.cpp @@ -2,22 +2,23 @@ #include "vkcv/Features.hpp" namespace vkcv { - - Features::Features(const std::initializer_list<std::string>& list) : m_features() { - for (const auto& extension : list) { + + Features::Features(const std::initializer_list<std::string> &list) : m_features() { + for (const auto &extension : list) { requireExtension(extension); } } - - void Features::requireExtension(const std::string& extension) { - m_features.emplace_back([extension](FeatureManager& featureManager) { + + 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) { + + 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 { @@ -25,22 +26,24 @@ namespace vkcv { } }); } - - void Features::requireFeature(const std::function<void(vk::PhysicalDeviceFeatures &)> &featureFunction) { - m_features.emplace_back([featureFunction](FeatureManager& featureManager) { + + 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) { + + 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) { + + 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 { @@ -48,15 +51,16 @@ namespace vkcv { } }); } - - void Features::tryFeature(const std::function<void(vk::PhysicalDeviceFeatures &)> &featureFunction) { - m_features.emplace_back([featureFunction](FeatureManager& featureManager) { + + 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 { + + const std::vector<Feature> &Features::getList() const { return m_features; } -} +} // namespace vkcv diff --git a/src/vkcv/File.cpp b/src/vkcv/File.cpp index 871dc06611903d5fb5cc8a9e3d53233510125826..f840fdb06850d6943864ef119883996a461a13fe 100644 --- a/src/vkcv/File.cpp +++ b/src/vkcv/File.cpp @@ -12,49 +12,47 @@ #include "vkcv/Logger.hpp" namespace vkcv { - + std::filesystem::path generateTemporaryFilePath() { std::filesystem::path tmp = generateTemporaryDirectoryPath(); - + if (std::filesystem::is_directory(tmp)) { return std::filesystem::path(tmp.string() + "W"); // add W for Wambo } else { return tmp; } } - + std::filesystem::path generateTemporaryDirectoryPath() { std::error_code code; auto tmp = std::filesystem::temp_directory_path(code); - + if (tmp.empty()) { tmp = std::filesystem::current_path(); } - + char name [16] = "vkcv_tmp_XXXXXX"; - + #ifdef _WIN32 int err = _mktemp_s(name, 16); - + if (err != 0) { vkcv_log(LogLevel::ERROR, "Temporary file path could not be generated"); return ""; } #else int fd = mkstemp(name); // creates a file locally - + if (fd == -1) { vkcv_log(LogLevel::ERROR, "Temporary file path could not be generated"); return ""; } - + close(fd); remove(name); // removes the local file again #endif - + return tmp / name; } - - - -} + +} // namespace vkcv diff --git a/src/vkcv/GraphicsPipelineConfig.cpp b/src/vkcv/GraphicsPipelineConfig.cpp index 37e86240e782460fe317c91e71c1ddcb5880fff0..987cd3a74492a2b4f1428fa75e546ce7ffcba8b9 100644 --- a/src/vkcv/GraphicsPipelineConfig.cpp +++ b/src/vkcv/GraphicsPipelineConfig.cpp @@ -2,120 +2,116 @@ #include "vkcv/GraphicsPipelineConfig.hpp" namespace vkcv { - - GraphicsPipelineConfig::GraphicsPipelineConfig() - : PipelineConfig(), - m_PassHandle(), - m_VertexLayout(), - m_Width(std::numeric_limits<uint32_t>::max()), - m_Height(std::numeric_limits<uint32_t>::max()) {} - - GraphicsPipelineConfig::GraphicsPipelineConfig(const ShaderProgram &program, - const PassHandle &pass, - const VertexLayout &vertexLayout, - const std::vector<DescriptorSetLayoutHandle> &layouts) - : PipelineConfig(program, layouts), - m_PassHandle(pass), - m_VertexLayout(vertexLayout), - m_Width(std::numeric_limits<uint32_t>::max()), - m_Height(std::numeric_limits<uint32_t>::max()) {} - + + GraphicsPipelineConfig::GraphicsPipelineConfig() : + PipelineConfig(), m_PassHandle(), m_VertexLayout(), + m_Width(std::numeric_limits<uint32_t>::max()), + m_Height(std::numeric_limits<uint32_t>::max()) {} + + GraphicsPipelineConfig::GraphicsPipelineConfig( + const ShaderProgram &program, const PassHandle &pass, const VertexLayout &vertexLayout, + const std::vector<DescriptorSetLayoutHandle> &layouts) : + PipelineConfig(program, layouts), + m_PassHandle(pass), m_VertexLayout(vertexLayout), + m_Width(std::numeric_limits<uint32_t>::max()), + m_Height(std::numeric_limits<uint32_t>::max()) {} + const PassHandle &GraphicsPipelineConfig::getPass() const { return m_PassHandle; } - + const VertexLayout &GraphicsPipelineConfig::getVertexLayout() const { return m_VertexLayout; } - + uint32_t GraphicsPipelineConfig::getWidth() const { return m_Width; } - + uint32_t GraphicsPipelineConfig::getHeight() const { return m_Height; } - + void GraphicsPipelineConfig::setResolution(uint32_t width, uint32_t height) { m_Width = width; m_Height = height; } - + bool GraphicsPipelineConfig::isViewportDynamic() const { - return ((m_Width == std::numeric_limits<uint32_t>::max()) && - (m_Height == std::numeric_limits<uint32_t>::max())); + return ((m_Width == std::numeric_limits<uint32_t>::max()) + && (m_Height == std::numeric_limits<uint32_t>::max())); } - + bool GraphicsPipelineConfig::isUsingConservativeRasterization() const { return m_UseConservativeRasterization; } - + void GraphicsPipelineConfig::setUsingConservativeRasterization(bool conservativeRasterization) { m_UseConservativeRasterization = conservativeRasterization; } - + PrimitiveTopology GraphicsPipelineConfig::getPrimitiveTopology() const { return m_PrimitiveTopology; } - + void GraphicsPipelineConfig::setPrimitiveTopology(PrimitiveTopology primitiveTopology) { m_PrimitiveTopology = primitiveTopology; } - + BlendMode GraphicsPipelineConfig::getBlendMode() const { return m_blendMode; } - + void GraphicsPipelineConfig::setBlendMode(BlendMode blendMode) { m_blendMode = blendMode; } - + bool GraphicsPipelineConfig::isDepthClampingEnabled() const { return m_EnableDepthClamping; } - + void GraphicsPipelineConfig::setDepthClampingEnabled(bool depthClamping) { m_EnableDepthClamping = depthClamping; } - + CullMode GraphicsPipelineConfig::getCulling() const { return m_Culling; } - + void GraphicsPipelineConfig::setCulling(CullMode cullMode) { m_Culling = cullMode; } - + DepthTest GraphicsPipelineConfig::getDepthTest() const { return m_DepthTest; } - + void GraphicsPipelineConfig::setDepthTest(DepthTest depthTest) { m_DepthTest = depthTest; } - + bool GraphicsPipelineConfig::isWritingDepth() const { return m_DepthWrite; } - + void GraphicsPipelineConfig::setWritingDepth(bool writingDepth) { m_DepthWrite = writingDepth; } - + bool GraphicsPipelineConfig::isWritingAlphaToCoverage() const { return m_AlphaToCoverage; } - + void GraphicsPipelineConfig::setWritingAlphaToCoverage(bool alphaToCoverage) { m_AlphaToCoverage = alphaToCoverage; } - + uint32_t GraphicsPipelineConfig::getTesselationControlPoints() const { return m_TessellationControlPoints; } - + void GraphicsPipelineConfig::setTesselationControlPoints(uint32_t tessellationControlPoints) { m_TessellationControlPoints = tessellationControlPoints; } - -} + +} // namespace vkcv diff --git a/src/vkcv/GraphicsPipelineManager.cpp b/src/vkcv/GraphicsPipelineManager.cpp index 2a495fa18950f7b48e2b082853d1b31b5a7cf9c9..255ce48e5b0fd3fa2b8a455699e18d2d0e9f756f 100644 --- a/src/vkcv/GraphicsPipelineManager.cpp +++ b/src/vkcv/GraphicsPipelineManager.cpp @@ -6,256 +6,239 @@ #include "vkcv/Multisampling.hpp" namespace vkcv { - + uint64_t GraphicsPipelineManager::getIdFrom(const GraphicsPipelineHandle &handle) const { return handle.getId(); } - - GraphicsPipelineHandle GraphicsPipelineManager::createById(uint64_t id, const HandleDestroyFunction &destroy) { + + GraphicsPipelineHandle + GraphicsPipelineManager::createById(uint64_t id, const HandleDestroyFunction &destroy) { return GraphicsPipelineHandle(id, destroy); } - + void GraphicsPipelineManager::destroyById(uint64_t id) { - auto& pipeline = getById(id); - + auto &pipeline = getById(id); + if (pipeline.m_handle) { getCore().getContext().getDevice().destroy(pipeline.m_handle); pipeline.m_handle = nullptr; } - + if (pipeline.m_layout) { getCore().getContext().getDevice().destroy(pipeline.m_layout); pipeline.m_layout = nullptr; } } - + GraphicsPipelineManager::GraphicsPipelineManager() noexcept : HandleManager<GraphicsPipelineEntry, GraphicsPipelineHandle>() {} - + GraphicsPipelineManager::~GraphicsPipelineManager() noexcept { clear(); - } - - // currently assuming default 32 bit formats, no lower precision or normalized variants supported - vk::Format vertexFormatToVulkanFormat(const VertexAttachmentFormat format) { - switch (format) { - case VertexAttachmentFormat::FLOAT: - return vk::Format::eR32Sfloat; - case VertexAttachmentFormat::FLOAT2: - return vk::Format::eR32G32Sfloat; - case VertexAttachmentFormat::FLOAT3: - return vk::Format::eR32G32B32Sfloat; - case VertexAttachmentFormat::FLOAT4: - return vk::Format::eR32G32B32A32Sfloat; - case VertexAttachmentFormat::INT: - return vk::Format::eR32Sint; - case VertexAttachmentFormat::INT2: - return vk::Format::eR32G32Sint; - case VertexAttachmentFormat::INT3: - return vk::Format::eR32G32B32Sint; - case VertexAttachmentFormat::INT4: - return vk::Format::eR32G32B32A32Sint; - default: - vkcv_log(LogLevel::WARNING, "Unknown vertex format"); - return vk::Format::eUndefined; - } - } - - vk::PrimitiveTopology primitiveTopologyToVulkanPrimitiveTopology(const PrimitiveTopology topology) { - switch (topology) { - case(PrimitiveTopology::PointList): - return vk::PrimitiveTopology::ePointList; - case(PrimitiveTopology::LineList): - return vk::PrimitiveTopology::eLineList; - case(PrimitiveTopology::TriangleList): - return vk::PrimitiveTopology::eTriangleList; - case(PrimitiveTopology::PatchList): - return vk::PrimitiveTopology::ePatchList; - default: - vkcv_log(LogLevel::ERROR, "Unknown primitive topology type"); - return vk::PrimitiveTopology::eTriangleList; - } - } - - vk::CompareOp depthTestToVkCompareOp(DepthTest depthTest) { - switch (depthTest) { - case(DepthTest::None): - return vk::CompareOp::eAlways; - case(DepthTest::Less): - return vk::CompareOp::eLess; - case(DepthTest::LessEqual): - return vk::CompareOp::eLessOrEqual; - case(DepthTest::Greater): - return vk::CompareOp::eGreater; - case(DepthTest::GreatherEqual): - return vk::CompareOp::eGreaterOrEqual; - case(DepthTest::Equal): - return vk::CompareOp::eEqual; - default: - vkcv_log(LogLevel::ERROR, "Unknown depth test enum"); - return vk::CompareOp::eAlways; - } - } - - vk::ShaderStageFlagBits shaderStageToVkShaderStage(ShaderStage stage) { - switch (stage) { - case ShaderStage::VERTEX: - return vk::ShaderStageFlagBits::eVertex; - case ShaderStage::FRAGMENT: - return vk::ShaderStageFlagBits::eFragment; - case ShaderStage::GEOMETRY: - return vk::ShaderStageFlagBits::eGeometry; - case ShaderStage::TESS_CONTROL: - return vk::ShaderStageFlagBits::eTessellationControl; - case ShaderStage::TESS_EVAL: - return vk::ShaderStageFlagBits::eTessellationEvaluation; - case ShaderStage::COMPUTE: - return vk::ShaderStageFlagBits::eCompute; - case ShaderStage::TASK: - return vk::ShaderStageFlagBits::eTaskNV; - case ShaderStage::MESH: - return vk::ShaderStageFlagBits::eMeshNV; - default: - vkcv_log(LogLevel::ERROR, "Unknown shader stage"); - return vk::ShaderStageFlagBits::eAll; - } - } - - bool createPipelineShaderStageCreateInfo( - const ShaderProgram& shaderProgram, - ShaderStage stage, - vk::Device device, - vk::PipelineShaderStageCreateInfo* outCreateInfo) { - - assert(outCreateInfo); - std::vector<uint32_t> code = shaderProgram.getShaderBinary(stage); - vk::ShaderModuleCreateInfo vertexModuleInfo({}, code.size() * sizeof(uint32_t), code.data()); - vk::ShaderModule shaderModule; - if (device.createShaderModule(&vertexModuleInfo, nullptr, &shaderModule) != vk::Result::eSuccess) - return false; - - const static auto entryName = "main"; - - *outCreateInfo = vk::PipelineShaderStageCreateInfo( - {}, - shaderStageToVkShaderStage(stage), - shaderModule, - entryName, - nullptr); - return true; - } - + } + + // currently assuming default 32 bit formats, no lower precision or normalized variants + // supported + vk::Format vertexFormatToVulkanFormat(const VertexAttachmentFormat format) { + switch (format) { + case VertexAttachmentFormat::FLOAT: + return vk::Format::eR32Sfloat; + case VertexAttachmentFormat::FLOAT2: + return vk::Format::eR32G32Sfloat; + case VertexAttachmentFormat::FLOAT3: + return vk::Format::eR32G32B32Sfloat; + case VertexAttachmentFormat::FLOAT4: + return vk::Format::eR32G32B32A32Sfloat; + case VertexAttachmentFormat::INT: + return vk::Format::eR32Sint; + case VertexAttachmentFormat::INT2: + return vk::Format::eR32G32Sint; + case VertexAttachmentFormat::INT3: + return vk::Format::eR32G32B32Sint; + case VertexAttachmentFormat::INT4: + return vk::Format::eR32G32B32A32Sint; + default: + vkcv_log(LogLevel::WARNING, "Unknown vertex format"); + return vk::Format::eUndefined; + } + } + + vk::PrimitiveTopology + primitiveTopologyToVulkanPrimitiveTopology(const PrimitiveTopology topology) { + switch (topology) { + case (PrimitiveTopology::PointList): + return vk::PrimitiveTopology::ePointList; + case (PrimitiveTopology::LineList): + return vk::PrimitiveTopology::eLineList; + case (PrimitiveTopology::TriangleList): + return vk::PrimitiveTopology::eTriangleList; + case (PrimitiveTopology::PatchList): + return vk::PrimitiveTopology::ePatchList; + default: + vkcv_log(LogLevel::ERROR, "Unknown primitive topology type"); + return vk::PrimitiveTopology::eTriangleList; + } + } + + vk::CompareOp depthTestToVkCompareOp(DepthTest depthTest) { + switch (depthTest) { + case (DepthTest::None): + return vk::CompareOp::eAlways; + case (DepthTest::Less): + return vk::CompareOp::eLess; + case (DepthTest::LessEqual): + return vk::CompareOp::eLessOrEqual; + case (DepthTest::Greater): + return vk::CompareOp::eGreater; + case (DepthTest::GreatherEqual): + return vk::CompareOp::eGreaterOrEqual; + case (DepthTest::Equal): + return vk::CompareOp::eEqual; + default: + vkcv_log(LogLevel::ERROR, "Unknown depth test enum"); + return vk::CompareOp::eAlways; + } + } + + vk::ShaderStageFlagBits shaderStageToVkShaderStage(ShaderStage stage) { + switch (stage) { + case ShaderStage::VERTEX: + return vk::ShaderStageFlagBits::eVertex; + case ShaderStage::FRAGMENT: + return vk::ShaderStageFlagBits::eFragment; + case ShaderStage::GEOMETRY: + return vk::ShaderStageFlagBits::eGeometry; + case ShaderStage::TESS_CONTROL: + return vk::ShaderStageFlagBits::eTessellationControl; + case ShaderStage::TESS_EVAL: + return vk::ShaderStageFlagBits::eTessellationEvaluation; + case ShaderStage::COMPUTE: + return vk::ShaderStageFlagBits::eCompute; + case ShaderStage::TASK: + return vk::ShaderStageFlagBits::eTaskNV; + case ShaderStage::MESH: + return vk::ShaderStageFlagBits::eMeshNV; + default: + vkcv_log(LogLevel::ERROR, "Unknown shader stage"); + return vk::ShaderStageFlagBits::eAll; + } + } + + bool createPipelineShaderStageCreateInfo(const ShaderProgram &shaderProgram, ShaderStage stage, + vk::Device device, + vk::PipelineShaderStageCreateInfo* outCreateInfo) { + + assert(outCreateInfo); + std::vector<uint32_t> code = shaderProgram.getShaderBinary(stage); + vk::ShaderModuleCreateInfo vertexModuleInfo({}, code.size() * sizeof(uint32_t), + code.data()); + vk::ShaderModule shaderModule; + if (device.createShaderModule(&vertexModuleInfo, nullptr, &shaderModule) + != vk::Result::eSuccess) + return false; + + const static auto entryName = "main"; + + *outCreateInfo = vk::PipelineShaderStageCreateInfo({}, shaderStageToVkShaderStage(stage), + shaderModule, entryName, nullptr); + return true; + } + /** - * Fills Vertex Attribute and Binding Description with the corresponding objects form the Vertex Layout. + * Fills Vertex Attribute and Binding Description with the corresponding objects form the Vertex + * Layout. * @param vertexAttributeDescriptions * @param vertexBindingDescriptions * @param existsVertexShader * @param config */ void fillVertexInputDescription( - std::vector<vk::VertexInputAttributeDescription> &vertexAttributeDescriptions, - std::vector<vk::VertexInputBindingDescription> &vertexBindingDescriptions, - const bool existsVertexShader, - const GraphicsPipelineConfig &config) { - + std::vector<vk::VertexInputAttributeDescription> &vertexAttributeDescriptions, + std::vector<vk::VertexInputBindingDescription> &vertexBindingDescriptions, + const bool existsVertexShader, const GraphicsPipelineConfig &config) { + if (existsVertexShader) { - const VertexLayout& layout = config.getVertexLayout(); - - // iterate over the layout's specified, mutually exclusive buffer bindings that make up a vertex buffer - for (const auto& vertexBinding : layout.vertexBindings) - { + const VertexLayout &layout = config.getVertexLayout(); + + // iterate over the layout's specified, mutually exclusive buffer bindings that make up + // a vertex buffer + for (const auto &vertexBinding : layout.vertexBindings) { vertexBindingDescriptions.emplace_back(vertexBinding.bindingLocation, vertexBinding.stride, vk::VertexInputRate::eVertex); - - // iterate over the bindings' specified, mutually exclusive vertex input attachments that make up a vertex - for (const auto& vertexAttachment : vertexBinding.vertexAttachments) - { - vertexAttributeDescriptions.emplace_back(vertexAttachment.inputLocation, - vertexBinding.bindingLocation, - vertexFormatToVulkanFormat(vertexAttachment.format), - vertexAttachment.offset % vertexBinding.stride); + + // iterate over the bindings' specified, mutually exclusive vertex input attachments + // that make up a vertex + for (const auto &vertexAttachment : vertexBinding.vertexAttachments) { + vertexAttributeDescriptions.emplace_back( + vertexAttachment.inputLocation, vertexBinding.bindingLocation, + vertexFormatToVulkanFormat(vertexAttachment.format), + vertexAttachment.offset % vertexBinding.stride); } } } } - + /** - * Creates a Pipeline Vertex Input State Create Info Struct and fills it with Attribute and Binding data. + * Creates a Pipeline Vertex Input State Create Info Struct and fills it with Attribute and + * Binding data. * @param vertexAttributeDescriptions * @param vertexBindingDescriptions * @return Pipeline Vertex Input State Create Info Struct */ vk::PipelineVertexInputStateCreateInfo createPipelineVertexInputStateCreateInfo( - std::vector<vk::VertexInputAttributeDescription> &vertexAttributeDescriptions, - std::vector<vk::VertexInputBindingDescription> &vertexBindingDescriptions) { - + std::vector<vk::VertexInputAttributeDescription> &vertexAttributeDescriptions, + std::vector<vk::VertexInputBindingDescription> &vertexBindingDescriptions) { + vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo( - {}, - vertexBindingDescriptions.size(), - vertexBindingDescriptions.data(), - vertexAttributeDescriptions.size(), - vertexAttributeDescriptions.data() - ); + {}, vertexBindingDescriptions.size(), vertexBindingDescriptions.data(), + vertexAttributeDescriptions.size(), vertexAttributeDescriptions.data()); return pipelineVertexInputStateCreateInfo; } - + /** * Creates a Pipeline Input Assembly State Create Info Struct with 'Primitive Restart' disabled. * @param config provides data for primitive topology. * @return Pipeline Input Assembly State Create Info Struct */ - vk::PipelineInputAssemblyStateCreateInfo createPipelineInputAssemblyStateCreateInfo(const GraphicsPipelineConfig &config) { + vk::PipelineInputAssemblyStateCreateInfo + createPipelineInputAssemblyStateCreateInfo(const GraphicsPipelineConfig &config) { vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo( - {}, - primitiveTopologyToVulkanPrimitiveTopology(config.getPrimitiveTopology()), - false - ); - + {}, primitiveTopologyToVulkanPrimitiveTopology(config.getPrimitiveTopology()), false); + return pipelineInputAssemblyStateCreateInfo; } - - vk::PipelineTessellationStateCreateInfo createPipelineTessellationStateCreateInfo(const GraphicsPipelineConfig &config) { + + vk::PipelineTessellationStateCreateInfo + createPipelineTessellationStateCreateInfo(const GraphicsPipelineConfig &config) { vk::PipelineTessellationStateCreateInfo pipelineTessellationStateCreateInfo( - {}, - config.getTesselationControlPoints() - ); - + {}, config.getTesselationControlPoints()); + return pipelineTessellationStateCreateInfo; } - + /** - * Creates a Pipeline Viewport State Create Info Struct with default set viewport and scissor settings. + * Creates a Pipeline Viewport State Create Info Struct with default set viewport and scissor + * settings. * @param config provides with and height of the output window * @return Pipeline Viewport State Create Info Struct */ - vk::PipelineViewportStateCreateInfo createPipelineViewportStateCreateInfo(const GraphicsPipelineConfig &config) { + vk::PipelineViewportStateCreateInfo + createPipelineViewportStateCreateInfo(const GraphicsPipelineConfig &config) { static vk::Viewport viewport; static vk::Rect2D scissor; - - viewport = vk::Viewport( - 0.f, 0.f, - static_cast<float>(config.getWidth()), - static_cast<float>(config.getHeight()), - 0.f, 1.f - ); - - scissor = vk::Rect2D( - { 0,0 }, - { config.getWidth(), config.getHeight() } - ); - - vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo( - {}, - 1, - &viewport, - 1, - &scissor - ); - + + viewport = vk::Viewport(0.f, 0.f, static_cast<float>(config.getWidth()), + static_cast<float>(config.getHeight()), 0.f, 1.f); + + scissor = vk::Rect2D({ 0, 0 }, { config.getWidth(), config.getHeight() }); + + vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo({}, 1, &viewport, 1, + &scissor); + return pipelineViewportStateCreateInfo; } - + /** * Creates a Pipeline Rasterization State Create Info Struct with default values set to: * Rasterizer Discard: Disabled @@ -269,313 +252,260 @@ namespace vkcv { */ vk::PipelineRasterizationStateCreateInfo createPipelineRasterizationStateCreateInfo( const GraphicsPipelineConfig &config, - const vk::PhysicalDeviceConservativeRasterizationPropertiesEXT& conservativeRasterProperties) { + const vk::PhysicalDeviceConservativeRasterizationPropertiesEXT + &conservativeRasterProperties) { vk::CullModeFlags cullMode; switch (config.getCulling()) { - case CullMode::None: - cullMode = vk::CullModeFlagBits::eNone; - break; - case CullMode::Front: - cullMode = vk::CullModeFlagBits::eFront; - break; - case CullMode::Back: - cullMode = vk::CullModeFlagBits::eBack; - break; - case CullMode::Both: - cullMode = vk::CullModeFlagBits::eFrontAndBack; - break; - default: + case CullMode::None: + cullMode = vk::CullModeFlagBits::eNone; + break; + case CullMode::Front: + cullMode = vk::CullModeFlagBits::eFront; + break; + case CullMode::Back: + cullMode = vk::CullModeFlagBits::eBack; + break; + case CullMode::Both: + cullMode = vk::CullModeFlagBits::eFrontAndBack; + break; + default: vkcv_log(LogLevel::ERROR, "Unknown CullMode"); - cullMode = vk::CullModeFlagBits::eNone; + cullMode = vk::CullModeFlagBits::eNone; } - - vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo ( - {}, - config.isDepthClampingEnabled(), - false, - vk::PolygonMode::eFill, - cullMode, - vk::FrontFace::eCounterClockwise, - false, - 0.f, - 0.f, - 0.f, - 1.f - ); + + vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo( + {}, config.isDepthClampingEnabled(), false, vk::PolygonMode::eFill, cullMode, + vk::FrontFace::eCounterClockwise, false, 0.f, 0.f, 0.f, 1.f); static vk::PipelineRasterizationConservativeStateCreateInfoEXT conservativeRasterization; - + if (config.isUsingConservativeRasterization()) { - const float overestimationSize = 1.0f - conservativeRasterProperties.primitiveOverestimationSize; - const float maxOverestimationSize = conservativeRasterProperties.maxExtraPrimitiveOverestimationSize; + const float overestimationSize = + 1.0f - conservativeRasterProperties.primitiveOverestimationSize; + const float maxOverestimationSize = + conservativeRasterProperties.maxExtraPrimitiveOverestimationSize; conservativeRasterization = vk::PipelineRasterizationConservativeStateCreateInfoEXT( - {}, - vk::ConservativeRasterizationModeEXT::eOverestimate, - std::min(std::max(overestimationSize, 0.f), maxOverestimationSize) - ); - + {}, vk::ConservativeRasterizationModeEXT::eOverestimate, + std::min(std::max(overestimationSize, 0.f), maxOverestimationSize)); + pipelineRasterizationStateCreateInfo.pNext = &conservativeRasterization; } - + return pipelineRasterizationStateCreateInfo; } - + /** * Creates a Pipeline Multisample State Create Info Struct. * @param config set MSAA Sample Count Flag * @return Pipeline Multisample State Create Info Struct */ - vk::PipelineMultisampleStateCreateInfo createPipelineMultisampleStateCreateInfo(const GraphicsPipelineConfig &config, - const PassConfig &passConfig) { + vk::PipelineMultisampleStateCreateInfo + createPipelineMultisampleStateCreateInfo(const GraphicsPipelineConfig &config, + const PassConfig &passConfig) { vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo( - {}, - msaaToSampleCountFlagBits(passConfig.getMultisampling()), - false, - 0.f, - nullptr, - config.isWritingAlphaToCoverage(), - false - ); - + {}, msaaToSampleCountFlagBits(passConfig.getMultisampling()), false, 0.f, nullptr, + config.isWritingAlphaToCoverage(), false); + return pipelineMultisampleStateCreateInfo; } - + /** * Creates a Pipeline Color Blend State Create Info Struct. * Currently only one blend mode is supported! There for, blending is set to additive. * @param config sets blend mode * @return */ - vk::PipelineColorBlendStateCreateInfo createPipelineColorBlendStateCreateInfo(const GraphicsPipelineConfig &config) { + vk::PipelineColorBlendStateCreateInfo + createPipelineColorBlendStateCreateInfo(const GraphicsPipelineConfig &config) { // currently set to additive, if not disabled // BlendFactors must be set as soon as additional BlendModes are added - static vk::PipelineColorBlendAttachmentState colorBlendAttachmentState ( - config.getBlendMode() != BlendMode::None, - vk::BlendFactor::eOne, - vk::BlendFactor::eOne, - vk::BlendOp::eAdd, - vk::BlendFactor::eOne, - vk::BlendFactor::eOne, - vk::BlendOp::eAdd, - vk::ColorComponentFlags( - VK_COLOR_COMPONENT_R_BIT | - VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | - VK_COLOR_COMPONENT_A_BIT - ) - ); - + static vk::PipelineColorBlendAttachmentState colorBlendAttachmentState( + config.getBlendMode() != BlendMode::None, vk::BlendFactor::eOne, vk::BlendFactor::eOne, + vk::BlendOp::eAdd, vk::BlendFactor::eOne, vk::BlendFactor::eOne, vk::BlendOp::eAdd, + vk::ColorComponentFlags(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT + | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT)); + vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo( - {}, - false, - vk::LogicOp::eClear, - 1, //TODO: hardcoded to one - &colorBlendAttachmentState, - { 1.f,1.f,1.f,1.f } - ); - + {}, false, vk::LogicOp::eClear, + 1, // TODO: hardcoded to one + &colorBlendAttachmentState, { 1.f, 1.f, 1.f, 1.f }); + return pipelineColorBlendStateCreateInfo; } - + /** * Creates a Pipeline Layout Create Info Struct. * @param config sets Push Constant Size and Descriptor Layouts. * @return Pipeline Layout Create Info Struct */ - vk::PipelineLayoutCreateInfo createPipelineLayoutCreateInfo(const GraphicsPipelineConfig &config, - const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts) { + vk::PipelineLayoutCreateInfo createPipelineLayoutCreateInfo( + const GraphicsPipelineConfig &config, + const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts) { static vk::PushConstantRange pushConstantRange; - + const size_t pushConstantsSize = config.getShaderProgram().getPushConstantsSize(); - pushConstantRange = vk::PushConstantRange( - vk::ShaderStageFlagBits::eAll, 0, pushConstantsSize - ); - - vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo( - {}, - (descriptorSetLayouts), - (pushConstantRange) - ); - + pushConstantRange = + vk::PushConstantRange(vk::ShaderStageFlagBits::eAll, 0, pushConstantsSize); + + vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo({}, (descriptorSetLayouts), + (pushConstantRange)); + if (pushConstantsSize == 0) { pipelineLayoutCreateInfo.pushConstantRangeCount = 0; } - + return pipelineLayoutCreateInfo; } - + /** * Creates a Pipeline Depth Stencil State Create Info Struct. * @param config sets if depth test in enabled or not. * @return Pipeline Layout Create Info Struct */ - vk::PipelineDepthStencilStateCreateInfo createPipelineDepthStencilStateCreateInfo(const GraphicsPipelineConfig &config) { + vk::PipelineDepthStencilStateCreateInfo + createPipelineDepthStencilStateCreateInfo(const GraphicsPipelineConfig &config) { const vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilCreateInfo( - vk::PipelineDepthStencilStateCreateFlags(), - config.getDepthTest() != DepthTest::None, - config.isWritingDepth(), - depthTestToVkCompareOp(config.getDepthTest()), - false, - false, - {}, - {}, - 0.0f, - 1.0f - ); - + vk::PipelineDepthStencilStateCreateFlags(), config.getDepthTest() != DepthTest::None, + config.isWritingDepth(), depthTestToVkCompareOp(config.getDepthTest()), false, false, + {}, {}, 0.0f, 1.0f); + return pipelineDepthStencilCreateInfo; } - + /** * Creates a Pipeline Dynamic State Create Info Struct. * @param config sets whenever a dynamic viewport is used or not. * @return Pipeline Dynamic State Create Info Struct */ - vk::PipelineDynamicStateCreateInfo createPipelineDynamicStateCreateInfo(const GraphicsPipelineConfig &config) { + vk::PipelineDynamicStateCreateInfo + createPipelineDynamicStateCreateInfo(const GraphicsPipelineConfig &config) { static std::vector<vk::DynamicState> dynamicStates; dynamicStates.clear(); - - if(config.isViewportDynamic()) { + + if (config.isViewportDynamic()) { dynamicStates.push_back(vk::DynamicState::eViewport); dynamicStates.push_back(vk::DynamicState::eScissor); } - + vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo( - {}, - static_cast<uint32_t>(dynamicStates.size()), - dynamicStates.data() - ); - + {}, static_cast<uint32_t>(dynamicStates.size()), dynamicStates.data()); + return dynamicStateCreateInfo; } - GraphicsPipelineHandle GraphicsPipelineManager::createPipeline(const GraphicsPipelineConfig &config, - const PassManager& passManager, - const DescriptorSetLayoutManager& descriptorManager) { - const vk::RenderPass &pass = passManager.getVkPass(config.getPass()); - - const auto& program = config.getShaderProgram(); - - const bool existsTaskShader = program.existsShader(ShaderStage::TASK); - const bool existsMeshShader = program.existsShader(ShaderStage::MESH); - const bool existsVertexShader = program.existsShader(ShaderStage::VERTEX); - const bool existsFragmentShader = program.existsShader(ShaderStage::FRAGMENT); - const bool existsGeometryShader = program.existsShader(ShaderStage::GEOMETRY); - const bool existsTessellationControlShader = program.existsShader(ShaderStage::TESS_CONTROL); - const bool existsTessellationEvaluationShader = program.existsShader(ShaderStage::TESS_EVAL); - - const bool validGeometryStages = ( - (existsVertexShader && (existsTessellationControlShader == existsTessellationEvaluationShader)) || - (existsTaskShader && existsMeshShader) - ); - - if (!validGeometryStages) { - vkcv_log(LogLevel::ERROR, "Requires vertex or task and mesh shader"); - return {}; - } - - if (!existsFragmentShader) { - vkcv_log(LogLevel::ERROR, "Requires fragment shader code"); - return {}; - } - - std::vector<vk::PipelineShaderStageCreateInfo> shaderStages; - auto destroyShaderModules = [&shaderStages, this] { - for (auto stage : shaderStages) { + GraphicsPipelineHandle + GraphicsPipelineManager::createPipeline(const GraphicsPipelineConfig &config, + const PassManager &passManager, + const DescriptorSetLayoutManager &descriptorManager) { + const vk::RenderPass &pass = passManager.getVkPass(config.getPass()); + + const auto &program = config.getShaderProgram(); + + const bool existsTaskShader = program.existsShader(ShaderStage::TASK); + const bool existsMeshShader = program.existsShader(ShaderStage::MESH); + const bool existsVertexShader = program.existsShader(ShaderStage::VERTEX); + const bool existsFragmentShader = program.existsShader(ShaderStage::FRAGMENT); + const bool existsGeometryShader = program.existsShader(ShaderStage::GEOMETRY); + const bool existsTessellationControlShader = + program.existsShader(ShaderStage::TESS_CONTROL); + const bool existsTessellationEvaluationShader = + program.existsShader(ShaderStage::TESS_EVAL); + + const bool validGeometryStages = + ((existsVertexShader + && (existsTessellationControlShader == existsTessellationEvaluationShader)) + || (existsTaskShader && existsMeshShader)); + + if (!validGeometryStages) { + vkcv_log(LogLevel::ERROR, "Requires vertex or task and mesh shader"); + return {}; + } + + if (!existsFragmentShader) { + vkcv_log(LogLevel::ERROR, "Requires fragment shader code"); + return {}; + } + + std::vector<vk::PipelineShaderStageCreateInfo> shaderStages; + auto destroyShaderModules = [&shaderStages, this] { + for (auto stage : shaderStages) { getCore().getContext().getDevice().destroyShaderModule(stage.module); - } - shaderStages.clear(); - }; - - if (existsVertexShader) { - vk::PipelineShaderStageCreateInfo createInfo; - const bool success = createPipelineShaderStageCreateInfo( - program, - ShaderStage::VERTEX, - getCore().getContext().getDevice(), - &createInfo); - - if (success) { - shaderStages.push_back(createInfo); - } else { - destroyShaderModules(); - return {}; - } - } - - if (existsTaskShader) { - vk::PipelineShaderStageCreateInfo createInfo; - const bool success = createPipelineShaderStageCreateInfo( - program, - ShaderStage::TASK, - getCore().getContext().getDevice(), - &createInfo); - - if (success) { - shaderStages.push_back(createInfo); - } else { - destroyShaderModules(); - return {}; - } - } - - if (existsMeshShader) { - vk::PipelineShaderStageCreateInfo createInfo; - const bool success = createPipelineShaderStageCreateInfo( - program, - ShaderStage::MESH, - getCore().getContext().getDevice(), - &createInfo); - - if (success) { - shaderStages.push_back(createInfo); - } else { - destroyShaderModules(); - return {}; - } - } - - { - vk::PipelineShaderStageCreateInfo createInfo; - const bool success = createPipelineShaderStageCreateInfo( - program, - ShaderStage::FRAGMENT, - getCore().getContext().getDevice(), - &createInfo); - - if (success) { - shaderStages.push_back(createInfo); - } else { - destroyShaderModules(); - return {}; - } - } - - if (existsGeometryShader) { - vk::PipelineShaderStageCreateInfo createInfo; - const bool success = createPipelineShaderStageCreateInfo( - program, - ShaderStage::GEOMETRY, - getCore().getContext().getDevice(), - &createInfo); - - if (success) { - shaderStages.push_back(createInfo); - } else { - destroyShaderModules(); - return {}; - } - } - + } + shaderStages.clear(); + }; + + if (existsVertexShader) { + vk::PipelineShaderStageCreateInfo createInfo; + const bool success = createPipelineShaderStageCreateInfo( + program, ShaderStage::VERTEX, getCore().getContext().getDevice(), &createInfo); + + if (success) { + shaderStages.push_back(createInfo); + } else { + destroyShaderModules(); + return {}; + } + } + + if (existsTaskShader) { + vk::PipelineShaderStageCreateInfo createInfo; + const bool success = createPipelineShaderStageCreateInfo( + program, ShaderStage::TASK, getCore().getContext().getDevice(), &createInfo); + + if (success) { + shaderStages.push_back(createInfo); + } else { + destroyShaderModules(); + return {}; + } + } + + if (existsMeshShader) { + vk::PipelineShaderStageCreateInfo createInfo; + const bool success = createPipelineShaderStageCreateInfo( + program, ShaderStage::MESH, getCore().getContext().getDevice(), &createInfo); + + if (success) { + shaderStages.push_back(createInfo); + } else { + destroyShaderModules(); + return {}; + } + } + + { + vk::PipelineShaderStageCreateInfo createInfo; + const bool success = createPipelineShaderStageCreateInfo( + program, ShaderStage::FRAGMENT, getCore().getContext().getDevice(), &createInfo); + + if (success) { + shaderStages.push_back(createInfo); + } else { + destroyShaderModules(); + return {}; + } + } + + if (existsGeometryShader) { + vk::PipelineShaderStageCreateInfo createInfo; + const bool success = createPipelineShaderStageCreateInfo( + program, ShaderStage::GEOMETRY, getCore().getContext().getDevice(), &createInfo); + + if (success) { + shaderStages.push_back(createInfo); + } else { + destroyShaderModules(); + return {}; + } + } + if (existsTessellationControlShader) { vk::PipelineShaderStageCreateInfo createInfo; const bool success = createPipelineShaderStageCreateInfo( - program, - ShaderStage::TESS_CONTROL, - getCore().getContext().getDevice(), - &createInfo); - + program, ShaderStage::TESS_CONTROL, getCore().getContext().getDevice(), + &createInfo); + if (success) { shaderStages.push_back(createInfo); } else { @@ -583,15 +513,12 @@ namespace vkcv { return {}; } } - + if (existsTessellationEvaluationShader) { vk::PipelineShaderStageCreateInfo createInfo; const bool success = createPipelineShaderStageCreateInfo( - program, - ShaderStage::TESS_EVAL, - getCore().getContext().getDevice(), - &createInfo); - + program, ShaderStage::TESS_EVAL, getCore().getContext().getDevice(), &createInfo); + if (success) { shaderStages.push_back(createInfo); } else { @@ -599,139 +526,129 @@ namespace vkcv { return {}; } } - - const PassConfig& passConfig = passManager.getPassConfig(config.getPass()); - // vertex input state - // Fill up VertexInputBindingDescription and VertexInputAttributeDescription Containers - std::vector<vk::VertexInputAttributeDescription> vertexAttributeDescriptions; - std::vector<vk::VertexInputBindingDescription> vertexBindingDescriptions; - fillVertexInputDescription(vertexAttributeDescriptions, vertexBindingDescriptions, existsVertexShader, config); + const PassConfig &passConfig = passManager.getPassConfig(config.getPass()); + + // vertex input state + // Fill up VertexInputBindingDescription and VertexInputAttributeDescription Containers + std::vector<vk::VertexInputAttributeDescription> vertexAttributeDescriptions; + std::vector<vk::VertexInputBindingDescription> vertexBindingDescriptions; + fillVertexInputDescription(vertexAttributeDescriptions, vertexBindingDescriptions, + existsVertexShader, config); - // Handover Containers to PipelineVertexInputStateCreateIngo Struct - vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo = - createPipelineVertexInputStateCreateInfo(vertexAttributeDescriptions, - vertexBindingDescriptions); + // Handover Containers to PipelineVertexInputStateCreateIngo Struct + vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo = + createPipelineVertexInputStateCreateInfo(vertexAttributeDescriptions, + vertexBindingDescriptions); - // input assembly state - vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo = - createPipelineInputAssemblyStateCreateInfo(config); + // input assembly state + vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo = + createPipelineInputAssemblyStateCreateInfo(config); // tesselation state vk::PipelineTessellationStateCreateInfo pipelineTessellationStateCreateInfo = - createPipelineTessellationStateCreateInfo(config); - - // viewport state - vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo = - createPipelineViewportStateCreateInfo(config); - - // rasterization state - vk::PhysicalDeviceConservativeRasterizationPropertiesEXT conservativeRasterProperties; - vk::PhysicalDeviceProperties deviceProperties; - vk::PhysicalDeviceProperties2 deviceProperties2(deviceProperties); - deviceProperties2.pNext = &conservativeRasterProperties; + createPipelineTessellationStateCreateInfo(config); + + // viewport state + vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo = + createPipelineViewportStateCreateInfo(config); + + // rasterization state + vk::PhysicalDeviceConservativeRasterizationPropertiesEXT conservativeRasterProperties; + vk::PhysicalDeviceProperties deviceProperties; + vk::PhysicalDeviceProperties2 deviceProperties2(deviceProperties); + deviceProperties2.pNext = &conservativeRasterProperties; getCore().getContext().getPhysicalDevice().getProperties2(&deviceProperties2); - vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo = - createPipelineRasterizationStateCreateInfo(config, conservativeRasterProperties); + vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo = + createPipelineRasterizationStateCreateInfo(config, conservativeRasterProperties); - // multisample state - vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo = - createPipelineMultisampleStateCreateInfo(config, passConfig); + // multisample state + vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo = + createPipelineMultisampleStateCreateInfo(config, passConfig); - // color blend state - vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo = - createPipelineColorBlendStateCreateInfo(config); + // color blend state + vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo = + createPipelineColorBlendStateCreateInfo(config); - // Dynamic State - vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = - createPipelineDynamicStateCreateInfo(config); + // Dynamic State + vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = + createPipelineDynamicStateCreateInfo(config); std::vector<vk::DescriptorSetLayout> descriptorSetLayouts; descriptorSetLayouts.reserve(config.getDescriptorSetLayouts().size()); - for (const auto& handle : config.getDescriptorSetLayouts()) { - descriptorSetLayouts.push_back(descriptorManager.getDescriptorSetLayout(handle).vulkanHandle); + for (const auto &handle : config.getDescriptorSetLayouts()) { + descriptorSetLayouts.push_back( + descriptorManager.getDescriptorSetLayout(handle).vulkanHandle); + } + + // pipeline layout + vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = + createPipelineLayoutCreateInfo(config, descriptorSetLayouts); + + vk::PipelineLayout vkPipelineLayout {}; + if (getCore().getContext().getDevice().createPipelineLayout(&pipelineLayoutCreateInfo, + nullptr, &vkPipelineLayout) + != vk::Result::eSuccess) { + destroyShaderModules(); + return {}; + } + + // Depth Stencil + const vk::PipelineDepthStencilStateCreateInfo depthStencilCreateInfo = + createPipelineDepthStencilStateCreateInfo(config); + + const vk::PipelineDepthStencilStateCreateInfo* p_depthStencilCreateInfo = nullptr; + + for (const auto &attachment : passConfig.getAttachments()) { + if ((isDepthFormat(attachment.getFormat())) + || (isStencilFormat(attachment.getFormat()))) { + p_depthStencilCreateInfo = &depthStencilCreateInfo; + break; + } } - - // pipeline layout - vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = - createPipelineLayoutCreateInfo(config, descriptorSetLayouts); - - vk::PipelineLayout vkPipelineLayout{}; - if (getCore().getContext().getDevice().createPipelineLayout(&pipelineLayoutCreateInfo, - nullptr, - &vkPipelineLayout) != vk::Result::eSuccess) { - destroyShaderModules(); - return {}; - } - - // Depth Stencil - const vk::PipelineDepthStencilStateCreateInfo depthStencilCreateInfo = - createPipelineDepthStencilStateCreateInfo(config); - - const vk::PipelineDepthStencilStateCreateInfo* p_depthStencilCreateInfo = nullptr; - - for (const auto& attachment : passConfig.getAttachments()) { - if ((isDepthFormat(attachment.getFormat())) || - (isStencilFormat(attachment.getFormat()))) { - p_depthStencilCreateInfo = &depthStencilCreateInfo; - break; - } - } - - // Get all setting structs together and create the Pipeline - const vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo( - {}, - static_cast<uint32_t>(shaderStages.size()), - shaderStages.data(), - &pipelineVertexInputStateCreateInfo, - &pipelineInputAssemblyStateCreateInfo, - &pipelineTessellationStateCreateInfo, - &pipelineViewportStateCreateInfo, - &pipelineRasterizationStateCreateInfo, - &pipelineMultisampleStateCreateInfo, - p_depthStencilCreateInfo, - &pipelineColorBlendStateCreateInfo, - &dynamicStateCreateInfo, - vkPipelineLayout, - pass, - 0, - {}, - 0 - ); - - vk::Pipeline vkPipeline{}; - if (getCore().getContext().getDevice().createGraphicsPipelines(nullptr, - 1, - &graphicsPipelineCreateInfo, - nullptr, - &vkPipeline) != vk::Result::eSuccess) - { - // Catch runtime error if the creation of the pipeline fails. - // Destroy everything to keep the memory clean. - destroyShaderModules(); - return {}; - } - - // Clean Up - destroyShaderModules(); - - // Hand over Handler to main Application - return add({ vkPipeline, vkPipelineLayout, config }); - } - - vk::Pipeline GraphicsPipelineManager::getVkPipeline(const GraphicsPipelineHandle &handle) const { - auto& pipeline = (*this)[handle]; - return pipeline.m_handle; - } - - vk::PipelineLayout GraphicsPipelineManager::getVkPipelineLayout(const GraphicsPipelineHandle &handle) const { - auto& pipeline = (*this)[handle]; - return pipeline.m_layout; - } - - const GraphicsPipelineConfig& GraphicsPipelineManager::getPipelineConfig(const GraphicsPipelineHandle &handle) const { - auto& pipeline = (*this)[handle]; - return pipeline.m_config; - } - -} + + // Get all setting structs together and create the Pipeline + const vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo( + {}, static_cast<uint32_t>(shaderStages.size()), shaderStages.data(), + &pipelineVertexInputStateCreateInfo, &pipelineInputAssemblyStateCreateInfo, + &pipelineTessellationStateCreateInfo, &pipelineViewportStateCreateInfo, + &pipelineRasterizationStateCreateInfo, &pipelineMultisampleStateCreateInfo, + p_depthStencilCreateInfo, &pipelineColorBlendStateCreateInfo, &dynamicStateCreateInfo, + vkPipelineLayout, pass, 0, {}, 0); + + vk::Pipeline vkPipeline {}; + if (getCore().getContext().getDevice().createGraphicsPipelines( + nullptr, 1, &graphicsPipelineCreateInfo, nullptr, &vkPipeline) + != vk::Result::eSuccess) { + // Catch runtime error if the creation of the pipeline fails. + // Destroy everything to keep the memory clean. + destroyShaderModules(); + return {}; + } + + // Clean Up + destroyShaderModules(); + + // Hand over Handler to main Application + return add({ vkPipeline, vkPipelineLayout, config }); + } + + vk::Pipeline + GraphicsPipelineManager::getVkPipeline(const GraphicsPipelineHandle &handle) const { + auto &pipeline = (*this) [handle]; + return pipeline.m_handle; + } + + vk::PipelineLayout + GraphicsPipelineManager::getVkPipelineLayout(const GraphicsPipelineHandle &handle) const { + auto &pipeline = (*this) [handle]; + return pipeline.m_layout; + } + + const GraphicsPipelineConfig & + GraphicsPipelineManager::getPipelineConfig(const GraphicsPipelineHandle &handle) const { + auto &pipeline = (*this) [handle]; + return pipeline.m_config; + } + +} // namespace vkcv diff --git a/src/vkcv/GraphicsPipelineManager.hpp b/src/vkcv/GraphicsPipelineManager.hpp index be18a4c983696eea177fbe6842e6f6ff57426b3a..602e1a96d29a4b78a3784c215074b9541bf5de47 100644 --- a/src/vkcv/GraphicsPipelineManager.hpp +++ b/src/vkcv/GraphicsPipelineManager.hpp @@ -8,32 +8,32 @@ // TODO: Edit @brief: add graphics pipeline, but only then when the compute part is in an own class. // TODO: More authors? Do we need authors (general question)? -#include <vulkan/vulkan.hpp> -#include <vector> +#include "DescriptorSetLayoutManager.hpp" #include "HandleManager.hpp" -#include "vkcv/GraphicsPipelineConfig.hpp" #include "PassManager.hpp" -#include "DescriptorSetLayoutManager.hpp" +#include "vkcv/GraphicsPipelineConfig.hpp" +#include <vector> +#include <vulkan/vulkan.hpp> namespace vkcv { - + struct GraphicsPipelineEntry { vk::Pipeline m_handle; vk::PipelineLayout m_layout; GraphicsPipelineConfig m_config; }; - + /** * @brief Class to manage graphics pipelines. */ - class GraphicsPipelineManager : public HandleManager<GraphicsPipelineEntry, GraphicsPipelineHandle> { + class GraphicsPipelineManager : + public HandleManager<GraphicsPipelineEntry, GraphicsPipelineHandle> { private: - [[nodiscard]] - uint64_t getIdFrom(const GraphicsPipelineHandle& handle) const override; - - [[nodiscard]] - GraphicsPipelineHandle createById(uint64_t id, const HandleDestroyFunction& destroy) override; - + [[nodiscard]] uint64_t getIdFrom(const GraphicsPipelineHandle &handle) const override; + + [[nodiscard]] GraphicsPipelineHandle + createById(uint64_t id, const HandleDestroyFunction &destroy) override; + /** * Destroys and deallocates graphics pipeline represented by a given * graphics pipeline handle id. @@ -41,56 +41,58 @@ namespace vkcv { * @param id Graphics pipeline handle id */ void destroyById(uint64_t id) override; - - public: - GraphicsPipelineManager() noexcept; - - ~GraphicsPipelineManager() noexcept override; // dtor - + + public: + GraphicsPipelineManager() noexcept; + + ~GraphicsPipelineManager() noexcept override; // dtor + GraphicsPipelineManager(const GraphicsPipelineManager &other) = delete; // copy-ctor - GraphicsPipelineManager(GraphicsPipelineManager &&other) = delete; // move-ctor; - - GraphicsPipelineManager & operator=(const GraphicsPipelineManager &other) = delete; // copy-assign op - GraphicsPipelineManager & operator=(GraphicsPipelineManager &&other) = delete; // move-assign op - - /** - * Creates a Graphics Pipeline based on the set shader stages in the Config Struct. - * This function is wrapped in /src/vkcv/Core.cpp by Core::createGraphicsPipeline(const PipelineConfig &config). - * Therefore the passManager is filled already by the overall context of an application. - * On application level it is necessary first to fill a PipelineConfig Struct. - * @param config Hands over all needed information for pipeline creation. - * @param passManager Hands over the corresponding render pass. - * @param descriptorManager Hands over the corresponding descriptor set layouts - * @return A Handler to the created Graphics Pipeline Object. - */ + GraphicsPipelineManager(GraphicsPipelineManager &&other) = delete; // move-ctor; + + GraphicsPipelineManager & + operator=(const GraphicsPipelineManager &other) = delete; // copy-assign op + GraphicsPipelineManager & + operator=(GraphicsPipelineManager &&other) = delete; // move-assign op + + /** + * Creates a Graphics Pipeline based on the set shader stages in the Config Struct. + * This function is wrapped in /src/vkcv/Core.cpp by Core::createGraphicsPipeline(const + * PipelineConfig &config). Therefore the passManager is filled already by the overall + * context of an application. On application level it is necessary first to fill a + * PipelineConfig Struct. + * @param config Hands over all needed information for pipeline creation. + * @param passManager Hands over the corresponding render pass. + * @param descriptorManager Hands over the corresponding descriptor set layouts + * @return A Handler to the created Graphics Pipeline Object. + */ GraphicsPipelineHandle createPipeline(const GraphicsPipelineConfig &config, - const PassManager& passManager, - const DescriptorSetLayoutManager& descriptorManager); - - /** - * Returns a vk::Pipeline object by handle. - * @param handle Directing to the requested pipeline. - * @return vk::Pipeline. - */ - [[nodiscard]] - vk::Pipeline getVkPipeline(const GraphicsPipelineHandle &handle) const; - - /** - * Returns a vk::PipelineLayout object by handle. - * @param handle Directing to the requested pipeline. - * @return vk::PipelineLayout. - */ - [[nodiscard]] - vk::PipelineLayout getVkPipelineLayout(const GraphicsPipelineHandle &handle) const; - - /** - * Returns the corresponding Pipeline Config Struct of a pipeline object directed by the given Handler. - * @param handle Directing to the requested pipeline. - * @return Pipeline Config Struct - */ - [[nodiscard]] - const GraphicsPipelineConfig &getPipelineConfig(const GraphicsPipelineHandle &handle) const; - - }; - -} + const PassManager &passManager, + const DescriptorSetLayoutManager &descriptorManager); + + /** + * Returns a vk::Pipeline object by handle. + * @param handle Directing to the requested pipeline. + * @return vk::Pipeline. + */ + [[nodiscard]] vk::Pipeline getVkPipeline(const GraphicsPipelineHandle &handle) const; + + /** + * Returns a vk::PipelineLayout object by handle. + * @param handle Directing to the requested pipeline. + * @return vk::PipelineLayout. + */ + [[nodiscard]] vk::PipelineLayout + getVkPipelineLayout(const GraphicsPipelineHandle &handle) const; + + /** + * Returns the corresponding Pipeline Config Struct of a pipeline object directed by the + * given Handler. + * @param handle Directing to the requested pipeline. + * @return Pipeline Config Struct + */ + [[nodiscard]] const GraphicsPipelineConfig & + getPipelineConfig(const GraphicsPipelineHandle &handle) const; + }; + +} // namespace vkcv diff --git a/src/vkcv/HandleManager.hpp b/src/vkcv/HandleManager.hpp index 13213dc2a4ff5975458690ddc41e5a879580ee16..a7b4b7aab30f4ce29d1f91c04336e733aba17b1b 100644 --- a/src/vkcv/HandleManager.hpp +++ b/src/vkcv/HandleManager.hpp @@ -7,110 +7,106 @@ #include "vkcv/Logger.hpp" namespace vkcv { - + class Core; - template<typename T, typename H = Handle> + template <typename T, typename H = Handle> class HandleManager { friend class Core; + private: Core* m_core; std::vector<T> m_entries; - + protected: HandleManager() noexcept : m_core(nullptr), m_entries() {} - - virtual bool init(Core& core) { + + virtual bool init(Core &core) { if (m_core) { vkcv_log(vkcv::LogLevel::ERROR, "Manager is already initialized"); return false; } - + if (!m_entries.empty()) { - vkcv_log(vkcv::LogLevel::WARNING, "Entries added before initialization will be erased"); + vkcv_log(vkcv::LogLevel::WARNING, + "Entries added before initialization will be erased"); } - + m_core = &core; m_entries.clear(); return true; } - - [[nodiscard]] - const Core& getCore() const { + + [[nodiscard]] const Core &getCore() const { return *m_core; } - - [[nodiscard]] - Core& getCore() { + + [[nodiscard]] Core &getCore() { return *m_core; } - - [[nodiscard]] - size_t getCount() const { + + [[nodiscard]] size_t getCount() const { return m_entries.size(); } - - [[nodiscard]] - const T& getById(uint64_t id) const { + + [[nodiscard]] const T &getById(uint64_t id) const { if (id >= m_entries.size()) { static T invalid; vkcv_log(vkcv::LogLevel::ERROR, "Invalid handle id"); return invalid; } - - return m_entries[id]; + + return m_entries [id]; } - - [[nodiscard]] - T& getById(uint64_t id) { + + [[nodiscard]] T &getById(uint64_t id) { if (id >= m_entries.size()) { static T invalid; vkcv_log(vkcv::LogLevel::ERROR, "Invalid handle id"); return invalid; } - - return m_entries[id]; + + return m_entries [id]; } - - virtual uint64_t getIdFrom(const H& handle) const = 0; - - [[nodiscard]] - virtual const T& operator[](const H& handle) const { - const Handle& _handle = handle; - return getById(getIdFrom(static_cast<const H&>(_handle))); + + virtual uint64_t getIdFrom(const H &handle) const = 0; + + [[nodiscard]] virtual const T &operator[](const H &handle) const { + const Handle &_handle = handle; + return getById(getIdFrom(static_cast<const H &>(_handle))); } - - [[nodiscard]] - virtual T& operator[](const H& handle) { - const Handle& _handle = handle; - return getById(getIdFrom(static_cast<const H&>(_handle))); + + [[nodiscard]] virtual T &operator[](const H &handle) { + const Handle &_handle = handle; + return getById(getIdFrom(static_cast<const H &>(_handle))); } - + H add(const T &entry) { const uint64_t id = m_entries.size(); m_entries.push_back(entry); - return createById(id, [&](uint64_t id) { destroyById(id); }); + return createById(id, [&](uint64_t id) { + destroyById(id); + }); } - - virtual H createById(uint64_t id, const HandleDestroyFunction& destroy) = 0; - + + virtual H createById(uint64_t id, const HandleDestroyFunction &destroy) = 0; + virtual void destroyById(uint64_t id) = 0; - + void clear() { for (uint64_t id = 0; id < m_entries.size(); id++) { destroyById(id); } } - + public: - HandleManager(HandleManager&& other) = delete; - HandleManager(const HandleManager& other) = delete; - - HandleManager& operator=(HandleManager&& other) = delete; - HandleManager& operator=(const HandleManager& other) = delete; - + HandleManager(HandleManager &&other) = delete; + HandleManager(const HandleManager &other) = delete; + + HandleManager &operator=(HandleManager &&other) = delete; + HandleManager &operator=(const HandleManager &other) = delete; + virtual ~HandleManager() noexcept = default; - }; -} +} // namespace vkcv diff --git a/src/vkcv/Handles.cpp b/src/vkcv/Handles.cpp index 65fc02dedeba39953c173103efe9b228f49e5d7f..abf5b9d7ec44699f6c581236b29fa921459c7ab4 100644 --- a/src/vkcv/Handles.cpp +++ b/src/vkcv/Handles.cpp @@ -3,99 +3,91 @@ #include <iostream> namespace vkcv { - - Handle::Handle() : - m_id(UINT64_MAX), m_rc(nullptr), m_destroy(nullptr) - {} - - Handle::Handle(uint64_t id, const HandleDestroyFunction& destroy) : - m_id(id), m_rc(new uint64_t(1)), m_destroy(destroy) - {} - + + Handle::Handle() : m_id(UINT64_MAX), m_rc(nullptr), m_destroy(nullptr) {} + + Handle::Handle(uint64_t id, const HandleDestroyFunction &destroy) : + m_id(id), m_rc(new uint64_t(1)), m_destroy(destroy) {} + Handle::~Handle() { if ((m_rc) && (*m_rc > 0) && (--(*m_rc) == 0)) { if (m_destroy) { m_destroy(m_id); } - + delete m_rc; } } - + Handle::Handle(const Handle &other) : - m_id(other.m_id), - m_rc(other.m_rc), - m_destroy(other.m_destroy) - { + m_id(other.m_id), m_rc(other.m_rc), m_destroy(other.m_destroy) { if (m_rc) { ++(*m_rc); } } - + Handle::Handle(Handle &&other) noexcept : - m_id(other.m_id), - m_rc(other.m_rc), - m_destroy(other.m_destroy) - { + m_id(other.m_id), m_rc(other.m_rc), m_destroy(other.m_destroy) { other.m_rc = nullptr; } - + Handle &Handle::operator=(const Handle &other) { if (&other == this) { return *this; } - + m_id = other.m_id; m_rc = other.m_rc; m_destroy = other.m_destroy; - + if (m_rc) { ++(*m_rc); } - + return *this; } - + Handle &Handle::operator=(Handle &&other) noexcept { m_id = other.m_id; m_rc = other.m_rc; m_destroy = other.m_destroy; - + other.m_rc = nullptr; - + return *this; } - + uint64_t Handle::getId() const { return m_id; } - + uint64_t Handle::getRC() const { - return m_rc? *m_rc : 0; + return m_rc ? *m_rc : 0; } - + Handle::operator bool() const { return (m_id < UINT64_MAX); } - + bool Handle::operator!() const { return (m_id == UINT64_MAX); } - - std::ostream& operator << (std::ostream& out, const Handle& handle) { + + std::ostream &operator<<(std::ostream &out, const Handle &handle) { if (handle) { - return out << "[" << typeid(handle).name() << ": " << handle.getId() << ":" << handle.getRC() << "]"; + return out << "[" << typeid(handle).name() << ": " << handle.getId() << ":" + << handle.getRC() << "]"; } else { return out << "[" << typeid(handle).name() << ": none]"; } } - + bool ImageHandle::isSwapchainImage() const { return (getId() == UINT64_MAX - 1); } - + ImageHandle ImageHandle::createSwapchainImageHandle(const HandleDestroyFunction &destroy) { return ImageHandle(uint64_t(UINT64_MAX - 1), destroy); } - -} + +} // namespace vkcv diff --git a/src/vkcv/Image.cpp b/src/vkcv/Image.cpp index e17b95fe719805faa5b200686e529fc700400dd4..6e5b5fc1b3efbbcf4203e9825230eca20cbf55e5 100644 --- a/src/vkcv/Image.cpp +++ b/src/vkcv/Image.cpp @@ -5,48 +5,48 @@ */ #include "vkcv/Image.hpp" -#include "vkcv/Downsampler.hpp" #include "ImageManager.hpp" +#include "vkcv/Downsampler.hpp" + +namespace vkcv { -namespace vkcv{ - bool isDepthFormat(const vk::Format format) { switch (format) { - case(vk::Format::eD16Unorm): - case(vk::Format::eD16UnormS8Uint): - case(vk::Format::eD24UnormS8Uint): - case(vk::Format::eD32Sfloat): - case(vk::Format::eD32SfloatS8Uint): - return true; - default: - return false; + case (vk::Format::eD16Unorm): + case (vk::Format::eD16UnormS8Uint): + case (vk::Format::eD24UnormS8Uint): + case (vk::Format::eD32Sfloat): + case (vk::Format::eD32SfloatS8Uint): + return true; + default: + return false; } } - + bool isStencilFormat(const vk::Format format) { switch (format) { - case(vk::Format::eS8Uint): - case(vk::Format::eD16UnormS8Uint): - case(vk::Format::eD24UnormS8Uint): - case(vk::Format::eD32SfloatS8Uint): - return true; - default: - return false; + case (vk::Format::eS8Uint): + case (vk::Format::eD16UnormS8Uint): + case (vk::Format::eD24UnormS8Uint): + case (vk::Format::eD32SfloatS8Uint): + return true; + default: + return false; } } - + vk::Format Image::getFormat() const { return m_core->getImageFormat(m_handle); } - + uint32_t Image::getWidth() const { return m_core->getImageWidth(m_handle); } - + uint32_t Image::getHeight() const { return m_core->getImageHeight(m_handle); } - + uint32_t Image::getDepth() const { return m_core->getImageDepth(m_handle); } @@ -55,7 +55,7 @@ namespace vkcv{ m_core->switchImageLayout(m_handle, newLayout); } - const vkcv::ImageHandle& Image::getHandle() const { + const vkcv::ImageHandle &Image::getHandle() const { return m_handle; } @@ -63,34 +63,21 @@ namespace vkcv{ return m_core->getImageMipLevels(m_handle); } - void Image::fill(const void *data, size_t size) { + void Image::fill(const void* data, size_t size) { m_core->fillImage(m_handle, data, size); } - void Image::recordMipChainGeneration(const vkcv::CommandStreamHandle& cmdStream, + void Image::recordMipChainGeneration(const vkcv::CommandStreamHandle &cmdStream, Downsampler &downsampler) { downsampler.recordDownsampling(cmdStream, m_handle); } - - Image image(Core &core, - vk::Format format, - uint32_t width, - uint32_t height, - uint32_t depth, - bool createMipChain, - bool supportStorage, - bool supportColorAttachment, + + Image image(Core &core, vk::Format format, uint32_t width, uint32_t height, uint32_t depth, + bool createMipChain, bool supportStorage, bool supportColorAttachment, Multisampling multisampling) { - return Image(&core, core.createImage( - format, - width, - height, - depth, - createMipChain, - supportStorage, - supportColorAttachment, - multisampling - )); + return Image(&core, + core.createImage(format, width, height, depth, createMipChain, supportStorage, + supportColorAttachment, multisampling)); } -} +} // namespace vkcv diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp index fbe109da5ee10d43d011c0120abcdff78934a7d7..993243cb5644dd3a1527f3c50efadc9fdc9aa299 100644 --- a/src/vkcv/ImageManager.cpp +++ b/src/vkcv/ImageManager.cpp @@ -13,201 +13,188 @@ #include <algorithm> namespace vkcv { - + bool ImageManager::init(Core &core, BufferManager &bufferManager) { if (!HandleManager<ImageEntry, ImageHandle>::init(core)) { return false; } - + m_bufferManager = &bufferManager; m_swapchainImages.clear(); return true; } - + uint64_t ImageManager::getIdFrom(const ImageHandle &handle) const { return handle.getId(); } - + ImageHandle ImageManager::createById(uint64_t id, const HandleDestroyFunction &destroy) { return ImageHandle(id, destroy); } - + void ImageManager::destroyById(uint64_t id) { - auto& image = getById(id); - - const vk::Device& device = getCore().getContext().getDevice(); - - for (auto& view : image.m_viewPerMip) { + auto &image = getById(id); + + const vk::Device &device = getCore().getContext().getDevice(); + + for (auto &view : image.m_viewPerMip) { if (view) { device.destroyImageView(view); view = nullptr; } } - - for (auto& view : image.m_arrayViewPerMip) { + + for (auto &view : image.m_arrayViewPerMip) { if (view) { device.destroyImageView(view); view = nullptr; } } - - const vma::Allocator& allocator = getCore().getContext().getAllocator(); - + + const vma::Allocator &allocator = getCore().getContext().getAllocator(); + if (image.m_handle) { allocator.destroyImage(image.m_handle, image.m_allocation); - + image.m_handle = nullptr; image.m_allocation = nullptr; } } - + const BufferManager &ImageManager::getBufferManager() const { return *m_bufferManager; } - + BufferManager &ImageManager::getBufferManager() { return *m_bufferManager; } - + void ImageManager::recordImageMipGenerationToCmdBuffer(vk::CommandBuffer cmdBuffer, - const ImageHandle& handle) { - auto& image = (*this)[handle]; + const ImageHandle &handle) { + auto &image = (*this) [handle]; recordImageLayoutTransition(handle, 0, 0, vk::ImageLayout::eGeneral, cmdBuffer); - + vk::ImageAspectFlags aspectMask = isDepthImageFormat(image.m_format) ? - vk::ImageAspectFlagBits::eDepth : vk::ImageAspectFlagBits::eColor; - + 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); - + 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 ImageEntry &ImageManager::operator[](const ImageHandle &handle) const { if (handle.isSwapchainImage()) { - return m_swapchainImages[m_currentSwapchainInputImage]; + return m_swapchainImages [m_currentSwapchainInputImage]; } - + return HandleManager<ImageEntry, ImageHandle>::operator[](handle); } - + ImageEntry &ImageManager::operator[](const ImageHandle &handle) { if (handle.isSwapchainImage()) { - return m_swapchainImages[m_currentSwapchainInputImage]; + return m_swapchainImages [m_currentSwapchainInputImage]; } - + return HandleManager<ImageEntry, ImageHandle>::operator[](handle); } - + ImageManager::ImageManager() noexcept : - HandleManager<ImageEntry, ImageHandle>(), - m_bufferManager(nullptr), - m_swapchainImages(), - m_currentSwapchainInputImage(0) - {} - + HandleManager<ImageEntry, ImageHandle>(), m_bufferManager(nullptr), m_swapchainImages(), + m_currentSwapchainInputImage(0) {} + ImageManager::~ImageManager() noexcept { clear(); - - for (const auto& swapchainImage : m_swapchainImages) { + + for (const auto &swapchainImage : m_swapchainImages) { for (const auto view : swapchainImage.m_viewPerMip) { getCore().getContext().getDevice().destroy(view); } } } - + bool isDepthImageFormat(vk::Format format) { - if ((format == vk::Format::eD16Unorm) || (format == vk::Format::eD16UnormS8Uint) || - (format == vk::Format::eD24UnormS8Uint) || (format == vk::Format::eD32Sfloat) || - (format == vk::Format::eD32SfloatS8Uint)) { + if ((format == vk::Format::eD16Unorm) || (format == vk::Format::eD16UnormS8Uint) + || (format == vk::Format::eD24UnormS8Uint) || (format == vk::Format::eD32Sfloat) + || (format == vk::Format::eD32SfloatS8Uint)) { return true; } else { return false; } } - ImageHandle ImageManager::createImage( - uint32_t width, - uint32_t height, - uint32_t depth, - vk::Format format, - uint32_t mipCount, - bool supportStorage, - bool supportColorAttachment, - Multisampling msaa) { - const vk::PhysicalDevice& physicalDevice = getCore().getContext().getPhysicalDevice(); - + ImageHandle ImageManager::createImage(uint32_t width, uint32_t height, uint32_t depth, + vk::Format format, uint32_t mipCount, bool supportStorage, + bool supportColorAttachment, Multisampling msaa) { + const vk::PhysicalDevice &physicalDevice = getCore().getContext().getPhysicalDevice(); + const vk::FormatProperties formatProperties = physicalDevice.getFormatProperties(format); - + vk::ImageCreateFlags createFlags; - vk::ImageUsageFlags imageUsageFlags = ( - vk::ImageUsageFlagBits::eSampled | - vk::ImageUsageFlagBits::eTransferDst | - vk::ImageUsageFlagBits::eTransferSrc - ); - + vk::ImageUsageFlags imageUsageFlags = + (vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst + | vk::ImageUsageFlagBits::eTransferSrc); + vk::ImageTiling imageTiling = vk::ImageTiling::eOptimal; - + if (supportStorage) { imageUsageFlags |= vk::ImageUsageFlagBits::eStorage; - - if (!(formatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eStorageImage)) { + + if (!(formatProperties.optimalTilingFeatures + & vk::FormatFeatureFlagBits::eStorageImage)) { imageTiling = vk::ImageTiling::eLinear; - - if (!(formatProperties.linearTilingFeatures & vk::FormatFeatureFlagBits::eStorageImage)) + + if (!(formatProperties.linearTilingFeatures + & vk::FormatFeatureFlagBits::eStorageImage)) return {}; } } - + if (supportColorAttachment) { imageUsageFlags |= vk::ImageUsageFlagBits::eColorAttachment; } - + const bool isDepthFormat = isDepthImageFormat(format); - + if (isDepthFormat) { imageUsageFlags |= vk::ImageUsageFlagBits::eDepthStencilAttachment; } - const vma::Allocator& allocator = getCore().getContext().getAllocator(); + const vma::Allocator &allocator = getCore().getContext().getAllocator(); vk::ImageType imageType = vk::ImageType::e3D; vk::ImageViewType imageViewType = vk::ImageViewType::e3D; - + if (depth <= 1) { if (height <= 1) { imageType = vk::ImageType::e1D; @@ -217,185 +204,128 @@ namespace vkcv { imageViewType = vk::ImageViewType::e2D; } } - + if (isDepthFormat) { imageType = vk::ImageType::e2D; imageViewType = vk::ImageViewType::e2D; } - + if (vk::ImageType::e3D == imageType) { createFlags |= vk::ImageCreateFlagBits::e2DArrayCompatible; } - + if (!formatProperties.optimalTilingFeatures) { if (!formatProperties.linearTilingFeatures) return {}; - + 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 arrayLayers = std::min<uint32_t>(1, imageFormatProperties.maxArrayLayers); - const vk::ImageCreateInfo imageCreateInfo ( - createFlags, - imageType, - format, - vk::Extent3D(width, height, depth), - mipCount, - arrayLayers, - msaaToSampleCountFlagBits(msaa), - imageTiling, - imageUsageFlags, - vk::SharingMode::eExclusive, - {}, - vk::ImageLayout::eUndefined - ); - + const vk::ImageCreateInfo imageCreateInfo( + createFlags, imageType, format, vk::Extent3D(width, height, depth), mipCount, + arrayLayers, msaaToSampleCountFlagBits(msaa), imageTiling, imageUsageFlags, + vk::SharingMode::eExclusive, {}, vk::ImageLayout::eUndefined); + auto imageAllocation = allocator.createImage( - imageCreateInfo, - vma::AllocationCreateInfo( - vma::AllocationCreateFlags(), - vma::MemoryUsage::eGpuOnly, - vk::MemoryPropertyFlagBits::eDeviceLocal, - vk::MemoryPropertyFlagBits::eDeviceLocal, - 0, - vma::Pool(), - nullptr - ) - ); + imageCreateInfo, + vma::AllocationCreateInfo(vma::AllocationCreateFlags(), vma::MemoryUsage::eGpuOnly, + vk::MemoryPropertyFlagBits::eDeviceLocal, + vk::MemoryPropertyFlagBits::eDeviceLocal, 0, vma::Pool(), + nullptr)); vk::Image image = imageAllocation.first; vma::Allocation allocation = imageAllocation.second; vk::ImageAspectFlags aspectFlags; - + if (isDepthFormat) { aspectFlags = vk::ImageAspectFlagBits::eDepth; } else { aspectFlags = vk::ImageAspectFlagBits::eColor; } - - const vk::Device& device = getCore().getContext().getDevice(); - + + const vk::Device &device = getCore().getContext().getDevice(); + std::vector<vk::ImageView> views; std::vector<vk::ImageView> arrayViews; - + for (uint32_t 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::ImageSubresourceRange( - aspectFlags, - mip, - mipCount - mip, - 0, - arrayLayers - ) - ); - + {}, image, imageViewType, format, + vk::ComponentMapping( + vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity, + vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity), + vk::ImageSubresourceRange(aspectFlags, mip, mipCount - mip, 0, arrayLayers)); + views.push_back(device.createImageView(imageViewCreateInfo)); } - + for (uint32_t mip = 0; mip < mipCount; mip++) { const vk::ImageViewCreateInfo imageViewCreateInfo( - {}, - image, - vk::ImageViewType::e2DArray, - format, - vk::ComponentMapping( - vk::ComponentSwizzle::eIdentity, - vk::ComponentSwizzle::eIdentity, - vk::ComponentSwizzle::eIdentity, - vk::ComponentSwizzle::eIdentity - ), - vk::ImageSubresourceRange( - aspectFlags, - mip, - 1, - 0, - arrayLayers - ) - ); - + {}, image, vk::ImageViewType::e2DArray, format, + vk::ComponentMapping( + vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity, + vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity), + vk::ImageSubresourceRange(aspectFlags, mip, 1, 0, arrayLayers)); + arrayViews.push_back(device.createImageView(imageViewCreateInfo)); } - - return add({ - image, - allocation, - - views, - arrayViews, - - width, - height, - depth, - - format, - arrayLayers, - vk::ImageLayout::eUndefined, - supportStorage - }); - } - + + return add({ image, allocation, + + views, arrayViews, + + width, height, depth, + + format, arrayLayers, vk::ImageLayout::eUndefined, supportStorage }); + } + ImageHandle ImageManager::createSwapchainImage() const { return ImageHandle::createSwapchainImageHandle(); } - + vk::Image ImageManager::getVulkanImage(const ImageHandle &handle) const { - auto& image = (*this)[handle]; + auto &image = (*this) [handle]; return image.m_handle; } - + vk::DeviceMemory ImageManager::getVulkanDeviceMemory(const ImageHandle &handle) const { if (handle.isSwapchainImage()) { vkcv_log(LogLevel::ERROR, "Swapchain image has no memory"); return nullptr; } - - auto& image = (*this)[handle]; - const vma::Allocator& allocator = getCore().getContext().getAllocator(); - - auto info = allocator.getAllocationInfo( - image.m_allocation - ); - + + auto &image = (*this) [handle]; + const vma::Allocator &allocator = getCore().getContext().getAllocator(); + + auto info = allocator.getAllocationInfo(image.m_allocation); + return info.deviceMemory; } - - vk::ImageView ImageManager::getVulkanImageView(const ImageHandle &handle, - size_t mipLevel, + + vk::ImageView ImageManager::getVulkanImageView(const ImageHandle &handle, size_t mipLevel, bool arrayView) const { if (handle.isSwapchainImage()) { - return m_swapchainImages[m_currentSwapchainInputImage].m_viewPerMip[0]; + return m_swapchainImages [m_currentSwapchainInputImage].m_viewPerMip [0]; } - - const auto& image = (*this)[handle]; - const auto& views = arrayView? image.m_arrayViewPerMip : image.m_viewPerMip; - + + const auto &image = (*this) [handle]; + const auto &views = arrayView ? image.m_arrayViewPerMip : image.m_viewPerMip; + if (mipLevel >= views.size()) { vkcv_log(LogLevel::ERROR, "Image does not have requested mipLevel"); return nullptr; } - - return views[mipLevel]; + + return views [mipLevel]; } - + static vk::ImageMemoryBarrier createImageLayoutTransitionBarrier(const ImageEntry &image, uint32_t mipLevelCount, uint32_t mipLevelOffset, @@ -406,268 +336,211 @@ namespace vkcv { } else { aspectFlags = vk::ImageAspectFlagBits::eColor; } - + const uint32_t mipLevelsMax = image.m_viewPerMip.size(); - + if (mipLevelOffset > mipLevelsMax) mipLevelOffset = mipLevelsMax; - + if ((!mipLevelCount) || (mipLevelOffset + mipLevelCount > mipLevelsMax)) mipLevelCount = mipLevelsMax - mipLevelOffset; - - vk::ImageSubresourceRange imageSubresourceRange( - aspectFlags, - mipLevelOffset, - mipLevelCount, - 0, - image.m_layers - ); - + + vk::ImageSubresourceRange imageSubresourceRange(aspectFlags, mipLevelOffset, mipLevelCount, + 0, image.m_layers); + // TODO: precise AccessFlagBits, will require a lot of context - return vk::ImageMemoryBarrier( - vk::AccessFlagBits::eMemoryWrite, - vk::AccessFlagBits::eMemoryRead, - image.m_layout, - newLayout, - VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_IGNORED, - image.m_handle, - imageSubresourceRange - ); - } - - void ImageManager::switchImageLayoutImmediate(const ImageHandle& handle, vk::ImageLayout newLayout) { - auto& image = (*this)[handle]; + return vk::ImageMemoryBarrier(vk::AccessFlagBits::eMemoryWrite, + vk::AccessFlagBits::eMemoryRead, image.m_layout, newLayout, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + image.m_handle, imageSubresourceRange); + } + + void ImageManager::switchImageLayoutImmediate(const ImageHandle &handle, + vk::ImageLayout newLayout) { + auto &image = (*this) [handle]; const auto transitionBarrier = createImageLayoutTransitionBarrier(image, 0, 0, newLayout); - - auto& core = getCore(); + + auto &core = getCore(); auto stream = core.createCommandStream(QueueType::Graphics); - + core.recordCommandsToStream( stream, - [transitionBarrier](const vk::CommandBuffer& commandBuffer) { - // TODO: precise PipelineStageFlagBits, will require a lot of context - commandBuffer.pipelineBarrier( - vk::PipelineStageFlagBits::eTopOfPipe, - vk::PipelineStageFlagBits::eBottomOfPipe, - {}, - nullptr, - nullptr, - transitionBarrier - ); + [transitionBarrier](const vk::CommandBuffer &commandBuffer) { + // TODO: precise PipelineStageFlagBits, will require a lot of context + commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, + vk::PipelineStageFlagBits::eBottomOfPipe, {}, nullptr, + nullptr, transitionBarrier); }, - nullptr - ); - + nullptr); + core.submitCommandStream(stream, false); image.m_layout = newLayout; } - void ImageManager::recordImageLayoutTransition(const ImageHandle& handle, - uint32_t mipLevelCount, - uint32_t mipLevelOffset, + void ImageManager::recordImageLayoutTransition(const ImageHandle &handle, + uint32_t mipLevelCount, uint32_t mipLevelOffset, vk::ImageLayout newLayout, vk::CommandBuffer cmdBuffer) { - auto& image = (*this)[handle]; - const auto transitionBarrier = createImageLayoutTransitionBarrier( - image, - mipLevelCount, - mipLevelOffset, - newLayout - ); - - cmdBuffer.pipelineBarrier( - vk::PipelineStageFlagBits::eAllCommands, - vk::PipelineStageFlagBits::eAllCommands, - {}, - nullptr, - nullptr, - transitionBarrier - ); - + auto &image = (*this) [handle]; + const auto transitionBarrier = + createImageLayoutTransitionBarrier(image, mipLevelCount, mipLevelOffset, newLayout); + + cmdBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands, + vk::PipelineStageFlagBits::eAllCommands, {}, nullptr, nullptr, + transitionBarrier); + image.m_layout = newLayout; } - void ImageManager::recordImageMemoryBarrier(const ImageHandle& handle, + void ImageManager::recordImageMemoryBarrier(const ImageHandle &handle, vk::CommandBuffer cmdBuffer) { - auto& image = (*this)[handle]; - const auto transitionBarrier = createImageLayoutTransitionBarrier(image, 0, 0, image.m_layout); - - cmdBuffer.pipelineBarrier( - vk::PipelineStageFlagBits::eAllCommands, - vk::PipelineStageFlagBits::eAllCommands, - {}, - nullptr, - nullptr, - transitionBarrier - ); - } - + auto &image = (*this) [handle]; + const auto transitionBarrier = + createImageLayoutTransitionBarrier(image, 0, 0, image.m_layout); + + cmdBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands, + vk::PipelineStageFlagBits::eAllCommands, {}, nullptr, nullptr, + transitionBarrier); + } + constexpr uint32_t getBytesPerPixel(vk::Format format) { switch (format) { - case vk::Format::eR8Unorm: - return 1; - case vk::Format::eR16Unorm: - return 2; - case vk::Format::eR32Uint: - case vk::Format::eR8G8B8A8Srgb: - case vk::Format::eR8G8B8A8Unorm: - return 4; - case vk::Format::eR16G16B16A16Sfloat: - return 8; - case vk::Format::eR32G32B32A32Sfloat: - return 16; - default: - std::cerr << "Unknown image format" << std::endl; - return 4; + case vk::Format::eR8Unorm: + return 1; + case vk::Format::eR16Unorm: + return 2; + case vk::Format::eR32Uint: + case vk::Format::eR8G8B8A8Srgb: + case vk::Format::eR8G8B8A8Unorm: + return 4; + case vk::Format::eR16G16B16A16Sfloat: + return 8; + case vk::Format::eR32G32B32A32Sfloat: + return 16; + default: + std::cerr << "Unknown image format" << std::endl; + return 4; } } - - void ImageManager::fillImage(const ImageHandle& handle, const void* data, size_t size) { + + void ImageManager::fillImage(const ImageHandle &handle, const void* data, size_t size) { if (handle.isSwapchainImage()) { vkcv_log(LogLevel::ERROR, "Swapchain image cannot be filled"); return; } - - auto& image = (*this)[handle]; + + auto &image = (*this) [handle]; switchImageLayoutImmediate(handle, vk::ImageLayout::eTransferDstOptimal); - - const size_t image_size = ( - image.m_width * image.m_height * image.m_depth * - getBytesPerPixel(image.m_format) - ); - + + const size_t image_size = + (image.m_width * image.m_height * image.m_depth * getBytesPerPixel(image.m_format)); + const size_t max_size = std::min(size, image_size); - + BufferHandle bufferHandle = getBufferManager().createBuffer( - TypeGuard(1), - BufferType::STAGING, - BufferMemoryType::DEVICE_LOCAL, - max_size, - false - ); - + TypeGuard(1), BufferType::STAGING, BufferMemoryType::DEVICE_LOCAL, max_size, false); + getBufferManager().fillBuffer(bufferHandle, data, max_size, 0); - + vk::Buffer stagingBuffer = getBufferManager().getBuffer(bufferHandle); - - auto& core = getCore(); + + auto &core = getCore(); auto stream = core.createCommandStream(QueueType::Transfer); - + core.recordCommandsToStream( - stream, - [&image, &stagingBuffer](const vk::CommandBuffer& commandBuffer) { - vk::ImageAspectFlags aspectFlags; - - if (isDepthImageFormat(image.m_format)) { - aspectFlags = vk::ImageAspectFlagBits::eDepth; - } else { - aspectFlags = vk::ImageAspectFlagBits::eColor; - } - - const vk::BufferImageCopy region ( - 0, - 0, - 0, - vk::ImageSubresourceLayers( - aspectFlags, - 0, - 0, - image.m_layers - ), - vk::Offset3D(0, 0, 0), - vk::Extent3D(image.m_width, image.m_height, image.m_depth) - ); - - commandBuffer.copyBufferToImage( - stagingBuffer, - image.m_handle, - vk::ImageLayout::eTransferDstOptimal, - 1, - ®ion - ); - }, - [&]() { - switchImageLayoutImmediate(handle,vk::ImageLayout::eShaderReadOnlyOptimal); + stream, + [&image, &stagingBuffer](const vk::CommandBuffer &commandBuffer) { + vk::ImageAspectFlags aspectFlags; + + if (isDepthImageFormat(image.m_format)) { + aspectFlags = vk::ImageAspectFlagBits::eDepth; + } else { + aspectFlags = vk::ImageAspectFlagBits::eColor; } - ); - + + const vk::BufferImageCopy region( + 0, 0, 0, vk::ImageSubresourceLayers(aspectFlags, 0, 0, image.m_layers), + vk::Offset3D(0, 0, 0), + vk::Extent3D(image.m_width, image.m_height, image.m_depth)); + + commandBuffer.copyBufferToImage(stagingBuffer, image.m_handle, + vk::ImageLayout::eTransferDstOptimal, 1, ®ion); + }, + [&]() { + switchImageLayoutImmediate(handle, vk::ImageLayout::eShaderReadOnlyOptimal); + }); + core.submitCommandStream(stream, false); } - void ImageManager::recordImageMipChainGenerationToCmdStream(const vkcv::CommandStreamHandle& cmdStream, - const ImageHandle& handle) { + void ImageManager::recordImageMipChainGenerationToCmdStream( + const vkcv::CommandStreamHandle &cmdStream, const ImageHandle &handle) { const auto record = [this, handle](const vk::CommandBuffer cmdBuffer) { recordImageMipGenerationToCmdBuffer(cmdBuffer, handle); }; - + getCore().recordCommandsToStream(cmdStream, record, nullptr); } - void ImageManager::recordMSAAResolve(vk::CommandBuffer cmdBuffer, - const ImageHandle& src, - const ImageHandle& dst) { - auto& srcImage = (*this)[src]; - auto& dstImage = (*this)[dst]; - + void ImageManager::recordMSAAResolve(vk::CommandBuffer cmdBuffer, const ImageHandle &src, + const ImageHandle &dst) { + auto &srcImage = (*this) [src]; + auto &dstImage = (*this) [dst]; + vk::ImageResolve region( vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), vk::Offset3D(0, 0, 0), vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), - vk::Offset3D(0, 0, 0), + vk::Offset3D(0, 0, 0), vk::Extent3D(dstImage.m_width, dstImage.m_height, dstImage.m_depth)); recordImageLayoutTransition(src, 0, 0, vk::ImageLayout::eTransferSrcOptimal, cmdBuffer); recordImageLayoutTransition(dst, 0, 0, vk::ImageLayout::eTransferDstOptimal, cmdBuffer); - cmdBuffer.resolveImage( - srcImage.m_handle, - srcImage.m_layout, - dstImage.m_handle, - dstImage.m_layout, - region); + cmdBuffer.resolveImage(srcImage.m_handle, srcImage.m_layout, dstImage.m_handle, + dstImage.m_layout, region); } uint32_t ImageManager::getImageWidth(const ImageHandle &handle) const { - auto& image = (*this)[handle]; + auto &image = (*this) [handle]; return image.m_width; } - + uint32_t ImageManager::getImageHeight(const ImageHandle &handle) const { - auto& image = (*this)[handle]; + auto &image = (*this) [handle]; return image.m_height; } - + uint32_t ImageManager::getImageDepth(const ImageHandle &handle) const { - auto& image = (*this)[handle]; + auto &image = (*this) [handle]; return image.m_depth; } - vk::Format ImageManager::getImageFormat(const ImageHandle& handle) const { - auto& image = (*this)[handle]; + vk::Format ImageManager::getImageFormat(const ImageHandle &handle) const { + auto &image = (*this) [handle]; return image.m_format; } - - bool ImageManager::isImageSupportingStorage(const ImageHandle& handle) const { + + bool ImageManager::isImageSupportingStorage(const ImageHandle &handle) const { if (handle.isSwapchainImage()) { return false; } - - auto& image = (*this)[handle]; + + auto &image = (*this) [handle]; return image.m_storage; } - uint32_t ImageManager::getImageMipCount(const ImageHandle& handle) const { + uint32_t ImageManager::getImageMipCount(const ImageHandle &handle) const { if (handle.isSwapchainImage()) { return 1; } - - auto& image = (*this)[handle]; + + auto &image = (*this) [handle]; return image.m_viewPerMip.size(); } - - uint32_t ImageManager::getImageArrayLayers(const ImageHandle& handle) const { - auto& image = (*this)[handle]; + + uint32_t ImageManager::getImageArrayLayers(const ImageHandle &handle) const { + auto &image = (*this) [handle]; return image.m_layers; } @@ -675,15 +548,13 @@ namespace vkcv { m_currentSwapchainInputImage = index; } - void ImageManager::setSwapchainImages(const std::vector<vk::Image>& images, - const std::vector<vk::ImageView>& views, - uint32_t width, - uint32_t height, - vk::Format format) { + void ImageManager::setSwapchainImages(const std::vector<vk::Image> &images, + const std::vector<vk::ImageView> &views, uint32_t width, + uint32_t height, vk::Format format) { // destroy old views - for (const auto& image : m_swapchainImages) { - for (const auto& view : image.m_viewPerMip) { + for (const auto &image : m_swapchainImages) { + for (const auto &view : image.m_viewPerMip) { getCore().getContext().getDevice().destroyImageView(view); } } @@ -691,26 +562,24 @@ namespace vkcv { assert(images.size() == views.size()); m_swapchainImages.clear(); for (size_t i = 0; i < images.size(); i++) { - m_swapchainImages.push_back({ - images[i], - nullptr, - { views[i] }, - {}, - width, - height, - 1, - format, - 1, - vk::ImageLayout::eUndefined, - false - }); + m_swapchainImages.push_back({ images [i], + nullptr, + { views [i] }, + {}, + width, + height, + 1, + format, + 1, + vk::ImageLayout::eUndefined, + false }); } } - void ImageManager::updateImageLayoutManual(const vkcv::ImageHandle& handle, + void ImageManager::updateImageLayoutManual(const vkcv::ImageHandle &handle, const vk::ImageLayout layout) { - auto& image = (*this)[handle]; + auto &image = (*this) [handle]; image.m_layout = layout; } -} \ No newline at end of file +} // namespace vkcv \ No newline at end of file diff --git a/src/vkcv/ImageManager.hpp b/src/vkcv/ImageManager.hpp index de91245c76a76ea0658a1fb69472d5f9059215e6..ddc44f9b519061a7881eb0904034da2276b82a12 100644 --- a/src/vkcv/ImageManager.hpp +++ b/src/vkcv/ImageManager.hpp @@ -5,15 +5,15 @@ * @brief class creating and managing images */ #include <vector> -#include <vulkan/vulkan.hpp> #include <vk_mem_alloc.hpp> +#include <vulkan/vulkan.hpp> #include "BufferManager.hpp" #include "HandleManager.hpp" #include "vkcv/Multisampling.hpp" namespace vkcv { - + /** * @brief Determine whether an image format is valid * for depth buffers. @@ -22,45 +22,44 @@ namespace vkcv { * @return True, if the format is usable for depth buffers, otherwise false. */ bool isDepthImageFormat(vk::Format format); - + struct ImageEntry { - vk::Image m_handle; - vma::Allocation m_allocation; - - std::vector<vk::ImageView> m_viewPerMip; - std::vector<vk::ImageView> m_arrayViewPerMip; - - uint32_t m_width; - uint32_t m_height; - uint32_t m_depth; - - vk::Format m_format; - uint32_t m_layers; - vk::ImageLayout m_layout; - bool m_storage; + vk::Image m_handle; + vma::Allocation m_allocation; + + std::vector<vk::ImageView> m_viewPerMip; + std::vector<vk::ImageView> m_arrayViewPerMip; + + uint32_t m_width; + uint32_t m_height; + uint32_t m_depth; + + vk::Format m_format; + uint32_t m_layers; + vk::ImageLayout m_layout; + bool m_storage; }; /** * @brief Class to manage the creation, destruction, allocation * and filling of images. */ - class ImageManager : HandleManager<ImageEntry, ImageHandle> - { + class ImageManager : HandleManager<ImageEntry, ImageHandle> { friend class Core; + private: BufferManager* m_bufferManager; - + std::vector<ImageEntry> m_swapchainImages; int m_currentSwapchainInputImage; - - bool init(Core& core, BufferManager& bufferManager); - - [[nodiscard]] - uint64_t getIdFrom(const ImageHandle& handle) const override; - - [[nodiscard]] - ImageHandle createById(uint64_t id, const HandleDestroyFunction& destroy) override; - + + bool init(Core &core, BufferManager &bufferManager); + + [[nodiscard]] uint64_t getIdFrom(const ImageHandle &handle) const override; + + [[nodiscard]] ImageHandle createById(uint64_t id, + const HandleDestroyFunction &destroy) override; + /** * Destroys and deallocates image represented by a given * image handle id. @@ -68,108 +67,78 @@ namespace vkcv { * @param id Image handle id */ void destroyById(uint64_t id) override; - - [[nodiscard]] - const BufferManager& getBufferManager() const; - - [[nodiscard]] - BufferManager& getBufferManager(); - - void recordImageMipGenerationToCmdBuffer(vk::CommandBuffer cmdBuffer, const ImageHandle& handle); - + + [[nodiscard]] const BufferManager &getBufferManager() const; + + [[nodiscard]] BufferManager &getBufferManager(); + + void recordImageMipGenerationToCmdBuffer(vk::CommandBuffer cmdBuffer, + const ImageHandle &handle); + protected: - [[nodiscard]] - virtual const ImageEntry& operator[](const ImageHandle& handle) const override; - - [[nodiscard]] - virtual ImageEntry& operator[](const ImageHandle& handle) override; - + [[nodiscard]] virtual const ImageEntry & + operator[](const ImageHandle &handle) const override; + + [[nodiscard]] virtual ImageEntry &operator[](const ImageHandle &handle) override; + public: ImageManager() noexcept; - + ~ImageManager() noexcept override; - - [[nodiscard]] - ImageHandle createImage( - uint32_t width, - uint32_t height, - uint32_t depth, - vk::Format format, - uint32_t mipCount, - bool supportStorage, - bool supportColorAttachment, - Multisampling msaa); - - [[nodiscard]] - ImageHandle createSwapchainImage() const; - - [[nodiscard]] - vk::Image getVulkanImage(const ImageHandle& handle) const; - - [[nodiscard]] - vk::DeviceMemory getVulkanDeviceMemory(const ImageHandle& handle) const; - - [[nodiscard]] - vk::ImageView getVulkanImageView(const ImageHandle& handle, - size_t mipLevel = 0, - bool arrayView = false) const; - - void switchImageLayoutImmediate(const ImageHandle& handle, - vk::ImageLayout newLayout); - - void recordImageLayoutTransition(const ImageHandle& handle, - uint32_t mipLevelCount, - uint32_t mipLevelOffset, - vk::ImageLayout newLayout, + + [[nodiscard]] ImageHandle createImage(uint32_t width, uint32_t height, uint32_t depth, + vk::Format format, uint32_t mipCount, + bool supportStorage, bool supportColorAttachment, + Multisampling msaa); + + [[nodiscard]] ImageHandle createSwapchainImage() const; + + [[nodiscard]] vk::Image getVulkanImage(const ImageHandle &handle) const; + + [[nodiscard]] vk::DeviceMemory getVulkanDeviceMemory(const ImageHandle &handle) const; + + [[nodiscard]] vk::ImageView getVulkanImageView(const ImageHandle &handle, + size_t mipLevel = 0, + bool arrayView = false) const; + + void switchImageLayoutImmediate(const ImageHandle &handle, vk::ImageLayout newLayout); + + void recordImageLayoutTransition(const ImageHandle &handle, uint32_t mipLevelCount, + uint32_t mipLevelOffset, vk::ImageLayout newLayout, vk::CommandBuffer cmdBuffer); - void recordImageMemoryBarrier(const ImageHandle& handle, - vk::CommandBuffer cmdBuffer); - - void fillImage(const ImageHandle& handle, - const void* data, - size_t size); - - void recordImageMipChainGenerationToCmdStream(const vkcv::CommandStreamHandle& cmdStream, - const ImageHandle& handle); - - void recordMSAAResolve(vk::CommandBuffer cmdBuffer, - const ImageHandle& src, - const ImageHandle& dst); - - [[nodiscard]] - uint32_t getImageWidth(const ImageHandle& handle) const; - - [[nodiscard]] - uint32_t getImageHeight(const ImageHandle& handle) const; - - [[nodiscard]] - uint32_t getImageDepth(const ImageHandle& handle) const; - - [[nodiscard]] - vk::Format getImageFormat(const ImageHandle& handle) const; - - [[nodiscard]] - bool isImageSupportingStorage(const ImageHandle& handle) const; - - [[nodiscard]] - uint32_t getImageMipCount(const ImageHandle& handle) const; - - [[nodiscard]] - uint32_t getImageArrayLayers(const ImageHandle& handle) const; + void recordImageMemoryBarrier(const ImageHandle &handle, vk::CommandBuffer cmdBuffer); + + void fillImage(const ImageHandle &handle, const void* data, size_t size); + + void recordImageMipChainGenerationToCmdStream(const vkcv::CommandStreamHandle &cmdStream, + const ImageHandle &handle); + + void recordMSAAResolve(vk::CommandBuffer cmdBuffer, const ImageHandle &src, + const ImageHandle &dst); + + [[nodiscard]] uint32_t getImageWidth(const ImageHandle &handle) const; + + [[nodiscard]] uint32_t getImageHeight(const ImageHandle &handle) const; + + [[nodiscard]] uint32_t getImageDepth(const ImageHandle &handle) const; + + [[nodiscard]] vk::Format getImageFormat(const ImageHandle &handle) const; + + [[nodiscard]] bool isImageSupportingStorage(const ImageHandle &handle) const; + + [[nodiscard]] uint32_t getImageMipCount(const ImageHandle &handle) const; + + [[nodiscard]] uint32_t getImageArrayLayers(const ImageHandle &handle) const; void setCurrentSwapchainImageIndex(int index); - - void setSwapchainImages(const std::vector<vk::Image>& images, - const std::vector<vk::ImageView>& views, - uint32_t width, - uint32_t height, - vk::Format format); - - // if manual vulkan work, e.g. ImGui integration, changes an image layout this function must be used - // to update the internal image state - void updateImageLayoutManual(const vkcv::ImageHandle& handle, - const vk::ImageLayout layout); + void setSwapchainImages(const std::vector<vk::Image> &images, + const std::vector<vk::ImageView> &views, uint32_t width, + uint32_t height, vk::Format format); + + // if manual vulkan work, e.g. ImGui integration, changes an image layout this function must + // be used to update the internal image state + void updateImageLayoutManual(const vkcv::ImageHandle &handle, const vk::ImageLayout layout); }; -} \ No newline at end of file +} // namespace vkcv \ No newline at end of file diff --git a/src/vkcv/Multisampling.cpp b/src/vkcv/Multisampling.cpp index 7b64dd06cbfbabf74ca777a840512d6eeffeb1ed..168ba0cf198491fb19cc29797d35d624f194b15d 100644 --- a/src/vkcv/Multisampling.cpp +++ b/src/vkcv/Multisampling.cpp @@ -1,38 +1,38 @@ -#include <vkcv/Multisampling.hpp> #include <vkcv/Logger.hpp> +#include <vkcv/Multisampling.hpp> namespace vkcv { - + vk::SampleCountFlagBits msaaToSampleCountFlagBits(Multisampling msaa) { switch (msaa) { - case Multisampling::None: - return vk::SampleCountFlagBits::e1; - case Multisampling::MSAA2X: - return vk::SampleCountFlagBits::e2; - case Multisampling::MSAA4X: - return vk::SampleCountFlagBits::e4; - case Multisampling::MSAA8X: - return vk::SampleCountFlagBits::e8; - default: - vkcv_log(vkcv::LogLevel::ERROR, "Unknown Multisampling enum setting"); - return vk::SampleCountFlagBits::e1; + case Multisampling::None: + return vk::SampleCountFlagBits::e1; + case Multisampling::MSAA2X: + return vk::SampleCountFlagBits::e2; + case Multisampling::MSAA4X: + return vk::SampleCountFlagBits::e4; + case Multisampling::MSAA8X: + return vk::SampleCountFlagBits::e8; + default: + vkcv_log(vkcv::LogLevel::ERROR, "Unknown Multisampling enum setting"); + return vk::SampleCountFlagBits::e1; } } uint32_t msaaToSampleCount(Multisampling msaa) { switch (msaa) { - case Multisampling::None: - return 1; - case Multisampling::MSAA2X: - return 2; - case Multisampling::MSAA4X: - return 4; - case Multisampling::MSAA8X: - return 8; - default: - vkcv_log(vkcv::LogLevel::ERROR, "Unknown Multisampling enum setting"); - return 1; + case Multisampling::None: + return 1; + case Multisampling::MSAA2X: + return 2; + case Multisampling::MSAA4X: + return 4; + case Multisampling::MSAA8X: + return 8; + default: + vkcv_log(vkcv::LogLevel::ERROR, "Unknown Multisampling enum setting"); + return 1; } } - -} \ No newline at end of file + +} // namespace vkcv \ No newline at end of file diff --git a/src/vkcv/Pass.cpp b/src/vkcv/Pass.cpp index 54482cd9d3189fd1e4ed5a15a07163b079105db4..0aaaa4a9771f7ff682d60e363a436de5ac13f5f5 100644 --- a/src/vkcv/Pass.cpp +++ b/src/vkcv/Pass.cpp @@ -2,46 +2,37 @@ #include "vkcv/Pass.hpp" namespace vkcv { - - PassHandle passFormats(Core &core, - const std::vector<vk::Format> formats, - bool clear, + + PassHandle passFormats(Core &core, const std::vector<vk::Format> formats, bool clear, Multisampling multisampling) { AttachmentDescriptions attachments; - + for (const auto format : formats) { - attachments.emplace_back( - format, - clear? AttachmentOperation::CLEAR : AttachmentOperation::LOAD, - AttachmentOperation::STORE - ); + attachments.emplace_back(format, + clear ? AttachmentOperation::CLEAR : AttachmentOperation::LOAD, + AttachmentOperation::STORE); } - - const PassConfig config (attachments, multisampling); + + const PassConfig config(attachments, multisampling); return core.createPass(config); } - - PassHandle passFormat(Core &core, - vk::Format format, - bool clear, - Multisampling multisampling) { + + PassHandle passFormat(Core &core, vk::Format format, bool clear, Multisampling multisampling) { return passFormats(core, { format }, clear, multisampling); } - - PassHandle passSwapchain(Core &core, - const SwapchainHandle &swapchain, - const std::vector<vk::Format> formats, - bool clear, + + PassHandle passSwapchain(Core &core, const SwapchainHandle &swapchain, + const std::vector<vk::Format> formats, bool clear, Multisampling multisampling) { - std::vector<vk::Format> swapchainFormats (formats); - - for (auto& format : swapchainFormats) { + std::vector<vk::Format> swapchainFormats(formats); + + for (auto &format : swapchainFormats) { if (vk::Format::eUndefined == format) { format = core.getSwapchainFormat(swapchain); } } - + return passFormats(core, swapchainFormats, clear, multisampling); } - -} + +} // namespace vkcv diff --git a/src/vkcv/PassConfig.cpp b/src/vkcv/PassConfig.cpp index 54f3f17f080ec01207a162532dc140e9abd92dd3..72310f209484a355afc461d72022ad9aa1cf4cbd 100644 --- a/src/vkcv/PassConfig.cpp +++ b/src/vkcv/PassConfig.cpp @@ -2,81 +2,61 @@ #include "vkcv/PassConfig.hpp" #include "vkcv/Image.hpp" -namespace vkcv -{ - - AttachmentDescription::AttachmentDescription(vk::Format format, - AttachmentOperation load, - AttachmentOperation store) - : m_format(format), - m_load_op(load), - m_store_op(store), - m_clear_value() - { +namespace vkcv { + + AttachmentDescription::AttachmentDescription(vk::Format format, AttachmentOperation load, + AttachmentOperation store) : + m_format(format), + m_load_op(load), m_store_op(store), m_clear_value() { if (isDepthFormat(format)) { - setClearValue(vk::ClearValue( - vk::ClearDepthStencilValue(1.0f, 0) - )); + setClearValue(vk::ClearValue(vk::ClearDepthStencilValue(1.0f, 0))); } else { setClearValue(vk::ClearValue( - vk::ClearColorValue(std::array<float, 4>{ - 0.0f, 0.0f, 0.0f, 0.0f - }) - )); + vk::ClearColorValue(std::array<float, 4> { 0.0f, 0.0f, 0.0f, 0.0f }))); } } - - AttachmentDescription::AttachmentDescription(vk::Format format, - AttachmentOperation load, + + AttachmentDescription::AttachmentDescription(vk::Format format, AttachmentOperation load, AttachmentOperation store, - const vk::ClearValue &clear) - : m_format(format), - m_load_op(load), - m_store_op(store), - m_clear_value(clear) - {} - + const vk::ClearValue &clear) : + m_format(format), + m_load_op(load), m_store_op(store), m_clear_value(clear) {} + vk::Format AttachmentDescription::getFormat() const { return m_format; } - + AttachmentOperation AttachmentDescription::getLoadOperation() const { return m_load_op; } - + AttachmentOperation AttachmentDescription::getStoreOperation() const { return m_store_op; } - + void AttachmentDescription::setClearValue(const vk::ClearValue &clear) { m_clear_value = clear; } - + const vk::ClearValue &AttachmentDescription::getClearValue() const { return m_clear_value; } - - PassConfig::PassConfig() - : m_attachments(), - m_multisampling(Multisampling::None) - {} - - PassConfig::PassConfig(const AttachmentDescriptions &attachments, - Multisampling multisampling) - : m_attachments(attachments), - m_multisampling(multisampling) - {} - + + PassConfig::PassConfig() : m_attachments(), m_multisampling(Multisampling::None) {} + + PassConfig::PassConfig(const AttachmentDescriptions &attachments, Multisampling multisampling) : + m_attachments(attachments), m_multisampling(multisampling) {} + const AttachmentDescriptions &PassConfig::getAttachments() const { return m_attachments; } - + void PassConfig::setMultisampling(Multisampling multisampling) { m_multisampling = multisampling; } - + Multisampling PassConfig::getMultisampling() const { return m_multisampling; } - -} + +} // namespace vkcv diff --git a/src/vkcv/PassManager.cpp b/src/vkcv/PassManager.cpp index 75343f4cecea4ac3d46180ccab4cf09d7a43a2a3..9b160bcf8c62eb5e3fe829a49d2e43d3f0eef1cb 100644 --- a/src/vkcv/PassManager.cpp +++ b/src/vkcv/PassManager.cpp @@ -1,174 +1,145 @@ #include "PassManager.hpp" -#include "vkcv/Image.hpp" #include "vkcv/Core.hpp" +#include "vkcv/Image.hpp" + +namespace vkcv { + + static vk::AttachmentStoreOp getVkStoreOpFromAttachOp(AttachmentOperation op) { + switch (op) { + case AttachmentOperation::STORE: + return vk::AttachmentStoreOp::eStore; + default: + return vk::AttachmentStoreOp::eDontCare; + } + } + + static vk::AttachmentLoadOp getVKLoadOpFromAttachOp(AttachmentOperation op) { + switch (op) { + case AttachmentOperation::LOAD: + return vk::AttachmentLoadOp::eLoad; + case AttachmentOperation::CLEAR: + return vk::AttachmentLoadOp::eClear; + default: + return vk::AttachmentLoadOp::eDontCare; + } + } -namespace vkcv -{ - - static vk::AttachmentStoreOp getVkStoreOpFromAttachOp(AttachmentOperation op) - { - switch(op) - { - case AttachmentOperation::STORE: - return vk::AttachmentStoreOp::eStore; - default: - return vk::AttachmentStoreOp::eDontCare; - } - } - - static vk::AttachmentLoadOp getVKLoadOpFromAttachOp(AttachmentOperation op) - { - switch(op) - { - case AttachmentOperation::LOAD: - return vk::AttachmentLoadOp::eLoad; - case AttachmentOperation::CLEAR: - return vk::AttachmentLoadOp::eClear; - default: - return vk::AttachmentLoadOp::eDontCare; - } - } - uint64_t PassManager::getIdFrom(const PassHandle &handle) const { return handle.getId(); } - + PassHandle PassManager::createById(uint64_t id, const HandleDestroyFunction &destroy) { return PassHandle(id, destroy); } - + void PassManager::destroyById(uint64_t id) { - auto& pass = getById(id); - + auto &pass = getById(id); + if (pass.m_Handle) { getCore().getContext().getDevice().destroy(pass.m_Handle); pass.m_Handle = nullptr; } } - + PassManager::PassManager() noexcept : HandleManager<PassEntry, PassHandle>() {} - + PassManager::~PassManager() noexcept { - clear(); - } - - PassHandle PassManager::createPass(const PassConfig &config) { - // description of all {color, input, depth/stencil} attachments of the render pass - std::vector<vk::AttachmentDescription> attachmentDescriptions{}; - - // individual references to color attachments (of a subpass) - std::vector<vk::AttachmentReference> colorAttachmentReferences{}; - // individual reference to depth attachment (of a subpass) - vk::AttachmentReference depthStencilAttachmentRef; - + clear(); + } + + PassHandle PassManager::createPass(const PassConfig &config) { + // description of all {color, input, depth/stencil} attachments of the render pass + std::vector<vk::AttachmentDescription> attachmentDescriptions {}; + + // individual references to color attachments (of a subpass) + std::vector<vk::AttachmentReference> colorAttachmentReferences {}; + // individual reference to depth attachment (of a subpass) + vk::AttachmentReference depthStencilAttachmentRef; + // stays nullptr if no depth attachment used - vk::AttachmentReference *pDepthStencil = nullptr; - + vk::AttachmentReference* pDepthStencil = nullptr; + const auto &featureManager = getCore().getContext().getFeatureManager(); - - const bool separateDepthStencil = ( - featureManager.checkFeatures<vk::PhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR>( + + const bool separateDepthStencil = + (featureManager.checkFeatures<vk::PhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR>( vk::StructureType::ePhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR, - [](const vk::PhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR& features) { + [](const vk::PhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR &features) { return features.separateDepthStencilLayouts; - } - ) - ); - - const auto& attachments = config.getAttachments(); - + })); + + const auto &attachments = config.getAttachments(); + std::vector<vk::ImageLayout> layouts; layouts.reserve(attachments.size()); - for (uint32_t i = 0; i < attachments.size(); i++) { - vk::Format format = attachments[i].getFormat(); - vk::ImageLayout layout; - - bool depthFormat = isDepthFormat(attachments[i].getFormat()); - bool stencilFormat = isStencilFormat(attachments[i].getFormat()); - - if ((separateDepthStencil) && (depthFormat) && (!stencilFormat)) { + for (uint32_t i = 0; i < attachments.size(); i++) { + vk::Format format = attachments [i].getFormat(); + vk::ImageLayout layout; + + bool depthFormat = isDepthFormat(attachments [i].getFormat()); + bool stencilFormat = isStencilFormat(attachments [i].getFormat()); + + if ((separateDepthStencil) && (depthFormat) && (!stencilFormat)) { layout = vk::ImageLayout::eDepthAttachmentOptimal; - } else - if ((separateDepthStencil) && (!depthFormat) && (stencilFormat)) { + } else if ((separateDepthStencil) && (!depthFormat) && (stencilFormat)) { layout = vk::ImageLayout::eStencilAttachmentOptimal; - } else - if ((depthFormat) || (stencilFormat)) { + } else if ((depthFormat) || (stencilFormat)) { layout = vk::ImageLayout::eDepthStencilAttachmentOptimal; } else { layout = vk::ImageLayout::eColorAttachmentOptimal; } - + if ((depthFormat) || (stencilFormat)) { depthStencilAttachmentRef = vk::AttachmentReference(i, layout); pDepthStencil = &depthStencilAttachmentRef; - } else { - vk::AttachmentReference attachmentRef (i, layout); - colorAttachmentReferences.push_back(attachmentRef); - } - - vk::AttachmentDescription attachmentDesc ( - {}, - format, - msaaToSampleCountFlagBits(config.getMultisampling()), - getVKLoadOpFromAttachOp(attachments[i].getLoadOperation()), - getVkStoreOpFromAttachOp(attachments[i].getStoreOperation()), - vk::AttachmentLoadOp::eDontCare, - vk::AttachmentStoreOp::eDontCare, - layout, - layout - ); - + } else { + vk::AttachmentReference attachmentRef(i, layout); + colorAttachmentReferences.push_back(attachmentRef); + } + + vk::AttachmentDescription attachmentDesc( + {}, format, msaaToSampleCountFlagBits(config.getMultisampling()), + getVKLoadOpFromAttachOp(attachments [i].getLoadOperation()), + getVkStoreOpFromAttachOp(attachments [i].getStoreOperation()), + vk::AttachmentLoadOp::eDontCare, vk::AttachmentStoreOp::eDontCare, layout, layout); + if (stencilFormat) { attachmentDesc.setStencilLoadOp(attachmentDesc.loadOp); attachmentDesc.setStencilStoreOp(attachmentDesc.storeOp); } - attachmentDescriptions.push_back(attachmentDesc); + attachmentDescriptions.push_back(attachmentDesc); layouts.push_back(layout); - } - - const vk::SubpassDescription subpassDescription ( - {}, - vk::PipelineBindPoint::eGraphics, - 0, - {}, - static_cast<uint32_t>(colorAttachmentReferences.size()), - colorAttachmentReferences.data(), - {}, - pDepthStencil, - 0, - {} - ); - - const vk::RenderPassCreateInfo passInfo ( - {}, - static_cast<uint32_t>(attachmentDescriptions.size()), - attachmentDescriptions.data(), - 1, - &subpassDescription, - 0, - {} - ); - - vk::RenderPass renderPass = getCore().getContext().getDevice().createRenderPass(passInfo); - - return add({ renderPass, config, layouts }); - } - - vk::RenderPass PassManager::getVkPass(const PassHandle &handle) const { - auto& pass = (*this)[handle]; - return pass.m_Handle; - } - - const PassConfig& PassManager::getPassConfig(const PassHandle &handle) const { - auto& pass = (*this)[handle]; + } + + const vk::SubpassDescription subpassDescription( + {}, vk::PipelineBindPoint::eGraphics, 0, {}, + static_cast<uint32_t>(colorAttachmentReferences.size()), + colorAttachmentReferences.data(), {}, pDepthStencil, 0, {}); + + const vk::RenderPassCreateInfo passInfo( + {}, static_cast<uint32_t>(attachmentDescriptions.size()), attachmentDescriptions.data(), + 1, &subpassDescription, 0, {}); + + vk::RenderPass renderPass = getCore().getContext().getDevice().createRenderPass(passInfo); + + return add({ renderPass, config, layouts }); + } + + vk::RenderPass PassManager::getVkPass(const PassHandle &handle) const { + auto &pass = (*this) [handle]; + return pass.m_Handle; + } + + const PassConfig &PassManager::getPassConfig(const PassHandle &handle) const { + auto &pass = (*this) [handle]; return pass.m_Config; - } - - const std::vector<vk::ImageLayout>& PassManager::getLayouts(const PassHandle &handle) const { - auto& pass = (*this)[handle]; + } + + const std::vector<vk::ImageLayout> &PassManager::getLayouts(const PassHandle &handle) const { + auto &pass = (*this) [handle]; return pass.m_Layouts; } - -} + +} // namespace vkcv diff --git a/src/vkcv/PassManager.hpp b/src/vkcv/PassManager.hpp index f8dc653c1017ff776d70f09415a3a10fff209695..fefbffaedc2b98da88b7ce625dbfc6f3ae448b48 100644 --- a/src/vkcv/PassManager.hpp +++ b/src/vkcv/PassManager.hpp @@ -1,32 +1,31 @@ #pragma once -#include <vulkan/vulkan.hpp> #include <vector> +#include <vulkan/vulkan.hpp> #include "HandleManager.hpp" #include "vkcv/PassConfig.hpp" -namespace vkcv -{ - +namespace vkcv { + struct PassEntry { vk::RenderPass m_Handle; PassConfig m_Config; std::vector<vk::ImageLayout> m_Layouts; }; - + /** * @brief Class to manage the creation and destruction of passes. */ - class PassManager : public HandleManager<PassEntry, PassHandle> { + class PassManager : public HandleManager<PassEntry, PassHandle> { friend class Core; - private: - [[nodiscard]] - uint64_t getIdFrom(const PassHandle& handle) const override; - - [[nodiscard]] - PassHandle createById(uint64_t id, const HandleDestroyFunction& destroy) override; - + + private: + [[nodiscard]] uint64_t getIdFrom(const PassHandle &handle) const override; + + [[nodiscard]] PassHandle createById(uint64_t id, + const HandleDestroyFunction &destroy) override; + /** * Destroys and deallocates pass represented by a given * pass handle id. @@ -34,24 +33,20 @@ namespace vkcv * @param id Pass handle id */ void destroyById(uint64_t id) override; - - public: + + public: PassManager() noexcept; - - ~PassManager() noexcept override; // dtor - - [[nodiscard]] - PassHandle createPass(const PassConfig &config); - - [[nodiscard]] - vk::RenderPass getVkPass(const PassHandle &handle) const; - - [[nodiscard]] - const PassConfig& getPassConfig(const PassHandle &handle) const; - - [[nodiscard]] - const std::vector<vk::ImageLayout>& getLayouts(const PassHandle &handle) const; - - }; - -} + + ~PassManager() noexcept override; // dtor + + [[nodiscard]] PassHandle createPass(const PassConfig &config); + + [[nodiscard]] vk::RenderPass getVkPass(const PassHandle &handle) const; + + [[nodiscard]] const PassConfig &getPassConfig(const PassHandle &handle) const; + + [[nodiscard]] const std::vector<vk::ImageLayout> & + getLayouts(const PassHandle &handle) const; + }; + +} // namespace vkcv diff --git a/src/vkcv/PipelineConfig.cpp b/src/vkcv/PipelineConfig.cpp index 7585f9fe6d95eaf0409eb187d9da43162770719f..e6fb1ceb9ead48369e8f944725a139bb3b7428a1 100644 --- a/src/vkcv/PipelineConfig.cpp +++ b/src/vkcv/PipelineConfig.cpp @@ -2,35 +2,37 @@ #include "vkcv/PipelineConfig.hpp" namespace vkcv { - + PipelineConfig::PipelineConfig() : m_ShaderProgram(), m_DescriptorSetLayouts() {} - + PipelineConfig::PipelineConfig(const ShaderProgram &program, - const std::vector<DescriptorSetLayoutHandle> &layouts) - : m_ShaderProgram(program), m_DescriptorSetLayouts(layouts) {} - - void PipelineConfig::setShaderProgram(const ShaderProgram& program) { + const std::vector<DescriptorSetLayoutHandle> &layouts) : + m_ShaderProgram(program), + m_DescriptorSetLayouts(layouts) {} + + void PipelineConfig::setShaderProgram(const ShaderProgram &program) { m_ShaderProgram = program; } - + const ShaderProgram &PipelineConfig::getShaderProgram() const { return m_ShaderProgram; } - + void PipelineConfig::addDescriptorSetLayout(const DescriptorSetLayoutHandle &layout) { m_DescriptorSetLayouts.push_back(layout); } - - void PipelineConfig::addDescriptorSetLayouts(const std::vector<DescriptorSetLayoutHandle> &layouts) { + + void + PipelineConfig::addDescriptorSetLayouts(const std::vector<DescriptorSetLayoutHandle> &layouts) { m_DescriptorSetLayouts.reserve(m_DescriptorSetLayouts.size() + layouts.size()); - - for (const auto& layout : layouts) { + + for (const auto &layout : layouts) { m_DescriptorSetLayouts.push_back(layout); } } - + const std::vector<DescriptorSetLayoutHandle> &PipelineConfig::getDescriptorSetLayouts() const { return m_DescriptorSetLayouts; } - -} + +} // namespace vkcv diff --git a/src/vkcv/PushConstants.cpp b/src/vkcv/PushConstants.cpp index 5492ba2e93df1eeceaf70a8dcca4841f6243cc43..df49f0a5ee08fc793e047f8755347fe47a2a3180 100644 --- a/src/vkcv/PushConstants.cpp +++ b/src/vkcv/PushConstants.cpp @@ -1,29 +1,23 @@ #include <vkcv/PushConstants.hpp> namespace vkcv { - - PushConstants::PushConstants(size_t sizePerDrawcall) : - m_typeGuard(sizePerDrawcall), - m_data() - {} - - PushConstants::PushConstants(const TypeGuard &guard) : - m_typeGuard(guard), - m_data() - {} - + + PushConstants::PushConstants(size_t sizePerDrawcall) : m_typeGuard(sizePerDrawcall), m_data() {} + + PushConstants::PushConstants(const TypeGuard &guard) : m_typeGuard(guard), m_data() {} + size_t PushConstants::getSizePerDrawcall() const { return m_typeGuard.typeSize(); } - + size_t PushConstants::getFullSize() const { return m_data.size(); } - + size_t PushConstants::getDrawcallCount() const { return getFullSize() / getSizePerDrawcall(); } - + void PushConstants::clear() { m_data.clear(); } @@ -41,4 +35,4 @@ namespace vkcv { } } -} +} // namespace vkcv diff --git a/src/vkcv/QueueManager.cpp b/src/vkcv/QueueManager.cpp index c818769e3ddca9b23134db1cf638f8852b554253..d292383ab58ff1e34343382828e7a5f43b6b6a33 100644 --- a/src/vkcv/QueueManager.cpp +++ b/src/vkcv/QueueManager.cpp @@ -1,81 +1,88 @@ +#include <iostream> #include <limits> #include <unordered_set> -#include <iostream> -#include "vkcv/QueueManager.hpp" #include "vkcv/Logger.hpp" +#include "vkcv/QueueManager.hpp" namespace vkcv { - /** - * Computes the queue handles from @p queuePairs - * @param device The device - * @param queuePairs The queuePairs that were created separately for each queue type (e.g., vk::QueueFlagBits::eGraphics) - * @return An array of queue handles based on the @p queuePairs - */ - std::vector<Queue> getQueues(const vk::Device& device, const std::vector<std::pair<int, int>>& queuePairs) { - std::vector<Queue> queues; - - for (auto q : queuePairs) { - const int queueFamilyIndex = q.first; // the queueIndex of the queue family - const int queueIndex = q.second; // the queueIndex within a queue family - - queues.push_back({ queueFamilyIndex, queueIndex, device.getQueue(queueFamilyIndex, queueIndex) }); - } - - return queues; - } - - - QueueManager QueueManager::create(vk::Device device, + /** + * Computes the queue handles from @p queuePairs + * @param device The device + * @param queuePairs The queuePairs that were created separately for each queue type (e.g., + * vk::QueueFlagBits::eGraphics) + * @return An array of queue handles based on the @p queuePairs + */ + std::vector<Queue> getQueues(const vk::Device &device, + const std::vector<std::pair<int, int>> &queuePairs) { + std::vector<Queue> queues; + + for (auto q : queuePairs) { + const int queueFamilyIndex = q.first; // the queueIndex of the queue family + const int queueIndex = q.second; // the queueIndex within a queue family + + queues.push_back( + { queueFamilyIndex, queueIndex, device.getQueue(queueFamilyIndex, queueIndex) }); + } + + return queues; + } + + QueueManager QueueManager::create(vk::Device device, const std::vector<std::pair<int, int>> &queuePairsGraphics, const std::vector<std::pair<int, int>> &queuePairsCompute, const std::vector<std::pair<int, int>> &queuePairsTransfer) { - std::vector<Queue> graphicsQueues = getQueues(device, queuePairsGraphics); - std::vector<Queue> computeQueues = getQueues(device, queuePairsCompute); - std::vector<Queue> transferQueues = getQueues(device, queuePairsTransfer); + std::vector<Queue> graphicsQueues = getQueues(device, queuePairsGraphics); + std::vector<Queue> computeQueues = getQueues(device, queuePairsCompute); + std::vector<Queue> transferQueues = getQueues(device, queuePairsTransfer); - return QueueManager( std::move(graphicsQueues), std::move(computeQueues), std::move(transferQueues), 0); + return QueueManager(std::move(graphicsQueues), std::move(computeQueues), + std::move(transferQueues), 0); } uint32_t QueueManager::checkSurfaceSupport(const vk::PhysicalDevice &physicalDevice, const vk::SurfaceKHR &surface) { - std::vector<vk::QueueFamilyProperties> qFamilyProperties = physicalDevice.getQueueFamilyProperties(); + std::vector<vk::QueueFamilyProperties> qFamilyProperties = + physicalDevice.getQueueFamilyProperties(); - for(uint32_t i = 0; i < qFamilyProperties.size(); i++) { + for (uint32_t i = 0; i < qFamilyProperties.size(); i++) { vk::Bool32 presentSupport; - - if ((vk::Result::eSuccess == physicalDevice.getSurfaceSupportKHR(i, surface, &presentSupport)) && - (presentSupport == VK_TRUE)) { + + if ((vk::Result::eSuccess + == physicalDevice.getSurfaceSupportKHR(i, surface, &presentSupport)) + && (presentSupport == VK_TRUE)) { return i; } } - + vkcv_log(LogLevel::WARNING, "No supported present queue"); return 0; } - QueueManager::QueueManager(std::vector<Queue>&& graphicsQueues, std::vector<Queue>&& computeQueues, - std::vector<Queue>&& transferQueues, size_t presentIndex) - : m_graphicsQueues(graphicsQueues), m_computeQueues(computeQueues), m_transferQueues(transferQueues), m_presentIndex(presentIndex) - {} + QueueManager::QueueManager(std::vector<Queue> &&graphicsQueues, + std::vector<Queue> &&computeQueues, + std::vector<Queue> &&transferQueues, size_t presentIndex) : + m_graphicsQueues(graphicsQueues), + m_computeQueues(computeQueues), m_transferQueues(transferQueues), + m_presentIndex(presentIndex) {} - const Queue &QueueManager::getPresentQueue() const { - return m_graphicsQueues[m_presentIndex]; - } + const Queue &QueueManager::getPresentQueue() const { + return m_graphicsQueues [m_presentIndex]; + } - const std::vector<Queue> &QueueManager::getGraphicsQueues() const { - return m_graphicsQueues; - } + const std::vector<Queue> &QueueManager::getGraphicsQueues() const { + return m_graphicsQueues; + } - const std::vector<Queue> &QueueManager::getComputeQueues() const { - return m_computeQueues; - } + const std::vector<Queue> &QueueManager::getComputeQueues() const { + return m_computeQueues; + } - const std::vector<Queue> &QueueManager::getTransferQueues() const { - return m_transferQueues; - } + const std::vector<Queue> &QueueManager::getTransferQueues() const { + return m_transferQueues; + } -} \ No newline at end of file +} // namespace vkcv \ No newline at end of file diff --git a/src/vkcv/Sampler.cpp b/src/vkcv/Sampler.cpp index f122608afa6445bd59735be5c3d2cedc2a5e3d08..9f07e096ed5cd65c578eca0dee6c6e6693b5a260 100644 --- a/src/vkcv/Sampler.cpp +++ b/src/vkcv/Sampler.cpp @@ -2,27 +2,20 @@ #include "vkcv/Sampler.hpp" namespace vkcv { - + SamplerHandle samplerLinear(Core &core, bool clampToEdge) { - return core.createSampler( - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerMipmapMode::LINEAR, - clampToEdge? - vkcv::SamplerAddressMode::CLAMP_TO_EDGE : - vkcv::SamplerAddressMode::REPEAT - ); + return core.createSampler(vkcv::SamplerFilterType::LINEAR, vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + clampToEdge ? vkcv::SamplerAddressMode::CLAMP_TO_EDGE : + vkcv::SamplerAddressMode::REPEAT); } - + SamplerHandle samplerNearest(Core &core, bool clampToEdge) { - return core.createSampler( - vkcv::SamplerFilterType::NEAREST, - vkcv::SamplerFilterType::NEAREST, - vkcv::SamplerMipmapMode::NEAREST, - clampToEdge? - vkcv::SamplerAddressMode::CLAMP_TO_EDGE : - vkcv::SamplerAddressMode::REPEAT - ); + return core.createSampler(vkcv::SamplerFilterType::NEAREST, + vkcv::SamplerFilterType::NEAREST, + vkcv::SamplerMipmapMode::NEAREST, + clampToEdge ? vkcv::SamplerAddressMode::CLAMP_TO_EDGE : + vkcv::SamplerAddressMode::REPEAT); } - -} + +} // namespace vkcv diff --git a/src/vkcv/SamplerManager.cpp b/src/vkcv/SamplerManager.cpp index 49accf6892560c1c8d3cd856cd1dd207bb214399..6907c6b1c0f2a58822b01180304ead671d995eeb 100644 --- a/src/vkcv/SamplerManager.cpp +++ b/src/vkcv/SamplerManager.cpp @@ -3,146 +3,130 @@ #include "vkcv/Core.hpp" namespace vkcv { - + uint64_t SamplerManager::getIdFrom(const SamplerHandle &handle) const { return handle.getId(); } - + SamplerHandle SamplerManager::createById(uint64_t id, const HandleDestroyFunction &destroy) { return SamplerHandle(id, destroy); } - + void SamplerManager::destroyById(uint64_t id) { - auto& sampler = getById(id); - + auto &sampler = getById(id); + if (sampler) { getCore().getContext().getDevice().destroySampler(sampler); sampler = nullptr; } } - + SamplerManager::SamplerManager() noexcept : HandleManager<vk::Sampler, SamplerHandle>() {} - + SamplerManager::~SamplerManager() noexcept { clear(); } - + SamplerHandle SamplerManager::createSampler(SamplerFilterType magFilter, SamplerFilterType minFilter, SamplerMipmapMode mipmapMode, - SamplerAddressMode addressMode, - float mipLodBias, + SamplerAddressMode addressMode, float mipLodBias, SamplerBorderColor borderColor) { vk::Filter vkMagFilter; vk::Filter vkMinFilter; vk::SamplerMipmapMode vkMipmapMode; vk::SamplerAddressMode vkAddressMode; vk::BorderColor vkBorderColor; - + switch (magFilter) { - case SamplerFilterType::NEAREST: - vkMagFilter = vk::Filter::eNearest; - break; - case SamplerFilterType::LINEAR: - vkMagFilter = vk::Filter::eLinear; - break; - default: - return SamplerHandle(); + case SamplerFilterType::NEAREST: + vkMagFilter = vk::Filter::eNearest; + break; + case SamplerFilterType::LINEAR: + vkMagFilter = vk::Filter::eLinear; + break; + default: + return SamplerHandle(); } - + switch (minFilter) { - case SamplerFilterType::NEAREST: - vkMinFilter = vk::Filter::eNearest; - break; - case SamplerFilterType::LINEAR: - vkMinFilter = vk::Filter::eLinear; - break; - default: - return SamplerHandle(); + case SamplerFilterType::NEAREST: + vkMinFilter = vk::Filter::eNearest; + break; + case SamplerFilterType::LINEAR: + vkMinFilter = vk::Filter::eLinear; + break; + default: + return SamplerHandle(); } - + switch (mipmapMode) { - case SamplerMipmapMode::NEAREST: - vkMipmapMode = vk::SamplerMipmapMode::eNearest; - break; - case SamplerMipmapMode::LINEAR: - vkMipmapMode = vk::SamplerMipmapMode::eLinear; - break; - default: - return SamplerHandle(); + case SamplerMipmapMode::NEAREST: + vkMipmapMode = vk::SamplerMipmapMode::eNearest; + break; + case SamplerMipmapMode::LINEAR: + vkMipmapMode = vk::SamplerMipmapMode::eLinear; + break; + default: + return SamplerHandle(); } - + switch (addressMode) { - case SamplerAddressMode::REPEAT: - vkAddressMode = vk::SamplerAddressMode::eRepeat; - break; - case SamplerAddressMode::MIRRORED_REPEAT: - vkAddressMode = vk::SamplerAddressMode::eMirroredRepeat; - break; - case SamplerAddressMode::CLAMP_TO_EDGE: - vkAddressMode = vk::SamplerAddressMode::eClampToEdge; - break; - case SamplerAddressMode::MIRROR_CLAMP_TO_EDGE: - vkAddressMode = vk::SamplerAddressMode::eMirrorClampToEdge; - break; - case SamplerAddressMode::CLAMP_TO_BORDER: - vkAddressMode = vk::SamplerAddressMode::eClampToBorder; - break; - default: - return SamplerHandle(); + case SamplerAddressMode::REPEAT: + vkAddressMode = vk::SamplerAddressMode::eRepeat; + break; + case SamplerAddressMode::MIRRORED_REPEAT: + vkAddressMode = vk::SamplerAddressMode::eMirroredRepeat; + break; + case SamplerAddressMode::CLAMP_TO_EDGE: + vkAddressMode = vk::SamplerAddressMode::eClampToEdge; + break; + case SamplerAddressMode::MIRROR_CLAMP_TO_EDGE: + vkAddressMode = vk::SamplerAddressMode::eMirrorClampToEdge; + break; + case SamplerAddressMode::CLAMP_TO_BORDER: + vkAddressMode = vk::SamplerAddressMode::eClampToBorder; + break; + default: + return SamplerHandle(); } - + switch (borderColor) { - case SamplerBorderColor::INT_ZERO_OPAQUE: - vkBorderColor = vk::BorderColor::eIntOpaqueBlack; - break; - case SamplerBorderColor::INT_ZERO_TRANSPARENT: - vkBorderColor = vk::BorderColor::eIntTransparentBlack; - break; - case SamplerBorderColor::FLOAT_ZERO_OPAQUE: - vkBorderColor = vk::BorderColor::eFloatOpaqueBlack; - break; - case SamplerBorderColor::FLOAT_ZERO_TRANSPARENT: - vkBorderColor = vk::BorderColor::eFloatTransparentBlack; - break; - case SamplerBorderColor::INT_ONE_OPAQUE: - vkBorderColor = vk::BorderColor::eIntOpaqueWhite; - break; - case SamplerBorderColor::FLOAT_ONE_OPAQUE: - vkBorderColor = vk::BorderColor::eFloatOpaqueWhite; - break; - default: - return SamplerHandle(); + case SamplerBorderColor::INT_ZERO_OPAQUE: + vkBorderColor = vk::BorderColor::eIntOpaqueBlack; + break; + case SamplerBorderColor::INT_ZERO_TRANSPARENT: + vkBorderColor = vk::BorderColor::eIntTransparentBlack; + break; + case SamplerBorderColor::FLOAT_ZERO_OPAQUE: + vkBorderColor = vk::BorderColor::eFloatOpaqueBlack; + break; + case SamplerBorderColor::FLOAT_ZERO_TRANSPARENT: + vkBorderColor = vk::BorderColor::eFloatTransparentBlack; + break; + case SamplerBorderColor::INT_ONE_OPAQUE: + vkBorderColor = vk::BorderColor::eIntOpaqueWhite; + break; + case SamplerBorderColor::FLOAT_ONE_OPAQUE: + vkBorderColor = vk::BorderColor::eFloatOpaqueWhite; + break; + default: + return SamplerHandle(); } - - const vk::SamplerCreateInfo samplerCreateInfo ( - vk::SamplerCreateFlags(), - vkMagFilter, - vkMinFilter, - vkMipmapMode, - vkAddressMode, - vkAddressMode, - vkAddressMode, - mipLodBias, - false, - 16.0f, - false, - vk::CompareOp::eAlways, - -1000.0f, - 1000.0f, - vkBorderColor, - false - ); - - const vk::Sampler sampler = getCore().getContext().getDevice().createSampler( - samplerCreateInfo - ); - + + const vk::SamplerCreateInfo samplerCreateInfo( + vk::SamplerCreateFlags(), vkMagFilter, vkMinFilter, vkMipmapMode, vkAddressMode, + vkAddressMode, vkAddressMode, mipLodBias, false, 16.0f, false, vk::CompareOp::eAlways, + -1000.0f, 1000.0f, vkBorderColor, false); + + const vk::Sampler sampler = + getCore().getContext().getDevice().createSampler(samplerCreateInfo); + return add(sampler); } - + vk::Sampler SamplerManager::getVulkanSampler(const SamplerHandle &handle) const { - return (*this)[handle]; + return (*this) [handle]; } -} +} // namespace vkcv diff --git a/src/vkcv/SamplerManager.hpp b/src/vkcv/SamplerManager.hpp index 3852d3be559b679710a64176ebe96c271ca92298..5ac033037f401ca97a658f2bec2d818110d2aa6a 100644 --- a/src/vkcv/SamplerManager.hpp +++ b/src/vkcv/SamplerManager.hpp @@ -8,36 +8,31 @@ #include "vkcv/Sampler.hpp" namespace vkcv { - + /** * @brief Class to manage the creation and destruction of samplers. */ class SamplerManager : public HandleManager<vk::Sampler, SamplerHandle> { friend class Core; + private: - [[nodiscard]] - uint64_t getIdFrom(const SamplerHandle& handle) const override; - - [[nodiscard]] - SamplerHandle createById(uint64_t id, const HandleDestroyFunction& destroy) override; - + [[nodiscard]] uint64_t getIdFrom(const SamplerHandle &handle) const override; + + [[nodiscard]] SamplerHandle createById(uint64_t id, + const HandleDestroyFunction &destroy) override; + void destroyById(uint64_t id) override; - + public: SamplerManager() noexcept; - + ~SamplerManager() noexcept override; - - SamplerHandle createSampler(SamplerFilterType magFilter, - SamplerFilterType minFilter, - SamplerMipmapMode mipmapMode, - SamplerAddressMode addressMode, - float mipLodBias, - SamplerBorderColor borderColor); - - [[nodiscard]] - vk::Sampler getVulkanSampler(const SamplerHandle& handle) const; - + + SamplerHandle createSampler(SamplerFilterType magFilter, SamplerFilterType minFilter, + SamplerMipmapMode mipmapMode, SamplerAddressMode addressMode, + float mipLodBias, SamplerBorderColor borderColor); + + [[nodiscard]] vk::Sampler getVulkanSampler(const SamplerHandle &handle) const; }; - -} + +} // namespace vkcv diff --git a/src/vkcv/ShaderProgram.cpp b/src/vkcv/ShaderProgram.cpp index e1af4e1bbea54024773bcf7f8d3090643d7a0186..6925d40c5aa967ca18cd0231499248a1006d52fe 100644 --- a/src/vkcv/ShaderProgram.cpp +++ b/src/vkcv/ShaderProgram.cpp @@ -8,382 +8,338 @@ #include "vkcv/Logger.hpp" namespace vkcv { - /** - * Reads the file of a given shader code. - * Only used within the class. - * @param[in] relative path to the shader code - * @return vector of chars as a buffer for the code - */ + /** + * Reads the file of a given shader code. + * Only used within the class. + * @param[in] relative path to the shader code + * @return vector of chars as a buffer for the code + */ std::vector<uint32_t> readShaderCode(const std::filesystem::path &shaderPath) { - std::ifstream file (shaderPath.string(), std::ios::ate | std::ios::binary); - + std::ifstream file(shaderPath.string(), std::ios::ate | std::ios::binary); + if (!file.is_open()) { vkcv_log(LogLevel::ERROR, "The file could not be opened: %s", shaderPath.c_str()); return std::vector<uint32_t>(); } - + size_t fileSize = (size_t)file.tellg(); - if (fileSize % sizeof(uint32_t) != 0) { - vkcv_log(LogLevel::ERROR, "The file is not a valid shader: %s", shaderPath.c_str()); - return std::vector<uint32_t>(); - } + if (fileSize % sizeof(uint32_t) != 0) { + vkcv_log(LogLevel::ERROR, "The file is not a valid shader: %s", shaderPath.c_str()); + return std::vector<uint32_t>(); + } std::vector<uint32_t> buffer(fileSize / sizeof(uint32_t)); - + file.seekg(0); file.read(reinterpret_cast<char*>(buffer.data()), fileSize); file.close(); - - return buffer; + + return buffer; } - VertexAttachmentFormat convertFormat(spirv_cross::SPIRType::BaseType basetype, uint32_t vecsize){ - switch (basetype) { - case spirv_cross::SPIRType::Int: - switch (vecsize) { - case 1: - return VertexAttachmentFormat::INT; - case 2: - return VertexAttachmentFormat::INT2; - case 3: - return VertexAttachmentFormat::INT3; - case 4: - return VertexAttachmentFormat::INT4; - default: - break; - } - break; - case spirv_cross::SPIRType::Float: - switch (vecsize) { - case 1: - return VertexAttachmentFormat::FLOAT; - case 2: - return VertexAttachmentFormat::FLOAT2; - case 3: - return VertexAttachmentFormat::FLOAT3; - case 4: - return VertexAttachmentFormat::FLOAT4; - default: - break; - } - break; - default: - break; - } - + VertexAttachmentFormat convertFormat(spirv_cross::SPIRType::BaseType basetype, + uint32_t vecsize) { + switch (basetype) { + case spirv_cross::SPIRType::Int: + switch (vecsize) { + case 1: + return VertexAttachmentFormat::INT; + case 2: + return VertexAttachmentFormat::INT2; + case 3: + return VertexAttachmentFormat::INT3; + case 4: + return VertexAttachmentFormat::INT4; + default: + break; + } + break; + case spirv_cross::SPIRType::Float: + switch (vecsize) { + case 1: + return VertexAttachmentFormat::FLOAT; + case 2: + return VertexAttachmentFormat::FLOAT2; + case 3: + return VertexAttachmentFormat::FLOAT3; + case 4: + return VertexAttachmentFormat::FLOAT4; + default: + break; + } + break; + default: + break; + } + vkcv_log(LogLevel::WARNING, "Unknown vertex format"); - return VertexAttachmentFormat::FLOAT; + return VertexAttachmentFormat::FLOAT; } ShaderProgram::ShaderProgram() noexcept : - m_Shaders{}, - m_VertexAttachments{}, - m_DescriptorSets{} - {} - - bool ShaderProgram::addShader(ShaderStage stage, const std::filesystem::path &path) - { - if(m_Shaders.find(stage) != m_Shaders.end()) { + m_Shaders {}, m_VertexAttachments {}, m_DescriptorSets {} {} + + bool ShaderProgram::addShader(ShaderStage stage, const std::filesystem::path &path) { + if (m_Shaders.find(stage) != m_Shaders.end()) { vkcv_log(LogLevel::WARNING, "Overwriting existing shader stage"); } - const std::vector<uint32_t> shaderCode = readShaderCode(path); - - if (shaderCode.empty()) { + const std::vector<uint32_t> shaderCode = readShaderCode(path); + + if (shaderCode.empty()) { return false; } else { - m_Shaders.insert(std::make_pair(stage, shaderCode)); - reflectShader(stage); - return true; - } + m_Shaders.insert(std::make_pair(stage, shaderCode)); + reflectShader(stage); + return true; + } } - const std::vector<uint32_t> &ShaderProgram::getShaderBinary(ShaderStage stage) const - { - return m_Shaders.at(stage); + const std::vector<uint32_t> &ShaderProgram::getShaderBinary(ShaderStage stage) const { + return m_Shaders.at(stage); } - bool ShaderProgram::existsShader(ShaderStage stage) const - { - if(m_Shaders.find(stage) == m_Shaders.end()) - return false; - else - return true; - } + bool ShaderProgram::existsShader(ShaderStage stage) const { + if (m_Shaders.find(stage) == m_Shaders.end()) + return false; + else + return true; + } - void ShaderProgram::reflectShader(ShaderStage shaderStage) - { - auto shaderCode = m_Shaders.at(shaderStage); + void ShaderProgram::reflectShader(ShaderStage shaderStage) { + auto shaderCode = m_Shaders.at(shaderStage); - spirv_cross::Compiler comp(shaderCode); - spirv_cross::ShaderResources resources = comp.get_shader_resources(); + spirv_cross::Compiler comp(shaderCode); + spirv_cross::ShaderResources resources = comp.get_shader_resources(); - //reflect vertex input - if (shaderStage == ShaderStage::VERTEX) - { + // reflect vertex input + if (shaderStage == ShaderStage::VERTEX) { // spirv-cross API (hopefully) returns the stage_inputs in order - for (uint32_t i = 0; i < resources.stage_inputs.size(); i++) - { - // spirv-cross specific objects - auto& stage_input = resources.stage_inputs[i]; - const spirv_cross::SPIRType& base_type = comp.get_type(stage_input.base_type_id); + for (uint32_t i = 0; i < resources.stage_inputs.size(); i++) { + // spirv-cross specific objects + auto &stage_input = resources.stage_inputs [i]; + const spirv_cross::SPIRType &base_type = comp.get_type(stage_input.base_type_id); // vertex input location - const uint32_t attachment_loc = comp.get_decoration(stage_input.id, spv::DecorationLocation); - // vertex input name - const std::string attachment_name = stage_input.name; + const uint32_t attachment_loc = + comp.get_decoration(stage_input.id, spv::DecorationLocation); + // vertex input name + const std::string attachment_name = stage_input.name; // vertex input format (implies its size) - const VertexAttachmentFormat attachment_format = convertFormat(base_type.basetype, base_type.vecsize); - - m_VertexAttachments.push_back({ - attachment_loc, - attachment_name, - attachment_format, - 0 - }); - } + const VertexAttachmentFormat attachment_format = + convertFormat(base_type.basetype, base_type.vecsize); + + m_VertexAttachments.push_back( + { attachment_loc, attachment_name, attachment_format, 0 }); + } } - //reflect descriptor sets (uniform buffer, storage buffer, sampler, sampled image, storage image) - std::vector<std::pair<uint32_t, DescriptorBinding>> bindings; - - for (uint32_t i = 0; i < resources.uniform_buffers.size(); i++) - { - auto& u = resources.uniform_buffers[i]; - const spirv_cross::SPIRType& base_type = comp.get_type(u.base_type_id); - const spirv_cross::SPIRType &type = comp.get_type(u.type_id); - - uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet); - uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding); - - uint32_t descriptorCount = base_type.vecsize; - bool variableCount = false; - // query whether reflected resources are qualified as one-dimensional array - if(type.array_size_literal[0]) - { - descriptorCount = type.array[0]; - if(type.array[0] == 0) - variableCount = true; - } - - DescriptorBinding binding { - bindingID, - DescriptorType::UNIFORM_BUFFER, - descriptorCount, - shaderStage, + // reflect descriptor sets (uniform buffer, storage buffer, sampler, sampled image, storage + // image) + std::vector<std::pair<uint32_t, DescriptorBinding>> bindings; + + for (uint32_t i = 0; i < resources.uniform_buffers.size(); i++) { + auto &u = resources.uniform_buffers [i]; + const spirv_cross::SPIRType &base_type = comp.get_type(u.base_type_id); + const spirv_cross::SPIRType &type = comp.get_type(u.type_id); + + uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet); + uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding); + + uint32_t descriptorCount = base_type.vecsize; + bool variableCount = false; + // query whether reflected resources are qualified as one-dimensional array + if (type.array_size_literal [0]) { + descriptorCount = type.array [0]; + if (type.array [0] == 0) + variableCount = true; + } + + DescriptorBinding binding { + bindingID, DescriptorType::UNIFORM_BUFFER, descriptorCount, shaderStage, variableCount, variableCount // partialBinding == variableCount }; - auto insertionResult = m_DescriptorSets[setID].insert(std::make_pair(bindingID, binding)); - if(!insertionResult.second) - { - vkcv_log(LogLevel::WARNING, - "Attempting to overwrite already existing binding %u at set ID %u.", - bindingID, - setID); - } - } - - for (uint32_t i = 0; i < resources.storage_buffers.size(); i++) - { - auto& u = resources.storage_buffers[i]; - const spirv_cross::SPIRType& base_type = comp.get_type(u.base_type_id); - const spirv_cross::SPIRType &type = comp.get_type(u.type_id); - - uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet); - uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding); - - uint32_t descriptorCount = base_type.vecsize; - bool variableCount = false; - // query whether reflected resources are qualified as one-dimensional array - if(type.array_size_literal[0]) - { - descriptorCount = type.array[0]; - if(type.array[0] == 0) - variableCount = true; - } - - DescriptorBinding binding { - bindingID, - DescriptorType::STORAGE_BUFFER, - descriptorCount, - shaderStage, + auto insertionResult = + m_DescriptorSets [setID].insert(std::make_pair(bindingID, binding)); + if (!insertionResult.second) { + vkcv_log(LogLevel::WARNING, + "Attempting to overwrite already existing binding %u at set ID %u.", + bindingID, setID); + } + } + + for (uint32_t i = 0; i < resources.storage_buffers.size(); i++) { + auto &u = resources.storage_buffers [i]; + const spirv_cross::SPIRType &base_type = comp.get_type(u.base_type_id); + const spirv_cross::SPIRType &type = comp.get_type(u.type_id); + + uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet); + uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding); + + uint32_t descriptorCount = base_type.vecsize; + bool variableCount = false; + // query whether reflected resources are qualified as one-dimensional array + if (type.array_size_literal [0]) { + descriptorCount = type.array [0]; + if (type.array [0] == 0) + variableCount = true; + } + + DescriptorBinding binding { + bindingID, DescriptorType::STORAGE_BUFFER, descriptorCount, shaderStage, variableCount, variableCount // partialBinding == variableCount }; - auto insertionResult = m_DescriptorSets[setID].insert(std::make_pair(bindingID, binding)); - if(!insertionResult.second) - { - vkcv_log(LogLevel::WARNING, - "Attempting to overwrite already existing binding %u at set ID %u.", - bindingID, - setID); - } - } - - for (uint32_t i = 0; i < resources.separate_samplers.size(); i++) { - auto& u = resources.separate_samplers[i]; - const spirv_cross::SPIRType& base_type = comp.get_type(u.base_type_id); - const spirv_cross::SPIRType &type = comp.get_type(u.type_id); - - uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet); - uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding); - - uint32_t descriptorCount = base_type.vecsize; - bool variableCount = false; - // query whether reflected resources are qualified as one-dimensional array - if(type.array_size_literal[0]) - { - descriptorCount = type.array[0]; - if(type.array[0] == 0) - variableCount = true; - } - - DescriptorBinding binding { - bindingID, - DescriptorType::SAMPLER, - descriptorCount, - shaderStage, - variableCount, + auto insertionResult = + m_DescriptorSets [setID].insert(std::make_pair(bindingID, binding)); + if (!insertionResult.second) { + vkcv_log(LogLevel::WARNING, + "Attempting to overwrite already existing binding %u at set ID %u.", + bindingID, setID); + } + } + + for (uint32_t i = 0; i < resources.separate_samplers.size(); i++) { + auto &u = resources.separate_samplers [i]; + const spirv_cross::SPIRType &base_type = comp.get_type(u.base_type_id); + const spirv_cross::SPIRType &type = comp.get_type(u.type_id); + + uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet); + uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding); + + uint32_t descriptorCount = base_type.vecsize; + bool variableCount = false; + // query whether reflected resources are qualified as one-dimensional array + if (type.array_size_literal [0]) { + descriptorCount = type.array [0]; + if (type.array [0] == 0) + variableCount = true; + } + + DescriptorBinding binding { + bindingID, DescriptorType::SAMPLER, descriptorCount, shaderStage, variableCount, variableCount // partialBinding == variableCount }; - auto insertionResult = m_DescriptorSets[setID].insert(std::make_pair(bindingID, binding)); - if(!insertionResult.second) - { - vkcv_log(LogLevel::WARNING, - "Attempting to overwrite already existing binding %u at set ID %u.", - bindingID, - setID); - } - } - - for (uint32_t i = 0; i < resources.separate_images.size(); i++) { - auto& u = resources.separate_images[i]; - const spirv_cross::SPIRType &base_type = comp.get_type(u.base_type_id); - const spirv_cross::SPIRType &type = comp.get_type(u.type_id); - - uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet); - uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding); - - uint32_t descriptorCount = base_type.vecsize; - bool variableCount = false; - // query whether reflected resources are qualified as one-dimensional array - if(type.array_size_literal[0]) - { - descriptorCount = type.array[0]; - if(type.array[0] == 0) - variableCount = true; - } - - DescriptorBinding binding { - bindingID, - DescriptorType::IMAGE_SAMPLED, - descriptorCount, - shaderStage, + auto insertionResult = + m_DescriptorSets [setID].insert(std::make_pair(bindingID, binding)); + if (!insertionResult.second) { + vkcv_log(LogLevel::WARNING, + "Attempting to overwrite already existing binding %u at set ID %u.", + bindingID, setID); + } + } + + for (uint32_t i = 0; i < resources.separate_images.size(); i++) { + auto &u = resources.separate_images [i]; + const spirv_cross::SPIRType &base_type = comp.get_type(u.base_type_id); + const spirv_cross::SPIRType &type = comp.get_type(u.type_id); + + uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet); + uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding); + + uint32_t descriptorCount = base_type.vecsize; + bool variableCount = false; + // query whether reflected resources are qualified as one-dimensional array + if (type.array_size_literal [0]) { + descriptorCount = type.array [0]; + if (type.array [0] == 0) + variableCount = true; + } + + DescriptorBinding binding { + bindingID, DescriptorType::IMAGE_SAMPLED, descriptorCount, shaderStage, variableCount, variableCount // partialBinding == variableCount }; - auto insertionResult = m_DescriptorSets[setID].insert(std::make_pair(bindingID, binding)); - if(!insertionResult.second) - { - vkcv_log(LogLevel::WARNING, - "Attempting to overwrite already existing binding %u at set ID %u.", - bindingID, - setID); - } - } - - for (uint32_t i = 0; i < resources.storage_images.size(); i++) { - auto& u = resources.storage_images[i]; - const spirv_cross::SPIRType& base_type = comp.get_type(u.base_type_id); - const spirv_cross::SPIRType &type = comp.get_type(u.type_id); - - uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet); - uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding); - - uint32_t descriptorCount = base_type.vecsize; - bool variableCount = false; - // query whether reflected resources are qualified as one-dimensional array - if(type.array_size_literal[0]) - { - descriptorCount = type.array[0]; - if(type.array[0] == 0) - variableCount = true; - } - - DescriptorBinding binding { - bindingID, - DescriptorType::IMAGE_STORAGE, - descriptorCount, - shaderStage, + auto insertionResult = + m_DescriptorSets [setID].insert(std::make_pair(bindingID, binding)); + if (!insertionResult.second) { + vkcv_log(LogLevel::WARNING, + "Attempting to overwrite already existing binding %u at set ID %u.", + bindingID, setID); + } + } + + for (uint32_t i = 0; i < resources.storage_images.size(); i++) { + auto &u = resources.storage_images [i]; + const spirv_cross::SPIRType &base_type = comp.get_type(u.base_type_id); + const spirv_cross::SPIRType &type = comp.get_type(u.type_id); + + uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet); + uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding); + + uint32_t descriptorCount = base_type.vecsize; + bool variableCount = false; + // query whether reflected resources are qualified as one-dimensional array + if (type.array_size_literal [0]) { + descriptorCount = type.array [0]; + if (type.array [0] == 0) + variableCount = true; + } + + DescriptorBinding binding { + bindingID, DescriptorType::IMAGE_STORAGE, descriptorCount, shaderStage, variableCount, variableCount // partialBinding == variableCount }; - auto insertionResult = m_DescriptorSets[setID].insert(std::make_pair(bindingID, binding)); - if(!insertionResult.second) - { - vkcv_log(LogLevel::WARNING, - "Attempting to overwrite already existing binding %u at set ID %u.", - bindingID, - setID); - } - } - - // Used to reflect acceleration structure bindings for RTX. - for (uint32_t i = 0; i < resources.acceleration_structures.size(); i++) { - auto& u = resources.acceleration_structures[i]; - const spirv_cross::SPIRType& base_type = comp.get_type(u.base_type_id); - - uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet); - uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding); - auto binding = DescriptorBinding { - bindingID, - DescriptorType::ACCELERATION_STRUCTURE_KHR, - base_type.vecsize, - shaderStage, - false, - false - }; + auto insertionResult = + m_DescriptorSets [setID].insert(std::make_pair(bindingID, binding)); + if (!insertionResult.second) { + vkcv_log(LogLevel::WARNING, + "Attempting to overwrite already existing binding %u at set ID %u.", + bindingID, setID); + } + } + + // Used to reflect acceleration structure bindings for RTX. + for (uint32_t i = 0; i < resources.acceleration_structures.size(); i++) { + auto &u = resources.acceleration_structures [i]; + const spirv_cross::SPIRType &base_type = comp.get_type(u.base_type_id); + + uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet); + uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding); + auto binding = DescriptorBinding { bindingID, + DescriptorType::ACCELERATION_STRUCTURE_KHR, + base_type.vecsize, + shaderStage, + false, + false }; + + auto insertionResult = + m_DescriptorSets [setID].insert(std::make_pair(bindingID, binding)); + if (!insertionResult.second) { + vkcv_log(LogLevel::WARNING, + "Attempting to overwrite already existing binding %u at set ID %u.", + bindingID, setID); + } + } - auto insertionResult = m_DescriptorSets[setID].insert(std::make_pair(bindingID, binding)); - if (!insertionResult.second) - { - vkcv_log(LogLevel::WARNING, - "Attempting to overwrite already existing binding %u at set ID %u.", - bindingID, - setID); - } - } - - //reflect push constants - for (const auto &pushConstantBuffer : resources.push_constant_buffers) - { - for (const auto &range : comp.get_active_buffer_ranges(pushConstantBuffer.id)) - { + // reflect push constants + for (const auto &pushConstantBuffer : resources.push_constant_buffers) { + for (const auto &range : comp.get_active_buffer_ranges(pushConstantBuffer.id)) { const size_t size = range.range + range.offset; m_pushConstantsSize = std::max(m_pushConstantsSize, size); } } - } + } - const VertexAttachments &ShaderProgram::getVertexAttachments() const - { - return m_VertexAttachments; + const VertexAttachments &ShaderProgram::getVertexAttachments() const { + return m_VertexAttachments; } - const std::unordered_map<uint32_t, DescriptorBindings>& ShaderProgram::getReflectedDescriptors() const - { - return m_DescriptorSets; - } + const std::unordered_map<uint32_t, DescriptorBindings> & + ShaderProgram::getReflectedDescriptors() const { + return m_DescriptorSets; + } - size_t ShaderProgram::getPushConstantsSize() const - { + size_t ShaderProgram::getPushConstantsSize() const { return m_pushConstantsSize; } -} +} // namespace vkcv diff --git a/src/vkcv/SwapchainManager.cpp b/src/vkcv/SwapchainManager.cpp index f16a4c30e9479bfcbc177e77783985d6d6a54f60..27efa5031853552ab9a2926d37ba3cb64cdbdc6c 100644 --- a/src/vkcv/SwapchainManager.cpp +++ b/src/vkcv/SwapchainManager.cpp @@ -5,131 +5,142 @@ #include "vkcv/Core.hpp" namespace vkcv { - + uint64_t SwapchainManager::getIdFrom(const SwapchainHandle &handle) const { return handle.getId(); } - - SwapchainHandle SwapchainManager::createById(uint64_t id, const HandleDestroyFunction &destroy) { + + SwapchainHandle SwapchainManager::createById(uint64_t id, + const HandleDestroyFunction &destroy) { return SwapchainHandle(id, destroy); } - + void SwapchainManager::destroyById(uint64_t id) { - auto& swapchain = getById(id); - + auto &swapchain = getById(id); + if (swapchain.m_Swapchain) { getCore().getContext().getDevice().destroySwapchainKHR(swapchain.m_Swapchain); swapchain.m_Swapchain = nullptr; } - + if (swapchain.m_Surface) { getCore().getContext().getInstance().destroySurfaceKHR(swapchain.m_Surface); swapchain.m_Surface = nullptr; } } - - SwapchainManager::SwapchainManager() noexcept : HandleManager<SwapchainEntry, SwapchainHandle>() {} + + SwapchainManager::SwapchainManager() noexcept : + HandleManager<SwapchainEntry, SwapchainHandle>() {} SwapchainManager::~SwapchainManager() noexcept { clear(); } - + /** - * @brief Creates vulkan surface and checks availability. - * - * @param[in,out] window Current window for the surface - * @param[in,out] instance Vulkan-Instance - * @param[in,out] physicalDevice Vulkan-PhysicalDevice - * @param[out] surface Vulkan-Surface - * @return Created vulkan surface - */ - static bool createVulkanSurface(GLFWwindow* window, - const vk::Instance& instance, - const vk::PhysicalDevice& physicalDevice, - vk::SurfaceKHR& surface) { + * @brief Creates vulkan surface and checks availability. + * + * @param[in,out] window Current window for the surface + * @param[in,out] instance Vulkan-Instance + * @param[in,out] physicalDevice Vulkan-PhysicalDevice + * @param[out] surface Vulkan-Surface + * @return Created vulkan surface + */ + static bool createVulkanSurface(GLFWwindow* window, const vk::Instance &instance, + const vk::PhysicalDevice &physicalDevice, + vk::SurfaceKHR &surface) { VkSurfaceKHR api_surface; - - if (glfwCreateWindowSurface(VkInstance(instance), window, nullptr, &api_surface) != VK_SUCCESS) { + + if (glfwCreateWindowSurface(VkInstance(instance), window, nullptr, &api_surface) + != VK_SUCCESS) { vkcv_log(LogLevel::ERROR, "Failed to create a window surface"); return false; } - + vk::Bool32 surfaceSupport = false; surface = vk::SurfaceKHR(api_surface); - - if ((physicalDevice.getSurfaceSupportKHR(0, surface, &surfaceSupport) != vk::Result::eSuccess) || - (!surfaceSupport)) { + + if ((physicalDevice.getSurfaceSupportKHR(0, surface, &surfaceSupport) + != vk::Result::eSuccess) + || (!surfaceSupport)) { vkcv_log(LogLevel::ERROR, "Surface is not supported by the device"); instance.destroy(surface); surface = nullptr; return false; } - + return true; } - + /** - * @brief Chooses an Extent and clamps values to the available capabilities. - * - * @param physicalDevice Vulkan-PhysicalDevice - * @param surface Vulkan-Surface of the swapchain - * @param window Window of the current application - * @return Chosen Extent for the surface - */ - static vk::Extent2D chooseExtent(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface, const Window &window) { + * @brief Chooses an Extent and clamps values to the available capabilities. + * + * @param physicalDevice Vulkan-PhysicalDevice + * @param surface Vulkan-Surface of the swapchain + * @param window Window of the current application + * @return Chosen Extent for the surface + */ + static vk::Extent2D chooseExtent(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface, + const Window &window) { int fb_width, fb_height; window.getFramebufferSize(fb_width, fb_height); - - VkExtent2D extent2D = { - static_cast<uint32_t>(fb_width), - static_cast<uint32_t>(fb_height) - }; - + + VkExtent2D extent2D = { static_cast<uint32_t>(fb_width), static_cast<uint32_t>(fb_height) }; + vk::SurfaceCapabilitiesKHR surfaceCapabilities; - if(physicalDevice.getSurfaceCapabilitiesKHR(surface, &surfaceCapabilities) != vk::Result::eSuccess) { + if (physicalDevice.getSurfaceCapabilitiesKHR(surface, &surfaceCapabilities) + != vk::Result::eSuccess) { vkcv_log(LogLevel::WARNING, "The capabilities of the surface can not be retrieved"); - + extent2D.width = std::max(MIN_SURFACE_SIZE, extent2D.width); extent2D.height = std::max(MIN_SURFACE_SIZE, extent2D.height); } else { - extent2D.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, extent2D.width)); - extent2D.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, extent2D.height)); + extent2D.width = + std::max(surfaceCapabilities.minImageExtent.width, + std::min(surfaceCapabilities.maxImageExtent.width, extent2D.width)); + extent2D.height = + std::max(surfaceCapabilities.minImageExtent.height, + std::min(surfaceCapabilities.maxImageExtent.height, extent2D.height)); } - + return extent2D; } - + /** - * @brief Chooses Surface Format for the current surface - * - * @param physicalDevice Vulkan-PhysicalDevice - * @param surface Vulkan-Surface of the swapchain - * @return Available Format - */ - static vk::SurfaceFormatKHR chooseSurfaceFormat(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { - std::vector<vk::SurfaceFormatKHR> availableFormats = physicalDevice.getSurfaceFormatsKHR(surface); - - for (const auto& availableFormat : availableFormats) { - if (availableFormat.format == vk::Format::eB8G8R8A8Unorm && availableFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) { + * @brief Chooses Surface Format for the current surface + * + * @param physicalDevice Vulkan-PhysicalDevice + * @param surface Vulkan-Surface of the swapchain + * @return Available Format + */ + static vk::SurfaceFormatKHR chooseSurfaceFormat(vk::PhysicalDevice physicalDevice, + vk::SurfaceKHR surface) { + std::vector<vk::SurfaceFormatKHR> availableFormats = + physicalDevice.getSurfaceFormatsKHR(surface); + + for (const auto &availableFormat : availableFormats) { + if (availableFormat.format == vk::Format::eB8G8R8A8Unorm + && availableFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) { return availableFormat; } } - - return availableFormats[0]; + + return availableFormats [0]; } - + /** - * @brief Returns vk::PresentModeKHR::eMailbox if available or - * vk::PresentModeKHR::eFifo otherwise - * - * @param physicalDevice Vulkan-PhysicalDevice - * @param surface Vulkan-Surface of the swapchain - * @return Available PresentationMode - */ - static vk::PresentModeKHR choosePresentMode(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { - std::vector<vk::PresentModeKHR> availablePresentModes = physicalDevice.getSurfacePresentModesKHR(surface); - - for (const auto& availablePresentMode : availablePresentModes) { + * @brief Returns vk::PresentModeKHR::eMailbox if available or + * vk::PresentModeKHR::eFifo otherwise + * + * @param physicalDevice Vulkan-PhysicalDevice + * @param surface Vulkan-Surface of the swapchain + * @return Available PresentationMode + */ + static vk::PresentModeKHR choosePresentMode(vk::PhysicalDevice physicalDevice, + vk::SurfaceKHR surface) { + std::vector<vk::PresentModeKHR> availablePresentModes = + physicalDevice.getSurfacePresentModesKHR(surface); + + for (const auto &availablePresentMode : availablePresentModes) { if (availablePresentMode == vk::PresentModeKHR::eMailbox) { return availablePresentMode; } @@ -137,124 +148,111 @@ namespace vkcv { // The FIFO present mode is guaranteed by the spec to be supported return vk::PresentModeKHR::eFifo; } - + /** - * @brief Returns the minImageCount +1 for at least double buffering, - * if it's greater than maxImageCount return maxImageCount - * - * @param physicalDevice Vulkan-PhysicalDevice - * @param surface Vulkan-Surface of the swapchain - * @return Available image count - */ + * @brief Returns the minImageCount +1 for at least double buffering, + * if it's greater than maxImageCount return maxImageCount + * + * @param physicalDevice Vulkan-PhysicalDevice + * @param surface Vulkan-Surface of the swapchain + * @return Available image count + */ static uint32_t chooseImageCount(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { - vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface); - + vk::SurfaceCapabilitiesKHR surfaceCapabilities = + physicalDevice.getSurfaceCapabilitiesKHR(surface); + // minImageCount should always be at least 2; set to 3 for triple buffering uint32_t imageCount = surfaceCapabilities.minImageCount + 1; - + // check if requested image count is supported - if (surfaceCapabilities.maxImageCount > 0 && imageCount > surfaceCapabilities.maxImageCount) { + if (surfaceCapabilities.maxImageCount > 0 + && imageCount > surfaceCapabilities.maxImageCount) { imageCount = surfaceCapabilities.maxImageCount; } - + return imageCount; } - - static bool createVulkanSwapchain(const Context& context, - const Window &window, - SwapchainEntry& entry) { - const vk::PhysicalDevice& physicalDevice = context.getPhysicalDevice(); - const vk::Device& device = context.getDevice(); - + + static bool createVulkanSwapchain(const Context &context, const Window &window, + SwapchainEntry &entry) { + const vk::PhysicalDevice &physicalDevice = context.getPhysicalDevice(); + const vk::Device &device = context.getDevice(); + entry.m_Extent = chooseExtent(physicalDevice, entry.m_Surface, window); - - if ((entry.m_Extent.width < MIN_SURFACE_SIZE) || (entry.m_Extent.height < MIN_SURFACE_SIZE)) { + + if ((entry.m_Extent.width < MIN_SURFACE_SIZE) + || (entry.m_Extent.height < MIN_SURFACE_SIZE)) { return false; } - - vk::SurfaceFormatKHR chosenSurfaceFormat = chooseSurfaceFormat(physicalDevice, entry.m_Surface); + + vk::SurfaceFormatKHR chosenSurfaceFormat = + chooseSurfaceFormat(physicalDevice, entry.m_Surface); vk::PresentModeKHR chosenPresentMode = choosePresentMode(physicalDevice, entry.m_Surface); uint32_t chosenImageCount = chooseImageCount(physicalDevice, entry.m_Surface); - + entry.m_Format = chosenSurfaceFormat.format; entry.m_ColorSpace = chosenSurfaceFormat.colorSpace; - - vk::SwapchainCreateInfoKHR swapchainCreateInfo ( - vk::SwapchainCreateFlagsKHR(), - entry.m_Surface, - chosenImageCount, - entry.m_Format, - entry.m_ColorSpace, - entry.m_Extent, - 1, - vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eStorage, - vk::SharingMode::eExclusive, - 0, - nullptr, - vk::SurfaceTransformFlagBitsKHR::eIdentity, - vk::CompositeAlphaFlagBitsKHR::eOpaque, - chosenPresentMode, - true, - entry.m_Swapchain - ); - + + vk::SwapchainCreateInfoKHR swapchainCreateInfo( + vk::SwapchainCreateFlagsKHR(), entry.m_Surface, chosenImageCount, entry.m_Format, + entry.m_ColorSpace, entry.m_Extent, 1, + vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eStorage, + vk::SharingMode::eExclusive, 0, nullptr, vk::SurfaceTransformFlagBitsKHR::eIdentity, + vk::CompositeAlphaFlagBitsKHR::eOpaque, chosenPresentMode, true, entry.m_Swapchain); + entry.m_Swapchain = device.createSwapchainKHR(swapchainCreateInfo); return true; } SwapchainHandle SwapchainManager::createSwapchain(Window &window) { - const vk::Instance& instance = getCore().getContext().getInstance(); - const vk::PhysicalDevice& physicalDevice = getCore().getContext().getPhysicalDevice(); - + const vk::Instance &instance = getCore().getContext().getInstance(); + const vk::PhysicalDevice &physicalDevice = getCore().getContext().getPhysicalDevice(); + vk::SurfaceKHR surfaceHandle; if (!createVulkanSurface(window.getWindow(), instance, physicalDevice, surfaceHandle)) { return {}; } - - uint32_t presentQueueIndex = QueueManager::checkSurfaceSupport(physicalDevice, surfaceHandle); - + + uint32_t presentQueueIndex = + QueueManager::checkSurfaceSupport(physicalDevice, surfaceHandle); + const vk::Extent2D extent = chooseExtent(physicalDevice, surfaceHandle, window); const vk::SurfaceFormatKHR format = chooseSurfaceFormat(physicalDevice, surfaceHandle); - - SwapchainEntry entry { - nullptr, - false, - - surfaceHandle, - presentQueueIndex, - extent, - format.format, - format.colorSpace - }; - + + SwapchainEntry entry { nullptr, false, + + surfaceHandle, presentQueueIndex, + extent, format.format, + format.colorSpace }; + if (!createVulkanSwapchain(getCore().getContext(), window, entry)) { instance.destroySurfaceKHR(surfaceHandle); return {}; } - + window.m_swapchainHandle = add(entry); return window.m_swapchainHandle; } - SwapchainEntry& SwapchainManager::getSwapchain(const SwapchainHandle& handle) { - return (*this)[handle]; + SwapchainEntry &SwapchainManager::getSwapchain(const SwapchainHandle &handle) { + return (*this) [handle]; } - + bool SwapchainManager::shouldUpdateSwapchain(const SwapchainHandle &handle) const { - return (*this)[handle].m_RecreationRequired; + return (*this) [handle].m_RecreationRequired; } - + void SwapchainManager::updateSwapchain(const SwapchainHandle &handle, const Window &window) { - auto& swapchain = (*this)[handle]; - + auto &swapchain = (*this) [handle]; + if (!swapchain.m_RecreationRequired) { return; } else { swapchain.m_RecreationRequired = false; } - + vk::SwapchainKHR oldSwapchain = swapchain.m_Swapchain; - + if (createVulkanSwapchain(getCore().getContext(), window, swapchain)) { if (oldSwapchain) { getCore().getContext().getDevice().destroySwapchainKHR(oldSwapchain); @@ -263,71 +261,68 @@ namespace vkcv { signalRecreation(handle); } } - - void SwapchainManager::signalRecreation(const SwapchainHandle& handle) { - (*this)[handle].m_RecreationRequired = true; + + void SwapchainManager::signalRecreation(const SwapchainHandle &handle) { + (*this) [handle].m_RecreationRequired = true; } - + vk::Format SwapchainManager::getFormat(const SwapchainHandle &handle) const { - return (*this)[handle].m_Format; + return (*this) [handle].m_Format; } - + uint32_t SwapchainManager::getImageCount(const SwapchainHandle &handle) const { - auto& swapchain = (*this)[handle]; - + auto &swapchain = (*this) [handle]; + uint32_t imageCount; - if (vk::Result::eSuccess != getCore().getContext().getDevice().getSwapchainImagesKHR(swapchain.m_Swapchain, - &imageCount, - nullptr)) { + if (vk::Result::eSuccess + != getCore().getContext().getDevice().getSwapchainImagesKHR(swapchain.m_Swapchain, + &imageCount, nullptr)) { return 0; } else { return imageCount; } } - + const vk::Extent2D &SwapchainManager::getExtent(const SwapchainHandle &handle) const { - return (*this)[handle].m_Extent; + return (*this) [handle].m_Extent; } - + uint32_t SwapchainManager::getPresentQueueIndex(const SwapchainHandle &handle) const { - return (*this)[handle].m_PresentQueueIndex; + return (*this) [handle].m_PresentQueueIndex; } - + vk::ColorSpaceKHR SwapchainManager::getSurfaceColorSpace(const SwapchainHandle &handle) const { - return (*this)[handle].m_ColorSpace; + return (*this) [handle].m_ColorSpace; } - - std::vector<vk::Image> SwapchainManager::getSwapchainImages(const SwapchainHandle& handle) const { - return getCore().getContext().getDevice().getSwapchainImagesKHR((*this)[handle].m_Swapchain); + + std::vector<vk::Image> + SwapchainManager::getSwapchainImages(const SwapchainHandle &handle) const { + return getCore().getContext().getDevice().getSwapchainImagesKHR( + (*this) [handle].m_Swapchain); } - std::vector<vk::ImageView> SwapchainManager::createSwapchainImageViews(SwapchainHandle& handle) { + std::vector<vk::ImageView> + SwapchainManager::createSwapchainImageViews(SwapchainHandle &handle) { std::vector<vk::Image> images = getSwapchainImages(handle); - auto& swapchain = (*this)[handle]; + auto &swapchain = (*this) [handle]; std::vector<vk::ImageView> imageViews; imageViews.reserve(images.size()); - //here can be swizzled with vk::ComponentSwizzle if needed - vk::ComponentMapping componentMapping( - vk::ComponentSwizzle::eR, - vk::ComponentSwizzle::eG, - vk::ComponentSwizzle::eB, - vk::ComponentSwizzle::eA); + // here can be swizzled with vk::ComponentSwizzle if needed + vk::ComponentMapping componentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, + vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA); vk::ImageSubresourceRange subResourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1); for (auto image : images) { - vk::ImageViewCreateInfo imageViewCreateInfo( - vk::ImageViewCreateFlags(), - image, - vk::ImageViewType::e2D, - swapchain.m_Format, - componentMapping, - subResourceRange); - - imageViews.push_back(getCore().getContext().getDevice().createImageView(imageViewCreateInfo)); + vk::ImageViewCreateInfo imageViewCreateInfo(vk::ImageViewCreateFlags(), image, + vk::ImageViewType::e2D, swapchain.m_Format, + componentMapping, subResourceRange); + + imageViews.push_back( + getCore().getContext().getDevice().createImageView(imageViewCreateInfo)); } - + return imageViews; } -} \ No newline at end of file +} // namespace vkcv \ No newline at end of file diff --git a/src/vkcv/SwapchainManager.hpp b/src/vkcv/SwapchainManager.hpp index d9ba37aacaea1adc2587534e444a178cb701c95e..27262ec65da2b841597347c965fa462fae6a0d4c 100644 --- a/src/vkcv/SwapchainManager.hpp +++ b/src/vkcv/SwapchainManager.hpp @@ -14,36 +14,36 @@ #include "HandleManager.hpp" namespace vkcv { - + const uint32_t MIN_SURFACE_SIZE = 2; - + /** - * @brief Structure to handle swapchains. - */ + * @brief Structure to handle swapchains. + */ struct SwapchainEntry { vk::SwapchainKHR m_Swapchain; bool m_RecreationRequired; - + vk::SurfaceKHR m_Surface; uint32_t m_PresentQueueIndex; vk::Extent2D m_Extent; vk::Format m_Format; vk::ColorSpaceKHR m_ColorSpace; }; - + /** * @brief Class to manage the creation, destruction and * allocation of swapchains. */ class SwapchainManager : public HandleManager<SwapchainEntry, SwapchainHandle> { friend class Core; + private: - [[nodiscard]] - uint64_t getIdFrom(const SwapchainHandle& handle) const override; - - [[nodiscard]] - SwapchainHandle createById(uint64_t id, const HandleDestroyFunction& destroy) override; - + [[nodiscard]] uint64_t getIdFrom(const SwapchainHandle &handle) const override; + + [[nodiscard]] SwapchainHandle createById(uint64_t id, + const HandleDestroyFunction &destroy) override; + /** * @brief Destroys a specific swapchain by a given id * @@ -70,9 +70,8 @@ namespace vkcv { * @param handle of the swapchain to get * @return the reference of the swapchain */ - [[nodiscard]] - SwapchainEntry& getSwapchain(const SwapchainHandle& handle); - + [[nodiscard]] SwapchainEntry &getSwapchain(const SwapchainHandle &handle); + /** * @brief Checks whether the swapchain needs to be recreated. * @@ -80,51 +79,49 @@ namespace vkcv { * @return True, if the swapchain should be updated, * otherwise false. */ - bool shouldUpdateSwapchain(const SwapchainHandle& handle) const; - + bool shouldUpdateSwapchain(const SwapchainHandle &handle) const; + /** * @brief Updates and recreates the swapchain. * * @param[in] handle Swapchain handle * @param[in] window that the new swapchain gets bound to */ - void updateSwapchain(const SwapchainHandle& handle, const Window &window); - + void updateSwapchain(const SwapchainHandle &handle, const Window &window); + /** * @brief Signals the swapchain to be recreated. * * @param[in] handle Swapchain handle */ - void signalRecreation(const SwapchainHandle& handle); - + void signalRecreation(const SwapchainHandle &handle); + /** - * @brief Returns the image format for the current surface - * of the swapchain. - * - * @param[in] handle Swapchain handle - * @return Swapchain image format - */ - [[nodiscard]] - vk::Format getFormat(const SwapchainHandle& handle) const; - + * @brief Returns the image format for the current surface + * of the swapchain. + * + * @param[in] handle Swapchain handle + * @return Swapchain image format + */ + [[nodiscard]] vk::Format getFormat(const SwapchainHandle &handle) const; + /** * @brief Returns the amount of images for the swapchain. * * @param[in] handle Swapchain handle * @return Number of images - */ - uint32_t getImageCount(const SwapchainHandle& handle) const; - + */ + uint32_t getImageCount(const SwapchainHandle &handle) const; + /** - * @brief Returns the extent from the current surface of - * the swapchain. - * - * @param[in] handle Swapchain handle - * @return Extent of the swapchains surface - */ - [[nodiscard]] - const vk::Extent2D& getExtent(const SwapchainHandle& handle) const; - + * @brief Returns the extent from the current surface of + * the swapchain. + * + * @param[in] handle Swapchain handle + * @return Extent of the swapchains surface + */ + [[nodiscard]] const vk::Extent2D &getExtent(const SwapchainHandle &handle) const; + /** * @brief Returns the present queue index to be used with * the swapchain and its current surface. @@ -132,9 +129,8 @@ namespace vkcv { * @param[in] handle Swapchain handle * @return Present queue family index */ - [[nodiscard]] - uint32_t getPresentQueueIndex(const SwapchainHandle& handle) const; - + [[nodiscard]] uint32_t getPresentQueueIndex(const SwapchainHandle &handle) const; + /** * @brief Returns the color space of the surface from * a swapchain. @@ -142,25 +138,22 @@ namespace vkcv { * @param[in] handle Swapchain handle * @return Color space */ - [[nodiscard]] - vk::ColorSpaceKHR getSurfaceColorSpace(const SwapchainHandle& handle) const; + [[nodiscard]] vk::ColorSpaceKHR getSurfaceColorSpace(const SwapchainHandle &handle) const; /** * gets the swapchain images * @param handle of the swapchain * @return a vector of the swapchain images */ - [[nodiscard]] - std::vector<vk::Image> getSwapchainImages(const SwapchainHandle& handle) const; + [[nodiscard]] std::vector<vk::Image> + getSwapchainImages(const SwapchainHandle &handle) const; /** * creates the swapchain imageViews for the swapchain * @param handle of the swapchain which ImageViews should be created * @return a ov ImageViews of the swapchain */ - [[nodiscard]] - std::vector<vk::ImageView> createSwapchainImageViews(SwapchainHandle& handle); - + [[nodiscard]] std::vector<vk::ImageView> createSwapchainImageViews(SwapchainHandle &handle); }; - -} \ No newline at end of file + +} // namespace vkcv \ No newline at end of file diff --git a/src/vkcv/TypeGuard.cpp b/src/vkcv/TypeGuard.cpp index 31a758913e4fea5bdef5d91e9519b67eefdd1e93..742071bb7b8d055ff1e3037a825052b0f24ae84a 100644 --- a/src/vkcv/TypeGuard.cpp +++ b/src/vkcv/TypeGuard.cpp @@ -1,74 +1,65 @@ #include <vkcv/TypeGuard.hpp> -#include <vkcv/Logger.hpp> #include <string.h> +#include <vkcv/Logger.hpp> namespace vkcv { - + #ifndef NDEBUG bool TypeGuard::checkType(const char* name, size_t hash, size_t size) const { if (!checkTypeSize(size)) { return false; } - + if ((!m_typeName) || (!name)) { return true; } - + if (m_typeHash != hash) { - vkcv_log( - LogLevel::WARNING, - "Hash (%lu) does not match the specified hash of the type guard (%lu)", - hash, - m_typeHash - ); - + vkcv_log(LogLevel::WARNING, + "Hash (%lu) does not match the specified hash of the type guard (%lu)", hash, + m_typeHash); + return false; } - + if (strcmp(m_typeName, name) != 0) { - vkcv_log( - LogLevel::WARNING, - "Name (%s) does not match the specified name of the type guard (%s)", - name, - m_typeName - ); - + vkcv_log(LogLevel::WARNING, + "Name (%s) does not match the specified name of the type guard (%s)", name, + m_typeName); + return false; } else { return true; } } #endif - + bool TypeGuard::checkTypeSize(size_t size) const { if (m_typeSize != size) { - vkcv_log( - LogLevel::WARNING, - "Size (%lu) does not match the specified size of the type guard (%lu)", - size, - m_typeSize - ); - + vkcv_log(LogLevel::WARNING, + "Size (%lu) does not match the specified size of the type guard (%lu)", size, + m_typeSize); + return false; } else { return true; } } - + TypeGuard::TypeGuard(size_t size) : #ifndef NDEBUG - m_typeName(nullptr), m_typeHash(0), + m_typeName(nullptr), m_typeHash(0), #endif - m_typeSize(size) - {} - + m_typeSize(size) { + } + TypeGuard::TypeGuard(const std::type_info &info, size_t size) : #ifndef NDEBUG - m_typeName(info.name()), m_typeHash(info.hash_code()), + m_typeName(info.name()), m_typeHash(info.hash_code()), #endif - m_typeSize(size) - {} + m_typeSize(size) { + } bool TypeGuard::operator==(const TypeGuard &other) const { #ifndef NDEBUG @@ -90,4 +81,4 @@ namespace vkcv { return m_typeSize; } -} +} // namespace vkcv diff --git a/src/vkcv/VertexData.cpp b/src/vkcv/VertexData.cpp index bea3b700549f2951987f148f537461c9ca7f9041..9b9db90166a0be6f0e3a4a5666f837ceba293690 100644 --- a/src/vkcv/VertexData.cpp +++ b/src/vkcv/VertexData.cpp @@ -2,41 +2,38 @@ #include "vkcv/VertexData.hpp" namespace vkcv { - + VertexBufferBinding vertexBufferBinding(const BufferHandle &buffer, size_t offset) { - VertexBufferBinding binding (buffer, offset); + VertexBufferBinding binding(buffer, offset); return binding; } - - VertexData::VertexData(const std::vector<VertexBufferBinding> &bindings) - : m_bindings(bindings), - m_indices(), - m_indexBitCount(IndexBitCount::Bit16), - m_count(0) {} - + + VertexData::VertexData(const std::vector<VertexBufferBinding> &bindings) : + m_bindings(bindings), m_indices(), m_indexBitCount(IndexBitCount::Bit16), m_count(0) {} + const std::vector<VertexBufferBinding> &VertexData::getVertexBufferBindings() const { return m_bindings; } - + void VertexData::setIndexBuffer(const BufferHandle &indices, IndexBitCount indexBitCount) { m_indices = indices; m_indexBitCount = indexBitCount; } - + const BufferHandle &VertexData::getIndexBuffer() const { return m_indices; } - + IndexBitCount VertexData::getIndexBitCount() const { return m_indexBitCount; } - + void VertexData::setCount(size_t count) { m_count = count; } - + size_t VertexData::getCount() const { return m_count; } - -} + +} // namespace vkcv diff --git a/src/vkcv/VertexLayout.cpp b/src/vkcv/VertexLayout.cpp index 1409fee0e485eb389fbd4697a4da98c0cdae2813..252973f539af51e67ecb30bbe86717961c3a17d6 100644 --- a/src/vkcv/VertexLayout.cpp +++ b/src/vkcv/VertexLayout.cpp @@ -6,53 +6,54 @@ #include "vkcv/Logger.hpp" namespace vkcv { - - uint32_t getFormatSize(VertexAttachmentFormat format) { - switch (format) { - case VertexAttachmentFormat::FLOAT: - return 4; - case VertexAttachmentFormat::FLOAT2: - return 8; - case VertexAttachmentFormat::FLOAT3: - return 12; - case VertexAttachmentFormat::FLOAT4: - return 16; - case VertexAttachmentFormat::INT: - return 4; - case VertexAttachmentFormat::INT2: - return 8; - case VertexAttachmentFormat::INT3: - return 12; - case VertexAttachmentFormat::INT4: - return 16; - default: - vkcv_log(LogLevel::WARNING, "No format given"); - return 0; - } - } - - VertexBinding createVertexBinding(uint32_t bindingLocation, const VertexAttachments &attachments) { + + uint32_t getFormatSize(VertexAttachmentFormat format) { + switch (format) { + case VertexAttachmentFormat::FLOAT: + return 4; + case VertexAttachmentFormat::FLOAT2: + return 8; + case VertexAttachmentFormat::FLOAT3: + return 12; + case VertexAttachmentFormat::FLOAT4: + return 16; + case VertexAttachmentFormat::INT: + return 4; + case VertexAttachmentFormat::INT2: + return 8; + case VertexAttachmentFormat::INT3: + return 12; + case VertexAttachmentFormat::INT4: + return 16; + default: + vkcv_log(LogLevel::WARNING, "No format given"); + return 0; + } + } + + VertexBinding createVertexBinding(uint32_t bindingLocation, + const VertexAttachments &attachments) { VertexBinding binding { bindingLocation, 0, attachments }; uint32_t offset = 0; - - for (auto& attachment : binding.vertexAttachments) { + + for (auto &attachment : binding.vertexAttachments) { attachment.offset = offset; offset += getFormatSize(attachment.format); } - + binding.stride = offset; return binding; } - + VertexBindings createVertexBindings(const VertexAttachments &attachments) { VertexBindings bindings; bindings.reserve(attachments.size()); - + for (uint32_t i = 0; i < attachments.size(); i++) { - bindings.push_back(createVertexBinding(i, { attachments[i] })); + bindings.push_back(createVertexBinding(i, { attachments [i] })); } - + return bindings; } - -} \ No newline at end of file + +} // namespace vkcv \ No newline at end of file diff --git a/src/vkcv/Window.cpp b/src/vkcv/Window.cpp index 8787053dd046d625961cc26c995fec28dc43d74b..f989f1b84014aaca0a703e57d27151faa960a8bd 100644 --- a/src/vkcv/Window.cpp +++ b/src/vkcv/Window.cpp @@ -1,94 +1,96 @@ +#include <GLFW/glfw3.h> #include <thread> #include <vector> -#include <GLFW/glfw3.h> #include "vkcv/Window.hpp" namespace vkcv { - - void Window_onMouseButtonEvent(GLFWwindow *callbackWindow, int button, int action, int mods) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); + + void Window_onMouseButtonEvent(GLFWwindow* callbackWindow, int button, int action, int mods) { + auto window = static_cast<Window*>(glfwGetWindowUserPointer(callbackWindow)); if (window != nullptr) { window->e_mouseButton(button, action, mods); } } - void Window_onMouseMoveEvent(GLFWwindow *callbackWindow, double x, double y) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); + void Window_onMouseMoveEvent(GLFWwindow* callbackWindow, double x, double y) { + auto window = static_cast<Window*>(glfwGetWindowUserPointer(callbackWindow)); if (window != nullptr) { window->e_mouseMove(x, y); } } - void Window_onMouseScrollEvent(GLFWwindow *callbackWindow, double xoffset, double yoffset) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); + void Window_onMouseScrollEvent(GLFWwindow* callbackWindow, double xoffset, double yoffset) { + auto window = static_cast<Window*>(glfwGetWindowUserPointer(callbackWindow)); if (window != nullptr) { window->e_mouseScroll(xoffset, yoffset); } } - void Window_onResize(GLFWwindow *callbackWindow, int width, int height) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); + void Window_onResize(GLFWwindow* callbackWindow, int width, int height) { + auto window = static_cast<Window*>(glfwGetWindowUserPointer(callbackWindow)); if (window != nullptr) { window->e_resize(width, height); } } - void Window_onKeyEvent(GLFWwindow *callbackWindow, int key, int scancode, int action, int mods) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); + void Window_onKeyEvent(GLFWwindow* callbackWindow, int key, int scancode, int action, + int mods) { + auto window = static_cast<Window*>(glfwGetWindowUserPointer(callbackWindow)); if (window != nullptr) { window->e_key(key, scancode, action, mods); } } - - void Window_onCharEvent(GLFWwindow *callbackWindow, unsigned int c) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); - + + void Window_onCharEvent(GLFWwindow* callbackWindow, unsigned int c) { + auto window = static_cast<Window*>(glfwGetWindowUserPointer(callbackWindow)); + if (window != nullptr) { window->e_char(c); } } - + static std::vector<GLFWwindow*> s_Windows; void Window_onGamepadEvent(int gamepadIndex) { Window::getFocusedWindow().e_gamepad(gamepadIndex); } - - static GLFWwindow* createGLFWWindow(const char *windowTitle, int width, int height, bool resizable) { - if(s_Windows.empty()) { + + static GLFWwindow* createGLFWWindow(const char* windowTitle, int width, int height, + bool resizable) { + if (s_Windows.empty()) { glfwInit(); } - + width = std::max(width, 1); height = std::max(height, 1); - + glfwDefaultWindowHints(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, resizable ? GLFW_TRUE : GLFW_FALSE); - - GLFWwindow *window = glfwCreateWindow(width, height, windowTitle, nullptr, nullptr); - + + GLFWwindow* window = glfwCreateWindow(width, height, windowTitle, nullptr, nullptr); + if (window) { s_Windows.push_back(window); } - + return window; } - - static void bindGLFWWindow(GLFWwindow *windowHandle, Window* window) { + + static void bindGLFWWindow(GLFWwindow* windowHandle, Window* window) { if (!windowHandle) { return; } - + glfwSetWindowUserPointer(windowHandle, window); - + // combine Callbacks with Events glfwSetMouseButtonCallback(windowHandle, Window_onMouseButtonEvent); glfwSetCursorPosCallback(windowHandle, Window_onMouseMoveEvent); @@ -97,72 +99,55 @@ namespace vkcv { glfwSetScrollCallback(windowHandle, Window_onMouseScrollEvent); glfwSetCharCallback(windowHandle, Window_onCharEvent); } - + Window::Window() : - m_title(), - m_resizable(false), - m_shouldClose(false), - m_window(nullptr), - e_mouseButton(true), - e_mouseMove(true), - e_mouseScroll(true), - e_resize(true), - e_key(true), - e_char(true), - e_gamepad(true) - {} - - Window::Window(const char* title, int width, int height, bool resizable) : - m_title(title), - m_resizable(resizable), - m_shouldClose(false), - m_window(createGLFWWindow(title, width, height, resizable)), - e_mouseButton(true), - e_mouseMove(true), - e_mouseScroll(true), - e_resize(true), - e_key(true), - e_char(true), - e_gamepad(true) - { + m_title(), m_resizable(false), m_shouldClose(false), m_window(nullptr), e_mouseButton(true), + e_mouseMove(true), e_mouseScroll(true), e_resize(true), e_key(true), e_char(true), + e_gamepad(true) {} + + Window::Window(const std::string &title, int width, int height, bool resizable) : + m_title(title), m_resizable(resizable), m_shouldClose(false), + m_window(createGLFWWindow(title.c_str(), width, height, resizable)), e_mouseButton(true), + e_mouseMove(true), e_mouseScroll(true), e_resize(true), e_key(true), e_char(true), + e_gamepad(true) { bindGLFWWindow(m_window, this); - } - - Window::~Window() { - Window::e_mouseButton.unlock(); - Window::e_mouseMove.unlock(); - Window::e_mouseScroll.unlock(); - Window::e_resize.unlock(); - Window::e_key.unlock(); - Window::e_char.unlock(); - Window::e_gamepad.unlock(); + } + + Window::~Window() { + Window::e_mouseButton.unlock(); + Window::e_mouseMove.unlock(); + Window::e_mouseScroll.unlock(); + Window::e_resize.unlock(); + Window::e_key.unlock(); + Window::e_char.unlock(); + Window::e_gamepad.unlock(); Window::e_resize.remove(m_resizeHandle); - if (m_window) { - s_Windows.erase(std::find(s_Windows.begin(), s_Windows.end(), m_window)); - glfwDestroyWindow(m_window); - } + if (m_window) { + s_Windows.erase(std::find(s_Windows.begin(), s_Windows.end(), m_window)); + glfwDestroyWindow(m_window); + } - if(s_Windows.empty()) { - glfwTerminate(); - } - } + if (s_Windows.empty()) { + glfwTerminate(); + } + } bool Window::hasOpenWindow() { for (auto glfwWindow : s_Windows) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(glfwWindow)); - + auto window = static_cast<Window*>(glfwGetWindowUserPointer(glfwWindow)); + if (window->isOpen()) { return true; } } - + return false; } - void Window::pollEvents() { - for (auto glfwWindow : s_Windows) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(glfwWindow)); - + void Window::pollEvents() { + for (auto glfwWindow : s_Windows) { + auto window = static_cast<Window*>(glfwGetWindowUserPointer(glfwWindow)); + window->e_mouseButton.unlock(); window->e_mouseMove.unlock(); window->e_mouseScroll.unlock(); @@ -174,15 +159,16 @@ namespace vkcv { glfwPollEvents(); - for (int gamepadIndex = GLFW_JOYSTICK_1; gamepadIndex <= GLFW_JOYSTICK_LAST; gamepadIndex++) { + for (int gamepadIndex = GLFW_JOYSTICK_1; gamepadIndex <= GLFW_JOYSTICK_LAST; + gamepadIndex++) { if (glfwJoystickPresent(gamepadIndex)) { Window_onGamepadEvent(gamepadIndex); } } - + for (auto glfwWindow : s_Windows) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(glfwWindow)); - + auto window = static_cast<Window*>(glfwGetWindowUserPointer(glfwWindow)); + window->e_mouseButton.lock(); window->e_mouseMove.lock(); window->e_mouseScroll.lock(); @@ -190,101 +176,99 @@ namespace vkcv { window->e_key.lock(); window->e_char.lock(); window->e_gamepad.lock(); - + window->m_shouldClose |= glfwWindowShouldClose(glfwWindow); } - } - - const std::vector<std::string>& Window::getExtensions() { + } + + const std::vector<std::string> &Window::getExtensions() { static std::vector<std::string> extensions; - + if (extensions.empty()) { - if(s_Windows.empty()) { + if (s_Windows.empty()) { glfwInit(); } - + uint32_t glfwExtensionCount = 0; const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); - + for (uint32_t i = 0; i < glfwExtensionCount; i++) { - extensions.emplace_back(glfwExtensions[i]); + extensions.emplace_back(glfwExtensions [i]); } - + if (s_Windows.empty()) { glfwTerminate(); } } - + return extensions; } - bool Window::isOpen() const { + bool Window::isOpen() const { if (!m_window) { return false; } - - return !m_shouldClose; - } - - const std::string& Window::getTitle() const { - return m_title; - } - - int Window::getWidth() const { - int width = 0; - - if (m_window) { - glfwGetWindowSize(m_window, &width, nullptr); - } - - return std::max(width, 1); - } - - int Window::getHeight() const { - int height = 0; - - if (m_window) { - glfwGetWindowSize(m_window, nullptr, &height); - } - - return std::max(height, 1); - } - + + return !m_shouldClose; + } + + const std::string &Window::getTitle() const { + return m_title; + } + + int Window::getWidth() const { + int width = 0; + + if (m_window) { + glfwGetWindowSize(m_window, &width, nullptr); + } + + return std::max(width, 1); + } + + int Window::getHeight() const { + int height = 0; + + if (m_window) { + glfwGetWindowSize(m_window, nullptr, &height); + } + + return std::max(height, 1); + } + bool Window::isResizable() const { return m_resizable; } - GLFWwindow* Window::getWindow() const { - return m_window; - } - - void Window::getFramebufferSize(int &width, int &height) const { + GLFWwindow* Window::getWindow() const { + return m_window; + } + + void Window::getFramebufferSize(int &width, int &height) const { if (m_window) { glfwGetFramebufferSize(m_window, &width, &height); } else { width = 0; height = 0; } - } + } - Window& Window::getFocusedWindow() { + Window &Window::getFocusedWindow() { static Window defaultWindow; - auto activeWindowIterator = std::find_if( - s_Windows.begin(), - s_Windows.end(), - [](GLFWwindow *window) { return glfwGetWindowAttrib(window, GLFW_FOCUSED); } - ); + auto activeWindowIterator = + std::find_if(s_Windows.begin(), s_Windows.end(), [](GLFWwindow* window) { + return glfwGetWindowAttrib(window, GLFW_FOCUSED); + }); - if( activeWindowIterator == s_Windows.end() ) - { + if (activeWindowIterator == s_Windows.end()) { return defaultWindow; } - Window& window = *static_cast<Window *>(glfwGetWindowUserPointer(*activeWindowIterator)); + Window &window = *static_cast<Window*>(glfwGetWindowUserPointer(*activeWindowIterator)); return window; } SwapchainHandle Window::getSwapchain() const { return m_swapchainHandle; } -} +} // namespace vkcv diff --git a/src/vkcv/WindowManager.cpp b/src/vkcv/WindowManager.cpp index 930c5f3a1d5b6c405f83fc94fdc9998efc9c1fea..058ee21933ee00df49bd158ded4e8a38979f67c3 100644 --- a/src/vkcv/WindowManager.cpp +++ b/src/vkcv/WindowManager.cpp @@ -1,70 +1,66 @@ #include "WindowManager.hpp" namespace vkcv { - + uint64_t WindowManager::getIdFrom(const WindowHandle &handle) const { return handle.getId(); } - + WindowHandle WindowManager::createById(uint64_t id, const HandleDestroyFunction &destroy) { return WindowHandle(id, destroy); } - + void WindowManager::destroyById(uint64_t id) { - auto& window = getById(id); + auto &window = getById(id); if (window) { delete window; window = nullptr; } } - - WindowManager::WindowManager() noexcept : HandleManager<Window *, WindowHandle>() {} + + WindowManager::WindowManager() noexcept : HandleManager<Window*, WindowHandle>() {} WindowManager::~WindowManager() noexcept { clear(); } WindowHandle WindowManager::createWindow(SwapchainManager &swapchainManager, - const char *applicationName, - uint32_t windowWidth, - uint32_t windowHeight, + const std::string &applicationName, + uint32_t windowWidth, uint32_t windowHeight, bool resizeable) { - auto window = new Window( - applicationName, - static_cast<int>(windowWidth), - static_cast<int>(windowHeight), - resizeable - ); + auto window = new Window(applicationName, static_cast<int>(windowWidth), + static_cast<int>(windowHeight), resizeable); SwapchainHandle swapchainHandle = swapchainManager.createSwapchain(*window); if (resizeable) { - const event_handle<int, int> &resizeHandle = window->e_resize.add([&,handle=swapchainHandle](int width, int height) { - // copy handle because it would run out of scope and be invalid - swapchainManager.signalRecreation(handle); - }); - + const event_handle<int, int> &resizeHandle = + window->e_resize.add([&, handle = swapchainHandle](int width, int height) { + // copy handle because it would run out of scope and be invalid + swapchainManager.signalRecreation(handle); + }); + window->m_resizeHandle = resizeHandle; } return add(window); } - Window &WindowManager::getWindow(const WindowHandle& handle) const { - return *(*this)[handle]; + Window &WindowManager::getWindow(const WindowHandle &handle) const { + return *(*this) [handle]; } - + std::vector<WindowHandle> WindowManager::getWindowHandles() const { std::vector<WindowHandle> handles; - + for (size_t id = 0; id < getCount(); id++) { if (getById(id)->isOpen()) { handles.push_back(WindowHandle(id)); } } - + return handles; } -} \ No newline at end of file +} // namespace vkcv \ No newline at end of file diff --git a/src/vkcv/WindowManager.hpp b/src/vkcv/WindowManager.hpp index 172cec2a1c9ee5a5c437c8e25f4daec4965fa9e9..71b107c71baca467b035cc326abc7e2d488ad586 100644 --- a/src/vkcv/WindowManager.hpp +++ b/src/vkcv/WindowManager.hpp @@ -1,8 +1,9 @@ #pragma once +#include <GLFW/glfw3.h> #include <memory> +#include <string> #include <vector> -#include <GLFW/glfw3.h> #include "vkcv/Window.hpp" @@ -18,12 +19,11 @@ namespace vkcv { friend class Core; private: - [[nodiscard]] - uint64_t getIdFrom(const WindowHandle& handle) const override; - - [[nodiscard]] - WindowHandle createById(uint64_t id, const HandleDestroyFunction& destroy) override; - + [[nodiscard]] uint64_t getIdFrom(const WindowHandle &handle) const override; + + [[nodiscard]] WindowHandle createById(uint64_t id, + const HandleDestroyFunction &destroy) override; + /** * Destroys a specific window by a given id. * @@ -49,27 +49,22 @@ namespace vkcv { * @return window handle */ WindowHandle createWindow(SwapchainManager &swapchainManager, - const char *applicationName, - uint32_t windowWidth, - uint32_t windowHeight, - bool resizeable); + const std::string &applicationName, uint32_t windowWidth, + uint32_t windowHeight, bool resizeable); /** * @param handle of the window to get * @return the reference of the window */ - [[nodiscard]] - Window &getWindow(const WindowHandle& handle) const; - + [[nodiscard]] Window &getWindow(const WindowHandle &handle) const; + /** * Returns a list of window handles for current active * and open windows. * * @return List of window handles */ - [[nodiscard]] - std::vector<WindowHandle> getWindowHandles() const; - + [[nodiscard]] std::vector<WindowHandle> getWindowHandles() const; }; - -} \ No newline at end of file + +} // namespace vkcv \ No newline at end of file