From d10e76d5a1a6b2b425cc6c780d91f52695177a02 Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Sat, 5 Apr 2025 00:47:00 +0200 Subject: Enable & use synchronization2 --- hk21/game/gpu.cpp | 126 +++++++++++++++++++++++++++++++++++---------- hk21/vulkan_loader/fns.hpp | 7 +-- 2 files changed, 104 insertions(+), 29 deletions(-) diff --git a/hk21/game/gpu.cpp b/hk21/game/gpu.cpp index c036cf2..3ea0da1 100644 --- a/hk21/game/gpu.cpp +++ b/hk21/game/gpu.cpp @@ -15,6 +15,11 @@ #include "hk21/vulkan_loader/api.hpp" +// @Todo Make fences recyclable +// @Todo Make command pool recyclable +// @Todo Make frame structure recyclable +// @Todo Auto barriers for images + #define VK_ALLOCATOR nullptr [[maybe_unused]] static void AslFormat(asl::Formatter& formatter, VkResult res) @@ -194,6 +199,22 @@ static asl::status_or find_physical_device(VkInstance instan continue; } + VkPhysicalDeviceSynchronization2Features synchronization2_features{}; + synchronization2_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES; + synchronization2_features.pNext = nullptr; + + VkPhysicalDeviceFeatures2 features{}; + features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + features.pNext = &synchronization2_features; + + vkGetPhysicalDeviceFeatures2(physical_device, &features); + + if (synchronization2_features.synchronization2 != VK_TRUE) + { + ASL_LOG_INFO("Device {}: synchronization2 not supported", name); + continue; + } + uint32_t queue_family_count{}; vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, nullptr); queue_family_prps.resize_zero(queue_family_count); @@ -232,9 +253,14 @@ static asl::status_or create_device(VkPhysicalDevice physical_device, .pQueuePriorities = &queue_priority, }; + VkPhysicalDeviceSynchronization2Features synchronization2_features{}; + synchronization2_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES; + synchronization2_features.pNext = nullptr; + synchronization2_features.synchronization2 = VK_TRUE; + VkDeviceCreateInfo create_info{ .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, - .pNext = nullptr, + .pNext = &synchronization2_features, .flags = 0, .queueCreateInfoCount = 1, .pQueueCreateInfos = &queue_create_info, @@ -535,11 +561,13 @@ public: return asl::runtime_error("Couldn't begin command buffer: {}", res); } - VkImageMemoryBarrier barrier1{ - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + VkImageMemoryBarrier2 barrier1{ + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, .pNext = nullptr, - .srcAccessMask = 0, - .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .srcStageMask = VK_PIPELINE_STAGE_2_NONE, + .srcAccessMask = VK_ACCESS_2_NONE, + .dstStageMask = VK_PIPELINE_STAGE_2_CLEAR_BIT, + .dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, .newLayout = VK_IMAGE_LAYOUT_GENERAL, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, @@ -554,7 +582,19 @@ public: }, }; - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier1); + VkDependencyInfo dependency_info1{ + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pNext = nullptr, + .dependencyFlags = 0, + .memoryBarrierCount = 0, + .pMemoryBarriers = nullptr, + .bufferMemoryBarrierCount = 0, + .pBufferMemoryBarriers = nullptr, + .imageMemoryBarrierCount = 1, + .pImageMemoryBarriers = &barrier1, + }; + + vkCmdPipelineBarrier2(command_buffer, &dependency_info1); VkClearColorValue clear_color{ .float32 = { 0.0F, 0.137F, 0.4F, 1.0F }, @@ -570,11 +610,13 @@ public: vkCmdClearColorImage(command_buffer, m_swapchain_images[image_index], VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, &range); - VkImageMemoryBarrier barrier2{ - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + VkImageMemoryBarrier2 barrier2{ + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, .pNext = nullptr, - .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, - .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, + .srcStageMask = VK_PIPELINE_STAGE_2_CLEAR_BIT, + .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, + .dstStageMask = VK_PIPELINE_STAGE_2_NONE, + .dstAccessMask = VK_ACCESS_2_NONE, .oldLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, @@ -589,7 +631,19 @@ public: }, }; - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier2); + VkDependencyInfo dependency_info2{ + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pNext = nullptr, + .dependencyFlags = 0, + .memoryBarrierCount = 0, + .pMemoryBarriers = nullptr, + .bufferMemoryBarrierCount = 0, + .pBufferMemoryBarriers = nullptr, + .imageMemoryBarrierCount = 1, + .pImageMemoryBarriers = &barrier2, + }; + + vkCmdPipelineBarrier2(command_buffer, &dependency_info2); res = vkEndCommandBuffer(command_buffer); if (res != VK_SUCCESS) @@ -597,23 +651,46 @@ public: return asl::runtime_error("Couldn't end command buffer: {}", res); } - VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - VkFence fence = create_fence(); - VkSubmitInfo submit_info{ - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + VkSemaphoreSubmitInfo semaphore_wait_submit_info{ + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, .pNext = nullptr, - .waitSemaphoreCount = 1, - .pWaitSemaphores = &m_swapchain_image_acquire_semaphore, - .pWaitDstStageMask = &wait_dst_stage_mask, - .commandBufferCount = 1, - .pCommandBuffers = &command_buffer, - .signalSemaphoreCount = 1, - .pSignalSemaphores = &m_queue_complete_semaphore, + .semaphore = m_swapchain_image_acquire_semaphore, + .value = 0, + .stageMask = VK_PIPELINE_STAGE_2_CLEAR_BIT, + .deviceIndex = 0, }; - res = vkQueueSubmit(m_queue, 1, &submit_info, fence); + VkSemaphoreSubmitInfo semaphore_signal_submit_info{ + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, + .pNext = nullptr, + .semaphore = m_queue_complete_semaphore, + .value = 0, + .stageMask = VK_PIPELINE_STAGE_2_CLEAR_BIT, + .deviceIndex = 0, + }; + + VkCommandBufferSubmitInfo command_buffer_submit_info{ + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO, + .pNext = nullptr, + .commandBuffer = command_buffer, + .deviceMask = 0, + }; + + VkSubmitInfo2 submit_info{ + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2, + .pNext = nullptr, + .flags = 0, + .waitSemaphoreInfoCount = 1, + .pWaitSemaphoreInfos = &semaphore_wait_submit_info, + .commandBufferInfoCount = 1, + .pCommandBufferInfos = &command_buffer_submit_info, + .signalSemaphoreInfoCount = 1, + .pSignalSemaphoreInfos = &semaphore_signal_submit_info, + }; + + res = vkQueueSubmit2(m_queue, 1, &submit_info, fence); if (res != VK_SUCCESS) { return asl::runtime_error("Couldn't submit queue: {}", res); @@ -645,9 +722,6 @@ public: return asl::ok(); } - // @Todo Make fences recyclable - // @Todo Make frame structure recyclable - void recycle_resources() { while (!m_in_flight_frames.is_empty()) diff --git a/hk21/vulkan_loader/fns.hpp b/hk21/vulkan_loader/fns.hpp index 2870397..377b103 100644 --- a/hk21/vulkan_loader/fns.hpp +++ b/hk21/vulkan_loader/fns.hpp @@ -16,7 +16,8 @@ FN(vkGetDeviceProcAddr) \ FN(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) \ FN(vkGetPhysicalDeviceSurfaceFormatsKHR) \ - FN(vkGetPhysicalDeviceSurfacePresentModesKHR) + FN(vkGetPhysicalDeviceSurfacePresentModesKHR) \ + FN(vkGetPhysicalDeviceFeatures2) #define VULKAN_DEVICE_FNS \ FN(vkDestroyDevice) \ @@ -35,10 +36,10 @@ FN(vkFreeCommandBuffers) \ FN(vkBeginCommandBuffer) \ FN(vkEndCommandBuffer) \ - FN(vkQueueSubmit) \ + FN(vkQueueSubmit2) \ FN(vkCreateSemaphore) \ FN(vkDestroySemaphore) \ - FN(vkCmdPipelineBarrier) \ + FN(vkCmdPipelineBarrier2) \ FN(vkCmdClearColorImage) \ FN(vkCreateFence) \ FN(vkDestroyFence) \ -- cgit