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(!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(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 m_buffer");
77 VkResult result = m_swapChain->submitCommandBuffers(&commandBuffer, &m_currentImageIndex);
78 if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || m_window.wasWindowResized()) {
79 m_window.resetWindowResizedFlag();
82 else if (result != VK_SUCCESS) {
83 throw std::runtime_error(
"Failed to submit command m_buffer");
86 m_isFrameStarted =
false;
92 assert(isFrameStarted &&
"Can't begin render pass when frame not in progress");
93 assert(commandBuffer == getCurrentCommandBuffer() &&
"Can't begin render pass on command m_buffer from a different frame");
95 VkRenderPassBeginInfo renderPassInfo{};
96 renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
97 renderPassInfo.renderPass = m_swapChain->getRenderPass();
98 renderPassInfo.framebuffer = m_swapChain->getFrameBuffer(m_currentImageIndex);
100 renderPassInfo.renderArea.offset = {0, 0};
101 renderPassInfo.renderArea.extent = m_swapChain->getSwapChainExtent();
103 std::array<VkClearValue, 2> clearValues{};
104 clearValues[0].color = {{0.01F, 0.01F, 0.01F, 1.0F}};
105 clearValues[1].depthStencil = {1.0F, 0};
106 renderPassInfo.clearValueCount =
static_cast<uint32_t
>(clearValues.size());
107 renderPassInfo.pClearValues = clearValues.data();
109 vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
111 VkViewport viewport{};
114 viewport.width =
static_cast<float>(m_swapChain->getSwapChainExtent().width);
115 viewport.height =
static_cast<float>(m_swapChain->getSwapChainExtent().height);
116 viewport.minDepth = 0.0F;
117 viewport.maxDepth = 1.0F;
118 const VkRect2D scissor{{0, 0}, m_swapChain->getSwapChainExtent()};
119 vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
120 vkCmdSetScissor(commandBuffer, 0, 1, &scissor);