Merge pull request #680 from cdavis5e/device-group-creation
Add a minimal implementation of VK_KHR_device_group_creation.
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
index 1a1282e..e087ea1 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
@@ -663,7 +663,7 @@
MVKResource* addResource(MVKResource* rez);
MVKResource* removeResource(MVKResource* rez);
void initPerformanceTracking();
- void initPhysicalDevice(MVKPhysicalDevice* physicalDevice);
+ void initPhysicalDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo* pCreateInfo);
void initQueues(const VkDeviceCreateInfo* pCreateInfo);
void initMTLCompileOptions();
void enableFeatures(const VkDeviceCreateInfo* pCreateInfo);
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index e22abc0..c1b6a68 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -2232,7 +2232,7 @@
{
initPerformanceTracking();
- initPhysicalDevice(physicalDevice);
+ initPhysicalDevice(physicalDevice, pCreateInfo);
enableFeatures(pCreateInfo);
enableExtensions(pCreateInfo);
@@ -2273,9 +2273,27 @@
_performanceStatistics.queue.mtlCommandBufferCompletion = initPerf;
}
-void MVKDevice::initPhysicalDevice(MVKPhysicalDevice* physicalDevice) {
+void MVKDevice::initPhysicalDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo* pCreateInfo) {
- _physicalDevice = physicalDevice;
+ const VkDeviceGroupDeviceCreateInfo* pGroupCreateInfo = nullptr;
+ for (const auto* next = (const VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) {
+ switch (next->sType) {
+ case VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO:
+ pGroupCreateInfo = (const VkDeviceGroupDeviceCreateInfo*)next;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // If I was given physical devices for a grouped device, use them.
+ // At this time, we only support device groups consisting of a single member,
+ // so this is sufficient for now.
+ if (pGroupCreateInfo && pGroupCreateInfo->physicalDeviceCount)
+ _physicalDevice = MVKPhysicalDevice::getMVKPhysicalDevice(pGroupCreateInfo->pPhysicalDevices[0]);
+ else
+ _physicalDevice = physicalDevice;
+
_pMVKConfig = _physicalDevice->_mvkInstance->getMoltenVKConfiguration();
_pMetalFeatures = _physicalDevice->getMetalFeatures();
_pProperties = &_physicalDevice->_properties;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.h b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.h
index 6784567..5771fe6 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.h
@@ -85,6 +85,20 @@
*/
VkResult getPhysicalDevices(uint32_t* pCount, VkPhysicalDevice* pPhysicalDevices);
+ /**
+ * If pPhysicalDeviceGroups is null, the value of pCount is updated with the number of
+ * physical device groups supported by this instance.
+ *
+ * If pPhysicalDeviceGroups is not null, then pCount physical device groups are copied into the array.
+ * If the number of available physical device groups is less than pCount, the value of pCount is
+ * updated to indicate the number of physical device groups actually returned in the array.
+ *
+ * Returns VK_SUCCESS if successful. Returns VK_INCOMPLETE if the number of physical
+ * device groups available in this instance is larger than the specified pCount. Returns other
+ * values if an error occurs.
+ */
+ VkResult getPhysicalDeviceGroups(uint32_t* pCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProps);
+
/** Returns the driver layer. */
MVKLayer* getDriverLayer() { return MVKLayerManager::globalManager()->getDriverLayer(); }
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
index 88c41af..ce9fa40 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
@@ -70,6 +70,36 @@
return result;
}
+VkResult MVKInstance::getPhysicalDeviceGroups(uint32_t* pCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProps) {
+
+ // According to the Vulkan spec:
+ // "Every physical device *must* be in exactly one device group."
+ // Since we don't really support this yet, we must return one group for every
+ // device.
+
+ // Get the number of physical devices
+ uint32_t pdCnt = (uint32_t)_physicalDevices.size();
+
+ // If properties aren't actually being requested yet, simply update the returned count
+ if ( !pPhysicalDeviceGroupProps ) {
+ *pCount = pdCnt;
+ return VK_SUCCESS;
+ }
+
+ // Othewise, determine how many physical device groups we'll return, and return that count
+ VkResult result = (*pCount >= pdCnt) ? VK_SUCCESS : VK_INCOMPLETE;
+ *pCount = min(pdCnt, *pCount);
+
+ // Now populate the device groups
+ for (uint32_t pdIdx = 0; pdIdx < *pCount; pdIdx++) {
+ pPhysicalDeviceGroupProps[pdIdx].physicalDeviceCount = 1;
+ pPhysicalDeviceGroupProps[pdIdx].physicalDevices[0] = _physicalDevices[pdIdx]->getVkPhysicalDevice();
+ pPhysicalDeviceGroupProps[pdIdx].subsetAllocation = VK_FALSE;
+ }
+
+ return result;
+}
+
MVKSurface* MVKInstance::createSurface(const VkMetalSurfaceCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator) {
return new MVKSurface(this, pCreateInfo, pAllocator);
@@ -523,6 +553,7 @@
ADD_DVC_ENTRY_POINT(vkCmdExecuteCommands);
// Instance extension functions:
+ ADD_INST_EXT_ENTRY_POINT(vkEnumeratePhysicalDeviceGroupsKHR, KHR_DEVICE_GROUP_CREATION);
ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceFeatures2KHR, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2);
ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceProperties2KHR, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2);
ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceFormatProperties2KHR, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2);
diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.def b/MoltenVK/MoltenVK/Layers/MVKExtensions.def
index 0a518a3..43e244b 100644
--- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def
+++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def
@@ -35,6 +35,7 @@
MVK_EXTENSION(KHR_bind_memory2, KHR_BIND_MEMORY_2)
MVK_EXTENSION(KHR_dedicated_allocation, KHR_DEDICATED_ALLOCATION)
MVK_EXTENSION(KHR_descriptor_update_template, KHR_DESCRIPTOR_UPDATE_TEMPLATE)
+MVK_EXTENSION(KHR_device_group_creation, KHR_DEVICE_GROUP_CREATION)
MVK_EXTENSION(KHR_get_memory_requirements2, KHR_GET_MEMORY_REQUIREMENTS_2)
MVK_EXTENSION(KHR_get_physical_device_properties2, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2)
MVK_EXTENSION(KHR_get_surface_capabilities2, KHR_GET_SURFACE_CAPABILITIES_2)
diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
index 8a287a5..3522f87 100644
--- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm
+++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
@@ -1964,6 +1964,21 @@
#pragma mark -
+#pragma mark VK_KHR_device_group_creation extension
+
+MVK_PUBLIC_SYMBOL VkResult vkEnumeratePhysicalDeviceGroupsKHR(
+ VkInstance instance,
+ uint32_t* pPhysicalDeviceGroupCount,
+ VkPhysicalDeviceGroupPropertiesKHR* pPhysicalDeviceGroupProperties) {
+ MVKTraceVulkanCallStart();
+ MVKInstance* mvkInst = MVKInstance::getMVKInstance(instance);
+ VkResult rslt = mvkInst->getPhysicalDeviceGroups(pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
+ MVKTraceVulkanCallEnd();
+ return rslt;
+}
+
+
+#pragma mark -
#pragma mark VK_KHR_get_memory_requirements2 extension
MVK_PUBLIC_SYMBOL void vkGetBufferMemoryRequirements2KHR(
@@ -2377,22 +2392,6 @@
#pragma mark -
-#pragma mark VK_EXT_host_query_reset extension
-
-MVK_PUBLIC_SYMBOL void vkResetQueryPoolEXT(
- VkDevice device,
- VkQueryPool queryPool,
- uint32_t firstQuery,
- uint32_t queryCount) {
-
- MVKTraceVulkanCallStart();
- auto* mvkQueryPool = (MVKQueryPool*)queryPool;
- mvkQueryPool->resetResults(firstQuery, queryCount, nullptr);
- MVKTraceVulkanCallEnd();
-}
-
-
-#pragma mark -
#pragma mark VK_EXT_debug_report extension
MVK_PUBLIC_SYMBOL VkResult vkCreateDebugReportCallbackEXT(
@@ -2608,6 +2607,23 @@
MVKTraceVulkanCallEnd();
}
+
+#pragma mark -
+#pragma mark VK_EXT_host_query_reset extension
+
+MVK_PUBLIC_SYMBOL void vkResetQueryPoolEXT(
+ VkDevice device,
+ VkQueryPool queryPool,
+ uint32_t firstQuery,
+ uint32_t queryCount) {
+
+ MVKTraceVulkanCallStart();
+ auto* mvkQueryPool = (MVKQueryPool*)queryPool;
+ mvkQueryPool->resetResults(firstQuery, queryCount, nullptr);
+ MVKTraceVulkanCallEnd();
+}
+
+
#pragma mark -
#pragma mark VK_EXT_metal_surface extension