Prefer MTLEvent for VkSemaphore, except on NVIDIA, prefer emulation.

Disable MVK_ALLOW_METAL_FENCES by default.
Disable use of MTLEvent on NVIDIA.
By default, use MTLEvent for VkSemaphore everywhere except NVIDIA.
By default, use CPU synchronization on NVIDIA.

These changes fix a large number of CTS synchronization test failures.
This commit is contained in:
Bill Hollings 2021-08-10 11:32:21 -04:00
parent 8e6731fd8e
commit 8c7db31cd7
4 changed files with 21 additions and 29 deletions

View File

@ -18,7 +18,9 @@ MoltenVK 1.1.5
Released TBD Released TBD
- Revert to prefer `MTLEvent` over `MTLFence` for `VkSemaphore`, except on NVIDIA. - Changes to how `VkSemaphore` is supported:
- Revert to prefer `MTLEvent` for `VkSemaphore`, except on NVIDIA, where emulation on CPU is preferred.
- Set default value of the `MVK_ALLOW_METAL_FENCES` environment variable to `0 (false)`,
- Vulkan timestamp query pools use Metal GPU counters when available. - Vulkan timestamp query pools use Metal GPU counters when available.
- Support resolving attachments with formats that Metal does not natively resolve. - Support resolving attachments with formats that Metal does not natively resolve.
- Fix issue where swapchain images were acquired out of order under heavy load. - Fix issue where swapchain images were acquired out of order under heavy load.

View File

