From 8f9dd52548ecb88a9f14a2a240a871f56c32413f Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Mon, 29 Sep 2025 21:02:18 +0700 Subject: [PATCH] Add draw triangle --- Core/Core/RenderEngine.cpp | 131 +++++++++++++++++++++++++++++++++++-- Core/Core/RenderEngine.h | 9 ++- TestGame/CMakeLists.txt | 2 +- 3 files changed, 135 insertions(+), 7 deletions(-) diff --git a/Core/Core/RenderEngine.cpp b/Core/Core/RenderEngine.cpp index 2577bc9..b31458d 100644 --- a/Core/Core/RenderEngine.cpp +++ b/Core/Core/RenderEngine.cpp @@ -383,6 +383,14 @@ void RenderEngine::create_render_pass() subpass_description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpass_description.colorAttachmentCount = 1; subpass_description.pColorAttachments = &attachment_reference; + + VkSubpassDependency dependency{}; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.srcAccessMask = 0; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; VkRenderPassCreateInfo render_pass_info{}; render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; @@ -390,6 +398,8 @@ void RenderEngine::create_render_pass() render_pass_info.pAttachments = &attachment_description; render_pass_info.subpassCount = 1; render_pass_info.pSubpasses = &subpass_description; + render_pass_info.dependencyCount = 1; + render_pass_info.pDependencies = &dependency; VK_CHECK(vkCreateRenderPass(device_, &render_pass_info, nullptr, &render_pass_)); } @@ -483,7 +493,7 @@ void RenderEngine::create_graphics_pipeline() multisample_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; VkPipelineColorBlendAttachmentState color_blend_attachment_state{}; - color_blend_attachment_state.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + color_blend_attachment_state.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; color_blend_attachment_state.blendEnable = VK_TRUE; color_blend_attachment_state.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; color_blend_attachment_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; @@ -564,7 +574,7 @@ void RenderEngine::create_command_pool() void RenderEngine::allocate_command_buffers() { - command_buffers_.resize(MAX_FRAMES_IN_FLIGHT); + command_buffers_.resize(swapchain_images_.size()); VkCommandBufferAllocateInfo command_buffer_allocate_info{}; command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; @@ -575,6 +585,104 @@ void RenderEngine::allocate_command_buffers() VK_CHECK(vkAllocateCommandBuffers(device_, &command_buffer_allocate_info, command_buffers_.data())); } +void RenderEngine::create_sync_objects() +{ + image_available_semaphores_.resize(swapchain_images_.size()); + render_finished_semaphores_.resize(swapchain_images_.size()); + in_flight_fences_.resize(swapchain_images_.size()); + + VkSemaphoreCreateInfo semaphore_info{}; + semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + VkFenceCreateInfo fence_info{}; + fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; + + for (size_t i = 0; i < swapchain_images_.size(); ++i) + { + VK_CHECK(vkCreateSemaphore(device_, &semaphore_info, nullptr, &image_available_semaphores_[i])); + VK_CHECK(vkCreateSemaphore(device_, &semaphore_info, nullptr, &render_finished_semaphores_[i])); + VK_CHECK(vkCreateFence(device_, &fence_info, nullptr, &in_flight_fences_[i])); + } +} + +void RenderEngine::record_command_buffer(VkCommandBuffer command_buffer, uint32_t image_index) +{ + VkCommandBufferBeginInfo command_buffer_begin_info{}; + command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + VK_CHECK(vkBeginCommandBuffer(command_buffer, &command_buffer_begin_info)); + + const VkClearValue clear_color = {{{0.0f, 0.0f, 0.0f, 1.0f}}}; + 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 = framebuffers_[image_index]; + render_pass_begin_info.renderArea.offset = {0, 0}; + render_pass_begin_info.renderArea.extent = swapchain_extent_; + render_pass_begin_info.clearValueCount = 1; + render_pass_begin_info.pClearValues = &clear_color; + vkCmdBeginRenderPass(command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE); + + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphycs_pipeline_); + + VkViewport viewport{}; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = static_cast(swapchain_extent_.width); + viewport.height = static_cast(swapchain_extent_.height); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + vkCmdSetViewport(command_buffer, 0, 1, &viewport); + + VkRect2D scissor{}; + scissor.offset = {0, 0}; + scissor.extent = swapchain_extent_; + vkCmdSetScissor(command_buffer, 0, 1, &scissor); + + vkCmdDraw(command_buffer, 3, 1, 0, 0); + + vkCmdEndRenderPass(command_buffer); + VK_CHECK(vkEndCommandBuffer(command_buffer)); +} + +void RenderEngine::draw_frame() +{ + vkWaitForFences(device_, 1, &in_flight_fences_[current_frame_], VK_TRUE, UINT64_MAX); + vkResetFences(device_, 1, &in_flight_fences_[current_frame_]); + + uint32_t image_index; + vkAcquireNextImageKHR(device_, swapchain_, UINT64_MAX, image_available_semaphores_[current_frame_], VK_NULL_HANDLE, &image_index); + + vkResetCommandBuffer(command_buffers_[current_frame_], 0); + record_command_buffer(command_buffers_[current_frame_], image_index); + + VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkSubmitInfo submit_info{}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &command_buffers_[current_frame_]; + submit_info.waitSemaphoreCount = 1; + submit_info.pWaitSemaphores = &image_available_semaphores_[current_frame_]; + submit_info.pWaitDstStageMask = &wait_stage; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = &render_finished_semaphores_[current_frame_]; + + VK_CHECK(vkQueueSubmit(graphics_queue_, 1, &submit_info, in_flight_fences_[current_frame_])); + + VkPresentInfoKHR present_info{}; + present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + present_info.waitSemaphoreCount = 1; + present_info.pWaitSemaphores = &render_finished_semaphores_[current_frame_]; + present_info.swapchainCount = 1; + present_info.pSwapchains = &swapchain_; + present_info.pImageIndices = &image_index; + present_info.pResults = nullptr; + + vkQueuePresentKHR(present_queue_, &present_info); + + current_frame_ = (current_frame_ + 1) % swapchain_images_.size(); +} + void RenderEngine::create_surface() { VK_CHECK(glfwCreateWindowSurface(instance_, window_, nullptr, &surface_)); @@ -595,11 +703,26 @@ window_(window) create_image_views(); create_render_pass(); create_graphics_pipeline(); + create_framebuffers(); + create_command_pool(); + allocate_command_buffers(); + create_sync_objects(); } RenderEngine::~RenderEngine() { - if (command_buffers_.size() > 0) + vkDeviceWaitIdle(device_); + + for (auto& i : image_available_semaphores_) + vkDestroySemaphore(device_, i, nullptr); + + for (auto& i : render_finished_semaphores_) + vkDestroySemaphore(device_, i, nullptr); + + for (auto& i : in_flight_fences_) + vkDestroyFence(device_, i, nullptr); + + if (command_buffers_.empty() == false) vkFreeCommandBuffers(device_, command_pool_, static_cast(command_buffers_.size()), command_buffers_.data()); if (command_pool_ != VK_NULL_HANDLE) @@ -649,8 +772,8 @@ void RenderEngine::start() { while (!glfwWindowShouldClose(window_)) { - glfwSwapBuffers(window_); glfwPollEvents(); + draw_frame(); } } diff --git a/Core/Core/RenderEngine.h b/Core/Core/RenderEngine.h index 6857c86..5dddb5e 100644 --- a/Core/Core/RenderEngine.h +++ b/Core/Core/RenderEngine.h @@ -35,7 +35,6 @@ class RenderEngine static const std::vector deviceExtensions; - const int MAX_FRAMES_IN_FLIGHT = 2; int current_frame_ = 0; CoreInstance& core_; @@ -58,6 +57,9 @@ class RenderEngine VkCommandPool command_pool_ = VK_NULL_HANDLE; std::vector command_buffers_; + std::vector image_available_semaphores_, render_finished_semaphores_; + std::vector in_flight_fences_; + #ifdef _DEBUG VkResult enable_layer_validation(VkDebugUtilsMessengerCreateInfoEXT* create_info); VkDebugUtilsMessengerEXT debug_messenger_; @@ -84,7 +86,10 @@ class RenderEngine void create_framebuffers(); void create_command_pool(); void allocate_command_buffers(); - + void create_sync_objects(); + + void record_command_buffer(VkCommandBuffer command_buffer, uint32_t image_index); + void draw_frame(); public: // Can throw the exception RenderEngine(CoreInstance& core, GLFWwindow* window, VkPresentModeKHR desired_present_mode = VK_PRESENT_MODE_MAILBOX_KHR); diff --git a/TestGame/CMakeLists.txt b/TestGame/CMakeLists.txt index 8a6a218..3b3abba 100644 --- a/TestGame/CMakeLists.txt +++ b/TestGame/CMakeLists.txt @@ -2,7 +2,7 @@ set(GAME_NAME TestGame) set(CMAKE_CXX_STANDARD 20) -file(GLOB_RECURSE SRC "*.cpp" "*.c" "*.h" "*.hpp" "*.res" "*.world" "*.conf") +file(GLOB_RECURSE SRC "*.cpp" "*.c" "*.h" "*.hpp" "*.res" "*.world" "*.conf" "*.frag" "*.vert") add_executable(${GAME_NAME} ${SRC}) target_link_libraries(${GAME_NAME} PRIVATE Core)