diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2a0858b970dead0233261c4f3c126a0bf64732f7..5f82b94af2a98dfb6700fb098a6b2a84adf7b9a8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -45,6 +45,9 @@ endif()
 # configure everything to use the required dependencies
 include(${vkcv_config}/Libraries.cmake)
 
+# set macro to enable vulkan debug labels
+list(APPEND vkcv_definitions VULKAN_DEBUG_LABELS)
+
 # set the compile definitions aka preprocessor variables
 add_compile_definitions(${vkcv_definitions})
 
diff --git a/projects/voxelization/assets/shaders/depthToMoments.comp b/projects/voxelization/assets/shaders/depthToMoments.comp
index 5a78d0cb9b748187d12057708fcd0de7658a61ed..79e47cdef02143ed97d53e533f47e822db8c0f6f 100644
--- a/projects/voxelization/assets/shaders/depthToMoments.comp
+++ b/projects/voxelization/assets/shaders/depthToMoments.comp
@@ -28,9 +28,11 @@ void main(){
         z += texelFetch(sampler2DMS(srcTexture, depthSampler), uv, i).r;
     }
     z /= msaaCount;
-    
+    z = 2 * z - 1;	// algorithm expects depth in range [-1:1]
+	
     float   z2                  = z*z;   
     vec4    moments             = vec4(z, z2, z2*z, z2*z2);
     vec4    momentsQuantized    = quantizeMoments(moments);
+	
     imageStore(outImage, uv, momentsQuantized);
 }
\ No newline at end of file
diff --git a/projects/voxelization/assets/shaders/shadowBlur.inc b/projects/voxelization/assets/shaders/shadowBlur.inc
index 06147415f118dca9badd15813b431a68682ce0b0..ed4994ed1ace34afdafff15920d18a2433a3c0a4 100644
--- a/projects/voxelization/assets/shaders/shadowBlur.inc
+++ b/projects/voxelization/assets/shaders/shadowBlur.inc
@@ -3,7 +3,7 @@
 
 vec4 blurMomentShadowMap1D(ivec2 coord, ivec2 blurDirection, texture2D srcTexture, sampler depthSampler){
     
-    int blurRadius  = 9;
+    int blurRadius  = 7;
     int minOffset   = -(blurRadius-1) / 2;
     int maxOffset   = -minOffset;
     
diff --git a/projects/voxelization/assets/shaders/shadowBlurX.comp b/projects/voxelization/assets/shaders/shadowBlurX.comp
index 45b91aad71673347dbf607fecef92463ef1c3c88..41d127fdf5ce46dec883d49af4f284b5787d5d38 100644
--- a/projects/voxelization/assets/shaders/shadowBlurX.comp
+++ b/projects/voxelization/assets/shaders/shadowBlurX.comp
@@ -18,6 +18,6 @@ void main(){
     }
     ivec2 coord = ivec2(gl_GlobalInvocationID.xy);    
     vec4 moments = blurMomentShadowMap1D(coord, ivec2(1, 0), srcTexture, depthSampler);
-    
+    // moments = texelFetch(sampler2D(srcTexture, depthSampler), coord, 0);
     imageStore(outImage, coord, moments);
 }
\ No newline at end of file
diff --git a/projects/voxelization/assets/shaders/shadowBlurY.comp b/projects/voxelization/assets/shaders/shadowBlurY.comp
index 51d4df054b0d99e54149863a5967143518f61dd2..c1710d7d6c75ef0093fecfe708272f56f9541eaf 100644
--- a/projects/voxelization/assets/shaders/shadowBlurY.comp
+++ b/projects/voxelization/assets/shaders/shadowBlurY.comp
@@ -16,10 +16,8 @@ void main(){
     if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(outImage)))){
         return;
     }
-    ivec2 coord = ivec2(gl_GlobalInvocationID.xy);
-    vec2 pixelSize = vec2(1) / textureSize(sampler2D(srcTexture, depthSampler), 0);
-    
+    ivec2 coord = ivec2(gl_GlobalInvocationID.xy);    
     vec4 moments = blurMomentShadowMap1D(coord, ivec2(0, 1), srcTexture, depthSampler);
