25 VkExtent2D extent = m_window.getExtent();
26 while (extent.width == 0 || extent.height == 0) {
27 extent = m_window.getExtent();
30 vkDeviceWaitIdle(m_device.device());
31 if (m_swapChain ==
nullptr) {
32 m_swapChain = std::make_unique<SwapChain>(m_device, extent);
34 std::shared_ptr<SwapChain> oldSwapChain = std::move(m_swapChain);
35 m_swapChain = std::make_unique<SwapChain>(m_device, extent, oldSwapChain);
36 if (!oldSwapChain->compareSwapFormats(*m_swapChain)) {
37 throw std::runtime_error(
"Swap chain image/depth format changed");
45 assert(!m_isFrameStarted &&
"Can't start new frame while previous one is still in progress");
47 const VkResult result = m_swapChain->acquireNextImage(&m_currentImageIndex);
48 if (result == VK_ERROR_OUT_OF_DATE_KHR) {
53 if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
54 throw std::runtime_error(
"Failed to acquire swap chain image");
57 m_isFrameStarted =
true;
59 VkCommandBuffer_T *commandBuffer = getCurrentCommandBuffer();
60 VkCommandBufferBeginInfo beginInfo{};
61 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
63 if (vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) {
64 throw std::runtime_error(
"Failed to begin recording command m_buffer");
71 assert(m_isFrameStarted &&
"Can't end frame that hasn't been started");
73 VkCommandBuffer_T *commandBuffer = getCurrentCommandBuffer();
74 if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
75 throw std::runtime_error(
"Failed to record command buffer");
77 if (
const VkResult result = m_swapChain->submitCommandBuffers(&commandBuffer, &m_currentImageIndex); result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || m_window.wasWindowResized()) {
78 m_window.resetWindowResizedFlag();
81 else if (result != VK_SUCCESS) {
82 throw std::runtime_error(
"Failed to submit command buffer");
85 m_isFrameStarted =
false;
91 assert(m_isFrameStarted &&
"Can't begin render pass when frame not in progress");
92 assert(commandBuffer == getCurrentCommandBuffer() &&
"Can't begin render pass on command m_buffer from a different frame");
94 VkRenderPassBeginInfo renderPassInfo{};
95 renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
96 renderPassInfo.renderPass = m_swapChain->getRenderPass();
97 renderPassInfo.framebuffer = m_swapChain->getFrameBuffer(m_currentImageIndex);
99 renderPassInfo.renderArea.offset = {.x=0, .y=0};
100 renderPassInfo.renderArea.extent = m_swapChain->getSwapChainExtent();
102 renderPassInfo.clearValueCount =
static_cast<uint32_t
>(m_clearValues.size());
103 renderPassInfo.pClearValues = m_clearValues.data();
105 vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
107 VkViewport viewport{};
110 viewport.width =
static_cast<float>(m_swapChain->getSwapChainExtent().width);
111 viewport.height =
static_cast<float>(m_swapChain->getSwapChainExtent().height);
112 viewport.minDepth = 0.0F;
113 viewport.maxDepth = 1.0F;
114 const VkRect2D scissor{{0, 0}, m_swapChain->getSwapChainExtent()};
115 vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
116 vkCmdSetScissor(commandBuffer, 0, 1, &scissor);