diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index 2d5dcd0f5e00e0870ea3b9cb4ea8d20f2f623c3d..817c3f5840895158f621ae0c022df07c3c97978a 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -270,6 +270,12 @@ namespace vkcv
 			const uint32_t dispatchCount[3],
 			const std::vector<DescriptorSetUsage> &descriptorSetUsages,
 			const PushConstants& pushConstants);
+		
+		void recordBeginDebugLabel(const CommandStreamHandle &cmdStream,
+								   const std::string& label,
+								   const std::array<float, 4>& color);
+		
+		void recordEndDebugLabel(const CommandStreamHandle &cmdStream);
 
 		void recordComputeIndirectDispatchToCmdStream(
 			const CommandStreamHandle               cmdStream,
@@ -320,6 +326,14 @@ namespace vkcv
 		
 		void recordBlitImage(const CommandStreamHandle& cmdStream, const ImageHandle& src, const ImageHandle& dst,
 							 SamplerFilterType filterType);
+	
+		void setDebugLabel(const BufferHandle &handle, const std::string &label);
+		void setDebugLabel(const PassHandle &handle, const std::string &label);
+		void setDebugLabel(const PipelineHandle &handle, const std::string &label);
+		void setDebugLabel(const DescriptorSetHandle &handle, const std::string &label);
+		void setDebugLabel(const SamplerHandle &handle, const std::string &label);
+		void setDebugLabel(const ImageHandle &handle, const std::string &label);
+		void setDebugLabel(const CommandStreamHandle &handle, const std::string &label);
 		
     };
 }
