diff --git a/config/Sources.cmake b/config/Sources.cmake index 1b35d798597d0c781d5c4e90679679a83fcedcb2..e7a36ff1eb287bbbc6e3331adaa84ab476916d21 100644 --- a/config/Sources.cmake +++ b/config/Sources.cmake @@ -67,4 +67,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 aa2d4a0996eb47b1c9c8a10d0ec3449775a9e504..6451d81ad3afd3f8154d778c9bceb68cdf34ba73 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -19,6 +19,7 @@ #include "SyncResources.hpp" #include "Result.hpp" #include "vkcv/DescriptorConfig.hpp" +#include "Sampler.hpp" namespace vkcv { @@ -32,6 +33,7 @@ namespace vkcv class PipelineManager; class DescriptorManager; class BufferManager; + class SamplerManager; class ImageManager; struct SubmitInfo { @@ -70,6 +72,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; std::unique_ptr<ImageManager> m_ImageManager; CommandResources m_CommandResources; @@ -168,7 +171,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 @@ -179,6 +182,19 @@ namespace vkcv 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); + /** * Creates an #Image with a given format, width, height and depth. * diff --git a/include/vkcv/Handles.hpp b/include/vkcv/Handles.hpp index 1fd6573976b1f5aab572eb982cc0c61eff01a9e9..58f795f0c99a0cd1b05045f9f401a26c0aac1b88 100644 --- a/include/vkcv/Handles.hpp +++ b/include/vkcv/Handles.hpp @@ -9,6 +9,7 @@ namespace vkcv { + class Handle { friend std::ostream& operator << (std::ostream& out, const Handle& handle); @@ -64,6 +65,12 @@ namespace vkcv using Handle::Handle; }; + class SamplerHandle : public Handle { + friend class SamplerManager; + private: + using Handle::Handle; + }; + class ImageHandle : public Handle { friend class ImageManager; private: 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 a71531563e6742c9c2155e2b21b18c54b769514f..d51d60e4788aeb0271d434520fad29edc3804c55 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -58,6 +58,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/Core.cpp b/src/vkcv/Core.cpp index 902d7387c77c47946c20a7d196aa3b4892a98539..d8a67ebd2160a20a2e9b7c9b2cf81e9d6cab6b07 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 "ImageManager.hpp" #include "DescriptorManager.hpp" #include "Surface.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_ImageManager{std::unique_ptr<ImageManager>(new ImageManager(*m_BufferManager))}, m_CommandResources(commandResources), m_SyncResources(syncResources) @@ -320,6 +322,11 @@ namespace vkcv } } + SamplerHandle Core::createSampler(SamplerFilterType magFilter, SamplerFilterType minFilter, + SamplerMipmapMode mipmapMode, SamplerAddressMode addressMode) { + return m_SamplerManager->createSampler(magFilter, minFilter, mipmapMode, addressMode); + } + Image Core::createImage(vk::Format format, uint32_t width, uint32_t height, uint32_t depth) { return Image::create(m_ImageManager.get(), format, width, height, depth); diff --git a/src/vkcv/SamplerManager.cpp b/src/vkcv/SamplerManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7935bbc16a54f170cb38161629c109d56cf56d3c --- /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.getId(); + + if (id >= m_samplers.size()) { + return nullptr; + } + + return m_samplers[id]; + } + + void SamplerManager::destroySampler(const SamplerHandle &handle) { + const uint64_t id = handle.getId(); + + 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); + + }; + +}