diff --git a/projects/voxelization/resources/shaders/sky.frag b/projects/voxelization/resources/shaders/sky.frag
new file mode 100644
index 0000000000000000000000000000000000000000..2a3b2ad03e1936641a565b2f3fbd1f19f186ff7a
--- /dev/null
+++ b/projects/voxelization/resources/shaders/sky.frag
@@ -0,0 +1,13 @@
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(location = 0) out vec3 outColor;
+
+layout( push_constant ) uniform constants{
+    vec3 skyColor;
+    float skyStrength;
+};
+
+void main()	{
+    outColor = skyColor * skyStrength;
+}
\ No newline at end of file
diff --git a/projects/voxelization/resources/shaders/sky.vert b/projects/voxelization/resources/shaders/sky.vert
new file mode 100644
index 0000000000000000000000000000000000000000..686e6f352e9bb1054656f58340a9cfc9b55fcff4
--- /dev/null
+++ b/projects/voxelization/resources/shaders/sky.vert
@@ -0,0 +1,12 @@
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+const vec2 positions[3] = {
+    vec2(-1, -1),
+    vec2(-1, 4),
+    vec2(4, -1)
+};
+
+void main()	{
+	gl_Position = vec4(positions[gl_VertexIndex], 1, 1);
+}
\ No newline at end of file
diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp
index fa2b921d9eb88a6f526617e95ec5e5f66bbe808b..daf1211f4d728e7dd180fba06c7164cbd70de30b 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -286,6 +286,52 @@ int main(int argc, const char** argv) {
 		return EXIT_FAILURE;
 	}
 
+	// sky
+	struct SkySettings {
+		glm::vec3   color;
+		float       strength;
+	};
+	SkySettings skySettings;
+	skySettings.color       = glm::vec3(0.15, 0.65, 1);
+	skySettings.strength    = 5;
+
+	const vkcv::AttachmentDescription skyColorAttachment(
+		vkcv::AttachmentOperation::STORE,
+		vkcv::AttachmentOperation::LOAD,
+		colorBufferFormat);
+
+	const vkcv::AttachmentDescription skyDepthAttachments(
+		vkcv::AttachmentOperation::STORE,
+		vkcv::AttachmentOperation::LOAD,
+		depthBufferFormat);
+
+	vkcv::PassConfig skyPassConfig({ skyColorAttachment, skyDepthAttachments }, msaa);
+	vkcv::PassHandle skyPass = core.createPass(skyPassConfig);
+
+	vkcv::ShaderProgram skyShader;
+	compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("resources/shaders/sky.vert"),
+		[&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
+		skyShader.addShader(shaderStage, path);
+	});
+	compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("resources/shaders/sky.frag"),
+		[&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
+		skyShader.addShader(shaderStage, path);
+	});
+
+	vkcv::PipelineConfig skyPipeConfig;
+	skyPipeConfig.m_ShaderProgram       = skyShader;
+	skyPipeConfig.m_Width               = windowWidth;
+	skyPipeConfig.m_Height              = windowHeight;
+	skyPipeConfig.m_PassHandle          = skyPass;
+	skyPipeConfig.m_VertexLayout        = vkcv::VertexLayout({});
+	skyPipeConfig.m_DescriptorLayouts   = {};
+	skyPipeConfig.m_UseDynamicViewport  = true;
+    skyPipeConfig.m_multisampling       = msaa;
+    skyPipeConfig.m_depthWrite          = false;
+
+	vkcv::PipelineHandle skyPipe = core.createGraphicsPipeline(skyPipeConfig);
+
+	// render targets
 	vkcv::ImageHandle depthBuffer           = core.createImage(depthBufferFormat, windowWidth, windowHeight, 1, false, false, false, msaa).getHandle();
 
     const bool colorBufferRequiresStorage   = !usingMsaa;
@@ -526,6 +572,15 @@ int main(int argc, const char** argv) {
 			voxelization.renderVoxelVisualisation(cmdStream, viewProjectionCamera, renderTargets, voxelVisualisationMip);
 		}
 
