Improve support for deviceUUID and deviceLUID.

- MTLDevice registryID is not constant across OS reboots,
  which is not conformant with deviceUUID requirements.
- Replace with combination of MTLDevice location, locationNumber,
  peerGroupID, and peerIndex, which should define uniqueness,
  and should be constant across OS reboots.
- Populate deviceLUID from MTLDevice registryID.
This commit is contained in:
Bill Hollings 2023-05-16 10:39:16 -04:00
parent 44c3063439
commit 665ef6df13
3 changed files with 54 additions and 9 deletions

View File

@ -32,6 +32,9 @@ Released TBD
disable recent fixes to handling LOD for arrayed depth images in shaders, disable recent fixes to handling LOD for arrayed depth images in shaders,
on Apple Silicon, when those fixes cause regression in rendering behavior. on Apple Silicon, when those fixes cause regression in rendering behavior.
- Identify each unsupported device feature flag that the app attempts to be enable. - 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`. - For correctness, set `VkPhysicalDeviceLimits::lineWidthGranularity` to `1`.
- Improve GitHub CI production of binary artifacts on submission and release. - Improve GitHub CI production of binary artifacts on submission and release.

View File

@ -1064,6 +1064,14 @@ protected:
/** Returns the registry ID of the specified device, or zero if the device does not have a registry ID. */ /** Returns the registry ID of the specified device, or zero if the device does not have a registry ID. */
uint64_t mvkGetRegistryID(id<MTLDevice> mtlDevice); uint64_t mvkGetRegistryID(id<MTLDevice> 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> mtlDevice);
/** Returns whether the MTLDevice supports BC texture compression. */ /** Returns whether the MTLDevice supports BC texture compression. */
bool mvkSupportsBCTextureCompression(id<MTLDevice> mtlDevice); bool mvkSupportsBCTextureCompression(id<MTLDevice> mtlDevice);

View File

@ -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) { void MVKPhysicalDevice::populateDeviceIDProperties(VkPhysicalDeviceVulkan11Properties* pVk11Props) {
uint8_t* uuid; uint8_t* uuid;
size_t uuidComponentOffset; size_t uuidComponentOffset;
// ---- Device ID ---------------------------------------------- // ---- Device UUID ----------------------------------------------
uuid = pVk11Props->deviceUUID; uuid = pVk11Props->deviceUUID;
uuidComponentOffset = 0; uuidComponentOffset = 0;
mvkClear(uuid, VK_UUID_SIZE); 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 // First 4 bytes contains GPU vendor ID
uint32_t vendorID = _properties.vendorID; uint32_t vendorID = _properties.vendorID;
*(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(vendorID); *(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(vendorID);
@ -746,10 +752,10 @@ void MVKPhysicalDevice::populateDeviceIDProperties(VkPhysicalDeviceVulkan11Prope
*(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(deviceID); *(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(deviceID);
uuidComponentOffset += sizeof(deviceID); uuidComponentOffset += sizeof(deviceID);
// Last 8 bytes contain the GPU registry ID // Last 8 bytes contain the GPU location identifier
uint64_t regID = mvkGetRegistryID(_mtlDevice); uint64_t locID = mvkGetLocationID(_mtlDevice);
*(uint64_t*)&uuid[uuidComponentOffset] = NSSwapHostLongLongToBig(regID); *(uint64_t*)&uuid[uuidComponentOffset] = NSSwapHostLongLongToBig(locID);
uuidComponentOffset += sizeof(regID); uuidComponentOffset += sizeof(locID);
// ---- Driver ID ---------------------------------------------- // ---- Driver ID ----------------------------------------------
uuid = pVk11Props->driverUUID; uuid = pVk11Props->driverUUID;
@ -772,10 +778,10 @@ void MVKPhysicalDevice::populateDeviceIDProperties(VkPhysicalDeviceVulkan11Prope
*(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(gpuCap); *(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(gpuCap);
uuidComponentOffset += sizeof(gpuCap); uuidComponentOffset += sizeof(gpuCap);
// ---- LUID ignored for Metal devices ------------------------ // ---- Device LUID ------------------------
mvkClear(pVk11Props->deviceLUID, VK_LUID_SIZE); *(uint64_t*)pVk11Props->deviceLUID = NSSwapHostLongLongToBig(mvkGetRegistryID(_mtlDevice));
pVk11Props->deviceNodeMask = 0; pVk11Props->deviceNodeMask = 1; // Per Vulkan spec
pVk11Props->deviceLUIDValid = VK_FALSE; pVk11Props->deviceLUIDValid = VK_TRUE;
} }
void MVKPhysicalDevice::populateSubgroupProperties(VkPhysicalDeviceVulkan11Properties* pVk11Props) { void MVKPhysicalDevice::populateSubgroupProperties(VkPhysicalDeviceVulkan11Properties* pVk11Props) {
@ -2732,6 +2738,8 @@ void MVKPhysicalDevice::initGPUInfoProperties() {
} }
#endif //MVK_IOS_OR_TVOS #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() { void MVKPhysicalDevice::initPipelineCacheUUID() {
// Clear the UUID // Clear the UUID
@ -4835,6 +4843,32 @@ uint64_t mvkGetRegistryID(id<MTLDevice> mtlDevice) {
return [mtlDevice respondsToSelector: @selector(registryID)] ? mtlDevice.registryID : 0; return [mtlDevice respondsToSelector: @selector(registryID)] ? mtlDevice.registryID : 0;
} }
uint64_t mvkGetLocationID(id<MTLDevice> 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. // If the supportsBCTextureCompression query is available, use it.
// Otherwise only macOS supports BC compression. // Otherwise only macOS supports BC compression.
bool mvkSupportsBCTextureCompression(id<MTLDevice> mtlDevice) { bool mvkSupportsBCTextureCompression(id<MTLDevice> mtlDevice) {