diff --git a/src/utility/indirect_cache.cpp b/src/utility/indirect_cache.cpp index 37205c4990c55d427faccbe18acdbc2bdbc485ca..1c0de87ec877d9a65a899bb6a15b24a6af82e5a1 100644 --- a/src/utility/indirect_cache.cpp +++ b/src/utility/indirect_cache.cpp @@ -20,6 +20,16 @@ bool IndirectCache::create(Scene::Ptr scene, const IndirectCacheSettings& settin return false; } + if (!this->create_command_buffer(device)) + { + return false; + } + + if (!this->create_fence(device)) + { + return false; + } + if (!this->create_buffers(device, settings)) { return false; @@ -192,6 +202,14 @@ void IndirectCache::destroy() this->domain_buffer->destroy(); } + if (this->command_buffer != VK_NULL_HANDLE) + { + vkFreeCommandBuffers(device->get(), this->command_pool, 1, &this->command_buffer); + } + + vkDestroyFence(device->get(), this->fence, lava::memory::alloc()); + vkDestroyCommandPool(device->get(), this->command_pool, lava::memory::alloc()); + vkDestroySampler(device->get(), this->indirect_sampler, lava::memory::alloc()); vkDestroySampler(device->get(), this->geometry_sampler, lava::memory::alloc()); vkDestroySampler(device->get(), this->injection_sampler, lava::memory::alloc()); @@ -228,163 +246,24 @@ void IndirectCache::destroy() void IndirectCache::compute_indirect(VkCommandBuffer command_buffer, lava::index frame) { - const std::vector<SceneLight>& lights = this->scene->get_lights(); - - std::vector<VkImageMemoryBarrier> clear_begin_barriers = IndirectCache::build_barriers(5, 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - clear_begin_barriers[0].image = this->distribution_red_image[0]; - clear_begin_barriers[1].image = this->distribution_green_image[0]; - clear_begin_barriers[2].image = this->distribution_blue_image[0]; - clear_begin_barriers[3].image = this->distribution_geometry_image[0]; - clear_begin_barriers[4].image = this->distribution_geometry_image[1]; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, clear_begin_barriers.size(), clear_begin_barriers.data()); - - VkClearColorValue clear_color; - clear_color.float32[0] = 0.0f; - clear_color.float32[1] = 0.0f; - clear_color.float32[2] = 0.0f; - clear_color.float32[3] = 0.0f; - - VkImageSubresourceRange subresource_range; - subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresource_range.baseMipLevel = 0; - subresource_range.levelCount = 1; - subresource_range.baseArrayLayer = 0; - subresource_range.layerCount = 1; - - vkCmdClearColorImage(command_buffer, this->distribution_red_image[0], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &subresource_range); - vkCmdClearColorImage(command_buffer, this->distribution_green_image[0], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &subresource_range); - vkCmdClearColorImage(command_buffer, this->distribution_blue_image[0], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &subresource_range); - vkCmdClearColorImage(command_buffer, this->distribution_geometry_image[0], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &subresource_range); - vkCmdClearColorImage(command_buffer, this->distribution_geometry_image[1], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &subresource_range); - - std::vector<VkImageMemoryBarrier> clear_end_barriers = IndirectCache::build_barriers(3, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - clear_end_barriers[0].image = this->distribution_red_image[0]; - clear_end_barriers[1].image = this->distribution_green_image[0]; - clear_end_barriers[2].image = this->distribution_blue_image[0]; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, clear_end_barriers.size(), clear_end_barriers.data()); - - std::vector<VkImageMemoryBarrier> geometry_begin_barriers = IndirectCache::build_barriers(2, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL); - geometry_begin_barriers[0].image = this->distribution_geometry_image[0]; - geometry_begin_barriers[1].image = this->distribution_geometry_image[1]; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, geometry_begin_barriers.size(), geometry_begin_barriers.data()); + this->submit_setup(); - this->geometry_pass->process(command_buffer, 0); + uint32_t batch_size = 100; + uint32_t batch_count = this->propagation_iterations / batch_size; + uint32_t batch_rest = this->propagation_iterations % batch_size; - std::vector<VkImageMemoryBarrier> geometry_end_barriers = IndirectCache::build_barriers(2, 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); - geometry_end_barriers[0].image = this->distribution_geometry_image[0]; - geometry_end_barriers[1].image = this->distribution_geometry_image[1]; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, geometry_end_barriers.size(), geometry_end_barriers.data()); - - for (uint32_t index = 0; index < lights.size(); index++) + for (uint32_t index = 0; index < batch_count; index++) { - const SceneLight& light = lights[index]; - - if (light.data.type != LIGHT_TYPE_DIRECTIONAL) - { - continue; - } - - this->frame = frame; - this->light_index = index; - this->capture_pass->process(command_buffer, 0); - this->injection_pass->process(command_buffer, 0); - } + lava::log()->debug("{}", index); - //NOTE: Memory barrier for source image provieded by injection render pass - // The final image layout of distribution_..._image[0] has to be VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL - - std::vector<VkImageMemoryBarrier> copy_barriers = IndirectCache::build_barriers(3, 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - copy_barriers[0].image = this->distribution_red_image[2]; - copy_barriers[1].image = this->distribution_green_image[2]; - copy_barriers[2].image = this->distribution_blue_image[2]; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, copy_barriers.size(), copy_barriers.data()); - - VkImageSubresourceLayers subresource_layers; - subresource_layers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresource_layers.mipLevel = 0; - subresource_layers.baseArrayLayer = 0; - subresource_layers.layerCount = 1; - - VkOffset3D offset; - offset.x = 0; - offset.y = 0; - offset.z = 0; - - VkExtent3D extend; - extend.width = this->domain_indirect_resolution.x; - extend.height = this->domain_indirect_resolution.y; - extend.depth = this->domain_indirect_resolution.z; - - VkImageCopy image_copy; - image_copy.srcSubresource = subresource_layers; - image_copy.srcOffset = offset; - image_copy.dstSubresource = subresource_layers; - image_copy.dstOffset = offset; - image_copy.extent = extend; - - vkCmdCopyImage(command_buffer, this->distribution_red_image[0], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, this->distribution_red_image[2], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); - vkCmdCopyImage(command_buffer, this->distribution_green_image[0], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, this->distribution_green_image[2], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); - vkCmdCopyImage(command_buffer, this->distribution_blue_image[0], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, this->distribution_blue_image[2], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); - - std::vector<VkImageMemoryBarrier> setup_src_barriers = IndirectCache::build_barriers(3, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL); - setup_src_barriers[0].image = this->distribution_red_image[0]; - setup_src_barriers[1].image = this->distribution_green_image[0]; - setup_src_barriers[2].image = this->distribution_blue_image[0]; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, setup_src_barriers.size(), setup_src_barriers.data()); - - std::vector<VkImageMemoryBarrier> setup_dst_barriers = IndirectCache::build_barriers(3, 0, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL); - setup_dst_barriers[0].image = this->distribution_red_image[1]; - setup_dst_barriers[1].image = this->distribution_green_image[1]; - setup_dst_barriers[2].image = this->distribution_blue_image[1]; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, setup_dst_barriers.size(), setup_dst_barriers.data()); - - std::vector<VkImageMemoryBarrier> setup_indirect_barriers = IndirectCache::build_barriers(3, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL); - setup_indirect_barriers[0].image = this->distribution_red_image[2]; - setup_indirect_barriers[1].image = this->distribution_green_image[2]; - setup_indirect_barriers[2].image = this->distribution_blue_image[2]; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, setup_indirect_barriers.size(), setup_indirect_barriers.data()); - - this->propagation_pipeline->bind(command_buffer); + this->submit_propagation(batch_size); + } - for (uint32_t index = 0; index < this->propagation_iterations; index++) + if (batch_rest > 0) { - uint32_t src_index = index % 2; - uint32_t dst_index = (index + 1) % 2; - - this->propagation_layout->bind(command_buffer, this->propagation_descriptor_set[src_index], 0, {}, VK_PIPELINE_BIND_POINT_COMPUTE); - - vkCmdDispatch(command_buffer, this->domain_work_groups.x, this->domain_work_groups.y, this->domain_work_groups.z); - - std::vector<VkImageMemoryBarrier> compue_src_barriers = IndirectCache::build_barriers(3, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL); - compue_src_barriers[0].image = this->distribution_red_image[src_index]; - compue_src_barriers[1].image = this->distribution_green_image[src_index]; - compue_src_barriers[2].image = this->distribution_blue_image[src_index]; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, compue_src_barriers.size(), compue_src_barriers.data()); - - std::vector<VkImageMemoryBarrier> compute_dst_barriers = IndirectCache::build_barriers(3, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL); - compute_dst_barriers[0].image = this->distribution_red_image[dst_index]; - compute_dst_barriers[1].image = this->distribution_green_image[dst_index]; - compute_dst_barriers[2].image = this->distribution_blue_image[dst_index]; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, compute_dst_barriers.size(), compute_dst_barriers.data()); - - std::vector<VkImageMemoryBarrier> compute_indirect_barriers = IndirectCache::build_barriers(3, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL); - compute_indirect_barriers[0].image = this->distribution_red_image[2]; - compute_indirect_barriers[1].image = this->distribution_green_image[2]; - compute_indirect_barriers[2].image = this->distribution_blue_image[2]; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, compute_indirect_barriers.size(), compute_indirect_barriers.data()); + this->submit_propagation(batch_rest); } - + 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]; @@ -452,6 +331,55 @@ bool IndirectCache::compute_domain(Scene::Ptr scene, const IndirectCacheSettings return true; } +bool IndirectCache::create_command_buffer(lava::device_ptr device) +{ + VkCommandPoolCreateInfo pool_info; + pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + pool_info.pNext = nullptr; + pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + pool_info.queueFamilyIndex = device->get_graphics_queue().family; + + if(vkCreateCommandPool(device->get(), &pool_info, lava::memory::alloc(), &this->command_pool) != VK_SUCCESS) + { + lava::log()->error("Can't create command pool for indirect cache!"); + + return false; + } + + VkCommandBufferAllocateInfo buffer_info; + buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + buffer_info.pNext = nullptr; + buffer_info.commandPool = this->command_pool; + buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + buffer_info.commandBufferCount = 1; + + if (vkAllocateCommandBuffers(device->get(), &buffer_info, &this->command_buffer) != VK_SUCCESS) + { + lava::log()->error("Can't create command buffer for indirect cache!"); + + return false; + } + + return true; +} + +bool IndirectCache::create_fence(lava::device_ptr device) +{ + VkFenceCreateInfo fence_info; + fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_info.pNext = nullptr; + fence_info.flags = 0; + + if (vkCreateFence(device->get(), &fence_info, lava::memory::alloc(), &this->fence) != VK_SUCCESS) + { + lava::log()->error("Can't create fence for indirect cache!"); + + return false; + } + + return true; +} + bool IndirectCache::create_buffers(lava::device_ptr device, const IndirectCacheSettings& settings) { glsl::IndirectDomain indirect_domain; @@ -1450,6 +1378,281 @@ bool IndirectCache::create_propagation_pipeline(lava::device_ptr device) return true; } +bool IndirectCache::submit_setup() +{ + 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 during setup of indirect cache!"); + + return false; + } + + const std::vector<SceneLight>& lights = this->scene->get_lights(); + + std::vector<VkImageMemoryBarrier> clear_begin_barriers = IndirectCache::build_barriers(5, 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + clear_begin_barriers[0].image = this->distribution_red_image[0]; + clear_begin_barriers[1].image = this->distribution_green_image[0]; + clear_begin_barriers[2].image = this->distribution_blue_image[0]; + clear_begin_barriers[3].image = this->distribution_geometry_image[0]; + clear_begin_barriers[4].image = this->distribution_geometry_image[1]; + + vkCmdPipelineBarrier(this->command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, clear_begin_barriers.size(), clear_begin_barriers.data()); + + VkClearColorValue clear_color; + clear_color.float32[0] = 0.0f; + clear_color.float32[1] = 0.0f; + clear_color.float32[2] = 0.0f; + clear_color.float32[3] = 0.0f; + + VkImageSubresourceRange subresource_range; + subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + subresource_range.baseMipLevel = 0; + subresource_range.levelCount = 1; + subresource_range.baseArrayLayer = 0; + subresource_range.layerCount = 1; + + vkCmdClearColorImage(this->command_buffer, this->distribution_red_image[0], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &subresource_range); + vkCmdClearColorImage(this->command_buffer, this->distribution_green_image[0], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &subresource_range); + vkCmdClearColorImage(this->command_buffer, this->distribution_blue_image[0], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &subresource_range); + vkCmdClearColorImage(this->command_buffer, this->distribution_geometry_image[0], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &subresource_range); + vkCmdClearColorImage(this->command_buffer, this->distribution_geometry_image[1], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &subresource_range); + + std::vector<VkImageMemoryBarrier> clear_end_barriers = IndirectCache::build_barriers(3, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + clear_end_barriers[0].image = this->distribution_red_image[0]; + clear_end_barriers[1].image = this->distribution_green_image[0]; + clear_end_barriers[2].image = this->distribution_blue_image[0]; + + vkCmdPipelineBarrier(this->command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, clear_end_barriers.size(), clear_end_barriers.data()); + + std::vector<VkImageMemoryBarrier> geometry_begin_barriers = IndirectCache::build_barriers(2, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL); + geometry_begin_barriers[0].image = this->distribution_geometry_image[0]; + geometry_begin_barriers[1].image = this->distribution_geometry_image[1]; + + vkCmdPipelineBarrier(this->command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, geometry_begin_barriers.size(), geometry_begin_barriers.data()); + + this->geometry_pass->process(this->command_buffer, 0); + + std::vector<VkImageMemoryBarrier> geometry_end_barriers = IndirectCache::build_barriers(2, 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); + geometry_end_barriers[0].image = this->distribution_geometry_image[0]; + geometry_end_barriers[1].image = this->distribution_geometry_image[1]; + + vkCmdPipelineBarrier(this->command_buffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, geometry_end_barriers.size(), geometry_end_barriers.data()); + + for (uint32_t index = 0; index < lights.size(); index++) + { + const SceneLight& light = lights[index]; + + if (light.data.type != LIGHT_TYPE_DIRECTIONAL) + { + continue; + } + + this->frame = frame; + this->light_index = index; + this->capture_pass->process(this->command_buffer, 0); + this->injection_pass->process(this->command_buffer, 0); + } + + //NOTE: Memory barrier for source image provieded by injection render pass + // The final image layout of distribution_..._image[0] has to be VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL + + std::vector<VkImageMemoryBarrier> copy_barriers = IndirectCache::build_barriers(3, 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + copy_barriers[0].image = this->distribution_red_image[2]; + copy_barriers[1].image = this->distribution_green_image[2]; + copy_barriers[2].image = this->distribution_blue_image[2]; + + vkCmdPipelineBarrier(this->command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, copy_barriers.size(), copy_barriers.data()); + + VkImageSubresourceLayers subresource_layers; + subresource_layers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + subresource_layers.mipLevel = 0; + subresource_layers.baseArrayLayer = 0; + subresource_layers.layerCount = 1; + + VkOffset3D offset; + offset.x = 0; + offset.y = 0; + offset.z = 0; + + VkExtent3D extend; + extend.width = this->domain_indirect_resolution.x; + extend.height = this->domain_indirect_resolution.y; + extend.depth = this->domain_indirect_resolution.z; + + VkImageCopy image_copy; + image_copy.srcSubresource = subresource_layers; + image_copy.srcOffset = offset; + image_copy.dstSubresource = subresource_layers; + image_copy.dstOffset = offset; + image_copy.extent = extend; + + vkCmdCopyImage(this->command_buffer, this->distribution_red_image[0], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, this->distribution_red_image[2], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); + vkCmdCopyImage(this->command_buffer, this->distribution_green_image[0], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, this->distribution_green_image[2], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); + vkCmdCopyImage(this->command_buffer, this->distribution_blue_image[0], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, this->distribution_blue_image[2], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); + + std::vector<VkImageMemoryBarrier> setup_src_barriers = IndirectCache::build_barriers(3, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL); + setup_src_barriers[0].image = this->distribution_red_image[0]; + setup_src_barriers[1].image = this->distribution_green_image[0]; + setup_src_barriers[2].image = this->distribution_blue_image[0]; + + vkCmdPipelineBarrier(this->command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, setup_src_barriers.size(), setup_src_barriers.data()); + + std::vector<VkImageMemoryBarrier> setup_dst_barriers = IndirectCache::build_barriers(3, 0, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL); + setup_dst_barriers[0].image = this->distribution_red_image[1]; + setup_dst_barriers[1].image = this->distribution_green_image[1]; + setup_dst_barriers[2].image = this->distribution_blue_image[1]; + + vkCmdPipelineBarrier(this->command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, setup_dst_barriers.size(), setup_dst_barriers.data()); + + std::vector<VkImageMemoryBarrier> setup_indirect_barriers = IndirectCache::build_barriers(3, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL); + setup_indirect_barriers[0].image = this->distribution_red_image[2]; + setup_indirect_barriers[1].image = this->distribution_green_image[2]; + setup_indirect_barriers[2].image = this->distribution_blue_image[2]; + + vkCmdPipelineBarrier(this->command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, setup_indirect_barriers.size(), setup_indirect_barriers.data()); + + if (vkEndCommandBuffer(this->command_buffer) != VK_SUCCESS) + { + lava::log()->error("Can't end command buffer during setup of indirect cache!"); + + 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 during setup of indirect cache!"); + + 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 during setup of indirect cache!"); + + 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 indirect cache setup!"); + + return false; + } + + return true; +} + +bool IndirectCache::submit_propagation(uint32_t iterations) +{ + 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 during propagation of indirect cache!"); + + return false; + } + + this->propagation_pipeline->bind(this->command_buffer); + + for (uint32_t index = 0; index < iterations; index++) + { + uint32_t src_index = index % 2; + uint32_t dst_index = (index + 1) % 2; + + this->propagation_layout->bind(this->command_buffer, this->propagation_descriptor_set[src_index], 0, {}, VK_PIPELINE_BIND_POINT_COMPUTE); + + vkCmdDispatch(this->command_buffer, this->domain_work_groups.x, this->domain_work_groups.y, this->domain_work_groups.z); + + std::vector<VkImageMemoryBarrier> compue_src_barriers = IndirectCache::build_barriers(3, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL); + compue_src_barriers[0].image = this->distribution_red_image[src_index]; + compue_src_barriers[1].image = this->distribution_green_image[src_index]; + compue_src_barriers[2].image = this->distribution_blue_image[src_index]; + + vkCmdPipelineBarrier(this->command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, compue_src_barriers.size(), compue_src_barriers.data()); + + std::vector<VkImageMemoryBarrier> compute_dst_barriers = IndirectCache::build_barriers(3, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL); + compute_dst_barriers[0].image = this->distribution_red_image[dst_index]; + compute_dst_barriers[1].image = this->distribution_green_image[dst_index]; + compute_dst_barriers[2].image = this->distribution_blue_image[dst_index]; + + vkCmdPipelineBarrier(this->command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, compute_dst_barriers.size(), compute_dst_barriers.data()); + + std::vector<VkImageMemoryBarrier> compute_indirect_barriers = IndirectCache::build_barriers(3, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL); + compute_indirect_barriers[0].image = this->distribution_red_image[2]; + compute_indirect_barriers[1].image = this->distribution_green_image[2]; + compute_indirect_barriers[2].image = this->distribution_blue_image[2]; + + vkCmdPipelineBarrier(this->command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, compute_indirect_barriers.size(), compute_indirect_barriers.data()); + } + + if (vkEndCommandBuffer(this->command_buffer) != VK_SUCCESS) + { + lava::log()->error("Can't end command buffer during propagation of indirect cache!"); + + 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 during propagation of indirect cache!"); + + 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 during propagation of indirect cache!"); + + 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 indirect propagation setup!"); + + 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 1f5563eb04e9fa4f5f50d9f0b32b2dc2c2a9724c..e6cebb150b30e17e7186ce57dbd70a06ba7c4762 100644 --- a/src/utility/indirect_cache.hpp +++ b/src/utility/indirect_cache.hpp @@ -45,7 +45,7 @@ struct IndirectCacheSettings { uint32_t capture_resolution = 1024; uint32_t voxel_resolution_scale = 1; //Needs to be greater or equal to one - float cell_size = 1.0f; //Where cell size is in meters + float cell_size = 0.5f; //Where cell size is in meters }; class IndirectCache @@ -59,7 +59,7 @@ public: bool create(Scene::Ptr scene, const IndirectCacheSettings& settings); void destroy(); - void compute_indirect(VkCommandBuffer command_buffer, lava::index frame); + void compute_indirect(VkCommandBuffer comannd_buffer, lava::index frame); lava::descriptor::ptr get_descriptor() const; VkDescriptorSet get_descriptor_set() const; @@ -69,6 +69,8 @@ public: private: bool compute_domain(Scene::Ptr scene, const IndirectCacheSettings& settings); + bool create_command_buffer(lava::device_ptr device); + bool create_fence(lava::device_ptr device); bool create_buffers(lava::device_ptr device, const IndirectCacheSettings& settings); bool create_images(lava::device_ptr device, const IndirectCacheSettings& settings); bool create_samplers(lava::device_ptr device); @@ -82,6 +84,9 @@ private: bool create_injection_pipeline(lava::device_ptr device); bool create_propagation_pipeline(lava::device_ptr device); + bool submit_setup(); + bool submit_propagation(uint32_t iterations); //NOTE: Iterations needs to be multiple of two + void pipeline_geometry(VkCommandBuffer command_buffer); void pipeline_capture(VkCommandBuffer command_buffer); void pipeline_injection(VkCommandBuffer command_buffer); @@ -105,6 +110,10 @@ private: glm::uvec3 domain_voxel_resolution = glm::uvec3(0); glm::uvec3 domain_work_groups = glm::uvec3(0); + VkCommandPool command_pool = VK_NULL_HANDLE; + VkCommandBuffer command_buffer = VK_NULL_HANDLE; + VkFence fence = VK_NULL_HANDLE; + lava::descriptor::pool::ptr descriptor_pool; lava::descriptor::ptr indirect_descriptor; lava::descriptor::ptr geometry_descriptor;