+		// sky
+		core.recordDrawcallsToCmdStream(
+			cmdStream,
+			skyPass,
+			skyPipe,
+			vkcv::PushConstantData((void*)&skySettings, sizeof(skySettings)),
+			{ vkcv::DrawcallInfo(vkcv::Mesh({}, nullptr, 3), {}) },
+			renderTargets);
+
 		const uint32_t fullscreenLocalGroupSize = 8;
 		const uint32_t fulsscreenDispatchCount[3] = {
 			static_cast<uint32_t>(glm::ceil(windowWidth  / static_cast<float>(fullscreenLocalGroupSize))),
@@ -581,6 +636,9 @@ int main(int argc, const char** argv) {
 		ImGui::DragFloat("Max shadow distance",     &maxShadowDistance);
 		maxShadowDistance = std::max(maxShadowDistance, 1.f);
 
+		ImGui::ColorEdit3("Sky color",      &skySettings.color.x);
+		ImGui::DragFloat("Sky strength",    &skySettings.strength, 0.1);
+
 		ImGui::Checkbox("Draw voxel visualisation", &renderVoxelVis);
 		ImGui::SliderInt("Visualisation mip",       &voxelVisualisationMip, 0, 7);
 		ImGui::DragFloat("Voxelization extent",     &voxelizationExtent, 1.f, 0.f);
diff --git a/src/vkcv/DrawcallRecording.cpp b/src/vkcv/DrawcallRecording.cpp
index df7b7bbcb3fe278622cd160593eb750db00ec7b1..d28ea36c6108306fe603185e9848a72af6455606 100644
--- a/src/vkcv/DrawcallRecording.cpp
+++ b/src/vkcv/DrawcallRecording.cpp
@@ -27,12 +27,14 @@ namespace vkcv {
         // char* cast because void* does not support pointer arithmetic
         const void* drawcallPushConstantData = drawcallPushConstantOffset + (char*)pushConstantData.data;
 
-        cmdBuffer.pushConstants(
-            pipelineLayout,
-            vk::ShaderStageFlagBits::eAll,
-            0,
-            pushConstantData.sizePerDrawcall,
-            drawcallPushConstantData);
+        if (pushConstantData.data && pushConstantData.sizePerDrawcall > 0) {
+            cmdBuffer.pushConstants(
+                pipelineLayout,
+                vk::ShaderStageFlagBits::eAll,
+                0,
+                pushConstantData.sizePerDrawcall,
+                drawcallPushConstantData);
+        }
 
         if (drawcall.mesh.indexBuffer) {
             cmdBuffer.bindIndexBuffer(drawcall.mesh.indexBuffer, 0, vk::IndexType::eUint16);	//FIXME: choose proper size
diff --git a/src/vkcv/PipelineManager.cpp b/src/vkcv/PipelineManager.cpp
index 1b05269a34f90d2df0f218dd6155c2ba85164db7..ca0f9225759cc7f4e16b1ba9596f2b9fd6275464 100644
--- a/src/vkcv/PipelineManager.cpp
+++ b/src/vkcv/PipelineManager.cpp
@@ -221,14 +221,18 @@ namespace vkcv
                 { 1.f,1.f,1.f,1.f }
         );
 
-		const size_t matrixPushConstantSize = config.m_ShaderProgram.getPushConstantSize();
-		const vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eAll, 0, matrixPushConstantSize);
+		const size_t pushConstantSize = config.m_ShaderProgram.getPushConstantSize();
+		const vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eAll, 0, pushConstantSize);
 
         // pipeline layout
         vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo(
 			{},
 			(config.m_DescriptorLayouts),
 			(pushConstantRange));
+		if (pushConstantSize == 0) {
+			pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
+		}
+
 
         vk::PipelineLayout vkPipelineLayout{};
         if (m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) != vk::Result::eSuccess)