diff --git a/include/vk.h b/include/vk.h index dcfefef..88a5155 100644 --- a/include/vk.h +++ b/include/vk.h @@ -13,6 +13,7 @@ class Vulkan public: void init(GLFWwindow* window); // инициализация void destroy(); // завершение работы + void renderFrame(); // рендер кадра private: VkInstance instance; // Экземпляр Vulkan PhysicalDevice physicalDevice; // Физическое устройство @@ -35,6 +36,7 @@ class Vulkan std::vector imageAvailableSemaphores; // семафор доступности изображения std::vector renderFinishedSemaphores; // семафор окончания рендера std::vector inWorkFences; // барьер кадра в работе + uint32_t currentFrame = 0; // Текущий кадр рендера // Структура для хранения флагов struct diff --git a/src/main.cpp b/src/main.cpp index 846b86d..f428a4d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,6 +30,7 @@ int main(int argc, char* argv[]) { while(!glfwWindowShouldClose(window)) { // Обработка событий glfwPollEvents(); + vulkan.renderFrame(); } // Уничтожение окна diff --git a/src/vk.cpp b/src/vk.cpp index 391ed1a..98a131e 100644 --- a/src/vk.cpp +++ b/src/vk.cpp @@ -991,3 +991,78 @@ void Vulkan::createFramebuffers() } } } + +// Рендер кадра +void Vulkan::renderFrame() +{ + vkWaitForFences(logicalDevice, 1, &inWorkFences[currentFrame], VK_TRUE, UINT64_MAX); + vkResetFences(logicalDevice, 1, &inWorkFences[currentFrame]); + + uint32_t imageIndex; + VkResult result = vkAcquireNextImageKHR(logicalDevice, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); + + if (result != VK_SUCCESS) + { + throw std::runtime_error("Unable to acquire swap chain image"); + } + + vkResetCommandBuffer(commandBuffers[currentFrame], 0); + VkCommandBufferBeginInfo beginInfo{}; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + + if (vkBeginCommandBuffer(commandBuffers[currentFrame], &beginInfo) != VK_SUCCESS) + { + throw std::runtime_error("Unable to begin recording command buffer"); + } + + VkClearValue clearColor = {0.0f, 0.0f, 0.0f, 1.0f}; + + VkRenderPassBeginInfo renderPassInfo{}; + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + renderPassInfo.renderPass = renderPass; + renderPassInfo.framebuffer = swapChainFramebuffers[imageIndex]; + renderPassInfo.renderArea.offset = {0, 0}; + renderPassInfo.renderArea.extent = surface.selectedExtent; + renderPassInfo.clearValueCount = 1; + renderPassInfo.pClearValues = &clearColor; + + vkCmdBeginRenderPass(commandBuffers[currentFrame], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); + + vkCmdBindPipeline(commandBuffers[currentFrame], VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline); + + VkBuffer vertexBuffers[] = {vertexBuffer}; + VkDeviceSize offsets[] = {0}; + vkCmdBindVertexBuffers(commandBuffers[currentFrame], 0, 1, vertexBuffers, offsets); + + vkCmdBindIndexBuffer(commandBuffers[currentFrame], indexBuffer, 0, VK_INDEX_TYPE_UINT16); + + vkCmdDrawIndexed(commandBuffers[currentFrame], 6, 1, 0, 0, 0); + + vkCmdEndRenderPass(commandBuffers[currentFrame]); + + if (vkEndCommandBuffer(commandBuffers[currentFrame]) != VK_SUCCESS) + { + throw std::runtime_error("Unable to record command buffer"); + } + + VkSemaphore waitSemaphores[] = {imageAvailableSemaphores[currentFrame]}; + VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; + VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[currentFrame]}; + + VkSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.waitSemaphoreCount = 1; + submitInfo.pWaitSemaphores = waitSemaphores; + submitInfo.pWaitDstStageMask = waitStages; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffers[currentFrame]; + submitInfo.signalSemaphoreCount = 1; + submitInfo.pSignalSemaphores = signalSemaphores; + + if (vkQueueSubmit(queue.descriptor, 1, &submitInfo, inWorkFences[currentFrame]) != VK_SUCCESS) + { + throw std::runtime_error("Unable to submit draw command buffer"); + } + + currentFrame = (currentFrame + 1) % surface.imageCount; +}