From 1f83e7582852e7727e5e0af687918bfbd1c9503e Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Sun, 19 Mar 2023 16:35:45 +0100
Subject: [PATCH] Abstract container types inside of framework

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 .github/workflows/linux.yml                   |  2 +
 config/Sources.cmake                          |  4 +-
 include/vkcv/Buffer.hpp                       |  7 +--
 include/vkcv/Container.hpp                    | 23 +++++++
 include/vkcv/Context.hpp                      |  4 +-
 include/vkcv/Core.hpp                         | 31 +++++-----
 include/vkcv/DescriptorBinding.hpp            |  5 +-
 include/vkcv/DescriptorSetUsage.hpp           |  7 +--
 include/vkcv/DescriptorWrites.hpp             | 30 ++++-----
 include/vkcv/Drawcall.hpp                     |  9 ++-
 include/vkcv/Event.hpp                        |  4 +-
 include/vkcv/FeatureManager.hpp               | 11 ++--
 include/vkcv/Features.hpp                     |  6 +-
 include/vkcv/File.hpp                         | 11 ++--
 include/vkcv/GraphicsPipelineConfig.hpp       |  4 +-
 include/vkcv/Interpolation.hpp                |  5 +-
 include/vkcv/Pass.hpp                         |  5 +-
 include/vkcv/PassConfig.hpp                   |  4 +-
 include/vkcv/PipelineConfig.hpp               | 11 ++--
 include/vkcv/PushConstants.hpp                |  6 +-
 include/vkcv/QueueManager.hpp                 | 24 +++----
 include/vkcv/RayTracingPipelineConfig.hpp     |  5 +-
 include/vkcv/ShaderProgram.hpp                | 12 ++--
 include/vkcv/VertexData.hpp                   |  5 +-
 include/vkcv/VertexLayout.hpp                 |  7 ++-
 include/vkcv/Window.hpp                       |  3 +-
 .../src/vkcv/shader/Compiler.cpp              |  5 +-
 projects/bindless_textures/src/main.cpp       |  4 +-
 src/vkcv/AccelerationStructureManager.cpp     | 22 +++----
 src/vkcv/AccelerationStructureManager.hpp     |  8 +--
 src/vkcv/BufferManager.cpp                    |  2 +-
 src/vkcv/BufferManager.hpp                    |  2 +-
 src/vkcv/CommandStreamManager.cpp             |  6 +-
 src/vkcv/CommandStreamManager.hpp             |  8 +--
 src/vkcv/ComputePipelineManager.cpp           |  4 +-
 src/vkcv/ComputePipelineManager.hpp           |  4 +-
 src/vkcv/Context.cpp                          | 54 ++++++++--------
 src/vkcv/Core.cpp                             | 62 ++++++++++---------
 src/vkcv/DescriptorSetLayoutManager.cpp       |  4 +-
 src/vkcv/DescriptorSetManager.cpp             | 14 ++---
 src/vkcv/DescriptorSetManager.hpp             |  4 +-
 src/vkcv/DescriptorSetUsage.cpp               |  2 +-
 src/vkcv/DescriptorWrites.cpp                 | 14 ++---
 src/vkcv/Drawcall.cpp                         |  4 +-
 src/vkcv/FeatureManager.cpp                   |  2 +-
 src/vkcv/Features.cpp                         |  2 +-
 src/vkcv/File.cpp                             | 10 +--
 src/vkcv/GraphicsPipelineConfig.cpp           |  2 +-
 src/vkcv/GraphicsPipelineManager.cpp          | 24 +++----
 src/vkcv/GraphicsPipelineManager.hpp          |  6 +-
 src/vkcv/HandleManager.hpp                    |  4 +-
 src/vkcv/ImageManager.cpp                     | 10 +--
 src/vkcv/ImageManager.hpp                     | 16 ++---
 src/vkcv/Pass.cpp                             |  6 +-
 src/vkcv/PassManager.cpp                      |  8 +--
 src/vkcv/PassManager.hpp                      |  7 ++-
 src/vkcv/PipelineConfig.cpp                   |  6 +-
 src/vkcv/QueueManager.cpp                     | 32 +++++-----
 src/vkcv/RayTracingPipelineConfig.cpp         |  2 +-
 src/vkcv/RayTracingPipelineManager.cpp        | 12 ++--
 src/vkcv/RayTracingPipelineManager.hpp        |  6 +-
 src/vkcv/SamplerManager.hpp                   |  2 +-
 src/vkcv/ShaderProgram.cpp                    |  8 +--
 src/vkcv/SwapchainManager.cpp                 | 12 ++--
 src/vkcv/SwapchainManager.hpp                 | 10 +--
 src/vkcv/VertexData.cpp                       |  4 +-
 src/vkcv/Window.cpp                           |  8 +--
 src/vkcv/WindowManager.cpp                    |  4 +-
 src/vkcv/WindowManager.hpp                    |  8 +--
 69 files changed, 359 insertions(+), 320 deletions(-)
 create mode 100644 include/vkcv/Container.hpp

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 1c6db855..5585f795 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -13,6 +13,7 @@ jobs:
 
       - name: Initialize LFS
         run: |
+          sudo apt-get -qq install git-lfs
           git lfs install
 
       - name: Load submodules
@@ -23,6 +24,7 @@ jobs:
       - name: Install dependencies
         run: |
           sudo apt-get -qq update
+          sudo apt-get -qq install cmake g++
           sudo apt-get -qq install libvulkan-dev xorg-dev
 
       - name: Build framework
