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);
+	
+	};
+	
+}