From 425505da47d2d999a1697dfc4011570113181ebc Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Thu, 15 Jun 2023 17:24:50 -0400 Subject: [PATCH] Don't call MTLCreateSystemDefaultDevice() on every swapchain creation. - When forcing the window system to use the same high-power GPU as the app, move the call to MTLCreateSystemDefaultDevice() to MVKDevice constructor, instead of MVKDevice::createSwapchain(), and test whether the VK_KHR_swapchain extension is enabled to determine the need to swap GPUs. - After calling MTLCreateSystemDefaultDevice() the GPU will already be the same high-power GPU, so remove attempting to replace the MTLDevice. - Remove MVKPhysicalDevice::replaceMTLDevice() as no longer used. - Remove many unnecessary inline declarations in MVKDevice.h (unrelated). --- MoltenVK/MoltenVK/GPUObjects/MVKDevice.h | 50 ++++++++++------------- MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 26 ++++++------ 2 files changed, 33 insertions(+), 43 deletions(-) diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h index 9fa47494..e14320bd 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h @@ -138,7 +138,7 @@ public: void getProperties(VkPhysicalDeviceProperties2* properties); /** Returns the name of this device. */ - inline const char* getName() { return _properties.deviceName; } + const char* getName() { return _properties.deviceName; } /** Populates the specified structure with the format properties of this device. */ void getFormatProperties(VkFormat format, VkFormatProperties* pFormatProperties); @@ -285,7 +285,7 @@ public: #pragma mark Memory models /** Returns a pointer to the memory characteristics of this device. */ - inline const VkPhysicalDeviceMemoryProperties* getMemoryProperties() { return &_memoryProperties; } + const VkPhysicalDeviceMemoryProperties* getMemoryProperties() { return &_memoryProperties; } /** Populates the specified memory properties with the memory characteristics of this device. */ VkResult getMemoryProperties(VkPhysicalDeviceMemoryProperties* pMemoryProperties); @@ -297,31 +297,31 @@ public: * Returns a bit mask of all memory type indices. * Each bit [0..31] in the returned bit mask indicates a distinct memory type. */ - inline uint32_t getAllMemoryTypes() { return _allMemoryTypes; } + uint32_t getAllMemoryTypes() { return _allMemoryTypes; } /** * Returns a bit mask of all memory type indices that allow host visibility to the memory. * Each bit [0..31] in the returned bit mask indicates a distinct memory type. */ - inline uint32_t getHostVisibleMemoryTypes() { return _hostVisibleMemoryTypes; } + uint32_t getHostVisibleMemoryTypes() { return _hostVisibleMemoryTypes; } /** * Returns a bit mask of all memory type indices that are coherent between host and device. * Each bit [0..31] in the returned bit mask indicates a distinct memory type. */ - inline uint32_t getHostCoherentMemoryTypes() { return _hostCoherentMemoryTypes; } + uint32_t getHostCoherentMemoryTypes() { return _hostCoherentMemoryTypes; } /** * Returns a bit mask of all memory type indices that do NOT allow host visibility to the memory. * Each bit [0..31] in the returned bit mask indicates a distinct memory type. */ - inline uint32_t getPrivateMemoryTypes() { return _privateMemoryTypes; } + uint32_t getPrivateMemoryTypes() { return _privateMemoryTypes; } /** * Returns a bit mask of all memory type indices that are lazily allocated. * Each bit [0..31] in the returned bit mask indicates a distinct memory type. */ - inline uint32_t getLazilyAllocatedMemoryTypes() { return _lazilyAllocatedMemoryTypes; } + uint32_t getLazilyAllocatedMemoryTypes() { return _lazilyAllocatedMemoryTypes; } /** Returns whether this is a unified memory device. */ bool getHasUnifiedMemory(); @@ -336,21 +336,13 @@ public: #pragma mark Metal /** Populates the specified structure with the Metal-specific features of this device. */ - inline const MVKPhysicalDeviceMetalFeatures* getMetalFeatures() { return &_metalFeatures; } + const MVKPhysicalDeviceMetalFeatures* getMetalFeatures() { return &_metalFeatures; } /** Returns whether or not vertex instancing can be used to implement multiview. */ - inline bool canUseInstancingForMultiview() { return _metalFeatures.layeredRendering && _metalFeatures.deferredStoreActions; } + bool canUseInstancingForMultiview() { return _metalFeatures.layeredRendering && _metalFeatures.deferredStoreActions; } /** Returns the underlying Metal device. */ - inline id getMTLDevice() { return _mtlDevice; } - - /*** Replaces the underlying Metal device .*/ - inline void replaceMTLDevice(id mtlDevice) { - if (mtlDevice != _mtlDevice) { - [_mtlDevice release]; - _mtlDevice = [mtlDevice retain]; - } - } + id getMTLDevice() { return _mtlDevice; } /** Returns whether the MSL version is supported on this device. */ bool mslVersionIsAtLeast(MTLLanguageVersion minVer) { return _metalFeatures.mslVersionEnum >= minVer; } @@ -387,7 +379,7 @@ public: * Returns a reference to this object suitable for use as a Vulkan API handle. * This is the compliment of the getMVKPhysicalDevice() method. */ - inline VkPhysicalDevice getVkPhysicalDevice() { return (VkPhysicalDevice)getVkHandle(); } + VkPhysicalDevice getVkPhysicalDevice() { return (VkPhysicalDevice)getVkHandle(); } /** * Retrieves the MVKPhysicalDevice instance referenced by the VkPhysicalDevice handle. @@ -475,16 +467,16 @@ public: MVKInstance* getInstance() override { return _physicalDevice->getInstance(); } /** Returns the physical device underlying this logical device. */ - inline MVKPhysicalDevice* getPhysicalDevice() { return _physicalDevice; } + MVKPhysicalDevice* getPhysicalDevice() { return _physicalDevice; } /** Returns info about the pixel format supported by the physical device. */ - inline MVKPixelFormats* getPixelFormats() { return &_physicalDevice->_pixelFormats; } + MVKPixelFormats* getPixelFormats() { return &_physicalDevice->_pixelFormats; } /** Returns the name of this device. */ - inline const char* getName() { return _pProperties->deviceName; } + const char* getName() { return _pProperties->deviceName; } /** Returns the common resource factory for creating command resources. */ - inline MVKCommandResourceFactory* getCommandResourceFactory() { return _commandResourceFactory; } + MVKCommandResourceFactory* getCommandResourceFactory() { return _commandResourceFactory; } /** Returns the function pointer corresponding to the specified named entry point. */ PFN_vkVoidFunction getProcAddr(const char* pName); @@ -699,7 +691,7 @@ public: * number of nanoseconds between the two calls. The convenience function mvkGetElapsedMilliseconds() * can be used to perform this calculation. */ - inline uint64_t getPerformanceTimestamp() { return _isPerformanceTracking ? mvkGetTimestamp() : 0; } + uint64_t getPerformanceTimestamp() { return _isPerformanceTracking ? mvkGetTimestamp() : 0; } /** * If performance is being tracked, adds the performance for an activity with a duration @@ -707,8 +699,8 @@ public: * * If endTime is zero or not supplied, the current time is used. */ - inline void addActivityPerformance(MVKPerformanceTracker& activityTracker, - uint64_t startTime, uint64_t endTime = 0) { + void addActivityPerformance(MVKPerformanceTracker& activityTracker, + uint64_t startTime, uint64_t endTime = 0) { if (_isPerformanceTracking) { updateActivityPerformance(activityTracker, startTime, endTime); @@ -742,7 +734,7 @@ public: #pragma mark Metal /** Returns the underlying Metal device. */ - inline id getMTLDevice() { return _physicalDevice->getMTLDevice(); } + id getMTLDevice() { return _physicalDevice->getMTLDevice(); } /** Returns whether this device is using Metal argument buffers. */ bool isUsingMetalArgumentBuffers() { return _isUsingMetalArgumentBuffers; }; @@ -818,7 +810,7 @@ public: void stopAutoGPUCapture(MVKConfigAutoGPUCaptureScope autoGPUCaptureScope); /** Returns whether this instance is currently automatically capturing a GPU trace. */ - inline bool isCurrentlyAutoGPUCapturing() { return _isCurrentlyAutoGPUCapturing; } + bool isCurrentlyAutoGPUCapturing() { return _isCurrentlyAutoGPUCapturing; } /** Returns the Metal objects underpinning the Vulkan objects indicated in the pNext chain of pMetalObjectsInfo. */ void getMetalObjects(VkExportMetalObjectsInfoEXT* pMetalObjectsInfo); @@ -866,7 +858,7 @@ public: * Returns a reference to this object suitable for use as a Vulkan API handle. * This is the compliment of the getMVKDevice() method. */ - inline VkDevice getVkDevice() { return (VkDevice)getVkHandle(); } + VkDevice getVkDevice() { return (VkDevice)getVkHandle(); } /** * Retrieves the MVKDevice instance referenced by the VkDevice handle. diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 4decedf2..93adca53 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -3629,20 +3629,6 @@ void MVKDevice::destroyImageView(MVKImageView* mvkImgView, MVKSwapchain* MVKDevice::createSwapchain(const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator) { -#if MVK_MACOS - // If we have selected a high-power GPU and want to force the window system - // to use it, force the window system to use a high-power GPU by calling the - // MTLCreateSystemDefaultDevice function, and if that GPU is the same as the - // selected GPU, update the MTLDevice instance used by the MVKPhysicalDevice. - id mtlDevice = _physicalDevice->getMTLDevice(); - if (mvkConfig().switchSystemGPU && !(mtlDevice.isLowPower || mtlDevice.isHeadless) ) { - id sysMTLDevice = MTLCreateSystemDefaultDevice(); - if (mvkGetRegistryID(sysMTLDevice) == mvkGetRegistryID(mtlDevice)) { - _physicalDevice->replaceMTLDevice(sysMTLDevice); - } - } -#endif - return new MVKSwapchain(this, pCreateInfo); } @@ -4488,6 +4474,18 @@ MVKDevice::MVKDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo initQueues(pCreateInfo); reservePrivateData(pCreateInfo); +#if MVK_MACOS + // After enableExtensions + // If the VK_KHR_swapchain extension is enabled, we expect to render to the screen. + // In a multi-GPU system, if we are using the high-power GPU and want the window system + // to also use that GPU to avoid copying content between GPUs, force the window system + // to use the high-power GPU by calling the MTLCreateSystemDefaultDevice() function. + if (_enabledExtensions.vk_KHR_swapchain.enabled && mvkConfig().switchSystemGPU && + !(_physicalDevice->_mtlDevice.isLowPower || _physicalDevice->_mtlDevice.isHeadless) ) { + MTLCreateSystemDefaultDevice(); + } +#endif + // After enableExtensions && enableFeatures // Use Metal arg buffs if available, and either config wants them always, // or config wants them with descriptor indexing and descriptor indexing has been enabled.