diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index e9b43973..3c698a62 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -33,6 +33,9 @@ Released TBD disable recent fixes to handling LOD for arrayed depth images in shaders, on Apple Silicon, when those fixes cause regression in rendering behavior. - Identify each unsupported device feature flag that the app attempts to be enable. +- Populate `deviceUUID` from `MTLDevice` location and peer group info, + which should be unique, and constant across OS reboots. +- Populate `deviceLUID` from `MTLDevice.registryID`. - For correctness, set `VkPhysicalDeviceLimits::lineWidthGranularity` to `1`. - Improve GitHub CI production of binary artifacts on submission and release. diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h index e1f7e310..037d7017 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h @@ -1064,6 +1064,14 @@ protected: /** Returns the registry ID of the specified device, or zero if the device does not have a registry ID. */ uint64_t mvkGetRegistryID(id mtlDevice); +/** + * Returns a value identifying the physical location of the specified device. + * The returned value is a hash of the location, locationNumber, peerGroupID, + * and peerIndex properties of the device. On devices with only one built-in GPU, + * the returned value will be zero. + */ +uint64_t mvkGetLocationID(id mtlDevice); + /** Returns whether the MTLDevice supports BC texture compression. */ bool mvkSupportsBCTextureCompression(id mtlDevice); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index ba0c3310..6adabc31 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -727,15 +727,21 @@ void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2* properties) { } } +// Since these are uint8_t arrays, use Big-Endian byte ordering, +// so a hex dump of the array is human readable in its parts. void MVKPhysicalDevice::populateDeviceIDProperties(VkPhysicalDeviceVulkan11Properties* pVk11Props) { uint8_t* uuid; size_t uuidComponentOffset; - // ---- Device ID ---------------------------------------------- + // ---- Device UUID ---------------------------------------------- uuid = pVk11Props->deviceUUID; uuidComponentOffset = 0; mvkClear(uuid, VK_UUID_SIZE); + // From Vulkan spec: deviceUUID must be universally unique for the device, + // AND must be immutable for a given device across instances, processes, + // driver APIs, driver versions, and system reboots. + // First 4 bytes contains GPU vendor ID uint32_t vendorID = _properties.vendorID; *(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(vendorID); @@ -746,10 +752,10 @@ void MVKPhysicalDevice::populateDeviceIDProperties(VkPhysicalDeviceVulkan11Prope *(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(deviceID); uuidComponentOffset += sizeof(deviceID); - // Last 8 bytes contain the GPU registry ID - uint64_t regID = mvkGetRegistryID(_mtlDevice); - *(uint64_t*)&uuid[uuidComponentOffset] = NSSwapHostLongLongToBig(regID); - uuidComponentOffset += sizeof(regID); + // Last 8 bytes contain the GPU location identifier + uint64_t locID = mvkGetLocationID(_mtlDevice); + *(uint64_t*)&uuid[uuidComponentOffset] = NSSwapHostLongLongToBig(locID); + uuidComponentOffset += sizeof(locID); // ---- Driver ID ---------------------------------------------- uuid = pVk11Props->driverUUID; @@ -772,10 +778,10 @@ void MVKPhysicalDevice::populateDeviceIDProperties(VkPhysicalDeviceVulkan11Prope *(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(gpuCap); uuidComponentOffset += sizeof(gpuCap); - // ---- LUID ignored for Metal devices ------------------------ - mvkClear(pVk11Props->deviceLUID, VK_LUID_SIZE); - pVk11Props->deviceNodeMask = 0; - pVk11Props->deviceLUIDValid = VK_FALSE; + // ---- Device LUID ------------------------ + *(uint64_t*)pVk11Props->deviceLUID = NSSwapHostLongLongToBig(mvkGetRegistryID(_mtlDevice)); + pVk11Props->deviceNodeMask = 1; // Per Vulkan spec + pVk11Props->deviceLUIDValid = VK_TRUE; } void MVKPhysicalDevice::populateSubgroupProperties(VkPhysicalDeviceVulkan11Properties* pVk11Props) { @@ -2732,6 +2738,8 @@ void MVKPhysicalDevice::initGPUInfoProperties() { } #endif //MVK_IOS_OR_TVOS +// Since this is a uint8_t array, use Big-Endian byte ordering, +// so a hex dump of the array is human readable in its parts. void MVKPhysicalDevice::initPipelineCacheUUID() { // Clear the UUID @@ -4835,6 +4843,32 @@ uint64_t mvkGetRegistryID(id mtlDevice) { return [mtlDevice respondsToSelector: @selector(registryID)] ? mtlDevice.registryID : 0; } +uint64_t mvkGetLocationID(id mtlDevice) { + uint64_t hash = 0; + +#if MVK_MACOS && !MVK_MACCAT + // All of these device properties were added at the same time, + // so only need to check for the presence of one of them. + if ([mtlDevice respondsToSelector: @selector(location)]) { + uint64_t val; + + val = mtlDevice.location; + hash = mvkHash(&val, 1, hash); + + val = mtlDevice.locationNumber; + hash = mvkHash(&val, 1, hash); + + val = mtlDevice.peerGroupID; + hash = mvkHash(&val, 1, hash); + + val = mtlDevice.peerIndex; + hash = mvkHash(&val, 1, hash); + } +#endif + + return hash; +} + // If the supportsBCTextureCompression query is available, use it. // Otherwise only macOS supports BC compression. bool mvkSupportsBCTextureCompression(id mtlDevice) {