diff --git a/config/Sources.cmake b/config/Sources.cmake
index ffbe38d67217ef515c89a5e6a26661441b22491d..ea9789752074a0f6b9f5c498c638ab1b13bc2d9d 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -26,13 +26,14 @@ set(vkcv_sources
 
 		${vkcv_include}/vkcv/Window.hpp
 		${vkcv_source}/vkcv/Window.cpp
-
+		
+		${vkcv_include}/vkcv/BufferTypes.hpp
 		${vkcv_include}/vkcv/Buffer.hpp
 		
 		${vkcv_include}/vkcv/PushConstants.hpp
 		${vkcv_source}/vkcv/PushConstants.cpp
 		
-		${vkcv_include}/vkcv/BufferManager.hpp
+		${vkcv_source}/vkcv/BufferManager.hpp
 		${vkcv_source}/vkcv/BufferManager.cpp
 
 		${vkcv_include}/vkcv/Image.hpp
@@ -101,7 +102,6 @@ set(vkcv_sources
         ${vkcv_include}/vkcv/DescriptorWrites.hpp
         
         ${vkcv_include}/vkcv/DrawcallRecording.hpp
-        ${vkcv_source}/vkcv/DrawcallRecording.cpp
         
         ${vkcv_source}/vkcv/CommandStreamManager.hpp
         ${vkcv_source}/vkcv/CommandStreamManager.cpp
diff --git a/include/vkcv/Buffer.hpp b/include/vkcv/Buffer.hpp
index 40821e68569397fce497426b66991fc38bb29859..be7cb66e97a68f9fd96bcf99495a1bda3db55078 100644
--- a/include/vkcv/Buffer.hpp
+++ b/include/vkcv/Buffer.hpp
@@ -7,8 +7,9 @@
 
 #include <vector>
 
+#include "BufferTypes.hpp"
+#include "Core.hpp"
 #include "Handles.hpp"
-#include "BufferManager.hpp"
 
 namespace vkcv {
 
@@ -19,10 +20,17 @@ namespace vkcv {
 	 */
 	template<typename T>
 	class Buffer {
-		friend class Core;
 	public:
-		// explicit destruction of default constructor
-		Buffer() = delete;
+		Buffer() : m_core(nullptr), m_handle() {};
+		
+		Buffer(const Buffer& other) = default;
+		Buffer(Buffer&& other) = default;
+		
+		Buffer& operator=(const Buffer& other) = default;
+		Buffer& operator=(Buffer&& other) = default;
+		
+		Buffer(Core* core, const BufferHandle& handle) :
+		m_core(core), m_handle(handle) {}
 		
 		/**
 		 * @brief Returns the buffers handle.
@@ -41,9 +49,14 @@ namespace vkcv {
 		 */
 		[[nodiscard]]
 		BufferType getType() const {
-			return m_type;
+			return m_core->getBufferType(m_handle);
 		};
 		
+		[[nodiscard]]
+		BufferMemoryType getMemoryType() const {
+			return m_core->getBufferMemoryType(m_handle);
+		}
+		
 		/**
 		 * @brief Returns the count of elements in the buffer.
 		 *
@@ -51,7 +64,7 @@ namespace vkcv {
 		 */
 		[[nodiscard]]
 		size_t getCount() const {
-			return m_count;
+			return m_core->getBufferSize(m_handle) / sizeof(T);
 		}
 		
 		/**
@@ -61,7 +74,7 @@ namespace vkcv {
 		 */
 		[[nodiscard]]
 		size_t getSize() const {
-			return m_count * sizeof(T);
+			return m_core->getBufferSize(m_handle);
 		}
 
 		/**
@@ -71,7 +84,7 @@ namespace vkcv {
 		 */
         [[nodiscard]]
 		vk::Buffer getVulkanHandle() const {
-            return m_manager->getBuffer(m_handle);
+            return m_core->getBuffer(m_handle);
         }
 
 		/**
@@ -84,7 +97,7 @@ namespace vkcv {
 		void fill(const T* data,
 				  size_t count = 0,
 				  size_t offset = 0) {
-			 m_manager->fillBuffer(m_handle, data, count * sizeof(T), offset * sizeof(T));
+			 m_core->fillBuffer(m_handle, data, count * sizeof(T), offset * sizeof(T));
 		}
 		
 		/**
@@ -108,7 +121,7 @@ namespace vkcv {
 		void read(T* data,
 				  size_t count = 0,
 				  size_t offset = 0) {
-			m_manager->readBuffer(m_handle, data, count * sizeof(T), offset * sizeof(T));
+			m_core->readBuffer(m_handle, data, count * sizeof(T), offset * sizeof(T));
 		}
 		
 		/**
@@ -132,77 +145,29 @@ namespace vkcv {
 		[[nodiscard]]
 		T* map(size_t offset = 0,
 			   size_t count = 0) {
-			return reinterpret_cast<T*>(m_manager->mapBuffer(m_handle, offset * sizeof(T), count * sizeof(T)));
+			return reinterpret_cast<T*>(m_core->mapBuffer(m_handle, offset * sizeof(T), count * sizeof(T)));
 		}
 
 		/**
 		 * @brief Unmaps the #Buffer, invalidates the pointer obtained by map().
 		 */
 		void unmap() {
-			m_manager->unmapBuffer(m_handle);
+			m_core->unmapBuffer(m_handle);
 		}
 
 	private:
-		BufferManager* const m_manager;
-		const BufferHandle m_handle;
-		const BufferType m_type;
-		const size_t m_count;
-		const BufferMemoryType m_memoryType;
-		
-		/**
-		 * @brief Constructor of the buffer object.
-		 *
-		 * @param[in,out] manager Buffer manager
-		 * @param[in] handle Buffer handle
-		 * @param[in] type Type of buffer
-		 * @param[in] count Count of elements
-		 * @param[in] memoryType Type of memory
-		 */
-		Buffer(BufferManager* manager,
-			   BufferHandle handle,
-			   BufferType type,
-			   size_t count,
-			   BufferMemoryType memoryType) :
-				m_manager(manager),
-				m_handle(handle),
-				m_type(type),
-				m_count(count),
-				m_memoryType(memoryType)
-		{}
-		
-		/**
-		 * @brief Creates a buffer object of type T with
-		 * a selected type, count of elements, memory type
-		 * and support of indirect usage.
-		 *
-		 * @param[in,out] manager Buffer manager
-		 * @param[in] type Buffer type
-		 * @param[in] count Count of elements
-		 * @param[in] memoryType Type of memory
-		 * @param[in] supportIndirect Support indirect usage
-		 * @return New buffer object
-		 */
-		[[nodiscard]]
-		static Buffer<T> create(BufferManager* manager,
-								BufferType type,
-								size_t count,
-								BufferMemoryType memoryType,
-								bool supportIndirect,
-								bool readable) {
-			return Buffer<T>(
-				manager,
-				manager->createBuffer(
-					type,
-					count * sizeof(T),
-					memoryType,
-					supportIndirect,
-					readable
-				),
-				type,
-				count,
-				memoryType
-			);
-		}
+		Core* m_core;
+		BufferHandle m_handle;
 		
 	};
+	
+	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));
+	}
+	
 }
diff --git a/include/vkcv/BufferTypes.hpp b/include/vkcv/BufferTypes.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..8d2938af50efd1b57ddd131837cc2e1198edab4f
--- /dev/null
+++ b/include/vkcv/BufferTypes.hpp
@@ -0,0 +1,34 @@
+#pragma once
+/**
+ * @authors Tobias Frisch
+ * @file vkcv/BufferTypes.hpp
+ * @brief Enum classes to specify attributes of buffers.
+ */
+
+namespace vkcv {
+	
+	/**
+	 * @brief Enum class to specify types of buffers.
+	 */
+	enum class BufferType {
+		INDEX,
+		VERTEX,
+		UNIFORM,
+		STORAGE,
+		STAGING,
+		INDIRECT,
+		
+		UNKNOWN
+	};
+	
+	/**
+	 * @brief Enum class to specify types of buffer memory.
+	 */
+	enum class BufferMemoryType {
+		DEVICE_LOCAL,
+		HOST_VISIBLE,
+		
+		UNKNOWN
+	};
+	
+}
diff --git a/include/vkcv/Context.hpp b/include/vkcv/Context.hpp
index d91855a54c83f17b8251aad7c6fe2cb2591f9add..bb2255c60e19266ae23d0ba51ff7681175ee68df 100644
--- a/include/vkcv/Context.hpp
+++ b/include/vkcv/Context.hpp
@@ -8,6 +8,7 @@
 #include <vulkan/vulkan.hpp>
 #include <vk_mem_alloc.hpp>
 
+#include "Handles.hpp"
 #include "QueueManager.hpp"
 #include "DrawcallRecording.hpp"
 #include "Features.hpp"
diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index be7cb6097acf2aa163c6e1ec8218a793caa6bd73..b93f70427919dc39d611a740d656b9def58d8897 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -9,12 +9,12 @@
 #include <memory>
 #include <vulkan/vulkan.hpp>
 
+#include "BufferTypes.hpp"
 #include "Context.hpp"
 #include "Swapchain.hpp"
 #include "Window.hpp"
 #include "PassConfig.hpp"
 #include "Handles.hpp"