diff --git a/config/Sources.cmake b/config/Sources.cmake
index b693dea5..1770ef32 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -9,7 +9,9 @@ set(vkcv_sources
 		
 		${vkcv_include}/vkcv/Context.hpp
 		${vkcv_source}/vkcv/Context.cpp
-
+		
+		${vkcv_include}/vkcv/Container.hpp
+		
 		${vkcv_include}/vkcv/Core.hpp
 		${vkcv_source}/vkcv/Core.cpp
 		
diff --git a/include/vkcv/Buffer.hpp b/include/vkcv/Buffer.hpp
index a7dba97e..0fd085ec 100644
--- a/include/vkcv/Buffer.hpp
+++ b/include/vkcv/Buffer.hpp
@@ -5,9 +5,8 @@
  * @brief Template buffer class for type security with buffers.
  */
 
-#include <vector>
-
 #include "BufferTypes.hpp"
+#include "Container.hpp"
 #include "Core.hpp"
 #include "Handles.hpp"
 
@@ -112,7 +111,7 @@ namespace vkcv {
 		 * @param vector Vector of type T to be copied into the #Buffer
 		 * @param offset The offset into the #Buffer where the data is copied into
 		 */
-		void fill(const std::vector<T> &vector, size_t offset = 0) {
+		void fill(const Vector<T> &vector, size_t offset = 0) {
 			fill(static_cast<const T*>(vector.data()), static_cast<size_t>(vector.size()), offset);
 		}
 		
@@ -146,7 +145,7 @@ namespace vkcv {
 		 * @param vector Vector of type T to be copied into from the #Buffer
 		 * @param offset The offset into the #Buffer where the data is copied from
 		 */
-		void read(std::vector<T> &vector, size_t offset = 0) {
+		void read(Vector<T> &vector, size_t offset = 0) {
 			read(static_cast<T*>(vector.data()), static_cast<size_t>(vector.size()), offset);
 		}
 
diff --git a/include/vkcv/Container.hpp b/include/vkcv/Container.hpp
new file mode 100644
index 00000000..20c79557
--- /dev/null
+++ b/include/vkcv/Container.hpp
@@ -0,0 +1,23 @@
+#pragma once
+/**
+ * @authors Tobias Frisch
+ * @file vkcv/Container.hpp
+ * @brief A header to define container types for the framework.
+ */
+
+#include <vector>
+#include <unordered_map>
+#include <unordered_set>
+
+namespace vkcv {
+	
+	template<typename K, typename V>
+	using Dictionary = std::unordered_map<K, V>;
+	
+	template<typename T>
+	using Vector = std::vector<T>;
+	
+	template<typename T>
+	using Set = std::unordered_set<T>;
+	
+}
diff --git a/include/vkcv/Context.hpp b/include/vkcv/Context.hpp
index ce56589d..82090760 100644
--- a/include/vkcv/Context.hpp
+++ b/include/vkcv/Context.hpp
@@ -100,9 +100,9 @@ namespace vkcv {
 		 * @return New context
 		 */
 		static Context create(const std::string &applicationName, uint32_t applicationVersion,
-							  const std::vector<vk::QueueFlagBits> &queueFlags,
+							  const Vector<vk::QueueFlagBits> &queueFlags,
 							  const Features &features,
-							  const std::vector<const char*> &instanceExtensions = {});
+							  const Vector<const char*> &instanceExtensions = {});
 
 	private:
 		/**
diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index 7d562d76..5939988c 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -13,6 +13,7 @@
 #include "BlitDownsampler.hpp"
 #include "BufferTypes.hpp"
 #include "ComputePipelineConfig.hpp"
+#include "Container.hpp"
 #include "Context.hpp"
 #include "DescriptorWrites.hpp"
 #include "DispatchSize.hpp"
@@ -85,8 +86,8 @@ namespace vkcv {
 		std::unique_ptr<CommandStreamManager> m_CommandStreamManager;
 		std::unique_ptr<WindowManager> m_WindowManager;
 		std::unique_ptr<SwapchainManager> m_SwapchainManager;
-
-		std::vector<vk::CommandPool> m_CommandPools;
+		
+		Vector<vk::CommandPool> m_CommandPools;
 		vk::Semaphore m_RenderFinished;
 		vk::Semaphore m_SwapchainImageAcquired;
 		uint32_t m_currentSwapchainImageIndex;
@@ -160,9 +161,9 @@ namespace vkcv {
 		 * @return New instance of #Context
 		 */
 		static Core create(const std::string &applicationName, uint32_t applicationVersion,
-						   const std::vector<vk::QueueFlagBits> &queueFlags = {},
+						   const Vector<vk::QueueFlagBits> &queueFlags = {},
 						   const Features &features = {},
-						   const std::vector<const char*> &instanceExtensions = {});
+						   const Vector<const char*> &instanceExtensions = {});
 
 		/**
 		 * Creates a basic vulkan graphics pipeline using @p config from the pipeline config class
@@ -536,8 +537,8 @@ namespace vkcv {
 		void recordDrawcallsToCmdStream(const CommandStreamHandle &cmdStreamHandle,
 										const GraphicsPipelineHandle &pipelineHandle,
 										const PushConstants &pushConstants,
-										const std::vector<InstanceDrawcall> &drawcalls,
-										const std::vector<ImageHandle> &renderTargets,
+										const Vector<InstanceDrawcall> &drawcalls,
+										const Vector<ImageHandle> &renderTargets,
 										const WindowHandle &windowHandle);
 
 		/**
@@ -555,8 +556,8 @@ namespace vkcv {
 		void recordIndirectDrawcallsToCmdStream(const CommandStreamHandle cmdStreamHandle,
 												const GraphicsPipelineHandle &pipelineHandle,
 												const PushConstants &pushConstantData,
-												const std::vector<IndirectDrawcall> &drawcalls,
-												const std::vector<ImageHandle> &renderTargets,
+												const Vector<IndirectDrawcall> &drawcalls,
+												const Vector<ImageHandle> &renderTargets,
 												const WindowHandle &windowHandle);
 
 		/**
@@ -574,8 +575,8 @@ namespace vkcv {
 		void recordMeshShaderDrawcalls(const CommandStreamHandle &cmdStreamHandle,
 									   const GraphicsPipelineHandle &pipelineHandle,
 									   const PushConstants &pushConstantData,
-									   const std::vector<TaskDrawcall> &drawcalls,
-									   const std::vector<ImageHandle> &renderTargets,
+									   const Vector<TaskDrawcall> &drawcalls,
+									   const Vector<ImageHandle> &renderTargets,
 									   const WindowHandle &windowHandle);
 
 		/**
@@ -592,7 +593,7 @@ namespace vkcv {
 		void recordRayGenerationToCmdStream(const CommandStreamHandle &cmdStreamHandle,
 											const RayTracingPipelineHandle &rayTracingPipeline,
 											const DispatchSize &dispatchSize,
-											const std::vector<DescriptorSetUsage>
+											const Vector<DescriptorSetUsage>
 											        &descriptorSetUsages,
 											const PushConstants &pushConstants,
 											const vkcv::WindowHandle &windowHandle);
@@ -610,7 +611,7 @@ namespace vkcv {
 		recordComputeDispatchToCmdStream(const CommandStreamHandle &cmdStream,
 										 const ComputePipelineHandle &computePipeline,
 										 const DispatchSize &dispatchSize,
-										 const std::vector<DescriptorSetUsage> &descriptorSetUsages,
+										 const Vector<DescriptorSetUsage> &descriptorSetUsages,
 										 const PushConstants &pushConstants);
 
 		/**
@@ -643,7 +644,7 @@ namespace vkcv {
 		void recordComputeIndirectDispatchToCmdStream(
 			const CommandStreamHandle cmdStream, const ComputePipelineHandle computePipeline,
 			const vkcv::BufferHandle buffer, const size_t bufferArgOffset,
-			const std::vector<DescriptorSetUsage> &descriptorSetUsages,
+			const Vector<DescriptorSetUsage> &descriptorSetUsages,
 			const PushConstants &pushConstants);
 
 		/**
@@ -968,7 +969,7 @@ namespace vkcv {
 		 * @return Acceleration structure handle
 		 */
 		AccelerationStructureHandle createAccelerationStructure(
-				const std::vector<GeometryData> &geometryData,
+				const Vector<GeometryData> &geometryData,
 				const BufferHandle &transformBuffer = {},
 				bool compaction = false);
 		
@@ -980,7 +981,7 @@ namespace vkcv {
 		 * @return Acceleration structure handle
 		 */
 		AccelerationStructureHandle createAccelerationStructure(
-				const std::vector<AccelerationStructureHandle> &handles);
+				const Vector<AccelerationStructureHandle> &handles);
 		
 		/**
 		 * @brief the underlying vulkan handle for an acceleration structure
diff --git a/include/vkcv/DescriptorBinding.hpp b/include/vkcv/DescriptorBinding.hpp
index c97d1dfe..4591618d 100644
--- a/include/vkcv/DescriptorBinding.hpp
+++ b/include/vkcv/DescriptorBinding.hpp
@@ -5,8 +5,7 @@
  * @brief Structures to handle descriptor bindings.
  */
 
-#include <unordered_map>
-
+#include "Container.hpp"
 #include "DescriptorTypes.hpp"
 #include "ShaderStage.hpp"
 
@@ -26,6 +25,6 @@ namespace vkcv {
 		bool operator==(const DescriptorBinding &other) const;
 	};
 
-	typedef std::unordered_map<uint32_t, DescriptorBinding> DescriptorBindings;
+	typedef Dictionary<uint32_t, DescriptorBinding> DescriptorBindings;
 
 } // namespace vkcv
diff --git a/include/vkcv/DescriptorSetUsage.hpp b/include/vkcv/DescriptorSetUsage.hpp
index 098d1846..d4316116 100644
--- a/include/vkcv/DescriptorSetUsage.hpp
+++ b/include/vkcv/DescriptorSetUsage.hpp
@@ -5,8 +5,7 @@
  * @brief Structures to handle descriptor usages.
  */
 
-#include <vector>
-
+#include "Container.hpp"
 #include "Handles.hpp"
 
 namespace vkcv {
@@ -17,10 +16,10 @@ namespace vkcv {
 	struct DescriptorSetUsage {
 		uint32_t location;
 		DescriptorSetHandle descriptorSet;
-		std::vector<uint32_t> dynamicOffsets;
+		Vector<uint32_t> dynamicOffsets;
 	};
 
 	DescriptorSetUsage useDescriptorSet(uint32_t location, const DescriptorSetHandle &descriptorSet,
-										const std::vector<uint32_t> &dynamicOffsets = {});
+										const Vector<uint32_t> &dynamicOffsets = {});
 
 } // namespace vkcv
diff --git a/include/vkcv/DescriptorWrites.hpp b/include/vkcv/DescriptorWrites.hpp
index 4bc306bc..ca50b915 100644
--- a/include/vkcv/DescriptorWrites.hpp
+++ b/include/vkcv/DescriptorWrites.hpp
@@ -5,9 +5,9 @@
  * @brief Structures to handle descriptor writes.
  */
 
-#include <vector>
 #include <vulkan/vulkan.hpp>
 
+#include "Container.hpp"
 #include "Handles.hpp"
 
 namespace vkcv {
@@ -61,7 +61,7 @@ namespace vkcv {
 	 */
 	struct AccelerationDescriptorWrite {
 		uint32_t binding;
-		std::vector<AccelerationStructureHandle> structures;
+		Vector<AccelerationStructureHandle> structures;
 	};
 
 	/**
@@ -70,12 +70,12 @@ namespace vkcv {
 	 */
 	class DescriptorWrites {
 	private:
-		std::vector<SampledImageDescriptorWrite> m_sampledImageWrites;
-		std::vector<StorageImageDescriptorWrite> m_storageImageWrites;
-		std::vector<BufferDescriptorWrite> m_uniformBufferWrites;
-		std::vector<BufferDescriptorWrite> m_storageBufferWrites;
-		std::vector<SamplerDescriptorWrite> m_samplerWrites;
-		std::vector<AccelerationDescriptorWrite> m_accelerationWrites;
+		Vector<SampledImageDescriptorWrite> m_sampledImageWrites;
+		Vector<StorageImageDescriptorWrite> m_storageImageWrites;
+		Vector<BufferDescriptorWrite> m_uniformBufferWrites;
+		Vector<BufferDescriptorWrite> m_storageBufferWrites;
+		Vector<SamplerDescriptorWrite> m_samplerWrites;
+		Vector<AccelerationDescriptorWrite> m_accelerationWrites;
 
 	public:
 		/**
@@ -159,49 +159,49 @@ namespace vkcv {
 		 */
 		DescriptorWrites &
 		writeAcceleration(uint32_t binding,
-						  const std::vector<AccelerationStructureHandle> &structures);
+						  const Vector<AccelerationStructureHandle> &structures);
 
 		/**
 		 * @brief Returns the list of stored write entries for sampled images.
 		 *
 		 * @return Sampled image write details
 		 */
-		[[nodiscard]] const std::vector<SampledImageDescriptorWrite> &getSampledImageWrites() const;
+		[[nodiscard]] const Vector<SampledImageDescriptorWrite> &getSampledImageWrites() const;
 
 		/**
 		 * @brief Returns the list of stored write entries for storage images.
 		 *
 		 * @return Storage image write details
 		 */
-		[[nodiscard]] const std::vector<StorageImageDescriptorWrite> &getStorageImageWrites() const;
+		[[nodiscard]] const Vector<StorageImageDescriptorWrite> &getStorageImageWrites() const;
 
 		/**
 		 * @brief Returns the list of stored write entries for uniform buffers.
 		 *
 		 * @return Uniform buffers write details
 		 */
-		[[nodiscard]] const std::vector<BufferDescriptorWrite> &getUniformBufferWrites() const;
+		[[nodiscard]] const Vector<BufferDescriptorWrite> &getUniformBufferWrites() const;
 
 		/**
 		 * @brief Returns the list of stored write entries for storage buffers.
 		 *
 		 * @return Storage buffers write details
 		 */
-		[[nodiscard]] const std::vector<BufferDescriptorWrite> &getStorageBufferWrites() const;
+		[[nodiscard]] const Vector<BufferDescriptorWrite> &getStorageBufferWrites() const;
 
 		/**
 		 * @brief Returns the list of stored write entries for samplers.
 		 *
 		 * @return Samplers write details
 		 */
-		[[nodiscard]] const std::vector<SamplerDescriptorWrite> &getSamplerWrites() const;
+		[[nodiscard]] const Vector<SamplerDescriptorWrite> &getSamplerWrites() const;
 
 		/**
 		 * @brief Returns the list of stored write entries for accelerations.
 		 *
 		 * @return Accelerations write details
 		 */
-		[[nodiscard]] const std::vector<AccelerationDescriptorWrite> &getAccelerationWrites() const;
+		[[nodiscard]] const Vector<AccelerationDescriptorWrite> &getAccelerationWrites() const;
 	};
 
 } // namespace vkcv
\ No newline at end of file
diff --git a/include/vkcv/Drawcall.hpp b/include/vkcv/Drawcall.hpp
index 5b229814..ca4b8165 100644
--- a/include/vkcv/Drawcall.hpp
+++ b/include/vkcv/Drawcall.hpp
@@ -5,8 +5,7 @@
  * @brief Classes to define different drawcalls.
  */
 
-#include <vector>
-
+#include "Container.hpp"
 #include "DescriptorSetUsage.hpp"
 #include "DispatchSize.hpp"
 #include "Handles.hpp"
@@ -19,7 +18,7 @@ namespace vkcv {
 	 */
 	class Drawcall {
 	private:
-		std::vector<DescriptorSetUsage> m_usages;
+		Vector<DescriptorSetUsage> m_usages;
 
 	public:
 		Drawcall() = default;
@@ -32,10 +31,10 @@ namespace vkcv {
 		Drawcall &operator=(const Drawcall &other) = default;
 		Drawcall &operator=(Drawcall &&other) noexcept = default;
 
-		[[nodiscard]] const std::vector<DescriptorSetUsage> &getDescriptorSetUsages() const;
+		[[nodiscard]] const Vector<DescriptorSetUsage> &getDescriptorSetUsages() const;
 
 		void useDescriptorSet(uint32_t location, const DescriptorSetHandle &descriptorSet,
-							  const std::vector<uint32_t> &dynamicOffsets = {});
+							  const Vector<uint32_t> &dynamicOffsets = {});
 	};
 
 	/**
diff --git a/include/vkcv/Event.hpp b/include/vkcv/Event.hpp
index 3bba94b2..328b0e51 100644
--- a/include/vkcv/Event.hpp
+++ b/include/vkcv/Event.hpp
@@ -15,7 +15,7 @@
 #endif
 #endif
 
-#include <vector>
+#include "Container.hpp"
 
 namespace vkcv {
 
@@ -50,7 +50,7 @@ namespace vkcv {
 	template <typename... T>
 	struct event {
 	private:
-		std::vector< event_function<T...> > m_functions;
+		Vector< event_function<T...> > m_functions;
 		uint32_t m_id_counter;
 
 #ifndef __MINGW32__
diff --git a/include/vkcv/FeatureManager.hpp b/include/vkcv/FeatureManager.hpp
index 4b0d4560..741d49a5 100644
--- a/include/vkcv/FeatureManager.hpp
+++ b/include/vkcv/FeatureManager.hpp
@@ -6,10 +6,9 @@
  */
 
 #include <functional>
-#include <unordered_set>
-#include <vector>
 #include <vulkan/vulkan.hpp>
 
+#include "Container.hpp"
 #include "Logger.hpp"
 
 namespace vkcv {
@@ -27,12 +26,12 @@ namespace vkcv {
 		/**
 		 * List of supported extensions.
 		 */
-		std::vector<const char*> m_supportedExtensions;
+		Vector<const char*> m_supportedExtensions;
 
 		/**
 		 * List of activated extensions for usage.
 		 */
-		std::vector<const char*> m_activeExtensions;
+		Vector<const char*> m_activeExtensions;
 
 		/**
 		 * Feature structure chain to request activated features.
@@ -42,7 +41,7 @@ namespace vkcv {
 		/**
 		 * List of base structures allocated to request extension specific features.
 		 */
-		std::vector<vk::BaseOutStructure*> m_featuresExtensions;
+		Vector<vk::BaseOutStructure*> m_featuresExtensions;
 
 		/**
 		 * @brief Checks support of the @p vk::PhysicalDeviceFeatures.
@@ -445,7 +444,7 @@ namespace vkcv {
 		 *
 		 * @return List of activated extensions
 		 */
-		[[nodiscard]] const std::vector<const char*> &getActiveExtensions() const;
+		[[nodiscard]] const Vector<const char*> &getActiveExtensions() const;
 
 		/**
 		 * @brief Request specific features for optional or required usage ( only core Vulkan 1.0 ).
diff --git a/include/vkcv/Features.hpp b/include/vkcv/Features.hpp
index 8b39de4f..04830490 100644
--- a/include/vkcv/Features.hpp
+++ b/include/vkcv/Features.hpp
@@ -7,8 +7,8 @@
 
 #include <functional>
 #include <initializer_list>
-#include <vector>
 
+#include "Container.hpp"
 #include "FeatureManager.hpp"
 
 namespace vkcv {
@@ -26,7 +26,7 @@ namespace vkcv {
 		/**
 		 * List of feature requests.
 		 */
-		std::vector<Feature> m_features;
+		Vector<Feature> m_features;
 
 	public:
 		/**
@@ -197,7 +197,7 @@ namespace vkcv {
 		 *
 		 * @return List of feature requests
 		 */
-		[[nodiscard]] const std::vector<Feature> &getList() const;
+		[[nodiscard]] const Vector<Feature> &getList() const;
 	};
 
 } // namespace vkcv
diff --git a/include/vkcv/File.hpp b/include/vkcv/File.hpp
index f6895d41..4f68d685 100644
--- a/include/vkcv/File.hpp
+++ b/include/vkcv/File.hpp
@@ -6,7 +6,8 @@
  */
 
 #include <filesystem>
-#include <vector>
+
+#include "Container.hpp"
 
 namespace vkcv {
 
@@ -33,7 +34,7 @@ namespace vkcv {
 	 * @return True on success, false otherwise
 	 */
 	bool writeContentToFile(const std::filesystem::path &path,
-							const std::vector<char>& content);
+							const Vector<char>& content);
 	
 	/**
 	 * @brief Write binary data from a vector to a file at
@@ -44,7 +45,7 @@ namespace vkcv {
 	 * @return True on success, false otherwise
 	 */
 	bool writeBinaryToFile(const std::filesystem::path &path,
-						   const std::vector<uint32_t>& binary);
+						   const Vector<uint32_t>& binary);
 	
 	/**
 	 * @brief Write text to a file at a given path.
@@ -65,7 +66,7 @@ namespace vkcv {
 	 * @return True on success, false otherwise
 	 */
 	bool readContentFromFile(const std::filesystem::path &path,
-							 std::vector<char>& content);
+							 Vector<char>& content);
 	
 	/**
 	 * @brief Read binary data from a file at a given path
@@ -76,7 +77,7 @@ namespace vkcv {
 	 * @return True on success, false otherwise
 	 */
 	bool readBinaryFromFile(const std::filesystem::path &path,
-							std::vector<uint32_t>& binary);
+							Vector<uint32_t>& binary);
 	
 	/**
 	 * @brief Read text from a file at a given path.
diff --git a/include/vkcv/GraphicsPipelineConfig.hpp b/include/vkcv/GraphicsPipelineConfig.hpp
index 2d67501b..3473ed0e 100644
--- a/include/vkcv/GraphicsPipelineConfig.hpp
+++ b/include/vkcv/GraphicsPipelineConfig.hpp
@@ -6,8 +6,8 @@
  */
 
 #include <cstdint>
-#include <vector>
 
+#include "Container.hpp"
 #include "Multisampling.hpp"
 #include "PipelineConfig.hpp"
 #include "VertexLayout.hpp"
@@ -83,7 +83,7 @@ namespace vkcv {
 		GraphicsPipelineConfig(const ShaderProgram &program,
 							   const PassHandle &pass,
 							   const VertexLayout &vertexLayout,
-							   const std::vector<DescriptorSetLayoutHandle> &layouts);
+							   const Vector<DescriptorSetLayoutHandle> &layouts);
 
 		GraphicsPipelineConfig(const GraphicsPipelineConfig &other) = default;
 		GraphicsPipelineConfig(GraphicsPipelineConfig &&other) = default;
diff --git a/include/vkcv/Interpolation.hpp b/include/vkcv/Interpolation.hpp
index c38a7aa7..a851c9cf 100644
--- a/include/vkcv/Interpolation.hpp
+++ b/include/vkcv/Interpolation.hpp
@@ -8,7 +8,8 @@
 #include <algorithm>
 #include <cmath>
 #include <functional>
-#include <vector>
+
+#include "Container.hpp"
 
 namespace vkcv {
 	
@@ -31,7 +32,7 @@ namespace vkcv {
 	struct interpolation {
 	private:
 		typename interpolation_function<V, T>::type m_function;
-		std::vector< interpolation_state<V, T> > m_states;
+		Vector< interpolation_state<V, T> > m_states;
 	
 	public:
 		interpolation(const typename interpolation_function<V, T>::type& function)
diff --git a/include/vkcv/Pass.hpp b/include/vkcv/Pass.hpp
index c5299d39..2a819f30 100644
--- a/include/vkcv/Pass.hpp
+++ b/include/vkcv/Pass.hpp
@@ -5,20 +5,21 @@
  * @brief Support functions for basic pass creation.
  */
 
+#include "Container.hpp"
 #include "Core.hpp"
 #include "Handles.hpp"
 #include "PassConfig.hpp"
 
 namespace vkcv {
 
-	PassHandle passFormats(Core &core, const std::vector<vk::Format> &formats, bool clear = true,
+	PassHandle passFormats(Core &core, const Vector<vk::Format> &formats, bool clear = true,
 						   Multisampling multisampling = Multisampling::None);
 
 	PassHandle passFormat(Core &core, vk::Format format, bool clear = true,
 						  Multisampling multisampling = Multisampling::None);
 
 	PassHandle passSwapchain(Core &core, const SwapchainHandle &swapchain,
-							 const std::vector<vk::Format> &formats, bool clear = true,
+							 const Vector<vk::Format> &formats, bool clear = true,
 							 Multisampling multisampling = Multisampling::None);
 
 } // namespace vkcv
diff --git a/include/vkcv/PassConfig.hpp b/include/vkcv/PassConfig.hpp
index efe741d0..4aade8e4 100644
--- a/include/vkcv/PassConfig.hpp
+++ b/include/vkcv/PassConfig.hpp
@@ -5,9 +5,9 @@
  * @brief Enums and structures to handle render pass configuration.
  */
 
-#include <vector>
 #include <vulkan/vulkan.hpp>
 
+#include "Container.hpp"
 #include "Multisampling.hpp"
 
 namespace vkcv {
@@ -60,7 +60,7 @@ namespace vkcv {
 		[[nodiscard]] const vk::ClearValue &getClearValue() const;
 	};
 
-	using AttachmentDescriptions = std::vector<AttachmentDescription>;
+	using AttachmentDescriptions = Vector<AttachmentDescription>;
 
 	/**
 	 * @brief Class to configure a pass for usage.
diff --git a/include/vkcv/PipelineConfig.hpp b/include/vkcv/PipelineConfig.hpp
index 575f1705..79f558b7 100644
--- a/include/vkcv/PipelineConfig.hpp
+++ b/include/vkcv/PipelineConfig.hpp
@@ -5,8 +5,7 @@
  * @brief Pipeline config class to hand over required information to pipeline creation
  */
 
-#include <vector>
-
+#include "Container.hpp"
 #include "Handles.hpp"
 #include "ShaderProgram.hpp"
 
@@ -18,13 +17,13 @@ namespace vkcv {
 	class PipelineConfig {
 	private:
 		ShaderProgram m_ShaderProgram;
-		std::vector<DescriptorSetLayoutHandle> m_DescriptorSetLayouts;
+		Vector<DescriptorSetLayoutHandle> m_DescriptorSetLayouts;
 
 	public:
 		PipelineConfig();
 
 		PipelineConfig(const ShaderProgram &program,
-					   const std::vector<DescriptorSetLayoutHandle> &layouts);
+					   const Vector<DescriptorSetLayoutHandle> &layouts);
 
 		PipelineConfig(const PipelineConfig &other) = default;
 		PipelineConfig(PipelineConfig &&other) = default;
@@ -40,9 +39,9 @@ namespace vkcv {
 
 		void addDescriptorSetLayout(const DescriptorSetLayoutHandle &layout);
 
-		void addDescriptorSetLayouts(const std::vector<DescriptorSetLayoutHandle> &layouts);
+		void addDescriptorSetLayouts(const Vector<DescriptorSetLayoutHandle> &layouts);
 
-		[[nodiscard]] const std::vector<DescriptorSetLayoutHandle> &getDescriptorSetLayouts() const;
+		[[nodiscard]] const Vector<DescriptorSetLayoutHandle> &getDescriptorSetLayouts() const;
 	};
 
 } // namespace vkcv
diff --git a/include/vkcv/PushConstants.hpp b/include/vkcv/PushConstants.hpp
index 4c577acb..d3d9736e 100644
--- a/include/vkcv/PushConstants.hpp
+++ b/include/vkcv/PushConstants.hpp
@@ -5,9 +5,9 @@
  * @brief Class to manage push constants for pipeline recording.
  */
 
-#include <vector>
 #include <vulkan/vulkan.hpp>
 
+#include "Container.hpp"
 #include "Logger.hpp"
 #include "TypeGuard.hpp"
 
@@ -19,7 +19,7 @@ namespace vkcv {
 	class PushConstants final {
 	private:
 		TypeGuard m_typeGuard;
-		std::vector<uint8_t> m_data;
+		Vector<uint8_t> m_data;
 
 	public:
 		explicit PushConstants(size_t sizePerDrawcall);
@@ -142,7 +142,7 @@ namespace vkcv {
 	}
 
 	template <typename T>
-	PushConstants pushConstants(const std::vector<T> &values) {
+	PushConstants pushConstants(const Vector<T> &values) {
 		auto pc = pushConstants<T>();
 
 		for (const T &value : values) {
diff --git a/include/vkcv/QueueManager.hpp b/include/vkcv/QueueManager.hpp
index 5bdf64dd..7ddd7275 100644
--- a/include/vkcv/QueueManager.hpp
+++ b/include/vkcv/QueueManager.hpp
@@ -7,6 +7,8 @@
 
 #include <vulkan/vulkan.hpp>
 
+#include "Container.hpp"
+
 namespace vkcv {
 
 	/**
@@ -44,9 +46,9 @@ namespace vkcv {
 		 * @return New queue manager with the specified queue pairs
 		 */
 		static QueueManager create(vk::Device device,
-								   const std::vector<std::pair<int, int>> &queuePairsGraphics,
-								   const std::vector<std::pair<int, int>> &queuePairsCompute,
-								   const std::vector<std::pair<int, int>> &queuePairsTransfer);
+								   const Vector<std::pair<int, int>> &queuePairsGraphics,
+								   const Vector<std::pair<int, int>> &queuePairsCompute,
+								   const Vector<std::pair<int, int>> &queuePairsTransfer);
 
 		/**
 		 * @brief Returns the default queue with present support.
@@ -61,21 +63,21 @@ namespace vkcv {
 		 *
 		 * @return Vector of graphics queues
 		 */
-		[[nodiscard]] const std::vector<Queue> &getGraphicsQueues() const;
+		[[nodiscard]] const Vector<Queue> &getGraphicsQueues() const;
 
 		/**
 		 * @brief Returns all queues with the compute flag.
 		 *
 		 * @return Vector of compute queues
 		 */
-		[[nodiscard]] const std::vector<Queue> &getComputeQueues() const;
+		[[nodiscard]] const Vector<Queue> &getComputeQueues() const;
 
 		/**
 		 * @brief Returns all queues with the transfer flag.
 		 *
 		 * @return Vector of transfer queues
 		 */
-		[[nodiscard]] const std::vector<Queue> &getTransferQueues() const;
+		[[nodiscard]] const Vector<Queue> &getTransferQueues() const;
 
 		/**
 		 * @brief Checks for presenting support of a given surface
@@ -90,13 +92,13 @@ namespace vkcv {
 											const vk::SurfaceKHR &surface);
 
 	private:
-		std::vector<Queue> m_graphicsQueues;
-		std::vector<Queue> m_computeQueues;
-		std::vector<Queue> m_transferQueues;
+		Vector<Queue> m_graphicsQueues;
+		Vector<Queue> m_computeQueues;
+		Vector<Queue> m_transferQueues;
 
 		size_t m_presentIndex;
 
-		QueueManager(std::vector<Queue> &&graphicsQueues, std::vector<Queue> &&computeQueues,
-					 std::vector<Queue> &&transferQueues, size_t presentIndex);
+		QueueManager(Vector<Queue> &&graphicsQueues, Vector<Queue> &&computeQueues,
+					 Vector<Queue> &&transferQueues, size_t presentIndex);
 	};
 } // namespace vkcv
diff --git a/include/vkcv/RayTracingPipelineConfig.hpp b/include/vkcv/RayTracingPipelineConfig.hpp
index 37ca1c4e..572eb5af 100644
--- a/include/vkcv/RayTracingPipelineConfig.hpp
+++ b/include/vkcv/RayTracingPipelineConfig.hpp
@@ -4,7 +4,8 @@
  * @file vkcv/RayTracingPipelineConfig.hpp
  * @brief Ray tracing pipeline config struct to hand over required information to pipeline creation.
  */
- 
+
+#include "Container.hpp"
 #include "PipelineConfig.hpp"
 
 namespace vkcv {
@@ -17,7 +18,7 @@ namespace vkcv {
 		RayTracingPipelineConfig();
 		
 		RayTracingPipelineConfig(const ShaderProgram &program,
-								 const std::vector<DescriptorSetLayoutHandle> &layouts);
+								 const Vector<DescriptorSetLayoutHandle> &layouts);
 		
 		RayTracingPipelineConfig(const RayTracingPipelineConfig &other) = default;
 		RayTracingPipelineConfig(RayTracingPipelineConfig &&other) = default;
diff --git a/include/vkcv/ShaderProgram.hpp b/include/vkcv/ShaderProgram.hpp
index c14a3631..a88597b0 100644
--- a/include/vkcv/ShaderProgram.hpp
+++ b/include/vkcv/ShaderProgram.hpp
@@ -10,9 +10,9 @@
 #include <filesystem>
 #include <iostream>
 #include <spirv_cross.hpp>
-#include <unordered_map>
 #include <vulkan/vulkan.hpp>
 
+#include "Container.hpp"
 #include "DescriptorBinding.hpp"
 #include "ShaderStage.hpp"
 #include "VertexLayout.hpp"
@@ -50,7 +50,7 @@ namespace vkcv {
 		 * @param[in] stage The stage of the shader
 		 * @return Shader code binary of the given stage
 		 */
-		const std::vector<uint32_t> &getShaderBinary(ShaderStage stage) const;
+		const Vector<uint32_t> &getShaderBinary(ShaderStage stage) const;
 
 		/**
 		 * @brief Returns whether a shader exists in the program for a
@@ -67,7 +67,7 @@ namespace vkcv {
 		 *
 		 * @return Vertex attachments
 		 */
-		const std::vector<VertexAttachment> &getVertexAttachments() const;
+		const Vector<VertexAttachment> &getVertexAttachments() const;
 
 		/**
 		 * @brief Returns the size of the programs push constants.
@@ -82,7 +82,7 @@ namespace vkcv {
 		 *
 		 * @return Reflected descriptor set bindings
 		 */
-		const std::unordered_map<uint32_t, DescriptorBindings> &getReflectedDescriptors() const;
+		const Dictionary<uint32_t, DescriptorBindings> &getReflectedDescriptors() const;
 
 	private:
 		/**
@@ -93,11 +93,11 @@ namespace vkcv {
 		 */
 		void reflectShader(ShaderStage shaderStage);
 
-		std::unordered_map<ShaderStage, std::vector<uint32_t> > m_Shaders;
+		Dictionary<ShaderStage, Vector<uint32_t> > m_Shaders;
 
 		// contains all vertex input attachments used in the vertex buffer
 		VertexAttachments m_VertexAttachments;
-		std::unordered_map<uint32_t, DescriptorBindings> m_DescriptorSets;
+		Dictionary<uint32_t, DescriptorBindings> m_DescriptorSets;
 		size_t m_pushConstantsSize = 0;
 	};
 
diff --git a/include/vkcv/VertexData.hpp b/include/vkcv/VertexData.hpp
index a9928a4d..881ca7c1 100644
--- a/include/vkcv/VertexData.hpp
+++ b/include/vkcv/VertexData.hpp
@@ -5,8 +5,7 @@
  * @brief Types to configure vertex data for drawcalls.
  */
 
-#include <vector>
-
+#include "Container.hpp"
 #include "Handles.hpp"
 
 namespace vkcv {
@@ -33,7 +32,7 @@ namespace vkcv {
 											size_t stride,
 											size_t offset = 0);
 
-	typedef std::vector<VertexBufferBinding> VertexBufferBindings;
+	typedef Vector<VertexBufferBinding> VertexBufferBindings;
 
 	/**
 	 * @brief Enum class to specify the size of indexes.
diff --git a/include/vkcv/VertexLayout.hpp b/include/vkcv/VertexLayout.hpp
index 2c6cfb48..0e3c872f 100644
--- a/include/vkcv/VertexLayout.hpp
+++ b/include/vkcv/VertexLayout.hpp
@@ -8,7 +8,8 @@
 
 #include <iostream>
 #include <string>
-#include <vector>
+
+#include "Container.hpp"
 
 namespace vkcv {
 
@@ -48,7 +49,7 @@ namespace vkcv {
 		uint32_t offset;
 	};
 
-	typedef std::vector<VertexAttachment> VertexAttachments;
+	typedef Vector<VertexAttachment> VertexAttachments;
 
 	/**
 	 * @brief Structure to store the details of a vertex buffer binding.
@@ -75,7 +76,7 @@ namespace vkcv {
 	VertexBinding createVertexBinding(uint32_t bindingLocation,
 									  const VertexAttachments &attachments);
 
-	typedef std::vector<VertexBinding> VertexBindings;
+	typedef Vector<VertexBinding> VertexBindings;
 
 	/**
 	 * Creates vertex bindings in a very simplified way with one vertex binding for
diff --git a/include/vkcv/Window.hpp b/include/vkcv/Window.hpp
index 3d157b98..799dd848 100644
--- a/include/vkcv/Window.hpp
+++ b/include/vkcv/Window.hpp
@@ -12,6 +12,7 @@
 #include <algorithm>
 #include <string>
 
+#include "Container.hpp"
 #include "Event.hpp"
 #include "Handles.hpp"
 
@@ -100,7 +101,7 @@ namespace vkcv {
 		 *
 		 * @return Required surface extensions
 		 */
-		static const std::vector<std::string> &getExtensions();
+		static const Vector<std::string> &getExtensions();
 
 		event< int, int, int> e_mouseButton;
 		event< double, double > e_mouseMove;
diff --git a/modules/shader_compiler/src/vkcv/shader/Compiler.cpp b/modules/shader_compiler/src/vkcv/shader/Compiler.cpp
index c7935f89..194faee9 100644
--- a/modules/shader_compiler/src/vkcv/shader/Compiler.cpp
+++ b/modules/shader_compiler/src/vkcv/shader/Compiler.cpp
@@ -1,6 +1,7 @@
 
 #include "vkcv/shader/Compiler.hpp"
 
+#include <vkcv/Container.hpp>
 #include <vkcv/File.hpp>
 #include <vkcv/Logger.hpp>
 
@@ -8,7 +9,7 @@ namespace vkcv::shader {
 	
 	bool Compiler::compileSourceWithHeaders(ShaderStage shaderStage,
 											const std::string &shaderSource,
-											const std::unordered_map<std::filesystem::path, std::string> &shaderHeaders,
+											const Dictionary<std::filesystem::path, std::string> &shaderHeaders,
 											const ShaderCompiledFunction &compiled) {
 		const std::filesystem::path directory = generateTemporaryDirectoryPath();
 		
@@ -42,7 +43,7 @@ namespace vkcv::shader {
 	}
 	
 	void Compiler::compileProgram(ShaderProgram& program,
-								  const std::unordered_map<ShaderStage, const std::filesystem::path>& stages,
+								  const Dictionary<ShaderStage, const std::filesystem::path>& stages,
 								  const ShaderProgramCompiledFunction& compiled,
 								  const std::filesystem::path& includePath, bool update) {
 		std::vector<std::pair<ShaderStage, const std::filesystem::path>> stageList;
diff --git a/projects/bindless_textures/src/main.cpp b/projects/bindless_textures/src/main.cpp
index 5021de5c..2a922747 100644
--- a/projects/bindless_textures/src/main.cpp
+++ b/projects/bindless_textures/src/main.cpp
@@ -140,9 +140,9 @@ int main(int argc, const char** argv) {
 	);
 	
 	const vkcv::VertexLayout firstMeshLayout { bindings };
-	const std::unordered_map<uint32_t, vkcv::DescriptorBinding> &descriptorBindings = firstMeshProgram.getReflectedDescriptors().at(0);
+	const vkcv::DescriptorBindings &descriptorBindings = firstMeshProgram.getReflectedDescriptors().at(0);
 
-    std::unordered_map<uint32_t, vkcv::DescriptorBinding> adjustedBindings = descriptorBindings;
+    vkcv::DescriptorBindings adjustedBindings = descriptorBindings;
     adjustedBindings[1].descriptorCount = 6;
 
     vkcv::DescriptorSetLayoutHandle descriptorSetLayout = core.createDescriptorSetLayout(adjustedBindings);
diff --git a/src/vkcv/AccelerationStructureManager.cpp b/src/vkcv/AccelerationStructureManager.cpp
index 18ab457e..02d3e65b 100644
--- a/src/vkcv/AccelerationStructureManager.cpp
+++ b/src/vkcv/AccelerationStructureManager.cpp
@@ -118,8 +118,8 @@ namespace vkcv {
 	static AccelerationStructureEntry buildAccelerationStructure(
 			Core& core,
 			BufferManager& bufferManager,
-			std::vector<vk::AccelerationStructureBuildGeometryInfoKHR> &geometryInfos,
-			const std::vector<vk::AccelerationStructureBuildRangeInfoKHR> &rangeInfos,
+			Vector<vk::AccelerationStructureBuildGeometryInfoKHR> &geometryInfos,
+			const Vector<vk::AccelerationStructureBuildRangeInfoKHR> &rangeInfos,
 			vk::AccelerationStructureTypeKHR accelerationStructureType,
 			size_t accelerationStructureSize,
 			size_t scratchBufferSize,
@@ -187,7 +187,7 @@ namespace vkcv {
 			geometryInfo.setScratchData(scratchBufferAddress);
 		}
 		
-		std::vector<const vk::AccelerationStructureBuildRangeInfoKHR*> pRangeInfos;
+		Vector<const vk::AccelerationStructureBuildRangeInfoKHR*> pRangeInfos;
 		pRangeInfos.resize(rangeInfos.size());
 		
 		for (size_t i = 0; i < rangeInfos.size(); i++) {
@@ -336,12 +336,12 @@ namespace vkcv {
 	}
 	
 	AccelerationStructureHandle AccelerationStructureManager::createAccelerationStructure(
-			const std::vector<GeometryData> &geometryData,
+			const Vector<GeometryData> &geometryData,
 			const BufferHandle &transformBuffer,
 			bool compaction) {
-		std::vector<vk::AccelerationStructureGeometryKHR> geometries;
-		std::vector<vk::AccelerationStructureBuildGeometryInfoKHR> geometryInfos;
-		std::vector<vk::AccelerationStructureBuildRangeInfoKHR> rangeInfos;
+		Vector<vk::AccelerationStructureGeometryKHR> geometries;
+		Vector<vk::AccelerationStructureBuildGeometryInfoKHR> geometryInfos;
+		Vector<vk::AccelerationStructureBuildRangeInfoKHR> rangeInfos;
 		
 		if (geometryData.empty()) {
 			return {};
@@ -371,7 +371,7 @@ namespace vkcv {
 		geometries.reserve(geometryData.size());
 		rangeInfos.reserve(geometryData.size());
 		
-		std::vector<uint32_t> maxPrimitiveCount;
+		Vector<uint32_t> maxPrimitiveCount;
 		
 		maxPrimitiveCount.reserve(geometryData.size());
 		
@@ -522,8 +522,8 @@ namespace vkcv {
 	}
 	
 	AccelerationStructureHandle AccelerationStructureManager::createAccelerationStructure(
-			const std::vector<AccelerationStructureHandle> &accelerationStructures) {
-		std::vector<vk::AccelerationStructureInstanceKHR> asInstances;
+			const Vector<AccelerationStructureHandle> &accelerationStructures) {
+		Vector<vk::AccelerationStructureInstanceKHR> asInstances;
 		
 		if (accelerationStructures.empty()) {
 			return {};
@@ -624,7 +624,7 @@ namespace vkcv {
 				{}
 		);
 		
-		std::vector<vk::AccelerationStructureBuildGeometryInfoKHR> asBuildGeometryInfos = {
+		Vector<vk::AccelerationStructureBuildGeometryInfoKHR> asBuildGeometryInfos = {
 				vk::AccelerationStructureBuildGeometryInfoKHR(
 						vk::AccelerationStructureTypeKHR::eTopLevel,
 						vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace,
diff --git a/src/vkcv/AccelerationStructureManager.hpp b/src/vkcv/AccelerationStructureManager.hpp
index 041b4acf..2a8a6901 100644
--- a/src/vkcv/AccelerationStructureManager.hpp
+++ b/src/vkcv/AccelerationStructureManager.hpp
@@ -6,13 +6,13 @@
  */
 
 #include <memory>
-#include <vector>
 
 #include <vk_mem_alloc.hpp>
 #include <vulkan/vulkan.hpp>
 
 #include "BufferManager.hpp"
 
+#include "vkcv/Container.hpp"
 #include "vkcv/Handles.hpp"
 #include "vkcv/GeometryData.hpp"
 
@@ -22,7 +22,7 @@ namespace vkcv {
 		vk::AccelerationStructureTypeKHR m_type;
 		vk::DeviceSize m_size;
 		vk::AccelerationStructureKHR m_accelerationStructure;
-		std::vector<AccelerationStructureHandle> m_children;
+		Vector<AccelerationStructureHandle> m_children;
 		BufferHandle m_storageBuffer;
 	};
 	
@@ -79,12 +79,12 @@ namespace vkcv {
 				const AccelerationStructureHandle &handle) const;
 		
 		[[nodiscard]] AccelerationStructureHandle createAccelerationStructure(
-				const std::vector<GeometryData> &geometryData,
+				const Vector<GeometryData> &geometryData,
 				const BufferHandle &transformBuffer,
 				bool compaction);
 		
 		[[nodiscard]] AccelerationStructureHandle createAccelerationStructure(
-				const std::vector<AccelerationStructureHandle> &accelerationStructures);
+				const Vector<AccelerationStructureHandle> &accelerationStructures);
 		
 	};
 	
diff --git a/src/vkcv/BufferManager.cpp b/src/vkcv/BufferManager.cpp
index 466ca064..6678270f 100644
--- a/src/vkcv/BufferManager.cpp
+++ b/src/vkcv/BufferManager.cpp
@@ -21,7 +21,7 @@ namespace vkcv {
 		const auto& memoryProperties = allocator.getMemoryProperties();
 		const auto& heaps = memoryProperties->memoryHeaps;
 		
-		std::vector<vk::MemoryPropertyFlags> heapMemoryFlags;
+		Vector<vk::MemoryPropertyFlags> heapMemoryFlags;
 		heapMemoryFlags.resize(heaps.size());
 		
 		for (const auto& type : memoryProperties->memoryTypes) {
diff --git a/src/vkcv/BufferManager.hpp b/src/vkcv/BufferManager.hpp
index 891b59fc..f26dbfe4 100644
--- a/src/vkcv/BufferManager.hpp
+++ b/src/vkcv/BufferManager.hpp
@@ -6,12 +6,12 @@
  */
 
 #include <memory>
-#include <vector>
 
 #include <vk_mem_alloc.hpp>
 #include <vulkan/vulkan.hpp>
 
 #include "vkcv/BufferTypes.hpp"
+#include "vkcv/Container.hpp"
 #include "vkcv/TypeGuard.hpp"
 
 #include "HandleManager.hpp"
diff --git a/src/vkcv/CommandStreamManager.cpp b/src/vkcv/CommandStreamManager.cpp
index b93cf0a8..87703e37 100644
--- a/src/vkcv/CommandStreamManager.cpp
+++ b/src/vkcv/CommandStreamManager.cpp
@@ -73,15 +73,15 @@ namespace vkcv {
 	}
 
 	void CommandStreamManager::submitCommandStreamSynchronous(
-		const CommandStreamHandle &handle, std::vector<vk::Semaphore> &waitSemaphores,
-		std::vector<vk::Semaphore> &signalSemaphores) {
+		const CommandStreamHandle &handle, Vector<vk::Semaphore> &waitSemaphores,
+		Vector<vk::Semaphore> &signalSemaphores) {
 		auto &stream = (*this) [handle];
 		stream.cmdBuffer.end();
 
 		const auto device = getCore().getContext().getDevice();
 		const vk::Fence waitFence = device.createFence({});
 
-		const std::vector<vk::PipelineStageFlags> waitDstStageMasks(
+		const Vector<vk::PipelineStageFlags> waitDstStageMasks(
 			waitSemaphores.size(), vk::PipelineStageFlagBits::eAllCommands);
 
 		const vk::SubmitInfo queueSubmitInfo(waitSemaphores, waitDstStageMasks, stream.cmdBuffer,
diff --git a/src/vkcv/CommandStreamManager.hpp b/src/vkcv/CommandStreamManager.hpp
index 898f170c..b2321cbc 100644
--- a/src/vkcv/CommandStreamManager.hpp
+++ b/src/vkcv/CommandStreamManager.hpp
@@ -1,8 +1,8 @@
 #pragma once
 
-#include <vector>
 #include <vulkan/vulkan.hpp>
 
+#include "vkcv/Container.hpp"
 #include "vkcv/Event.hpp"
 #include "vkcv/EventFunctionTypes.hpp"
 
@@ -19,7 +19,7 @@ namespace vkcv {
 		vk::CommandBuffer cmdBuffer;
 		vk::CommandPool cmdPool;
 		vk::Queue queue;
-		std::vector<FinishCommandFunction> callbacks;
+		Vector<FinishCommandFunction> callbacks;
 	};
 
 	/**
@@ -79,8 +79,8 @@ namespace vkcv {
 		 * commands is finished
 		 */
 		void submitCommandStreamSynchronous(const CommandStreamHandle &handle,
-											std::vector<vk::Semaphore> &waitSemaphores,
-											std::vector<vk::Semaphore> &signalSemaphores);
+											Vector<vk::Semaphore> &waitSemaphores,
+											Vector<vk::Semaphore> &signalSemaphores);
 
 		/**
 		 * @brief Returns the underlying vulkan handle of a #CommandStream to be used for manual
diff --git a/src/vkcv/ComputePipelineManager.cpp b/src/vkcv/ComputePipelineManager.cpp
index 453dddd1..12d3e673 100644
--- a/src/vkcv/ComputePipelineManager.cpp
+++ b/src/vkcv/ComputePipelineManager.cpp
@@ -33,7 +33,7 @@ namespace vkcv {
 	vk::Result ComputePipelineManager::createShaderModule(vk::ShaderModule &module,
 														  const ShaderProgram &shaderProgram,
 														  const ShaderStage stage) {
-		std::vector<uint32_t> code = shaderProgram.getShaderBinary(stage);
+		Vector<uint32_t> code = shaderProgram.getShaderBinary(stage);
 		vk::ShaderModuleCreateInfo moduleInfo({}, code.size() * sizeof(uint32_t), code.data());
 		return getCore().getContext().getDevice().createShaderModule(&moduleInfo, nullptr, &module);
 	}
@@ -55,7 +55,7 @@ namespace vkcv {
 
 	ComputePipelineHandle ComputePipelineManager::createComputePipeline(
 		const ShaderProgram &shaderProgram,
-		const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts) {
+		const Vector<vk::DescriptorSetLayout> &descriptorSetLayouts) {
 		// Temporally handing over the Shader Program instead of a pipeline config
 		vk::ShaderModule computeModule {};
 		if (createShaderModule(computeModule, shaderProgram, ShaderStage::COMPUTE)
diff --git a/src/vkcv/ComputePipelineManager.hpp b/src/vkcv/ComputePipelineManager.hpp
index 32fdc579..c6833eac 100644
--- a/src/vkcv/ComputePipelineManager.hpp
+++ b/src/vkcv/ComputePipelineManager.hpp
@@ -6,12 +6,12 @@
  * @brief Creation and handling of Compute Pipelines
  */
 
-#include <vector>
 #include <vulkan/vulkan.hpp>
 
 #include "HandleManager.hpp"
 
 #include "vkcv/ComputePipelineConfig.hpp"
+#include "vkcv/Container.hpp"
 #include "vkcv/ShaderProgram.hpp"
 
 namespace vkcv {
@@ -74,7 +74,7 @@ namespace vkcv {
 		 */
 		ComputePipelineHandle
 		createComputePipeline(const ShaderProgram &shaderProgram,
-							  const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts);
+							  const Vector<vk::DescriptorSetLayout> &descriptorSetLayouts);
 	};
 
 } // namespace vkcv
diff --git a/src/vkcv/Context.cpp b/src/vkcv/Context.cpp
index 9a3ef1ff..56229cd9 100644
--- a/src/vkcv/Context.cpp
+++ b/src/vkcv/Context.cpp
@@ -95,7 +95,7 @@ namespace vkcv {
 	 */
 	static bool pickPhysicalDevice(const vk::Instance &instance,
 								   vk::PhysicalDevice &physicalDevice) {
-		const std::vector<vk::PhysicalDevice> &devices = instance.enumeratePhysicalDevices();
+		const Vector<vk::PhysicalDevice> &devices = instance.enumeratePhysicalDevices();
 
 		if (devices.empty()) {
 			vkcv_log(LogLevel::ERROR, "Failed to find GPUs with Vulkan support");
@@ -147,8 +147,8 @@ namespace vkcv {
 	 * @param check The const vector const char* reference elements to be checked by "supported"
 	 * @return True, if all elements in "check" are supported (contained in supported)
 	 */
-	bool checkSupport(const std::vector<const char*> &supported,
-					  const std::vector<const char*> &check) {
+	bool checkSupport(const Vector<const char*> &supported,
+					  const Vector<const char*> &check) {
 		for (auto checkElem : check) {
 			bool found = false;
 			for (auto supportedElem : supported) {
@@ -163,8 +163,8 @@ namespace vkcv {
 		return true;
 	}
 
-	std::vector<std::string> getRequiredExtensions() {
-		std::vector<std::string> extensions = Window::getExtensions();
+	Vector<std::string> getRequiredExtensions() {
+		Vector<std::string> extensions = Window::getExtensions();
 
 #ifdef VULKAN_DEBUG_LABELS
 		extensions.emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
@@ -196,21 +196,21 @@ namespace vkcv {
 	 */
 	static void
 	queueCreateInfosQueueHandles(vk::PhysicalDevice &physicalDevice,
-								 const std::vector<float> &queuePriorities,
-								 const std::vector<vk::QueueFlagBits> &queueFlags,
-								 std::vector<vk::DeviceQueueCreateInfo> &queueCreateInfos,
-								 std::vector<std::pair<int, int>> &queuePairsGraphics,
-								 std::vector<std::pair<int, int>> &queuePairsCompute,
-								 std::vector<std::pair<int, int>> &queuePairsTransfer) {
+								 const Vector<float> &queuePriorities,
+								 const Vector<vk::QueueFlagBits> &queueFlags,
+								 Vector<vk::DeviceQueueCreateInfo> &queueCreateInfos,
+								 Vector<std::pair<int, int>> &queuePairsGraphics,
+								 Vector<std::pair<int, int>> &queuePairsCompute,
+								 Vector<std::pair<int, int>> &queuePairsTransfer) {
 		queueCreateInfos = {};
 		queuePairsGraphics = {};
 		queuePairsCompute = {};
 		queuePairsTransfer = {};
-		std::vector<vk::QueueFamilyProperties> qFamilyProperties =
+		Vector<vk::QueueFamilyProperties> qFamilyProperties =
 			physicalDevice.getQueueFamilyProperties();
 
 		// check priorities of flags -> the lower prioCount the higher the priority
-		std::vector<int> prios;
+		Vector<int> prios;
 		for (auto flag : queueFlags) {
 			int prioCount = 0;
 			for (size_t i = 0; i < qFamilyProperties.size(); i++) {
@@ -220,7 +220,7 @@ namespace vkcv {
 			prios.push_back(prioCount);
 		}
 		// resort flags with heighest priority before allocating the queues
-		std::vector<vk::QueueFlagBits> newFlags;
+		Vector<vk::QueueFlagBits> newFlags;
 		for (size_t i = 0; i < prios.size(); i++) {
 			auto minElem = std::min_element(prios.begin(), prios.end());
 			int index = minElem - prios.begin();
@@ -232,7 +232,7 @@ namespace vkcv {
 		// herefore: create vector that updates available queues in each queue family
 		// structure: [qFamily_0, ..., qFamily_n] where
 		// - qFamily_i = [GraphicsCount, ComputeCount, TransferCount], 0 <= i <= n
-		std::vector<std::vector<int>> queueFamilyStatus, initialQueueFamilyStatus;
+		Vector<Vector<int>> queueFamilyStatus, initialQueueFamilyStatus;
 
 		for (auto qFamily : qFamilyProperties) {
 			auto graphicsCount =
@@ -349,15 +349,15 @@ namespace vkcv {
 	}
 
 	Context Context::create(const std::string &applicationName, uint32_t applicationVersion,
-							const std::vector<vk::QueueFlagBits> &queueFlags,
+							const Vector<vk::QueueFlagBits> &queueFlags,
 							const Features &features,
-							const std::vector<const char*> &instanceExtensions) {
+							const Vector<const char*> &instanceExtensions) {
 		// check for layer support
 
-		const std::vector<vk::LayerProperties> &layerProperties =
+		const Vector<vk::LayerProperties> &layerProperties =
 			vk::enumerateInstanceLayerProperties();
 
-		std::vector<const char*> supportedLayers;
+		Vector<const char*> supportedLayers;
 		supportedLayers.reserve(layerProperties.size());
 
 		for (auto &elem : layerProperties) {
@@ -366,7 +366,7 @@ namespace vkcv {
 
 // if in debug mode, check if validation layers are supported. Enable them if supported
 #ifdef VULKAN_VALIDATION_LAYERS
-		std::vector<const char*> validationLayers = { "VK_LAYER_KHRONOS_validation" };
+		Vector<const char*> validationLayers = { "VK_LAYER_KHRONOS_validation" };
 
 		if (!checkSupport(supportedLayers, validationLayers)) {
 			vkcv_log_throw_error("Validation layers requested but not available!");
@@ -374,10 +374,10 @@ namespace vkcv {
 #endif
 
 		// check for instance extension support
-		std::vector<vk::ExtensionProperties> instanceExtensionProperties =
+		Vector<vk::ExtensionProperties> instanceExtensionProperties =
 			vk::enumerateInstanceExtensionProperties();
 
-		std::vector<const char*> supportedExtensions;
+		Vector<const char*> supportedExtensions;
 		supportedExtensions.reserve(instanceExtensionProperties.size());
 
 		for (auto &elem : instanceExtensionProperties) {
@@ -386,7 +386,7 @@ namespace vkcv {
 
 		// for GLFW: get all required extensions
 		auto requiredStrings = getRequiredExtensions();
-		std::vector<const char*> requiredExtensions;
+		Vector<const char*> requiredExtensions;
 
 		for (const auto &extension : requiredStrings) {
 			requiredExtensions.push_back(extension.c_str());
@@ -414,7 +414,7 @@ namespace vkcv {
 
 		vk::Instance instance = vk::createInstance(instanceCreateInfo);
 
-		std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices();
+		Vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices();
 		vk::PhysicalDevice physicalDevice;
 
 		if (!pickPhysicalDevice(instance, physicalDevice)) {
@@ -433,10 +433,10 @@ namespace vkcv {
 
 		const auto &extensions = featureManager.getActiveExtensions();
 
-		std::vector<vk::DeviceQueueCreateInfo> qCreateInfos;
-		std::vector<float> qPriorities;
+		Vector<vk::DeviceQueueCreateInfo> qCreateInfos;
+		Vector<float> qPriorities;
 		qPriorities.resize(queueFlags.size(), 1.f);
-		std::vector<std::pair<int, int>> queuePairsGraphics, queuePairsCompute, queuePairsTransfer;
+		Vector<std::pair<int, int>> queuePairsGraphics, queuePairsCompute, queuePairsTransfer;
 
 		queueCreateInfosQueueHandles(physicalDevice, qPriorities, queueFlags, qCreateInfos,
 									 queuePairsGraphics, queuePairsCompute, queuePairsTransfer);
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index d31a9ff3..9f1274b2 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -19,7 +19,9 @@
 #include "RayTracingPipelineManager.hpp"
 #include "SamplerManager.hpp"
 #include "WindowManager.hpp"
+
 #include "vkcv/BlitDownsampler.hpp"
+#include "vkcv/Container.hpp"
 #include "vkcv/Core.hpp"
 #include "vkcv/Image.hpp"
 #include "vkcv/Logger.hpp"
@@ -33,8 +35,8 @@ namespace vkcv {
 	 * @param[in] queueManager Queue manager
 	 * @return Set of queue family indices
 	 */
-	static std::unordered_set<int> generateQueueFamilyIndexSet(const QueueManager &queueManager) {
-		std::unordered_set<int> indexSet;
+	static Set<int> generateQueueFamilyIndexSet(const QueueManager &queueManager) {
+		Set<int> indexSet;
 
 		for (const auto &queue : queueManager.getGraphicsQueues()) {
 			indexSet.insert(queue.familyIndex);
@@ -60,9 +62,9 @@ namespace vkcv {
 	 * @param[in] familyIndexSet Set of queue family indices
 	 * @return New command pools
 	 */
-	static std::vector<vk::CommandPool>
-	createCommandPools(const vk::Device &device, const std::unordered_set<int> &familyIndexSet) {
-		std::vector<vk::CommandPool> commandPoolsPerQueueFamily;
+	static Vector<vk::CommandPool>
+	createCommandPools(const vk::Device &device, const Set<int> &familyIndexSet) {
+		Vector<vk::CommandPool> commandPoolsPerQueueFamily;
 		commandPoolsPerQueueFamily.resize(familyIndexSet.size());
 
 		const vk::CommandPoolCreateFlags poolFlags = vk::CommandPoolCreateFlagBits::eTransient;
@@ -76,8 +78,8 @@ namespace vkcv {
 	}
 
 	Core Core::create(const std::string &applicationName, uint32_t applicationVersion,
-					  const std::vector<vk::QueueFlagBits> &queueFlags, const Features &features,
-					  const std::vector<const char*> &instanceExtensions) {
+					  const Vector<vk::QueueFlagBits> &queueFlags, const Features &features,
+					  const Vector<const char*> &instanceExtensions) {
 		Context context = Context::create(applicationName, applicationVersion, queueFlags, features,
 										  instanceExtensions);
 
@@ -141,7 +143,7 @@ namespace vkcv {
 	}
 
 	ComputePipelineHandle Core::createComputePipeline(const ComputePipelineConfig &config) {
-		std::vector<vk::DescriptorSetLayout> layouts;
+		Vector<vk::DescriptorSetLayout> layouts;
 		layouts.resize(config.getDescriptorSetLayouts().size());
 
 		for (size_t i = 0; i < layouts.size(); i++) {
@@ -283,7 +285,7 @@ namespace vkcv {
 	}
 
 	static std::array<uint32_t, 2>
-	getWidthHeightFromRenderTargets(const std::vector<ImageHandle> &renderTargets,
+	getWidthHeightFromRenderTargets(const Vector<ImageHandle> &renderTargets,
 									const vk::Extent2D &swapchainExtent,
 									const ImageManager &imageManager) {
 
@@ -306,13 +308,13 @@ namespace vkcv {
 		return widthHeight;
 	}
 
-	static vk::Framebuffer createFramebuffer(const std::vector<ImageHandle> &renderTargets,
+	static vk::Framebuffer createFramebuffer(const Vector<ImageHandle> &renderTargets,
 											 const ImageManager &imageManager,
 											 const vk::Extent2D &renderExtent,
 											 const vk::RenderPass &renderpass,
 											 const vk::Device &device) {
 
-		std::vector<vk::ImageView> attachmentsViews;
+		Vector<vk::ImageView> attachmentsViews;
 		for (const ImageHandle &handle : renderTargets) {
 			attachmentsViews.push_back(imageManager.getVulkanImageView(handle));
 		}
@@ -324,7 +326,7 @@ namespace vkcv {
 		return device.createFramebuffer(createInfo);
 	}
 
-	void transitionRendertargetsToAttachmentLayout(const std::vector<ImageHandle> &renderTargets,
+	void transitionRendertargetsToAttachmentLayout(const Vector<ImageHandle> &renderTargets,
 												   ImageManager &imageManager,
 												   const vk::CommandBuffer cmdBuffer) {
 
@@ -337,9 +339,9 @@ namespace vkcv {
 		}
 	}
 
-	std::vector<vk::ClearValue>
-	createAttachmentClearValues(const std::vector<AttachmentDescription> &attachments) {
-		std::vector<vk::ClearValue> clearValues;
+	Vector<vk::ClearValue>
+	createAttachmentClearValues(const Vector<AttachmentDescription> &attachments) {
+		Vector<vk::ClearValue> clearValues;
 		for (const auto &attachment : attachments) {
 			if (attachment.getLoadOperation() == AttachmentOperation::CLEAR) {
 				clearValues.push_back(attachment.getClearValue());
@@ -421,7 +423,7 @@ namespace vkcv {
 									   const CommandStreamHandle &cmdStreamHandle,
 									   const GraphicsPipelineHandle &pipelineHandle,
 									   const PushConstants &pushConstants,
-									   const std::vector<ImageHandle> &renderTargets,
+									   const Vector<ImageHandle> &renderTargets,
 									   const WindowHandle &windowHandle,
 									   const RecordCommandFunction &record) {
 
@@ -467,7 +469,7 @@ namespace vkcv {
 		}
 
 		auto submitFunction = [&](const vk::CommandBuffer &cmdBuffer) {
-			const std::vector<vk::ClearValue> clearValues =
+			const Vector<vk::ClearValue> clearValues =
 				createAttachmentClearValues(attachments);
 
 			const vk::RenderPassBeginInfo beginInfo(renderPass, framebuffer, renderArea,
@@ -500,8 +502,8 @@ namespace vkcv {
 	void Core::recordDrawcallsToCmdStream(const CommandStreamHandle &cmdStreamHandle,
 										  const GraphicsPipelineHandle &pipelineHandle,
 										  const PushConstants &pushConstantData,
-										  const std::vector<InstanceDrawcall> &drawcalls,
-										  const std::vector<ImageHandle> &renderTargets,
+										  const Vector<InstanceDrawcall> &drawcalls,
+										  const Vector<ImageHandle> &renderTargets,
 										  const WindowHandle &windowHandle) {
 
 		if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) {
@@ -569,8 +571,8 @@ namespace vkcv {
 	void Core::recordIndirectDrawcallsToCmdStream(
 		const vkcv::CommandStreamHandle cmdStreamHandle,
 		const vkcv::GraphicsPipelineHandle &pipelineHandle,
-		const vkcv::PushConstants &pushConstantData, const std::vector<IndirectDrawcall> &drawcalls,
-		const std::vector<ImageHandle> &renderTargets, const vkcv::WindowHandle &windowHandle) {
+		const vkcv::PushConstants &pushConstantData, const Vector<IndirectDrawcall> &drawcalls,
+		const Vector<ImageHandle> &renderTargets, const vkcv::WindowHandle &windowHandle) {
 
 		if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) {
 			return;
@@ -632,8 +634,8 @@ namespace vkcv {
 	void Core::recordMeshShaderDrawcalls(const CommandStreamHandle &cmdStreamHandle,
 										 const GraphicsPipelineHandle &pipelineHandle,
 										 const PushConstants &pushConstantData,
-										 const std::vector<TaskDrawcall> &drawcalls,
-										 const std::vector<ImageHandle> &renderTargets,
+										 const Vector<TaskDrawcall> &drawcalls,
+										 const Vector<ImageHandle> &renderTargets,
 										 const WindowHandle &windowHandle) {
 
 		if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) {
@@ -659,7 +661,7 @@ namespace vkcv {
 		const CommandStreamHandle &cmdStreamHandle,
 		const RayTracingPipelineHandle &rayTracingPipeline,
 		const DispatchSize &dispatchSize,
-		const std::vector<DescriptorSetUsage> &descriptorSetUsages,
+		const Vector<DescriptorSetUsage> &descriptorSetUsages,
 		const PushConstants &pushConstants,
 		const vkcv::WindowHandle &windowHandle) {
 		
@@ -731,7 +733,7 @@ namespace vkcv {
 		const CommandStreamHandle &cmdStreamHandle,
 		const ComputePipelineHandle &computePipeline,
 		const DispatchSize &dispatchSize,
-		const std::vector<DescriptorSetUsage> &descriptorSetUsages,
+		const Vector<DescriptorSetUsage> &descriptorSetUsages,
 		const PushConstants &pushConstants) {
 		auto submitFunction = [&](const vk::CommandBuffer &cmdBuffer) {
 			const auto pipelineLayout =
@@ -800,7 +802,7 @@ namespace vkcv {
 	void Core::recordComputeIndirectDispatchToCmdStream(
 		const CommandStreamHandle cmdStream, const ComputePipelineHandle computePipeline,
 		const vkcv::BufferHandle buffer, const size_t bufferArgOffset,
-		const std::vector<DescriptorSetUsage> &descriptorSetUsages,
+		const Vector<DescriptorSetUsage> &descriptorSetUsages,
 		const PushConstants &pushConstants) {
 
 		auto submitFunction = [&](const vk::CommandBuffer &cmdBuffer) {
@@ -906,10 +908,10 @@ namespace vkcv {
 	}
 
 	void Core::submitCommandStream(const CommandStreamHandle &stream, bool signalRendering) {
-		std::vector<vk::Semaphore> waitSemaphores;
+		Vector<vk::Semaphore> waitSemaphores;
 
 		// FIXME: add proper user controllable sync
-		std::vector<vk::Semaphore> signalSemaphores;
+		Vector<vk::Semaphore> signalSemaphores;
 		if (signalRendering) {
 			signalSemaphores.push_back(m_RenderFinished);
 		}
@@ -1367,7 +1369,7 @@ namespace vkcv {
 	}
 	
 	AccelerationStructureHandle Core::createAccelerationStructure(
-			const std::vector<GeometryData> &geometryData,
+			const Vector<GeometryData> &geometryData,
 			const BufferHandle &transformBuffer,
 			bool compaction) {
 		return m_AccelerationStructureManager->createAccelerationStructure(
@@ -1378,7 +1380,7 @@ namespace vkcv {
 	}
 	
 	AccelerationStructureHandle Core::createAccelerationStructure(
-			const std::vector<AccelerationStructureHandle> &handles) {
+			const Vector<AccelerationStructureHandle> &handles) {
 		return m_AccelerationStructureManager->createAccelerationStructure(handles);
 	}
 	
diff --git a/src/vkcv/DescriptorSetLayoutManager.cpp b/src/vkcv/DescriptorSetLayoutManager.cpp
index 14fe4d51..6bbdb099 100644
--- a/src/vkcv/DescriptorSetLayoutManager.cpp
+++ b/src/vkcv/DescriptorSetLayoutManager.cpp
@@ -58,8 +58,8 @@ namespace vkcv {
 		}
 
 		// create the descriptor set's layout and binding flags by iterating over its bindings
-		std::vector<vk::DescriptorSetLayoutBinding> bindingsVector = {};
-		std::vector<vk::DescriptorBindingFlags> bindingsFlags = {};
+		Vector<vk::DescriptorSetLayoutBinding> bindingsVector = {};
+		Vector<vk::DescriptorBindingFlags> bindingsFlags = {};
 
 		for (auto bindingElem : bindings) {
 			DescriptorBinding binding = bindingElem.second;
diff --git a/src/vkcv/DescriptorSetManager.cpp b/src/vkcv/DescriptorSetManager.cpp
index 605e5d3c..5304031f 100644
--- a/src/vkcv/DescriptorSetManager.cpp
+++ b/src/vkcv/DescriptorSetManager.cpp
@@ -144,22 +144,22 @@ namespace vkcv {
 												  const SamplerManager &samplerManager) {
 		auto &set = (*this) [handle];
 
-		std::vector<vk::DescriptorImageInfo> imageInfos;
-		std::vector<vk::DescriptorBufferInfo> bufferInfos;
+		Vector<vk::DescriptorImageInfo> imageInfos;
+		Vector<vk::DescriptorBufferInfo> bufferInfos;
 		
 		bufferInfos.reserve(
 				writes.getUniformBufferWrites().size() +
 				writes.getStorageBufferWrites().size()
 		);
 		
-		std::vector<vk::AccelerationStructureKHR> accelerationStructures;
-		std::vector<size_t> accelerationStructureOffsets;
+		Vector<vk::AccelerationStructureKHR> accelerationStructures;
+		Vector<size_t> accelerationStructureOffsets;
 		
 		accelerationStructureOffsets.reserve(writes.getAccelerationWrites().size());
 
-		std::vector<vk::WriteDescriptorSetAccelerationStructureKHR> writeStructures;
+		Vector<vk::WriteDescriptorSetAccelerationStructureKHR> writeStructures;
 
-		std::vector<WriteDescriptorSetInfo> writeInfos;
+		Vector<WriteDescriptorSetInfo> writeInfos;
 		writeInfos.reserve(
 				writes.getSampledImageWrites().size() +
 				writes.getStorageImageWrites().size() +
@@ -311,7 +311,7 @@ namespace vkcv {
 			writeInfos.push_back(vulkanWrite);
 		}
 
-		std::vector<vk::WriteDescriptorSet> vulkanWrites;
+		Vector<vk::WriteDescriptorSet> vulkanWrites;
 		vulkanWrites.reserve(writeInfos.size());
 
 		for (const auto &write : writeInfos) {
diff --git a/src/vkcv/DescriptorSetManager.hpp b/src/vkcv/DescriptorSetManager.hpp
index 06ea6dd7..5dbdc954 100644
--- a/src/vkcv/DescriptorSetManager.hpp
+++ b/src/vkcv/DescriptorSetManager.hpp
@@ -35,8 +35,8 @@ namespace vkcv {
 	private:
 		DescriptorSetLayoutManager* m_DescriptorSetLayoutManager;
 
-		std::vector<vk::DescriptorPool> m_Pools;
-		std::vector<vk::DescriptorPoolSize> m_PoolSizes;
+		Vector<vk::DescriptorPool> m_Pools;
+		Vector<vk::DescriptorPoolSize> m_PoolSizes;
 		vk::DescriptorPoolCreateInfo m_PoolInfo;
 
 		bool init(Core &core, DescriptorSetLayoutManager &descriptorSetLayoutManager);
diff --git a/src/vkcv/DescriptorSetUsage.cpp b/src/vkcv/DescriptorSetUsage.cpp
index cfa2ba19..dcd283e9 100644
--- a/src/vkcv/DescriptorSetUsage.cpp
+++ b/src/vkcv/DescriptorSetUsage.cpp
@@ -4,7 +4,7 @@
 namespace vkcv {
 
 	DescriptorSetUsage useDescriptorSet(uint32_t location, const DescriptorSetHandle &descriptorSet,
-										const std::vector<uint32_t> &dynamicOffsets) {
+										const Vector<uint32_t> &dynamicOffsets) {
 		DescriptorSetUsage usage;
 		usage.location = location;
 		usage.descriptorSet = descriptorSet;
diff --git a/src/vkcv/DescriptorWrites.cpp b/src/vkcv/DescriptorWrites.cpp
index b4be5958..2e9d567c 100644
--- a/src/vkcv/DescriptorWrites.cpp
+++ b/src/vkcv/DescriptorWrites.cpp
@@ -77,7 +77,7 @@ namespace vkcv {
 	}
 
 	DescriptorWrites &DescriptorWrites::writeAcceleration(
-		uint32_t binding, const std::vector<AccelerationStructureHandle> &structures) {
+		uint32_t binding, const Vector<AccelerationStructureHandle> &structures) {
 		AccelerationDescriptorWrite write;
 		write.binding = binding;
 		write.structures = structures;
@@ -85,29 +85,29 @@ namespace vkcv {
 		return *this;
 	}
 
-	const std::vector<SampledImageDescriptorWrite> &
+	const Vector<SampledImageDescriptorWrite> &
 	DescriptorWrites::getSampledImageWrites() const {
 		return m_sampledImageWrites;
 	}
 
-	const std::vector<StorageImageDescriptorWrite> &
+	const Vector<StorageImageDescriptorWrite> &
 	DescriptorWrites::getStorageImageWrites() const {
 		return m_storageImageWrites;
 	}
 
-	const std::vector<BufferDescriptorWrite> &DescriptorWrites::getUniformBufferWrites() const {
+	const Vector<BufferDescriptorWrite> &DescriptorWrites::getUniformBufferWrites() const {
 		return m_uniformBufferWrites;
 	}
 
-	const std::vector<BufferDescriptorWrite> &DescriptorWrites::getStorageBufferWrites() const {
+	const Vector<BufferDescriptorWrite> &DescriptorWrites::getStorageBufferWrites() const {
 		return m_storageBufferWrites;
 	}
 
-	const std::vector<SamplerDescriptorWrite> &DescriptorWrites::getSamplerWrites() const {
+	const Vector<SamplerDescriptorWrite> &DescriptorWrites::getSamplerWrites() const {
 		return m_samplerWrites;
 	}
 
-	const std::vector<AccelerationDescriptorWrite> &
+	const Vector<AccelerationDescriptorWrite> &
 	DescriptorWrites::getAccelerationWrites() const {
 		return m_accelerationWrites;
 	}
diff --git a/src/vkcv/Drawcall.cpp b/src/vkcv/Drawcall.cpp
index 73142b55..cc93d74f 100644
--- a/src/vkcv/Drawcall.cpp
+++ b/src/vkcv/Drawcall.cpp
@@ -7,12 +7,12 @@
 
 namespace vkcv {
 
-	const std::vector<DescriptorSetUsage> &Drawcall::getDescriptorSetUsages() const {
+	const Vector<DescriptorSetUsage> &Drawcall::getDescriptorSetUsages() const {
 		return m_usages;
 	}
 
 	void Drawcall::useDescriptorSet(uint32_t location, const DescriptorSetHandle &descriptorSet,
-									const std::vector<uint32_t> &dynamicOffsets) {
+									const Vector<uint32_t> &dynamicOffsets) {
 		DescriptorSetUsage usage;
 		usage.location = location;
 		usage.descriptorSet = descriptorSet;
diff --git a/src/vkcv/FeatureManager.cpp b/src/vkcv/FeatureManager.cpp
index 51e86f6c..10980c27 100644
--- a/src/vkcv/FeatureManager.cpp
+++ b/src/vkcv/FeatureManager.cpp
@@ -648,7 +648,7 @@ namespace vkcv {
 		return false;
 	}
 
-	const std::vector<const char*> &FeatureManager::getActiveExtensions() const {
+	const Vector<const char*> &FeatureManager::getActiveExtensions() const {
 		return m_activeExtensions;
 	}
 
diff --git a/src/vkcv/Features.cpp b/src/vkcv/Features.cpp
index fcfdd7b9..33ed9bb6 100644
--- a/src/vkcv/Features.cpp
+++ b/src/vkcv/Features.cpp
@@ -59,7 +59,7 @@ namespace vkcv {
 		});
 	}
 
-	const std::vector<Feature> &Features::getList() const {
+	const Vector<Feature> &Features::getList() const {
 		return m_features;
 	}
 
diff --git a/src/vkcv/File.cpp b/src/vkcv/File.cpp
index 32ded3e5..702ae899 100644
--- a/src/vkcv/File.cpp
+++ b/src/vkcv/File.cpp
@@ -58,7 +58,7 @@ namespace vkcv {
 	}
 	
 	bool writeContentToFile(const std::filesystem::path &path,
-							const std::vector<char>& content) {
+							const Vector<char>& content) {
 		std::ofstream file (path.string(), std::ios::out);
 		
 		if (!file.is_open()) {
@@ -74,7 +74,7 @@ namespace vkcv {
 	}
 	
 	bool writeBinaryToFile(const std::filesystem::path &path,
-						   const std::vector<uint32_t>& binary) {
+						   const Vector<uint32_t>& binary) {
 		std::ofstream file (path.string(), std::ios::out);
 		
 		if (!file.is_open()) {
@@ -109,7 +109,7 @@ namespace vkcv {
 	}
 	
 	bool readContentFromFile(const std::filesystem::path &path,
-							 std::vector<char>& content) {
+							 Vector<char>& content) {
 		std::ifstream file (path.string(), std::ios::ate);
 		
 		if (!file.is_open()) {
@@ -128,7 +128,7 @@ namespace vkcv {
 	}
 	
 	bool readBinaryFromFile(const std::filesystem::path &path,
-							std::vector<uint32_t>& binary) {
+							Vector<uint32_t>& binary) {
 		std::ifstream file (path.string(), std::ios::ate);
 		
 		if (!file.is_open()) {
@@ -165,7 +165,7 @@ namespace vkcv {
 		}
 		
 		const std::streamsize fileSize = file.tellg();
-		std::vector<char> buffer (fileSize);
+		Vector<char> buffer (fileSize);
 		buffer.resize(fileSize);
 		
 		file.seekg(0);
diff --git a/src/vkcv/GraphicsPipelineConfig.cpp b/src/vkcv/GraphicsPipelineConfig.cpp
index 383c0de1..7a669bbf 100644
--- a/src/vkcv/GraphicsPipelineConfig.cpp
+++ b/src/vkcv/GraphicsPipelineConfig.cpp
@@ -12,7 +12,7 @@ namespace vkcv {
 		const ShaderProgram &program,
 		const PassHandle &pass,
 		const VertexLayout &vertexLayout,
-		const std::vector<DescriptorSetLayoutHandle> &layouts) :
+		const Vector<DescriptorSetLayoutHandle> &layouts) :
 		PipelineConfig(program, layouts),
 		m_PassHandle(pass),
 		m_VertexLayout(vertexLayout),
diff --git a/src/vkcv/GraphicsPipelineManager.cpp b/src/vkcv/GraphicsPipelineManager.cpp
index 4f8a217d..be8e0bfb 100644
--- a/src/vkcv/GraphicsPipelineManager.cpp
+++ b/src/vkcv/GraphicsPipelineManager.cpp
@@ -131,7 +131,7 @@ namespace vkcv {
 			vk::PipelineShaderStageCreateInfo* outCreateInfo) {
 
 		assert(outCreateInfo);
-		std::vector<uint32_t> code = shaderProgram.getShaderBinary(stage);
+		Vector<uint32_t> code = shaderProgram.getShaderBinary(stage);
 		vk::ShaderModuleCreateInfo vertexModuleInfo(
 				{},
 				code.size() * sizeof(uint32_t),
@@ -162,8 +162,8 @@ namespace vkcv {
 	 * @param config
 	 */
 	static void fillVertexInputDescription(
-		std::vector<vk::VertexInputAttributeDescription> &vertexAttributeDescriptions,
-		std::vector<vk::VertexInputBindingDescription> &vertexBindingDescriptions,
+		Vector<vk::VertexInputAttributeDescription> &vertexAttributeDescriptions,
+		Vector<vk::VertexInputBindingDescription> &vertexBindingDescriptions,
 		const bool existsVertexShader,
 		const GraphicsPipelineConfig &config) {
 
@@ -197,8 +197,8 @@ namespace vkcv {
 	 * @return Pipeline Vertex Input State Create Info Struct
 	 */
 	static vk::PipelineVertexInputStateCreateInfo createPipelineVertexInputStateCreateInfo(
-		std::vector<vk::VertexInputAttributeDescription> &vertexAttributeDescriptions,
-		std::vector<vk::VertexInputBindingDescription> &vertexBindingDescriptions) {
+		Vector<vk::VertexInputAttributeDescription> &vertexAttributeDescriptions,
+		Vector<vk::VertexInputBindingDescription> &vertexBindingDescriptions) {
 
 		vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo(
 			{}, vertexBindingDescriptions.size(), vertexBindingDescriptions.data(),
@@ -346,7 +346,7 @@ namespace vkcv {
 	static vk::PipelineColorBlendStateCreateInfo
 	createPipelineColorBlendStateCreateInfo(const GraphicsPipelineConfig &config,
 											const PassConfig &passConfig) {
-		static std::vector<vk::PipelineColorBlendAttachmentState> colorBlendAttachmentStates;
+		static Vector<vk::PipelineColorBlendAttachmentState> colorBlendAttachmentStates;
 		
 		colorBlendAttachmentStates.clear();
 		colorBlendAttachmentStates.reserve(passConfig.getAttachments().size());
@@ -397,7 +397,7 @@ namespace vkcv {
 	 */
 	static vk::PipelineLayoutCreateInfo createPipelineLayoutCreateInfo(
 		const GraphicsPipelineConfig &config,
-		const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts) {
+		const Vector<vk::DescriptorSetLayout> &descriptorSetLayouts) {
 		static vk::PushConstantRange pushConstantRange;
 
 		const size_t pushConstantsSize = config.getShaderProgram().getPushConstantsSize();
@@ -450,7 +450,7 @@ namespace vkcv {
 	 */
 	static vk::PipelineDynamicStateCreateInfo
 	createPipelineDynamicStateCreateInfo(const GraphicsPipelineConfig &config) {
-		static std::vector<vk::DynamicState> dynamicStates;
+		static Vector<vk::DynamicState> dynamicStates;
 		dynamicStates.clear();
 
 		if (config.isViewportDynamic()) {
@@ -497,7 +497,7 @@ namespace vkcv {
 			return {};
 		}
 
-		std::vector<vk::PipelineShaderStageCreateInfo> shaderStages;
+		Vector<vk::PipelineShaderStageCreateInfo> shaderStages;
 		auto destroyShaderModules = [&shaderStages, this] {
 			for (auto stage : shaderStages) {
 				getCore().getContext().getDevice().destroyShaderModule(stage.module);
@@ -601,8 +601,8 @@ namespace vkcv {
 
 		// vertex input state
 		// Fill up VertexInputBindingDescription and VertexInputAttributeDescription Containers
-		std::vector<vk::VertexInputAttributeDescription> vertexAttributeDescriptions;
-		std::vector<vk::VertexInputBindingDescription> vertexBindingDescriptions;
+		Vector<vk::VertexInputAttributeDescription> vertexAttributeDescriptions;
+		Vector<vk::VertexInputBindingDescription> vertexBindingDescriptions;
 		fillVertexInputDescription(vertexAttributeDescriptions, vertexBindingDescriptions,
 								   existsVertexShader, config);
 
@@ -644,7 +644,7 @@ namespace vkcv {
 		vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo =
 			createPipelineDynamicStateCreateInfo(config);
 
-		std::vector<vk::DescriptorSetLayout> descriptorSetLayouts;
+		Vector<vk::DescriptorSetLayout> descriptorSetLayouts;
 		descriptorSetLayouts.reserve(config.getDescriptorSetLayouts().size());
 		for (const auto &handle : config.getDescriptorSetLayouts()) {
 			descriptorSetLayouts.push_back(
diff --git a/src/vkcv/GraphicsPipelineManager.hpp b/src/vkcv/GraphicsPipelineManager.hpp
index 867bd46f..d5574653 100644
--- a/src/vkcv/GraphicsPipelineManager.hpp
+++ b/src/vkcv/GraphicsPipelineManager.hpp
@@ -6,12 +6,14 @@
  * @brief Creation and handling of graphic pipelines
  */
 
+#include <vulkan/vulkan.hpp>
+
 #include "DescriptorSetLayoutManager.hpp"
 #include "HandleManager.hpp"
 #include "PassManager.hpp"
+
+#include "vkcv/Container.hpp"
 #include "vkcv/GraphicsPipelineConfig.hpp"
-#include <vector>
-#include <vulkan/vulkan.hpp>
 
 namespace vkcv {
 
diff --git a/src/vkcv/HandleManager.hpp b/src/vkcv/HandleManager.hpp
index a7b4b7aa..0bca3076 100644
--- a/src/vkcv/HandleManager.hpp
+++ b/src/vkcv/HandleManager.hpp
@@ -1,8 +1,8 @@
 #pragma once
 
 #include <optional>
-#include <vector>
 
+#include "vkcv/Container.hpp"
 #include "vkcv/Handles.hpp"
 #include "vkcv/Logger.hpp"
 
@@ -16,7 +16,7 @@ namespace vkcv {
 
 	private:
 		Core* m_core;
-		std::vector<T> m_entries;
+		Vector<T> m_entries;
 
 	protected:
 		HandleManager() noexcept : m_core(nullptr), m_entries() {}
diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp
index 5ecbd70f..e46a267c 100644
--- a/src/vkcv/ImageManager.cpp
+++ b/src/vkcv/ImageManager.cpp
@@ -289,8 +289,8 @@ namespace vkcv {
 		
 		const vk::Device &device = getCore().getContext().getDevice();
 		
-		std::vector<vk::ImageView> views;
-		std::vector<vk::ImageView> arrayViews;
+		Vector<vk::ImageView> views;
+		Vector<vk::ImageView> arrayViews;
 		
 		for (uint32_t mip = 0; mip < mipCount; mip++) {
 			const vk::ImageViewCreateInfo imageViewCreateInfo(
@@ -340,7 +340,7 @@ namespace vkcv {
 			arrayViews.push_back(device.createImageView(imageViewCreateInfo));
 		}
 		
-		std::vector<vk::ImageLayout> layers;
+		Vector<vk::ImageLayout> layers;
 		layers.resize(arrayLayers, vk::ImageLayout::eUndefined);
 		
 		return add({
@@ -707,8 +707,8 @@ namespace vkcv {
 		m_currentSwapchainInputImage = index;
 	}
 	
-	void ImageManager::setSwapchainImages(const std::vector<vk::Image> &images,
-										  const std::vector<vk::ImageView> &views, uint32_t width,
+	void ImageManager::setSwapchainImages(const Vector<vk::Image> &images,
+										  const Vector<vk::ImageView> &views, uint32_t width,
 										  uint32_t height, vk::Format format) {
 		
 		// destroy old views
diff --git a/src/vkcv/ImageManager.hpp b/src/vkcv/ImageManager.hpp
index 7d9c278d..d334c59b 100644
--- a/src/vkcv/ImageManager.hpp
+++ b/src/vkcv/ImageManager.hpp
@@ -4,12 +4,14 @@
  * @file vkcv/ImageManager.hpp
  * @brief class creating and managing images
  */
-#include <vector>
+
 #include <vk_mem_alloc.hpp>
 #include <vulkan/vulkan.hpp>
 
 #include "BufferManager.hpp"
 #include "HandleManager.hpp"
+
+#include "vkcv/Container.hpp"
 #include "vkcv/ImageConfig.hpp"
 
 namespace vkcv {
@@ -27,15 +29,15 @@ namespace vkcv {
 		vk::Image m_handle;
 		vma::Allocation m_allocation;
 
-		std::vector<vk::ImageView> m_viewPerMip;
-		std::vector<vk::ImageView> m_arrayViewPerMip;
+		Vector<vk::ImageView> m_viewPerMip;
+		Vector<vk::ImageView> m_arrayViewPerMip;
 
 		uint32_t m_width;
 		uint32_t m_height;
 		uint32_t m_depth;
 
 		vk::Format m_format;
-		std::vector<vk::ImageLayout> m_layers;
+		Vector<vk::ImageLayout> m_layers;
 		bool m_storage;
 	};
 
@@ -49,7 +51,7 @@ namespace vkcv {
 	private:
 		BufferManager* m_bufferManager;
 
-		std::vector<ImageEntry> m_swapchainImages;
+		Vector<ImageEntry> m_swapchainImages;
 		int m_currentSwapchainInputImage;
 
 		bool init(Core &core, BufferManager &bufferManager);
@@ -133,8 +135,8 @@ namespace vkcv {
 
 		void setCurrentSwapchainImageIndex(int index);
 
-		void setSwapchainImages(const std::vector<vk::Image> &images,
-								const std::vector<vk::ImageView> &views, uint32_t width,
+		void setSwapchainImages(const Vector<vk::Image> &images,
+								const Vector<vk::ImageView> &views, uint32_t width,
 								uint32_t height, vk::Format format);
 
 		// if manual vulkan work, e.g. ImGui integration, changes an image layout this function must
diff --git a/src/vkcv/Pass.cpp b/src/vkcv/Pass.cpp
index 147d7151..d88b2682 100644
--- a/src/vkcv/Pass.cpp
+++ b/src/vkcv/Pass.cpp
@@ -3,7 +3,7 @@
 
 namespace vkcv {
 
-	PassHandle passFormats(Core &core, const std::vector<vk::Format> &formats, bool clear,
+	PassHandle passFormats(Core &core, const Vector<vk::Format> &formats, bool clear,
 						   Multisampling multisampling) {
 		AttachmentDescriptions attachments;
 
@@ -22,9 +22,9 @@ namespace vkcv {
 	}
 
 	PassHandle passSwapchain(Core &core, const SwapchainHandle &swapchain,
-							 const std::vector<vk::Format> &formats, bool clear,
+							 const Vector<vk::Format> &formats, bool clear,
 							 Multisampling multisampling) {
-		std::vector<vk::Format> swapchainFormats (formats);
+		Vector<vk::Format> swapchainFormats (formats);
 
 		for (auto &format : swapchainFormats) {
 			if (vk::Format::eUndefined == format) {
diff --git a/src/vkcv/PassManager.cpp b/src/vkcv/PassManager.cpp
index 9b160bcf..944df1b6 100644
--- a/src/vkcv/PassManager.cpp
+++ b/src/vkcv/PassManager.cpp
@@ -49,10 +49,10 @@ namespace vkcv {
 
 	PassHandle PassManager::createPass(const PassConfig &config) {
 		// description of all {color, input, depth/stencil} attachments of the render pass
-		std::vector<vk::AttachmentDescription> attachmentDescriptions {};
+		Vector<vk::AttachmentDescription> attachmentDescriptions {};
 
 		// individual references to color attachments (of a subpass)
-		std::vector<vk::AttachmentReference> colorAttachmentReferences {};
+		Vector<vk::AttachmentReference> colorAttachmentReferences {};
 		// individual reference to depth attachment (of a subpass)
 		vk::AttachmentReference depthStencilAttachmentRef;
 
@@ -70,7 +70,7 @@ namespace vkcv {
 
 		const auto &attachments = config.getAttachments();
 
-		std::vector<vk::ImageLayout> layouts;
+		Vector<vk::ImageLayout> layouts;
 		layouts.reserve(attachments.size());
 
 		for (uint32_t i = 0; i < attachments.size(); i++) {
@@ -137,7 +137,7 @@ namespace vkcv {
 		return pass.m_Config;
 	}
 
-	const std::vector<vk::ImageLayout> &PassManager::getLayouts(const PassHandle &handle) const {
+	const Vector<vk::ImageLayout> &PassManager::getLayouts(const PassHandle &handle) const {
 		auto &pass = (*this) [handle];
 		return pass.m_Layouts;
 	}
diff --git a/src/vkcv/PassManager.hpp b/src/vkcv/PassManager.hpp
index fefbffae..227d936e 100644
--- a/src/vkcv/PassManager.hpp
+++ b/src/vkcv/PassManager.hpp
@@ -1,9 +1,10 @@
 #pragma once
 
-#include <vector>
 #include <vulkan/vulkan.hpp>
 
 #include "HandleManager.hpp"
+
+#include "vkcv/Container.hpp"
 #include "vkcv/PassConfig.hpp"
 
 namespace vkcv {
@@ -11,7 +12,7 @@ namespace vkcv {
 	struct PassEntry {
 		vk::RenderPass m_Handle;
 		PassConfig m_Config;
-		std::vector<vk::ImageLayout> m_Layouts;
+		Vector<vk::ImageLayout> m_Layouts;
 	};
 
 	/**
@@ -45,7 +46,7 @@ namespace vkcv {
 
 		[[nodiscard]] const PassConfig &getPassConfig(const PassHandle &handle) const;
 
-		[[nodiscard]] const std::vector<vk::ImageLayout> &
+		[[nodiscard]] const Vector<vk::ImageLayout> &
 		getLayouts(const PassHandle &handle) const;
 	};
 
diff --git a/src/vkcv/PipelineConfig.cpp b/src/vkcv/PipelineConfig.cpp
index e6fb1ceb..a7a8f612 100644
--- a/src/vkcv/PipelineConfig.cpp
+++ b/src/vkcv/PipelineConfig.cpp
@@ -6,7 +6,7 @@ namespace vkcv {
 	PipelineConfig::PipelineConfig() : m_ShaderProgram(), m_DescriptorSetLayouts() {}
 
 	PipelineConfig::PipelineConfig(const ShaderProgram &program,
-								   const std::vector<DescriptorSetLayoutHandle> &layouts) :
+								   const Vector<DescriptorSetLayoutHandle> &layouts) :
 		m_ShaderProgram(program),
 		m_DescriptorSetLayouts(layouts) {}
 
@@ -23,7 +23,7 @@ namespace vkcv {
 	}
 
 	void
-	PipelineConfig::addDescriptorSetLayouts(const std::vector<DescriptorSetLayoutHandle> &layouts) {
+	PipelineConfig::addDescriptorSetLayouts(const Vector<DescriptorSetLayoutHandle> &layouts) {
 		m_DescriptorSetLayouts.reserve(m_DescriptorSetLayouts.size() + layouts.size());
 
 		for (const auto &layout : layouts) {
@@ -31,7 +31,7 @@ namespace vkcv {
 		}
 	}
 
-	const std::vector<DescriptorSetLayoutHandle> &PipelineConfig::getDescriptorSetLayouts() const {
+	const Vector<DescriptorSetLayoutHandle> &PipelineConfig::getDescriptorSetLayouts() const {
 		return m_DescriptorSetLayouts;
 	}
 
diff --git a/src/vkcv/QueueManager.cpp b/src/vkcv/QueueManager.cpp
index d292383a..711087eb 100644
--- a/src/vkcv/QueueManager.cpp
+++ b/src/vkcv/QueueManager.cpp
@@ -15,9 +15,9 @@ namespace vkcv {
 	 * vk::QueueFlagBits::eGraphics)
 	 * @return An array of queue handles based on the @p queuePairs
 	 */
-	std::vector<Queue> getQueues(const vk::Device &device,
-								 const std::vector<std::pair<int, int>> &queuePairs) {
-		std::vector<Queue> queues;
+	Vector<Queue> getQueues(const vk::Device &device,
+								 const Vector<std::pair<int, int>> &queuePairs) {
+		Vector<Queue> queues;
 
 		for (auto q : queuePairs) {
 			const int queueFamilyIndex = q.first; // the queueIndex of the queue family
@@ -31,13 +31,13 @@ namespace vkcv {
 	}
 
 	QueueManager QueueManager::create(vk::Device device,
-									  const std::vector<std::pair<int, int>> &queuePairsGraphics,
-									  const std::vector<std::pair<int, int>> &queuePairsCompute,
-									  const std::vector<std::pair<int, int>> &queuePairsTransfer) {
+									  const Vector<std::pair<int, int>> &queuePairsGraphics,
+									  const Vector<std::pair<int, int>> &queuePairsCompute,
+									  const Vector<std::pair<int, int>> &queuePairsTransfer) {
 
-		std::vector<Queue> graphicsQueues = getQueues(device, queuePairsGraphics);
-		std::vector<Queue> computeQueues = getQueues(device, queuePairsCompute);
-		std::vector<Queue> transferQueues = getQueues(device, queuePairsTransfer);
+		Vector<Queue> graphicsQueues = getQueues(device, queuePairsGraphics);
+		Vector<Queue> computeQueues = getQueues(device, queuePairsCompute);
+		Vector<Queue> transferQueues = getQueues(device, queuePairsTransfer);
 
 		return QueueManager(std::move(graphicsQueues), std::move(computeQueues),
 							std::move(transferQueues), 0);
@@ -45,7 +45,7 @@ namespace vkcv {
 
 	uint32_t QueueManager::checkSurfaceSupport(const vk::PhysicalDevice &physicalDevice,
 											   const vk::SurfaceKHR &surface) {
-		std::vector<vk::QueueFamilyProperties> qFamilyProperties =
+		Vector<vk::QueueFamilyProperties> qFamilyProperties =
 			physicalDevice.getQueueFamilyProperties();
 
 		for (uint32_t i = 0; i < qFamilyProperties.size(); i++) {
@@ -62,9 +62,9 @@ namespace vkcv {
 		return 0;
 	}
 
-	QueueManager::QueueManager(std::vector<Queue> &&graphicsQueues,
-							   std::vector<Queue> &&computeQueues,
-							   std::vector<Queue> &&transferQueues, size_t presentIndex) :
+	QueueManager::QueueManager(Vector<Queue> &&graphicsQueues,
+							   Vector<Queue> &&computeQueues,
+							   Vector<Queue> &&transferQueues, size_t presentIndex) :
 		m_graphicsQueues(graphicsQueues),
 		m_computeQueues(computeQueues), m_transferQueues(transferQueues),
 		m_presentIndex(presentIndex) {}
@@ -73,15 +73,15 @@ namespace vkcv {
 		return m_graphicsQueues [m_presentIndex];
 	}
 
-	const std::vector<Queue> &QueueManager::getGraphicsQueues() const {
+	const Vector<Queue> &QueueManager::getGraphicsQueues() const {
 		return m_graphicsQueues;
 	}
 
-	const std::vector<Queue> &QueueManager::getComputeQueues() const {
+	const Vector<Queue> &QueueManager::getComputeQueues() const {
 		return m_computeQueues;
 	}
 
-	const std::vector<Queue> &QueueManager::getTransferQueues() const {
+	const Vector<Queue> &QueueManager::getTransferQueues() const {
 		return m_transferQueues;
 	}
 
diff --git a/src/vkcv/RayTracingPipelineConfig.cpp b/src/vkcv/RayTracingPipelineConfig.cpp
index cec0bdec..776340ea 100644
--- a/src/vkcv/RayTracingPipelineConfig.cpp
+++ b/src/vkcv/RayTracingPipelineConfig.cpp
@@ -8,7 +8,7 @@ namespace vkcv {
 	
 	RayTracingPipelineConfig::RayTracingPipelineConfig(
 			const ShaderProgram &program,
-			const std::vector<DescriptorSetLayoutHandle> &layouts) :
+			const Vector<DescriptorSetLayoutHandle> &layouts) :
 			PipelineConfig(program, layouts) {}
 	
 }
diff --git a/src/vkcv/RayTracingPipelineManager.cpp b/src/vkcv/RayTracingPipelineManager.cpp
index 147c216d..aae73acf 100644
--- a/src/vkcv/RayTracingPipelineManager.cpp
+++ b/src/vkcv/RayTracingPipelineManager.cpp
@@ -66,7 +66,7 @@ namespace vkcv {
 			vk::PipelineShaderStageCreateInfo* outCreateInfo) {
 		
 		assert(outCreateInfo);
-		std::vector<uint32_t> code = shaderProgram.getShaderBinary(stage);
+		Vector<uint32_t> code = shaderProgram.getShaderBinary(stage);
 		vk::ShaderModuleCreateInfo vertexModuleInfo(
 				{},
 				code.size() * sizeof(uint32_t),
@@ -98,7 +98,7 @@ namespace vkcv {
 	 */
 	static vk::PipelineLayoutCreateInfo createPipelineLayoutCreateInfo(
 			const RayTracingPipelineConfig &config,
-			const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts) {
+			const Vector<vk::DescriptorSetLayout> &descriptorSetLayouts) {
 		static vk::PushConstantRange pushConstantRange;
 		
 		const size_t pushConstantsSize = config.getShaderProgram().getPushConstantsSize();
@@ -142,7 +142,7 @@ namespace vkcv {
 		uint32_t closestHitStageIndex = VK_SHADER_UNUSED_KHR;
 		uint32_t intersectionStageIndex = VK_SHADER_UNUSED_KHR;
 		
-		std::vector<vk::PipelineShaderStageCreateInfo> shaderStages;
+		Vector<vk::PipelineShaderStageCreateInfo> shaderStages;
 		shaderStages.reserve(
 				(existsRayGenShader? 1 : 0)
 				+ (existsRayAnyHitShader? 1 : 0)
@@ -159,7 +159,7 @@ namespace vkcv {
 			shaderStages.clear();
 		};
 		
-		std::vector<vk::RayTracingShaderGroupCreateInfoKHR> shaderGroups;
+		Vector<vk::RayTracingShaderGroupCreateInfoKHR> shaderGroups;
 		shaderGroups.reserve(
 				(existsRayGenShader? 1 : 0)
 				+ (existsRayMissShader? 1 : 0)
@@ -312,7 +312,7 @@ namespace vkcv {
 			);
 		}
 		
-		std::vector<vk::DescriptorSetLayout> descriptorSetLayouts;
+		Vector<vk::DescriptorSetLayout> descriptorSetLayouts;
 		descriptorSetLayouts.reserve(config.getDescriptorSetLayouts().size());
 		for (const auto &handle : config.getDescriptorSetLayouts()) {
 			descriptorSetLayouts.push_back(
@@ -374,7 +374,7 @@ namespace vkcv {
 				rayTracingPipelineProperties.shaderGroupHandleSize * shaderGroups.size()
 		);
 		
-		std::vector<uint8_t> shaderGroupHandleEntries;
+		Vector<uint8_t> shaderGroupHandleEntries;
 		shaderGroupHandleEntries.resize(shaderGroupHandlesSize);
 		
 		if (getCore().getContext().getDevice().getRayTracingShaderGroupHandlesKHR(
diff --git a/src/vkcv/RayTracingPipelineManager.hpp b/src/vkcv/RayTracingPipelineManager.hpp
index f2b9da8b..84097bd0 100644
--- a/src/vkcv/RayTracingPipelineManager.hpp
+++ b/src/vkcv/RayTracingPipelineManager.hpp
@@ -6,13 +6,15 @@
  * @brief Creation and handling of ray tracing pipelines
  */
 
+#include <vulkan/vulkan.hpp>
+
 #include "BufferManager.hpp"
 #include "DescriptorSetLayoutManager.hpp"
 #include "HandleManager.hpp"
 #include "PassManager.hpp"
+
+#include "vkcv/Container.hpp"
 #include "vkcv/RayTracingPipelineConfig.hpp"
-#include <vector>
-#include <vulkan/vulkan.hpp>
 
 namespace vkcv {
 	
diff --git a/src/vkcv/SamplerManager.hpp b/src/vkcv/SamplerManager.hpp
index 5ac03303..e9b07347 100644
--- a/src/vkcv/SamplerManager.hpp
+++ b/src/vkcv/SamplerManager.hpp
@@ -1,10 +1,10 @@
 #pragma once
 
-#include <vector>
 #include <vulkan/vulkan.hpp>
 
 #include "HandleManager.hpp"
 
+#include "vkcv/Container.hpp"
 #include "vkcv/Sampler.hpp"
 
 namespace vkcv {
diff --git a/src/vkcv/ShaderProgram.cpp b/src/vkcv/ShaderProgram.cpp
index 099af639..2deeeb81 100644
--- a/src/vkcv/ShaderProgram.cpp
+++ b/src/vkcv/ShaderProgram.cpp
@@ -58,7 +58,7 @@ namespace vkcv {
 			vkcv_log(LogLevel::WARNING, "Overwriting existing shader stage");
 		}
 
-		std::vector<uint32_t> shaderCode;
+		Vector<uint32_t> shaderCode;
 		if ((!readBinaryFromFile(path, shaderCode)) || (shaderCode.empty())) {
 			return false;
 		}
@@ -68,7 +68,7 @@ namespace vkcv {
 		return true;
 	}
 
-	const std::vector<uint32_t> &ShaderProgram::getShaderBinary(ShaderStage stage) const {
+	const Vector<uint32_t> &ShaderProgram::getShaderBinary(ShaderStage stage) const {
 		return m_Shaders.at(stage);
 	}
 
@@ -109,7 +109,7 @@ namespace vkcv {
 
 		// reflect descriptor sets (uniform buffer, storage buffer, sampler, sampled image, storage
 		// image)
-		std::vector<std::pair<uint32_t, DescriptorBinding>> bindings;
+		Vector<std::pair<uint32_t, DescriptorBinding>> bindings;
 
 		for (uint32_t i = 0; i < resources.uniform_buffers.size(); i++) {
 			auto &u = resources.uniform_buffers [i];
@@ -318,7 +318,7 @@ namespace vkcv {
 		return m_VertexAttachments;
 	}
 
-	const std::unordered_map<uint32_t, DescriptorBindings> &
+	const Dictionary<uint32_t, DescriptorBindings> &
 	ShaderProgram::getReflectedDescriptors() const {
 		return m_DescriptorSets;
 	}
diff --git a/src/vkcv/SwapchainManager.cpp b/src/vkcv/SwapchainManager.cpp
index 7586f9ad..c8984530 100644
--- a/src/vkcv/SwapchainManager.cpp
+++ b/src/vkcv/SwapchainManager.cpp
@@ -114,7 +114,7 @@ namespace vkcv {
 	 */
 	static vk::SurfaceFormatKHR chooseSurfaceFormat(vk::PhysicalDevice physicalDevice,
 													vk::SurfaceKHR surface) {
-		std::vector<vk::SurfaceFormatKHR> availableFormats =
+		Vector<vk::SurfaceFormatKHR> availableFormats =
 			physicalDevice.getSurfaceFormatsKHR(surface);
 
 		for (const auto &availableFormat : availableFormats) {
@@ -137,7 +137,7 @@ namespace vkcv {
 	 */
 	static vk::PresentModeKHR choosePresentMode(vk::PhysicalDevice physicalDevice,
 												vk::SurfaceKHR surface) {
-		std::vector<vk::PresentModeKHR> availablePresentModes =
+		Vector<vk::PresentModeKHR> availablePresentModes =
 			physicalDevice.getSurfacePresentModesKHR(surface);
 
 		for (const auto &availablePresentMode : availablePresentModes) {
@@ -301,18 +301,18 @@ namespace vkcv {
 		return (*this) [handle].m_ColorSpace;
 	}
 
-	std::vector<vk::Image>
+	Vector<vk::Image>
 	SwapchainManager::getSwapchainImages(const SwapchainHandle &handle) const {
 		return getCore().getContext().getDevice().getSwapchainImagesKHR(
 			(*this) [handle].m_Swapchain);
 	}
 
-	std::vector<vk::ImageView>
+	Vector<vk::ImageView>
 	SwapchainManager::createSwapchainImageViews(SwapchainHandle &handle) {
-		std::vector<vk::Image> images = getSwapchainImages(handle);
+		Vector<vk::Image> images = getSwapchainImages(handle);
 		auto &swapchain = (*this) [handle];
 
-		std::vector<vk::ImageView> imageViews;
+		Vector<vk::ImageView> imageViews;
 		imageViews.reserve(images.size());
 		// here can be swizzled with vk::ComponentSwizzle if needed
 		vk::ComponentMapping componentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG,
diff --git a/src/vkcv/SwapchainManager.hpp b/src/vkcv/SwapchainManager.hpp
index 27262ec6..6cd6f21f 100644
--- a/src/vkcv/SwapchainManager.hpp
+++ b/src/vkcv/SwapchainManager.hpp
@@ -6,13 +6,13 @@
  */
 
 #include <atomic>
-#include <vector>
 #include <vulkan/vulkan.hpp>
 
-#include "vkcv/Window.hpp"
-
 #include "HandleManager.hpp"
 
+#include "vkcv/Container.hpp"
+#include "vkcv/Window.hpp"
+
 namespace vkcv {
 
 	const uint32_t MIN_SURFACE_SIZE = 2;
@@ -145,7 +145,7 @@ namespace vkcv {
 		 * @param handle of the swapchain
 		 * @return a vector of the swapchain images
 		 */
-		[[nodiscard]] std::vector<vk::Image>
+		[[nodiscard]] Vector<vk::Image>
 		getSwapchainImages(const SwapchainHandle &handle) const;
 
 		/**
@@ -153,7 +153,7 @@ namespace vkcv {
 		 * @param handle of the swapchain which ImageViews should be created
 		 * @return a ov ImageViews of the swapchain
 		 */
-		[[nodiscard]] std::vector<vk::ImageView> createSwapchainImageViews(SwapchainHandle &handle);
+		[[nodiscard]] Vector<vk::ImageView> createSwapchainImageViews(SwapchainHandle &handle);
 	};
 
 } // namespace vkcv
\ No newline at end of file
diff --git a/src/vkcv/VertexData.cpp b/src/vkcv/VertexData.cpp
index 70c99059..ac1600e1 100644
--- a/src/vkcv/VertexData.cpp
+++ b/src/vkcv/VertexData.cpp
@@ -13,10 +13,10 @@ namespace vkcv {
 		return binding;
 	}
 
-	VertexData::VertexData(const std::vector<VertexBufferBinding> &bindings) :
+	VertexData::VertexData(const Vector<VertexBufferBinding> &bindings) :
 		m_bindings(bindings), m_indices(), m_indexBitCount(IndexBitCount::Bit16), m_count(0) {}
 
-	const std::vector<VertexBufferBinding> &VertexData::getVertexBufferBindings() const {
+	const Vector<VertexBufferBinding> &VertexData::getVertexBufferBindings() const {
 		return m_bindings;
 	}
 
diff --git a/src/vkcv/Window.cpp b/src/vkcv/Window.cpp
index f989f1b8..78afe0f2 100644
--- a/src/vkcv/Window.cpp
+++ b/src/vkcv/Window.cpp
@@ -1,8 +1,8 @@
 
 #include <GLFW/glfw3.h>
 #include <thread>
-#include <vector>
 
+#include "vkcv/Container.hpp"
 #include "vkcv/Window.hpp"
 
 namespace vkcv {
@@ -56,7 +56,7 @@ namespace vkcv {
 		}
 	}
 
-	static std::vector<GLFWwindow*> s_Windows;
+	static Vector<GLFWwindow*> s_Windows;
 
 	void Window_onGamepadEvent(int gamepadIndex) {
 		Window::getFocusedWindow().e_gamepad(gamepadIndex);
@@ -181,8 +181,8 @@ namespace vkcv {
 		}
 	}
 
-	const std::vector<std::string> &Window::getExtensions() {
-		static std::vector<std::string> extensions;
+	const Vector<std::string> &Window::getExtensions() {
+		static Vector<std::string> extensions;
 
 		if (extensions.empty()) {
 			if (s_Windows.empty()) {
diff --git a/src/vkcv/WindowManager.cpp b/src/vkcv/WindowManager.cpp
index 077b9ec3..331826e6 100644
--- a/src/vkcv/WindowManager.cpp
+++ b/src/vkcv/WindowManager.cpp
@@ -56,8 +56,8 @@ namespace vkcv {
 		return *(*this) [handle];
 	}
 
-	std::vector<WindowHandle> WindowManager::getWindowHandles() const {
-		std::vector<WindowHandle> handles;
+	Vector<WindowHandle> WindowManager::getWindowHandles() const {
+		Vector<WindowHandle> handles;
 
 		for (size_t id = 0; id < getCount(); id++) {
 			if (getById(id)->isOpen()) {
diff --git a/src/vkcv/WindowManager.hpp b/src/vkcv/WindowManager.hpp
index 71b107c7..51b45f63 100644
--- a/src/vkcv/WindowManager.hpp
+++ b/src/vkcv/WindowManager.hpp
@@ -3,13 +3,13 @@
 #include <GLFW/glfw3.h>
 #include <memory>
 #include <string>
-#include <vector>
-
-#include "vkcv/Window.hpp"
 
 #include "HandleManager.hpp"
 #include "SwapchainManager.hpp"
 
+#include "vkcv/Container.hpp"
+#include "vkcv/Window.hpp"
+
 namespace vkcv {
 
 	/**
@@ -64,7 +64,7 @@ namespace vkcv {
 		 *
 		 * @return List of window handles
 		 */
-		[[nodiscard]] std::vector<WindowHandle> getWindowHandles() const;
+		[[nodiscard]] Vector<WindowHandle> getWindowHandles() const;
 	};
 
 } // namespace vkcv
\ No newline at end of file
-- 
GitLab