Implement VK_KHR_internally_synchronized_queues Internally, the queues are almost already internally synchronized. This simple implementation adds a high-level lock at the entry-point level just in case. Test: dEQP-VK.synchronization2.internally_synchronized_queues.* Change-Id: I3fcd1fba06662f2212db9008fdf9a3c9c7582de2 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/77408 Reviewed-by: Chris Forbes <chrisforbes@google.com> Commit-Queue: Shahbaz Youssefi <syoussefi@google.com> Tested-by: Shahbaz Youssefi <syoussefi@google.com>
diff --git a/src/Vulkan/VkDevice.cpp b/src/Vulkan/VkDevice.cpp index cc58b08..6ead907 100644 --- a/src/Vulkan/VkDevice.cpp +++ b/src/Vulkan/VkDevice.cpp
@@ -136,7 +136,7 @@ for(uint32_t j = 0; j < queueCreateInfo.queueCount; j++, queueID++) { - new(&queues[queueID]) Queue(this, scheduler.get()); + new(&queues[queueID]) Queue(this, scheduler.get(), queueCreateInfo.flags); } }
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp index 21dbcb1..5d5edcf 100644 --- a/src/Vulkan/VkPhysicalDevice.cpp +++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -426,6 +426,12 @@ } template<typename T> +static void getPhysicalDeviceInternallySynchronizedQueuesFeatures(T *features) +{ + features->internallySynchronizedQueues = VK_TRUE; +} + +template<typename T> static void getPhysicalDeviceVulkan12Features(T *features) { features->samplerMirrorClampToEdge = VK_TRUE; @@ -698,6 +704,9 @@ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES: getPhysicalDeviceIndexTypeUint8Features(reinterpret_cast<VkPhysicalDeviceIndexTypeUint8Features *>(curExtension)); break; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INTERNALLY_SYNCHRONIZED_QUEUES_FEATURES_KHR: + getPhysicalDeviceInternallySynchronizedQueuesFeatures(reinterpret_cast<VkPhysicalDeviceInternallySynchronizedQueuesFeaturesKHR *>(curExtension)); + break; case VK_STRUCTURE_TYPE_MAX_ENUM: // TODO(b/176893525): This may not be legal. dEQP tests that this value is ignored. break; default: @@ -1818,6 +1827,13 @@ return CheckFeature(requested, supported, indexTypeUint8); } +bool PhysicalDevice::hasExtendedFeatures(const VkPhysicalDeviceInternallySynchronizedQueuesFeaturesKHR *requested) const +{ + auto supported = getSupportedFeatures(requested); + + return CheckFeature(requested, supported, internallySynchronizedQueues); +} + bool PhysicalDevice::hasExtendedFeatures(const VkPhysicalDeviceDescriptorIndexingFeatures *requested) const { auto supported = getSupportedFeatures(requested);
diff --git a/src/Vulkan/VkPhysicalDevice.hpp b/src/Vulkan/VkPhysicalDevice.hpp index b750692..a12b8a6 100644 --- a/src/Vulkan/VkPhysicalDevice.hpp +++ b/src/Vulkan/VkPhysicalDevice.hpp
@@ -67,6 +67,7 @@ bool hasExtendedFeatures(const VkPhysicalDeviceSwapchainMaintenance1FeaturesKHR *requested) const; bool hasExtendedFeatures(const VkPhysicalDeviceHostImageCopyFeatures *requested) const; bool hasExtendedFeatures(const VkPhysicalDeviceIndexTypeUint8Features *requested) const; + bool hasExtendedFeatures(const VkPhysicalDeviceInternallySynchronizedQueuesFeaturesKHR *requested) const; const VkPhysicalDeviceProperties &getProperties() const; void getProperties(VkPhysicalDeviceIDProperties *properties) const;
diff --git a/src/Vulkan/VkQueue.cpp b/src/Vulkan/VkQueue.cpp index fc329e9..a0d143d 100644 --- a/src/Vulkan/VkQueue.cpp +++ b/src/Vulkan/VkQueue.cpp
@@ -32,10 +32,14 @@ namespace vk { -Queue::Queue(Device *device, marl::Scheduler *scheduler) +Queue::Queue(Device *device, marl::Scheduler *scheduler, VkDeviceQueueCreateFlags flags) : device(device) { queueThread = std::thread(&Queue::taskLoop, this, scheduler); + if (((int)flags & VK_DEVICE_QUEUE_CREATE_INTERNALLY_SYNCHRONIZED_BIT_KHR) != 0) + { + internalMutex.reset(new marl::mutex); + } } Queue::~Queue() @@ -256,4 +260,13 @@ // Optional single debug label } +std::unique_lock<marl::mutex> Queue::getInternalLock() +{ + if (internalMutex) + { + return std::unique_lock<marl::mutex>(*internalMutex); + } + return std::unique_lock<marl::mutex>(); +} + } // namespace vk
diff --git a/src/Vulkan/VkQueue.hpp b/src/Vulkan/VkQueue.hpp index 5691020..1b145ef 100644 --- a/src/Vulkan/VkQueue.hpp +++ b/src/Vulkan/VkQueue.hpp
@@ -43,7 +43,7 @@ VK_LOADER_DATA loaderData = { ICD_LOADER_MAGIC }; public: - Queue(Device *device, marl::Scheduler *scheduler); + Queue(Device *device, marl::Scheduler *scheduler, VkDeviceQueueCreateFlags flags); ~Queue(); operator VkQueue() @@ -61,6 +61,8 @@ void endDebugUtilsLabel(); void insertDebugUtilsLabel(const VkDebugUtilsLabelEXT *pLabelInfo); + std::unique_lock<marl::mutex> getInternalLock(); + private: struct Task { @@ -85,6 +87,8 @@ sw::Chan<Task> pending; sw::Chan<SubmitInfo *> toDelete; std::thread queueThread; + // For VK_KHR_internally_synchronized_queues + std::unique_ptr<marl::mutex> internalMutex; }; static inline Queue *Cast(VkQueue object)
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp index d6bc854..6e4dad0 100644 --- a/src/Vulkan/libVulkan.cpp +++ b/src/Vulkan/libVulkan.cpp
@@ -459,6 +459,7 @@ { { VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION } }, { { VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME, VK_KHR_PIPELINE_LIBRARY_SPEC_VERSION } }, { { VK_KHR_UNIFIED_IMAGE_LAYOUTS_EXTENSION_NAME, VK_KHR_UNIFIED_IMAGE_LAYOUTS_SPEC_VERSION } }, + { { VK_KHR_INTERNALLY_SYNCHRONIZED_QUEUES_EXTENSION_NAME, VK_KHR_INTERNALLY_SYNCHRONIZED_QUEUES_SPEC_VERSION } }, #ifndef __ANDROID__ { { VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME, VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_SPEC_VERSION } }, { { VK_KHR_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME, VK_KHR_SWAPCHAIN_MAINTENANCE_1_SPEC_VERSION } }, @@ -1243,6 +1244,7 @@ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT: case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES: case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES: + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INTERNALLY_SYNCHRONIZED_QUEUES_FEATURES_KHR: break; default: // "the [driver] must skip over, without processing (other than reading the sType and pNext members) any structures in the chain with sType values not defined by [supported extenions]" @@ -1268,7 +1270,8 @@ for(uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) { const VkDeviceQueueCreateInfo &queueCreateInfo = pCreateInfo->pQueueCreateInfos[i]; - if(queueCreateInfo.flags != 0) + + if((queueCreateInfo.flags & ~VK_DEVICE_QUEUE_CREATE_INTERNALLY_SYNCHRONIZED_BIT_KHR) != 0) { UNSUPPORTED("pCreateInfo->pQueueCreateInfos[%d]->flags 0x%08X", i, queueCreateInfo.flags); } @@ -1388,6 +1391,7 @@ TRACE("(VkQueue queue = %p, uint32_t submitCount = %d, const VkSubmitInfo* pSubmits = %p, VkFence fence = %p)", queue, submitCount, pSubmits, static_cast<void *>(fence)); + auto queueLock = vk::Cast(queue)->getInternalLock(); return vk::Cast(queue)->submit(submitCount, vk::SubmitInfo::Allocate(submitCount, pSubmits), vk::Cast(fence)); } @@ -1396,6 +1400,7 @@ TRACE("(VkQueue queue = %p, uint32_t submitCount = %d, const VkSubmitInfo2* pSubmits = %p, VkFence fence = %p)", queue, submitCount, pSubmits, static_cast<void *>(fence)); + auto queueLock = vk::Cast(queue)->getInternalLock(); return vk::Cast(queue)->submit(submitCount, vk::SubmitInfo::Allocate(submitCount, pSubmits), vk::Cast(fence)); } @@ -1403,6 +1408,7 @@ { TRACE("(VkQueue queue = %p)", queue); + auto queueLock = vk::Cast(queue)->getInternalLock(); return vk::Cast(queue)->waitIdle(); } @@ -1679,6 +1685,7 @@ { TRACE("()"); UNSUPPORTED("vkQueueBindSparse"); + auto queueLock = vk::Cast(queue)->getInternalLock(); return VK_SUCCESS; } @@ -4214,7 +4221,7 @@ extInfo = extInfo->pNext; } - if(pQueueInfo->flags != 0) + if((pQueueInfo->flags & VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT) != 0) { // The only flag that can be set here is VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT // According to the Vulkan 1.2.132 spec, 4.3.1. Queue Family Properties: @@ -4488,6 +4495,7 @@ TRACE("(VkQueue queue = %p, const VkDebugUtilsLabelEXT* pLabelInfo = %p)", queue, pLabelInfo); + auto queueLock = vk::Cast(queue)->getInternalLock(); vk::Cast(queue)->beginDebugUtilsLabel(pLabelInfo); } @@ -4495,6 +4503,7 @@ { TRACE("(VkQueue queue = %p)", queue); + auto queueLock = vk::Cast(queue)->getInternalLock(); vk::Cast(queue)->endDebugUtilsLabel(); } @@ -4503,6 +4512,7 @@ TRACE("(VkQueue queue = %p, const VkDebugUtilsLabelEXT* pLabelInfo = %p)", queue, pLabelInfo); + auto queueLock = vk::Cast(queue)->getInternalLock(); vk::Cast(queue)->insertDebugUtilsLabel(pLabelInfo); } @@ -4922,6 +4932,7 @@ TRACE("(VkQueue queue = %p, const VkPresentInfoKHR* pPresentInfo = %p)", queue, pPresentInfo); + auto queueLock = vk::Cast(queue)->getInternalLock(); return vk::Cast(queue)->present(pPresentInfo); }