Files
Np_Term/impl/vulkan_engine/vulkan/drawing.cpp

192 lines
6.9 KiB
C++

#include <GLFW/glfw3.h>
#include "precomp.h"
#include "vulkan_engine/vulkan/graphics.h"
namespace veng {
void Graphics::CreateFramebuffers() {
swap_chain_framebuffers_.resize(swap_chain_image_views_.size());
for (std::uint32_t i = 0; i < swap_chain_image_views_.size(); i++) {
std::array<VkImageView, 2> attachments = {swap_chain_image_views_[i],
depth_texture_.image_view};
VkFramebufferCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
info.renderPass = render_pass_;
info.attachmentCount = attachments.size();
info.pAttachments = attachments.data();
info.width = extent_.width;
info.height = extent_.height;
info.layers = 1;
VkResult result = vkCreateFramebuffer(logical_device_, &info, nullptr,
&swap_chain_framebuffers_[i]);
if (result != VK_SUCCESS) std::exit(EXIT_FAILURE);
}
}
void Graphics::CreateCommandPool() {
QueueFamilyIndices indices = FindQueueFamilies(physical_device_);
VkCommandPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
pool_info.queueFamilyIndex = indices.graphics_family.value();
VkResult result =
vkCreateCommandPool(logical_device_, &pool_info, nullptr, &command_pool_);
if (result != VK_SUCCESS) std::exit(EXIT_FAILURE);
}
void Graphics::CreateCommandBuffer() {
VkCommandBufferAllocateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
info.commandPool = command_pool_;
info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
info.commandBufferCount = 1;
for (Frame& frame : frames_) {
VkResult result =
vkAllocateCommandBuffers(logical_device_, &info, &frame.command_buffer);
if (result != VK_SUCCESS) std::exit(EXIT_FAILURE);
}
}
void Graphics::BeginCommands() {
vkResetCommandBuffer(frames_[current_frame_].command_buffer, 0);
VkCommandBufferBeginInfo begin_info = {};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
VkResult result = vkBeginCommandBuffer(
frames_[current_frame_].command_buffer, &begin_info);
if (result != VK_SUCCESS)
throw std::runtime_error("Failed to begin command buffer!");
std::array<VkClearValue, 2> clear_values;
clear_values[0].color = {{0.f, 0.f, 0.f, 1.f}};
clear_values[1].depthStencil = {1.f, 0};
VkRenderPassBeginInfo render_pass_begin_info = {};
render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
render_pass_begin_info.renderPass = render_pass_;
render_pass_begin_info.framebuffer =
swap_chain_framebuffers_[current_image_index_];
render_pass_begin_info.renderArea.offset = {0, 0};
render_pass_begin_info.renderArea.extent = extent_;
render_pass_begin_info.clearValueCount = clear_values.size();
render_pass_begin_info.pClearValues = clear_values.data();
vkCmdBeginRenderPass(frames_[current_frame_].command_buffer,
&render_pass_begin_info,
VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(frames_[current_frame_].command_buffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
pipeline_);
VkViewport viewport = GetViewport();
VkRect2D scissor = GetScissor();
vkCmdSetViewport(frames_[current_frame_].command_buffer, 0, 1, &viewport);
vkCmdSetScissor(frames_[current_frame_].command_buffer, 0, 1, &scissor);
}
void Graphics::EndCommands() {
vkCmdEndRenderPass(frames_[current_frame_].command_buffer);
VkResult result = vkEndCommandBuffer(frames_[current_frame_].command_buffer);
if (result != VK_SUCCESS)
throw std::runtime_error("Failed to record command buffer!");
}
void Graphics::CreateSignals() {
for (Frame& frame : frames_) {
VkSemaphoreCreateInfo semafore_info = {};
semafore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
if (vkCreateSemaphore(logical_device_, &semafore_info, nullptr,
&frame.image_available_signal) !=
VK_SUCCESS)
std::exit(EXIT_FAILURE);
if (vkCreateSemaphore(logical_device_, &semafore_info, nullptr,
&frame.render_finished_signal) !=
VK_SUCCESS)
std::exit(EXIT_FAILURE);
VkFenceCreateInfo fence_info = {};
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
if (vkCreateFence(logical_device_, &fence_info, nullptr,
&frame.still_rendering_fence) !=
VK_SUCCESS)
std::exit(EXIT_FAILURE);
}
}
bool Graphics::BeginFrame() {
vkWaitForFences(logical_device_, 1,
&frames_[current_frame_].still_rendering_fence, VK_TRUE,
UINT64_MAX);
VkResult image_acquire_result = vkAcquireNextImageKHR(logical_device_, swap_chain_, UINT64_MAX,
frames_[current_frame_].image_available_signal,
VK_NULL_HANDLE, &current_image_index_);
if (image_acquire_result == VK_ERROR_OUT_OF_DATE_KHR) {
RecreateSwapChain();
return false;
}
if (image_acquire_result != VK_SUCCESS &&
image_acquire_result != VK_SUBOPTIMAL_KHR)
throw std::runtime_error("Couldn't acquire render image!");
vkResetFences(logical_device_, 1,
&frames_[current_frame_].still_rendering_fence);
BeginCommands();
SetModelMatrix(glm::mat4(1.f));
return true;
}
void veng::Graphics::EndFrame() {
EndCommands();
VkSubmitInfo submit_info = {};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = &frames_[current_frame_].image_available_signal;
submit_info.pWaitDstStageMask = &wait_stage;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &frames_[current_frame_].command_buffer;
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores =
&frames_[current_frame_].render_finished_signal;
VkResult submit_result =
vkQueueSubmit(graphics_queue_, 1, &submit_info,
frames_[current_frame_].still_rendering_fence);
if (submit_result != VK_SUCCESS)
throw std::runtime_error("failed to submit draw commands!");
VkPresentInfoKHR present_info = {};
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
present_info.waitSemaphoreCount = 1;
present_info.pWaitSemaphores =
&frames_[current_frame_].render_finished_signal;
present_info.swapchainCount = 1;
present_info.pSwapchains = &swap_chain_;
present_info.pImageIndices = &current_image_index_;
VkResult result = vkQueuePresentKHR(present_queue_, &present_info);
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR)
RecreateSwapChain();
else if (result != VK_SUCCESS)
throw std::runtime_error("Failed to present swap chain image!");
current_frame_ = (current_frame_++) % MAX_BUFFERED_FRAMES;
}
} // namespace veng