-    
+    // moments = texelFetch(sampler2D(srcTexture, depthSampler), coord, 0);
     imageStore(outImage, coord, moments);
 }
\ No newline at end of file
diff --git a/projects/voxelization/assets/shaders/shadowMapping.inc b/projects/voxelization/assets/shaders/shadowMapping.inc
index c56ae8985c5c5fcef780b622d8b888f1081af74c..9124a05c310c2cc16e6b02802f5adb36bde42804 100644
--- a/projects/voxelization/assets/shaders/shadowMapping.inc
+++ b/projects/voxelization/assets/shaders/shadowMapping.inc
@@ -6,7 +6,8 @@
 // nice math blob from the moment shadow mapping presentation
 float ComputeMSMShadowIntensity(vec4 _4Moments, float FragmentDepth, float DepthBias, float MomentBias)
 {
-    vec4 b=mix(_4Moments, vec4(0.5),MomentBias);
+    vec4 b=mix(_4Moments, vec4(0, 0.63, 0, 0.63),MomentBias);
+	
     vec3 z;
     z[0]=FragmentDepth-DepthBias;
     float L32D22=fma(-b[0], b[1], b[2]);
@@ -39,24 +40,23 @@ float ComputeMSMShadowIntensity(vec4 _4Moments, float FragmentDepth, float Depth
 }
 
 vec4 quantizeMoments(vec4 moments){
-    mat4 T = mat4(
-        -2.07224649,     13.7948857237,   0.105877704,   9.7924062118,
-         32.23703778,   -59.4683975703, -1.9077466311, -33.7652110555,
-        -68.571074599,   82.0359750338,  9.3496555107,  47.9456096605,
-         39.3703274134, -35.364903257,  -6.6543490743, -23.9728048165);
-    vec4 quantized = T * moments;
-    quantized[0] += 0.0359558848;
-    return quantized;
+    vec4 quantized;
+	quantized.r = 1.5 * moments.r - 2 * moments.b + 0.5;
+	quantized.g = 4   * moments.g - 4 * moments.a;
+	quantized.b = sqrt(3)/2 * moments.r - sqrt(12)/9 * moments.b + 0.5;
+	quantized.a = 0.5 * moments.g + 0.5 * moments.a;
+	
+	return quantized;
 }
 
 vec4 unquantizeMoments(vec4 moments){
-    moments[0] -= 0.0359558848;
-    mat4 T = mat4(
-        0.2227744146,  0.1549679261,  0.1451988946,  0.163127443,
-        0.0771972861,  0.1394629426,  0.2120202157,  0.2591432266,
-        0.7926986636,  0.7963415838,  0.7258694464,  0.6539092497,
-        0.0319417555,  -0.1722823173, -0.2758014811, -0.3376131734);
-    return T * moments;
+    moments -= vec4(0.5, 0, 0.5, 0);
+	vec4 unquantized;
+	unquantized.r = -1.f / 3 * moments.r + sqrt(3) * moments.b;
+	unquantized.g = 0.125 * moments.g + moments.a;
+	unquantized.b = -0.75 * moments.r + 0.75 * sqrt(3) * moments.b;
+	unquantized.a = -0.125 * moments.g + moments.a;
+	return unquantized / 0.98;	// division reduces light bleeding
 }
 
 float rescaleRange(float a, float b, float v)
@@ -78,18 +78,20 @@ float shadowTest(vec3 worldPos, LightInfo lightInfo, texture2D shadowMap, sample
     if(any(lessThan(lightPos.xy, vec2(0))) || any(greaterThan(lightPos.xy, vec2(1)))){
         return 1;
     }
-    
+	
     lightPos.z = clamp(lightPos.z, 0, 1);
+	lightPos.z = 2 * lightPos.z - 1;	// algorithm expects depth in range [-1:1]
 
     vec4 shadowMapSample = texture(sampler2D(shadowMap, shadowMapSampler), lightPos.xy);
     
     shadowMapSample = unquantizeMoments(shadowMapSample);
     
     float depthBias     = 0.f;
-    float momentBias    = 0.0003;
+    float momentBias    = 0.0006;
     
     float shadow = ComputeMSMShadowIntensity(shadowMapSample, lightPos.z, depthBias, momentBias);
-    return reduceLightBleeding(shadow, 0.1f);
+	return clamp(shadow, 0, 1);
+    // return reduceLightBleeding(shadow, 0.1f);
 }
 
 #endif // #ifndef SHADOW_MAPPING_INC
\ No newline at end of file
diff --git a/projects/voxelization/src/BloomAndFlares.cpp b/projects/voxelization/src/BloomAndFlares.cpp
index d47f61d0dc7fea4e38508b7b1d6c040595e2944a..2014d7a0219141ec6363b38a5311cb924b6b6a45 100644
--- a/projects/voxelization/src/BloomAndFlares.cpp
+++ b/projects/voxelization/src/BloomAndFlares.cpp
@@ -127,6 +127,8 @@ void BloomAndFlares::execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStre
             1
     };
 
