diff --git a/config/Sources.cmake b/config/Sources.cmake index cb73f57c2ca7278765ef0c8d01989c09a445c7b5..9d1743fa7cfe43c460ad68c4c40ab12a4f904496 100644 --- a/config/Sources.cmake +++ b/config/Sources.cmake @@ -61,4 +61,7 @@ set(vkcv_sources ${vkcv_include}/vkcv/DescriptorConfig.hpp ${vkcv_source}/vkcv/DescriptorConfig.cpp + + ${vkcv_source}/vkcv/SamplerManager.hpp + ${vkcv_source}/vkcv/SamplerManager.cpp ) diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index e2fc5c587247a915f5bca345f8077f33ee5d8977..ffee796dab83a0c760d2b74586b0b0c500f57e20 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -18,6 +18,7 @@ #include "SyncResources.hpp" #include "Result.hpp" #include "vkcv/DescriptorConfig.hpp" +#include "Sampler.hpp" namespace vkcv { @@ -26,6 +27,7 @@ namespace vkcv class PipelineManager; class DescriptorManager; class BufferManager; + class SamplerManager; struct SubmitInfo { QueueType queueType; @@ -63,6 +65,7 @@ namespace vkcv std::unique_ptr<PipelineManager> m_PipelineManager; std::unique_ptr<DescriptorManager> m_DescriptorManager; std::unique_ptr<BufferManager> m_BufferManager; + std::unique_ptr<SamplerManager> m_SamplerManager; CommandResources m_CommandResources; SyncResources m_SyncResources; @@ -160,7 +163,7 @@ namespace vkcv PassHandle createPass(const PassConfig &config); /** - * Creates a #Buffer with data-type T and @p bufferType + * Creates a #Buffer with data-type T and @p bufferType * @param type Type of Buffer created * @param count Count of elements of type T * @param memoryType Type of Buffers memory @@ -170,6 +173,19 @@ namespace vkcv Buffer<T> createBuffer(vkcv::BufferType type, size_t count, BufferMemoryType memoryType = BufferMemoryType::DEVICE_LOCAL) { return Buffer<T>::create(m_BufferManager.get(), type, count, memoryType); } + + /** + * Creates a Sampler with given attributes. + * + * @param magFilter Magnifying filter + * @param minFilter Minimizing filter + * @param mipmapMode Mipmapping filter + * @param addressMode Address mode + * @return Sampler handle + */ + [[nodiscard]] + SamplerHandle createSampler(SamplerFilterType magFilter, SamplerFilterType minFilter, + SamplerMipmapMode mipmapMode, SamplerAddressMode addressMode); /** TODO: * @param setDescriptions diff --git a/include/vkcv/Handles.hpp b/include/vkcv/Handles.hpp index ad48a1ecbd41f75286cc33e88e62699468a5f11f..40cfa8e4cd7d8971303318ec1a5507a58977a213 100644 --- a/include/vkcv/Handles.hpp +++ b/include/vkcv/Handles.hpp @@ -14,4 +14,5 @@ namespace vkcv struct PassHandle {uint64_t id;}; struct PipelineHandle {uint64_t id;}; struct ResourcesHandle {uint64_t id;}; + struct SamplerHandle {uint64_t id;}; } diff --git a/include/vkcv/Sampler.hpp b/include/vkcv/Sampler.hpp new file mode 100644 index 0000000000000000000000000000000000000000..007ed5ae4737275ddacbc5881a2c4c202b8806a4 --- /dev/null +++ b/include/vkcv/Sampler.hpp @@ -0,0 +1,22 @@ +#pragma once + +namespace vkcv { + + enum class SamplerFilterType { + NEAREST = 1, + LINEAR = 2 + }; + + enum class SamplerMipmapMode { + NEAREST = 1, + LINEAR = 2 + }; + + enum class SamplerAddressMode { + REPEAT = 1, + MIRRORED_REPEAT = 2, + CLAMP_TO_EDGE = 3, + MIRROR_CLAMP_TO_EDGE = 4 + }; + +} diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index 07da9506c5546985d4852e5d7d87ecbbcfe5e788..620fe0652c189bc3f928c9183c9403387a93b3e0 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -53,6 +53,13 @@ int main(int argc, const char** argv) { m[1] = { 0, 0, 0 }; m[2] = { 0, 0, 0 }; buffer.unmap();*/ + + vkcv::SamplerHandle sampler = core.createSampler( + vkcv::SamplerFilterType::NEAREST, + vkcv::SamplerFilterType::NEAREST, + vkcv::SamplerMipmapMode::NEAREST, + vkcv::SamplerAddressMode::REPEAT + ); std::cout << "Physical device: " << physicalDevice.getProperties().deviceName << std::endl; diff --git a/src/vkcv/BufferManager.cpp b/src/vkcv/BufferManager.cpp index cb2425a51ee177d062120b0eb61ae089f6f1692f..a91a0a1479cc1f7ff7e1421c37f0313a4e137b3d 100644 --- a/src/vkcv/BufferManager.cpp +++ b/src/vkcv/BufferManager.cpp @@ -280,10 +280,12 @@ namespace vkcv { if (buffer.m_memory) { device.freeMemory(buffer.m_memory); + buffer.m_memory = nullptr; } if (buffer.m_handle) { device.destroyBuffer(buffer.m_handle); + buffer.m_handle = nullptr; } } diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index fa53b4faa666134bde9230863f78c96e648c9037..b328b0cff15536df55cf4ec1e4c002cae3be63f7 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -10,6 +10,7 @@ #include "PassManager.hpp" #include "PipelineManager.hpp" #include "vkcv/BufferManager.hpp" +#include "SamplerManager.hpp" #include "DescriptorManager.hpp" #include "Surface.hpp" #include "ImageLayoutTransitions.hpp" @@ -95,6 +96,7 @@ namespace vkcv m_PipelineManager{std::make_unique<PipelineManager>(m_Context.m_Device)}, m_DescriptorManager(std::make_unique<DescriptorManager>(m_Context.m_Device)), m_BufferManager{std::unique_ptr<BufferManager>(new BufferManager())}, + m_SamplerManager(std::unique_ptr<SamplerManager>(new SamplerManager(m_Context.m_Device))), m_CommandResources(commandResources), m_SyncResources(syncResources) { @@ -253,6 +255,11 @@ namespace vkcv finish(); } } + + SamplerHandle Core::createSampler(SamplerFilterType magFilter, SamplerFilterType minFilter, + SamplerMipmapMode mipmapMode, SamplerAddressMode addressMode) { + return m_SamplerManager->createSampler(magFilter, minFilter, mipmapMode, addressMode); + } ResourcesHandle Core::createResourceDescription(const std::vector<DescriptorSet> &descriptorSets) { diff --git a/src/vkcv/SamplerManager.cpp b/src/vkcv/SamplerManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9ff5481bdcd4792acc6125c5331d71cb3f7563df --- /dev/null +++ b/src/vkcv/SamplerManager.cpp @@ -0,0 +1,127 @@ + +#include "SamplerManager.hpp" +#include "vkcv/Core.hpp" + +namespace vkcv { + + SamplerManager::SamplerManager(const vk::Device& device) noexcept : + m_device(device), m_samplers() + {} + + SamplerManager::~SamplerManager() { + for (uint64_t id = 0; id < m_samplers.size(); id++) { + destroySampler(SamplerHandle{id}); + } + } + + SamplerHandle SamplerManager::createSampler(SamplerFilterType magFilter, + SamplerFilterType minFilter, + SamplerMipmapMode mipmapMode, + SamplerAddressMode addressMode) { + vk::Filter vkMagFilter; + vk::Filter vkMinFilter; + vk::SamplerMipmapMode vkMipmapMode; + vk::SamplerAddressMode vkAddressMode; + + switch (magFilter) { + 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(); + } + + switch (mipmapMode) { + 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; + default: + return SamplerHandle(); + } + + const vk::SamplerCreateInfo samplerCreateInfo ( + vk::SamplerCreateFlags(), + vkMagFilter, + vkMinFilter, + vkMipmapMode, + vkAddressMode, + vkAddressMode, + vkAddressMode, + 0.0f, + false, + 16.0f, + false, + vk::CompareOp::eAlways, + 0.0f, + 1.0f, + vk::BorderColor::eIntOpaqueBlack, + false + ); + + const vk::Sampler sampler = m_device.createSampler(samplerCreateInfo); + + const uint64_t id = m_samplers.size(); + m_samplers.push_back(sampler); + return SamplerHandle{id}; + } + + vk::Sampler SamplerManager::getVulkanSampler(const SamplerHandle &handle) const { + const uint64_t id = handle.id; + + if (id >= m_samplers.size()) { + return nullptr; + } + + return m_samplers[id]; + } + + void SamplerManager::destroySampler(const SamplerHandle &handle) { + const uint64_t id = handle.id; + + if (id >= m_samplers.size()) { + return; + } + + auto& sampler = m_samplers[id]; + + if (sampler) { + m_device.destroySampler(sampler); + sampler = nullptr; + } + } + +} diff --git a/src/vkcv/SamplerManager.hpp b/src/vkcv/SamplerManager.hpp new file mode 100644 index 0000000000000000000000000000000000000000..41f58b2f33daaf8b08c785c05c7f14184cf47958 --- /dev/null +++ b/src/vkcv/SamplerManager.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include <vector> +#include <vulkan/vulkan.hpp> + +#include "vkcv/Handles.hpp" +#include "vkcv/Sampler.hpp" + +namespace vkcv { + + class Core; + + class SamplerManager { + friend class Core; + private: + vk::Device m_device; + std::vector<vk::Sampler> m_samplers; + + explicit SamplerManager(const vk::Device& device) noexcept; + + public: + ~SamplerManager(); + + SamplerManager(const SamplerManager& other) = delete; + SamplerManager(SamplerManager&& other) = delete; + + SamplerManager& operator=(const SamplerManager& other) = delete; + SamplerManager& operator=(SamplerManager&& other) = delete; + + SamplerHandle createSampler(SamplerFilterType magFilter, + SamplerFilterType minFilter, + SamplerMipmapMode mipmapMode, + SamplerAddressMode addressMode); + + [[nodiscard]] + vk::Sampler getVulkanSampler(const SamplerHandle& handle) const; + + void destroySampler(const SamplerHandle& handle); + + }; + +}