From 4f5fc58b6e907fac95553ea0e81fa876ef943eeb Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Wed, 30 Sep 2026 03:00:07 -0400 Subject: [PATCH] Use copy commands 2 --- .../renderer_vulkan/present/frame_gen.cpp | 6 +- .../renderer_vulkan/present/layer.cpp | 4 +- .../renderer_vulkan/present/util.cpp | 12 ++- .../renderer_vulkan/vk_buffer_cache.cpp | 12 ++- .../renderer_vulkan/vk_present_manager.cpp | 16 +-- .../renderer_vulkan/vk_query_cache.cpp | 22 +++-- .../renderer_vulkan/vk_texture_cache.cpp | 93 +++++++++--------- .../vulkan_common/vulkan_device.cpp | 4 +- src/video_core/vulkan_common/vulkan_device.h | 1 + .../vulkan_common/vulkan_wrapper.cpp | 31 +++--- src/video_core/vulkan_common/vulkan_wrapper.h | 98 ++++++++++++++----- 11 files changed, 193 insertions(+), 106 deletions(-) diff --git a/src/video_core/renderer_vulkan/present/frame_gen.cpp b/src/video_core/renderer_vulkan/present/frame_gen.cpp index d5916d6170..38981448de 100644 --- a/src/video_core/renderer_vulkan/present/frame_gen.cpp +++ b/src/video_core/renderer_vulkan/present/frame_gen.cpp @@ -140,8 +140,10 @@ VkImageMemoryBarrier2 MakeTransitionBarrier(VkImage image, VkPipelineStageFlags2 }; } -VkImageCopy MakeCopyRegion(VkExtent2D extent) { - return VkImageCopy{ +VkImageCopy2 MakeCopyRegion(VkExtent2D extent) { + return VkImageCopy2{ + .sType = VK_STRUCTURE_TYPE_IMAGE_COPY_2, + .pNext = nullptr, .srcSubresource{ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .mipLevel = 0, diff --git a/src/video_core/renderer_vulkan/present/layer.cpp b/src/video_core/renderer_vulkan/present/layer.cpp index 562928b953..d0411df705 100644 --- a/src/video_core/renderer_vulkan/present/layer.cpp +++ b/src/video_core/renderer_vulkan/present/layer.cpp @@ -343,7 +343,9 @@ void Layer::UpdateRawImage(const Tegra::FramebufferConfig& framebuffer, size_t i buffer.Flush(); // Ensure host writes are visible before the GPU copy. } - const VkBufferImageCopy copy{ + const VkBufferImageCopy2 copy{ + .sType = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2, + .pNext = nullptr, .bufferOffset = image_offset, .bufferRowLength = 0, .bufferImageHeight = 0, diff --git a/src/video_core/renderer_vulkan/present/util.cpp b/src/video_core/renderer_vulkan/present/util.cpp index f04df4afd2..63e8e5f5e8 100644 --- a/src/video_core/renderer_vulkan/present/util.cpp +++ b/src/video_core/renderer_vulkan/present/util.cpp @@ -89,7 +89,9 @@ void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& sc std::ranges::copy(initial_contents, upload_buffer.Mapped().begin()); upload_buffer.Flush(); - const std::array regions{{{ + const VkBufferImageCopy2 region{ + .sType = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2, + .pNext = nullptr, .bufferOffset = 0, .bufferRowLength = dimensions.width, .bufferImageHeight = dimensions.height, @@ -99,14 +101,14 @@ void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& sc .layerCount = 1}, .imageOffset{}, .imageExtent{.width = dimensions.width, .height = dimensions.height, .depth = 1}, - }}}; + }; scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([&](vk::CommandBuffer cmdbuf) { TransitionImageLayout(cmdbuf, *image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_UNDEFINED); cmdbuf.CopyBufferToImage(*upload_buffer, *image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - regions); + region); TransitionImageLayout(cmdbuf, *image, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); }); @@ -163,7 +165,9 @@ void DownloadColorImage(vk::CommandBuffer& cmdbuf, VkImage image, VkBuffer buffe .dstStageMask = vk::PIPELINE_STAGE_HOST, .dstAccessMask = VK_ACCESS_2_HOST_READ_BIT, }; - const VkBufferImageCopy copy{ + const VkBufferImageCopy2 copy{ + .sType = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2, + .pNext = nullptr, .bufferOffset = 0, .bufferRowLength = 0, .bufferImageHeight = 0, diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 7b9287d797..488fd639aa 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -36,8 +36,10 @@ struct VertexBindings { u32 count; }; -VkBufferCopy MakeBufferCopy(const VideoCommon::BufferCopy& copy) { - return VkBufferCopy{ +VkBufferCopy2 MakeBufferCopy(const VideoCommon::BufferCopy& copy) { + return VkBufferCopy2{ + .sType = VK_STRUCTURE_TYPE_BUFFER_COPY_2, + .pNext = nullptr, .srcOffset = copy.src_offset, .dstOffset = copy.dst_offset, .size = copy.size, @@ -234,7 +236,9 @@ public: scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([src_buffer = staging.buffer, src_offset = staging.offset, dst_buffer = *buffer, size_bytes](vk::CommandBuffer cmdbuf) { - const VkBufferCopy copy{ + const VkBufferCopy2 copy{ + .sType = VK_STRUCTURE_TYPE_BUFFER_COPY_2, + .pNext = nullptr, .srcOffset = src_offset, .dstOffset = 0, .size = size_bytes, @@ -500,7 +504,7 @@ void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer, } // Measuring a popular game, this number never exceeds the specified size once data is warmed up - boost::container::small_vector vk_copies(copies.size()); + boost::container::small_vector vk_copies(copies.size()); std::ranges::transform(copies, vk_copies.begin(), MakeBufferCopy); if (src_buffer == staging_pool.StreamBuf() && can_reorder_upload) { scheduler.RecordWithUploadBuffer([src_buffer, dst_buffer, vk_copies]( diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp index 58b2f14670..144a23b4b8 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp @@ -51,9 +51,11 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice& physical_device, VkFormat form }; } -[[nodiscard]] VkImageBlit MakeImageBlit(s32 frame_width, s32 frame_height, s32 swapchain_width, - s32 swapchain_height) { - return VkImageBlit{ +[[nodiscard]] VkImageBlit2 MakeImageBlit(s32 frame_width, s32 frame_height, s32 swapchain_width, + s32 swapchain_height) { + return VkImageBlit2{ + .sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2, + .pNext = nullptr, .srcSubresource = MakeImageSubresourceLayers(), .srcOffsets = { @@ -85,9 +87,11 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice& physical_device, VkFormat form }; } -[[nodiscard]] VkImageCopy MakeImageCopy(u32 frame_width, u32 frame_height, u32 swapchain_width, - u32 swapchain_height) { - return VkImageCopy{ +[[nodiscard]] VkImageCopy2 MakeImageCopy(u32 frame_width, u32 frame_height, u32 swapchain_width, + u32 swapchain_height) { + return VkImageCopy2{ + .sType = VK_STRUCTURE_TYPE_IMAGE_COPY_2, + .pNext = nullptr, .srcSubresource = MakeImageSubresourceLayers(), .srcOffset = { diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 5a574e289a..3fab3eb7fd 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -653,11 +653,13 @@ public: scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([this, dst_buffer = stagging_buffer.buffer, extra_offset, start, size](vk::CommandBuffer cmdbuf) { - std::array copy{VkBufferCopy{ + const VkBufferCopy2 copy{ + .sType = VK_STRUCTURE_TYPE_BUFFER_COPY_2, + .pNext = nullptr, .srcOffset = start * QUERY_SIZE, .dstOffset = extra_offset, .size = size * QUERY_SIZE, - }}; + }; cmdbuf.CopyBuffer(*buffer, dst_buffer, copy); }); } @@ -1040,11 +1042,13 @@ private: src_offset = offsets[slot_index], slot](vk::CommandBuffer cmdbuf) { cmdbuf.PipelineBarrier(READ_BARRIER); - std::array copy{VkBufferCopy{ + const VkBufferCopy2 copy{ + .sType = VK_STRUCTURE_TYPE_BUFFER_COPY_2, + .pNext = nullptr, .srcOffset = src_offset, .dstOffset = slot * TFBQueryBank::QUERY_SIZE, .size = TFBQueryBank::QUERY_SIZE, - }}; + }; cmdbuf.CopyBuffer(src_buffer, dst_buffer, copy); cmdbuf.PipelineBarrier(WRITE_BARRIER); }); @@ -1339,7 +1343,7 @@ struct QueryCacheRuntimeImpl { std::vector> little_cache; std::vector> buffers_to_upload_to; std::vector redirect_cache; - std::vector> copies_setup; + std::vector> copies_setup; // Host conditional rendering data std::optional conditional_resolve_pass; @@ -1657,7 +1661,9 @@ void QueryCacheRuntime::SyncValues(std::span values, VkBuffer ba size_t accumulated_size = 0; for (size_t i = 0; i < values.size(); i++) { size_t which_copy = impl->redirect_cache[i]; - impl->copies_setup[which_copy].emplace_back(VkBufferCopy{ + impl->copies_setup[which_copy].emplace_back(VkBufferCopy2{ + .sType = VK_STRUCTURE_TYPE_BUFFER_COPY_2, + .pNext = nullptr, .srcOffset = current_offset + accumulated_size, .dstOffset = impl->buffers_to_upload_to[which_copy].second + values[i].address - impl->little_cache[which_copy].first, @@ -1671,7 +1677,9 @@ void QueryCacheRuntime::SyncValues(std::span values, VkBuffer ba } else { for (size_t i = 0; i < values.size(); i++) { size_t which_copy = impl->redirect_cache[i]; - impl->copies_setup[which_copy].emplace_back(VkBufferCopy{ + impl->copies_setup[which_copy].emplace_back(VkBufferCopy2{ + .sType = VK_STRUCTURE_TYPE_BUFFER_COPY_2, + .pNext = nullptr, .srcOffset = values[i].offset, .dstOffset = impl->buffers_to_upload_to[which_copy].second + values[i].address - impl->little_cache[which_copy].first, diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 55b3b7e81d..a7c22db002 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -503,9 +503,11 @@ void SanitizeDepthStencilSwizzle(std::array& swizzle, }; } -[[nodiscard]] VkImageCopy MakeImageCopy(const VideoCommon::ImageCopy& copy, - VkImageAspectFlags aspect_mask) noexcept { - return VkImageCopy{ +[[nodiscard]] VkImageCopy2 MakeImageCopy(const VideoCommon::ImageCopy& copy, + VkImageAspectFlags aspect_mask) noexcept { + return VkImageCopy2{ + .sType = VK_STRUCTURE_TYPE_IMAGE_COPY_2, + .pNext = nullptr, .srcSubresource = MakeImageSubresourceLayers(copy.src_subresource, aspect_mask), .srcOffset = MakeOffset3D(copy.src_offset), .dstSubresource = MakeImageSubresourceLayers(copy.dst_subresource, aspect_mask), @@ -514,9 +516,12 @@ void SanitizeDepthStencilSwizzle(std::array& swizzle, }; } -[[nodiscard]] VkBufferImageCopy MakeBufferImageCopy(const VideoCommon::ImageCopy& copy, bool is_src, - VkImageAspectFlags aspect_mask) noexcept { - return VkBufferImageCopy{ +[[nodiscard]] VkBufferImageCopy2 MakeBufferImageCopy(const VideoCommon::ImageCopy& copy, + bool is_src, + VkImageAspectFlags aspect_mask) noexcept { + return VkBufferImageCopy2{ + .sType = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2, + .pNext = nullptr, .bufferOffset = 0, .bufferRowLength = 0, .bufferImageHeight = 0, @@ -527,25 +532,13 @@ void SanitizeDepthStencilSwizzle(std::array& swizzle, }; } -[[maybe_unused]] [[nodiscard]] boost::container::small_vector -TransformBufferCopies(std::span copies, size_t buffer_offset) { - boost::container::small_vector result(copies.size()); - std::ranges::transform( - copies, result.begin(), [buffer_offset](const VideoCommon::BufferCopy& copy) { - return VkBufferCopy{ - .srcOffset = static_cast(copy.src_offset + buffer_offset), - .dstOffset = static_cast(copy.dst_offset), - .size = static_cast(copy.size), - }; - }); - return result; -} - -[[nodiscard]] boost::container::small_vector TransformBufferImageCopies( +[[nodiscard]] boost::container::small_vector TransformBufferImageCopies( std::span copies, size_t buffer_offset, VkImageAspectFlags aspect_mask) { struct Maker { - VkBufferImageCopy operator()(const BufferImageCopy& copy) const { - return VkBufferImageCopy{ + VkBufferImageCopy2 operator()(const BufferImageCopy& copy) const { + return VkBufferImageCopy2{ + .sType = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2, + .pNext = nullptr, .bufferOffset = copy.buffer_offset + buffer_offset, .bufferRowLength = copy.buffer_row_length, .bufferImageHeight = copy.buffer_image_height, @@ -574,14 +567,14 @@ TransformBufferCopies(std::span copies, size_t bu VkImageAspectFlags aspect_mask; }; if (aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { - boost::container::small_vector result(copies.size() * 2); + boost::container::small_vector result(copies.size() * 2); std::ranges::transform(copies, result.begin(), Maker{buffer_offset, VK_IMAGE_ASPECT_DEPTH_BIT}); std::ranges::transform(copies, result.begin() + copies.size(), Maker{buffer_offset, VK_IMAGE_ASPECT_STENCIL_BIT}); return result; } else { - boost::container::small_vector result(copies.size()); + boost::container::small_vector result(copies.size()); std::ranges::transform(copies, result.begin(), Maker{buffer_offset, aspect_mask}); return result; } @@ -688,7 +681,7 @@ struct RangedBarrierRange { }; void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage image, VkImageAspectFlags aspect_mask, bool is_initialized, - std::span copies) { + std::span copies) { // Compute exact mip/layer range being written to RangedBarrierRange range; for (const auto& region : copies) { @@ -732,10 +725,12 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im cmdbuf.PipelineBarrier(0, {}, {}, write_barrier); } -[[nodiscard]] VkImageBlit MakeImageBlit(const Region2D& dst_region, const Region2D& src_region, - const VkImageSubresourceLayers& dst_layers, - const VkImageSubresourceLayers& src_layers) { - return VkImageBlit{ +[[nodiscard]] VkImageBlit2 MakeImageBlit(const Region2D& dst_region, const Region2D& src_region, + const VkImageSubresourceLayers& dst_layers, + const VkImageSubresourceLayers& src_layers) { + return VkImageBlit2{ + .sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2, + .pNext = nullptr, .srcSubresource = src_layers, .srcOffsets = { @@ -772,11 +767,13 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im dst_region.end.y - dst_region.start.y == src_region.end.y - src_region.start.y; } -[[nodiscard]] VkImageResolve MakeImageResolve(const Region2D& dst_region, - const Region2D& src_region, - const VkImageSubresourceLayers& dst_layers, - const VkImageSubresourceLayers& src_layers) { - return VkImageResolve{ +[[nodiscard]] VkImageResolve2 MakeImageResolve(const Region2D& dst_region, + const Region2D& src_region, + const VkImageSubresourceLayers& dst_layers, + const VkImageSubresourceLayers& src_layers) { + return VkImageResolve2{ + .sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2, + .pNext = nullptr, .srcSubresource = src_layers, .srcOffset = { @@ -879,10 +876,12 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const .x = static_cast(up_scaling ? scaled_width : extent.width), .y = static_cast(up_scaling ? scaled_height : extent.height), }; - boost::container::small_vector regions; + boost::container::small_vector regions; regions.reserve(resources.levels); for (s32 level = 0; level < resources.levels; level++) { regions.push_back({ + .sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2, + .pNext = nullptr, .srcSubresource{ .aspectMask = aspect_mask, .mipLevel = static_cast(level), @@ -1237,8 +1236,8 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src, if (ENABLE_MSAA_RESOLVE_CONSUME) { InvalidateResolveShadow(dst.Handle()); } - boost::container::small_vector vk_in_copies(copies.size()); - boost::container::small_vector vk_out_copies(copies.size()); + boost::container::small_vector vk_in_copies(copies.size()); + boost::container::small_vector vk_out_copies(copies.size()); const VkImageAspectFlags src_aspect_mask = src.AspectMask(); const VkImageAspectFlags dst_aspect_mask = dst.AspectMask(); @@ -1267,10 +1266,10 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src, vk_in_copies, vk_out_copies](vk::CommandBuffer cmdbuf) { RangedBarrierRange dst_range; RangedBarrierRange src_range; - for (const VkBufferImageCopy& copy : vk_in_copies) { + for (const VkBufferImageCopy2& copy : vk_in_copies) { src_range.AddLayers(copy.imageSubresource); } - for (const VkBufferImageCopy& copy : vk_out_copies) { + for (const VkBufferImageCopy2& copy : vk_out_copies) { dst_range.AddLayers(copy.imageSubresource); } static constexpr VkMemoryBarrier2 READ_BARRIER{ @@ -1397,7 +1396,6 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst } }(); // Use shader-based depth/stencil blits if hardware doesn't support the format - // Note: MSAA resolves (MSAA->single) use vkCmdResolveImage which works fine if (!can_blit_depth_stencil) { UNIMPLEMENTED_IF(is_src_msaa || is_dst_msaa); blit_image_helper.BlitDepthStencil(dst_framebuffer, src, dst_region, src_region, @@ -1647,7 +1645,7 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src, }; return ReinterpretImage(dst, src, std::span{&oneCopy, 1}); } - boost::container::small_vector vk_copies(copies.size()); + boost::container::small_vector vk_copies(copies.size()); const VkImageAspectFlags aspect_mask = dst.AspectMask(); ASSERT(aspect_mask == src.AspectMask()); @@ -1660,7 +1658,7 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src, scheduler.Record([dst_image, src_image, aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) { RangedBarrierRange dst_range; RangedBarrierRange src_range; - for (const VkImageCopy& copy : vk_copies) { + for (const VkImageCopy2& copy : vk_copies) { dst_range.AddLayers(copy.dstSubresource); src_range.AddLayers(copy.srcSubresource); } @@ -1749,7 +1747,9 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src, const VkImageAspectFlags aspect_mask = shadow->aspect_mask; const VkImage shadow_image = *shadow->image; const VkImage dst_image = dst.Handle(); - const VkImageCopy region{ + const VkImageCopy2 region{ + .sType = VK_STRUCTURE_TYPE_IMAGE_COPY_2, + .pNext = nullptr, .srcSubresource{ .aspectMask = aspect_mask, .mipLevel = 0, @@ -2199,7 +2199,8 @@ void Image::DownloadMemory(std::span buffers_span, std::span o } boost::container::small_vector buffers_vector{}; - boost::container::small_vector, 8> + boost::container::small_vector< + boost::container::small_vector, 8> vk_copies; for (size_t index = 0; index < buffers_span.size(); index++) { buffers_vector.emplace_back(buffers_span[index]); @@ -2278,7 +2279,7 @@ void Image::DownloadMemory(std::span buffers_span, std::span o return; } else { boost::container::small_vector buffers_vector{}; - boost::container::small_vector, 8> + boost::container::small_vector, 8> vk_copies; for (size_t index = 0; index < buffers_span.size(); index++) { buffers_vector.emplace_back(buffers_span[index]); diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 6ec6bc88e9..6c52137e08 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -1423,7 +1423,9 @@ void Device::RemoveUnsuitableExtensions() { extensions.synchronization2 = features.synchronization2.synchronization2; extensions.dynamic_rendering = features.dynamic_rendering.dynamicRendering; - if (!extensions.synchronization2 || !extensions.dynamic_rendering) { + const bool copy_commands2 = + extensions.copy_commands2 || instance_version >= VK_API_VERSION_1_3; + if (!extensions.synchronization2 || !extensions.dynamic_rendering || !copy_commands2) { throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT); } } diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 7a8de7beb8..460a3b702e 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -97,6 +97,7 @@ VK_DEFINE_HANDLE(VmaAllocator) EXTENSION(EXT, SHADER_VIEWPORT_INDEX_LAYER, shader_viewport_index_layer) \ EXTENSION(EXT, TOOLING_INFO, tooling_info) \ EXTENSION(EXT, VERTEX_ATTRIBUTE_DIVISOR, vertex_attribute_divisor) \ + EXTENSION(KHR, COPY_COMMANDS_2, copy_commands2) \ EXTENSION(KHR, CREATE_RENDERPASS_2, create_renderpass2) \ EXTENSION(KHR, DEPTH_STENCIL_RESOLVE, depth_stencil_resolve) \ EXTENSION(KHR, DRAW_INDIRECT_COUNT, draw_indirect_count) \ diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 092914ca03..9a901cd8fb 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp @@ -96,13 +96,13 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { X(vkCmdBindPipeline); X(vkCmdBindTransformFeedbackBuffersEXT); X(vkCmdBindVertexBuffers); - X(vkCmdBlitImage); + X(vkCmdBlitImage2); X(vkCmdClearAttachments); X(vkCmdClearColorImage); - X(vkCmdCopyBuffer); - X(vkCmdCopyBufferToImage); - X(vkCmdCopyImage); - X(vkCmdCopyImageToBuffer); + X(vkCmdCopyBuffer2); + X(vkCmdCopyBufferToImage2); + X(vkCmdCopyImage2); + X(vkCmdCopyImageToBuffer2); X(vkCmdCopyQueryPoolResults); X(vkCmdDispatch); X(vkCmdDispatchIndirect); @@ -158,7 +158,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { X(vkCmdSetColorBlendEnableEXT); X(vkCmdSetColorBlendEquationEXT); X(vkCmdResetQueryPool); - X(vkCmdResolveImage); + X(vkCmdResolveImage2); X(vkCreateBuffer); X(vkCreateBufferView); X(vkCreateCommandPool); @@ -253,12 +253,19 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { Proc(dld.vkQueueSubmit2, dld, "vkQueueSubmit2KHR", device); } - if (!dld.vkCmdBeginRendering) { - Proc(dld.vkCmdBeginRendering, dld, "vkCmdBeginRenderingKHR", device); - } - if (!dld.vkCmdEndRendering) { - Proc(dld.vkCmdEndRendering, dld, "vkCmdEndRenderingKHR", device); - } + const auto load_khr = [&](auto& function, const char* name) { + if (!function) { + Proc(function, dld, name, device); + } + }; + load_khr(dld.vkCmdBeginRendering, "vkCmdBeginRenderingKHR"); + load_khr(dld.vkCmdEndRendering, "vkCmdEndRenderingKHR"); + load_khr(dld.vkCmdBlitImage2, "vkCmdBlitImage2KHR"); + load_khr(dld.vkCmdCopyBuffer2, "vkCmdCopyBuffer2KHR"); + load_khr(dld.vkCmdCopyBufferToImage2, "vkCmdCopyBufferToImage2KHR"); + load_khr(dld.vkCmdCopyImage2, "vkCmdCopyImage2KHR"); + load_khr(dld.vkCmdCopyImageToBuffer2, "vkCmdCopyImageToBuffer2KHR"); + load_khr(dld.vkCmdResolveImage2, "vkCmdResolveImage2KHR"); #undef X } diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index 26f8f2a0f5..d524a36b65 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h @@ -246,13 +246,13 @@ struct DeviceDispatch : InstanceDispatch { PFN_vkCmdBindTransformFeedbackBuffersEXT vkCmdBindTransformFeedbackBuffersEXT{}; PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers{}; PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT{}; - PFN_vkCmdBlitImage vkCmdBlitImage{}; + PFN_vkCmdBlitImage2 vkCmdBlitImage2{}; PFN_vkCmdClearAttachments vkCmdClearAttachments{}; PFN_vkCmdClearColorImage vkCmdClearColorImage{}; - PFN_vkCmdCopyBuffer vkCmdCopyBuffer{}; - PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage{}; - PFN_vkCmdCopyImage vkCmdCopyImage{}; - PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer{}; + PFN_vkCmdCopyBuffer2 vkCmdCopyBuffer2{}; + PFN_vkCmdCopyBufferToImage2 vkCmdCopyBufferToImage2{}; + PFN_vkCmdCopyImage2 vkCmdCopyImage2{}; + PFN_vkCmdCopyImageToBuffer2 vkCmdCopyImageToBuffer2{}; PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults{}; PFN_vkCmdDispatch vkCmdDispatch{}; PFN_vkCmdDispatchIndirect vkCmdDispatchIndirect{}; @@ -272,7 +272,7 @@ struct DeviceDispatch : InstanceDispatch { PFN_vkCmdPushConstants vkCmdPushConstants{}; PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR{}; PFN_vkCmdResetQueryPool vkCmdResetQueryPool{}; - PFN_vkCmdResolveImage vkCmdResolveImage{}; + PFN_vkCmdResolveImage2 vkCmdResolveImage2{}; PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants{}; PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT{}; PFN_vkCmdSetDepthBias vkCmdSetDepthBias{}; @@ -1274,16 +1274,35 @@ public: } void BlitImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image, - VkImageLayout dst_layout, Span regions, + VkImageLayout dst_layout, Span regions, VkFilter filter) const noexcept { - dld->vkCmdBlitImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(), - regions.data(), filter); + const VkBlitImageInfo2 info{ + .sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2, + .pNext = nullptr, + .srcImage = src_image, + .srcImageLayout = src_layout, + .dstImage = dst_image, + .dstImageLayout = dst_layout, + .regionCount = regions.size(), + .pRegions = regions.data(), + .filter = filter, + }; + dld->vkCmdBlitImage2(handle, &info); } void ResolveImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image, - VkImageLayout dst_layout, Span regions) { - dld->vkCmdResolveImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(), - regions.data()); + VkImageLayout dst_layout, Span regions) const noexcept { + const VkResolveImageInfo2 info{ + .sType = VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2, + .pNext = nullptr, + .srcImage = src_image, + .srcImageLayout = src_layout, + .dstImage = dst_image, + .dstImageLayout = dst_layout, + .regionCount = regions.size(), + .pRegions = regions.data(), + }; + dld->vkCmdResolveImage2(handle, &info); } void Dispatch(u32 x, u32 y, u32 z) const noexcept { @@ -1353,26 +1372,59 @@ public: } void CopyBufferToImage(VkBuffer src_buffer, VkImage dst_image, VkImageLayout dst_image_layout, - Span regions) const noexcept { - dld->vkCmdCopyBufferToImage(handle, src_buffer, dst_image, dst_image_layout, regions.size(), - regions.data()); + Span regions) const noexcept { + const VkCopyBufferToImageInfo2 info{ + .sType = VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2, + .pNext = nullptr, + .srcBuffer = src_buffer, + .dstImage = dst_image, + .dstImageLayout = dst_image_layout, + .regionCount = regions.size(), + .pRegions = regions.data(), + }; + dld->vkCmdCopyBufferToImage2(handle, &info); } void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer, - Span regions) const noexcept { - dld->vkCmdCopyBuffer(handle, src_buffer, dst_buffer, regions.size(), regions.data()); + Span regions) const noexcept { + const VkCopyBufferInfo2 info{ + .sType = VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2, + .pNext = nullptr, + .srcBuffer = src_buffer, + .dstBuffer = dst_buffer, + .regionCount = regions.size(), + .pRegions = regions.data(), + }; + dld->vkCmdCopyBuffer2(handle, &info); } void CopyImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image, - VkImageLayout dst_layout, Span regions) const noexcept { - dld->vkCmdCopyImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(), - regions.data()); + VkImageLayout dst_layout, Span regions) const noexcept { + const VkCopyImageInfo2 info{ + .sType = VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2, + .pNext = nullptr, + .srcImage = src_image, + .srcImageLayout = src_layout, + .dstImage = dst_image, + .dstImageLayout = dst_layout, + .regionCount = regions.size(), + .pRegions = regions.data(), + }; + dld->vkCmdCopyImage2(handle, &info); } void CopyImageToBuffer(VkImage src_image, VkImageLayout src_layout, VkBuffer dst_buffer, - Span regions) const noexcept { - dld->vkCmdCopyImageToBuffer(handle, src_image, src_layout, dst_buffer, regions.size(), - regions.data()); + Span regions) const noexcept { + const VkCopyImageToBufferInfo2 info{ + .sType = VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2, + .pNext = nullptr, + .srcImage = src_image, + .srcImageLayout = src_layout, + .dstBuffer = dst_buffer, + .regionCount = regions.size(), + .pRegions = regions.data(), + }; + dld->vkCmdCopyImageToBuffer2(handle, &info); } void CopyQueryPoolResults(VkQueryPool query_pool, u32 first_query, u32 query_count,