diff --git a/include/vkcv/BufferManager.hpp b/include/vkcv/BufferManager.hpp
index a390a2ff3be7f84b0c12f065398f9e40a42017e0..9eb80d70862a79a01593e6fe4c3aabe98d253ac8 100644
--- a/include/vkcv/BufferManager.hpp
+++ b/include/vkcv/BufferManager.hpp
@@ -132,6 +132,9 @@ namespace vkcv
 		 */
 		void unmapBuffer(const BufferHandle& handle);
 		
+		void recordBufferMemoryBarrier(
+			const BufferHandle& handle,
+			vk::CommandBuffer cmdBuffer);
 	};
 	
 }
diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index af186fe222fc17ac7bc676e4f2c9ed8f82e04c00..3d21e4bbfffef180c62a10b61add2ac015e52aa9 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -276,5 +276,6 @@ namespace vkcv
 		void prepareImageForSampling(const CommandStreamHandle cmdStream, const ImageHandle image);
 		void prepareImageForStorage(const CommandStreamHandle cmdStream, const ImageHandle image);
 		void recordImageMemoryBarrier(const CommandStreamHandle cmdStream, const ImageHandle image);
-    };
+		void recordBufferMemoryBarrier(const CommandStreamHandle cmdStream, const BufferHandle buffer);
+	};
 }
diff --git a/projects/voxelization/resources/shaders/voxel.inc b/projects/voxelization/resources/shaders/voxel.inc
new file mode 100644
index 0000000000000000000000000000000000000000..5e56878aca5a13b9ac41949ce89bf8709429382a
--- /dev/null
+++ b/projects/voxelization/resources/shaders/voxel.inc
@@ -0,0 +1,8 @@
+struct VoxelInfo{
+    vec3 offset;
+    float extent;
+};
+
+uint flattenVoxelUVToIndex(ivec3 UV, ivec3 voxelImageSize){
+    return UV.x + UV.y * voxelImageSize.x + UV.z *  voxelImageSize.x*  voxelImageSize.y;
+}
\ No newline at end of file
diff --git a/projects/voxelization/resources/shaders/voxelBufferToImage.comp b/projects/voxelization/resources/shaders/voxelBufferToImage.comp
new file mode 100644
index 0000000000000000000000000000000000000000..4c5d73c05ab95a979fdd78e852e9c60c7820ac2a
--- /dev/null
+++ b/projects/voxelization/resources/shaders/voxelBufferToImage.comp
@@ -0,0 +1,22 @@
+#version 450
+#extension GL_GOOGLE_include_directive : enable
+#include "voxel.inc"
+
+layout(set=0, binding=0) buffer voxelBuffer{
+    uint isFilled[];
+};
+
+layout(set=0, binding=1, r8) uniform image3D voxelImage;
+
+layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
+
+void main(){
+
+    ivec3 voxelImageSize = imageSize(voxelImage);
+    if(any(greaterThanEqual(gl_GlobalInvocationID, voxelImageSize))){
+        return;
+    }
+    ivec3 UV = ivec3(gl_GlobalInvocationID);
+    uint flatIndex = flattenVoxelUVToIndex(UV, voxelImageSize);
+    imageStore(voxelImage, UV, vec4(isFilled[flatIndex], vec3(0)));
+}
\ No newline at end of file
diff --git a/projects/voxelization/resources/shaders/voxelInfo.inc b/projects/voxelization/resources/shaders/voxelInfo.inc
deleted file mode 100644
index c8ef9c6c7272a44b212a9578fd5aa234e23924c2..0000000000000000000000000000000000000000
--- a/projects/voxelization/resources/shaders/voxelInfo.inc
+++ /dev/null
@@ -1,4 +0,0 @@
-struct VoxelInfo{
-    vec3 offset;
-    float extent;
-};
\ No newline at end of file
diff --git a/projects/voxelization/resources/shaders/voxelReset.comp b/projects/voxelization/resources/shaders/voxelReset.comp
index ca67b74cf66428f13da62e073a247d59695cc7d3..bbbc296571458f2116d2dcfbf53749d43d23ca27 100644
--- a/projects/voxelization/resources/shaders/voxelReset.comp
+++ b/projects/voxelization/resources/shaders/voxelReset.comp
@@ -1,13 +1,19 @@
-#version 440
+#version 450
 
