diff --git a/projects/voxelization/src/BloomAndFlares.cpp b/projects/voxelization/src/BloomAndFlares.cpp
index 71a09fcac55756cd616e9b55b5a3b239e1c8b5d0..4e69e5595107b435de05b177b586e61ac7a7cacb 100644
--- a/projects/voxelization/src/BloomAndFlares.cpp
+++ b/projects/voxelization/src/BloomAndFlares.cpp
@@ -16,7 +16,7 @@ BloomAndFlares::BloomAndFlares(
                                               vkcv::SamplerMipmapMode::LINEAR,
                                               vkcv::SamplerAddressMode::CLAMP_TO_EDGE)),
         m_Blur(p_Core->createImage(colorBufferFormat, width, height, 1, true, true, false)),
-        m_LensFeatures(p_Core->createImage(colorBufferFormat, width, height, 1, false, true, false))
+        m_LensFeatures(p_Core->createImage(colorBufferFormat, width, height, 1, true, true, false))
 {
     vkcv::shader::GLSLCompiler compiler;
 
@@ -49,6 +49,11 @@ BloomAndFlares::BloomAndFlares(
         m_UpsampleDescSets.push_back(
                 p_Core->createDescriptorSet(usProg.getReflectedDescriptors()[0]));
     }
+    for (uint32_t mipLevel = 0; mipLevel < m_LensFeatures.getMipCount(); mipLevel++) {
+        m_UpsampleLensFlareDescSets.push_back(
+            p_Core->createDescriptorSet(usProg.getReflectedDescriptors()[0]));
+    }
+
     m_UpsamplePipe = p_Core->createComputePipeline(
             usProg, { p_Core->getDescriptorSet(m_UpsampleDescSets[0]).layout });
 
@@ -197,18 +202,21 @@ void BloomAndFlares::execLensFeaturePipe(const vkcv::CommandStreamHandle &cmdStr
     p_Core->prepareImageForSampling(cmdStream, m_Blur.getHandle());
     p_Core->prepareImageForStorage(cmdStream, m_LensFeatures.getHandle());
 
+    const uint32_t targetMip = 2;
+    const uint32_t mipLevel = std::min(targetMip, m_LensFeatures.getMipCount());
+
     vkcv::DescriptorWrites lensFeatureWrites;
     lensFeatureWrites.sampledImageWrites = {vkcv::SampledImageDescriptorWrite(0, m_Blur.getHandle(), 0)};
     lensFeatureWrites.samplerWrites = {vkcv::SamplerDescriptorWrite(1, m_LinearSampler)};
-    lensFeatureWrites.storageImageWrites = {vkcv::StorageImageDescriptorWrite(2, m_LensFeatures.getHandle(), 0)};
+    lensFeatureWrites.storageImageWrites = {vkcv::StorageImageDescriptorWrite(2, m_LensFeatures.getHandle(), mipLevel)};
     p_Core->writeDescriptorSet(m_LensFlareDescSet, lensFeatureWrites);
 
     auto dispatchCountX  = static_cast<float>(m_Width)  / 8.0f;
     auto dispatchCountY = static_cast<float>(m_Height) / 8.0f;
     // lens feature generation dispatch
     uint32_t lensFeatureDispatchCount[3] = {
-            static_cast<uint32_t>(glm::ceil(dispatchCountX)),
-            static_cast<uint32_t>(glm::ceil(dispatchCountY)),
+            static_cast<uint32_t>(glm::ceil(dispatchCountX / std::exp2(mipLevel))),
+            static_cast<uint32_t>(glm::ceil(dispatchCountY / std::exp2(mipLevel))),
             1
     };
     p_Core->recordComputeDispatchToCmdStream(
@@ -217,6 +225,43 @@ void BloomAndFlares::execLensFeaturePipe(const vkcv::CommandStreamHandle &cmdStr
             lensFeatureDispatchCount,
             {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_LensFlareDescSet).vulkanHandle)},
             vkcv::PushConstantData(nullptr, 0));
+
+    // upsample dispatch
+    p_Core->prepareImageForStorage(cmdStream, m_LensFeatures.getHandle());
+
+    // upsample dispatch for each mip map
+    for (uint32_t i = mipLevel; i > 0; i--)
+    {
+        // mip descriptor writes
+        vkcv::DescriptorWrites mipUpsampleWrites;
+        mipUpsampleWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_LensFeatures.getHandle(), i, true) };
+        mipUpsampleWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, m_LinearSampler) };
+        mipUpsampleWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, m_LensFeatures.getHandle(), i - 1) };
+        p_Core->writeDescriptorSet(m_UpsampleLensFlareDescSets[i], mipUpsampleWrites);
+
+        auto mipDivisor = glm::pow(2.0f, static_cast<float>(i) - 1.0f);
+
+        auto upsampleDispatchX = static_cast<float>(m_Width) / mipDivisor;
+        auto upsampleDispatchY = static_cast<float>(m_Height) / mipDivisor;
+        upsampleDispatchX /= 8.0f;
+        upsampleDispatchY /= 8.0f;
+
+        const uint32_t upsampleDispatchCount[3] = {
+                static_cast<uint32_t>(glm::ceil(upsampleDispatchX)),
+                static_cast<uint32_t>(glm::ceil(upsampleDispatchY)),
+                1
+        };
+
+        p_Core->recordComputeDispatchToCmdStream(
+            cmdStream,
+            m_UpsamplePipe,
+            upsampleDispatchCount,
+            { vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_UpsampleLensFlareDescSets[i]).vulkanHandle) },
+            vkcv::PushConstantData(nullptr, 0)
+        );
+        // image barrier between mips
+        p_Core->recordImageMemoryBarrier(cmdStream, m_LensFeatures.getHandle());
+    }
 }
 
 void BloomAndFlares::execCompositePipe(const vkcv::CommandStreamHandle &cmdStream,
@@ -268,7 +313,7 @@ void BloomAndFlares::updateImageDimensions(uint32_t width, uint32_t height)
 
     p_Core->getContext().getDevice().waitIdle();
     m_Blur = p_Core->createImage(m_ColorBufferFormat, m_Width, m_Height, 1, true, true, false);
-    m_LensFeatures = p_Core->createImage(m_ColorBufferFormat, m_Width, m_Height, 1, false, true, false);
+    m_LensFeatures = p_Core->createImage(m_ColorBufferFormat, m_Width, m_Height, 1, true, true, false);
 }
 
 
diff --git a/projects/voxelization/src/BloomAndFlares.hpp b/projects/voxelization/src/BloomAndFlares.hpp
index 756b1ca154ea5232df04eb09a88bb743c5bd28aa..71ec21ebfd3dbca6cbb751772a97b7e492157676 100644
--- a/projects/voxelization/src/BloomAndFlares.hpp
+++ b/projects/voxelization/src/BloomAndFlares.hpp
@@ -30,6 +30,7 @@ private:
 
     vkcv::PipelineHandle                     m_UpsamplePipe;
     std::vector<vkcv::DescriptorSetHandle>   m_UpsampleDescSets;   // per mip desc set
+    std::vector<vkcv::DescriptorSetHandle>   m_UpsampleLensFlareDescSets;   // per mip desc set
 
     vkcv::PipelineHandle                     m_LensFlarePipe;
     vkcv::DescriptorSetHandle                m_LensFlareDescSet;