From a83f1a14e7c2015160249e92ea943ae927f4fd3b Mon Sep 17 00:00:00 2001 From: swinston Date: Wed, 28 Jan 2026 00:31:43 -0800 Subject: [PATCH 1/2] Add read access flags to color and depth attachment barriers for correct Vulkan synchronization --- attachments/simple_engine/renderer_rendering.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/attachments/simple_engine/renderer_rendering.cpp b/attachments/simple_engine/renderer_rendering.cpp index 2456e8c2..32bf7dc7 100644 --- a/attachments/simple_engine/renderer_rendering.cpp +++ b/attachments/simple_engine/renderer_rendering.cpp @@ -314,7 +314,7 @@ void Renderer::renderReflectionPass(vk::raii::CommandBuffer& cmd, .srcStageMask = vk::PipelineStageFlagBits2::eTopOfPipe, .srcAccessMask = {}, .dstStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput, - .dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite, + .dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite | vk::AccessFlagBits2::eColorAttachmentRead, .oldLayout = vk::ImageLayout::eShaderReadOnlyOptimal, .newLayout = vk::ImageLayout::eColorAttachmentOptimal, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, @@ -327,7 +327,7 @@ void Renderer::renderReflectionPass(vk::raii::CommandBuffer& cmd, .srcStageMask = vk::PipelineStageFlagBits2::eTopOfPipe, .srcAccessMask = {}, .dstStageMask = vk::PipelineStageFlagBits2::eEarlyFragmentTests, - .dstAccessMask = vk::AccessFlagBits2::eDepthStencilAttachmentWrite, + .dstAccessMask = vk::AccessFlagBits2::eDepthStencilAttachmentWrite | vk::AccessFlagBits2::eDepthStencilAttachmentRead, .oldLayout = vk::ImageLayout::eUndefined, .newLayout = vk::ImageLayout::eDepthAttachmentOptimal, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, @@ -1924,7 +1924,7 @@ void Renderer::Render(const std::vector& entities, CameraComponent* ca swapchainToColor.srcStageMask = vk::PipelineStageFlagBits2::eBottomOfPipe; swapchainToColor.srcAccessMask = vk::AccessFlagBits2::eNone; swapchainToColor.dstStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput; - swapchainToColor.dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite; + swapchainToColor.dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite | vk::AccessFlagBits2::eColorAttachmentRead; swapchainToColor.oldLayout = (imageIndex < swapChainImageLayouts.size()) ? swapChainImageLayouts[imageIndex] : vk::ImageLayout::eUndefined; swapchainToColor.newLayout = vk::ImageLayout::eColorAttachmentOptimal; swapchainToColor.image = swapChainImages[imageIndex]; @@ -2362,7 +2362,7 @@ void Renderer::Render(const std::vector& entities, CameraComponent* ca .srcStageMask = oscSrcStage, .srcAccessMask = oscSrcAccess, .dstStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput, - .dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite, + .dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite | vk::AccessFlagBits2::eColorAttachmentRead, .oldLayout = oscOldLayout, .newLayout = vk::ImageLayout::eColorAttachmentOptimal, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, @@ -2471,7 +2471,7 @@ void Renderer::Render(const std::vector& entities, CameraComponent* ca .srcStageMask = vk::PipelineStageFlagBits2::eBottomOfPipe, .srcAccessMask = vk::AccessFlagBits2::eNone, .dstStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput, - .dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite, + .dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite | vk::AccessFlagBits2::eColorAttachmentRead, .oldLayout = vk::ImageLayout::eUndefined, .newLayout = vk::ImageLayout::eColorAttachmentOptimal, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, @@ -2620,7 +2620,7 @@ void Renderer::Render(const std::vector& entities, CameraComponent* ca .srcStageMask = vk::PipelineStageFlagBits2::eBottomOfPipe, .srcAccessMask = vk::AccessFlagBits2::eNone, .dstStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput, - .dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite, + .dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite | vk::AccessFlagBits2::eColorAttachmentRead, .oldLayout = (imageIndex < swapChainImageLayouts.size()) ? swapChainImageLayouts[imageIndex] : vk::ImageLayout::eUndefined, .newLayout = vk::ImageLayout::eColorAttachmentOptimal, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, From 42a09d511fcf9bd7eea4bb22721268be462acdf3 Mon Sep 17 00:00:00 2001 From: swinston Date: Wed, 28 Jan 2026 00:42:14 -0800 Subject: [PATCH 2/2] Remove attachment feedback loop extension support and simplify device feature requirements This addresses the best practices validation layer warnings. --- attachments/simple_engine/renderer.h | 1 - attachments/simple_engine/renderer_core.cpp | 16 ---------------- attachments/simple_engine/vulkan_device.cpp | 13 +++---------- 3 files changed, 3 insertions(+), 27 deletions(-) diff --git a/attachments/simple_engine/renderer.h b/attachments/simple_engine/renderer.h index b35c089a..2c716e22 100644 --- a/attachments/simple_engine/renderer.h +++ b/attachments/simple_engine/renderer.h @@ -1566,7 +1566,6 @@ class Renderer { VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME, - VK_EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_EXTENSION_NAME, VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME, // Robustness and safety VK_EXT_ROBUSTNESS_2_EXTENSION_NAME, diff --git a/attachments/simple_engine/renderer_core.cpp b/attachments/simple_engine/renderer_core.cpp index f55092af..d2c2af1d 100644 --- a/attachments/simple_engine/renderer_core.cpp +++ b/attachments/simple_engine/renderer_core.cpp @@ -795,23 +795,7 @@ void Renderer::addSupportedOptionalExtensions() { avail.insert(e.extensionName); } - // First, handle dependency: VK_EXT_attachment_feedback_loop_dynamic_state requires VK_EXT_attachment_feedback_loop_layout - const char* dynState = VK_EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_EXTENSION_NAME; - const char* layoutReq = "VK_EXT_attachment_feedback_loop_layout"; - bool dynSupported = avail.contains(dynState); - bool layoutSupported = avail.contains(layoutReq); for (const auto& optionalExt : optionalDeviceExtensions) { - if (std::strcmp(optionalExt, dynState) == 0) { - if (dynSupported && layoutSupported) { - deviceExtensions.push_back(dynState); - deviceExtensions.push_back(layoutReq); - std::cout << "Adding optional extension: " << dynState << std::endl; - std::cout << "Adding required-by-optional extension: " << layoutReq << std::endl; - } else if (dynSupported && !layoutSupported) { - std::cout << "Skipping extension due to missing dependency: " << dynState << " requires " << layoutReq << std::endl; - } - continue; // handled - } if (avail.contains(optionalExt)) { deviceExtensions.push_back(optionalExt); std::cout << "Adding optional extension: " << optionalExt << std::endl; diff --git a/attachments/simple_engine/vulkan_device.cpp b/attachments/simple_engine/vulkan_device.cpp index 1e5d9988..c67e66df 100644 --- a/attachments/simple_engine/vulkan_device.cpp +++ b/attachments/simple_engine/vulkan_device.cpp @@ -86,17 +86,12 @@ bool VulkanDevice::pickPhysicalDevice() { } // Check for required features - auto features = device.template getFeatures2(); + auto features = device.template getFeatures2(); bool supportsRequiredFeatures = (features.template get().dynamicRendering == VK_TRUE); if (!supportsRequiredFeatures) { std::cout << " - Does not support required features (dynamicRendering)" << std::endl; } - if (features.template get().attachmentFeedbackLoopLayout == VK_FALSE) { - supportsRequiredFeatures = false; - std::cout << " - Does not support required feature (attachmentFeedbackLoopLayout)" << std::endl; - } - return supportsVulkan1_3 && supportsGraphics && supportsAllRequiredExtensions && swapChainAdequate && supportsRequiredFeatures; }); @@ -142,12 +137,10 @@ bool VulkanDevice::createLogicalDevice(bool enableValidationLayers, const std::v // Enable required features using StructureChain vk::StructureChain< vk::PhysicalDeviceFeatures2, - vk::PhysicalDeviceVulkan13Features, - vk::PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT + vk::PhysicalDeviceVulkan13Features > featureChain{ {.features = {.depthClamp = vk::True, .samplerAnisotropy = vk::True}}, - {.synchronization2 = vk::True, .dynamicRendering = vk::True}, - {.attachmentFeedbackLoopLayout = vk::True} + {.synchronization2 = vk::True, .dynamicRendering = vk::True} }; auto& features = featureChain.get();