From cb0c80c31e78ed4c7533785b98c6a99f84c48503 Mon Sep 17 00:00:00 2001 From: Ribbit Date: Fri, 10 Oct 2025 21:20:28 -0700 Subject: [PATCH] [vk] Improve Vulkan image layout transitions --- src/video_core/renderer_vulkan/blit_image.cpp | 27 +-- .../renderer_vulkan/present/util.cpp | 194 +++++++++++++++++- src/video_core/renderer_vulkan/present/util.h | 5 +- .../renderer_vulkan/vk_render_pass_cache.cpp | 48 ++++- 4 files changed, 228 insertions(+), 46 deletions(-) diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 68543bdd48..eeda0adfae 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp @@ -24,6 +24,7 @@ #include "video_core/host_shaders/vulkan_depthstencil_clear_frag_spv.h" #include "video_core/renderer_vulkan/blit_image.h" #include "video_core/renderer_vulkan/maxwell_to_vk.h" +#include "video_core/renderer_vulkan/present/util.h" #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_shader_util.h" #include "video_core/renderer_vulkan/vk_state_tracker.h" @@ -423,32 +424,6 @@ VkExtent2D GetConversionExtent(const ImageView& src_image_view) { }; } -void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout, - VkImageLayout source_layout = VK_IMAGE_LAYOUT_GENERAL) { - constexpr VkFlags flags{VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT}; - const VkImageMemoryBarrier barrier{ - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = flags, - .dstAccessMask = flags, - .oldLayout = source_layout, - .newLayout = target_layout, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = image, - .subresourceRange{ - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }; - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - 0, barrier); -} - void RecordShaderReadBarrier(Scheduler& scheduler, const ImageView& image_view) { const VkImage image = image_view.ImageHandle(); const VkImageSubresourceRange subresource_range = SubresourceRangeFromView(image_view); diff --git a/src/video_core/renderer_vulkan/present/util.cpp b/src/video_core/renderer_vulkan/present/util.cpp index 29a1c34976..ae6d68c241 100644 --- a/src/video_core/renderer_vulkan/present/util.cpp +++ b/src/video_core/renderer_vulkan/present/util.cpp @@ -5,6 +5,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/assert.h" +#include #include #include "video_core/renderer_vulkan/present/util.h" @@ -46,30 +47,203 @@ vk::Image CreateWrappedImage(MemoryAllocator& allocator, VkExtent2D dimensions, return allocator.CreateImage(image_ci); } +namespace { + +constexpr VkAccessFlags AccessMaskForLayout(VkImageLayout layout) { + switch (layout) { + case VK_IMAGE_LAYOUT_UNDEFINED: + case VK_IMAGE_LAYOUT_PREINITIALIZED: + return 0; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + return VK_ACCESS_TRANSFER_WRITE_BIT; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + return VK_ACCESS_TRANSFER_READ_BIT; + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: + return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; +#ifdef VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL: + return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; +#endif +#ifdef VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL: + return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; +#endif +#ifdef VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL + case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL: + return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; +#endif +#ifdef VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL + case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL: + return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; +#endif +#ifdef VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: + return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; +#endif +#ifdef VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: + return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; +#endif + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + return VK_ACCESS_SHADER_READ_BIT; + case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: + return 0; + case VK_IMAGE_LAYOUT_GENERAL: + return VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; + default: + return VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; + } +} + +constexpr VkPipelineStageFlags StageMaskForLayout(VkImageLayout layout) { + switch (layout) { + case VK_IMAGE_LAYOUT_UNDEFINED: + case VK_IMAGE_LAYOUT_PREINITIALIZED: + return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + return VK_PIPELINE_STAGE_TRANSFER_BIT; + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + return VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: + return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; +#ifdef VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL: + return VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; +#endif +#ifdef VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL: + return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; +#endif +#ifdef VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL + case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL: + return VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; +#endif +#ifdef VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL + case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL: + return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; +#endif +#ifdef VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: + return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; +#endif +#ifdef VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: + return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; +#endif + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + return VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: + return VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + case VK_IMAGE_LAYOUT_GENERAL: + return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + default: + return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + } +} + +constexpr VkImageAspectFlags AspectMaskForLayout(VkImageLayout layout) { + switch (layout) { + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: + return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; +#ifdef VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL: + return VK_IMAGE_ASPECT_DEPTH_BIT; +#endif +#ifdef VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL: + return VK_IMAGE_ASPECT_DEPTH_BIT; +#endif +#ifdef VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL + case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL: + return VK_IMAGE_ASPECT_STENCIL_BIT; +#endif +#ifdef VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL + case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL: + return VK_IMAGE_ASPECT_STENCIL_BIT; +#endif +#ifdef VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: + return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; +#endif +#ifdef VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: + return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; +#endif + default: + return VK_IMAGE_ASPECT_COLOR_BIT; + } +} + +constexpr VkImageAspectFlags AspectMaskForTransition(VkImageLayout old_layout, + VkImageLayout new_layout) { + const VkImageAspectFlags new_aspect = AspectMaskForLayout(new_layout); + if (new_aspect != VK_IMAGE_ASPECT_COLOR_BIT) { + return new_aspect; + } + const VkImageAspectFlags old_aspect = AspectMaskForLayout(old_layout); + if (old_aspect != VK_IMAGE_ASPECT_COLOR_BIT) { + return old_aspect; + } + return VK_IMAGE_ASPECT_COLOR_BIT; +} + +} // Anonymous namespace + void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout, - VkImageLayout source_layout) { - constexpr VkFlags flags{VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT}; + VkImageLayout source_layout, + std::optional aspect_mask_override) { + const VkAccessFlags src_access = AccessMaskForLayout(source_layout); + const VkAccessFlags dst_access = AccessMaskForLayout(target_layout); + const VkPipelineStageFlags src_stage = StageMaskForLayout(source_layout); + const VkPipelineStageFlags dst_stage = StageMaskForLayout(target_layout); + const VkImageAspectFlags aspect_mask = + aspect_mask_override.value_or(AspectMaskForTransition(source_layout, target_layout)); + const VkImageMemoryBarrier barrier{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .pNext = nullptr, - .srcAccessMask = flags, - .dstAccessMask = flags, + .srcAccessMask = src_access, + .dstAccessMask = dst_access, .oldLayout = source_layout, .newLayout = target_layout, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = image, .subresourceRange{ - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .aspectMask = aspect_mask, .baseMipLevel = 0, .levelCount = 1, .baseArrayLayer = 0, .layerCount = 1, }, }; - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - 0, barrier); + cmdbuf.PipelineBarrier(src_stage, dst_stage, 0, barrier); } void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& scheduler, @@ -211,7 +385,7 @@ vk::RenderPass CreateWrappedRenderPass(const Device& device, VkFormat format, constexpr VkAttachmentReference color_attachment_ref{ .attachment = 0, - .layout = VK_IMAGE_LAYOUT_GENERAL, + .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, }; const VkSubpassDescription subpass_description{ @@ -234,7 +408,7 @@ vk::RenderPass CreateWrappedRenderPass(const Device& device, VkFormat format, .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, .srcAccessMask = 0, .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - .dependencyFlags = 0, + .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT, }; return device.GetLogical().CreateRenderPass(VkRenderPassCreateInfo{ diff --git a/src/video_core/renderer_vulkan/present/util.h b/src/video_core/renderer_vulkan/present/util.h index 38cc6203c5..f04aeba4a2 100644 --- a/src/video_core/renderer_vulkan/present/util.h +++ b/src/video_core/renderer_vulkan/present/util.h @@ -6,6 +6,8 @@ #pragma once +#include + #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/vulkan_common/vulkan_memory_allocator.h" #include "video_core/vulkan_common/vulkan_wrapper.h" @@ -18,7 +20,8 @@ vk::Buffer CreateWrappedBuffer(MemoryAllocator& allocator, VkDeviceSize size, Me vk::Image CreateWrappedImage(MemoryAllocator& allocator, VkExtent2D dimensions, VkFormat format); void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout, - VkImageLayout source_layout = VK_IMAGE_LAYOUT_GENERAL); + VkImageLayout source_layout = VK_IMAGE_LAYOUT_GENERAL, + std::optional aspect_mask_override = std::nullopt); void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& scheduler, vk::Image& image, VkExtent2D dimensions, VkFormat format, std::span initial_contents = {}); diff --git a/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp index 80ff75e3b9..2848746613 100644 --- a/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp @@ -84,7 +84,7 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) { const bool is_valid{format != PixelFormat::Invalid}; references[index] = VkAttachmentReference{ .attachment = is_valid ? num_colors : VK_ATTACHMENT_UNUSED, - .layout = VK_IMAGE_LAYOUT_GENERAL, + .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, }; if (is_valid) { descriptions.push_back(AttachmentDescription(*device, format, key.samples)); @@ -97,7 +97,7 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) { if (key.depth_format != PixelFormat::Invalid) { depth_reference = VkAttachmentReference{ .attachment = num_colors, - .layout = VK_IMAGE_LAYOUT_GENERAL, + .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, }; descriptions.push_back(AttachmentDescription(*device, key.depth_format, key.samples)); } @@ -113,9 +113,38 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) { .preserveAttachmentCount = 0, .pPreserveAttachments = nullptr, }; - const VkSubpassDependency dependency{ - .srcSubpass = 0, // Current subpass - .dstSubpass = 0, // Same subpass (self-dependency) + boost::container::static_vector dependencies; + if (num_colors > 0) { + dependencies.push_back({ + .srcSubpass = VK_SUBPASS_EXTERNAL, + .dstSubpass = 0, + .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .srcAccessMask = 0, + .dstAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, + .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT, + }); + } + if (has_depth) { + dependencies.push_back({ + .srcSubpass = VK_SUBPASS_EXTERNAL, + .dstSubpass = 0, + .srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT, + }); + } + if (num_colors > 0 || has_depth) { + // Preserve existing self dependency to maintain implicit ordering for drivers + dependencies.push_back({ + .srcSubpass = 0, + .dstSubpass = 0, .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, @@ -123,8 +152,9 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) { .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, - .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT - }; + .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT, + }); + } pair->second = device->GetLogical().CreateRenderPass({ .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, .pNext = nullptr, @@ -133,8 +163,8 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) { .pAttachments = descriptions.empty() ? nullptr : descriptions.data(), .subpassCount = 1, .pSubpasses = &subpass, - .dependencyCount = 1, - .pDependencies = &dependency, + .dependencyCount = static_cast(dependencies.size()), + .pDependencies = dependencies.data(), }); return *pair->second; }