-layout(set=0, binding=0, r8) uniform image3D voxelImage;
+layout(set=0, binding=0) buffer voxelizationBuffer{
+    uint isFilled[];
+};
 
-layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
+layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
+
+layout( push_constant ) uniform constants{
+    int voxelCount;
+};
 
 void main(){
 
-    if(any(greaterThanEqual(gl_GlobalInvocationID, imageSize(voxelImage)))){
+    if(gl_GlobalInvocationID.x> voxelCount){
         return;
     }  
-    imageStore(voxelImage, ivec3(gl_GlobalInvocationID), vec4(0.f));
+    isFilled[gl_GlobalInvocationID.x] = 0;
 }
\ No newline at end of file
diff --git a/projects/voxelization/resources/shaders/voxelVisualisation.vert b/projects/voxelization/resources/shaders/voxelVisualisation.vert
index 9884087de536eddd827ee443a30d64a8c65317a7..0b1bb57e1b37348e877281af7e09343a4b348dd1 100644
--- a/projects/voxelization/resources/shaders/voxelVisualisation.vert
+++ b/projects/voxelization/resources/shaders/voxelVisualisation.vert
@@ -2,7 +2,7 @@
 #extension GL_ARB_separate_shader_objects : enable
 #extension GL_GOOGLE_include_directive : enable
 
-#include "voxelInfo.inc"
+#include "voxel.inc"
 
 layout(location = 0) out float passCubeHalf;
 
diff --git a/projects/voxelization/resources/shaders/voxelization.frag b/projects/voxelization/resources/shaders/voxelization.frag
index 0b946fbb8664da0a2300725d26595ca7372f2ac2..9be9c259d2d57e3cae6f1710b2c650060c2dad40 100644
--- a/projects/voxelization/resources/shaders/voxelization.frag
+++ b/projects/voxelization/resources/shaders/voxelization.frag
@@ -2,15 +2,20 @@
 #extension GL_ARB_separate_shader_objects : enable
 #extension GL_GOOGLE_include_directive : enable
 
-#include "voxelInfo.inc"
+#include "voxel.inc"
 
 layout(location = 0) in vec3 passPos;
 
-layout(set=0, binding=0, r8) uniform image3D  voxelImage;
+layout(set=0, binding=0) buffer voxelizationBuffer{
+    uint isFilled[];
+};
+
 layout(set=0, binding=1) uniform voxelizationInfo{
     VoxelInfo voxelInfo;
 };
 
+layout(set=0, binding=2, r8) uniform image3D voxelImage;
+
 vec3 worldToVoxelCoordinates(vec3 world, VoxelInfo info){
     return (world - info.offset) / info.extent + 0.5f;
 }
@@ -21,10 +26,11 @@ ivec3 voxelCoordinatesToUV(vec3 voxelCoordinates, ivec3 voxelImageResolution){
 
 void main()	{
     vec3 voxelCoordinates = worldToVoxelCoordinates(passPos, voxelInfo);
-    ivec3 voxeImageSize = imageSize(voxelImage);
-    ivec3 UV = voxelCoordinatesToUV(voxelCoordinates, voxeImageSize);
-    if(any(lessThan(UV, ivec3(0))) || any(greaterThanEqual(UV, voxeImageSize))){
+    ivec3 voxelImageSize = imageSize(voxelImage);
+    ivec3 UV = voxelCoordinatesToUV(voxelCoordinates, voxelImageSize);
+    if(any(lessThan(UV, ivec3(0))) || any(greaterThanEqual(UV, voxelImageSize))){
         return;
     }
-    imageStore(voxelImage, UV, vec4(1));
+    uint flatIndex = flattenVoxelUVToIndex(UV, voxelImageSize);
+    isFilled[flatIndex] = 1;
 }
\ No newline at end of file
diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp
index 6559fbf2e73c43391633f0c7340a3d38caa93b42..17a9d82d1c881b9c53d6af637d4d6838d1916f34 100644
--- a/projects/voxelization/src/Voxelization.cpp
+++ b/projects/voxelization/src/Voxelization.cpp
@@ -48,17 +48,28 @@ vkcv::ShaderProgram loadVoxelResetShader() {
 	return shader;
 }
 
+vkcv::ShaderProgram loadVoxelBufferToImageShader() {
+	vkcv::shader::GLSLCompiler compiler;
+	vkcv::ShaderProgram shader;
+	compiler.compile(vkcv::ShaderStage::COMPUTE, "resources/shaders/voxelBufferToImage.comp",
+		[&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
+		shader.addShader(shaderStage, path);
+	});
+	return shader;
+}
+
 const uint32_t voxelResolution = 32;
 const size_t voxelCount = voxelResolution * voxelResolution * voxelResolution;
 const vk::Format voxelizationDummyFormat = vk::Format::eR8Unorm;
 
 Voxelization::Voxelization(vkcv::Core* corePtr, const Dependencies& dependencies) 
-	: 
+	:
 	m_corePtr(corePtr), 
 	m_voxelImage(m_corePtr->createImage(vk::Format::eR8Unorm, voxelResolution, voxelResolution, voxelResolution, true)),
 	m_dummyRenderTarget(m_corePtr->createImage(voxelizationDummyFormat, voxelResolution, voxelResolution, 1, false, true)),
 	m_voxelInfoBuffer(m_corePtr->createBuffer<VoxelizationInfo>(vkcv::BufferType::UNIFORM, 1)),
-	m_visualisationIndexBuffer(m_corePtr->createBuffer<uint16_t>(vkcv::BufferType::INDEX, voxelCount)) {
+	m_visualisationIndexBuffer(m_corePtr->createBuffer<uint16_t>(vkcv::BufferType::INDEX, voxelCount)),
+	m_voxelBuffer(m_corePtr->createBuffer<VoxelBufferContent>(vkcv::BufferType::STORAGE, voxelCount)){
 
 	const vkcv::ShaderProgram voxelizationShader = loadVoxelizationShader();
 
@@ -84,8 +95,9 @@ Voxelization::Voxelization(vkcv::Core* corePtr, const Dependencies& dependencies
 	m_voxelizationPipe = m_corePtr->createGraphicsPipeline(voxelizationPipeConfig);
 
 	vkcv::DescriptorWrites voxelizationDescriptorWrites;
-	voxelizationDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(0, m_voxelImage.getHandle()) };
+	voxelizationDescriptorWrites.storageBufferWrites = { vkcv::StorageBufferDescriptorWrite(0, m_voxelBuffer.getHandle()) };
 	voxelizationDescriptorWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(1, m_voxelInfoBuffer.getHandle()) };
+	voxelizationDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, m_voxelImage.getHandle()) };
 	m_corePtr->writeDescriptorSet(m_voxelizationDescriptorSet, voxelizationDescriptorWrites);
 
 	vkcv::ShaderProgram voxelVisualisationShader = loadVoxelVisualisationShader();
@@ -130,7 +142,7 @@ Voxelization::Voxelization(vkcv::Core* corePtr, const Dependencies& dependencies
 
 	vkcv::DescriptorWrites voxelVisualisationDescriptorWrite;
 	voxelVisualisationDescriptorWrite.storageImageWrites = 
-	{ vkcv::StorageImageDescriptorWrite(0,  m_voxelImage.getHandle()) };
+	{ vkcv::StorageImageDescriptorWrite(0, m_voxelImage.getHandle()) };
 	voxelVisualisationDescriptorWrite.uniformBufferWrites = 
 	{ vkcv::UniformBufferDescriptorWrite(1, m_voxelInfoBuffer.getHandle()) };
 	m_corePtr->writeDescriptorSet(m_visualisationDescriptorSet, voxelVisualisationDescriptorWrite);
@@ -145,8 +157,21 @@ Voxelization::Voxelization(vkcv::Core* corePtr, const Dependencies& dependencies
 		{ m_corePtr->getDescriptorSet(m_voxelResetDescriptorSet).layout });
 
 	vkcv::DescriptorWrites resetVoxelWrites;
-	resetVoxelWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(0, m_voxelImage.getHandle()) };
+	resetVoxelWrites.storageBufferWrites = { vkcv::StorageBufferDescriptorWrite(0, m_voxelBuffer.getHandle()) };
 	m_corePtr->writeDescriptorSet(m_voxelResetDescriptorSet, resetVoxelWrites);
+
+
+	vkcv::ShaderProgram bufferToImageShader = loadVoxelBufferToImageShader();
+
+	m_bufferToImageDescriptorSet = m_corePtr->createDescriptorSet(bufferToImageShader.getReflectedDescriptors()[0]);
+	m_bufferToImagePipe = m_corePtr->createComputePipeline(
+		bufferToImageShader,
+		{ m_corePtr->getDescriptorSet(m_bufferToImageDescriptorSet).layout });
+
+	vkcv::DescriptorWrites bufferToImageDescriptorWrites;
+	bufferToImageDescriptorWrites.storageBufferWrites = { vkcv::StorageBufferDescriptorWrite(0, m_voxelBuffer.getHandle()) };
+	bufferToImageDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(1, m_voxelImage.getHandle()) };
+	m_corePtr->writeDescriptorSet(m_bufferToImageDescriptorSet, bufferToImageDescriptorWrites);
 }
 
 void Voxelization::voxelizeMeshes(
@@ -184,11 +209,11 @@ void Voxelization::voxelizeMeshes(
 	const vkcv::PushConstantData voxelizationPushConstantData((void*)voxelizationMatrices.data(), 2 * sizeof(glm::mat4));
 
 	// reset voxels
-	const uint32_t resetVoxelGroupSize[3] = { 4, 4, 4 };
+	const uint32_t resetVoxelGroupSize = 64;
 	uint32_t resetVoxelDispatchCount[3];
-	for (int i = 0; i < 3; i++) {
-		resetVoxelDispatchCount[i] = glm::ceil(voxelResolution / float(resetVoxelGroupSize[i]));
-	}
+	resetVoxelDispatchCount[0] = glm::ceil(voxelCount / float(resetVoxelGroupSize));
+	resetVoxelDispatchCount[1] = 1;
+	resetVoxelDispatchCount[2] = 1;
 
 	m_corePtr->prepareImageForStorage(cmdStream, m_voxelImage.getHandle());
 	m_corePtr->recordComputeDispatchToCmdStream(
@@ -197,8 +222,9 @@ void Voxelization::voxelizeMeshes(
 		resetVoxelDispatchCount,
 		{ vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_voxelResetDescriptorSet).vulkanHandle) },
 		vkcv::PushConstantData(nullptr, 0));
-	m_corePtr->recordImageMemoryBarrier(cmdStream, m_voxelImage.getHandle());
+	m_corePtr->recordBufferMemoryBarrier(cmdStream, m_voxelBuffer.getHandle());
 
+	// voxelization
 	std::vector<vkcv::DrawcallInfo> drawcalls;
 	for (const auto& mesh : meshes) {
 		drawcalls.push_back(vkcv::DrawcallInfo(
@@ -206,7 +232,6 @@ void Voxelization::voxelizeMeshes(
 			{ vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_voxelizationDescriptorSet).vulkanHandle) }));
 	}
 
