From 126a10bc22e2bcd81424766a3d65fe87fc84e78c Mon Sep 17 00:00:00 2001
From: Jens Koenen <koenen@vr.rwth-aachen.de>
Date: Wed, 4 Jan 2023 12:56:26 +0100
Subject: [PATCH] Moved computation of indirect cache from first frame to
 create.

---
 src/utility/indirect_cache.cpp | 101 +++++++++++++++++++++++++++++----
 src/utility/indirect_cache.hpp |   3 +-
 src/vr_application.cpp         |  14 +++--
 3 files changed, 102 insertions(+), 16 deletions(-)

diff --git a/src/utility/indirect_cache.cpp b/src/utility/indirect_cache.cpp
index 2ef468dd..00fb122b 100644
--- a/src/utility/indirect_cache.cpp
+++ b/src/utility/indirect_cache.cpp
@@ -244,19 +244,32 @@ void IndirectCache::destroy()
     }
 }
 
-void IndirectCache::compute_indirect(VkCommandBuffer command_buffer, lava::index frame)
+bool IndirectCache::compute_indirect(lava::index frame)
 {
-    this->submit_setup();
+    this->frame = frame;
+
+    if (!this->submit_setup())
+    {
+        return false;
+    }
 
     uint32_t batch_size = 100;
     uint32_t batch_count = this->propagation_iterations / batch_size;
     uint32_t batch_rest = this->propagation_iterations % batch_size;
 
+    if (batch_rest % 2 != 0)
+    {
+        batch_rest += 1;
+    }
+
     lava::log()->info("Computing Indirect Cache: 0%");
 
     for (uint32_t index = 0; index < batch_count; index++)
     {
-        this->submit_propagation(batch_size);
+        if (!this->submit_propagation(batch_size))
+        {
+            return false;
+        }
 
         uint32_t progress = (((index + 1) * batch_size * 100) / this->propagation_iterations);
         lava::log()->info("Computing Indirect Cache: {}%", progress);
@@ -264,17 +277,20 @@ void IndirectCache::compute_indirect(VkCommandBuffer command_buffer, lava::index
 
     if (batch_rest > 0)
     {
-        this->submit_propagation(batch_rest);
+        if (!this->submit_propagation(batch_rest))
+        {
+            return false;
+        }
 
         lava::log()->info("Computing Indirect Cache: 100%");
     }
     
-    std::vector<VkImageMemoryBarrier> final_barriers = IndirectCache::build_barriers(3, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
-    final_barriers[0].image = this->distribution_red_image[2];
-    final_barriers[1].image = this->distribution_green_image[2];
-    final_barriers[2].image = this->distribution_blue_image[2];
+    if (!this->submit_barrier())
+    {
+        return false;
+    }
 
-    vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, final_barriers.size(), final_barriers.data());
+    return true;
 }
 
 lava::descriptor::ptr IndirectCache::get_descriptor() const
@@ -1483,7 +1499,6 @@ bool IndirectCache::submit_setup()
             continue;
         }
         
-        this->frame = frame;
         this->light_index = index;
         this->capture_pass->process(this->command_buffer, 0);
         this->injection_pass->process(this->command_buffer, 0);
@@ -1683,6 +1698,72 @@ bool IndirectCache::submit_propagation(uint32_t iterations)
     return true;
 }
 
