static void Rhi_FrameBegin(alloc* Scratch) { uint8_t* ScratchMark = Scratch->at; if (rhi->recreateSwapchain) { vkDeviceWaitIdle(rhi->dev); CreateSwapchain(Scratch); rhi->swapchainUsable = true; rhi->recreateSwapchain = false; } else { VulkanWaitTimelineSemaphore(rhi->graphicsQueue.timeline, rhi->graphicsQueue.cmdDone); } if (rhi->swapchainUsable) { VkResult acquireResult = vkAcquireNextImageKHR(rhi->dev, rhi->swapchain, UINT64_MAX, rhi->SwapChainAcquireSemaphore, VK_NULL_HANDLE, &rhi->SwapChainIndex); switch (acquireResult) { case VK_ERROR_OUT_OF_DATE_KHR: { rhi->swapchainUsable = false; rhi->recreateSwapchain = true; break; } case VK_SUBOPTIMAL_KHR: { rhi->swapchainUsable = true; rhi->recreateSwapchain = true; break; } default: { VK_CHECK(acquireResult); rhi->recreateSwapchain = false; rhi->swapchainUsable = true; break; } } } if (!rhi->swapchainUsable) { vkDeviceWaitIdle(rhi->dev); } rhi_cmdlist cmd = rhi->graphicsQueue.cmd; Rhi_ResetCmdList(cmd); VkCommandBuffer cmdbuf = ((rhi_cmdlist_data*)cmd)->cmdbuf; VkCommandBufferBeginInfo commandBufferBeginInfo{}; commandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; VK_CHECK(vkBeginCommandBuffer(cmdbuf, &commandBufferBeginInfo)); Scratch->at = ScratchMark; } static void Rhi_FrameEnd(alloc* Scratch) { uint8_t* ScratchMark = Scratch->at; rhi_cmdlist_data* Cmd = (rhi_cmdlist_data*)rhi->graphicsQueue.cmd; VkCommandBuffer cmdbuf = Cmd->cmdbuf; VK_CHECK(vkEndCommandBuffer(cmdbuf)); WriteDescriptorTables(Scratch); VkPipelineStageFlags waitStages[1] { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, }; VkSemaphore* renderSemaphore = &rhi->SwapChain[rhi->SwapChainIndex].Semaphore; if (!(*renderSemaphore)) { VkSemaphoreCreateInfo semaphoreCreateInfo{}; semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; VK_CHECK(vkCreateSemaphore(rhi->dev, &semaphoreCreateInfo, nullptr, renderSemaphore)); } VkSemaphore signalSemaphores[2] { rhi->graphicsQueue.timeline, *renderSemaphore, }; uint32_t signalSemaphoresCount; if (rhi->swapchainUsable) signalSemaphoresCount = 2; else signalSemaphoresCount = 1; rhi->graphicsQueue.cmdDone = rhi->graphicsQueue.timelineNext++; VkTimelineSemaphoreSubmitInfo timelineSubmitInfo{}; timelineSubmitInfo.sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO; timelineSubmitInfo.signalSemaphoreValueCount = signalSemaphoresCount; timelineSubmitInfo.pSignalSemaphoreValues = &rhi->graphicsQueue.cmdDone; VkSubmitInfo submitInfo{}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.pNext = &timelineSubmitInfo; if (rhi->swapchainUsable) { submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = &rhi->SwapChainAcquireSemaphore; } submitInfo.pWaitDstStageMask = waitStages; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &cmdbuf; submitInfo.signalSemaphoreCount = signalSemaphoresCount; submitInfo.pSignalSemaphores = signalSemaphores; VK_CHECK(vkQueueSubmit(rhi->graphicsQueue.queue, 1, &submitInfo, VK_NULL_HANDLE)); if (rhi->swapchainUsable) { VkPresentInfoKHR presentInfo{}; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.waitSemaphoreCount = 1; presentInfo.pWaitSemaphores = renderSemaphore; presentInfo.swapchainCount = 1; presentInfo.pSwapchains = &rhi->swapchain; presentInfo.pImageIndices = &rhi->SwapChainIndex; VkResult presentResult = vkQueuePresentKHR(rhi->graphicsQueue.queue, &presentInfo); } Scratch->at = ScratchMark; } static float RhiClearColorValue[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; static void Rhi_SetClearColor(float r, float g, float b) { RhiClearColorValue[0] = r; RhiClearColorValue[1] = g; RhiClearColorValue[2] = b; RhiClearColorValue[3] = 1.0f; } static void Rhi_PassBegin(rhi_render_target_view rtv, rhi_depth_stencil_view dsv) { rhi_cmdlist_data* Cmd = (rhi_cmdlist_data*)rhi->graphicsQueue.cmd; VkCommandBuffer cmdbuf = Cmd->cmdbuf; rhi_texture_view_data* RenderTargetView = (rhi_texture_view_data*)rtv; rhi_texture_data* RenderTarget = (rhi_texture_data*)RenderTargetView->texture; VkRenderingAttachmentInfo colorAttachmentInfo{}; colorAttachmentInfo.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; colorAttachmentInfo.imageView = RenderTargetView->imageView; colorAttachmentInfo.imageLayout = RenderTarget->layout; colorAttachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; colorAttachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE; colorAttachmentInfo.clearValue = { { { RhiClearColorValue[0], RhiClearColorValue[1], RhiClearColorValue[2], RhiClearColorValue[3] } } }; VkRenderingInfo renderingInfo{}; renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; renderingInfo.renderArea = { { 0, 0 }, { RenderTarget->extent.width, RenderTarget->extent.height } }; renderingInfo.layerCount = 1; renderingInfo.colorAttachmentCount = 1; renderingInfo.pColorAttachments = &colorAttachmentInfo; VkRenderingAttachmentInfo depthAttachmentInfo{}; if (dsv) { rhi_texture_view_data* DepthStencilView = (rhi_texture_view_data*)dsv; rhi_texture_data* DepthStencil = (rhi_texture_data*) DepthStencilView->texture; depthAttachmentInfo.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; depthAttachmentInfo.imageView = DepthStencilView->imageView; depthAttachmentInfo.imageLayout = DepthStencil->layout; depthAttachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; depthAttachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE; depthAttachmentInfo.clearValue = { { { 1.0f, 1.0f, 1.0f, 1.0f } } }; renderingInfo.pDepthAttachment = &depthAttachmentInfo; } vkCmdBeginRendering(cmdbuf, &renderingInfo); VkViewport viewport{}; viewport.x = 0.f; viewport.y = (float)RenderTarget->extent.height; viewport.width = (float)RenderTarget->extent.width; viewport.height = -(float)RenderTarget->extent.height; viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; vkCmdSetViewport(cmdbuf, 0, 1, &viewport); VkRect2D scissor{}; scissor.offset = { 0, 0 }; scissor.extent = { RenderTarget->extent.width, RenderTarget->extent.height }; vkCmdSetScissor(cmdbuf, 0, 1, &scissor); } void Rhi_PassEnd() { rhi_cmdlist_data* Cmd = (rhi_cmdlist_data*)rhi->graphicsQueue.cmd; VkCommandBuffer cmdbuf = Cmd->cmdbuf; vkCmdEndRendering(cmdbuf); Cmd->passConstantHead += CbvOffset(rhi->limits.PassConstantSize); }