-	// voxelization
 	m_corePtr->recordDrawcallsToCmdStream(
 		cmdStream,
 		m_voxelizationPass,
@@ -214,6 +239,21 @@ void Voxelization::voxelizeMeshes(
 		voxelizationPushConstantData,
 		drawcalls,
 		{ m_dummyRenderTarget.getHandle() });
+
+	// buffer to image
+	const uint32_t bufferToImageGroupSize[3] = { 4, 4, 4 };
+	uint32_t bufferToImageDispatchCount[3];
+	for (int i = 0; i < 3; i++) {
+		bufferToImageDispatchCount[i] = glm::ceil(voxelResolution / float(bufferToImageGroupSize[i]));
+	}
+
+	m_corePtr->recordComputeDispatchToCmdStream(
+		cmdStream,
+		m_bufferToImagePipe,
+		bufferToImageDispatchCount,
+		{ vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_bufferToImageDescriptorSet).vulkanHandle) },
+		vkcv::PushConstantData(nullptr, 0));
+
 	m_corePtr->recordImageMemoryBarrier(cmdStream, m_voxelImage.getHandle());
 }
 
diff --git a/projects/voxelization/src/Voxelization.hpp b/projects/voxelization/src/Voxelization.hpp
index 7b569db2834abcd19540d1cf6b87863ca5d8767a..db1f1d85ee1e2d937e0bff84c81265fe2b32e611 100644
--- a/projects/voxelization/src/Voxelization.hpp
+++ b/projects/voxelization/src/Voxelization.hpp
@@ -25,7 +25,13 @@ public:
 private:
 	vkcv::Core* m_corePtr;
 