-#include "Buffer.hpp"
 #include "Image.hpp"
 #include "BlitDownsampler.hpp"
 #include "GraphicsPipelineConfig.hpp"
@@ -192,43 +192,137 @@ namespace vkcv
          * 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 config a render pass config object from the render pass config class
+         * @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);
-
-        /**
-            * 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
-            * return Buffer-Object
-            */
-        template<typename T>
-        Buffer<T> createBuffer(vkcv::BufferType type,
-							   size_t count,
-							   BufferMemoryType memoryType = BufferMemoryType::DEVICE_LOCAL,
-							   bool supportIndirect = false,
-							   bool readable = false) {
-        	return Buffer<T>::create(
-					m_BufferManager.get(),
-					type,
-					count,
-					memoryType,
-					supportIndirect,
-					readable
-			);
-        }
+	
+		/**
+		 * @brief Creates a buffer with given parameters and returns its handle.
+		 *
+		 * @param[in] type Type of buffer created
+		 * @param[in] typeGuard Type guard for the buffer
+		 * @param[in] count Count of elements of its guarded type
+		 * @param[in] memoryType Type of buffers memory
+		 * @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,
+								  BufferMemoryType memoryType = BufferMemoryType::DEVICE_LOCAL,
+								  bool readable = false);
+	
+		/**
+		 * @brief Creates a buffer with given parameters and returns its handle.
+		 *
+		 * @param[in] type Type of buffer created
+		 * @param[in] size Size of the buffer
+		 * @param[in] memoryType Type of buffers memory
+		 * @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,
+								  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;
+	
+		/**
+		 * @brief Returns the buffer type of a buffer represented
+		 * by a given buffer handle.
+		 *
+		 * @param[in] buffer Buffer handle
+		 * @return Buffer type
+		 */
+		[[nodiscard]]
+		BufferType getBufferType(const BufferHandle& buffer) const;
+	
+		/**
+		 * @brief Returns the buffer memory type of a buffer
+		 * represented by a given buffer handle.
+		 *
+		 * @param[in] buffer Buffer handle
+		 * @return Buffer memory type
+		 */
+		[[nodiscard]]
+		BufferMemoryType getBufferMemoryType(const BufferHandle& buffer) const;
+	
+		/**
+		 * @brief Returns the size of a buffer represented
+		 * by a given buffer handle.
+		 *
+		 * @param[in] buffer Buffer handle
+		 * @return Size of the buffer
+		 */
+		[[nodiscard]]
+		size_t getBufferSize(const BufferHandle& buffer) const;
+	
+		/**
+		 * @brief Fills a buffer represented by a given buffer
+		 * handle with custom data.
+		 *
+		 * @param[in] buffer Buffer handle
+		 * @param[in] data Pointer to data
+		 * @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);
+	
+		/**
+		 * @brief Reads from a buffer represented by a given
+		 * buffer handle to some data pointer.
+		 *
+		 * @param[in] buffer Buffer handle
+		 * @param[in] data Pointer to data
+		 * @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);
+	
+		/**
+		 * @brief Maps memory to a buffer represented by a given
+		 * buffer handle and returns it.
+		 *
+		 * @param[in] buffer Buffer handle
+		 * @param[in] offset Offset of mapping in bytes
+		 * @param[in] size Size of mapping in bytes
+		 * @return Pointer to mapped memory
+		 */
+		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 magFilter Magnifying filter
-         * @param minFilter Minimizing filter
-         * @param mipmapMode Mipmapping filter
-         * @param addressMode Address mode
-         * @param mipLodBias Mip level of detail bias
+         * @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]]
@@ -465,7 +559,7 @@ namespace vkcv
                 const vkcv::DescriptorSetHandle                     &compiledDescriptorSet,
 				const vkcv::Mesh                                    &compiledMesh,
 				const std::vector<ImageHandle>                      &renderTargets,
-				const vkcv::Buffer<vk::DrawIndexedIndirectCommand>  &indirectBuffer,
+				const BufferHandle  								&indirectBuffer,
 				const uint32_t                                      drawCount,
 				const WindowHandle                                  &windowHandle);
 		
diff --git a/include/vkcv/DrawcallRecording.hpp b/include/vkcv/DrawcallRecording.hpp
index 76b94dc8b4f8595d98e87920329eb616d703f0db..597774eef59a2ac4d059dba1cfd9934370a86c4e 100644
--- a/include/vkcv/DrawcallRecording.hpp
+++ b/include/vkcv/DrawcallRecording.hpp
@@ -11,8 +11,6 @@
 #include "DescriptorConfig.hpp"
 #include "PushConstants.hpp"
 