+	p_Core->recordBeginDebugLabel(cmdStream, "Bloom downsample", { 1, 1, 1, 1 });
+
     // downsample dispatch of original color attachment
     p_Core->prepareImageForSampling(cmdStream, colorAttachment);
     p_Core->prepareImageForStorage(cmdStream, m_Blur.getHandle());
@@ -182,10 +184,14 @@ void BloomAndFlares::execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStre
         // image barrier between mips
         p_Core->recordImageMemoryBarrier(cmdStream, m_Blur.getHandle());
     }
+
+    p_Core->recordEndDebugLabel(cmdStream);
 }
 
 void BloomAndFlares::execUpsamplePipe(const vkcv::CommandStreamHandle &cmdStream)
 {
+    p_Core->recordBeginDebugLabel(cmdStream, "Bloom upsample", { 1, 1, 1, 1 });
+
     // upsample dispatch
     p_Core->prepareImageForStorage(cmdStream, m_Blur.getHandle());
 
@@ -227,10 +233,14 @@ void BloomAndFlares::execUpsamplePipe(const vkcv::CommandStreamHandle &cmdStream
         // image barrier between mips
         p_Core->recordImageMemoryBarrier(cmdStream, m_Blur.getHandle());
     }
+
+    p_Core->recordEndDebugLabel(cmdStream);
 }
 
 void BloomAndFlares::execLensFeaturePipe(const vkcv::CommandStreamHandle &cmdStream)
 {
+    p_Core->recordBeginDebugLabel(cmdStream, "Lense flare generation", { 1, 1, 1, 1 });
+
     // lens feature generation descriptor writes
     p_Core->prepareImageForSampling(cmdStream, m_Blur.getHandle());
     p_Core->prepareImageForStorage(cmdStream, m_LensFeatures.getHandle());
@@ -295,11 +305,15 @@ void BloomAndFlares::execLensFeaturePipe(const vkcv::CommandStreamHandle &cmdStr
         // image barrier between mips
         p_Core->recordImageMemoryBarrier(cmdStream, m_LensFeatures.getHandle());
     }
+
+    p_Core->recordEndDebugLabel(cmdStream);
 }
 
 void BloomAndFlares::execCompositePipe(const vkcv::CommandStreamHandle &cmdStream, const vkcv::ImageHandle& colorAttachment,
     const uint32_t attachmentWidth, const uint32_t attachmentHeight, const glm::vec3& cameraForward)
 {
+    p_Core->recordBeginDebugLabel(cmdStream, "Bloom/lense flare composition", { 1, 1, 1, 1 });
+
     p_Core->prepareImageForSampling(cmdStream, m_Blur.getHandle());
     p_Core->prepareImageForSampling(cmdStream, m_LensFeatures.getHandle());
     p_Core->prepareImageForStorage(cmdStream, colorAttachment);
@@ -329,11 +343,13 @@ void BloomAndFlares::execCompositePipe(const vkcv::CommandStreamHandle &cmdStrea
 
     // bloom composite dispatch
     p_Core->recordComputeDispatchToCmdStream(
-            cmdStream,
-            m_CompositePipe,
-            compositeDispatchCount,
-            {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_CompositeDescSet).vulkanHandle)},
-			pushConstants);
+        cmdStream,
+        m_CompositePipe,
+        compositeDispatchCount,
+        {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_CompositeDescSet).vulkanHandle)},
+        pushConstants);
+
+    p_Core->recordEndDebugLabel(cmdStream);
 }
 
 void BloomAndFlares::execWholePipeline(const vkcv::CommandStreamHandle &cmdStream, const vkcv::ImageHandle &colorAttachment, 
diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp
index d8041c1e9935d148ded8fb1ca8f0e4d8b79fce71..ce4261ff2403139d10b9d677e7aa216a3e41178f 100644
--- a/projects/voxelization/src/ShadowMapping.cpp
+++ b/projects/voxelization/src/ShadowMapping.cpp
@@ -266,6 +266,7 @@ void ShadowMapping::recordShadowMapRendering(
 		drawcalls.push_back(vkcv::DrawcallInfo(mesh, {}));
 	}
 
+	m_corePtr->recordBeginDebugLabel(cmdStream, "Shadow map depth", {1, 1, 1, 1});
 	m_corePtr->recordDrawcallsToCmdStream(
 		cmdStream,
 		m_shadowMapPass,
@@ -275,6 +276,7 @@ void ShadowMapping::recordShadowMapRendering(
 		{ m_shadowMapDepth.getHandle() },
 		windowHandle);
 	m_corePtr->prepareImageForSampling(cmdStream, m_shadowMapDepth.getHandle());
+	m_corePtr->recordEndDebugLabel(cmdStream);
 
 	// depth to moments
 	uint32_t dispatchCount[3];
@@ -287,6 +289,8 @@ void ShadowMapping::recordShadowMapRendering(
 	vkcv::PushConstants msaaPushConstants (sizeof(msaaSampleCount));
 	msaaPushConstants.appendDrawcall(msaaSampleCount);
 
+	m_corePtr->recordBeginDebugLabel(cmdStream, "Depth to moments", { 1, 1, 1, 1 });
+
 	m_corePtr->prepareImageForStorage(cmdStream, m_shadowMap.getHandle());
 	m_corePtr->recordComputeDispatchToCmdStream(
 		cmdStream,
@@ -295,6 +299,9 @@ void ShadowMapping::recordShadowMapRendering(
 		{ vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_depthToMomentsDescriptorSet).vulkanHandle) },
 		msaaPushConstants);
 	m_corePtr->prepareImageForSampling(cmdStream, m_shadowMap.getHandle());
+	m_corePtr->recordEndDebugLabel(cmdStream);
+
+	m_corePtr->recordBeginDebugLabel(cmdStream, "Moment shadow map blur", { 1, 1, 1, 1 });
 
 	// blur X
 	m_corePtr->prepareImageForStorage(cmdStream, m_shadowMapIntermediate.getHandle());
@@ -316,6 +323,8 @@ void ShadowMapping::recordShadowMapRendering(
 		vkcv::PushConstants(0));
 	m_shadowMap.recordMipChainGeneration(cmdStream);
 	m_corePtr->prepareImageForSampling(cmdStream, m_shadowMap.getHandle());
+
+	m_corePtr->recordEndDebugLabel(cmdStream);
 }
 
 vkcv::ImageHandle ShadowMapping::getShadowMap() {
diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp
index 3cbff0df84757fb370a0372ddd45a9df401d4b60..c023af21c673651984e945ab03d16280c18f0768 100644
--- a/projects/voxelization/src/Voxelization.cpp
+++ b/projects/voxelization/src/Voxelization.cpp
@@ -251,6 +251,7 @@ void Voxelization::voxelizeMeshes(
 	vkcv::PushConstants voxelCountPushConstants (sizeof(voxelCount));
 	voxelCountPushConstants.appendDrawcall(voxelCount);
 
+	m_corePtr->recordBeginDebugLabel(cmdStream, "Voxel reset", { 1, 1, 1, 1 });
 	m_corePtr->recordComputeDispatchToCmdStream(
 		cmdStream,
 		m_voxelResetPipe,
@@ -258,6 +259,7 @@ void Voxelization::voxelizeMeshes(
 		{ vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_voxelResetDescriptorSet).vulkanHandle) },
 		voxelCountPushConstants);
 	m_corePtr->recordBufferMemoryBarrier(cmdStream, m_voxelBuffer.getHandle());
+	m_corePtr->recordEndDebugLabel(cmdStream);
 
 	// voxelization
 	std::vector<vkcv::DrawcallInfo> drawcalls;
@@ -270,6 +272,7 @@ void Voxelization::voxelizeMeshes(
 			},1));
 	}
 
