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).
This commit is contained in:
Bill Hollings 2023-06-15 17:24:50 -04:00
parent 4a9bf78e03
commit 425505da47
2 changed files with 33 additions and 43 deletions

View File

@ -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<MTLDevice> getMTLDevice() { return _mtlDevice; }
/*** Replaces the underlying Metal device .*/
inline void replaceMTLDevice(id<MTLDevice> mtlDevice) {
if (mtlDevice != _mtlDevice) {
[_mtlDevice release];
_mtlDevice = [mtlDevice retain];
}
}
id<MTLDevice> 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<MTLDevice> getMTLDevice() { return _physicalDevice->getMTLDevice(); }
id<MTLDevice> 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.

View File

@ -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> mtlDevice = _physicalDevice->getMTLDevice();
if (mvkConfig().switchSystemGPU && !(mtlDevice.isLowPower || mtlDevice.isHeadless) ) {
id<MTLDevice> 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.