diff --git a/modules/asset_loader/src/vkcv/asset/asset_loader.cpp b/modules/asset_loader/src/vkcv/asset/asset_loader.cpp
index 571d965a400de7197b6fb46f163c4099a5b353f1..2ca35bdab791ea18a67f33e53ab17fc485cbad02 100644
--- a/modules/asset_loader/src/vkcv/asset/asset_loader.cpp
+++ b/modules/asset_loader/src/vkcv/asset/asset_loader.cpp
@@ -107,7 +107,7 @@ namespace vkcv::asset {
 									const std::vector<fx::gltf::BufferView> &bufferViews,
 									std::vector<VertexAttribute> &dst) {
 		for (const auto &attrib : src) {
-			VertexAttribute att;
+			VertexAttribute att {};
 			
 			if (attrib.first == "POSITION") {
 				att.type = PrimitiveType::POSITION;
@@ -282,7 +282,7 @@ namespace vkcv::asset {
 	 * modes, default is repeat, the other modes aren't available.
 	 */
 	static vkcv::asset::Sampler loadSampler(const fx::gltf::Sampler &src) {
-		Sampler dst;
+		Sampler dst {};
 		
 		dst.minLOD = 0;
 		dst.maxLOD = VK_LOD_CLAMP_NONE;
@@ -414,13 +414,13 @@ namespace vkcv::asset {
 			}
 	
 			if (posAccessor.bufferView >= sceneObjects.bufferViews.size()) {
-				vkcv_log(LogLevel::ERROR, "Access to bufferView out of bounds: %lu",
+				vkcv_log(LogLevel::ERROR, "Access to bufferView out of bounds: %d",
 						posAccessor.bufferView);
 				return ASSET_ERROR;
 			}
 			const fx::gltf::BufferView& vertexBufferView = sceneObjects.bufferViews[posAccessor.bufferView];
 			if (vertexBufferView.buffer >= sceneObjects.buffers.size()) {
-				vkcv_log(LogLevel::ERROR, "Access to buffer out of bounds: %lu",
+				vkcv_log(LogLevel::ERROR, "Access to buffer out of bounds: %d",
 						vertexBufferView.buffer);
 				return ASSET_ERROR;
 			}
@@ -571,7 +571,7 @@ namespace vkcv::asset {
 					texture.sampler = -1;
 				} else
 				if (static_cast<size_t>(textureObject.sampler) >= scene.samplers.size()) {
-					vkcv_log(LogLevel::ERROR, "Sampler of texture '%s' missing (%s) %d",
+					vkcv_log(LogLevel::ERROR, "Sampler of texture '%s' missing (%s)",
 							 textureObject.name.c_str(), path.c_str());
 					return ASSET_ERROR;
 				} else {
diff --git a/modules/scene/src/vkcv/scene/Scene.cpp b/modules/scene/src/vkcv/scene/Scene.cpp
index d6fa2a40a494ef57386e52a306e962a460c66dd6..c0065af5928d9ad2e2c9afd1a1ea44c35d94d799 100644
--- a/modules/scene/src/vkcv/scene/Scene.cpp
+++ b/modules/scene/src/vkcv/scene/Scene.cpp
@@ -116,6 +116,10 @@ namespace vkcv::scene {
 								size_t							 pushConstantsSizePerDrawcall,
 								const RecordMeshDrawcallFunction &record,
 								const std::vector<ImageHandle>   &renderTargets) {
+		m_core->recordBeginDebugLabel(cmdStream, "vkcv::scene::Scene", {
+			0.0f, 1.0f, 0.0f, 1.0f
+		});
+		
 		PushConstants pushConstants (pushConstantsSizePerDrawcall);
 		std::vector<DrawcallInfo> drawcalls;
 		size_t count = 0;
@@ -137,6 +141,8 @@ namespace vkcv::scene {
 				drawcalls,
 				renderTargets
 		);
+		
+		m_core->recordEndDebugLabel(cmdStream);
 	}
 	
 	Scene Scene::create(Core& core) {
diff --git a/modules/upscaling/src/vkcv/upscaling/BilinearUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/BilinearUpscaling.cpp
index 9c36acf5d050e3f4f19223020357b6c32534a2de..54df1829006964b30cc1831dc7115e9d5d222a51 100644
--- a/modules/upscaling/src/vkcv/upscaling/BilinearUpscaling.cpp
+++ b/modules/upscaling/src/vkcv/upscaling/BilinearUpscaling.cpp
@@ -7,7 +7,13 @@ namespace vkcv::upscaling {
 	
 	void BilinearUpscaling::recordUpscaling(const CommandStreamHandle &cmdStream, const ImageHandle &input,
 											const ImageHandle &output) {
+		m_core.recordBeginDebugLabel(cmdStream, "vkcv::upscaling::BilinearUpscaling", {
+			0.0f, 0.0f, 1.0f, 1.0f
+		});
+		
 		m_core.recordBlitImage(cmdStream, input, output, SamplerFilterType::LINEAR);
+		
+		m_core.recordEndDebugLabel(cmdStream);
 	}
 
 }
diff --git a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
index 85908a76d51082b09cf5e6b09ac01fbbd4ef9266..b11051273ba6f9e56d3a537931f9d33fff657e43 100644
--- a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
+++ b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
@@ -245,6 +245,10 @@ namespace vkcv::upscaling {
 	void FSRUpscaling::recordUpscaling(const CommandStreamHandle& cmdStream,
 									   const ImageHandle& input,
 									   const ImageHandle& output) {
+		m_core.recordBeginDebugLabel(cmdStream, "vkcv::upscaling::FSRUpscaling", {
+			1.0f, 0.0f, 0.0f, 1.0f
+		});
+		
 		const uint32_t inputWidth = m_core.getImageWidth(input);
 		const uint32_t inputHeight = m_core.getImageHeight(input);
 		
@@ -361,6 +365,8 @@ namespace vkcv::upscaling {
 					PushConstants(0)
 			);
 		}
+		
+		m_core.recordEndDebugLabel(cmdStream);
 	}
 	
 	bool FSRUpscaling::isHdrEnabled() const {
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index 76e860dea27126c943fa6b6a7d5a01f174203920..d1d856b8863badef8a1b01f6277979cde019c4e0 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -29,6 +29,8 @@ int main(int argc, const char** argv) {
 	uint16_t indices[3] = { 0, 1, 2 };
 	triangleIndexBuffer.fill(&indices[0], sizeof(indices));
 
+	core.setDebugLabel(triangleIndexBuffer.getHandle(), "Triangle Index Buffer");
+	
 	// an example attachment for passes that output to the window
 	const vkcv::AttachmentDescription present_color_attachment(
 		vkcv::AttachmentOperation::STORE,
@@ -43,6 +45,8 @@ int main(int argc, const char** argv) {
 		std::cout << "Error. Could not create renderpass. Exiting." << std::endl;
 		return EXIT_FAILURE;
 	}
+	
+	core.setDebugLabel(trianglePass, "Triangle Pass");
 
 	vkcv::ShaderProgram triangleShaderProgram;
 	vkcv::shader::GLSLCompiler compiler;
@@ -75,12 +79,15 @@ int main(int argc, const char** argv) {
 		return EXIT_FAILURE;
 	}
 	
+	core.setDebugLabel(trianglePipeline, "Triangle Pipeline");
+	
 	auto start = std::chrono::system_clock::now();
 
 	const vkcv::Mesh renderMesh({}, triangleIndexBuffer.getVulkanHandle(), 3);
 	vkcv::DrawcallInfo drawcall(renderMesh, {},1);
 
 	const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
+	core.setDebugLabel(swapchainInput, "Swapchain Image");
 
     vkcv::camera::CameraManager cameraManager(window);
     uint32_t camIndex0 = cameraManager.addCamera(vkcv::camera::ControllerType::PILOT);
@@ -110,6 +117,7 @@ int main(int argc, const char** argv) {
 		pushConstants.appendDrawcall(mvp);
 		
 		auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
+		core.setDebugLabel(cmdStream, "Render Commands");
 
 		core.recordDrawcallsToCmdStream(
 			cmdStream,
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index 851f08a4c0894b6f6753270ba068e9b2dd544574..095fdd2e98e7f48a14c3426c89e3f336b848b463 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -263,9 +263,8 @@ namespace vkcv
 		vk::Device                      device) {
 
 		std::vector<vk::ImageView> attachmentsViews;
-		for (const ImageHandle handle : renderTargets) {
-			vk::ImageView targetHandle = imageManager.getVulkanImageView(handle);
-			attachmentsViews.push_back(targetHandle);
+		for (const ImageHandle& handle : renderTargets) {
+			attachmentsViews.push_back(imageManager.getVulkanImageView(handle));
 		}
 
 		const std::array<uint32_t, 2> widthHeight = getWidthHeightFromRenderTargets(renderTargets, swapchain, imageManager);
@@ -287,8 +286,7 @@ namespace vkcv
 		ImageManager&                   imageManager,
 		const vk::CommandBuffer         cmdBuffer) {
 
-		for (const ImageHandle handle : renderTargets) {
-			vk::ImageView targetHandle = imageManager.getVulkanImageView(handle);
+		for (const ImageHandle& handle : renderTargets) {
 			const bool isDepthImage = isDepthFormat(imageManager.getImageFormat(handle));
 			const vk::ImageLayout targetLayout =
 				isDepthImage ? vk::ImageLayout::eDepthStencilAttachmentOptimal : vk::ImageLayout::eColorAttachmentOptimal;
@@ -501,7 +499,50 @@ namespace vkcv
 
 		recordCommandsToStream(cmdStreamHandle, submitFunction, nullptr);
 	}
+	
+	void Core::recordBeginDebugLabel(const CommandStreamHandle &cmdStream,
+									 const std::string& label,
+									 const std::array<float, 4>& color) {
+#ifndef NDEBUG
+		static PFN_vkCmdBeginDebugUtilsLabelEXT beginDebugLabel = reinterpret_cast<PFN_vkCmdBeginDebugUtilsLabelEXT>(
+				m_Context.getDevice().getProcAddr("vkCmdBeginDebugUtilsLabelEXT")
+		);
+		
+		if (!beginDebugLabel) {
+			return;
+		}
+		
+		auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) {
+			const vk::DebugUtilsLabelEXT debug (
+					label.c_str(),
+					color
+			);
+			
+			beginDebugLabel(cmdBuffer, &(static_cast<const VkDebugUtilsLabelEXT&>(debug)));
+		};
 
+		recordCommandsToStream(cmdStream, submitFunction, nullptr);
+#endif
+	}
+	
+	void Core::recordEndDebugLabel(const CommandStreamHandle &cmdStream) {
+#ifndef NDEBUG
+		static PFN_vkCmdEndDebugUtilsLabelEXT endDebugLabel = reinterpret_cast<PFN_vkCmdEndDebugUtilsLabelEXT>(
+				m_Context.getDevice().getProcAddr("vkCmdEndDebugUtilsLabelEXT")
+		);
+		
+		if (!endDebugLabel) {
+			return;
+		}
+		
+		auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) {
+			endDebugLabel(cmdBuffer);
+		};
+
+		recordCommandsToStream(cmdStream, submitFunction, nullptr);
+#endif
+	}
+	
 	void Core::recordComputeIndirectDispatchToCmdStream(
 		const CommandStreamHandle               cmdStream,
 		const PipelineHandle                    computePipeline,
@@ -820,4 +861,141 @@ namespace vkcv
 		}, nullptr);
 	}
 	
+	static void setDebugObjectLabel(const vk::Device& device, const vk::ObjectType& type,
+									uint64_t handle, const std::string& label) {
+#ifndef NDEBUG
+		static PFN_vkSetDebugUtilsObjectNameEXT setDebugLabel = reinterpret_cast<PFN_vkSetDebugUtilsObjectNameEXT>(
+				device.getProcAddr("vkSetDebugUtilsObjectNameEXT")
+		);
+		
+		if (!setDebugLabel) {
+			return;
+		}
+		
+		const vk::DebugUtilsObjectNameInfoEXT debug (
+				type,
+				handle,
+				label.c_str()
+		);
+		
+		setDebugLabel(device, &(static_cast<const VkDebugUtilsObjectNameInfoEXT&>(debug)));
+#endif
+	}
+	
+	void Core::setDebugLabel(const BufferHandle &handle, const std::string &label) {
+		if (!handle) {
+			vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle");
+			return;
+		}
+		
+		setDebugObjectLabel(
+				m_Context.getDevice(),
+				vk::ObjectType::eBuffer,
+				reinterpret_cast<uint64_t>(static_cast<VkBuffer>(
+						m_BufferManager->getBuffer(handle)
+				)),
+				label
+		);
+	}
+	
+	void Core::setDebugLabel(const PassHandle &handle, const std::string &label) {
+		if (!handle) {
+			vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle");
+			return;
+		}
+		
+		setDebugObjectLabel(
+				m_Context.getDevice(),
+				vk::ObjectType::eRenderPass,
+				reinterpret_cast<uint64_t>(static_cast<VkRenderPass>(
+						m_PassManager->getVkPass(handle)
+				)),
+				label
+		);
+	}
+	
+	void Core::setDebugLabel(const PipelineHandle &handle, const std::string &label) {
+		if (!handle) {
+			vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle");
+			return;
+		}
+		
+		setDebugObjectLabel(
+				m_Context.getDevice(),
+				vk::ObjectType::ePipeline,
+				reinterpret_cast<uint64_t>(static_cast<VkPipeline>(
+						m_PipelineManager->getVkPipeline(handle)
+				)),
+				label
+		);
+	}
+	
+	void Core::setDebugLabel(const DescriptorSetHandle &handle, const std::string &label) {
+		if (!handle) {
+			vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle");
+			return;
+		}
+		
+		setDebugObjectLabel(
+				m_Context.getDevice(),
+				vk::ObjectType::eDescriptorSet,
+				reinterpret_cast<uint64_t>(static_cast<VkDescriptorSet>(
+						m_DescriptorManager->getDescriptorSet(handle).vulkanHandle
+				)),
+				label
+		);
+	}
+	
+	void Core::setDebugLabel(const SamplerHandle &handle, const std::string &label) {
+		if (!handle) {
+			vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle");
+			return;
+		}
+		
+		setDebugObjectLabel(
+				m_Context.getDevice(),
+				vk::ObjectType::eSampler,
+				reinterpret_cast<uint64_t>(static_cast<VkSampler>(
+						m_SamplerManager->getVulkanSampler(handle)
+				)),
+				label
+		);
+	}
+	
+	void Core::setDebugLabel(const ImageHandle &handle, const std::string &label) {
+		if (!handle) {
+			vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle");
+			return;
+		} else
+		if (handle.isSwapchainImage()) {
+			vkcv_log(LogLevel::WARNING, "Can't set debug label to swapchain image");
+			return;
+		}
+		
+		setDebugObjectLabel(
+				m_Context.getDevice(),
+				vk::ObjectType::eImage,
+				reinterpret_cast<uint64_t>(static_cast<VkImage>(
+						m_ImageManager->getVulkanImage(handle)
+				)),
+				label
+		);
+	}
+	
+	void Core::setDebugLabel(const CommandStreamHandle &handle, const std::string &label) {
+		if (!handle) {
+			vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle");
+			return;
+		}
+		
+		setDebugObjectLabel(
+				m_Context.getDevice(),
+				vk::ObjectType::eCommandBuffer,
+				reinterpret_cast<uint64_t>(static_cast<VkCommandBuffer>(
+						m_CommandStreamManager->getStreamCommandBuffer(handle)
+				)),
+				label
+		);
+	}
+	
 }
diff --git a/src/vkcv/DrawcallRecording.cpp b/src/vkcv/DrawcallRecording.cpp
index d89ace3859717f753534402507a713a78bfb6876..ca8b248a06d06c7aed6f8d0e9760645b727a5993 100644
--- a/src/vkcv/DrawcallRecording.cpp
+++ b/src/vkcv/DrawcallRecording.cpp
@@ -52,8 +52,6 @@ namespace vkcv {
         }
     }
 
-
-
     struct MeshShaderFunctions
     {
         PFN_vkCmdDrawMeshTasksNV cmdDrawMeshTasks                           = nullptr;
diff --git a/src/vkcv/QueueManager.cpp b/src/vkcv/QueueManager.cpp
index 15e958b0de929e53170324ade27a9b3663a15d6a..79e15c9b00e4c67fb956bdcd0e8b1ff05261b2f1 100644
--- a/src/vkcv/QueueManager.cpp
+++ b/src/vkcv/QueueManager.cpp
@@ -44,7 +44,7 @@ namespace vkcv {
         std::vector<int> prios;
         for(auto flag: queueFlags) {
             int prioCount = 0;
-            for (int i = 0; i < qFamilyProperties.size(); i++) {
+            for (size_t i = 0; i < qFamilyProperties.size(); i++) {
                 prioCount += (static_cast<uint32_t>(flag & qFamilyProperties[i].queueFlags) != 0) * qFamilyProperties[i].queueCount;
             }
             prios.push_back(prioCount);
@@ -65,10 +65,14 @@ namespace vkcv {
         std::vector<std::vector<int>> queueFamilyStatus, initialQueueFamilyStatus;
 
         for (auto qFamily : qFamilyProperties) {
-            int graphicsCount = int(static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eGraphics) != 0) * qFamily.queueCount;
-            int computeCount = int(static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eCompute) != 0) * qFamily.queueCount;
-            int transferCount = int(static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eTransfer) != 0) * qFamily.queueCount;
-            queueFamilyStatus.push_back({graphicsCount, computeCount, transferCount});
+            auto graphicsCount = static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eGraphics) != 0? qFamily.queueCount : 0;
+			auto computeCount = static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eCompute) != 0? qFamily.queueCount : 0;
+			auto transferCount = static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eTransfer) != 0? qFamily.queueCount : 0;
+            queueFamilyStatus.push_back({
+				static_cast<int>(graphicsCount),
+				static_cast<int>(computeCount),
+				static_cast<int>(transferCount)
+			});
         }
 
         initialQueueFamilyStatus = queueFamilyStatus;