+	m_corePtr->recordBeginDebugLabel(cmdStream, "Voxelization", { 1, 1, 1, 1 });
 	m_corePtr->prepareImageForStorage(cmdStream, m_voxelImageIntermediate.getHandle());
 	m_corePtr->recordDrawcallsToCmdStream(
 		cmdStream,
@@ -279,6 +282,7 @@ void Voxelization::voxelizeMeshes(
 		drawcalls,
 		{ m_dummyRenderTarget.getHandle() },
 		windowHandle);
+	m_corePtr->recordEndDebugLabel(cmdStream);
 
 	// buffer to image
 	const uint32_t bufferToImageGroupSize[3] = { 4, 4, 4 };
@@ -287,6 +291,7 @@ void Voxelization::voxelizeMeshes(
 		bufferToImageDispatchCount[i] = glm::ceil(voxelResolution / float(bufferToImageGroupSize[i]));
 	}
 
+	m_corePtr->recordBeginDebugLabel(cmdStream, "Voxel buffer to image", { 1, 1, 1, 1 });
 	m_corePtr->recordComputeDispatchToCmdStream(
 		cmdStream,
 		m_bufferToImagePipe,
@@ -295,14 +300,17 @@ void Voxelization::voxelizeMeshes(
 		vkcv::PushConstants(0));
 
 	m_corePtr->recordImageMemoryBarrier(cmdStream, m_voxelImageIntermediate.getHandle());
+	m_corePtr->recordEndDebugLabel(cmdStream);
 
 	// intermediate image mipchain
+	m_corePtr->recordBeginDebugLabel(cmdStream, "Intermediate Voxel mipmap generation", { 1, 1, 1, 1 });
 	m_voxelImageIntermediate.recordMipChainGeneration(cmdStream);
 	m_corePtr->prepareImageForSampling(cmdStream, m_voxelImageIntermediate.getHandle());
+	m_corePtr->recordEndDebugLabel(cmdStream);
 
 	// secondary bounce
+	m_corePtr->recordBeginDebugLabel(cmdStream, "Voxel secondary bounce", { 1, 1, 1, 1 });
 	m_corePtr->prepareImageForStorage(cmdStream, m_voxelImage.getHandle());
-
 	m_corePtr->recordComputeDispatchToCmdStream(
 		cmdStream,
 		m_secondaryBouncePipe,
@@ -310,12 +318,14 @@ void Voxelization::voxelizeMeshes(
 		{ vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_secondaryBounceDescriptorSet).vulkanHandle) },
 		vkcv::PushConstants(0));
 	m_voxelImage.recordMipChainGeneration(cmdStream);
-
 	m_corePtr->recordImageMemoryBarrier(cmdStream, m_voxelImage.getHandle());
+	m_corePtr->recordEndDebugLabel(cmdStream);
 
 	// final image mipchain
+	m_corePtr->recordBeginDebugLabel(cmdStream, "Voxel mipmap generation", { 1, 1, 1, 1 });
 	m_voxelImage.recordMipChainGeneration(cmdStream);
 	m_corePtr->prepareImageForSampling(cmdStream, m_voxelImage.getHandle());
+	m_corePtr->recordEndDebugLabel(cmdStream);
 }
 
 void Voxelization::renderVoxelVisualisation(
@@ -344,6 +354,7 @@ void Voxelization::renderVoxelVisualisation(
 		vkcv::Mesh({}, nullptr, drawVoxelCount),
 		{ vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_visualisationDescriptorSet).vulkanHandle) },1);
 
