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::RenderPass> vk_render_pass;
|
||||||
std::unique_ptr<vk::raii::Pipeline> vk_pipeline;
|
std::unique_ptr<vk::raii::Pipeline> vk_pipeline;
|
||||||
std::unique_ptr<vk::raii::CommandPool> vk_command_pool;
|
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::DescriptorSetLayout> vk_descriptor_set_layout;
|
||||||
std::unique_ptr<vk::raii::DescriptorPool> vk_descriptor_pool;
|
std::unique_ptr<vk::raii::DescriptorPool> vk_descriptor_pool;
|
||||||
std::unique_ptr<vk::raii::DescriptorSets> vk_descriptor_sets;
|
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;
|
uint current_frame_index = 0;
|
||||||
std::unique_ptr<vk::raii::Semaphore> vk_semephore_render_finished;
|
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 {
|
struct VulkanDeviceQueriedInfo {
|
||||||
std::unique_ptr<vk::raii::SurfaceKHR> screen_surface;
|
std::unique_ptr<vk::raii::SurfaceKHR> screen_surface;
|
||||||
@ -643,9 +645,9 @@ public:
|
|||||||
const vk::CommandBufferAllocateInfo command_buffer_alloc_info {
|
const vk::CommandBufferAllocateInfo command_buffer_alloc_info {
|
||||||
.commandPool = **this->vk_command_pool,
|
.commandPool = **this->vk_command_pool,
|
||||||
.level = vk::CommandBufferLevel::ePrimary,
|
.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
|
// vertex
|
||||||
@ -671,9 +673,11 @@ public:
|
|||||||
this->CopyBuffer(*index_buffer_staging.first, *this->vk_buffer_index.first, index_buffer_size);
|
this->CopyBuffer(*index_buffer_staging.first, *this->vk_buffer_index.first, index_buffer_size);
|
||||||
}
|
}
|
||||||
{ // syncronizing vars
|
{ // syncronizing vars
|
||||||
this->vk_semephore_image_available = std::make_unique<vk::raii::Semaphore>(*this->vk_gpu, vk::SemaphoreCreateInfo {});
|
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||||
this->vk_semephore_render_finished = std::make_unique<vk::raii::Semaphore>(*this->vk_gpu, vk::SemaphoreCreateInfo {});
|
this->vk_semephores_image_available.push_back(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 });
|
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) {
|
} catch (const vk::SystemError& e) {
|
||||||
std::cout << "Received Vulkan-Specific Error during process init: " << e.what() << std::endl
|
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;
|
std::cout << "Completed tests with: " << std::to_string(amount_of_frames_needed) << " frames!" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawFrame() const {
|
void DrawFrame() {
|
||||||
const std::array<vk::Fence, 1> wait_fences = { *this->vk_fence_in_flight };
|
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());
|
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)
|
if (fence_result != vk::Result::eSuccess)
|
||||||
throw std::runtime_error("failed to wait for frame fence!");
|
throw std::runtime_error("failed to wait for frame fence!");
|
||||||
this->vk_gpu->resetFences(wait_fences);
|
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::eSuccess) {
|
||||||
if (next_image.first == vk::Result::eNotReady) // i think its best to just return...
|
if (next_image.first == vk::Result::eNotReady) // i think its best to just return...
|
||||||
return;
|
return;
|
||||||
if (next_image.first != vk::Result::eSuboptimalKHR)
|
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!
|
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);
|
constexpr auto wait_stages = vk::PipelineStageFlags(vk::PipelineStageFlagBits::eColorAttachmentOutput);
|
||||||
const std::array<vk::Semaphore, 1> signal_semaphores = { *this->vk_semephore_render_finished };
|
const std::array<vk::Semaphore, 1> signal_semaphores = { *this->vk_semephores_render_finished[this->current_frame_index] };
|
||||||
|
|
||||||
const std::vector<vk::CommandBuffer> command_buffers(this->vk_command_buffers->begin(), this->vk_command_buffers->end());
|
|
||||||
|
|
||||||
const vk::SubmitInfo submit_info {
|
const vk::SubmitInfo submit_info {
|
||||||
.waitSemaphoreCount = wait_semaphores.size(),
|
.waitSemaphoreCount = wait_semaphores.size(),
|
||||||
.pWaitSemaphores = wait_semaphores.data(),
|
.pWaitSemaphores = wait_semaphores.data(),
|
||||||
.pWaitDstStageMask = &wait_stages,
|
.pWaitDstStageMask = &wait_stages,
|
||||||
.commandBufferCount = static_cast<std::uint32_t>(command_buffers.size()),
|
.commandBufferCount = 1,
|
||||||
.pCommandBuffers = command_buffers.data(),
|
.pCommandBuffers = &*command_buffer,
|
||||||
.signalSemaphoreCount = signal_semaphores.size(),
|
.signalSemaphoreCount = signal_semaphores.size(),
|
||||||
.pSignalSemaphores = signal_semaphores.data()
|
.pSignalSemaphores = signal_semaphores.data()
|
||||||
};
|
};
|
||||||
const std::array<vk::SubmitInfo, 1> submit_queue = { submit_info };
|
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 std::array<vk::SwapchainKHR, 1> swapchains = { *this->vk_swapchain };
|
||||||
const vk::PresentInfoKHR present_info {
|
const vk::PresentInfoKHR present_info {
|
||||||
@ -826,6 +829,8 @@ public:
|
|||||||
const vk::Result present_result = this->vk_queue_present->presentKHR(present_info);
|
const vk::Result present_result = this->vk_queue_present->presentKHR(present_info);
|
||||||
if (present_result != vk::Result::eSuccess)
|
if (present_result != vk::Result::eSuccess)
|
||||||
throw std::runtime_error("failed to present image!");
|
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 {
|
void RecordCommandBuffer(const vk::raii::CommandBuffer& command_buffer, std::uint32_t image_index) const {
|
||||||
@ -890,7 +895,7 @@ private:
|
|||||||
.pfnUserCallback = &VulkanDebugCallback
|
.pfnUserCallback = &VulkanDebugCallback
|
||||||
};
|
};
|
||||||
#endif
|
#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_device_extensions = { vk::KHRSwapchainExtensionName };
|
||||||
static constexpr std::array<const char*, 1> required_vulkan_validation_layers = { "VK_LAYER_KHRONOS_validation" };
|
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
|
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