-#include "Buffer.hpp"
-
 namespace vkcv {
 	
 	/**
@@ -92,13 +90,5 @@ namespace vkcv {
         std::vector<DescriptorSetUsage> descriptorSets;
         uint32_t taskCount;
     };
-
-    void recordMeshShaderDrawcall(const Core& core,
-								  vk::CommandBuffer cmdBuffer,
-								  vk::PipelineLayout pipelineLayout,
-								  const PushConstants& pushConstantData,
-								  uint32_t pushConstantOffset,
-								  const MeshShaderDrawcall& drawcall,
-								  uint32_t firstTask);
 	
 }
diff --git a/modules/algorithm/include/vkcv/algorithm/SinglePassDownsampler.hpp b/modules/algorithm/include/vkcv/algorithm/SinglePassDownsampler.hpp
index c2d9721d5db6791b82bcf5a7d0a832fd9ab5db77..a46ab4fc4e7ff237af52ba629455a06758e54e0f 100644
--- a/modules/algorithm/include/vkcv/algorithm/SinglePassDownsampler.hpp
+++ b/modules/algorithm/include/vkcv/algorithm/SinglePassDownsampler.hpp
@@ -2,6 +2,7 @@
 
 #include <vector>
 
+#include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
 #include <vkcv/Downsampler.hpp>
 #include <vkcv/ShaderProgram.hpp>
diff --git a/modules/algorithm/src/vkcv/algorithm/SinglePassDownsampler.cpp b/modules/algorithm/src/vkcv/algorithm/SinglePassDownsampler.cpp
index 40ac830cd894736b76c5d220118377d02e9bb1b5..0ebcbb5d3ac13886bd4779e750897b104bad8303 100644
--- a/modules/algorithm/src/vkcv/algorithm/SinglePassDownsampler.cpp
+++ b/modules/algorithm/src/vkcv/algorithm/SinglePassDownsampler.cpp
@@ -149,7 +149,8 @@ namespace vkcv::algorithm {
 		 m_descriptorSetLayout(),
 		 m_descriptorSets(),
 		
-		 m_globalCounter(m_core.createBuffer<uint32_t>(
+		 m_globalCounter(buffer<uint32_t>(
+				 m_core,
 				 vkcv::BufferType::STORAGE,
 				 6
 		 )),
diff --git a/modules/scene/src/vkcv/scene/MeshPart.cpp b/modules/scene/src/vkcv/scene/MeshPart.cpp
index 50d14ed49d43496ada3853034be1455b044bd902..adb611f0addec81510d1ede6899410c0913a8aab 100644
--- a/modules/scene/src/vkcv/scene/MeshPart.cpp
+++ b/modules/scene/src/vkcv/scene/MeshPart.cpp
@@ -2,6 +2,8 @@
 #include "vkcv/scene/MeshPart.hpp"
 #include "vkcv/scene/Scene.hpp"
 
+#include <vkcv/Buffer.hpp>
+
 namespace vkcv::scene {
 	
 	MeshPart::MeshPart(Scene& scene) :
@@ -18,8 +20,8 @@ namespace vkcv::scene {
 						std::vector<DrawcallInfo>& drawcalls) {
 		Core& core = *(m_scene.m_core);
 		
-		auto vertexBuffer = core.createBuffer<uint8_t>(
-				BufferType::VERTEX, vertexGroup.vertexBuffer.data.size()
+		auto vertexBuffer = buffer<uint8_t>(
+				core, BufferType::VERTEX, vertexGroup.vertexBuffer.data.size()
 		);
 		
 		vertexBuffer.fill(vertexGroup.vertexBuffer.data);
@@ -35,8 +37,8 @@ namespace vkcv::scene {
 			m_vertexBindings.emplace_back(attribute.offset, vertexBuffer.getVulkanHandle());
 		}
 		
-		auto indexBuffer = core.createBuffer<uint8_t>(
-				BufferType::INDEX, vertexGroup.indexBuffer.data.size()
+		auto indexBuffer = buffer<uint8_t>(
+				core, BufferType::INDEX, vertexGroup.indexBuffer.data.size()
 		);
 		
 		indexBuffer.fill(vertexGroup.indexBuffer.data);
diff --git a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
index fd5bbd3795d62aee7dac6e80a72066556a5ffe07..64bc78aca4fe42ff813d05fc016a70c7108bd557 100644
--- a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
+++ b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
@@ -2,6 +2,7 @@
 
 #include "Upscaling.hpp"
 
+#include <vkcv/Buffer.hpp>
 #include <vkcv/ShaderProgram.hpp>
 
 namespace vkcv::upscaling {
diff --git a/modules/upscaling/include/vkcv/upscaling/NISUpscaling.hpp b/modules/upscaling/include/vkcv/upscaling/NISUpscaling.hpp
index 9a35bfd57fd261587eea0d327d2eb3154b1cd38a..913983400808f3353adf3a1c653045345d36c6f1 100644
--- a/modules/upscaling/include/vkcv/upscaling/NISUpscaling.hpp
+++ b/modules/upscaling/include/vkcv/upscaling/NISUpscaling.hpp
@@ -2,6 +2,7 @@
 
 #include "Upscaling.hpp"
 
+#include <vkcv/Buffer.hpp>
 #include <vkcv/ShaderProgram.hpp>
 
 namespace vkcv::upscaling {
diff --git a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
index a470cd21aba04faf7087e883cadfecb322876553..a0858c1709e069847eb57ae61d22abcccfde48ab 100644
--- a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
+++ b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
@@ -164,12 +164,16 @@ namespace vkcv::upscaling {
 	m_rcasDescriptorSetLayout(m_core.createDescriptorSetLayout(getDescriptorBindings())),
 	m_rcasDescriptorSet(m_core.createDescriptorSet(m_rcasDescriptorSetLayout)),
 
-	m_easuConstants(m_core.createBuffer<FSRConstants>(
-			BufferType::UNIFORM,1,
+	m_easuConstants(buffer<FSRConstants>(
+			m_core,
+			BufferType::UNIFORM,
+			1,
 			BufferMemoryType::HOST_VISIBLE
 	)),
-	m_rcasConstants(m_core.createBuffer<FSRConstants>(
-			BufferType::UNIFORM,1,
+	m_rcasConstants(buffer<FSRConstants>(
+			m_core,
+			BufferType::UNIFORM,
+			1,
 			BufferMemoryType::HOST_VISIBLE
 	)),
 	m_intermediateImage(),
diff --git a/modules/upscaling/src/vkcv/upscaling/NISUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/NISUpscaling.cpp
index 2fd8e23f6c0a3c615ec6085ad1abfdad1a9794ab..21ad96526485f5fa8dcacfe02492a68e991eb712 100644
--- a/modules/upscaling/src/vkcv/upscaling/NISUpscaling.cpp
+++ b/modules/upscaling/src/vkcv/upscaling/NISUpscaling.cpp
@@ -137,8 +137,10 @@ namespace vkcv::upscaling {
 	m_scalerDescriptorSetLayout(m_core.createDescriptorSetLayout(getDescriptorBindings())),
 	m_scalerDescriptorSet(m_core.createDescriptorSet(m_scalerDescriptorSetLayout)),
 	
-	m_scalerConstants(m_core.createBuffer<uint8_t>(
-			BufferType::UNIFORM, sizeof(NISConfig),
+	m_scalerConstants(buffer<uint8_t>(
+			m_core,
+			BufferType::UNIFORM,
+			sizeof(NISConfig),
 			BufferMemoryType::HOST_VISIBLE
 	)),
 	m_sampler(m_core.createSampler(
diff --git a/projects/bindless_textures/src/main.cpp b/projects/bindless_textures/src/main.cpp
index fdef23f8537edeca665a4d4d9994e53af649e989..9ea16b91b1217bc3cee9ee0bcd3562bda0f5f963 100644
--- a/projects/bindless_textures/src/main.cpp
+++ b/projects/bindless_textures/src/main.cpp
@@ -1,4 +1,5 @@
 #include <iostream>
+#include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
@@ -79,7 +80,8 @@ int main(int argc, const char** argv) {
 	}
 
 	assert(!mesh.vertexGroups.empty());
-	auto vertexBuffer = core.createBuffer<uint8_t>(
+	auto vertexBuffer = vkcv::buffer<uint8_t>(
+			core,
 			vkcv::BufferType::VERTEX,
 			mesh.vertexGroups[0].vertexBuffer.data.size(),
 			vkcv::BufferMemoryType::DEVICE_LOCAL
@@ -87,7 +89,8 @@ int main(int argc, const char** argv) {
 	
 	vertexBuffer.fill(mesh.vertexGroups[0].vertexBuffer.data);
 
-	auto indexBuffer = core.createBuffer<uint8_t>(
+	auto indexBuffer = vkcv::buffer<uint8_t>(
+			core,
 			vkcv::BufferType::INDEX,
 			mesh.vertexGroups[0].indexBuffer.data.size(),
 			vkcv::BufferMemoryType::DEVICE_LOCAL
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index b84834cda37ef87eb6893ad201a230cbea422d20..6bb34e8ebae552a45043411967164a6e23cc35f8 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -1,4 +1,5 @@
 #include <iostream>
+#include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
 #include <vkcv/camera/CameraManager.hpp>
 #include <chrono>
@@ -30,7 +31,8 @@ int main(int argc, const char** argv) {
 	}
 
 	assert(!mesh.vertexGroups.empty());
-	auto vertexBuffer = core.createBuffer<uint8_t>(
+	auto vertexBuffer = vkcv::buffer<uint8_t>(
+			core,
 			vkcv::BufferType::VERTEX,
 			mesh.vertexGroups[0].vertexBuffer.data.size(),
 			vkcv::BufferMemoryType::DEVICE_LOCAL
@@ -38,7 +40,8 @@ int main(int argc, const char** argv) {
 	
 	vertexBuffer.fill(mesh.vertexGroups[0].vertexBuffer.data);
 
-	auto indexBuffer = core.createBuffer<uint8_t>(
+	auto indexBuffer = vkcv::buffer<uint8_t>(
+			core,
 			vkcv::BufferType::INDEX,
 			mesh.vertexGroups[0].indexBuffer.data.size(),
 			vkcv::BufferMemoryType::DEVICE_LOCAL
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index 81330c39c37b24d928e4c34958b8fd3a4dfda10e..6959e2bda1138971486dc2d703f30a6506f2781d 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -1,4 +1,5 @@
 #include <iostream>
+#include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
@@ -21,7 +22,7 @@ int main(int argc, const char** argv) {
 	vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, true);
 	vkcv::Window& window = core.getWindow(windowHandle);
 
-	auto triangleIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3, vkcv::BufferMemoryType::DEVICE_LOCAL);
+	auto triangleIndexBuffer = vkcv::buffer<uint16_t>(core, vkcv::BufferType::INDEX, 3);
 	uint16_t indices[3] = { 0, 1, 2 };
 	triangleIndexBuffer.fill(&indices[0], sizeof(indices));
 
diff --git a/projects/head_demo/src/main.cpp b/projects/head_demo/src/main.cpp
index 89fb5e08d1c4a5ceec8c43f3c4043f8978d5d404..a159684f2d7972fd6c609a6f66083ef7ed1250e5 100644
--- a/projects/head_demo/src/main.cpp
+++ b/projects/head_demo/src/main.cpp
@@ -1,4 +1,5 @@
 #include <iostream>
+#include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
@@ -118,7 +119,7 @@ int main(int argc, const char** argv) {
 	float clipY = 0.0f;
 	float clipZ = 0.0f;
 	
-	auto clipBuffer = core.createBuffer<float>(vkcv::BufferType::UNIFORM, 4);
+	auto clipBuffer = vkcv::buffer<float>(core, vkcv::BufferType::UNIFORM, 4);
 	clipBuffer.fill({ clipLimit, -clipX, -clipY, -clipZ });
 	
 	vkcv::DescriptorWrites clipWrites;
diff --git a/projects/indirect_dispatch/src/AppSetup.cpp b/projects/indirect_dispatch/src/AppSetup.cpp
index 933f20db73313e25bc9e4863f2bf4530df26a366..d428a327125d24fe691b71023d43af588e57b795 100644
--- a/projects/indirect_dispatch/src/AppSetup.cpp
+++ b/projects/indirect_dispatch/src/AppSetup.cpp
@@ -1,5 +1,6 @@
 #include "AppSetup.hpp"
 #include "AppConfig.hpp"
+#include <vkcv/Buffer.hpp>
 #include <vkcv/asset/asset_loader.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
 
@@ -23,12 +24,14 @@ bool loadMesh(vkcv::Core& core, const std::filesystem::path& path, MeshResources
 	auto& vertexData = scene.vertexGroups[0].vertexBuffer;
 	auto& indexData  = scene.vertexGroups[0].indexBuffer;
 
-	vkcv::Buffer vertexBuffer = core.createBuffer<uint8_t>(
+	vkcv::Buffer<uint8_t> vertexBuffer = vkcv::buffer<uint8_t>(
+		core,
 		vkcv::BufferType::VERTEX,
 		vertexData.data.size(),
 		vkcv::BufferMemoryType::DEVICE_LOCAL);
 
-	vkcv::Buffer indexBuffer = core.createBuffer<uint8_t>(
+	vkcv::Buffer<uint8_t> indexBuffer = vkcv::buffer<uint8_t>(
+		core,
 		vkcv::BufferType::INDEX,
 		indexData.data.size(),
 		vkcv::BufferMemoryType::DEVICE_LOCAL);
diff --git a/projects/indirect_dispatch/src/MotionBlur.cpp b/projects/indirect_dispatch/src/MotionBlur.cpp
index 7f3e8ae8a5deeb55539762554f7b4736331ae499..df5399efdc39f2c1a81a965c25699f962dc53d31 100644
--- a/projects/indirect_dispatch/src/MotionBlur.cpp
+++ b/projects/indirect_dispatch/src/MotionBlur.cpp
@@ -2,6 +2,7 @@
 #include "MotionBlurConfig.hpp"
 #include "MotionBlurSetup.hpp"
 #include <array>
+#include <vkcv/Buffer.hpp>
 
 std::array<uint32_t, 3> computeFullscreenDispatchSize(
 	const uint32_t imageWidth,
@@ -56,23 +57,23 @@ bool MotionBlur::initialize(vkcv::Core* corePtr, const uint32_t targetWidth, con
 		((MotionBlurConfig::maxWidth + MotionBlurConfig::maxMotionTileSize - 1) / MotionBlurConfig::maxMotionTileSize) *
 		((MotionBlurConfig::maxHeight + MotionBlurConfig::maxMotionTileSize - 1) / MotionBlurConfig::maxMotionTileSize));
 
-	m_copyPathWorkTileBuffer = m_core->createBuffer<uint32_t>(
-		vkcv::BufferType::STORAGE, 
+	m_copyPathWorkTileBuffer = vkcv::buffer<uint32_t>(
+		*m_core,
+		vkcv::BufferType::INDIRECT,
 		workTileBufferSize, 
-		vkcv::BufferMemoryType::DEVICE_LOCAL, 
-		true).getHandle();
+		vkcv::BufferMemoryType::DEVICE_LOCAL).getHandle();
 
-	m_fullPathWorkTileBuffer = m_core->createBuffer<uint32_t>(
-		vkcv::BufferType::STORAGE, 
+	m_fullPathWorkTileBuffer = vkcv::buffer<uint32_t>(
+		*m_core,
+		vkcv::BufferType::INDIRECT,
 		workTileBufferSize, 
-		vkcv::BufferMemoryType::DEVICE_LOCAL, 
-		true).getHandle();
+		vkcv::BufferMemoryType::DEVICE_LOCAL).getHandle();
 
-	m_fastPathWorkTileBuffer = m_core->createBuffer<uint32_t>(
-		vkcv::BufferType::STORAGE,
+	m_fastPathWorkTileBuffer = vkcv::buffer<uint32_t>(
+		*m_core,
+		vkcv::BufferType::INDIRECT,
 		workTileBufferSize,
-		vkcv::BufferMemoryType::DEVICE_LOCAL,
-		true).getHandle();
+		vkcv::BufferMemoryType::DEVICE_LOCAL).getHandle();
 
 	vkcv::DescriptorWrites tileResetDescriptorWrites;
 	tileResetDescriptorWrites.writeStorageBuffer(
diff --git a/projects/indirect_draw/src/main.cpp b/projects/indirect_draw/src/main.cpp
index e9d50c468ad33746b57400edaeb0c36f9d6b38e2..d9990a28c88cb75063b9f4d310322a2f4102c70c 100644
--- a/projects/indirect_draw/src/main.cpp
+++ b/projects/indirect_draw/src/main.cpp
@@ -1,4 +1,5 @@
 #include <iostream>
+#include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
 #include <vkcv/camera/CameraManager.hpp>
 #include <chrono>
@@ -393,26 +394,29 @@ int main(int argc, const char** argv) {
         compiledInterleavedVertexBuffer.insert(compiledInterleavedVertexBuffer.end(),vertexGroup.begin(),vertexGroup.end());
 	}
 
-	auto vkCompiledVertexBuffer = core.createBuffer<Vertex>(
+	auto vkCompiledVertexBuffer = vkcv::buffer<Vertex>(
+			core,
 			vkcv::BufferType::VERTEX,
             compiledInterleavedVertexBuffer.size(),
-			vkcv::BufferMemoryType::DEVICE_LOCAL
-			);
+			vkcv::BufferMemoryType::DEVICE_LOCAL);
     vkCompiledVertexBuffer.fill(compiledInterleavedVertexBuffer.data());
 
-    auto vkCompiledIndexBuffer = core.createBuffer<uint8_t>(
+    auto vkCompiledIndexBuffer = vkcv::buffer<uint8_t>(
+			core,
             vkcv::BufferType::INDEX,
             compiledIndexBuffer.size(),
             vkcv::BufferMemoryType::DEVICE_LOCAL);
     vkCompiledIndexBuffer.fill(compiledIndexBuffer.data());
 
-    vkcv::Buffer<vk::DrawIndexedIndirectCommand> indirectBuffer = core.createBuffer<vk::DrawIndexedIndirectCommand>(
+    vkcv::Buffer<vk::DrawIndexedIndirectCommand> indirectBuffer = vkcv::buffer<vk::DrawIndexedIndirectCommand>(
+			core,
             vkcv::BufferType::INDIRECT,
             indexedIndirectCommands.size(),
             vkcv::BufferMemoryType::DEVICE_LOCAL);
     indirectBuffer.fill(indexedIndirectCommands);
 
-    auto boundingBoxBuffer = core.createBuffer<glm::vec4>(
+    auto boundingBoxBuffer = vkcv::buffer<glm::vec4>(
+			core,
             vkcv::BufferType::STORAGE,
             compiledBoundingBoxBuffer.size());
     boundingBoxBuffer.fill(compiledBoundingBoxBuffer);
@@ -422,7 +426,8 @@ int main(int argc, const char** argv) {
 	{
 		modelMatrix.push_back(glm::make_mat4(mesh.modelMatrix.data()));
 	}
-	vkcv::Buffer<glm::mat4> modelBuffer = core.createBuffer<glm::mat4>(
+	vkcv::Buffer<glm::mat4> modelBuffer = vkcv::buffer<glm::mat4>(
+			core,
 			vkcv::BufferType::STORAGE,
 			modelMatrix.size(),
 			vkcv::BufferMemoryType::DEVICE_LOCAL
@@ -481,7 +486,8 @@ int main(int argc, const char** argv) {
     vkcv::DescriptorSetLayoutHandle cullingSetLayout = core.createDescriptorSetLayout(cullingBindings);
     vkcv::DescriptorSetHandle cullingDescSet = core.createDescriptorSet(cullingSetLayout);
 
-    vkcv::Buffer<CameraPlanes> cameraPlaneBuffer = core.createBuffer<CameraPlanes>(
+    vkcv::Buffer<CameraPlanes> cameraPlaneBuffer = vkcv::buffer<CameraPlanes>(
+			core,
             vkcv::BufferType::UNIFORM,
             1);
 
@@ -575,7 +581,7 @@ int main(int argc, const char** argv) {
             descriptorSet,
             compiledMesh,
 			renderTargets,
-			indirectBuffer,
+			indirectBuffer.getHandle(),
             indexedIndirectCommands.size(),
 			windowHandle);
 
diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp
index 56a8d827e25c15508717bc8d0dd685156969ed54..5b727a19e689092687e38bad07e13dee6a04872f 100644
--- a/projects/mesh_shader/src/main.cpp
+++ b/projects/mesh_shader/src/main.cpp
@@ -1,4 +1,5 @@
 #include <iostream>
+#include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
@@ -103,14 +104,16 @@ int main(int argc, const char** argv) {
 
     assert(!mesh.vertexGroups.empty());
 
-    auto vertexBuffer = core.createBuffer<uint8_t>(
+    auto vertexBuffer = vkcv::buffer<uint8_t>(
+			core,
             vkcv::BufferType::VERTEX,
             mesh.vertexGroups[0].vertexBuffer.data.size(),
             vkcv::BufferMemoryType::DEVICE_LOCAL
     );
     vertexBuffer.fill(mesh.vertexGroups[0].vertexBuffer.data);
 
-    auto indexBuffer = core.createBuffer<uint8_t>(
+    auto indexBuffer = vkcv::buffer<uint8_t>(
+			core,
             vkcv::BufferType::INDEX,
             mesh.vertexGroups[0].indexBuffer.data.size(),
             vkcv::BufferMemoryType::DEVICE_LOCAL
@@ -139,17 +142,20 @@ int main(int argc, const char** argv) {
 
     const auto meshShaderModelData = createMeshShaderModelData(interleavedVertices, forsythResult.indexBuffer, forsythResult.skippedIndices);
 
-	auto meshShaderVertexBuffer = core.createBuffer<vkcv::meshlet::Vertex>(
+	auto meshShaderVertexBuffer = vkcv::buffer<vkcv::meshlet::Vertex>(
+		core,
 		vkcv::BufferType::STORAGE,
 		meshShaderModelData.vertices.size());
 	meshShaderVertexBuffer.fill(meshShaderModelData.vertices);
 
-	auto meshShaderIndexBuffer = core.createBuffer<uint32_t>(
+	auto meshShaderIndexBuffer = vkcv::buffer<uint32_t>(
+		core,
 		vkcv::BufferType::STORAGE,
 		meshShaderModelData.localIndices.size());
 	meshShaderIndexBuffer.fill(meshShaderModelData.localIndices);
 
-	auto meshletBuffer = core.createBuffer<vkcv::meshlet::Meshlet>(
+	auto meshletBuffer = vkcv::buffer<vkcv::meshlet::Meshlet>(
+		core,
 		vkcv::BufferType::STORAGE,
 		meshShaderModelData.meshlets.size(),
 		vkcv::BufferMemoryType::DEVICE_LOCAL
@@ -219,7 +225,7 @@ int main(int argc, const char** argv) {
 		glm::mat4 mvp;
 	};
 	const size_t objectCount = 1;
-	vkcv::Buffer<ObjectMatrices> matrixBuffer = core.createBuffer<ObjectMatrices>(vkcv::BufferType::STORAGE, objectCount);
+	vkcv::Buffer<ObjectMatrices> matrixBuffer = vkcv::buffer<ObjectMatrices>(core, vkcv::BufferType::STORAGE, objectCount);
 
 	vkcv::DescriptorWrites vertexShaderDescriptorWrites;
 	vertexShaderDescriptorWrites.writeStorageBuffer(0, matrixBuffer.getHandle());
@@ -272,7 +278,7 @@ int main(int argc, const char** argv) {
 		return EXIT_FAILURE;
 	}
 
-	vkcv::Buffer<CameraPlanes> cameraPlaneBuffer = core.createBuffer<CameraPlanes>(vkcv::BufferType::UNIFORM, 1);
+	vkcv::Buffer<CameraPlanes> cameraPlaneBuffer = vkcv::buffer<CameraPlanes>(core, vkcv::BufferType::UNIFORM, 1);
 
 	vkcv::DescriptorWrites meshShaderWrites;
 	meshShaderWrites.writeStorageBuffer(
diff --git a/projects/particle_simulation/src/main.cpp b/projects/particle_simulation/src/main.cpp
index f13fb8e07addd1c5b6090adb8d43257d47039bc3..50963769b7d87e71e4e4fcdffb61281b5feff220 100644
--- a/projects/particle_simulation/src/main.cpp
+++ b/projects/particle_simulation/src/main.cpp
@@ -1,4 +1,5 @@
 #include <iostream>
+#include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
@@ -26,8 +27,8 @@ int main(int argc, const char **argv) {
     vkcv::Window& window = core.getWindow(windowHandle);
 	vkcv::camera::CameraManager cameraManager(window);
 
-    auto particleIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3,
-                                                           vkcv::BufferMemoryType::DEVICE_LOCAL);
+    auto particleIndexBuffer = vkcv::buffer<uint16_t>(core, vkcv::BufferType::INDEX, 3,
+													  vkcv::BufferMemoryType::DEVICE_LOCAL);
     uint16_t indices[3] = {0, 1, 2};
     particleIndexBuffer.fill(&indices[0], sizeof(indices));
 
@@ -99,7 +100,8 @@ int main(int argc, const char **argv) {
             particleShaderProgram.getReflectedDescriptors().at(0));
     vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorSetLayout);
 
-    vkcv::Buffer<glm::vec3> vertexBuffer = core.createBuffer<glm::vec3>(
+    vkcv::Buffer<glm::vec3> vertexBuffer = vkcv::buffer<glm::vec3>(
+			core,
             vkcv::BufferType::VERTEX,
             3
     );
@@ -138,12 +140,14 @@ int main(int argc, const char **argv) {
 		computeShaderProgram, {computeDescriptorSetLayout}
 	});
 
-    vkcv::Buffer<glm::vec4> color = core.createBuffer<glm::vec4>(
+    vkcv::Buffer<glm::vec4> color = vkcv::buffer<glm::vec4>(
+			core,
             vkcv::BufferType::UNIFORM,
             1
     );
 
-    vkcv::Buffer<glm::vec2> position = core.createBuffer<glm::vec2>(
+    vkcv::Buffer<glm::vec2> position = vkcv::buffer<glm::vec2>(
+			core,
             vkcv::BufferType::UNIFORM,
             1
     );
@@ -153,7 +157,8 @@ int main(int argc, const char **argv) {
     glm::vec2 lifeTime = glm::vec2(-1.f,8.f);
     ParticleSystem particleSystem = ParticleSystem( 100000 , minVelocity, maxVelocity, lifeTime);
 
-    vkcv::Buffer<Particle> particleBuffer = core.createBuffer<Particle>(
+    vkcv::Buffer<Particle> particleBuffer = vkcv::buffer<Particle>(
+			core,
             vkcv::BufferType::STORAGE,
             particleSystem.getParticles().size()
     );
diff --git a/projects/path_tracer/src/main.cpp b/projects/path_tracer/src/main.cpp
index 4eb3a6490cb61a791f56e280f4160193caa5e7c6..e7147e6b1367ba7b8a3dd7a1e39a26493fca0ba4 100644
--- a/projects/path_tracer/src/main.cpp
+++ b/projects/path_tracer/src/main.cpp
@@ -1,3 +1,4 @@
+#include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
 #include <vkcv/camera/CameraManager.hpp>
 #include <vkcv/asset/asset_loader.hpp>
@@ -174,17 +175,20 @@ int main(int argc, const char** argv) {
 	planes.emplace_back(Plane(glm::vec3( 0,  0,     2), glm::vec3( 0,  0, -1), glm::vec2(2), whiteMaterialIndex));
 	planes.emplace_back(Plane(glm::vec3( 0,  1.9,   0), glm::vec3( 0, -1,  0), glm::vec2(1), lightMaterialIndex));
 
-	vkcv::Buffer<Sphere> sphereBuffer = core.createBuffer<Sphere>(
+	vkcv::Buffer<Sphere> sphereBuffer = vkcv::buffer<Sphere>(
+		core,
 		vkcv::BufferType::STORAGE,
 		spheres.size());
 	sphereBuffer.fill(spheres);
 
-	vkcv::Buffer<Plane> planeBuffer = core.createBuffer<Plane>(
+	vkcv::Buffer<Plane> planeBuffer = vkcv::buffer<Plane>(
+		core,
 		vkcv::BufferType::STORAGE,
 		planes.size());
 	planeBuffer.fill(planes);
 
-	vkcv::Buffer<Material> materialBuffer = core.createBuffer<Material>(
+	vkcv::Buffer<Material> materialBuffer = vkcv::buffer<Material>(
+		core,
 		vkcv::BufferType::STORAGE,
 		materialSettings.size());
 
diff --git a/projects/saf_r/src/main.cpp b/projects/saf_r/src/main.cpp
index b9b290e2d324a8d550a4ffc41e0afe344d90a7db..3e6d9e6c3db736d55e05e7993c9f94e946bab360 100644
--- a/projects/saf_r/src/main.cpp
+++ b/projects/saf_r/src/main.cpp
@@ -1,5 +1,6 @@
 #include <iostream>
 #include <vkcv/Core.hpp>
+#include <vkcv/Buffer.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
 #include <vkcv/asset/asset_loader.hpp>
@@ -132,13 +133,15 @@ int main(int argc, const char** argv) {
 
 	
 	//create Buffer for compute shader
-	vkcv::Buffer<safrScene::Light> lightsBuffer = core.createBuffer<safrScene::Light>(
+	vkcv::Buffer<safrScene::Light> lightsBuffer = vkcv::buffer<safrScene::Light>(
+		core,
 		vkcv::BufferType::STORAGE,
 		lights.size()
 	);
 	lightsBuffer.fill(lights);
 
-	vkcv::Buffer<safrScene::Sphere> sphereBuffer = core.createBuffer<safrScene::Sphere>(
+	vkcv::Buffer<safrScene::Sphere> sphereBuffer = vkcv::buffer<safrScene::Sphere>(
+		core,
 		vkcv::BufferType::STORAGE,
 		spheres.size()
 	);
@@ -153,7 +156,7 @@ int main(int argc, const char** argv) {
 	
     core.writeDescriptorSet(computeDescriptorSet, computeWrites);
 
-	auto safrIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3, vkcv::BufferMemoryType::DEVICE_LOCAL);
+	auto safrIndexBuffer = vkcv::buffer<uint16_t>(core, vkcv::BufferType::INDEX, 3);
 	uint16_t indices[3] = { 0, 1, 2 };
 	safrIndexBuffer.fill(&indices[0], sizeof(indices));
 
diff --git a/projects/sph/src/main.cpp b/projects/sph/src/main.cpp
index 601075421a7bf2814e10514ae010fc83b7024f0a..8b4be7475ea29f38f02871ddf306a5593ae7197f 100644
--- a/projects/sph/src/main.cpp
+++ b/projects/sph/src/main.cpp
@@ -1,5 +1,6 @@
 #include <iostream>
 #include <vkcv/Core.hpp>
+#include <vkcv/Buffer.hpp>
 #include <vkcv/camera/CameraManager.hpp>
 #include <chrono>
 #include <random>
@@ -25,8 +26,7 @@ int main(int argc, const char **argv) {
 
     vkcv::camera::CameraManager cameraManager(window);
 
-    auto particleIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3,
-                                                           vkcv::BufferMemoryType::DEVICE_LOCAL);
+    auto particleIndexBuffer = vkcv::buffer<uint16_t>(core, vkcv::BufferType::INDEX, 3);
     uint16_t indices[3] = {0, 1, 2};
     particleIndexBuffer.fill(&indices[0], sizeof(indices));
 
@@ -98,7 +98,8 @@ int main(int argc, const char **argv) {
             particleShaderProgram.getReflectedDescriptors().at(0));
     vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorSetLayout);
 
-    vkcv::Buffer<glm::vec3> vertexBuffer = core.createBuffer<glm::vec3>(
+    vkcv::Buffer<glm::vec3> vertexBuffer = vkcv::buffer<glm::vec3>(
+			core,
             vkcv::BufferType::VERTEX,
             3
     );
@@ -134,12 +135,14 @@ int main(int argc, const char **argv) {
 
     vkcv::GraphicsPipelineHandle particlePipeline = core.createGraphicsPipeline(particlePipelineDefinition);
 
-    vkcv::Buffer<glm::vec4> color = core.createBuffer<glm::vec4>(
+    vkcv::Buffer<glm::vec4> color = vkcv::buffer<glm::vec4>(
+			core,
             vkcv::BufferType::UNIFORM,
             1
     );
 
-    vkcv::Buffer<glm::vec2> position = core.createBuffer<glm::vec2>(
+    vkcv::Buffer<glm::vec2> position = vkcv::buffer<glm::vec2>(
+			core,
             vkcv::BufferType::UNIFORM,
             1
     );
@@ -165,15 +168,16 @@ int main(int argc, const char **argv) {
     }
 
     // creating and filling particle buffer
-    vkcv::Buffer<Particle> particleBuffer1 = core.createBuffer<Particle>(
+    vkcv::Buffer<Particle> particleBuffer1 = vkcv::buffer<Particle>(
+			core,
             vkcv::BufferType::STORAGE,
-            numberParticles * sizeof(glm::vec4) * 3
-
+            numberParticles
     );
 
-    vkcv::Buffer<Particle> particleBuffer2 = core.createBuffer<Particle>(
-        vkcv::BufferType::STORAGE,
-        numberParticles * sizeof(glm::vec4) * 3
+    vkcv::Buffer<Particle> particleBuffer2 = vkcv::buffer<Particle>(
+			core,
+			vkcv::BufferType::STORAGE,
+			numberParticles
     );
 
     particleBuffer1.fill(particles);
diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp
index 8b8fd8bd87f5349372233111c06917075406ffb7..eb463944877803aef13b92aeb9be3ef88cb2bb22 100644
--- a/projects/voxelization/src/ShadowMapping.cpp
+++ b/projects/voxelization/src/ShadowMapping.cpp
@@ -154,7 +154,7 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert
 	m_shadowMap(corePtr->createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1, true, true)),
 	m_shadowMapIntermediate(corePtr->createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1, false, true)),
 	m_shadowMapDepth(corePtr->createImage(shadowMapDepthFormat, shadowMapResolution, shadowMapResolution, 1, false, false, false, msaa)),
-	m_lightInfoBuffer(corePtr->createBuffer<LightInfo>(vkcv::BufferType::UNIFORM, sizeof(glm::vec3))){
+	m_lightInfoBuffer(buffer<LightInfo>(*corePtr, vkcv::BufferType::UNIFORM, 1)){
 
 	vkcv::ShaderProgram shadowShader = loadShadowShader();
 
diff --git a/projects/voxelization/src/ShadowMapping.hpp b/projects/voxelization/src/ShadowMapping.hpp
index 14fef77df51632977f4c4eade4ebcdc28ba56b68..4901d6ec470893d83ec978d00a78b9fba90a9fbc 100644
--- a/projects/voxelization/src/ShadowMapping.hpp
+++ b/projects/voxelization/src/ShadowMapping.hpp
@@ -1,4 +1,6 @@
 #pragma once
+
+#include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
 #include <vkcv/camera/Camera.hpp>
 #include <vkcv/Downsampler.hpp>
diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp
index 99e82ce7520fb54b3bbfcc625467261bef1bf741..049bdb1d28855fc3fe9a83d5fd176818bdf06678 100644
--- a/projects/voxelization/src/Voxelization.cpp
+++ b/projects/voxelization/src/Voxelization.cpp
@@ -86,9 +86,9 @@ Voxelization::Voxelization(
 	m_corePtr(corePtr),
 	m_voxelImageIntermediate(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, true, true)),
 	m_voxelImage(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, true, true)),
-	m_voxelBuffer(m_corePtr->createBuffer<VoxelBufferContent>(vkcv::BufferType::STORAGE, voxelCount)),
+	m_voxelBuffer(buffer<VoxelBufferContent>(*m_corePtr, vkcv::BufferType::STORAGE, voxelCount)),
 	m_dummyRenderTarget(m_corePtr->createImage(voxelizationDummyFormat, voxelResolution, voxelResolution, 1, false, false, true)),
-	m_voxelInfoBuffer(m_corePtr->createBuffer<VoxelizationInfo>(vkcv::BufferType::UNIFORM, 1)) {
+	m_voxelInfoBuffer(buffer<VoxelizationInfo>(*m_corePtr, vkcv::BufferType::UNIFORM, 1)) {
 
 	const vkcv::ShaderProgram voxelizationShader = loadVoxelizationShader();
 
diff --git a/projects/voxelization/src/Voxelization.hpp b/projects/voxelization/src/Voxelization.hpp
index 866efaf47354bc0a53ebd500d06dc4a49b0ed690..de710b64502fe240e455b8d588cccd18872003da 100644
--- a/projects/voxelization/src/Voxelization.hpp
+++ b/projects/voxelization/src/Voxelization.hpp
@@ -1,4 +1,6 @@
 #pragma once
+
+#include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
 #include <glm/glm.hpp>
 #include <vkcv/camera/Camera.hpp>
diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp
index b2101b1dc436d66c441c0a453a7498577578c9d3..55e3b38af19550c5cdbd8ed836ce98f49f85534e 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -153,7 +153,8 @@ int main(int argc, const char** argv) {
 
 	std::vector<vkcv::Buffer<uint8_t>> vertexBuffers;
 	for (const vkcv::asset::VertexGroup& group : scene.vertexGroups) {
-		vertexBuffers.push_back(core.createBuffer<uint8_t>(
+		vertexBuffers.push_back(buffer<uint8_t>(
+			core,
 			vkcv::BufferType::VERTEX,
 			group.vertexBuffer.data.size()));
 		vertexBuffers.back().fill(group.vertexBuffer.data);
@@ -161,7 +162,8 @@ int main(int argc, const char** argv) {
 
 	std::vector<vkcv::Buffer<uint8_t>> indexBuffers;
 	for (const auto& dataBuffer : iBuffers) {
-		indexBuffers.push_back(core.createBuffer<uint8_t>(
+		indexBuffers.push_back(buffer<uint8_t>(
+			core,
 			vkcv::BufferType::INDEX,
 			dataBuffer.size()));
 		indexBuffers.back().fill(dataBuffer);
@@ -579,7 +581,7 @@ int main(int argc, const char** argv) {
 		msaa);
 
 	vkcv::effects::BloomAndFlaresEffect bloomFlares (core, true);
-	vkcv::Buffer<glm::vec3> cameraPosBuffer = core.createBuffer<glm::vec3>(vkcv::BufferType::UNIFORM, 1);
+	vkcv::Buffer<glm::vec3> cameraPosBuffer = buffer<glm::vec3>(core, vkcv::BufferType::UNIFORM, 1);
 
 	struct VolumetricSettings {
 		glm::vec3   scatteringCoefficient;
@@ -587,7 +589,7 @@ int main(int argc, const char** argv) {
 		glm::vec3   absorptionCoefficient;
 	};
 	vkcv::Buffer<VolumetricSettings> volumetricSettingsBuffer
-		= core.createBuffer<VolumetricSettings>(vkcv::BufferType::UNIFORM ,1);
+		= buffer<VolumetricSettings>(core, vkcv::BufferType::UNIFORM ,1);
 
 	// write forward pass descriptor set
 	vkcv::DescriptorWrites forwardDescriptorWrites;
diff --git a/projects/wobble_bobble/src/main.cpp b/projects/wobble_bobble/src/main.cpp
index 4cbca35f10ed9f88f25051bb7bc9b8e4d71c235b..079eb9390f007ba1ec8a5b06cef2c957efe2ec91 100644
--- a/projects/wobble_bobble/src/main.cpp
+++ b/projects/wobble_bobble/src/main.cpp
@@ -1,4 +1,5 @@
 
+#include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
 #include <vkcv/camera/CameraManager.hpp>
 #include <vkcv/gui/GUI.hpp>
@@ -238,7 +239,8 @@ vkcv::ComputePipelineHandle createComputePipeline(vkcv::Core& core, vkcv::shader
 
 vkcv::BufferHandle resetParticles(vkcv::Core& core, size_t count, const glm::vec3& velocity,
 					float density, float size, int form, int mode) {
-	vkcv::Buffer<Particle> particles = core.createBuffer<Particle>(
+	vkcv::Buffer<Particle> particles = vkcv::buffer<Particle>(
+			core,
 			vkcv::BufferType::STORAGE,
 			count
 	);
@@ -327,8 +329,8 @@ int main(int argc, const char **argv) {
 			vkcv::SamplerBorderColor::FLOAT_ZERO_TRANSPARENT
 	);
 	
-	vkcv::Buffer<Simulation> simulation = core.createBuffer<Simulation>(
-			vkcv::BufferType::UNIFORM, 1, vkcv::BufferMemoryType::HOST_VISIBLE
+	vkcv::Buffer<Simulation> simulation = vkcv::buffer<Simulation>(
+			core, vkcv::BufferType::UNIFORM, 1, vkcv::BufferMemoryType::HOST_VISIBLE
 	);
 	
 	Simulation* sim = simulation.map();
@@ -565,14 +567,14 @@ int main(int argc, const char **argv) {
 	vkcv::GraphicsPipelineHandle gfxPipelineParticles = core.createGraphicsPipeline(gfxPipelineConfigParticles);
 	vkcv::GraphicsPipelineHandle gfxPipelineLines = core.createGraphicsPipeline(gfxPipelineConfigLines);
 	
-	vkcv::Buffer<glm::vec2> trianglePositions = core.createBuffer<glm::vec2>(vkcv::BufferType::VERTEX, 3);
+	vkcv::Buffer<glm::vec2> trianglePositions = vkcv::buffer<glm::vec2>(core, vkcv::BufferType::VERTEX, 3);
 	trianglePositions.fill({
 		glm::vec2(-1.0f, -1.0f),
 		glm::vec2(+0.0f, +1.5f),
 		glm::vec2(+1.0f, -1.0f)
 	});
 	
-	vkcv::Buffer<uint16_t> triangleIndices = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3);
+	vkcv::Buffer<uint16_t> triangleIndices = vkcv::buffer<uint16_t>(core, vkcv::BufferType::INDEX, 3);
 	triangleIndices.fill({
 		0, 1, 2
 	});
@@ -583,7 +585,7 @@ int main(int argc, const char **argv) {
 			triangleIndices.getCount()
 	);
 	
-	vkcv::Buffer<glm::vec3> linesPositions = core.createBuffer<glm::vec3>(vkcv::BufferType::VERTEX, 8);
+	vkcv::Buffer<glm::vec3> linesPositions = vkcv::buffer<glm::vec3>(core, vkcv::BufferType::VERTEX, 8);
 	linesPositions.fill({
 		glm::vec3(0.0f, 0.0f, 0.0f),
 		glm::vec3(1.0f, 0.0f, 0.0f),
@@ -595,7 +597,7 @@ int main(int argc, const char **argv) {
 		glm::vec3(1.0f, 1.0f, 1.0f)
 	});
 	
-	vkcv::Buffer<uint16_t> linesIndices = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 24);
+	vkcv::Buffer<uint16_t> linesIndices = vkcv::buffer<uint16_t>(core, vkcv::BufferType::INDEX, 24);
 	linesIndices.fill({
 		0, 1,
 		1, 3,
diff --git a/src/vkcv/BufferManager.cpp b/src/vkcv/BufferManager.cpp
index e1b1a5097be2bd088d1ec1bd39b78695331899f3..3e245cb7b980ddca03de08073fac2bd15a43dfb8 100644
--- a/src/vkcv/BufferManager.cpp
+++ b/src/vkcv/BufferManager.cpp
@@ -3,7 +3,7 @@
  * @file vkcv/BufferManager.cpp
  */
 
-#include "vkcv/BufferManager.hpp"
+#include "BufferManager.hpp"
 #include "vkcv/Core.hpp"
 #include <vkcv/Logger.hpp>
 
@@ -20,10 +20,10 @@ namespace vkcv {
 		}
 		
 		m_stagingBuffer = createBuffer(
+				TypeGuard(1),
 				BufferType::STAGING,
-				1024 * 1024,
 				BufferMemoryType::HOST_VISIBLE,
-				false,
+				1024 * 1024,
 				false
 		);
 	}
