diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/FrameContext.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/FrameContext.cpp index 1d86aac1..d9eda7bd 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/FrameContext.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/FrameContext.cpp @@ -7,6 +7,9 @@ // End of Source File Header #include "FrameContext.h" +#if MOBILEGL_BUILD_DISAGGREGATED +#include +#endif namespace MobileGL::MG_Backend::DirectVulkan { VkResult FrameContext::Initialize(VkDevice device, VkCommandPool commandPool, Uint32 frameCount) { @@ -217,6 +220,13 @@ namespace MobileGL::MG_Backend::DirectVulkan { VkImageMemoryBarrier presentBarrier{}; presentBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; presentBarrier.srcAccessMask = 0; +#if MOBILEGL_BUILD_DISAGGREGATED + // A layout transition writes the image too. Order it after the wire + // render pass's storeOp, clears and copies instead of relying on the old + // per-draw queue-idle path. This applies even when contents are discarded. + if (MG_Config::Transport != MG_Config::TransportMode::Monolith) + presentBarrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; +#endif presentBarrier.dstAccessMask = 0; presentBarrier.oldLayout = oldLayout; presentBarrier.newLayout = presentLayout; @@ -228,7 +238,14 @@ namespace MobileGL::MG_Backend::DirectVulkan { presentBarrier.subresourceRange.levelCount = 1; presentBarrier.subresourceRange.baseArrayLayer = 0; presentBarrier.subresourceRange.layerCount = 1; - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, + vkCmdPipelineBarrier(commandBuffer, +#if MOBILEGL_BUILD_DISAGGREGATED + MG_Config::Transport != MG_Config::TransportMode::Monolith + ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, +#else + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, +#endif + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &presentBarrier); if (openedRecording) { diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/ProgramFactory.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/ProgramFactory.cpp index cde67a8f..5228cf01 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/ProgramFactory.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/ProgramFactory.cpp @@ -3365,6 +3365,13 @@ namespace MobileGL::MG_Backend::DirectVulkan { updateAfterBindSampledImages + updateAfterBindStorageImages; const auto& uab = m_updateAfterBindLimits; entry.usesUpdateAfterBind = +#if MOBILEGL_BUILD_DISAGGREGATED + // Vulkan forbids ANY update-after-bind binding in a set layout that + // contains a dynamic buffer descriptor (VUID 03001/03011). Wire draws + // retain UniformManager's per-frame, content-versioned descriptor sets; + // this selects the legal ordinary pool, not in-place mutation of a live set. + (!program.IsWire() || entry.dynamicBindings.empty()) && +#endif uab.enabled && updateAfterBindSamplers <= uab.maxPerStageSamplers && updateAfterBindUniformBuffers <= uab.maxPerStageUniformBuffers && updateAfterBindStorageBuffers <= uab.maxPerStageStorageBuffers && diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index 97c41e48..37c44260 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -7667,7 +7667,16 @@ void main() { VkMemoryBarrier memoryBarrier = BuildMemoryBarrierForGlBarriers(barriers); MGLOG_D("DirectVulkan: glMemoryBarrier(0x%x)", static_cast(barriers)); - vkCmdPipelineBarrier(frame.commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + vkCmdPipelineBarrier(frame.commandBuffer, +#if MOBILEGL_BUILD_DISAGGREGATED + // ALL_COMMANDS does not include HOST. The barrier's + // HOST_WRITE access must have a matching source stage. + MG_Config::Transport != MG_Config::TransportMode::Monolith + ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT | VK_PIPELINE_STAGE_HOST_BIT + : VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, +#else + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, +#endif VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr); } @@ -14277,7 +14286,14 @@ void main() { descriptorIndexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES; VkPhysicalDeviceDescriptorIndexingProperties descriptorIndexingProperties{}; descriptorIndexingProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES; - const Bool descriptorIndexingCore = m_physicalDevice.properties.apiVersion >= VK_API_VERSION_1_2; + const Bool descriptorIndexingCore = +#if MOBILEGL_BUILD_DISAGGREGATED && !defined(VK_USE_PLATFORM_WIN32_KHR) + // CreateInstance requests Vulkan 1.1 on these platforms. A 1.2+ GPU + // does not promote descriptor indexing into that application's core + // API; the wire path must enable VK_EXT_descriptor_indexing instead. + (MG_Config::Transport == MG_Config::TransportMode::Monolith) && +#endif + m_physicalDevice.properties.apiVersion >= VK_API_VERSION_1_2; const Bool descriptorIndexingExtension = IsExtensionSupported(availableExtensions, VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); auto getPhysicalDeviceProperties2 = reinterpret_cast(