diff --git a/samples/api/hpp_oit_linked_lists/hpp_oit_linked_lists.cpp b/samples/api/hpp_oit_linked_lists/hpp_oit_linked_lists.cpp index f03f286b0c..9f287d39b4 100644 --- a/samples/api/hpp_oit_linked_lists/hpp_oit_linked_lists.cpp +++ b/samples/api/hpp_oit_linked_lists/hpp_oit_linked_lists.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2023-2025, NVIDIA +/* Copyright (c) 2023-2026, NVIDIA * * SPDX-License-Identifier: Apache-2.0 * @@ -20,6 +20,8 @@ HPPOITLinkedLists::HPPOITLinkedLists() { title = "HPP OIT linked lists"; + + add_device_extension(vk::KHRSynchronization2ExtensionName); } HPPOITLinkedLists::~HPPOITLinkedLists() @@ -94,6 +96,8 @@ void HPPOITLinkedLists::request_gpu_features(vkb::core::PhysicalDeviceCpp &gpu) { requested_features.samplerAnisotropy = true; } + + REQUEST_REQUIRED_FEATURE(gpu, vk::PhysicalDeviceSynchronization2FeaturesKHR, synchronization2); } void HPPOITLinkedLists::build_command_buffers() @@ -132,15 +136,18 @@ void HPPOITLinkedLists::build_command_buffers() } command_buffer.endRenderPass(); - vkb::common::image_layout_transition(command_buffer, - linked_list_head_image->get_handle(), - vk::PipelineStageFlagBits::eFragmentShader, - vk::PipelineStageFlagBits::eFragmentShader, - vk::AccessFlagBits::eShaderWrite, - vk::AccessFlagBits::eShaderRead, - vk::ImageLayout::eGeneral, - vk::ImageLayout::eGeneral, - {vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1}); + // Insert a pipeline barrier to ensure that all writes to the fragment buffer performed in the gather pass are made available before reading from it in the combine pass + vk::BufferMemoryBarrier2 buffer_barrier{.srcStageMask = vk::PipelineStageFlagBits2::eFragmentShader, + .srcAccessMask = vk::AccessFlagBits2::eShaderStorageWrite, + .dstStageMask = vk::PipelineStageFlagBits2::eFragmentShader, + .dstAccessMask = vk::AccessFlagBits2::eShaderStorageRead, + .srcQueueFamilyIndex = vk::QueueFamilyIgnored, + .dstQueueFamilyIndex = vk::QueueFamilyIgnored, + .buffer = fragment_buffer->get_handle(), + .offset = 0, + .size = vk::WholeSize}; + vk::DependencyInfo dependency_info{.dependencyFlags = vk::DependencyFlagBits::eByRegion, .bufferMemoryBarrierCount = 1, .pBufferMemoryBarriers = &buffer_barrier}; + command_buffer.pipelineBarrier2(dependency_info); // Combine pass combine_render_pass_begin_info.framebuffer = framebuffers[i]; @@ -270,21 +277,26 @@ void HPPOITLinkedLists::create_fragment_resources(vk::Extent2D const &extent) { const vk::Extent3D image_extent{extent.width, extent.height, 1}; const vk::Format image_format{vk::Format::eR32Uint}; - linked_list_head_image = std::make_unique(get_device(), - image_extent, - image_format, - vk::ImageUsageFlagBits::eStorage | vk::ImageUsageFlagBits::eTransferDst, - VMA_MEMORY_USAGE_GPU_ONLY, - vk::SampleCountFlagBits::e1); + linked_list_head_image = std::make_unique(get_device(), + image_extent, + image_format, + vk::ImageUsageFlagBits::eStorage | vk::ImageUsageFlagBits::eTransferDst, + VMA_MEMORY_USAGE_GPU_ONLY, + vk::SampleCountFlagBits::e1); + linked_list_head_image->set_debug_name("linked_list_head_image"); + linked_list_head_image_view = std::make_unique(*linked_list_head_image, vk::ImageViewType::e2D, image_format); + linked_list_head_image_view->set_debug_name("linked_list_head_image_view"); fragment_max_count = extent.width * extent.height * kFragmentsPerPixelAverage; const uint32_t fragment_buffer_size = sizeof(glm::uvec3) * fragment_max_count; fragment_buffer = std::make_unique(get_device(), fragment_buffer_size, vk::BufferUsageFlagBits::eStorageBuffer, VMA_MEMORY_USAGE_GPU_ONLY); + fragment_buffer->set_debug_name("fragment_buffer"); fragment_counter = std::make_unique( get_device(), sizeof(glm::uint), vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eTransferDst, VMA_MEMORY_USAGE_GPU_ONLY); + fragment_counter->set_debug_name("fragment_counter"); } void HPPOITLinkedLists::create_gather_pass_objects(vk::Extent2D const &extent) diff --git a/samples/api/oit_linked_lists/oit_linked_lists.cpp b/samples/api/oit_linked_lists/oit_linked_lists.cpp index a854e5225a..3fb24a6baf 100644 --- a/samples/api/oit_linked_lists/oit_linked_lists.cpp +++ b/samples/api/oit_linked_lists/oit_linked_lists.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2023-2025, Google +/* Copyright (c) 2023-2026, Google * * SPDX-License-Identifier: Apache-2.0 * @@ -20,6 +20,9 @@ OITLinkedLists::OITLinkedLists() { + title = "OIT linked lists"; + + add_device_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME); } OITLinkedLists::~OITLinkedLists() @@ -115,6 +118,8 @@ void OITLinkedLists::request_gpu_features(vkb::core::PhysicalDeviceC &gpu) { throw std::runtime_error("This sample requires support for buffers and images stores and atomic operations in the fragment shader stage"); } + + REQUEST_REQUIRED_FEATURE(gpu, VkPhysicalDeviceSynchronization2FeaturesKHR, synchronization2); } void OITLinkedLists::on_update_ui_overlay(vkb::Drawer &drawer) @@ -161,13 +166,19 @@ void OITLinkedLists::build_command_buffers() vkCmdEndRenderPass(draw_cmd_buffers[i]); } - VkImageSubresourceRange subresource_range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - vkb::image_layout_transition( - draw_cmd_buffers[i], linked_list_head_image->get_handle(), - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, - VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, - subresource_range); + // Insert a pipeline barrier to ensure that all writes to the fragment buffer performed in the gather pass are made available before reading from it in the combine pass + VkBufferMemoryBarrier2 buffer_barrier{.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2, + .srcStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, + .srcAccessMask = VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + .dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, + .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .buffer = fragment_buffer->get_handle(), + .offset = 0, + .size = VK_WHOLE_SIZE}; + VkDependencyInfo dependency_info{.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT, .bufferMemoryBarrierCount = 1, .pBufferMemoryBarriers = &buffer_barrier}; + vkCmdPipelineBarrier2KHR(draw_cmd_buffers[i], &dependency_info); // Combine pass { @@ -252,17 +263,22 @@ void OITLinkedLists::create_fragment_resources(const uint32_t width, const uint3 { const VkExtent3D image_extent = {width, height, 1}; linked_list_head_image = std::make_unique(get_device(), image_extent, VK_FORMAT_R32_UINT, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY, VK_SAMPLE_COUNT_1_BIT); - linked_list_head_image_view = std::make_unique(*linked_list_head_image, VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R32_UINT); + linked_list_head_image->set_debug_name("linked_list_head_image"); + + linked_list_head_image_view = std::make_unique(*linked_list_head_image, VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R32_UINT); + linked_list_head_image_view->set_debug_name("linked_list_head_image_view"); } { fragment_max_count = width * height * kFragmentsPerPixelAverage; const uint32_t fragment_buffer_size = sizeof(glm::uvec3) * fragment_max_count; fragment_buffer = std::make_unique(get_device(), fragment_buffer_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY); + fragment_buffer->set_debug_name("fragment_buffer"); } { fragment_counter = std::make_unique(get_device(), sizeof(glm::uint), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY); + fragment_counter->set_debug_name("fragment_counter"); } }