diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md index 3c726b42..6c3c5492 100755 --- a/Docs/MoltenVK_Runtime_UserGuide.md +++ b/Docs/MoltenVK_Runtime_UserGuide.md @@ -131,8 +131,13 @@ the *Metal* environment. 2. Click the **+** button, and (selecting from the list of system libraries) add `libc++.tbd`. 3. If you do not have the **Link Frameworks Automatically** (aka `CLANG_MODULES_AUTOLINK`) and **Enable Modules (C and Objective-C** (aka `CLANG_ENABLE_MODULES`) settings enabled, click the - **+** button, and (selecting from the list of system frameworks) add `Metal.framework`, - `IOSurface.framework`, and `QuartzCore.framework`. + **+** button, and (selecting from the list of system frameworks) add the following frameworks: + - `Metal.framework` + - `IOSurface.framework` + - `QuartzCore.framework` + - `IOKit.framework` (*macOS*) + - `UIKit.framework` (*iOS*) + - `Foundation.framework`. 4. When a *Metal* app is running from *Xcode*, the default ***Scheme*** settings reduce performance. To improve performance and gain the benefits of *Metal*, perform the @@ -185,8 +190,13 @@ follow these instructions: 2. Click the **+** button, and (selecting from the list of system libraries) add `libc++.tbd`. 3. If you do not have the **Link Frameworks Automatically** (aka `CLANG_MODULES_AUTOLINK`) and **Enable Modules (C and Objective-C** (aka `CLANG_ENABLE_MODULES`) settings enabled, click the - **+** button, and (selecting from the list of system frameworks) add `Metal.framework`, - `IOSurface.framework`, and `QuartzCore.framework`. + **+** button, and (selecting from the list of system frameworks) add the following frameworks: + - `Metal.framework` + - `IOSurface.framework` + - `QuartzCore.framework` + - `IOKit.framework` (*macOS*) + - `UIKit.framework` (*iOS*) + - `Foundation.framework`. 4. Arrange to install the `libMoltenVK.dylib` file in your application environment: diff --git a/External/SPIRV-Cross b/External/SPIRV-Cross index 6a0f6980..3925fe88 160000 --- a/External/SPIRV-Cross +++ b/External/SPIRV-Cross @@ -1 +1 @@ -Subproject commit 6a0f6980ef851c3973f8e723737aa764b04b18ca +Subproject commit 3925fe88e91e32747db84c2bd3caa5e1f3ec70c7 diff --git a/External/Vulkan-Hpp b/External/Vulkan-Hpp index 047961e9..82a14093 160000 --- a/External/Vulkan-Hpp +++ b/External/Vulkan-Hpp @@ -1 +1 @@ -Subproject commit 047961e987a7a42f45249c969b10d044f9396a8d +Subproject commit 82a14093cfb3f11da82d3b080ab650ce36a5ba13 diff --git a/External/Vulkan-LoaderAndValidationLayers b/External/Vulkan-LoaderAndValidationLayers index 54c67413..eb591982 160000 --- a/External/Vulkan-LoaderAndValidationLayers +++ b/External/Vulkan-LoaderAndValidationLayers @@ -1 +1 @@ -Subproject commit 54c674136a33dae33d378f734b174d7ec7ef633b +Subproject commit eb59198227debc125069ad9a008a1b17cefd564f diff --git a/MoltenVK/MoltenVK.xcodeproj/project.pbxproj b/MoltenVK/MoltenVK.xcodeproj/project.pbxproj index 6170af0e..bd2473fc 100644 --- a/MoltenVK/MoltenVK.xcodeproj/project.pbxproj +++ b/MoltenVK/MoltenVK.xcodeproj/project.pbxproj @@ -770,7 +770,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "set -e\n\nexport MVK_PROD_NAME=\"MoltenVK\"\nexport MVK_DYLIB_NAME=\"lib${MVK_PROD_NAME}.dylib\"\nexport MVK_BUILT_PROD_PATH=\"${BUILT_PRODUCTS_DIR}\"\nexport MVK_PLATFORM_SDK_DIR=\"${PLATFORM_DEVELOPER_SDK_DIR}/${PLATFORM_NAME}.sdk\"\nexport MVK_SYS_FWK_DIR=\"${MVK_PLATFORM_SDK_DIR}/System/Library/Frameworks\"\nexport MVK_USR_LIB_DIR=\"${MVK_PLATFORM_SDK_DIR}/usr/lib\"\n\nclang \\\n-dynamiclib \\\n-arch x86_64 \\\n-mmacosx-version-min=10.11 \\\n-compatibility_version 1.0.0 -current_version 1.0.0 \\\n-install_name \"@rpath/${MVK_DYLIB_NAME}\" \\\n-Wno-incompatible-sysroot \\\n-isysroot ${MVK_PLATFORM_SDK_DIR} \\\n-iframework ${MVK_SYS_FWK_DIR} \\\n-framework Metal -framework IOSurface -framework QuartzCore -framework Foundation \\\n--library-directory ${MVK_USR_LIB_DIR} \\\n-lSystem -lc++ \\\n-o \"${MVK_BUILT_PROD_PATH}/${MVK_DYLIB_NAME}\" \\\n-force_load \"${MVK_BUILT_PROD_PATH}/${MVK_PROD_NAME}.framework/${MVK_PROD_NAME}\"\n"; + shellScript = "set -e\n\nexport MVK_PROD_NAME=\"MoltenVK\"\nexport MVK_DYLIB_NAME=\"lib${MVK_PROD_NAME}.dylib\"\nexport MVK_BUILT_PROD_PATH=\"${BUILT_PRODUCTS_DIR}\"\nexport MVK_PLATFORM_SDK_DIR=\"${PLATFORM_DEVELOPER_SDK_DIR}/${PLATFORM_NAME}.sdk\"\nexport MVK_SYS_FWK_DIR=\"${MVK_PLATFORM_SDK_DIR}/System/Library/Frameworks\"\nexport MVK_USR_LIB_DIR=\"${MVK_PLATFORM_SDK_DIR}/usr/lib\"\n\nclang \\\n-dynamiclib \\\n-arch x86_64 \\\n-mmacosx-version-min=10.11 \\\n-compatibility_version 1.0.0 -current_version 1.0.0 \\\n-install_name \"@rpath/${MVK_DYLIB_NAME}\" \\\n-Wno-incompatible-sysroot \\\n-isysroot ${MVK_PLATFORM_SDK_DIR} \\\n-iframework ${MVK_SYS_FWK_DIR} \\\n-framework Metal -framework IOSurface -framework IOKit -framework QuartzCore -framework Foundation \\\n--library-directory ${MVK_USR_LIB_DIR} \\\n-lSystem -lc++ \\\n-o \"${MVK_BUILT_PROD_PATH}/${MVK_DYLIB_NAME}\" \\\n-force_load \"${MVK_BUILT_PROD_PATH}/${MVK_PROD_NAME}.framework/${MVK_PROD_NAME}\"\n"; }; A9731FAD1EDDAE39006B7298 /* Create Dynamic Library */ = { isa = PBXShellScriptBuildPhase; @@ -784,7 +784,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "set -e\n\nexport MVK_PROD_NAME=\"MoltenVK\"\nexport MVK_DYLIB_NAME=\"lib${MVK_PROD_NAME}.dylib\"\nexport MVK_BUILT_PROD_PATH=\"${BUILT_PRODUCTS_DIR}\"\nexport MVK_PLATFORM_SDK_DIR=\"${PLATFORM_DEVELOPER_SDK_DIR}/${PLATFORM_NAME}.sdk\"\nexport MVK_SYS_FWK_DIR=\"${MVK_PLATFORM_SDK_DIR}/System/Library/Frameworks\"\nexport MVK_USR_LIB_DIR=\"${MVK_PLATFORM_SDK_DIR}/usr/lib\"\n\nclang \\\n-dynamiclib \\\n-arch arm64 \\\n-mios-version-min=9.0 \\\n-compatibility_version 1.0.0 -current_version 1.0.0 \\\n-install_name \"@rpath/${MVK_DYLIB_NAME}\" \\\n-Wno-incompatible-sysroot \\\n-isysroot ${MVK_PLATFORM_SDK_DIR} \\\n-iframework ${MVK_SYS_FWK_DIR} \\\n-framework Metal -framework IOSurface -framework QuartzCore -framework Foundation \\\n--library-directory ${MVK_USR_LIB_DIR} \\\n-lSystem -lc++ \\\n-o \"${MVK_BUILT_PROD_PATH}/${MVK_DYLIB_NAME}\" \\\n-force_load \"${MVK_BUILT_PROD_PATH}/${MVK_PROD_NAME}.framework/${MVK_PROD_NAME}\"\n"; + shellScript = "set -e\n\nexport MVK_PROD_NAME=\"MoltenVK\"\nexport MVK_DYLIB_NAME=\"lib${MVK_PROD_NAME}.dylib\"\nexport MVK_BUILT_PROD_PATH=\"${BUILT_PRODUCTS_DIR}\"\nexport MVK_PLATFORM_SDK_DIR=\"${PLATFORM_DEVELOPER_SDK_DIR}/${PLATFORM_NAME}.sdk\"\nexport MVK_SYS_FWK_DIR=\"${MVK_PLATFORM_SDK_DIR}/System/Library/Frameworks\"\nexport MVK_USR_LIB_DIR=\"${MVK_PLATFORM_SDK_DIR}/usr/lib\"\n\nclang \\\n-dynamiclib \\\n-arch arm64 \\\n-mios-version-min=9.0 \\\n-compatibility_version 1.0.0 -current_version 1.0.0 \\\n-install_name \"@rpath/${MVK_DYLIB_NAME}\" \\\n-Wno-incompatible-sysroot \\\n-isysroot ${MVK_PLATFORM_SDK_DIR} \\\n-iframework ${MVK_SYS_FWK_DIR} \\\n-framework Metal -framework IOSurface -framework UIKit -framework QuartzCore -framework Foundation \\\n--library-directory ${MVK_USR_LIB_DIR} \\\n-lSystem -lc++ \\\n-o \"${MVK_BUILT_PROD_PATH}/${MVK_DYLIB_NAME}\" \\\n-force_load \"${MVK_BUILT_PROD_PATH}/${MVK_PROD_NAME}.framework/${MVK_PROD_NAME}\"\n"; }; /* End PBXShellScriptBuildPhase section */ diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index f61f6438..0587d3aa 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -288,16 +288,6 @@ VkResult MVKPhysicalDevice::getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMe #pragma mark Construction -/** Returns the device type of the specified MTLDevice. */ -static VkPhysicalDeviceType getDeviceType(id mtlDevice) { -#if MVK_IOS - return VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU; -#endif -#if MVK_MACOS - return (mtlDevice.isLowPower ? VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU : VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU); -#endif -} - /** Initializes the Metal-specific physical device features of this instance. */ void MVKPhysicalDevice::initMetalFeatures() { memset(&_metalFeatures, 0, sizeof(_metalFeatures)); // Start with everything cleared @@ -472,14 +462,10 @@ void MVKPhysicalDevice::initFeatures() { void MVKPhysicalDevice::initProperties() { memset(&_properties, 0, sizeof(_properties)); // Start with everything cleared - // TODO: determine correct values _properties.apiVersion = MVK_VULKAN_API_VERSION; _properties.driverVersion = MVK_VERSION; - _properties.vendorID = 0; - _properties.deviceID = 0; - _properties.deviceType = getDeviceType(_mtlDevice); - strlcpy(_properties.deviceName, _mtlDevice.name.UTF8String, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE); - memset(_properties.pipelineCacheUUID, 0, VK_UUID_SIZE); + + mvkPopulateGPUInfo(_properties, _mtlDevice); // Limits #if MVK_IOS @@ -865,7 +851,7 @@ void MVKPhysicalDevice::initMemoryProperties() { } void MVKPhysicalDevice::logFeatureSets() { - string fsMsg = "GPU device %s supports the following Metal Feature Sets:"; + string fsMsg = "GPU device %s (vendorID: %#06x, deviceID: %#06x, pipelineCacheUUID: %s) supports the following Metal Feature Sets:"; #if MVK_IOS if ( [_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily4_v1] ) { fsMsg += "\n\tiOS GPU Family 4 v1"; } @@ -891,7 +877,8 @@ void MVKPhysicalDevice::logFeatureSets() { if ( [_mtlDevice supportsFeatureSet: MTLFeatureSet_macOS_GPUFamily1_v1] ) { fsMsg += "\n\tOSX GPU Family 1 v1"; } #endif - MVKLogInfo(fsMsg.c_str(), _properties.deviceName); + MVKLogInfo(fsMsg.c_str(), _properties.deviceName, _properties.vendorID, _properties.deviceID, + [[[NSUUID alloc] initWithUUIDBytes: _properties.pipelineCacheUUID] autorelease].UUIDString.UTF8String); } /** Initializes the queue families supported by this instance. */ diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm index e06f3024..e0724157 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm @@ -29,13 +29,11 @@ const MVKMTLFunction MVKMTLFunctionNull = { nil, MTLSizeMake(1, 1, 1) }; #pragma mark - #pragma mark MVKShaderLibrary -uint32_t getOffsetForConstantId(const VkSpecializationInfo* pSpecInfo, uint32_t constantId) +static uint32_t getOffsetForConstantId(const VkSpecializationInfo* pSpecInfo, uint32_t constantId) { for (uint32_t specIdx = 0; specIdx < pSpecInfo->mapEntryCount; specIdx++) { const VkSpecializationMapEntry* pMapEntry = &pSpecInfo->pMapEntries[specIdx]; - if (pMapEntry->constantID == constantId) { - return pMapEntry->offset; - } + if (pMapEntry->constantID == constantId) { return pMapEntry->offset; } } return -1; diff --git a/MoltenVK/MoltenVK/Utility/MVKOSExtensions.h b/MoltenVK/MoltenVK/Utility/MVKOSExtensions.h index 6f5a2303..2cd1d0ea 100644 --- a/MoltenVK/MoltenVK/Utility/MVKOSExtensions.h +++ b/MoltenVK/MoltenVK/Utility/MVKOSExtensions.h @@ -22,6 +22,7 @@ #pragma once #include "MVKCommonEnvironment.h" +#include #import #import @@ -105,4 +106,6 @@ MVKOSVersion mvkOSVersion(void); /** Returns an approximation of how much memory, in bytes, the device can use with good performance. */ uint64_t mvkRecommendedMaxWorkingSetSize(id mtlDevice); +/** Populate the propertes with info about the GPU represented by the MTLDevice. */ +void mvkPopulateGPUInfo(VkPhysicalDeviceProperties& devProps, id mtlDevice); diff --git a/MoltenVK/MoltenVK/Utility/MVKOSExtensions.mm b/MoltenVK/MoltenVK/Utility/MVKOSExtensions.mm index 2864871a..d8558602 100644 --- a/MoltenVK/MoltenVK/Utility/MVKOSExtensions.mm +++ b/MoltenVK/MoltenVK/Utility/MVKOSExtensions.mm @@ -20,9 +20,22 @@ #include "MVKOSExtensions.h" #include "MVKFoundation.h" -#import -#import +#include +#include +#include +#include +#if MVK_MACOS +#import +#import +#import +#endif + +#if MVK_IOS +#import +#endif + +using namespace std; static const MVKOSVersion kMVKOSVersionUnknown = 0.0f; static MVKOSVersion _mvkOSVersion = kMVKOSVersionUnknown; @@ -131,4 +144,104 @@ uint64_t mvkRecommendedMaxWorkingSetSize(id mtlDevice) { return 128 * MEBI; // Conservative minimum for macOS GPU's & iOS shared memory } +// Personalize the pipelineCacheUUID by blending in the vendorID and deviceID values into the lower 8 bytes. +static void mvkBlendUUID(VkPhysicalDeviceProperties& devProps) { + uint32_t idOffset = VK_UUID_SIZE; + + idOffset -= sizeof(uint32_t); + *(uint32_t*)&devProps.pipelineCacheUUID[idOffset] ^= NSSwapHostIntToBig(devProps.deviceID); + + idOffset -= sizeof(uint32_t); + *(uint32_t*)&devProps.pipelineCacheUUID[idOffset] ^= NSSwapHostIntToBig(devProps.vendorID); +} + +#if MVK_MACOS + +static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef propertyName) { + + uint32_t value = 0; + + CFTypeRef cfProp = IORegistryEntrySearchCFProperty(entry, + kIOServicePlane, + propertyName, + kCFAllocatorDefault, + kIORegistryIterateRecursively | + kIORegistryIterateParents); + if (cfProp) { + const uint32_t* pValue = reinterpret_cast(CFDataGetBytePtr((CFDataRef)cfProp)); + if (pValue) { value = *pValue; } + CFRelease(cfProp); + } + + return value; +} + +void mvkPopulateGPUInfo(VkPhysicalDeviceProperties& devProps, id mtlDevice) { + + static const UInt32 kIntelVendorId = 0x8086; + bool isFound = false; + + bool isIntegrated = mtlDevice.isLowPower; + devProps.deviceType = isIntegrated ? VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU : VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU; + strlcpy(devProps.deviceName, mtlDevice.name.UTF8String, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE); + + // Iterate all GPU's, looking for a match. + // The match dictionary is consumed by IOServiceGetMatchingServices and does not need to be released + io_iterator_t entryIterator; + if (IOServiceGetMatchingServices(kIOMasterPortDefault, + IOServiceMatching("IOPCIDevice"), + &entryIterator) == kIOReturnSuccess) { + io_registry_entry_t entry; + while ( !isFound && (entry = IOIteratorNext(entryIterator)) ) { + if (mvkGetEntryProperty(entry, CFSTR("class-code")) == 0x30000) { // 0x30000 : DISPLAY_VGA + + // The Intel GPU will always be marked as integrated. + // Return on a match of either Intel && low power, or non-Intel and non-low-power. + uint32_t vendorID = mvkGetEntryProperty(entry, CFSTR("vendor-id")); + if ( (vendorID == kIntelVendorId) == isIntegrated) { + isFound = true; + devProps.vendorID = vendorID; + devProps.deviceID = mvkGetEntryProperty(entry, CFSTR("device-id")); + } + } + } + IOObjectRelease(entryIterator); + } + + // Create a pipelineCacheUUID by blending the UUID of the computer with the vendor and device ID's + uuid_t uuid = {}; + timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; + gethostuuid(uuid, &ts); + memcpy(devProps.pipelineCacheUUID, uuid, min(sizeof(uuid_t), (size_t)VK_UUID_SIZE)); + mvkBlendUUID(devProps); +} + +#endif //MVK_MACOS + +#if MVK_IOS + +void mvkPopulateGPUInfo(VkPhysicalDeviceProperties& devProps, id mtlDevice) { + NSUInteger coreCnt = NSProcessInfo.processInfo.processorCount; + uint32_t devID = 0xa070; + if ([mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily4_v1]) { + devID = 0xa110; + } else if ([mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily3_v1]) { + devID = coreCnt > 2 ? 0xa101 : 0xa100; + } else if ([mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily2_v1]) { + devID = coreCnt > 2 ? 0xa081 : 0xa080; + } + + devProps.vendorID = 0x0000106b; // Apple's PCI ID + devProps.deviceID = devID; + devProps.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU; + strlcpy(devProps.deviceName, mtlDevice.name.UTF8String, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE); + + // Create a pipelineCacheUUID by blending the UUID of the computer with the vendor and device ID's + uuid_t uuid = {}; + [UIDevice.currentDevice.identifierForVendor getUUIDBytes:uuid]; + memcpy(devProps.pipelineCacheUUID, uuid, min(sizeof(uuid_t), (size_t)VK_UUID_SIZE)); + mvkBlendUUID(devProps); +} +#endif //MVK_IOS + diff --git a/README.md b/README.md index a2a19d2e..73b3d7ef 100755 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ Building **MoltenVK** instructions in the [*Third-Party Components*](#third-party) section above to retrieve and install the required third-party components. ->***Note:*** At runtime, **MoltenVK** can run on *iOS 9* and *macOS 11.0* devices, +>***Note:*** At runtime, **MoltenVK** can run on *iOS 9* and *macOS 10.11* devices, >but it does reference advanced OS frameworks during building. *Xcode 9* >or above is required to build **MoltenVK**, and build and link **MoltenVK** projects.