From 940611fe654489000b9f9e57e1b510cef54556b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 11 Oct 2020 09:19:06 +0200 Subject: [PATCH 1/3] Remove the USE_GENERAL_LAYOUT_FOR* debug defines. --- Common/GPU/Vulkan/VulkanContext.cpp | 18 -------- Common/GPU/Vulkan/VulkanContext.h | 6 --- Common/GPU/Vulkan/VulkanQueueRunner.cpp | 55 ------------------------- Common/GPU/Vulkan/thin3d_vulkan.cpp | 4 -- GPU/Vulkan/DrawEngineVulkan.cpp | 12 ------ GPU/Vulkan/VulkanUtil.cpp | 8 ---- 6 files changed, 103 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanContext.cpp b/Common/GPU/Vulkan/VulkanContext.cpp index 9435c988d3..0a572cf8ac 100644 --- a/Common/GPU/Vulkan/VulkanContext.cpp +++ b/Common/GPU/Vulkan/VulkanContext.cpp @@ -1126,24 +1126,6 @@ void TransitionImageLayout2(VkCommandBuffer cmd, VkImage image, int baseMip, int VkImageLayout oldImageLayout, VkImageLayout newImageLayout, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) { -#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR - if (aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) { - // Hack to disable transaction elimination on ARM Mali. - if (oldImageLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL || oldImageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) - oldImageLayout = VK_IMAGE_LAYOUT_GENERAL; - if (newImageLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL || newImageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) - newImageLayout = VK_IMAGE_LAYOUT_GENERAL; - } -#endif -#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_DEPTH_STENCIL - if (aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) { - // Hack to disable transaction elimination on ARM Mali. - if (oldImageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || oldImageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) - oldImageLayout = VK_IMAGE_LAYOUT_GENERAL; - if (newImageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || newImageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) - newImageLayout = VK_IMAGE_LAYOUT_GENERAL; - } -#endif VkImageMemoryBarrier image_memory_barrier{ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; image_memory_barrier.srcAccessMask = srcAccessMask; image_memory_barrier.dstAccessMask = dstAccessMask; diff --git a/Common/GPU/Vulkan/VulkanContext.h b/Common/GPU/Vulkan/VulkanContext.h index ec2fa44beb..db467eff93 100644 --- a/Common/GPU/Vulkan/VulkanContext.h +++ b/Common/GPU/Vulkan/VulkanContext.h @@ -107,12 +107,6 @@ private: std::vector callbacks_; }; -// Useful for debugging on ARM Mali. This eliminates transaction elimination -// which can cause artifacts if you get barriers wrong (or if there are driver bugs). -// Cost is reduced performance on some GPU architectures. -// #define VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR -// #define VULKAN_USE_GENERAL_LAYOUT_FOR_DEPTH_STENCIL - // VulkanContext manages the device and swapchain, and deferred deletion of objects. class VulkanContext { public: diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.cpp b/Common/GPU/Vulkan/VulkanQueueRunner.cpp index ff5fb56d2f..a8fd7925a0 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.cpp +++ b/Common/GPU/Vulkan/VulkanQueueRunner.cpp @@ -126,22 +126,13 @@ void VulkanQueueRunner::InitBackbufferRenderPass() { attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // Don't care about storing backbuffer Z - we clear it anyway. attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; -#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_DEPTH_STENCIL - attachments[1].initialLayout = VK_IMAGE_LAYOUT_GENERAL; - attachments[1].finalLayout = VK_IMAGE_LAYOUT_GENERAL; -#else attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; -#endif attachments[1].flags = 0; VkAttachmentReference color_reference{}; color_reference.attachment = 0; -#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR - color_reference.layout = VK_IMAGE_LAYOUT_GENERAL; -#else color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; -#endif VkAttachmentReference depth_reference{}; depth_reference.attachment = 1; @@ -204,13 +195,8 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(const RPKey &key) { attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; -#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR - attachments[0].initialLayout = VK_IMAGE_LAYOUT_GENERAL; - attachments[0].finalLayout = VK_IMAGE_LAYOUT_GENERAL; -#else attachments[0].initialLayout = key.prevColorLayout; attachments[0].finalLayout = key.finalColorLayout; -#endif attachments[0].flags = 0; attachments[1].format = vulkan_->GetDeviceInfo().preferredDepthStencilFormat; @@ -239,13 +225,8 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(const RPKey &key) { } attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; -#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_DEPTH_STENCIL - attachments[1].initialLayout = VK_IMAGE_LAYOUT_GENERAL; - attachments[1].finalLayout = VK_IMAGE_LAYOUT_GENERAL; -#else attachments[1].initialLayout = key.prevDepthStencilLayout; attachments[1].finalLayout = key.finalDepthStencilLayout; -#endif attachments[1].flags = 0; VkAttachmentReference color_reference{}; @@ -1580,24 +1561,6 @@ void VulkanQueueRunner::SetupTransitionToTransferSrc(VKRImage &img, VkImageMemor barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; img.layout = barrier.newLayout; - - // NOTE: Must do this AFTER updating img.layout to avoid behaviour differences. -#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR - if (aspect == VK_IMAGE_ASPECT_COLOR_BIT) { - if (barrier.oldLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL || barrier.oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) - barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - if (barrier.newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL || barrier.newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) - barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - } -#endif -#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_DEPTH_STENCIL - if (aspect != VK_IMAGE_ASPECT_COLOR_BIT) { - if (barrier.oldLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || barrier.oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) - barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - if (barrier.newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || barrier.newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) - barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - } -#endif } void VulkanQueueRunner::SetupTransitionToTransferDst(VKRImage &img, VkImageMemoryBarrier &barrier, VkPipelineStageFlags &stage, VkImageAspectFlags aspect) { @@ -1639,24 +1602,6 @@ void VulkanQueueRunner::SetupTransitionToTransferDst(VKRImage &img, VkImageMemor barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; img.layout = barrier.newLayout; - - // NOTE: Must do this AFTER updating img.layout to avoid behaviour differences. -#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR - if (aspect == VK_IMAGE_ASPECT_COLOR_BIT) { - if (barrier.oldLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL || barrier.oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) - barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - if (barrier.newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL || barrier.newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) - barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - } -#endif -#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_DEPTH_STENCIL - if (aspect != VK_IMAGE_ASPECT_COLOR_BIT) { - if (barrier.oldLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || barrier.oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) - barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - if (barrier.newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || barrier.newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) - barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - } -#endif } void VulkanQueueRunner::PerformReadback(const VKRStep &step, VkCommandBuffer cmd) { diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index 502a5194f5..6fab2a9841 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -993,11 +993,7 @@ VkDescriptorSet VKContext::GetOrCreateDescriptorSet(VkBuffer buf) { if (key.imageViews_[i] && key.samplers_[i] && key.samplers_[i]->GetSampler()) { imageDesc[i].imageView = key.imageViews_[i]; imageDesc[i].sampler = key.samplers_[i]->GetSampler(); -#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR - imageDesc[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; -#else imageDesc[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; -#endif writes[numWrites].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writes[numWrites].dstSet = descSet; writes[numWrites].dstArrayElement = 0; diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 04d48db348..0033521449 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -446,11 +446,7 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView if (imageView) { _dbg_assert_(sampler != VK_NULL_HANDLE); -#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR - tex[0].imageLayout = VK_IMAGE_LAYOUT_GENERAL; -#else tex[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; -#endif tex[0].imageView = imageView; tex[0].sampler = sampler; writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; @@ -464,11 +460,7 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView } if (boundSecondary_) { -#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR - tex[1].imageLayout = VK_IMAGE_LAYOUT_GENERAL; -#else tex[1].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; -#endif tex[1].imageView = boundSecondary_; tex[1].sampler = samplerSecondary_; writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; @@ -482,11 +474,7 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView } if (boundDepal_) { -#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR - tex[2].imageLayout = VK_IMAGE_LAYOUT_GENERAL; -#else tex[2].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; -#endif tex[2].imageView = boundDepal_; tex[2].sampler = samplerSecondary_; // doesn't matter, we use load writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; diff --git a/GPU/Vulkan/VulkanUtil.cpp b/GPU/Vulkan/VulkanUtil.cpp index bcf6f655f9..bb39dff229 100644 --- a/GPU/Vulkan/VulkanUtil.cpp +++ b/GPU/Vulkan/VulkanUtil.cpp @@ -196,11 +196,7 @@ VkDescriptorSet Vulkan2D::GetDescriptorSet(VkImageView tex1, VkSampler sampler1, VkDescriptorImageInfo image1{}; VkDescriptorImageInfo image2{}; if (tex1 && sampler1) { -#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR - image1.imageLayout = VK_IMAGE_LAYOUT_GENERAL; -#else image1.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; -#endif image1.imageView = tex1; image1.sampler = sampler1; writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; @@ -213,11 +209,7 @@ VkDescriptorSet Vulkan2D::GetDescriptorSet(VkImageView tex1, VkSampler sampler1, } if (tex2 && sampler2) { // TODO: Also support LAYOUT_GENERAL to be able to texture from framebuffers without transitioning them? -#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR - image2.imageLayout = VK_IMAGE_LAYOUT_GENERAL; -#else image2.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; -#endif image2.imageView = tex2; image2.sampler = sampler2; writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; From 692048fb8bdebe67a113ba40bca2dc25ebe2f917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 11 Oct 2020 10:21:50 +0200 Subject: [PATCH 2/3] VK: Separate layout transitions from renderpasses again. According to sage advice from themaister, this is just unnecessary overengineering. Having them separate reduces the size of the renderpass key - we might be able to just change that to an array lookup again. Will also make it easier to in the future add depth-less render passes. --- Common/GPU/Vulkan/VulkanQueueRunner.cpp | 340 ++++++++++++++---------- Common/GPU/Vulkan/VulkanQueueRunner.h | 11 +- 2 files changed, 205 insertions(+), 146 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.cpp b/Common/GPU/Vulkan/VulkanQueueRunner.cpp index a8fd7925a0..c2a6c6aa0e 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.cpp +++ b/Common/GPU/Vulkan/VulkanQueueRunner.cpp @@ -12,8 +12,7 @@ void VulkanQueueRunner::CreateDeviceObjects() { INFO_LOG(G3D, "VulkanQueueRunner::CreateDeviceObjects"); InitBackbufferRenderPass(); - framebufferRenderPass_ = GetRenderPass(VKRRenderPassAction::CLEAR, VKRRenderPassAction::CLEAR, VKRRenderPassAction::CLEAR, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + framebufferRenderPass_ = GetRenderPass(VKRRenderPassAction::CLEAR, VKRRenderPassAction::CLEAR, VKRRenderPassAction::CLEAR); #if 0 // Just to check whether it makes sense to split some of these. drawidx is way bigger than the others... @@ -195,8 +194,8 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(const RPKey &key) { attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[0].initialLayout = key.prevColorLayout; - attachments[0].finalLayout = key.finalColorLayout; + attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; attachments[0].flags = 0; attachments[1].format = vulkan_->GetDeviceInfo().preferredDepthStencilFormat; @@ -225,8 +224,8 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(const RPKey &key) { } attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments[1].initialLayout = key.prevDepthStencilLayout; - attachments[1].finalLayout = key.finalDepthStencilLayout; + attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; attachments[1].flags = 0; VkAttachmentReference color_reference{}; @@ -249,136 +248,12 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(const RPKey &key) { subpass.preserveAttachmentCount = 0; subpass.pPreserveAttachments = nullptr; - VkSubpassDependency deps[2]{}; - int numDeps = 0; - switch (key.prevColorLayout) { - case VK_IMAGE_LAYOUT_UNDEFINED: - // No need to specify stage or access. - break; - case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - // Already the right color layout. Unclear that we need to do a lot here.. - break; - case VK_IMAGE_LAYOUT_GENERAL: - // We came from the Mali workaround, and are transitioning back to COLOR_ATTACHMENT_OPTIMAL. - deps[numDeps].srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - deps[numDeps].srcStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - break; - case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - deps[numDeps].srcAccessMask |= VK_ACCESS_SHADER_READ_BIT; - deps[numDeps].srcStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - deps[numDeps].srcAccessMask |= VK_ACCESS_TRANSFER_WRITE_BIT; - deps[numDeps].srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - deps[numDeps].srcAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; - deps[numDeps].srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - default: - _dbg_assert_msg_(false, "GetRenderPass: Unexpected color layout %d", (int)key.prevColorLayout); - break; - } - - switch (key.prevDepthStencilLayout) { - case VK_IMAGE_LAYOUT_UNDEFINED: - // No need to specify stage or access. - break; - case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: - // Already the right depth layout. Unclear that we need to do a lot here.. - break; - case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - deps[numDeps].srcAccessMask |= VK_ACCESS_SHADER_READ_BIT; - deps[numDeps].srcStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - deps[numDeps].srcAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; - deps[numDeps].srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - deps[numDeps].srcAccessMask |= VK_ACCESS_TRANSFER_WRITE_BIT; - deps[numDeps].srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - default: - _dbg_assert_msg_(false, "GetRenderPass: Unexpected depth layout %d", (int)key.prevDepthStencilLayout); - break; - } - - if (deps[numDeps].srcAccessMask) { - deps[numDeps].srcSubpass = VK_SUBPASS_EXTERNAL; - deps[numDeps].dstSubpass = 0; - deps[numDeps].dependencyFlags = 0; - deps[numDeps].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - deps[numDeps].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - numDeps++; - } - - // And the final transition. - // Don't need to transition it if VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL. - switch (key.finalColorLayout) { - case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - deps[numDeps].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - deps[numDeps].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - deps[numDeps].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - deps[numDeps].dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - deps[numDeps].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - deps[numDeps].dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - case VK_IMAGE_LAYOUT_UNDEFINED: - case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - // Nothing to do. - break; - default: - _dbg_assert_msg_(false, "GetRenderPass: Unexpected final color layout %d", (int)key.finalColorLayout); - break; - } - - switch (key.finalDepthStencilLayout) { - case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - deps[numDeps].dstAccessMask |= VK_ACCESS_SHADER_READ_BIT; - deps[numDeps].dstStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - deps[numDeps].dstAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; - deps[numDeps].dstStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - deps[numDeps].dstAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; - deps[numDeps].dstStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - case VK_IMAGE_LAYOUT_UNDEFINED: - case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: - // Nothing to do. - break; - default: - _dbg_assert_msg_(false, "GetRenderPass: Unexpected final depth layout %d", (int)key.finalDepthStencilLayout); - break; - } - - if (deps[numDeps].dstAccessMask) { - deps[numDeps].srcSubpass = 0; - deps[numDeps].dstSubpass = VK_SUBPASS_EXTERNAL; - deps[numDeps].dependencyFlags = 0; - deps[numDeps].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - deps[numDeps].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - numDeps++; - } - VkRenderPassCreateInfo rp{ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO }; rp.attachmentCount = 2; rp.pAttachments = attachments; rp.subpassCount = 1; rp.pSubpasses = &subpass; - if (numDeps) { - rp.dependencyCount = numDeps; - rp.pDependencies = deps; - } - VkResult res = vkCreateRenderPass(vulkan_->GetDevice(), &rp, nullptr, &pass); _assert_(res == VK_SUCCESS); _assert_(pass != VK_NULL_HANDLE); @@ -997,6 +872,194 @@ void VulkanQueueRunner::LogReadbackImage(const VKRStep &step) { INFO_LOG(G3D, "%s", StepToString(step).c_str()); } +void TransitionToOptimal(VkCommandBuffer cmd, VkImage colorImage, VkImageLayout colorLayout, VkImage depthStencilImage, VkImageLayout depthStencilLayout) { + VkPipelineStageFlags srcStageMask = 0; + VkPipelineStageFlags dstStageMask = 0; + int barrierCount = 0; + VkImageMemoryBarrier barrier[2]{}; + + if (colorLayout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { + barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier[0].pNext = nullptr; + switch (colorLayout) { + case VK_IMAGE_LAYOUT_UNDEFINED: + // No need to specify stage or access. + break; + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + // Already the right color layout. Unclear that we need to do a lot here.. + break; + case VK_IMAGE_LAYOUT_GENERAL: + // We came from the Mali workaround, and are transitioning back to COLOR_ATTACHMENT_OPTIMAL. + barrier[0].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + srcStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + break; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + barrier[0].srcAccessMask |= VK_ACCESS_SHADER_READ_BIT; + srcStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + barrier[0].srcAccessMask |= VK_ACCESS_TRANSFER_WRITE_BIT; + srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + barrier[0].srcAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; + srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + default: + _dbg_assert_msg_(false, "GetRenderPass: Unexpected color layout %d", (int)colorLayout); + break; + } + dstStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + barrier[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + barrier[0].oldLayout = colorLayout; + barrier[0].newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + barrier[0].image = colorImage; + barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier[0].subresourceRange.baseMipLevel = 0; + barrier[0].subresourceRange.levelCount = 1; + barrier[0].subresourceRange.layerCount = 1; + barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrierCount++; + } + + if (depthStencilImage != VK_NULL_HANDLE && depthStencilLayout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { + barrier[1].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier[1].pNext = nullptr; + switch (depthStencilLayout) { + case VK_IMAGE_LAYOUT_UNDEFINED: + // No need to specify stage or access. + break; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + // Already the right depth layout. Unclear that we need to do a lot here.. + break; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + barrier[1].srcAccessMask |= VK_ACCESS_SHADER_READ_BIT; + srcStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + barrier[1].srcAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; + srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + barrier[1].srcAccessMask |= VK_ACCESS_TRANSFER_WRITE_BIT; + srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + default: + _dbg_assert_msg_(false, "GetRenderPass: Unexpected depth layout %d", (int)depthStencilLayout); + break; + } + dstStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + barrier[1].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + barrier[1].oldLayout = depthStencilLayout; + barrier[1].newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + barrier[1].image = depthStencilImage; + barrier[1].subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + barrier[1].subresourceRange.baseMipLevel = 0; + barrier[1].subresourceRange.levelCount = 1; + barrier[1].subresourceRange.layerCount = 1; + barrier[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + + barrierCount++; + } + + if (barrierCount) { + vkCmdPipelineBarrier(cmd, srcStageMask, dstStageMask, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, barrierCount, barrier); + } +} + +void TransitionFromOptimal(VkCommandBuffer cmd, VkImage colorImage, VkImageLayout colorLayout, VkImage depthStencilImage, VkImageLayout depthStencilLayout) { + VkPipelineStageFlags srcStageMask = 0; + VkPipelineStageFlags dstStageMask = 0; + + // If layouts aren't optimal, transition them. + VkImageMemoryBarrier barrier[2]{}; + + int barrierCount = 0; + if (colorLayout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { + barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier[0].pNext = nullptr; + srcStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + barrier[0].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + // And the final transition. + // Don't need to transition it if VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL. + switch (colorLayout) { + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + dstStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + dstStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + dstStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + case VK_IMAGE_LAYOUT_UNDEFINED: + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + // Nothing to do. + break; + default: + _dbg_assert_msg_(false, "GetRenderPass: Unexpected final color layout %d", (int)colorLayout); + break; + } + barrier[0].oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + barrier[0].newLayout = colorLayout; + barrier[0].image = colorImage; + barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier[0].subresourceRange.baseMipLevel = 0; + barrier[0].subresourceRange.levelCount = 1; + barrier[0].subresourceRange.layerCount = 1; + barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrierCount++; + } + + if (depthStencilImage && depthStencilLayout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { + barrier[1].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier[1].pNext = nullptr; + + srcStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + barrier[1].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + switch (depthStencilLayout) { + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + barrier[1].dstAccessMask |= VK_ACCESS_SHADER_READ_BIT; + dstStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + barrier[1].dstAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; + dstStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + barrier[1].dstAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; + dstStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + case VK_IMAGE_LAYOUT_UNDEFINED: + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + // Nothing to do. + break; + default: + _dbg_assert_msg_(false, "GetRenderPass: Unexpected final depth layout %d", (int)depthStencilLayout); + break; + } + barrier[1].oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + barrier[1].newLayout = depthStencilLayout; + barrier[1].image = depthStencilImage; + barrier[1].subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + barrier[1].subresourceRange.baseMipLevel = 0; + barrier[1].subresourceRange.levelCount = 1; + barrier[1].subresourceRange.layerCount = 1; + barrier[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrierCount++; + } + if (barrierCount) { + vkCmdPipelineBarrier(cmd, srcStageMask, dstStageMask, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, barrierCount, barrier); + } +} + void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer cmd) { // TODO: If there are multiple, we can transition them together. @@ -1292,8 +1355,10 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c } vkCmdEndRenderPass(cmd); - // The renderpass handles the layout transition. if (fb) { + // If the desired final layout aren't the optimal layout for rendering, transition. + TransitionFromOptimal(cmd, fb->color.image, step.render.finalColorLayout, fb->depth.image, step.render.finalDepthStencilLayout); + fb->color.layout = step.render.finalColorLayout; fb->depth.layout = step.render.finalDepthStencilLayout; } @@ -1331,15 +1396,12 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step fb->color.layout = VK_IMAGE_LAYOUT_GENERAL; } - renderPass = GetRenderPass( - step.render.color, step.render.depth, step.render.stencil, - fb->color.layout, fb->depth.layout, - step.render.finalColorLayout, - step.render.finalDepthStencilLayout); + TransitionToOptimal(cmd, fb->color.image, fb->color.layout, fb->depth.image, fb->depth.layout); - // We now do any layout pretransitions as part of the render pass. - fb->color.layout = step.render.finalColorLayout; - fb->depth.layout = step.render.finalDepthStencilLayout; + renderPass = GetRenderPass(step.render.color, step.render.depth, step.render.stencil); + + // The transition from the optimal format happens after EndRenderPass, now that we don't + // do it as part of the renderpass itself anymore. if (step.render.color == VKRRenderPassAction::CLEAR) { Uint8x4ToFloat4(clearVal[0].color.float32, step.render.clearColor); diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.h b/Common/GPU/Vulkan/VulkanQueueRunner.h index ada7cc49e2..59ee054845 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.h +++ b/Common/GPU/Vulkan/VulkanQueueRunner.h @@ -209,17 +209,12 @@ public: VKRRenderPassAction colorLoadAction; VKRRenderPassAction depthLoadAction; VKRRenderPassAction stencilLoadAction; - VkImageLayout prevColorLayout; - VkImageLayout prevDepthStencilLayout; - VkImageLayout finalColorLayout; - VkImageLayout finalDepthStencilLayout; }; // Only call this from the render thread! Also ok during initialization (LoadCache). VkRenderPass GetRenderPass( - VKRRenderPassAction colorLoadAction, VKRRenderPassAction depthLoadAction, VKRRenderPassAction stencilLoadAction, - VkImageLayout prevColorLayout, VkImageLayout prevDepthStencilLayout, VkImageLayout finalColorLayout, VkImageLayout finalDepthStencilLayout) { - RPKey key{ colorLoadAction, depthLoadAction, stencilLoadAction, prevColorLayout, prevDepthStencilLayout, finalColorLayout, finalDepthStencilLayout }; + VKRRenderPassAction colorLoadAction, VKRRenderPassAction depthLoadAction, VKRRenderPassAction stencilLoadAction) { + RPKey key{ colorLoadAction, depthLoadAction, stencilLoadAction }; return GetRenderPass(key); } @@ -271,6 +266,8 @@ private: VkImage backbufferImage_ = VK_NULL_HANDLE; VkRenderPass backbufferRenderPass_ = VK_NULL_HANDLE; + + // The "Compatible" render pass. Used when creating pipelines that render to "normal" framebuffers. VkRenderPass framebufferRenderPass_ = VK_NULL_HANDLE; // Renderpasses, all combinations of preserving or clearing or dont-care-ing fb contents. From 9d78ba93e0e9a332931f8a0f40a81aaee486c5bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 11 Oct 2020 11:17:43 +0200 Subject: [PATCH 3/3] Bugfix --- Common/GPU/Vulkan/VulkanQueueRunner.cpp | 60 ++++++++++++------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.cpp b/Common/GPU/Vulkan/VulkanQueueRunner.cpp index c2a6c6aa0e..a1c117932c 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.cpp +++ b/Common/GPU/Vulkan/VulkanQueueRunner.cpp @@ -924,8 +924,8 @@ void TransitionToOptimal(VkCommandBuffer cmd, VkImage colorImage, VkImageLayout } if (depthStencilImage != VK_NULL_HANDLE && depthStencilLayout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { - barrier[1].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier[1].pNext = nullptr; + barrier[barrierCount].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier[barrierCount].pNext = nullptr; switch (depthStencilLayout) { case VK_IMAGE_LAYOUT_UNDEFINED: // No need to specify stage or access. @@ -934,15 +934,15 @@ void TransitionToOptimal(VkCommandBuffer cmd, VkImage colorImage, VkImageLayout // Already the right depth layout. Unclear that we need to do a lot here.. break; case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - barrier[1].srcAccessMask |= VK_ACCESS_SHADER_READ_BIT; + barrier[barrierCount].srcAccessMask |= VK_ACCESS_SHADER_READ_BIT; srcStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break; case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - barrier[1].srcAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; + barrier[barrierCount].srcAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; break; case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - barrier[1].srcAccessMask |= VK_ACCESS_TRANSFER_WRITE_BIT; + barrier[barrierCount].srcAccessMask |= VK_ACCESS_TRANSFER_WRITE_BIT; srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; break; default: @@ -950,16 +950,16 @@ void TransitionToOptimal(VkCommandBuffer cmd, VkImage colorImage, VkImageLayout break; } dstStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - barrier[1].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; - barrier[1].oldLayout = depthStencilLayout; - barrier[1].newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - barrier[1].image = depthStencilImage; - barrier[1].subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - barrier[1].subresourceRange.baseMipLevel = 0; - barrier[1].subresourceRange.levelCount = 1; - barrier[1].subresourceRange.layerCount = 1; - barrier[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier[barrierCount].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + barrier[barrierCount].oldLayout = depthStencilLayout; + barrier[barrierCount].newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + barrier[barrierCount].image = depthStencilImage; + barrier[barrierCount].subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + barrier[barrierCount].subresourceRange.baseMipLevel = 0; + barrier[barrierCount].subresourceRange.levelCount = 1; + barrier[barrierCount].subresourceRange.layerCount = 1; + barrier[barrierCount].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier[barrierCount].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrierCount++; } @@ -1018,22 +1018,22 @@ void TransitionFromOptimal(VkCommandBuffer cmd, VkImage colorImage, VkImageLayou } if (depthStencilImage && depthStencilLayout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { - barrier[1].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier[1].pNext = nullptr; + barrier[barrierCount].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier[barrierCount].pNext = nullptr; srcStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - barrier[1].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + barrier[barrierCount].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; switch (depthStencilLayout) { case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - barrier[1].dstAccessMask |= VK_ACCESS_SHADER_READ_BIT; + barrier[barrierCount].dstAccessMask |= VK_ACCESS_SHADER_READ_BIT; dstStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break; case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - barrier[1].dstAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; + barrier[barrierCount].dstAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; dstStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; break; case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - barrier[1].dstAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; + barrier[barrierCount].dstAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; dstStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; break; case VK_IMAGE_LAYOUT_UNDEFINED: @@ -1044,15 +1044,15 @@ void TransitionFromOptimal(VkCommandBuffer cmd, VkImage colorImage, VkImageLayou _dbg_assert_msg_(false, "GetRenderPass: Unexpected final depth layout %d", (int)depthStencilLayout); break; } - barrier[1].oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - barrier[1].newLayout = depthStencilLayout; - barrier[1].image = depthStencilImage; - barrier[1].subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - barrier[1].subresourceRange.baseMipLevel = 0; - barrier[1].subresourceRange.levelCount = 1; - barrier[1].subresourceRange.layerCount = 1; - barrier[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier[barrierCount].oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + barrier[barrierCount].newLayout = depthStencilLayout; + barrier[barrierCount].image = depthStencilImage; + barrier[barrierCount].subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + barrier[barrierCount].subresourceRange.baseMipLevel = 0; + barrier[barrierCount].subresourceRange.levelCount = 1; + barrier[barrierCount].subresourceRange.layerCount = 1; + barrier[barrierCount].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier[barrierCount].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrierCount++; } if (barrierCount) {