Merge pull request #2509 from billhollings/amd-disable-mtlheap

Disable MVK_CONFIG_USE_MTLHEAP for AMD devices by default.
diff --git a/Docs/MoltenVK_Configuration_Parameters.md b/Docs/MoltenVK_Configuration_Parameters.md
index 6e9deaf..11141d9 100644
--- a/Docs/MoltenVK_Configuration_Parameters.md
+++ b/Docs/MoltenVK_Configuration_Parameters.md
@@ -661,17 +661,25 @@
 ---------------------------------------
 #### MVK_CONFIG_USE_MTLHEAP
 
-##### Type: Boolean
+##### Type: Enumeration
+- `0`: Do not use `MTLHeap` for allocating resources.
+- `1`: Use `MTLHeap` for allocating resources, where safe to do so. On AMD GPUs, this is the same as `0`, 
+  due to potential challenges with `MTLHeap` usage on those platforms. On other GPUs this is the same as `2`.
+- `2`: Use `MTLHeap` for allocating resources.
+
 ##### Default: `1`
 
-Controls whether **MoltenVK** should use `MTLHeaps` for allocating textures and buffers from device memory.
-If this setting is enabled, and placement `MTLHeaps` are available on the platform, **MoltenVK** will allocate a
-placement `MTLHeap` for each `VkDeviceMemory` instance, and allocate textures and buffers from that placement heap.
-If this parameter is disabled, **MoltenVK** will allocate textures and buffers from general device memory.
+Controls whether **MoltenVK** should use `MTLHeap` for allocating textures and buffers from device memory.
+If this setting is active, **MoltenVK** will allocate a placement `MTLHeap` for each `VkDeviceMemory` instance, 
+and allocate textures and buffers from that placement heap. If this parameter is not active, **MoltenVK** will 
+allocate textures and buffers from general device memory.
 
-Vulkan extension `VK_EXT_image_2d_view_of_3d` requires this parameter to be enabled, 
+Vulkan extension `VK_EXT_image_2d_view_of_3d` requires this parameter to be active, 
 to allow aliasing of texture memory between the 3D image and the 2D view.
 
+To force `MTLHeap` to be used on AMD GPUs, set this parameter to `2`. 
+To disable the use of `MTLHeap` on any GPU, set this parameter to `0`.
+
 
 ---------------------------------------
 #### MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE
diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md
index 84b279a..6b6d0cd 100644
--- a/Docs/MoltenVK_Runtime_UserGuide.md
+++ b/Docs/MoltenVK_Runtime_UserGuide.md
@@ -253,7 +253,7 @@
 - `VK_KHR_get_surface_capabilities2`
 - `VK_KHR_imageless_framebuffer`
 - `VK_EXT_image_2d_view_of_3d`
-  - *Requires MVK_CONFIG_USE_MTLHEAP to be enabled.*
+  - *Requires `MVK_CONFIG_USE_MTLHEAP` to be active.*
 - `VK_KHR_image_format_list`
 - `VK_KHR_incremental_present`
 - `VK_KHR_index_type_uint8`
diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md
index caf333c..0ecd215 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -38,7 +38,8 @@
 	- `VK_EXT_pipeline_robustness`
 	- `VK_EXT_tooling_info`
 - Add support for `B5G6R5_UNORM_PACK16` `B5G5R5A1_UNORM_PACK16`, and `B8G8R8A8` formats using swizzle.