-	vkcv::Image                 m_voxelImage;
+	struct VoxelBufferContent{
+		uint32_t isFilled;
+	};
+
+	vkcv::Image                         m_voxelImage;
+    vkcv::Buffer<VoxelBufferContent>    m_voxelBuffer;
+
 	vkcv::Image                 m_dummyRenderTarget;
 	vkcv::PassHandle            m_voxelizationPass;
 	vkcv::PipelineHandle        m_voxelizationPipe;
@@ -34,6 +40,9 @@ private:
 	vkcv::PipelineHandle        m_voxelResetPipe;
 	vkcv::DescriptorSetHandle   m_voxelResetDescriptorSet;
 
+	vkcv::PipelineHandle        m_bufferToImagePipe;
+	vkcv::DescriptorSetHandle   m_bufferToImageDescriptorSet;
+
 	vkcv::PassHandle            m_visualisationPass;
 	vkcv::PipelineHandle        m_visualisationPipe;
 	vkcv::Buffer<uint16_t>      m_visualisationIndexBuffer;
diff --git a/src/vkcv/BufferManager.cpp b/src/vkcv/BufferManager.cpp
index 6d494c4ec90726d46039007607464378624f1c75..4df411c193acffa42401e4f5932d97f531cac9c9 100644
--- a/src/vkcv/BufferManager.cpp
+++ b/src/vkcv/BufferManager.cpp
@@ -5,6 +5,7 @@
 
 #include "vkcv/BufferManager.hpp"
 #include "vkcv/Core.hpp"
