Merge pull request #939 from cdavis5e/macos-rgb10a2-surface

MVKDevice: Advertise VK_FORMAT_A2B10G10R10_UNORM_PACK32 as a surface format.
diff --git a/MoltenVK/MoltenVK/API/mvk_datatypes.h b/MoltenVK/MoltenVK/API/mvk_datatypes.h
index 4ecd650..b5579e5 100644
--- a/MoltenVK/MoltenVK/API/mvk_datatypes.h
+++ b/MoltenVK/MoltenVK/API/mvk_datatypes.h
@@ -443,7 +443,7 @@
 #define MVK_VK_MEMORY_TYPE_METAL_PRIVATE	(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
 
 /** Macro indicating the Vulkan memory type bits corresponding to Metal shared memory (host visible and coherent). */
-#define MVK_VK_MEMORY_TYPE_METAL_SHARED		(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
+#define MVK_VK_MEMORY_TYPE_METAL_SHARED		(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
 
 /** Macro indicating the Vulkan memory type bits corresponding to Metal managed memory (host visible and non-coherent). */
 #define MVK_VK_MEMORY_TYPE_METAL_MANAGED	(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm
index 91054c6..72804cd 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm
@@ -52,7 +52,7 @@
 		pMemoryRequirements->alignment = _byteAlignment;
 	}
 	pMemoryRequirements->memoryTypeBits = _device->getPhysicalDevice()->getAllMemoryTypes();
-#if MVK_IOS
+#if MVK_IOS_OR_TVOS
 	// Memoryless storage is not allowed for buffers
 	mvkDisableFlags(pMemoryRequirements->memoryTypeBits, _device->getPhysicalDevice()->getLazilyAllocatedMemoryTypes());
 #endif
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index 192560c..947b7d4 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -41,7 +41,7 @@
 using namespace std;
 
 
-#if MVK_IOS
+#if MVK_IOS_OR_TVOS
 #	include <UIKit/UIKit.h>
 #	define MVKViewClass		UIView
 #endif
@@ -425,7 +425,7 @@
 			}
 			// Metal does not allow compressed or depth/stencil formats on 3D textures
 			if (mvkFmt == kMVKFormatDepthStencil
-#if MVK_IOS
+#if MVK_IOS_OR_TVOS
 				|| mvkFmt == kMVKFormatCompressed
 #endif
 				) {
@@ -959,6 +959,7 @@
 	_metalFeatures.mtlCopyBufferAlignment = 1;
     _metalFeatures.texelBuffers = true;
 	_metalFeatures.maxTextureDimension = (8 * KIBI);
+    _metalFeatures.dynamicMTLBufferSize = (4 * KIBI);
 
     if (supportsMTLFeatureSet(tvOS_GPUFamily1_v2)) {
 		_metalFeatures.mslVersionEnum = MTLLanguageVersion1_2;
@@ -973,6 +974,8 @@
 
 	if (supportsMTLFeatureSet(tvOS_GPUFamily1_v4)) {
 		_metalFeatures.mslVersionEnum = MTLLanguageVersion2_1;
+		_metalFeatures.events = true;
+		_metalFeatures.textureBuffers = true;
 	}
 
 	if (supportsMTLFeatureSet(tvOS_GPUFamily2_v1)) {
@@ -1421,7 +1424,7 @@
 #if MVK_MACOS
 	_properties.limits.maxUniformBufferRange = (64 * KIBI);
 #endif
-#if MVK_IOS
+#if MVK_IOS_OR_TVOS
 	_properties.limits.maxUniformBufferRange = (uint32_t)_metalFeatures.maxMTLBufferSize;
 #endif
 	_properties.limits.maxStorageBufferRange = (uint32_t)_metalFeatures.maxMTLBufferSize;
@@ -1514,6 +1517,18 @@
         _texelBuffAlignProperties.uniformTexelBufferOffsetSingleTexelAlignment = VK_FALSE;
     }
 
+#if MVK_TVOS
+    _properties.limits.maxFragmentInputComponents = 60;
+
+    if (supportsMTLFeatureSet(tvOS_GPUFamily2_v1)) {
+        _properties.limits.optimalBufferCopyOffsetAlignment = 16;
+    } else {
+        _properties.limits.optimalBufferCopyOffsetAlignment = 64;
+    }
+
+    _properties.limits.maxTessellationGenerationLevel = 16;
+    _properties.limits.maxTessellationPatchSize = 32;
+#endif
 #if MVK_IOS
     _properties.limits.maxFragmentInputComponents = 60;
 
@@ -1590,6 +1605,13 @@
 	if ( [_mtlDevice respondsToSelector: @selector(maxThreadgroupMemoryLength)] ) {
 		_properties.limits.maxComputeSharedMemorySize = (uint32_t)_mtlDevice.maxThreadgroupMemoryLength;
 	} else {
+#if MVK_TVOS
+		if (supportsMTLFeatureSet(tvOS_GPUFamily2_v1)) {
+			_properties.limits.maxComputeSharedMemorySize = (16 * KIBI);
+		} else {
+			_properties.limits.maxComputeSharedMemorySize = ((16 * KIBI) - 32);
+		}
+#endif
 #if MVK_IOS
 		if (supportsMTLFeatureSet(iOS_GPUFamily4_v1)) {
 			_properties.limits.maxComputeSharedMemorySize = (32 * KIBI);
@@ -1917,7 +1939,7 @@
 	// On newer OS's, combine highest Metal version with highest GPU family
 	// (Mac & Apple GPU lists should be mutex on platform)
 	uint32_t mtlVer = 0;
-#if MVK_IOS
+#if MVK_IOS_OR_TVOS
 	if (mvkOSVersionIsAtLeast(13.0)) { mtlVer = 0x30000; }
 #endif
 #if MVK_MACOS
@@ -2075,6 +2097,13 @@
 		typeIdx++;
 	}
 #endif
+#if MVK_TVOS
+	if (supportsMTLFeatureSet(tvOS_GPUFamily1_v2)) {
+		memlessBit = 1 << typeIdx;
+		setMemoryType(typeIdx, mainHeapIdx, MVK_VK_MEMORY_TYPE_METAL_MEMORYLESS);
+		typeIdx++;
+	}
+#endif
 
 	_memoryProperties.memoryTypeCount = typeIdx;
 
@@ -2111,7 +2140,7 @@
 		return _mtlDevice.recommendedMaxWorkingSetSize;
 	}
 #endif
-#if MVK_IOS
+#if MVK_IOS_OR_TVOS
 	// GPU and CPU use shared memory. Estimate the current free memory in the system.
 	uint64_t freeMem = mvkGetAvailableMemorySize();
 	if (freeMem) { return freeMem; }
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index 0f3523b..6efd58f 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -583,7 +583,7 @@
         mvkDisableFlags(pMemoryRequirements->memoryTypeBits, _device->getPhysicalDevice()->getHostCoherentMemoryTypes());
     }
 #endif
-#if MVK_IOS
+#if MVK_IOS_OR_TVOS
     // Only transient attachments may use memoryless storage
     if (!mvkAreAllFlagsEnabled(_usage, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) ) {
         mvkDisableFlags(pMemoryRequirements->memoryTypeBits, _device->getPhysicalDevice()->getLazilyAllocatedMemoryTypes());