-- Enable `MVK_CONFIG_USE_MTLHEAP` by default to support `VK_EXT_image_2d_view_of_3d`.
+- Convert `MVK_CONFIG_USE_MTLHEAP` to enumeration, and set active by default to support 
+  `VK_EXT_image_2d_view_of_3d`, except on _AMD_ devices.
 - Remove `glslang` as dependency library.
 - `MoltenVKShaderConverter` no longer accepts GLSL` shaders as input.
 - Fixes to managing descriptor set allocation in a Metal argument buffer.
diff --git a/MoltenVK/MoltenVK/API/mvk_private_api.h b/MoltenVK/MoltenVK/API/mvk_private_api.h
index cb3fbc6..29e7ae6 100644
--- a/MoltenVK/MoltenVK/API/mvk_private_api.h
+++ b/MoltenVK/MoltenVK/API/mvk_private_api.h
@@ -185,6 +185,14 @@
 	MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_MAX_ENUM                   = 0x7FFFFFFF,
 } MVKConfigActivityPerformanceLoggingStyle;
 
+/** Identifies when MTLHeap is used to allocate buffer and image resources. */
+typedef enum MVKConfigUseMTLHeap {
+	MVK_CONFIG_USE_MTLHEAP_NEVER      = 0,  /**< Do not use MTLHeap for allocating resources. */
+	MVK_CONFIG_USE_MTLHEAP_WHERE_SAFE = 1,  /**< Use MTLHeap for allocating resources, where safe to do so. On AMD GPUs, this is the same as MVK_CONFIG_USE_MTLHEAP_NEVER, due to potential challenges with MTLHeap usage on those platforms. On other GPUs this is the same as MVK_CONFIG_USE_MTLHEAP_ALWAYS. */
+	MVK_CONFIG_USE_MTLHEAP_ALWAYS     = 2,  /**< Use MTLHeap for allocating resources. */
+	MVK_CONFIG_USE_MTLHEAP_MAX_ENUM   = 0x7FFFFFFF
+} MVKConfigUseMTLHeap;
+
 /**
  * MoltenVK configuration. You can retrieve a copy of this structure using the vkGetMoltenVKConfigurationMVK() function.
  *
@@ -227,7 +235,7 @@
 	VkBool32 texture1DAs2D;                                                    /**< MVK_CONFIG_TEXTURE_1D_AS_2D */
 	VkBool32 preallocateDescriptors;                                           /**< Obsolete, deprecated, and ignored. */
 	VkBool32 useCommandPooling;                                                /**< MVK_CONFIG_USE_COMMAND_POOLING */
-	VkBool32 useMTLHeap;                                                       /**< MVK_CONFIG_USE_MTLHEAP */
+	MVKConfigUseMTLHeap useMTLHeap;                                            /**< MVK_CONFIG_USE_MTLHEAP */
 	MVKConfigActivityPerformanceLoggingStyle activityPerformanceLoggingStyle;  /**< MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE */
 	uint32_t apiVersionToAdvertise;                                            /**< MVK_CONFIG_API_VERSION_TO_ADVERTISE */
 	MVKConfigAdvertiseExtensions advertiseExtensions;                          /**< MVK_CONFIG_ADVERTISE_EXTENSIONS */
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index 24d55ab..84de5fc 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -513,7 +513,7 @@
 				portabilityFeatures->imageViewFormatReinterpretation = true;
 				portabilityFeatures->imageViewFormatSwizzle = (_metalFeatures.nativeTextureSwizzle ||
 															   getMVKConfig().fullImageViewSwizzle);
-				portabilityFeatures->imageView2DOn3DImage = getMVKConfig().useMTLHeap;
+				portabilityFeatures->imageView2DOn3DImage = _metalFeatures.placementHeaps;
 				portabilityFeatures->multisampleArrayImage = _metalFeatures.multisampleArrayTextures;
 				portabilityFeatures->mutableComparisonSamplers = _metalFeatures.depthSampleCompare;
 				portabilityFeatures->pointPolygons = false;
@@ -611,11 +611,9 @@
 				break;
 			}
 			case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT: {
-				if (getMVKConfig().useMTLHeap) {
-					auto* extFeatures = (VkPhysicalDeviceImage2DViewOf3DFeaturesEXT*)next;
-					extFeatures->image2DViewOf3D = true;
-					extFeatures->sampler2DViewOf3D = true;
-				}
+				auto* extFeatures = (VkPhysicalDeviceImage2DViewOf3DFeaturesEXT*)next;
+				extFeatures->image2DViewOf3D = _metalFeatures.placementHeaps;
+				extFeatures->sampler2DViewOf3D = _metalFeatures.placementHeaps;
 				break;
 			}
 			case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT: {
@@ -2244,6 +2242,12 @@
 			break;
 	}
 
+	// AMD support for MTLHeap is buggy.
+	auto cfgUseMTLHeap = getMVKConfig().useMTLHeap;
+	bool useMTLHeap = (_properties.vendorID == kAMDVendorId
+					   ? cfgUseMTLHeap == MVK_CONFIG_USE_MTLHEAP_ALWAYS
+					   : cfgUseMTLHeap != MVK_CONFIG_USE_MTLHEAP_NEVER);
+
 #if MVK_TVOS
 	_metalFeatures.mslVersionEnum = MTLLanguageVersion2_0;
     _metalFeatures.mtlBufferAlignment = 64;
@@ -2282,7 +2286,7 @@
 
 	if ( mvkOSVersionIsAtLeast(13.0) ) {
 		_metalFeatures.mslVersionEnum = MTLLanguageVersion2_2;
-		_metalFeatures.placementHeaps = getMVKConfig().useMTLHeap;
+		_metalFeatures.placementHeaps = useMTLHeap;
 		_metalFeatures.nativeTextureSwizzle = true;
 		if (supportsMTLGPUFamily(Apple3)) {
 			_metalFeatures.native3DCompressedTextures = true;
@@ -2384,7 +2388,7 @@
 
 	if ( mvkOSVersionIsAtLeast(13.0) ) {
 		_metalFeatures.mslVersionEnum = MTLLanguageVersion2_2;
-		_metalFeatures.placementHeaps = getMVKConfig().useMTLHeap;
+		_metalFeatures.placementHeaps = useMTLHeap;
 		_metalFeatures.nativeTextureSwizzle = true;
 
 		if (supportsMTLGPUFamily(Apple3)) {
@@ -2495,7 +2499,7 @@
         }
 		if (supportsMTLGPUFamily(Mac2)) {
 			_metalFeatures.nativeTextureSwizzle = true;
-			_metalFeatures.placementHeaps = getMVKConfig().useMTLHeap;
+			_metalFeatures.placementHeaps = useMTLHeap;
 			_metalFeatures.renderWithoutAttachments = true;
 		}
 	}
@@ -3623,7 +3627,7 @@
 	if (!_metalFeatures.arrayOfTextures || !_metalFeatures.arrayOfSamplers) {
 		pWritableExtns->vk_EXT_descriptor_indexing.enabled = false;
 	}
-	if (!getMVKConfig().useMTLHeap) {
+	if (!_metalFeatures.placementHeaps) {
 		pWritableExtns->vk_EXT_image_2d_view_of_3d.enabled = false;
 	}
     
diff --git a/MoltenVK/MoltenVK/Utility/MVKConfigMembers.def b/MoltenVK/MoltenVK/Utility/MVKConfigMembers.def
index bd9c49c..b8ff581 100644
--- a/MoltenVK/MoltenVK/Utility/MVKConfigMembers.def
+++ b/MoltenVK/MoltenVK/Utility/MVKConfigMembers.def
@@ -74,7 +74,7 @@
 MVK_CONFIG_MEMBER(texture1DAs2D,                          VkBool32,                                 TEXTURE_1D_AS_2D)
 MVK_CONFIG_MEMBER(preallocateDescriptors,                 VkBool32,                                 PREALLOCATE_DESCRIPTORS)			// Deprecated legacy
 MVK_CONFIG_MEMBER(useCommandPooling,                      VkBool32,                                 USE_COMMAND_POOLING)
-MVK_CONFIG_MEMBER(useMTLHeap,                             VkBool32,                                 USE_MTLHEAP)
+MVK_CONFIG_MEMBER(useMTLHeap,                             MVKConfigUseMTLHeap,                      USE_MTLHEAP)
 MVK_CONFIG_MEMBER(apiVersionToAdvertise,                  uint32_t,                                 API_VERSION_TO_ADVERTISE)
 MVK_CONFIG_MEMBER(advertiseExtensions,                    uint32_t,                                 ADVERTISE_EXTENSIONS)
 MVK_CONFIG_MEMBER(resumeLostDevice,                       VkBool32,                                 RESUME_LOST_DEVICE)
diff --git a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h
index fc04884..ab486f8 100644
--- a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h
+++ b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h
@@ -311,9 +311,12 @@
 #  	define MVK_CONFIG_USE_COMMAND_POOLING    1
 #endif
 
-/** Use MTLHeaps where possible when allocating MTLBuffers and MTLTextures. Enabled by default. */
+/**
+ * Use MTLHeap when allocating MTLBuffers and MTLTextures.
+ * Enabled by default where safe to use MTLHeap on the platform.
+ */
 #ifndef MVK_CONFIG_USE_MTLHEAP
-#  	define MVK_CONFIG_USE_MTLHEAP    1
+#  	define MVK_CONFIG_USE_MTLHEAP    MVK_CONFIG_USE_MTLHEAP_WHERE_SAFE
 #endif
 
 /** The Vulkan API version to advertise. Defaults to MVK_VULKAN_API_VERSION. */