+	m_corePtr->recordBeginDebugLabel(cmdStream, "Voxel visualisation", { 1, 1, 1, 1 });
 	m_corePtr->prepareImageForStorage(cmdStream, m_voxelImage.getHandle());
 	m_corePtr->recordDrawcallsToCmdStream(
 		cmdStream,
@@ -353,6 +364,7 @@ void Voxelization::renderVoxelVisualisation(
 		{ drawcall },
 		renderTargets,
 		windowHandle);
+	m_corePtr->recordEndDebugLabel(cmdStream);
 }
 
 void Voxelization::updateVoxelOffset(const vkcv::camera::Camera& camera) {
diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp
index a7798813a52429d31f207ae24af6a3effb90c17c..0f9e9fb870cb1277f43ea204f351103d1072f8b8 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -765,6 +765,7 @@ int main(int argc, const char** argv) {
 		
 		const std::vector<vkcv::ImageHandle>    prepassRenderTargets = { depthBuffer };
 
+		core.recordBeginDebugLabel(cmdStream, "Depth prepass", { 1, 1, 1, 1 });
 		core.recordDrawcallsToCmdStream(
 			cmdStream,
 			prepassPass,
@@ -775,6 +776,7 @@ int main(int argc, const char** argv) {
 			windowHandle);
 
 		core.recordImageMemoryBarrier(cmdStream, depthBuffer);
+		core.recordEndDebugLabel(cmdStream);
 		
 		vkcv::PushConstants pushConstants (2 * sizeof(glm::mat4));
 		
@@ -791,6 +793,7 @@ int main(int argc, const char** argv) {
 		
 		const std::vector<vkcv::ImageHandle>    renderTargets = { colorBuffer, depthBuffer };
 
+		core.recordBeginDebugLabel(cmdStream, "Forward rendering", { 1, 1, 1, 1 });
 		core.recordDrawcallsToCmdStream(
 			cmdStream,
 			forwardPass,
@@ -799,6 +802,7 @@ int main(int argc, const char** argv) {
 			drawcalls,
 			renderTargets,
 			windowHandle);
+		core.recordEndDebugLabel(cmdStream);
 
 		if (renderVoxelVis) {
 			voxelization.renderVoxelVisualisation(cmdStream, viewProjectionCamera, renderTargets, voxelVisualisationMip, windowHandle);
@@ -808,6 +812,7 @@ int main(int argc, const char** argv) {
 		skySettingsPushConstants.appendDrawcall(skySettings);
 
 		// sky
+		core.recordBeginDebugLabel(cmdStream, "Sky", { 1, 1, 1, 1 });
 		core.recordDrawcallsToCmdStream(
 			cmdStream,
 			skyPass,
@@ -816,6 +821,7 @@ int main(int argc, const char** argv) {
 			{ vkcv::DrawcallInfo(vkcv::Mesh({}, nullptr, 3), {}) },
 			renderTargets,
 			windowHandle);
+		core.recordEndDebugLabel(cmdStream);
 
 		const uint32_t fullscreenLocalGroupSize = 8;
 		
@@ -832,8 +838,8 @@ int main(int argc, const char** argv) {
 		fulsscreenDispatchCount[2] = 1;
 
 		if (usingMsaa) {
+			core.recordBeginDebugLabel(cmdStream, "MSAA resolve", { 1, 1, 1, 1 });
 			if (msaaCustomResolve) {
-
 				core.prepareImageForSampling(cmdStream, colorBuffer);
 				core.prepareImageForStorage(cmdStream, resolvedColorBuffer);
 
@@ -850,6 +856,7 @@ int main(int argc, const char** argv) {
 			else {
 				core.resolveMSAAImage(cmdStream, colorBuffer, resolvedColorBuffer);
 			}
+			core.recordEndDebugLabel(cmdStream);
 		}
 
 		bloomFlares.execWholePipeline(cmdStream, resolvedColorBuffer, fsrWidth, fsrHeight,
@@ -859,6 +866,7 @@ int main(int argc, const char** argv) {
 		core.prepareImageForStorage(cmdStream, swapBuffer);
 		core.prepareImageForSampling(cmdStream, resolvedColorBuffer);
 		
+		core.recordBeginDebugLabel(cmdStream, "Tonemapping", { 1, 1, 1, 1 });
 		core.recordComputeDispatchToCmdStream(
 			cmdStream, 
 			tonemappingPipeline, 
@@ -871,6 +879,7 @@ int main(int argc, const char** argv) {
 		
 		core.prepareImageForStorage(cmdStream, swapBuffer2);
 		core.prepareImageForSampling(cmdStream, swapBuffer);
+		core.recordEndDebugLabel(cmdStream);
 		
 		if (bilinearUpscaling) {
 			upscaling1.recordUpscaling(cmdStream, swapBuffer, swapBuffer2);
@@ -895,6 +904,7 @@ int main(int argc, const char** argv) {
 				glm::ceil(swapchainHeight / static_cast<float>(fullscreenLocalGroupSize))
 		);
 		
+		core.recordBeginDebugLabel(cmdStream, "Post Processing", { 1, 1, 1, 1 });
 		core.recordComputeDispatchToCmdStream(
 				cmdStream,
 				postEffectsPipeline,
@@ -904,6 +914,7 @@ int main(int argc, const char** argv) {
 				).vulkanHandle) },
 				timePushConstants
 		);
+		core.recordEndDebugLabel(cmdStream);
 
 		// present and end
 		core.prepareSwapchainImageForPresent(cmdStream);
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index 00ea4a9fec2bbc49ef078074ca7e13927d146b9d..a07d25836e4b541a023665e12b902b2880027eb4 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -52,7 +52,7 @@ namespace vkcv
     Core::Core(Context &&context, const CommandResources& commandResources, const SyncResources& syncResources) noexcept :
             m_Context(std::move(context)),
             m_PassManager{std::make_unique<PassManager>(m_Context.m_Device)},
-            m_PipelineManager{std::make_unique<GraphicsPipelineManager>(m_Context.m_Device)},
+            m_PipelineManager{std::make_unique<GraphicsPipelineManager>(m_Context.m_Device, m_Context.m_PhysicalDevice)},
             m_ComputePipelineManager{std::make_unique<ComputePipelineManager>(m_Context.m_Device)},
             m_DescriptorManager(std::make_unique<DescriptorManager>(m_Context.m_Device)),
             m_BufferManager{std::unique_ptr<BufferManager>(new BufferManager())},
@@ -443,7 +443,7 @@ namespace vkcv
 	void Core::recordBeginDebugLabel(const CommandStreamHandle &cmdStream,
 									 const std::string& label,
 									 const std::array<float, 4>& color) {
-#ifndef NDEBUG
+	#ifdef VULKAN_DEBUG_LABELS
 		static PFN_vkCmdBeginDebugUtilsLabelEXT beginDebugLabel = reinterpret_cast<PFN_vkCmdBeginDebugUtilsLabelEXT>(
 				m_Context.getDevice().getProcAddr("vkCmdBeginDebugUtilsLabelEXT")
 		);
@@ -462,11 +462,11 @@ namespace vkcv
 		};
 
 		recordCommandsToStream(cmdStream, submitFunction, nullptr);
-#endif
+	#endif
 	}
 	
 	void Core::recordEndDebugLabel(const CommandStreamHandle &cmdStream) {
-#ifndef NDEBUG
+	#ifdef VULKAN_DEBUG_LABELS
 		static PFN_vkCmdEndDebugUtilsLabelEXT endDebugLabel = reinterpret_cast<PFN_vkCmdEndDebugUtilsLabelEXT>(
 				m_Context.getDevice().getProcAddr("vkCmdEndDebugUtilsLabelEXT")
 		);
@@ -480,7 +480,7 @@ namespace vkcv
 		};
 
 		recordCommandsToStream(cmdStream, submitFunction, nullptr);
-#endif
+	#endif
 	}
 	
 	void Core::recordComputeIndirectDispatchToCmdStream(
@@ -864,7 +864,7 @@ namespace vkcv
 	
 	static void setDebugObjectLabel(const vk::Device& device, const vk::ObjectType& type,
 									uint64_t handle, const std::string& label) {
-#ifndef NDEBUG
+#ifndef VULKAN_DEBUG_LABELS
 		static PFN_vkSetDebugUtilsObjectNameEXT setDebugLabel = reinterpret_cast<PFN_vkSetDebugUtilsObjectNameEXT>(
 				device.getProcAddr("vkSetDebugUtilsObjectNameEXT")
 		);
diff --git a/src/vkcv/GraphicsPipelineManager.cpp b/src/vkcv/GraphicsPipelineManager.cpp
index cb7dd31dddd3a5c0742f95e8429175724aa26454..870220f45b52c022f7c2d445a40e99ab4a6a4a2f 100644
--- a/src/vkcv/GraphicsPipelineManager.cpp
+++ b/src/vkcv/GraphicsPipelineManager.cpp
@@ -5,8 +5,9 @@
 namespace vkcv
 {
 	
-	GraphicsPipelineManager::GraphicsPipelineManager(vk::Device device) noexcept :
-            m_Device{device},
+	GraphicsPipelineManager::GraphicsPipelineManager(vk::Device device, vk::PhysicalDevice physicalDevice) noexcept :
+            m_Device(device),
+            m_physicalDevice(physicalDevice),
             m_Pipelines{}
     {}
 	
@@ -237,7 +238,9 @@ namespace vkcv
 	 * @param config sets Depth Clamping and Culling Mode
 	 * @return Pipeline Rasterization State Create Info Struct
 	 */
-	vk::PipelineRasterizationStateCreateInfo createPipelineRasterizationStateCreateInfo(const GraphicsPipelineConfig &config) {
+	vk::PipelineRasterizationStateCreateInfo createPipelineRasterizationStateCreateInfo(
+		const GraphicsPipelineConfig &config,
+		const vk::PhysicalDeviceConservativeRasterizationPropertiesEXT& conservativeRasterProperties) {
 		vk::CullModeFlags cullMode;
 		switch (config.m_culling) {
 			case CullMode::None:
@@ -267,14 +270,14 @@ namespace vkcv
 				0.f,
 				1.f
 		);
-		
+
 		static vk::PipelineRasterizationConservativeStateCreateInfoEXT conservativeRasterization;
 		
 		if (config.m_UseConservativeRasterization) {
 			conservativeRasterization = vk::PipelineRasterizationConservativeStateCreateInfoEXT(
 					{},
 					vk::ConservativeRasterizationModeEXT::eOverestimate,
-					0.f
+					std::max(1 - conservativeRasterProperties.primitiveOverestimationSize, 0.f)
 			);
 			
 			pipelineRasterizationStateCreateInfo.pNext = &conservativeRasterization;
@@ -544,8 +547,13 @@ namespace vkcv
                 createPipelineViewportStateCreateInfo(config);
 
         // rasterization state
+        vk::PhysicalDeviceConservativeRasterizationPropertiesEXT    conservativeRasterProperties;
+        vk::PhysicalDeviceProperties                                deviceProperties;
+        vk::PhysicalDeviceProperties2                               deviceProperties2(deviceProperties);
+        deviceProperties2.pNext = &conservativeRasterProperties;
+        m_physicalDevice.getProperties2(&deviceProperties2);
         vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo =
-                createPipelineRasterizationStateCreateInfo(config);
+                createPipelineRasterizationStateCreateInfo(config, conservativeRasterProperties);
 
         // multisample state
         vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo =
diff --git a/src/vkcv/GraphicsPipelineManager.hpp b/src/vkcv/GraphicsPipelineManager.hpp
index a08e64939dc967511095f22862c52de05148d7e9..782603ab0e1ffa9bde05fda96c5d2d259eff1953 100644
--- a/src/vkcv/GraphicsPipelineManager.hpp
+++ b/src/vkcv/GraphicsPipelineManager.hpp
@@ -20,7 +20,7 @@ namespace vkcv
     {
     public:
 		GraphicsPipelineManager() = delete; // no default ctor
-        explicit GraphicsPipelineManager(vk::Device device) noexcept; // ctor
+        explicit GraphicsPipelineManager(vk::Device device, vk::PhysicalDevice physicalDevice) noexcept; // ctor
         ~GraphicsPipelineManager() noexcept; // dtor
 	
 		GraphicsPipelineManager(const GraphicsPipelineManager &other) = delete; // copy-ctor
@@ -71,8 +71,9 @@ namespace vkcv
 			GraphicsPipelineConfig m_config;
         };
 
-        vk::Device m_Device;
-        std::vector<GraphicsPipeline> m_Pipelines;
+        vk::Device                      m_Device;
+        vk::PhysicalDevice              m_physicalDevice; // needed to get infos to configure conservative rasterization
+        std::vector<GraphicsPipeline>   m_Pipelines;
 
         void destroyPipelineById(uint64_t id);