+bool IndirectCache::submit_barrier()
+{
+    VkCommandBufferBeginInfo begin_info;
+    begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+    begin_info.pNext = nullptr;
+    begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+    begin_info.pInheritanceInfo = nullptr;
+
+    if (vkBeginCommandBuffer(this->command_buffer, &begin_info) != VK_SUCCESS)
+    {
+        lava::log()->error("Can't begin command buffer of indirect cache for barrier submission!");
+
+        return false;
+    }
+
+    std::vector<VkImageMemoryBarrier> final_barriers = IndirectCache::build_barriers(3, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+    final_barriers[0].image = this->distribution_red_image[2];
+    final_barriers[1].image = this->distribution_green_image[2];
+    final_barriers[2].image = this->distribution_blue_image[2];
+
+    vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, final_barriers.size(), final_barriers.data());
+
+    if (vkEndCommandBuffer(this->command_buffer) != VK_SUCCESS)
+    {
+        lava::log()->error("Can't end command buffer of indirect cache for barrier submission!");
+
+        return false;
+    }
+
+    lava::device_ptr device = this->scene->get_light_descriptor()->get_device();
+
+    if (vkResetFences(device->get(), 1, &this->fence) != VK_SUCCESS)
+    {
+        lava::log()->error("Can't reset fence of indirect cache for barrier submission!");
+
+        return false;
+    }
+
+    VkSubmitInfo submit_info;
+    submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+    submit_info.pNext = nullptr;
+    submit_info.waitSemaphoreCount = 0;
+    submit_info.pWaitSemaphores = nullptr;
+    submit_info.pWaitDstStageMask = nullptr;
+    submit_info.commandBufferCount = 1;
+    submit_info.pCommandBuffers = &this->command_buffer;
+    submit_info.signalSemaphoreCount = 0;
+    submit_info.pSignalSemaphores = nullptr;
+
+    if (vkQueueSubmit(device->get_graphics_queue().vk_queue, 1, &submit_info, this->fence) != VK_SUCCESS)
+    {
+        lava::log()->error("Can't submit command buffer of indirect cache for barrier submission!");
+
+        return false;
+    }
+
+    if (vkWaitForFences(device->get(), 1, &this->fence, VK_TRUE, std::numeric_limits<uint64_t>::max()) != VK_SUCCESS)
+    {
+        lava::log()->error("Can't wait for completion of barrier!");
+
+        return false;
+    }
+
+    return true;
+}
+
 void IndirectCache::pipeline_geometry(VkCommandBuffer command_buffer)
 {
     std::array<uint32_t, 3> push_constants;
diff --git a/src/utility/indirect_cache.hpp b/src/utility/indirect_cache.hpp
index 055b3564..91157d56 100644
--- a/src/utility/indirect_cache.hpp
+++ b/src/utility/indirect_cache.hpp
@@ -60,7 +60,7 @@ public:
     bool create(Scene::Ptr scene, const IndirectCacheSettings& settings);
     void destroy();
 
-    void compute_indirect(VkCommandBuffer comannd_buffer, lava::index frame);
+    bool compute_indirect(lava::index frame);
 
     lava::descriptor::ptr get_descriptor() const;
     VkDescriptorSet get_descriptor_set() const;
@@ -87,6 +87,7 @@ private:
    
     bool submit_setup();
     bool submit_propagation(uint32_t iterations); //NOTE: Iterations needs to be multiple of two
+    bool submit_barrier();
 
     void pipeline_geometry(VkCommandBuffer command_buffer);
     void pipeline_capture(VkCommandBuffer command_buffer);
diff --git a/src/vr_application.cpp b/src/vr_application.cpp
index 4c1acab6..716e32fa 100644
--- a/src/vr_application.cpp
+++ b/src/vr_application.cpp
@@ -466,6 +466,15 @@ bool VRApplication::on_create()
 
             return false;
         }
+
+        this->scene->write(0);
+
+        if (!this->indirect_cache->compute_indirect(0))
+        {
+            lava::log()->error("Can't compute indirect cache!");
+
+            return false;
+        }
     }
 
     return this->create_config();
@@ -708,11 +717,6 @@ bool VRApplication::on_render(VkCommandBuffer command_buffer, lava::index frame)
         {
             this->shadow_cache->compute_shadow(command_buffer, frame);
         }
-
-        if (this->indirect_cache != nullptr)
-        {
-            this->indirect_cache->compute_indirect(command_buffer, frame);
-        }
         
         this->cache_filled = true;
     }
-- 
GitLab