@ -559,9 +559,9 @@ typedef struct {
* *
* This parameter interacts with semaphoreUseMTLEvent. If both are enabled, on GPUs other than * This parameter interacts with semaphoreUseMTLEvent. If both are enabled, on GPUs other than
* NVIDIA, semaphoreUseMTLEvent takes priority and MTLEvent will be used if it is available, * NVIDIA, semaphoreUseMTLEvent takes priority and MTLEvent will be used if it is available,
* otherwise MTLFence will be used if it is available. On NVIDIA GPUs, the opposite priority * otherwise MTLFence will be used if it is available. On NVIDIA GPUs, MTLEvent is disabled
* applies. If neither semaphoreUseMTLFence nor semaphoreUseMTLEvent are enabled, or if neither * for VkSemaphores, so CPU-based synchronization will be used unless semaphoreUseMTLFence
* MTLEvent nor MTLFence are available, CPU-based synchoronization will be used. * is enabled and MTLFence is available.
* *
* In the special case of VK_SEMAPHORE_TYPE_TIMELINE semaphores, MoltenVK will always * In the special case of VK_SEMAPHORE_TYPE_TIMELINE semaphores, MoltenVK will always
* use MTLSharedEvent if it is available on the platform, regardless of the values of * use MTLSharedEvent if it is available on the platform, regardless of the values of
@ -573,8 +573,7 @@ typedef struct {
* The initial value or this parameter is set by the * The initial value or this parameter is set by the
* MVK_ALLOW_METAL_FENCES * MVK_ALLOW_METAL_FENCES
* runtime environment variable or MoltenVK compile-time build setting. * runtime environment variable or MoltenVK compile-time build setting.
* If neither is set, this setting is enabled by default, and VkSemaphore will use MTLFence, * If neither is set, this setting is disabled by default, and VkSemaphore will not use MTLFence.
* if it is available, unless MTLEvent is available and semaphoreUseMTLEvent is enabled.
*/ */
VkBool32 semaphoreUseMTLFence; VkBool32 semaphoreUseMTLFence;
@ -583,9 +582,9 @@ typedef struct {
* *
* This parameter interacts with semaphoreUseMTLFence. If both are enabled, on GPUs other than * This parameter interacts with semaphoreUseMTLFence. If both are enabled, on GPUs other than
* NVIDIA, semaphoreUseMTLEvent takes priority and MTLEvent will be used if it is available, * NVIDIA, semaphoreUseMTLEvent takes priority and MTLEvent will be used if it is available,
* otherwise MTLFence will be used if it is available. On NVIDIA GPUs, the opposite priority * otherwise MTLFence will be used if it is available. On NVIDIA GPUs, MTLEvent is disabled
* applies. If neither semaphoreUseMTLFence nor semaphoreUseMTLEvent are enabled, or if neither * for VkSemaphores, so CPU-based synchronization will be used unless semaphoreUseMTLFence
* MTLEvent nor MTLFence are available, CPU-based synchoronization will be used. * is enabled and MTLFence is available.
* *
* In the special case of VK_SEMAPHORE_TYPE_TIMELINE semaphores, MoltenVK will always * In the special case of VK_SEMAPHORE_TYPE_TIMELINE semaphores, MoltenVK will always
* use MTLSharedEvent if it is available on the platform, regardless of the values of * use MTLSharedEvent if it is available on the platform, regardless of the values of
@ -598,7 +597,7 @@ typedef struct {
* MVK_ALLOW_METAL_EVENTS * MVK_ALLOW_METAL_EVENTS
* runtime environment variable or MoltenVK compile-time build setting. * runtime environment variable or MoltenVK compile-time build setting.
* If neither is set, this setting is enabled by default, and VkSemaphore will use MTLEvent, * If neither is set, this setting is enabled by default, and VkSemaphore will use MTLEvent,
* if it is available. * if it is available, except on NVIDIA GPUs.
*/ */
VkBool32 semaphoreUseMTLEvent; VkBool32 semaphoreUseMTLEvent;

View File

@ -3951,22 +3951,13 @@ void MVKDevice::initPhysicalDevice(MVKPhysicalDevice* physicalDevice, const VkDe
_pProperties = &_physicalDevice->_properties; _pProperties = &_physicalDevice->_properties;
_pMemoryProperties = &_physicalDevice->_memoryProperties; _pMemoryProperties = &_physicalDevice->_memoryProperties;
// Decide whether semaphores should use a MTLFence or MTLEvent if they are available. // Decide whether Vulkan semaphores should use a MTLEvent or MTLFence if they are available.
// Prefer MTLEvent over MTLFence, because MTLEvent handles sync across MTLCommandBuffers and MTLCommandQueues, // Prefer MTLEvent, because MTLEvent handles sync across MTLCommandBuffers and MTLCommandQueues.
// except on NVIDIA GPUs, which have demonstrated trouble with MTLEvents, prefer MTLFence. // However, do not allow use of MTLEvents on NVIDIA GPUs, which have demonstrated trouble with MTLEvents.
bool canUseMTLEventForSem4 = _pMetalFeatures->events && mvkConfig().semaphoreUseMTLEvent; // Since MTLFence config is disabled by default, emulation will be used on NVIDIA unless MTLFence is enabled.
bool canUseMTLEventForSem4 = _pMetalFeatures->events && mvkConfig().semaphoreUseMTLEvent && (_pProperties->vendorID != kNVVendorId);
bool canUseMTLFenceForSem4 = _pMetalFeatures->fences && mvkConfig().semaphoreUseMTLFence; bool canUseMTLFenceForSem4 = _pMetalFeatures->fences && mvkConfig().semaphoreUseMTLFence;
switch (_pProperties->vendorID) { _vkSemaphoreStyle = canUseMTLEventForSem4 ? VkSemaphoreStyleUseMTLEvent : (canUseMTLFenceForSem4 ? VkSemaphoreStyleUseMTLFence : VkSemaphoreStyleUseEmulation);
case kNVVendorId:
_vkSemaphoreStyle = canUseMTLFenceForSem4 ? VkSemaphoreStyleUseMTLFence : (canUseMTLEventForSem4 ? VkSemaphoreStyleUseMTLEvent : VkSemaphoreStyleUseEmulation);
break;
case kAppleVendorId:
case kIntelVendorId:
case kAMDVendorId:
default:
_vkSemaphoreStyle = canUseMTLEventForSem4 ? VkSemaphoreStyleUseMTLEvent : (canUseMTLFenceForSem4 ? VkSemaphoreStyleUseMTLFence : VkSemaphoreStyleUseEmulation);
break;
}
switch (_vkSemaphoreStyle) { switch (_vkSemaphoreStyle) {
case VkSemaphoreStyleUseMTLEvent: case VkSemaphoreStyleUseMTLEvent:
MVKLogInfo("Using MTLEvent for Vulkan semaphores."); MVKLogInfo("Using MTLEvent for Vulkan semaphores.");

View File

@ -233,15 +233,15 @@ void mvkSetConfig(const MVKConfiguration& mvkConfig);
/** /**
* Allow the use of MTLFence or MTLEvent for VkSemaphore synchronization behaviour. * Allow the use of MTLFence or MTLEvent for VkSemaphore synchronization behaviour.
* By default: * By default:
* - MVK_ALLOW_METAL_FENCES is enabled
* - MVK_ALLOW_METAL_EVENTS is enabled * - MVK_ALLOW_METAL_EVENTS is enabled
* - MVK_ALLOW_METAL_FENCES is disabled
* */ * */
#ifndef MVK_ALLOW_METAL_FENCES
# define MVK_ALLOW_METAL_FENCES 1
#endif
#ifndef MVK_ALLOW_METAL_EVENTS #ifndef MVK_ALLOW_METAL_EVENTS
# define MVK_ALLOW_METAL_EVENTS 1 # define MVK_ALLOW_METAL_EVENTS 1
#endif #endif
#ifndef MVK_ALLOW_METAL_FENCES
# define MVK_ALLOW_METAL_FENCES 0
#endif
/** Substitute Metal 2D textures for Vulkan 1D images. Enabled by default. */ /** Substitute Metal 2D textures for Vulkan 1D images. Enabled by default. */
#ifndef MVK_CONFIG_TEXTURE_1D_AS_2D #ifndef MVK_CONFIG_TEXTURE_1D_AS_2D