Added multiple command-buffers and syncronization commands to allow the system to render multiple frames at once.
This commit is contained in:
parent
7e429da9ae
commit
cec2cb3ec9
49
src/main.cpp
49
src/main.cpp
@ -89,13 +89,15 @@ class VulkanExampleApplication {
|
||||
std::unique_ptr<vk::raii::RenderPass> vk_render_pass;
|
||||
std::unique_ptr<vk::raii::Pipeline> vk_pipeline;
|
||||
std::unique_ptr<vk::raii::CommandPool> vk_command_pool;
|
||||
std::unique_ptr<vk::raii::CommandBuffers> vk_command_buffers;
|
||||
std::unique_ptr<vk::raii::DescriptorSetLayout> vk_descriptor_set_layout;
|
||||
std::unique_ptr<vk::raii::DescriptorPool> vk_descriptor_pool;
|
||||
std::unique_ptr<vk::raii::DescriptorSets> vk_descriptor_sets;
|
||||
std::unique_ptr<vk::raii::Fence> vk_fence_in_flight;
|
||||
std::unique_ptr<vk::raii::Semaphore> vk_semephore_image_available;
|
||||
std::unique_ptr<vk::raii::Semaphore> vk_semephore_render_finished;
|
||||
|
||||
uint current_frame_index = 0;
|
||||
std::vector<vk::raii::CommandBuffer> vk_command_buffers;
|
||||
std::vector<vk::raii::Fence> vk_fences_in_flight;
|
||||
std::vector<vk::raii::Semaphore> vk_semephores_image_available;
|
||||
std::vector<vk::raii::Semaphore> vk_semephores_render_finished;
|
||||
|
||||
struct VulkanDeviceQueriedInfo {
|
||||
std::unique_ptr<vk::raii::SurfaceKHR> 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<vk::raii::CommandBuffers>(*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<vk::raii::Semaphore>(*this->vk_gpu, vk::SemaphoreCreateInfo {});
|
||||
this->vk_semephore_render_finished = std::make_unique<vk::raii::Semaphore>(*this->vk_gpu, vk::SemaphoreCreateInfo {});
|
||||
this->vk_fence_in_flight = std::make_unique<vk::raii::Fence>(*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<vk::Fence, 1> wait_fences = { *this->vk_fence_in_flight };
|
||||
void DrawFrame() {
|
||||
const std::array<vk::Fence, 1> 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<std::uint64_t>::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<std::uint64_t>::max(), *this->vk_semephore_image_available);
|
||||
const auto next_image = this->vk_swapchain->acquireNextImage(std::numeric_limits<std::uint64_t>::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<vk::Semaphore, 1> wait_semaphores = { *this->vk_semephore_image_available };
|
||||
const std::array<vk::Semaphore, 1> wait_semaphores = { *this->vk_semephores_image_available[this->current_frame_index] };
|
||||
constexpr auto wait_stages = vk::PipelineStageFlags(vk::PipelineStageFlagBits::eColorAttachmentOutput);
|
||||
const std::array<vk::Semaphore, 1> signal_semaphores = { *this->vk_semephore_render_finished };
|
||||
|
||||
const std::vector<vk::CommandBuffer> command_buffers(this->vk_command_buffers->begin(), this->vk_command_buffers->end());
|
||||
const std::array<vk::Semaphore, 1> 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<std::uint32_t>(command_buffers.size()),
|
||||
.pCommandBuffers = command_buffers.data(),
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &*command_buffer,
|
||||
.signalSemaphoreCount = signal_semaphores.size(),
|
||||
.pSignalSemaphores = signal_semaphores.data()
|
||||
};
|
||||
const std::array<vk::SubmitInfo, 1> 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<vk::SwapchainKHR, 1> 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<const char*, 1> required_vulkan_device_extensions = { vk::KHRSwapchainExtensionName };
|
||||
static constexpr std::array<const char*, 1> 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user