@@ -34,10 +34,10 @@ namespace vkcv {
 		}
 	}
 	
-	BufferHandle BufferManager::createBuffer(BufferType type,
-											 size_t size,
+	BufferHandle BufferManager::createBuffer(const TypeGuard &typeGuard,
+											 BufferType type,
 											 BufferMemoryType memoryType,
-											 bool supportIndirect,
+											 size_t size,
 											 bool readable) {
 		vk::BufferCreateFlags createFlags;
 		vk::BufferUsageFlags usageFlags;
@@ -60,7 +60,8 @@ namespace vkcv {
 				usageFlags = vk::BufferUsageFlagBits::eIndexBuffer;
 				break;
             case BufferType::INDIRECT:
-                usageFlags = vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eIndirectBuffer ;
+                usageFlags = vk::BufferUsageFlagBits::eStorageBuffer |
+							 vk::BufferUsageFlagBits::eIndirectBuffer ;
                 break;
 			default:
 				vkcv_log(LogLevel::WARNING, "Unknown buffer type");
@@ -71,10 +72,6 @@ namespace vkcv {
 			usageFlags |= vk::BufferUsageFlagBits::eTransferDst;
 		}
 		
-		if (supportIndirect) {
-			usageFlags |= vk::BufferUsageFlagBits::eIndirectBuffer;
-		}
-		
 		if (readable) {
 			usageFlags |= vk::BufferUsageFlagBits::eTransferSrc;
 		}
@@ -124,7 +121,16 @@ namespace vkcv {
 		vma::Allocation allocation = bufferAllocation.second;
 		
 		const uint64_t id = m_buffers.size();
-		m_buffers.push_back({ buffer, allocation, size, mappable });
+		m_buffers.push_back({
+			typeGuard,
+			type,
+			memoryType,
+			size,
+			buffer,
+			allocation,
+			mappable
+		});
+		
 		return BufferHandle(id, [&](uint64_t id) { destroyBufferById(id); });
 	}
 	
@@ -266,6 +272,42 @@ namespace vkcv {
 		return buffer.m_handle;
 	}
 	
+	TypeGuard BufferManager::getTypeGuard(const BufferHandle &handle) const {
+		const uint64_t id = handle.getId();
+		
+		if (id >= m_buffers.size()) {
+			return TypeGuard(0);
+		}
+		
+		auto& buffer = m_buffers[id];
+		
+		return buffer.m_typeGuard;
+	}
+	
+	BufferType BufferManager::getBufferType(const BufferHandle &handle) const {
+		const uint64_t id = handle.getId();
+		
+		if (id >= m_buffers.size()) {
+			return BufferType::UNKNOWN;
+		}
+		
+		auto& buffer = m_buffers[id];
+		
+		return buffer.m_type;
+	}
+	
+	BufferMemoryType BufferManager::getBufferMemoryType(const BufferHandle &handle) const {
+		const uint64_t id = handle.getId();
+		
+		if (id >= m_buffers.size()) {
+			return BufferMemoryType::UNKNOWN;
+		}
+		
+		auto& buffer = m_buffers[id];
+		
+		return buffer.m_memoryType;
+	}
+	
 	size_t BufferManager::getBufferSize(const BufferHandle &handle) const {
 		const uint64_t id = handle.getId();
 		
diff --git a/include/vkcv/BufferManager.hpp b/src/vkcv/BufferManager.hpp
similarity index 77%
rename from include/vkcv/BufferManager.hpp
rename to src/vkcv/BufferManager.hpp
index 8da11cfea885471f490836bf24c8b5169d1ce401..dd9b07e3b7abd6c7533c57bd77fe9e590fd28c40 100644
--- a/include/vkcv/BufferManager.hpp
+++ b/src/vkcv/BufferManager.hpp
@@ -9,30 +9,11 @@
 #include <vulkan/vulkan.hpp>
 #include <vk_mem_alloc.hpp>
 
-#include "Handles.hpp"
+#include "vkcv/BufferTypes.hpp"
+#include "vkcv/Handles.hpp"
+#include "vkcv/TypeGuard.hpp"
 
-namespace vkcv
-{
-	
-	/**
-	 * @brief Enum class to specify types of buffers.
-	 */
-	enum class BufferType {
-		INDEX,
-		VERTEX,
-		UNIFORM,
-		STORAGE,
-		STAGING,
-		INDIRECT
-	};
-	
-	/**
-	 * @brief Enum class to specify types of buffer memory.
-	 */
-	enum class BufferMemoryType {
-		DEVICE_LOCAL,
-		HOST_VISIBLE
-	};
+namespace vkcv {
 	
 	class Core;
 	
@@ -45,12 +26,17 @@ namespace vkcv
 		friend class Core;
 	private:
 		
-		struct Buffer
-		{
+		struct Buffer {
+			TypeGuard m_typeGuard;
+			
+			BufferType m_type;
+			BufferMemoryType m_memoryType;
+			size_t m_size;
+			
 			vk::Buffer m_handle;
 			vma::Allocation m_allocation;
-			size_t m_size = 0;
-			bool m_mappable = false;
+			
+			bool m_mappable;
 		};
 		
 		Core* m_core;
@@ -82,17 +68,18 @@ namespace vkcv
 		 * @brief Creates and allocates a new buffer and returns its
 		 * unique buffer handle.
 		 *
+		 * @param[in] typeGuard Type guard
 		 * @param[in] type Type of buffer
-		 * @param[in] size Size of buffer in bytes
 		 * @param[in] memoryType Type of buffers memory
+		 * @param[in] size Size of buffer in bytes
 		 * @param[in] supportIndirect Support of indirect usage
 		 * @param[in] readable Support read functionality
 		 * @return New buffer handle
 		 */
-		BufferHandle createBuffer(BufferType type,
-								  size_t size,
+		BufferHandle createBuffer(const TypeGuard &typeGuard,
+								  BufferType type,
 								  BufferMemoryType memoryType,
-								  bool supportIndirect,
+								  size_t size,
 								  bool readable);
 		
 		/**
@@ -105,6 +92,36 @@ namespace vkcv
 		[[nodiscard]]
 		vk::Buffer getBuffer(const BufferHandle& handle) const;
 		
+		/**
+		 * @brief Returns the type guard of a buffer represented
+		 * by a given buffer handle.
+		 *
+		 * @param[in] handle Buffer handle
+		 * @return Type guard
+		 */
+		[[nodiscard]]
+		TypeGuard getTypeGuard(const BufferHandle& handle) const;
+		
+		/**
+		 * @brief Returns the buffer type of a buffer represented
+		 * by a given buffer handle.
+		 *
+		 * @param[in] handle Buffer handle
+		 * @return Buffer type
+		 */
+		[[nodiscard]]
+		BufferType getBufferType(const BufferHandle& handle) const;
+		
+		/**
+		 * @brief Returns the buffer memory type of a buffer
+		 * represented by a given buffer handle.
+		 *
+		 * @param[in] handle Buffer handle
+		 * @return Buffer memory type
+		 */
+		[[nodiscard]]
+		BufferMemoryType getBufferMemoryType(const BufferHandle& handle) const;
+		
 		/**
 		 * @brief Returns the size of a buffer represented
 		 * by a given buffer handle.
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index 06942b87c072566120d4397f3d3be728770ae057..3716acb0e02a3c02ea0b994c40d4b81fae778a9c 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -10,7 +10,7 @@
 #include "PassManager.hpp"
 #include "GraphicsPipelineManager.hpp"
 #include "ComputePipelineManager.hpp"
-#include "vkcv/BufferManager.hpp"
+#include "BufferManager.hpp"
 #include "SamplerManager.hpp"
 #include "ImageManager.hpp"
 #include "DescriptorManager.hpp"
@@ -80,13 +80,11 @@ namespace vkcv
 		destroySyncResources(m_Context.getDevice(), m_SyncResources);
 	}
 	
-	GraphicsPipelineHandle Core::createGraphicsPipeline(const GraphicsPipelineConfig &config)
-    {
+	GraphicsPipelineHandle Core::createGraphicsPipeline(const GraphicsPipelineConfig &config) {
         return m_PipelineManager->createPipeline(config, *m_PassManager, *m_DescriptorManager);
     }
 
-    ComputePipelineHandle Core::createComputePipeline(const ComputePipelineConfig &config)
-    {
+    ComputePipelineHandle Core::createComputePipeline(const ComputePipelineConfig &config) {
 		std::vector<vk::DescriptorSetLayout> layouts;
 		layouts.resize(config.m_DescriptorSetLayouts.size());
 	
@@ -97,11 +95,69 @@ namespace vkcv
         return m_ComputePipelineManager->createComputePipeline(config.m_ShaderProgram, layouts);
     }
 
-    PassHandle Core::createPass(const PassConfig &config)
-    {
+    PassHandle Core::createPass(const PassConfig &config) {
         return m_PassManager->createPass(config);
     }
-
+	
+	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
+		);
+	}
+	
+	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) {
+		m_BufferManager->fillBuffer(handle, data, size, 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;
@@ -401,7 +457,7 @@ namespace vkcv
             const vkcv::DescriptorSetHandle                     &compiledDescriptorSet,
             const vkcv::Mesh                                    &compiledMesh,
             const std::vector<ImageHandle>                      &renderTargets,
-            const vkcv::Buffer<vk::DrawIndexedIndirectCommand>  &indirectBuffer,
+            const BufferHandle  								&indirectBuffer,
             const uint32_t                                      drawCount,
 			const WindowHandle                                  &windowHandle) {
 
@@ -475,7 +531,7 @@ namespace vkcv
             cmdBuffer.bindIndexBuffer(compiledMesh.indexBuffer, 0, getIndexType(compiledMesh.indexBitCount));
 
             cmdBuffer.drawIndexedIndirect(
-                    indirectBuffer.getVulkanHandle(),
+                    m_BufferManager->getBuffer(indirectBuffer),
                     0,
                     drawCount,
                     sizeof(vk::DrawIndexedIndirectCommand));
@@ -489,6 +545,46 @@ namespace vkcv
 
         recordCommandsToStream(cmdStreamHandle, submitFunction, finishFunction);
     }
+	
+	static void recordMeshShaderDrawcall(const Core& core,
+										 vk::CommandBuffer cmdBuffer,
+										 vk::PipelineLayout pipelineLayout,
+										 const PushConstants& pushConstantData,
+										 uint32_t pushConstantOffset,
+										 const MeshShaderDrawcall& drawcall,
+										 uint32_t firstTask) {
+		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.descriptorSets) {
+			cmdBuffer.bindDescriptorSets(
+					vk::PipelineBindPoint::eGraphics,
+					pipelineLayout,
+					descriptorUsage.setLocation,
+					core.getDescriptorSet(descriptorUsage.descriptorSet).vulkanHandle,
+					nullptr);
+		}
+		
+		// char* cast because void* does not support pointer arithmetic
+		const void* drawcallPushConstantData = pushConstantOffset + (char*)pushConstantData.getData();
+		
+		if (pushConstantData.getData()) {
+			cmdBuffer.pushConstants(
+					pipelineLayout,
+					vk::ShaderStageFlagBits::eAll,
+					0,
+					pushConstantData.getSizePerDrawcall(),
+					drawcallPushConstantData);
+		}
+		
+		cmdDrawMeshTasks(VkCommandBuffer(cmdBuffer), drawcall.taskCount, firstTask);
+	}
 
 	void Core::recordMeshShaderDrawcalls(
 		const CommandStreamHandle&                          cmdStreamHandle,
diff --git a/src/vkcv/DescriptorManager.hpp b/src/vkcv/DescriptorManager.hpp
index c996e8c94f6dbb6f45f173f60f59f344a9a58623..7b79e3327bf79a8e3afd6d77210dfb956851c06b 100644
--- a/src/vkcv/DescriptorManager.hpp
+++ b/src/vkcv/DescriptorManager.hpp
@@ -12,7 +12,7 @@
 #include "vkcv/DescriptorWrites.hpp"
 
 #include "ImageManager.hpp"
-#include "vkcv/BufferManager.hpp"
+#include "BufferManager.hpp"
 #include "SamplerManager.hpp"
 
 namespace vkcv
diff --git a/src/vkcv/DrawcallRecording.cpp b/src/vkcv/DrawcallRecording.cpp
deleted file mode 100644
index eef87ca65d5f461f1c37b678634cf3e6f8973397..0000000000000000000000000000000000000000
--- a/src/vkcv/DrawcallRecording.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-
-#include "vkcv/DrawcallRecording.hpp"
-#include "vkcv/Logger.hpp"
-#include "vkcv/Core.hpp"
-
-namespace vkcv {
-
-    void recordMeshShaderDrawcall(const Core& core,
-                                  vk::CommandBuffer cmdBuffer,
-                                  vk::PipelineLayout pipelineLayout,
-                                  const PushConstants& pushConstantData,
-                                  uint32_t pushConstantOffset,
-                                  const MeshShaderDrawcall& drawcall,
-                                  uint32_t firstTask) {
-        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.descriptorSets) {
-            cmdBuffer.bindDescriptorSets(
-                vk::PipelineBindPoint::eGraphics,
-                pipelineLayout,
-                descriptorUsage.setLocation,
-				core.getDescriptorSet(descriptorUsage.descriptorSet).vulkanHandle,
-                nullptr);
-        }
-
-        // char* cast because void* does not support pointer arithmetic
-        const void* drawcallPushConstantData = pushConstantOffset + (char*)pushConstantData.getData();
-
-        if (pushConstantData.getData()) {
-            cmdBuffer.pushConstants(
-                pipelineLayout,
-                vk::ShaderStageFlagBits::eAll,
-                0,
-                pushConstantData.getSizePerDrawcall(),
-                drawcallPushConstantData);
-        }
-    
-        cmdDrawMeshTasks(VkCommandBuffer(cmdBuffer), drawcall.taskCount, firstTask);
-    }
-}
diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp
index 585c1faf554060ccd0cdc2e6158ddffb2a11951e..b6d5a1f49fd6bbf57656d32318704b88b350d9f4 100644
--- a/src/vkcv/ImageManager.cpp
+++ b/src/vkcv/ImageManager.cpp
@@ -6,6 +6,7 @@
 #include "ImageManager.hpp"
 #include "vkcv/Core.hpp"
 #include "vkcv/Logger.hpp"
+#include "vkcv/TypeGuard.hpp"
 
 #include <algorithm>
 
@@ -512,10 +513,10 @@ namespace vkcv {
 		const size_t max_size = std::min(size, image_size);
 		
 		BufferHandle bufferHandle = m_bufferManager.createBuffer(
+				TypeGuard(1),
 				BufferType::STAGING,
-				max_size,
 				BufferMemoryType::DEVICE_LOCAL,
-				false,
+				max_size,
 				false
 		);
 		
diff --git a/src/vkcv/ImageManager.hpp b/src/vkcv/ImageManager.hpp
index 3e577fd9a61fea6334faaf136386bf845ca387e8..fca4f3b23944238f69da377090b2d3b34848b8af 100644
--- a/src/vkcv/ImageManager.hpp
+++ b/src/vkcv/ImageManager.hpp
@@ -8,7 +8,7 @@
 #include <vulkan/vulkan.hpp>
 #include <vk_mem_alloc.hpp>
 
-#include "vkcv/BufferManager.hpp"
+#include "BufferManager.hpp"
 #include "vkcv/Handles.hpp"
 #include "vkcv/ImageConfig.hpp"