diff --git a/src/main.cpp b/src/main.cpp index 975baf2..b764407 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -89,13 +89,15 @@ class VulkanExampleApplication { std::unique_ptr vk_render_pass; std::unique_ptr vk_pipeline; std::unique_ptr vk_command_pool; - std::unique_ptr vk_command_buffers; std::unique_ptr vk_descriptor_set_layout; std::unique_ptr vk_descriptor_pool; std::unique_ptr vk_descriptor_sets; - std::unique_ptr vk_fence_in_flight; - std::unique_ptr vk_semephore_image_available; - std::unique_ptr vk_semephore_render_finished; + + uint current_frame_index = 0; + std::vector vk_command_buffers; + std::vector vk_fences_in_flight; + std::vector vk_semephores_image_available; + std::vector vk_semephores_render_finished; struct VulkanDeviceQueriedInfo { std::unique_ptr screen_surface; @@ -643,9 +645,9 @@ public: const vk::CommandBufferAllocateInfo command_buffer_alloc_info { .commandPool = **this->vk_command_pool, .level = vk::CommandBufferLevel::ePrimary, - .commandBufferCount = 1 + .commandBufferCount = MAX_FRAMES_IN_FLIGHT }; - this->vk_command_buffers = std::make_unique(*this->vk_gpu, command_buffer_alloc_info); + this->vk_command_buffers = vk::raii::CommandBuffers(*this->vk_gpu, command_buffer_alloc_info); } { // vertex @@ -671,9 +673,11 @@ public: this->CopyBuffer(*index_buffer_staging.first, *this->vk_buffer_index.first, index_buffer_size); } { // syncronizing vars - this->vk_semephore_image_available = std::make_unique(*this->vk_gpu, vk::SemaphoreCreateInfo {}); - this->vk_semephore_render_finished = std::make_unique(*this->vk_gpu, vk::SemaphoreCreateInfo {}); - this->vk_fence_in_flight = std::make_unique(*this->vk_gpu, vk::FenceCreateInfo { .flags = vk::FenceCreateFlagBits::eSignaled }); + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + this->vk_semephores_image_available.push_back(vk::raii::Semaphore(*this->vk_gpu, vk::SemaphoreCreateInfo {})); + this->vk_semephores_render_finished.push_back(vk::raii::Semaphore(*this->vk_gpu, vk::SemaphoreCreateInfo {})); + this->vk_fences_in_flight.push_back(vk::raii::Fence(*this->vk_gpu, vk::FenceCreateInfo { .flags = vk::FenceCreateFlagBits::eSignaled })); + } } } catch (const vk::SystemError& e) { std::cout << "Received Vulkan-Specific Error during process init: " << e.what() << std::endl @@ -778,41 +782,40 @@ public: std::cout << "Completed tests with: " << std::to_string(amount_of_frames_needed) << " frames!" << std::endl; } - void DrawFrame() const { - const std::array wait_fences = { *this->vk_fence_in_flight }; + void DrawFrame() { + const std::array wait_fences = { *this->vk_fences_in_flight[this->current_frame_index] }; const vk::Result fence_result = this->vk_gpu->waitForFences(wait_fences, vk::True, std::numeric_limits::max()); if (fence_result != vk::Result::eSuccess) throw std::runtime_error("failed to wait for frame fence!"); this->vk_gpu->resetFences(wait_fences); - const auto next_image = this->vk_swapchain->acquireNextImage(std::numeric_limits::max(), *this->vk_semephore_image_available); + const auto next_image = this->vk_swapchain->acquireNextImage(std::numeric_limits::max(), *this->vk_semephores_image_available[this->current_frame_index]); if (next_image.first != vk::Result::eSuccess) { if (next_image.first == vk::Result::eNotReady) // i think its best to just return... return; if (next_image.first != vk::Result::eSuboptimalKHR) throw std::runtime_error("failed to aquire next image!: " + std::to_string((int)next_image.first)); // vk::Result::eTimeout and everything else throws! } - this->vk_command_buffers->front().reset(); + const auto& command_buffer = this->vk_command_buffers[this->current_frame_index]; + command_buffer.reset(); - this->RecordCommandBuffer(this->vk_command_buffers->front(), next_image.second); + this->RecordCommandBuffer(command_buffer, next_image.second); - const std::array wait_semaphores = { *this->vk_semephore_image_available }; + const std::array wait_semaphores = { *this->vk_semephores_image_available[this->current_frame_index] }; constexpr auto wait_stages = vk::PipelineStageFlags(vk::PipelineStageFlagBits::eColorAttachmentOutput); - const std::array signal_semaphores = { *this->vk_semephore_render_finished }; - - const std::vector command_buffers(this->vk_command_buffers->begin(), this->vk_command_buffers->end()); + const std::array signal_semaphores = { *this->vk_semephores_render_finished[this->current_frame_index] }; const vk::SubmitInfo submit_info { .waitSemaphoreCount = wait_semaphores.size(), .pWaitSemaphores = wait_semaphores.data(), .pWaitDstStageMask = &wait_stages, - .commandBufferCount = static_cast(command_buffers.size()), - .pCommandBuffers = command_buffers.data(), + .commandBufferCount = 1, + .pCommandBuffers = &*command_buffer, .signalSemaphoreCount = signal_semaphores.size(), .pSignalSemaphores = signal_semaphores.data() }; const std::array submit_queue = { submit_info }; - this->vk_queue_graphics->submit(submit_queue, **this->vk_fence_in_flight); + this->vk_queue_graphics->submit(submit_queue, *this->vk_fences_in_flight[this->current_frame_index]); const std::array swapchains = { *this->vk_swapchain }; const vk::PresentInfoKHR present_info { @@ -826,6 +829,8 @@ public: const vk::Result present_result = this->vk_queue_present->presentKHR(present_info); if (present_result != vk::Result::eSuccess) throw std::runtime_error("failed to present image!"); + + this->current_frame_index = (this->current_frame_index + 1) % MAX_FRAMES_IN_FLIGHT; } void RecordCommandBuffer(const vk::raii::CommandBuffer& command_buffer, std::uint32_t image_index) const { @@ -890,7 +895,7 @@ private: .pfnUserCallback = &VulkanDebugCallback }; #endif - + static constexpr int MAX_FRAMES_IN_FLIGHT = 2; static constexpr std::array required_vulkan_device_extensions = { vk::KHRSwapchainExtensionName }; static constexpr std::array required_vulkan_validation_layers = { "VK_LAYER_KHRONOS_validation" }; static constexpr vk::Format required_vulkan_default_format = vk::Format::eR8G8B8A8Unorm; // formats Preffered front to back. FIFO