From 45ee4f005676daaa36ad968e5afd85bf2efc5e12 Mon Sep 17 00:00:00 2001 From: HappyTanuki Date: Sat, 17 May 2025 20:13:34 +0900 Subject: [PATCH] =?UTF-8?q?=ED=99=94=EB=A9=B4=ED=81=AC=EA=B8=B0=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 12 +++- assets/player.fbx | Bin 0 -> 11932 bytes include/precomp.h | 2 + include/vulkan/graphics.h | 36 +++++++---- src/main.cpp | 43 +++++++++++-- src/vulkan/buffers.cpp | 94 +++++++++++++++------------ src/vulkan/class.cpp | 28 +++++--- src/vulkan/devices_and_queues.cpp | 2 + src/vulkan/drawing.cpp | 102 ++++++++++++++++++------------ src/vulkan/graphics_pipeline.cpp | 59 ++++++++++++++++- src/vulkan/presentation.cpp | 6 +- src/vulkan/texture.cpp | 51 ++++++++++++--- 12 files changed, 308 insertions(+), 127 deletions(-) create mode 100644 assets/player.fbx diff --git a/CMakeLists.txt b/CMakeLists.txt index fb447ae..3aeedea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,14 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(GSL) +FetchContent_Declare( + ASSIMP + GIT_REPOSITORY "https://github.com/assimp/assimp.git" + GIT_TAG "v5.4.3" + GIT_SHALLOW ON +) +FetchContent_MakeAvailable(ASSIMP) + file(GLOB_RECURSE VulkanEngineSources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/glfw/*.cpp" @@ -50,6 +58,7 @@ target_link_libraries(VulkanEngine PRIVATE glm) target_link_libraries(VulkanEngine PRIVATE glfw) target_link_libraries(VulkanEngine PRIVATE Microsoft.GSL::GSL) target_link_libraries(VulkanEngine PRIVATE spdlog) +target_link_libraries(VulkanEngine PRIVATE assimp::assimp) target_include_directories(VulkanEngine PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") target_compile_features(VulkanEngine PRIVATE cxx_std_20) @@ -64,4 +73,5 @@ file(GLOB_RECURSE ShaderSources CONFIGURE_DEPENDS add_shaders(VulkanEngineShaders ${ShaderSources}) add_dependencies(VulkanEngine VulkanEngineShaders) -file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/assets/paving-stones.jpg" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/assets") \ No newline at end of file +file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/assets/paving-stones.jpg" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/assets") +file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/assets/player.fbx" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/assets") \ No newline at end of file diff --git a/assets/player.fbx b/assets/player.fbx new file mode 100644 index 0000000000000000000000000000000000000000..8d9bef7c90b474916a47bb9e2309f3c6703cd91b GIT binary patch literal 11932 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 azskp(ZolU3f4_CZkwdfJN!_)4*8c$fXs!JK literal 0 HcmV?d00001 diff --git a/include/precomp.h b/include/precomp.h index ab426eb..6104642 100644 --- a/include/precomp.h +++ b/include/precomp.h @@ -12,3 +12,5 @@ #include "spdlog/spdlog.h" #include "utilities.h" + +#define MAX_BUFFERED_FRAMES (2) diff --git a/include/vulkan/graphics.h b/include/vulkan/graphics.h index c285e2b..ee6e298 100644 --- a/include/vulkan/graphics.h +++ b/include/vulkan/graphics.h @@ -8,6 +8,19 @@ #include "vertex.h" namespace veng { + +struct Frame { + VkSemaphore image_available_signal = VK_NULL_HANDLE; + VkSemaphore render_finished_signal = VK_NULL_HANDLE; + VkFence still_rendering_fence = VK_NULL_HANDLE; + + VkCommandBuffer command_buffer = VK_NULL_HANDLE; + + VkDescriptorSet uniform_set = VK_NULL_HANDLE; + BufferHandle uniform_buffer; + void* uniform_buffer_location; +}; + class Graphics final { public: Graphics(gsl::not_null window); @@ -66,6 +79,7 @@ class Graphics final { void CreateDescriptorPools(); void CreateDescriptorSets(); void CreateTextureSampler(); + void CreateDepthResources(); void RecreateSwapChain(); void CleanupSwapChain(); @@ -111,11 +125,14 @@ class Graphics final { void EndTransientCommandBuffer(VkCommandBuffer command_buffer); void CreateUniformBuffers(); - TextureHandle CreateImage(glm::ivec2 size, VkBufferUsageFlags usage, + TextureHandle CreateImage(glm::ivec2 size, VkFormat image_format, + VkBufferUsageFlags usage, VkMemoryPropertyFlags properties); - void TransitionImageLayout(VkImage image, VkImageLayout old_layout, VkImageLayout new_layout); + void TransitionImageLayout(VkImage image, VkImageLayout old_layout, + VkImageLayout new_layout); void CopyBufferToImage(VkBuffer buffer, VkImage image, glm::ivec2 image_size); - VkImageView CreateImageView(VkImage image, VkFormat format); + VkImageView CreateImageView(VkImage image, VkFormat format, + VkImageAspectFlags aspect_flag); VkViewport GetViewport(); VkRect2D GetScissor(); @@ -147,23 +164,20 @@ class Graphics final { VkDescriptorSetLayout descriptor_set_layout_ = VK_NULL_HANDLE; VkCommandPool command_pool_ = VK_NULL_HANDLE; - VkCommandBuffer command_buffer_ = VK_NULL_HANDLE; - - VkSemaphore image_available_signal_ = VK_NULL_HANDLE; - VkSemaphore render_finished_signal_ = VK_NULL_HANDLE; - VkFence still_rendering_fence_ = VK_NULL_HANDLE; std::uint32_t current_image_index_ = 0; VkDescriptorSetLayout uniform_set_layout_ = VK_NULL_HANDLE; VkDescriptorPool uniform_pool_ = VK_NULL_HANDLE; - VkDescriptorSet uniform_set_ = VK_NULL_HANDLE; - BufferHandle uniform_buffer_; - void* uniform_buffer_location_; + VkDescriptorSetLayout texture_set_layout_ = VK_NULL_HANDLE; VkDescriptorPool texture_pool_ = VK_NULL_HANDLE; VkSampler texture_sampler_ = VK_NULL_HANDLE; + TextureHandle depth_texture_; + + std::array frames_; + std::int32_t current_frame_ = 0; gsl::not_null window_; bool validation_enabled_ = false; diff --git a/src/main.cpp b/src/main.cpp index 8690d34..02e1dee 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,15 +1,16 @@ #include #include +#include +#include "assimp/Importer.hpp" +#include "assimp/postprocess.h" #include "glfw/glfw_initialization.h" #include "glfw/glfw_monitor.h" #include "glfw/glfw_window.h" #include "precomp.h" #include "vulkan/graphics.h" -#include - std::int32_t main(std::int32_t argc, gsl::zstring* argv) { const veng::GlfwInitialization _glfw; @@ -18,6 +19,17 @@ std::int32_t main(std::int32_t argc, gsl::zstring* argv) { veng::Graphics graphics(&window); + Assimp::Importer assetImporter; + + const struct aiScene* scene = assetImporter.ReadFile( + "assets/player.fbx", aiProcess_CalcTangentSpace | aiProcess_Triangulate | + aiProcess_JoinIdenticalVertices | aiProcess_SortByPType); + + if (nullptr == scene) { + spdlog::error(assetImporter.GetErrorString()); + return false; + } + std::array vertices = { veng::Vertex{{-.5f, -.5f, 0.f}, {0.f, 1.f}}, veng::Vertex{{.5f, -.5f, 0.f}, {1.f, 1.f}}, @@ -30,28 +42,45 @@ std::int32_t main(std::int32_t argc, gsl::zstring* argv) { glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), glm::radians(45.f), glm::vec3(0.f, 1.f, 0.f)); + + glm::mat4 rotation2 = + glm::rotate(glm::mat4(1.0f), glm::radians(0.f), glm::vec3(0.f, 0.f, 1.f)); + glm::mat4 view = glm::translate(glm::mat4(1.f), glm::vec3(0.f, 0.f, -2.f)); glm::mat4 projection = - glm::perspective(glm::radians(60.f), 800.f / 600.f, 0.1f, 100.f); + glm::perspective(glm::radians(150.f), 800.f / 600.f, 0.1f, 100.f); graphics.SetViewProjection(view, projection); - veng::TextureHandle texture = graphics.CreateTexture("assets/paving-stones.jpg"); + veng::TextureHandle texture = + graphics.CreateTexture("assets/paving-stones.jpg"); double last_time = glfwGetTime(); + glm::ivec2 window_size; while (!window.ShouldClose()) { glfwPollEvents(); + glm::ivec2 current_window_size = window.GetFramebufferSize(); + if (current_window_size != window_size && current_window_size.x != 0 && current_window_size.y != 0) { + window_size = current_window_size; + projection = glm::perspective( + glm::radians(90.f), + (float)current_window_size.x / (float)current_window_size.y, 0.1f, + 100.f); + graphics.SetViewProjection(view, projection); + } + if (graphics.BeginFrame()) { double current_time = glfwGetTime(); float delta_time = static_cast(current_time - last_time); last_time = current_time; - std::cout << 1.f / delta_time << std::endl; - graphics.SetTexture(texture); + rotation2 = glm::rotate(rotation2, delta_time * glm::radians(-360.f), + glm::vec3(0.f, 0.f, 1.f)); + graphics.SetModelMatrix(rotation2); graphics.RenderIndexedBuffer(buffer, index_buffer, indices.size()); - rotation = glm::rotate(rotation, delta_time * glm::radians(3600.f), + rotation = glm::rotate(rotation, delta_time * glm::radians(360.f), glm::vec3(0.f, 0.f, 1.f)); graphics.SetModelMatrix(rotation); graphics.RenderIndexedBuffer(buffer, index_buffer, indices.size()); diff --git a/src/vulkan/buffers.cpp b/src/vulkan/buffers.cpp index a9222a4..37bd695 100644 --- a/src/vulkan/buffers.cpp +++ b/src/vulkan/buffers.cpp @@ -134,34 +134,40 @@ void Graphics::DestroyBuffer(BufferHandle handle) { } void Graphics::SetModelMatrix(glm::mat4 model) { - vkCmdPushConstants(command_buffer_, pipeline_layout_, + // for (Frame& frame : frames_) + vkCmdPushConstants(frames_[current_frame_].command_buffer, pipeline_layout_, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &model); } void Graphics::SetViewProjection(glm::mat4 view, glm::mat4 projection) { UniformTransformations transformations{view, projection}; - std::memcpy(uniform_buffer_location_, &transformations, - sizeof(UniformTransformations)); + for (Frame& frame : frames_) + std::memcpy(frame.uniform_buffer_location, + &transformations, sizeof(UniformTransformations)); } void Graphics::RenderBuffer(BufferHandle handle, std::uint32_t vertex_count) { VkDeviceSize offset = 0; - vkCmdBindDescriptorSets(command_buffer_, VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline_layout_, 0, 1, &uniform_set_, 0, nullptr); - vkCmdBindVertexBuffers(command_buffer_, 0, 1, &handle.buffer, &offset); - vkCmdDraw(command_buffer_, vertex_count, 1, 0, 0); + vkCmdBindDescriptorSets(frames_[current_frame_].command_buffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_, 0, + 1, &frames_[current_frame_].uniform_set, 0, nullptr); + vkCmdBindVertexBuffers(frames_[current_frame_].command_buffer, 0, 1, + &handle.buffer, &offset); + vkCmdDraw(frames_[current_frame_].command_buffer, vertex_count, 1, 0, 0); } void Graphics::RenderIndexedBuffer(BufferHandle vertex_buffer, BufferHandle index_buffer, std::uint32_t count) { VkDeviceSize offset = 0; - vkCmdBindDescriptorSets(command_buffer_, VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline_layout_, 0, 1, &uniform_set_, 0, nullptr); - vkCmdBindVertexBuffers(command_buffer_, 0, 1, &vertex_buffer.buffer, &offset); - vkCmdBindIndexBuffer(command_buffer_, index_buffer.buffer, 0, - VK_INDEX_TYPE_UINT32); - vkCmdDrawIndexed(command_buffer_, count, 1, 0, 0, 0); + vkCmdBindDescriptorSets(frames_[current_frame_].command_buffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_, 0, + 1, &frames_[current_frame_].uniform_set, 0, nullptr); + vkCmdBindVertexBuffers(frames_[current_frame_].command_buffer, 0, 1, + &vertex_buffer.buffer, &offset); + vkCmdBindIndexBuffer(frames_[current_frame_].command_buffer, + index_buffer.buffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdDrawIndexed(frames_[current_frame_].command_buffer, count, 1, 0, 0, 0); SetModelMatrix(glm::mat4(1.f)); } @@ -198,13 +204,15 @@ void Graphics::EndTransientCommandBuffer(VkCommandBuffer command_buffer) { void Graphics::CreateUniformBuffers() { VkDeviceSize buffer_size = sizeof(UniformTransformations); - uniform_buffer_ = - CreateBuffer(buffer_size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + for (Frame& frame : frames_) { + frame.uniform_buffer = + CreateBuffer(buffer_size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - vkMapMemory(logical_device_, uniform_buffer_.memory, 0, buffer_size, 0, - &uniform_buffer_location_); + vkMapMemory(logical_device_, frame.uniform_buffer.memory, 0, buffer_size, 0, + &frame.uniform_buffer_location); + } } void Graphics::CreateDescriptorSetLayouts() { @@ -249,13 +257,13 @@ void Graphics::CreateDescriptorSetLayouts() { void Graphics::CreateDescriptorPools() { VkDescriptorPoolSize uniform_pool_size = {}; uniform_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - uniform_pool_size.descriptorCount = 1; + uniform_pool_size.descriptorCount = MAX_BUFFERED_FRAMES; VkDescriptorPoolCreateInfo uniform_create_info = {}; uniform_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; uniform_create_info.poolSizeCount = 1; uniform_create_info.pPoolSizes = &uniform_pool_size; - uniform_create_info.maxSets = 1; + uniform_create_info.maxSets = MAX_BUFFERED_FRAMES; if (vkCreateDescriptorPool(logical_device_, &uniform_create_info, nullptr, &uniform_pool_) != VK_SUCCESS) { @@ -284,31 +292,33 @@ void Graphics::CreateDescriptorPools() { } void Graphics::CreateDescriptorSets() { - VkDescriptorSetAllocateInfo set_info = {}; - set_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - set_info.descriptorPool = uniform_pool_; - set_info.descriptorSetCount = 1; - set_info.pSetLayouts = &uniform_set_layout_; + for (Frame& frame : frames_) { + VkDescriptorSetAllocateInfo set_info = {}; + set_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + set_info.descriptorPool = uniform_pool_; + set_info.descriptorSetCount = 1; + set_info.pSetLayouts = &uniform_set_layout_; - VkResult result = - vkAllocateDescriptorSets(logical_device_, &set_info, &uniform_set_); - if (result != VK_SUCCESS) std::exit(EXIT_FAILURE); + VkResult result = vkAllocateDescriptorSets(logical_device_, &set_info, + &frame.uniform_set); + if (result != VK_SUCCESS) std::exit(EXIT_FAILURE); - VkDescriptorBufferInfo buffer_info = {}; - buffer_info.buffer = uniform_buffer_.buffer; - buffer_info.offset = 0; - buffer_info.range = sizeof(UniformTransformations); + VkDescriptorBufferInfo buffer_info = {}; + buffer_info.buffer = frame.uniform_buffer.buffer; + buffer_info.offset = 0; + buffer_info.range = sizeof(UniformTransformations); - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = uniform_set_; - descriptor_write.dstBinding = 0; - descriptor_write.dstArrayElement = 0; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_write.descriptorCount = 1; - descriptor_write.pBufferInfo = &buffer_info; + VkWriteDescriptorSet descriptor_write = {}; + descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptor_write.dstSet = frame.uniform_set; + descriptor_write.dstBinding = 0; + descriptor_write.dstArrayElement = 0; + descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptor_write.descriptorCount = 1; + descriptor_write.pBufferInfo = &buffer_info; - vkUpdateDescriptorSets(logical_device_, 1, &descriptor_write, 0, nullptr); + vkUpdateDescriptorSets(logical_device_, 1, &descriptor_write, 0, nullptr); + } } } // namespace veng diff --git a/src/vulkan/class.cpp b/src/vulkan/class.cpp index 183e388..2d340c3 100644 --- a/src/vulkan/class.cpp +++ b/src/vulkan/class.cpp @@ -16,6 +16,7 @@ Graphics::~Graphics() { if (logical_device_ != VK_NULL_HANDLE) { vkDeviceWaitIdle(logical_device_); CleanupSwapChain(); + DestroyTexture(depth_texture_); if (texture_pool_ != VK_NULL_HANDLE) vkDestroyDescriptorPool(logical_device_, texture_pool_, nullptr); @@ -30,21 +31,25 @@ Graphics::~Graphics() { if (uniform_pool_ != VK_NULL_HANDLE) vkDestroyDescriptorPool(logical_device_, uniform_pool_, nullptr); - DestroyBuffer(uniform_buffer_); + for (Frame& frame : frames_) { + DestroyBuffer(frame.uniform_buffer); + + if (frame.image_available_signal != VK_NULL_HANDLE) + vkDestroySemaphore(logical_device_, frame.image_available_signal, + nullptr); + + if (frame.render_finished_signal != VK_NULL_HANDLE) + vkDestroySemaphore(logical_device_, frame.render_finished_signal, + nullptr); + + if (frame.still_rendering_fence != VK_NULL_HANDLE) + vkDestroyFence(logical_device_, frame.still_rendering_fence, nullptr); + } if (uniform_set_layout_ != VK_NULL_HANDLE) vkDestroyDescriptorSetLayout(logical_device_, uniform_set_layout_, nullptr); - if (image_available_signal_ != VK_NULL_HANDLE) - vkDestroySemaphore(logical_device_, image_available_signal_, nullptr); - - if (render_finished_signal_ != VK_NULL_HANDLE) - vkDestroySemaphore(logical_device_, render_finished_signal_, nullptr); - - if (still_rendering_fence_ != VK_NULL_HANDLE) - vkDestroyFence(logical_device_, still_rendering_fence_, nullptr); - if (command_pool_ != VK_NULL_HANDLE) vkDestroyCommandPool(logical_device_, command_pool_, nullptr); @@ -81,6 +86,7 @@ void Graphics::InitializeVulkan() { CreateRenderPass(); CreateDescriptorSetLayouts(); CreateGraphicsPipeline(); + CreateDepthResources(); CreateFramebuffers(); CreateCommandPool(); CreateCommandBuffer(); @@ -89,6 +95,8 @@ void Graphics::InitializeVulkan() { CreateDescriptorPools(); CreateDescriptorSets(); CreateTextureSampler(); + TransitionImageLayout(depth_texture_.image, VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); } } // namespace veng diff --git a/src/vulkan/devices_and_queues.cpp b/src/vulkan/devices_and_queues.cpp index e11a176..358419a 100644 --- a/src/vulkan/devices_and_queues.cpp +++ b/src/vulkan/devices_and_queues.cpp @@ -140,6 +140,8 @@ void Graphics::CreateLogicalDeviceAndQueues() { } VkPhysicalDeviceFeatures required_features = {}; + required_features.depthBounds = true; + required_features.depthClamp = true; VkDeviceCreateInfo device_info = {}; device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; diff --git a/src/vulkan/drawing.cpp b/src/vulkan/drawing.cpp index 73d2a29..6433918 100644 --- a/src/vulkan/drawing.cpp +++ b/src/vulkan/drawing.cpp @@ -9,11 +9,14 @@ void Graphics::CreateFramebuffers() { swap_chain_framebuffers_.resize(swap_chain_image_views_.size()); for (std::uint32_t i = 0; i < swap_chain_image_views_.size(); i++) { + std::array attachments = {swap_chain_image_views_[i], + depth_texture_.image_view}; + VkFramebufferCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; info.renderPass = render_pass_; - info.attachmentCount = 1; - info.pAttachments = &swap_chain_image_views_[i]; + info.attachmentCount = attachments.size(); + info.pAttachments = attachments.data(); info.width = extent_.width; info.height = extent_.height; info.layers = 1; @@ -43,21 +46,28 @@ void Graphics::CreateCommandBuffer() { info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; info.commandBufferCount = 1; - VkResult result = - vkAllocateCommandBuffers(logical_device_, &info, &command_buffer_); - if (result != VK_SUCCESS) std::exit(EXIT_FAILURE); + for (Frame& frame : frames_) { + VkResult result = + vkAllocateCommandBuffers(logical_device_, &info, &frame.command_buffer); + if (result != VK_SUCCESS) std::exit(EXIT_FAILURE); + } } void Graphics::BeginCommands() { - vkResetCommandBuffer(command_buffer_, 0); + vkResetCommandBuffer(frames_[current_frame_].command_buffer, 0); VkCommandBufferBeginInfo begin_info = {}; begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - VkResult result = vkBeginCommandBuffer(command_buffer_, &begin_info); + VkResult result = vkBeginCommandBuffer( + frames_[current_frame_].command_buffer, &begin_info); if (result != VK_SUCCESS) throw std::runtime_error("Failed to begin command buffer!"); + std::array clear_values; + clear_values[0].color = {{0.f, 0.f, 0.f, 1.f}}; + clear_values[1].depthStencil = {1.f, 0}; + VkRenderPassBeginInfo render_pass_begin_info = {}; render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; render_pass_begin_info.renderPass = render_pass_; @@ -65,54 +75,60 @@ void Graphics::BeginCommands() { swap_chain_framebuffers_[current_image_index_]; render_pass_begin_info.renderArea.offset = {0, 0}; render_pass_begin_info.renderArea.extent = extent_; + render_pass_begin_info.clearValueCount = clear_values.size(); + render_pass_begin_info.pClearValues = clear_values.data(); - VkClearValue clear_color = {{{0.f, 0.f, 0.f, 1.f}}}; - render_pass_begin_info.clearValueCount = 1; - render_pass_begin_info.pClearValues = &clear_color; - - vkCmdBeginRenderPass(command_buffer_, &render_pass_begin_info, + vkCmdBeginRenderPass(frames_[current_frame_].command_buffer, + &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE); - vkCmdBindPipeline(command_buffer_, VK_PIPELINE_BIND_POINT_GRAPHICS, + vkCmdBindPipeline(frames_[current_frame_].command_buffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_); VkViewport viewport = GetViewport(); VkRect2D scissor = GetScissor(); - vkCmdSetViewport(command_buffer_, 0, 1, &viewport); - vkCmdSetScissor(command_buffer_, 0, 1, &scissor); + vkCmdSetViewport(frames_[current_frame_].command_buffer, 0, 1, &viewport); + vkCmdSetScissor(frames_[current_frame_].command_buffer, 0, 1, &scissor); } void Graphics::EndCommands() { - vkCmdEndRenderPass(command_buffer_); - VkResult result = vkEndCommandBuffer(command_buffer_); + vkCmdEndRenderPass(frames_[current_frame_].command_buffer); + VkResult result = vkEndCommandBuffer(frames_[current_frame_].command_buffer); if (result != VK_SUCCESS) throw std::runtime_error("Failed to record command buffer!"); } void Graphics::CreateSignals() { - VkSemaphoreCreateInfo semafore_info = {}; - semafore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + for (Frame& frame : frames_) { + VkSemaphoreCreateInfo semafore_info = {}; + semafore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - if (vkCreateSemaphore(logical_device_, &semafore_info, nullptr, - &image_available_signal_) != VK_SUCCESS) - std::exit(EXIT_FAILURE); - if (vkCreateSemaphore(logical_device_, &semafore_info, nullptr, - &render_finished_signal_) != VK_SUCCESS) - std::exit(EXIT_FAILURE); + if (vkCreateSemaphore(logical_device_, &semafore_info, nullptr, + &frame.image_available_signal) != + VK_SUCCESS) + std::exit(EXIT_FAILURE); + if (vkCreateSemaphore(logical_device_, &semafore_info, nullptr, + &frame.render_finished_signal) != + VK_SUCCESS) + std::exit(EXIT_FAILURE); - VkFenceCreateInfo fence_info = {}; - fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; + VkFenceCreateInfo fence_info = {}; + fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; - if (vkCreateFence(logical_device_, &fence_info, nullptr, - &still_rendering_fence_) != VK_SUCCESS) - std::exit(EXIT_FAILURE); + if (vkCreateFence(logical_device_, &fence_info, nullptr, + &frame.still_rendering_fence) != + VK_SUCCESS) + std::exit(EXIT_FAILURE); + } } bool Graphics::BeginFrame() { - vkWaitForFences(logical_device_, 1, &still_rendering_fence_, VK_TRUE, + vkWaitForFences(logical_device_, 1, + &frames_[current_frame_].still_rendering_fence, VK_TRUE, UINT64_MAX); - VkResult image_acquire_result = vkAcquireNextImageKHR( - logical_device_, swap_chain_, UINT64_MAX, image_available_signal_, + VkResult image_acquire_result = vkAcquireNextImageKHR(logical_device_, swap_chain_, UINT64_MAX, + frames_[current_frame_].image_available_signal, VK_NULL_HANDLE, ¤t_image_index_); if (image_acquire_result == VK_ERROR_OUT_OF_DATE_KHR) { @@ -124,7 +140,8 @@ bool Graphics::BeginFrame() { image_acquire_result != VK_SUBOPTIMAL_KHR) throw std::runtime_error("Couldn't acquire render image!"); - vkResetFences(logical_device_, 1, &still_rendering_fence_); + vkResetFences(logical_device_, 1, + &frames_[current_frame_].still_rendering_fence); BeginCommands(); SetModelMatrix(glm::mat4(1.f)); @@ -139,22 +156,25 @@ void veng::Graphics::EndFrame() { VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = &image_available_signal_; + submit_info.pWaitSemaphores = &frames_[current_frame_].image_available_signal; submit_info.pWaitDstStageMask = &wait_stage; submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer_; + submit_info.pCommandBuffers = &frames_[current_frame_].command_buffer; submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &render_finished_signal_; + submit_info.pSignalSemaphores = + &frames_[current_frame_].render_finished_signal; VkResult submit_result = - vkQueueSubmit(graphics_queue_, 1, &submit_info, still_rendering_fence_); + vkQueueSubmit(graphics_queue_, 1, &submit_info, + frames_[current_frame_].still_rendering_fence); if (submit_result != VK_SUCCESS) throw std::runtime_error("failed to submit draw commands!"); VkPresentInfoKHR present_info = {}; present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; present_info.waitSemaphoreCount = 1; - present_info.pWaitSemaphores = &render_finished_signal_; + present_info.pWaitSemaphores = + &frames_[current_frame_].render_finished_signal; present_info.swapchainCount = 1; present_info.pSwapchains = &swap_chain_; present_info.pImageIndices = ¤t_image_index_; @@ -164,6 +184,8 @@ void veng::Graphics::EndFrame() { RecreateSwapChain(); else if (result != VK_SUCCESS) throw std::runtime_error("Failed to present swap chain image!"); + + current_frame_ = (current_frame_++) % MAX_BUFFERED_FRAMES; } } // namespace veng diff --git a/src/vulkan/graphics_pipeline.cpp b/src/vulkan/graphics_pipeline.cpp index 91f1a48..34692eb 100644 --- a/src/vulkan/graphics_pipeline.cpp +++ b/src/vulkan/graphics_pipeline.cpp @@ -149,6 +149,17 @@ void Graphics::CreateGraphicsPipeline() { color_blending_info.attachmentCount = 1; color_blending_info.pAttachments = &color_blend_attachment; + VkPipelineDepthStencilStateCreateInfo depth_stencil_info = {}; + depth_stencil_info.sType = + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depth_stencil_info.depthTestEnable = VK_TRUE; + depth_stencil_info.depthWriteEnable = VK_TRUE; + depth_stencil_info.depthCompareOp = VK_COMPARE_OP_LESS; + depth_stencil_info.depthBoundsTestEnable = VK_TRUE; + depth_stencil_info.minDepthBounds = 0.f; + depth_stencil_info.maxDepthBounds = 1.f; + depth_stencil_info.stencilTestEnable = VK_FALSE; + VkPushConstantRange model_matrix_range = {}; model_matrix_range.offset = 0; model_matrix_range.size = sizeof(glm::mat4); @@ -177,7 +188,7 @@ void Graphics::CreateGraphicsPipeline() { pipeline_info.pViewportState = &viewport_info; pipeline_info.pRasterizationState = &rasterization_state_info; pipeline_info.pMultisampleState = &multisampling_info; - pipeline_info.pDepthStencilState = nullptr; + pipeline_info.pDepthStencilState = &depth_stencil_info; pipeline_info.pColorBlendState = &color_blending_info; pipeline_info.pDynamicState = &dynamic_state_info; pipeline_info.layout = pipeline_layout_; @@ -204,17 +215,50 @@ void Graphics::CreateRenderPass() { color_attachment_ref.attachment = 0; color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkAttachmentDescription depth_attachment = {}; + depth_attachment.format = VK_FORMAT_D32_SFLOAT; + depth_attachment.samples = VK_SAMPLE_COUNT_1_BIT; + depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + depth_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + depth_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + depth_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + depth_attachment.finalLayout = + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkAttachmentReference depth_attachment_ref = {}; + depth_attachment_ref.attachment = 1; + depth_attachment_ref.layout = + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + VkSubpassDescription main_subpass = {}; main_subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; main_subpass.colorAttachmentCount = 1; main_subpass.pColorAttachments = &color_attachment_ref; + main_subpass.pDepthStencilAttachment = &depth_attachment_ref; + + VkSubpassDependency dependency = {}; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.srcAccessMask = 0; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + + std::array attachments = {color_attachment, + depth_attachment}; VkRenderPassCreateInfo render_pass_info = {}; render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - render_pass_info.attachmentCount = 1; - render_pass_info.pAttachments = &color_attachment; + render_pass_info.attachmentCount = attachments.size(); + render_pass_info.pAttachments = attachments.data(); render_pass_info.subpassCount = 1; render_pass_info.pSubpasses = &main_subpass; + render_pass_info.dependencyCount = 1; + render_pass_info.pDependencies = &dependency; VkResult result = vkCreateRenderPass(logical_device_, &render_pass_info, nullptr, &render_pass_); @@ -234,6 +278,7 @@ void veng::Graphics::RecreateSwapChain() { CreateSwapChain(); CreateImageViews(); + CreateDepthResources(); CreateFramebuffers(); } @@ -248,6 +293,14 @@ void veng::Graphics::CleanupSwapChain() { if (swap_chain_ != VK_NULL_HANDLE) vkDestroySwapchainKHR(logical_device_, swap_chain_, nullptr); + + vkDeviceWaitIdle(logical_device_); + vkDestroyImageView(logical_device_, depth_texture_.image_view, nullptr); + depth_texture_.image_view = VK_NULL_HANDLE; + vkDestroyImage(logical_device_, depth_texture_.image, nullptr); + depth_texture_.image = VK_NULL_HANDLE; + vkFreeMemory(logical_device_, depth_texture_.memory, nullptr); + depth_texture_.memory = VK_NULL_HANDLE; } } // namespace veng diff --git a/src/vulkan/presentation.cpp b/src/vulkan/presentation.cpp index c016312..472860e 100644 --- a/src/vulkan/presentation.cpp +++ b/src/vulkan/presentation.cpp @@ -140,7 +140,7 @@ void Graphics::CreateSwapChain() { swap_chain_images_.data()); } -VkImageView Graphics::CreateImageView(VkImage image, VkFormat format) { +VkImageView Graphics::CreateImageView(VkImage image, VkFormat format, VkImageAspectFlags aspect_flag) { VkImageViewCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; info.image = image; @@ -150,7 +150,7 @@ VkImageView Graphics::CreateImageView(VkImage image, VkFormat format) { info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + info.subresourceRange.aspectMask = aspect_flag; info.subresourceRange.baseMipLevel = 0; info.subresourceRange.levelCount = 1; info.subresourceRange.baseArrayLayer = 0; @@ -167,7 +167,7 @@ void Graphics::CreateImageViews() { auto image_view_it = swap_chain_image_views_.begin(); for (VkImage image : swap_chain_images_) { - *image_view_it = CreateImageView(image, surface_format_.format); + *image_view_it = CreateImageView(image, surface_format_.format, VK_IMAGE_ASPECT_COLOR_BIT); std::advance(image_view_it, 1); } diff --git a/src/vulkan/texture.cpp b/src/vulkan/texture.cpp index ee3f0ff..927a558 100644 --- a/src/vulkan/texture.cpp +++ b/src/vulkan/texture.cpp @@ -52,7 +52,7 @@ TextureHandle Graphics::CreateTexture(gsl::czstring path) { stbi_image_free(pixel_data); TextureHandle handle = - CreateImage(image_extents, + CreateImage(image_extents, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); @@ -62,7 +62,8 @@ TextureHandle Graphics::CreateTexture(gsl::czstring path) { TransitionImageLayout(handle.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - handle.image_view = CreateImageView(handle.image, VK_FORMAT_R8G8B8A8_SRGB); + handle.image_view = CreateImageView(handle.image, VK_FORMAT_R8G8B8A8_SRGB, + VK_IMAGE_ASPECT_COLOR_BIT); VkDescriptorSetAllocateInfo set_info = {}; set_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; @@ -96,14 +97,23 @@ TextureHandle Graphics::CreateTexture(gsl::czstring path) { void Graphics::DestroyTexture(TextureHandle handle) { vkDeviceWaitIdle(logical_device_); - vkFreeDescriptorSets(logical_device_, texture_pool_, 1, &handle.set); - vkDestroyImageView(logical_device_, handle.image_view, nullptr); - vkDestroyImage(logical_device_, handle.image, nullptr); - vkFreeMemory(logical_device_, handle.memory, nullptr); + + if (handle.set != VK_NULL_HANDLE) + vkFreeDescriptorSets(logical_device_, texture_pool_, 1, &handle.set); + + if (handle.image_view != VK_NULL_HANDLE) + vkDestroyImageView(logical_device_, handle.image_view, nullptr); + + if (handle.image != VK_NULL_HANDLE) + vkDestroyImage(logical_device_, handle.image, nullptr); + + if (handle.memory != VK_NULL_HANDLE) + vkFreeMemory(logical_device_, handle.memory, nullptr); } void Graphics::SetTexture(TextureHandle handle) { - vkCmdBindDescriptorSets(command_buffer_, VK_PIPELINE_BIND_POINT_GRAPHICS, + vkCmdBindDescriptorSets(frames_[current_frame_].command_buffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_, 1, 1, &handle.set, 0, nullptr); } @@ -118,7 +128,6 @@ void Graphics::TransitionImageLayout(VkImage image, VkImageLayout old_layout, barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.image = image; - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; barrier.subresourceRange.baseArrayLayer = 0; barrier.subresourceRange.baseMipLevel = 0; barrier.subresourceRange.levelCount = 1; @@ -139,8 +148,20 @@ void Graphics::TransitionImageLayout(VkImage image, VkImageLayout old_layout, barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; destination_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } else if (old_layout == VK_IMAGE_LAYOUT_UNDEFINED && + new_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { + barrier.srcAccessMask = 0; + barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + destination_stage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; } + if (new_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + else + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + vkCmdPipelineBarrier(local_command_buffer, source_stage, destination_stage, 0, 0, nullptr, 0, nullptr, 1, &barrier); @@ -169,7 +190,8 @@ void Graphics::CopyBufferToImage(VkBuffer buffer, VkImage image, EndTransientCommandBuffer(local_command_buffer); } -TextureHandle Graphics::CreateImage(glm::ivec2 size, VkBufferUsageFlags usage, +TextureHandle Graphics::CreateImage(glm::ivec2 size, VkFormat image_format, + VkBufferUsageFlags usage, VkMemoryPropertyFlags properties) { TextureHandle handle = {}; @@ -183,7 +205,7 @@ TextureHandle Graphics::CreateImage(glm::ivec2 size, VkBufferUsageFlags usage, image_info.extent.depth = 1; image_info.mipLevels = 1; image_info.arrayLayers = 1; - image_info.format = VK_FORMAT_R8G8B8A8_SRGB; + image_info.format = image_format; image_info.tiling = VK_IMAGE_TILING_OPTIMAL; image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; image_info.samples = VK_SAMPLE_COUNT_1_BIT; @@ -216,4 +238,13 @@ TextureHandle Graphics::CreateImage(glm::ivec2 size, VkBufferUsageFlags usage, return handle; } +void Graphics::CreateDepthResources() { + VkFormat kDepthFormat = VK_FORMAT_D32_SFLOAT; + depth_texture_ = CreateImage({extent_.width, extent_.height}, kDepthFormat, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + depth_texture_.image_view = CreateImageView( + depth_texture_.image, kDepthFormat, VK_IMAGE_ASPECT_DEPTH_BIT); +} + } // namespace veng