+#include <vkcv/Logger.hpp>
 
 namespace vkcv {
 	
@@ -335,4 +336,33 @@ namespace vkcv {
 		}
 	}
 
+	void BufferManager ::recordBufferMemoryBarrier(const BufferHandle& handle, vk::CommandBuffer cmdBuffer) {
+
+		const uint64_t id = handle.getId();
+
+		if (id >= m_buffers.size()) {
+			vkcv_log(vkcv::LogLevel::ERROR, "Invalid buffer handle");
+			return;
+		}
+
+		auto& buffer = m_buffers[id];
+		
+		vk::BufferMemoryBarrier memoryBarrier(
+			vk::AccessFlagBits::eMemoryWrite, 
+			vk::AccessFlagBits::eMemoryRead,
+			0,
+			0,
+			buffer.m_handle,
+			0,
+			buffer.m_size);
+
+		cmdBuffer.pipelineBarrier(
+			vk::PipelineStageFlagBits::eTopOfPipe,
+			vk::PipelineStageFlagBits::eBottomOfPipe,
+			{},
+			nullptr,
+			memoryBarrier,
+			nullptr);
+	}
+
 }
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index 1531bc2b77fb24db407e1f31d3bac200fe4c1bd3..86d8b518bb5ddb4056d03e4ccecdffc6a710acb0 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -501,4 +501,10 @@ namespace vkcv
 			m_ImageManager->recordImageMemoryBarrier(image, cmdBuffer);
 		}, nullptr);
 	}
+
+	void Core::recordBufferMemoryBarrier(const CommandStreamHandle cmdStream, const BufferHandle buffer) {
+		recordCommandsToStream(cmdStream, [buffer, this](const vk::CommandBuffer cmdBuffer) {
+			m_BufferManager->recordBufferMemoryBarrier(buffer, cmdBuffer);
+		}, nullptr);
+	}
 }