MVKImage: Handle VK_IMAGE_CREATE_EXTENDED_USAGE_BIT.

If this bit is set, add `MTLTextureUsage` bits for features supported by
all possible view formats, not just the image format. Happily, Metal's
API validator layer is OK with this.

This is needed for the mutable format tests, which use this bit with a
format that doesn't support writing, then casts the image to a format
which does.
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
index a4eae12..b88450f 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
@@ -366,6 +366,7 @@
 	bool _isLinear;
 	bool _is3DCompressed;
 	bool _isAliasable;
+	bool _hasExtendedUsage;
 };
 
 
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index a6c5635..58cbfeb 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -123,7 +123,7 @@
     mtlTexDesc.mipmapLevelCount = _image->_mipLevels;
     mtlTexDesc.sampleCount = mvkSampleCountFromVkSampleCountFlagBits(_image->_samples);
     mtlTexDesc.arrayLength = _image->_arrayLayers;
-    mtlTexDesc.usageMVK = _image->getPixelFormats()->getMTLTextureUsage(_image->_usage, mtlPixFmt, minUsage, _image->_isLinear);
+    mtlTexDesc.usageMVK = _image->getPixelFormats()->getMTLTextureUsage(_image->_usage, mtlPixFmt, minUsage, _image->_isLinear, _image->_hasExtendedUsage);
     mtlTexDesc.storageModeMVK = _image->getMTLStorageMode();
     mtlTexDesc.cpuCacheMode = _image->getMTLCPUCacheMode();
 
@@ -802,6 +802,7 @@
 	MVKPixelFormats* pixFmts = getPixelFormats();
     _vkFormat = pCreateInfo->format;
 	_usage = pCreateInfo->usage;
+	_hasExtendedUsage = mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_IMAGE_CREATE_EXTENDED_USAGE_BIT);
 
 	_is3DCompressed = (getImageType() == VK_IMAGE_TYPE_3D) && (pixFmts->getFormatType(pCreateInfo->format) == kMVKFormatCompressed) && !_device->_pMetalFeatures->native3DCompressedTextures;
 	_isDepthStencilAttachment = (mvkAreAllFlagsEnabled(pCreateInfo->usage, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ||
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h
index 1df4621..e87063e 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h
@@ -77,6 +77,61 @@
 	kMVKMTLFmtCapsMultiPlanar = kMVKMTLFmtCapsChromaSubsampling,
 } MVKMTLFmtCaps;
 
+inline MVKMTLFmtCaps operator|(MVKMTLFmtCaps leftCaps, MVKMTLFmtCaps rightCaps) {
+	return static_cast<MVKMTLFmtCaps>(static_cast<uint32_t>(leftCaps) | rightCaps);
+}
+
+inline MVKMTLFmtCaps& operator|=(MVKMTLFmtCaps& leftCaps, MVKMTLFmtCaps rightCaps) {
+	return (leftCaps = leftCaps | rightCaps);
+}
+
+
+#pragma mark -
+#pragma mark Metal view classes
+
+enum class MVKMTLViewClass : uint8_t {
+	None,
+	Color8,
+	Color16,
+	Color32,
+	Color64,
+	Color128,
+	PVRTC_RGB_2BPP,
+	PVRTC_RGB_4BPP,
+	PVRTC_RGBA_2BPP,
+	PVRTC_RGBA_4BPP,
+	EAC_R11,
+	EAC_RG11,
+	EAC_RGBA8,
+	ETC2_RGB8,
+	ETC2_RGB8A1,
+	ASTC_4x4,
+	ASTC_5x4,
+	ASTC_5x5,
+	ASTC_6x5,
+	ASTC_6x6,
+	ASTC_8x5,
+	ASTC_8x6,
+	ASTC_8x8,
+	ASTC_10x5,
+	ASTC_10x6,
+	ASTC_10x8,
+	ASTC_10x10,
+	ASTC_12x10,
+	ASTC_12x12,
+	BC1_RGBA,
+	BC2_RGBA,
+	BC3_RGBA,
+	BC4_R,
+	BC5_RG,
+	BC6H_RGB,
+	BC7_RGBA,
+	Depth24_Stencil8,
+	Depth32_Stencil8,
+	BGRA10_XR,
+	BGR10_XR
+};
+
 
 #pragma mark -
 #pragma mark Format descriptors
@@ -114,6 +169,7 @@
 	};
 	VkFormat vkFormat;
 	MVKMTLFmtCaps mtlFmtCaps;
+	MVKMTLViewClass mtlViewClass;
 	const char* name;
 
 	inline bool isSupported() const { return (mtlPixelFormat != MTLPixelFormatInvalid) && (mtlFmtCaps != kMVKMTLFmtCapsNone); };
@@ -254,10 +310,13 @@
 	VkFormatProperties& getVkFormatProperties(VkFormat vkFormat);
 
 	/** Returns the Metal format capabilities supported by the specified Vulkan format, without substitution. */
-	MVKMTLFmtCaps getCapabilities(VkFormat vkFormat);
+	MVKMTLFmtCaps getCapabilities(VkFormat vkFormat, bool isExtended = false);
 
 	/** Returns the Metal format capabilities supported by the specified Metal format. */
-	MVKMTLFmtCaps getCapabilities(MTLPixelFormat mtlFormat);
+	MVKMTLFmtCaps getCapabilities(MTLPixelFormat mtlFormat, bool isExtended = false);
+
+	/** Returns the Metal view class of the specified Metal format. */
+	MVKMTLViewClass getViewClass(MTLPixelFormat mtlFormat);
 
 	/** Returns the name of the specified Vulkan format. */
 	const char* getName(VkFormat vkFormat);
@@ -283,12 +342,15 @@
 	/**
 	 * Returns the Metal texture usage from the Vulkan image usage and Metal format, ensuring that at least the
 	 * usages in minUsage are included, even if they wouldn't naturally be included based on the other two parameters.
-     *  isLinear further restricts the allowed usage to those that are valid for linear textures.
+     * isLinear further restricts the allowed usage to those that are valid for linear textures.
+     * isExtended expands the allowed usage to those that are valid for all formats which
+     * can be used in a view created from the specified format.
 	 */
 	MTLTextureUsage getMTLTextureUsage(VkImageUsageFlags vkImageUsageFlags,
 									   MTLPixelFormat mtlFormat,
 									   MTLTextureUsage minUsage = MTLTextureUsageUnknown,
-                                       bool isLinear = false);
+                                       bool isLinear = false,
+                                       bool isExtended = false);
 
 	/** Enumerates all formats that support the given features, calling a specified function for each one. */
 	void enumerateSupportedFormats(VkFormatProperties properties, bool any, std::function<bool(VkFormat)> func);
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
index 0589252..d27b4b2 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
@@ -320,12 +320,23 @@
 	return getVkFormatDesc(vkFormat).properties;
 }
 
-MVKMTLFmtCaps MVKPixelFormats::getCapabilities(VkFormat vkFormat) {
-	return getMTLPixelFormatDesc(getVkFormatDesc(vkFormat).mtlPixelFormat).mtlFmtCaps;
+MVKMTLFmtCaps MVKPixelFormats::getCapabilities(VkFormat vkFormat, bool isExtended) {
+	return getCapabilities(getVkFormatDesc(vkFormat).mtlPixelFormat, isExtended);
 }
 
-MVKMTLFmtCaps MVKPixelFormats::getCapabilities(MTLPixelFormat mtlFormat) {
-	return getMTLPixelFormatDesc(mtlFormat).mtlFmtCaps;
+MVKMTLFmtCaps MVKPixelFormats::getCapabilities(MTLPixelFormat mtlFormat, bool isExtended) {
+    MVKMTLFormatDesc& mtlDesc = getMTLPixelFormatDesc(mtlFormat);
+    MVKMTLFmtCaps caps = mtlDesc.mtlFmtCaps;
+    if (!isExtended || mtlDesc.mtlViewClass == MVKMTLViewClass::None) { return caps; }
+    // Now get caps of all formats in the view class.
+    for (auto& otherDesc : _mtlPixelFormatDescriptions) {
+        if (otherDesc.mtlViewClass == mtlDesc.mtlViewClass) { caps |= otherDesc.mtlFmtCaps; }
+    }
+    return caps;
+}
+
+MVKMTLViewClass MVKPixelFormats::getViewClass(MTLPixelFormat mtlFormat) {
+    return getMTLPixelFormatDesc(mtlFormat).mtlViewClass;
 }
 
 const char* MVKPixelFormats::getName(VkFormat vkFormat) {
@@ -453,13 +464,14 @@
 MTLTextureUsage MVKPixelFormats::getMTLTextureUsage(VkImageUsageFlags vkImageUsageFlags,
 													MTLPixelFormat mtlFormat,
 													MTLTextureUsage minUsage,
-                                                    bool isLinear) {
+                                                    bool isLinear,
+                                                    bool isExtended) {
 	bool isDepthFmt = isDepthFormat(mtlFormat);
 	bool isStencilFmt = isStencilFormat(mtlFormat);
 	bool isCombinedDepthStencilFmt = isDepthFmt && isStencilFmt;
 	bool isColorFormat = !(isDepthFmt || isStencilFmt);
 	bool supportsStencilViews = _physicalDevice ? _physicalDevice->getMetalFeatures()->stencilViews : false;
-	MVKMTLFmtCaps mtlFmtCaps = getCapabilities(mtlFormat);
+	MVKMTLFmtCaps mtlFmtCaps = getCapabilities(mtlFormat, isExtended);
 
 	MTLTextureUsage mtlUsage = minUsage;
 
@@ -479,7 +491,7 @@
 	}
 #if MVK_MACOS
     // Clearing a linear image may use shader writes.
-    if (mvkIsAnyFlagEnabled(vkImageUsageFlags, VK_IMAGE_USAGE_TRANSFER_DST_BIT) &&
+    if (mvkIsAnyFlagEnabled(vkImageUsageFlags, (VK_IMAGE_USAGE_TRANSFER_DST_BIT)) &&
         mvkIsAnyFlagEnabled(mtlFmtCaps, kMVKMTLFmtCapsWrite) && isLinear) {
 
 		mvkEnableFlags(mtlUsage, MTLTextureUsageShaderWrite);
@@ -856,11 +868,11 @@
 	// When adding to this list, be sure to ensure _vkFormatCount is large enough for the format count
 }
 
-#define addMTLPixelFormatDesc(MTL_FMT, IOS_CAPS, MACOS_CAPS)  \
+#define addMTLPixelFormatDesc(MTL_FMT, VIEW_CLASS, IOS_CAPS, MACOS_CAPS)  \
 	MVKAssert(fmtIdx < _mtlPixelFormatCount, "Attempting to describe %d MTLPixelFormats, but only have space for %d. Increase the value of _mtlPixelFormatCount", fmtIdx + 1, _mtlPixelFormatCount);  \
 	_mtlPixelFormatDescriptions[fmtIdx++] = { .mtlPixelFormat = MTLPixelFormat ##MTL_FMT, VK_FORMAT_UNDEFINED,  \
 											  mvkSelectPlatformValue<MVKMTLFmtCaps>(kMVKMTLFmtCaps ##MACOS_CAPS, kMVKMTLFmtCaps ##IOS_CAPS),  \
-											  "MTLPixelFormat" #MTL_FMT }
+											  MVKMTLViewClass:: VIEW_CLASS, "MTLPixelFormat" #MTL_FMT }
 
 void MVKPixelFormats::initMTLPixelFormatCapabilities() {
 
@@ -871,159 +883,157 @@
 	// When adding to this list, be sure to ensure _mtlPixelFormatCount is large enough for the format count
 
 	// MTLPixelFormatInvalid must come first.
-	addMTLPixelFormatDesc( Invalid, None, None );
+	addMTLPixelFormatDesc( Invalid, None, None, None );
 
 	// Ordinary 8-bit pixel formats
-	addMTLPixelFormatDesc( A8Unorm, RF, RF );
-	addMTLPixelFormatDesc( R8Unorm, All, All );
-	addMTLPixelFormatDesc( R8Unorm_sRGB, RFCMRB, None );
-	addMTLPixelFormatDesc( R8Snorm, RFWCMB, All );
-	addMTLPixelFormatDesc( R8Uint, RWCM, RWCM );
-	addMTLPixelFormatDesc( R8Sint, RWCM, RWCM );
+	addMTLPixelFormatDesc( A8Unorm, Color8, RF, RF );
+	addMTLPixelFormatDesc( R8Unorm, Color8, All, All );
+	addMTLPixelFormatDesc( R8Unorm_sRGB, Color8, RFCMRB, None );
+	addMTLPixelFormatDesc( R8Snorm, Color8, RFWCMB, All );
+	addMTLPixelFormatDesc( R8Uint, Color8, RWCM, RWCM );
+	addMTLPixelFormatDesc( R8Sint, Color8, RWCM, RWCM );
 
 	// Ordinary 16-bit pixel formats
-	addMTLPixelFormatDesc( R16Unorm, RFWCMB, All );
-	addMTLPixelFormatDesc( R16Snorm, RFWCMB, All );
-	addMTLPixelFormatDesc( R16Uint, RWCM, RWCM );
-	addMTLPixelFormatDesc( R16Sint, RWCM, RWCM );
-	addMTLPixelFormatDesc( R16Float, All, All );
+	addMTLPixelFormatDesc( R16Unorm, Color16, RFWCMB, All );
+	addMTLPixelFormatDesc( R16Snorm, Color16, RFWCMB, All );
+	addMTLPixelFormatDesc( R16Uint, Color16, RWCM, RWCM );
+	addMTLPixelFormatDesc( R16Sint, Color16, RWCM, RWCM );
+	addMTLPixelFormatDesc( R16Float, Color16, All, All );
 
-	addMTLPixelFormatDesc( RG8Unorm, All, All );
-	addMTLPixelFormatDesc( RG8Unorm_sRGB, RFCMRB, None );
-	addMTLPixelFormatDesc( RG8Snorm, RFWCMB, All );
-	addMTLPixelFormatDesc( RG8Uint, RWCM, RWCM );
-	addMTLPixelFormatDesc( RG8Sint, RWCM, RWCM );
+	addMTLPixelFormatDesc( RG8Unorm, Color16, All, All );
+	addMTLPixelFormatDesc( RG8Unorm_sRGB, Color16, RFCMRB, None );
+	addMTLPixelFormatDesc( RG8Snorm, Color16, RFWCMB, All );
+	addMTLPixelFormatDesc( RG8Uint, Color16, RWCM, RWCM );
+	addMTLPixelFormatDesc( RG8Sint, Color16, RWCM, RWCM );
 
 	// Packed 16-bit pixel formats
-	addMTLPixelFormatDesc( B5G6R5Unorm, RFCMRB, None );
-	addMTLPixelFormatDesc( A1BGR5Unorm, RFCMRB, None );
-	addMTLPixelFormatDesc( ABGR4Unorm, RFCMRB, None );
-	addMTLPixelFormatDesc( BGR5A1Unorm, RFCMRB, None );
+	addMTLPixelFormatDesc( B5G6R5Unorm, Color16, RFCMRB, None );
+	addMTLPixelFormatDesc( A1BGR5Unorm, Color16, RFCMRB, None );
+	addMTLPixelFormatDesc( ABGR4Unorm, Color16, RFCMRB, None );
+	addMTLPixelFormatDesc( BGR5A1Unorm, Color16, RFCMRB, None );
 
 	// Ordinary 32-bit pixel formats
-	addMTLPixelFormatDesc( R32Uint, RC, RWCM );
-	addMTLPixelFormatDesc( R32Sint, RC, RWCM );
-	addMTLPixelFormatDesc( R32Float, RCMB, All );
+	addMTLPixelFormatDesc( R32Uint, Color32, RC, RWCM );
+	addMTLPixelFormatDesc( R32Sint, Color32, RC, RWCM );
+	addMTLPixelFormatDesc( R32Float, Color32, RCMB, All );
 
-	addMTLPixelFormatDesc( RG16Unorm, RFWCMB, All );
-	addMTLPixelFormatDesc( RG16Snorm, RFWCMB, All );
-	addMTLPixelFormatDesc( RG16Uint, RWCM, RWCM );
-	addMTLPixelFormatDesc( RG16Sint, RWCM, RWCM );
-	addMTLPixelFormatDesc( RG16Float, All, All );
+	addMTLPixelFormatDesc( RG16Unorm, Color32, RFWCMB, All );
+	addMTLPixelFormatDesc( RG16Snorm, Color32, RFWCMB, All );
+	addMTLPixelFormatDesc( RG16Uint, Color32, RWCM, RWCM );
+	addMTLPixelFormatDesc( RG16Sint, Color32, RWCM, RWCM );
+	addMTLPixelFormatDesc( RG16Float, Color32, All, All );
 
-	addMTLPixelFormatDesc( RGBA8Unorm, All, All );
-	addMTLPixelFormatDesc( RGBA8Unorm_sRGB, RFCMRB, RFCMRB );
-	addMTLPixelFormatDesc( RGBA8Snorm, RFWCMB, All );
-	addMTLPixelFormatDesc( RGBA8Uint, RWCM, RWCM );
-	addMTLPixelFormatDesc( RGBA8Sint, RWCM, RWCM );
+	addMTLPixelFormatDesc( RGBA8Unorm, Color32, All, All );
+	addMTLPixelFormatDesc( RGBA8Unorm_sRGB, Color32, RFCMRB, RFCMRB );
+	addMTLPixelFormatDesc( RGBA8Snorm, Color32, RFWCMB, All );
+	addMTLPixelFormatDesc( RGBA8Uint, Color32, RWCM, RWCM );
+	addMTLPixelFormatDesc( RGBA8Sint, Color32, RWCM, RWCM );
 
-	addMTLPixelFormatDesc( BGRA8Unorm, All, All );
-	addMTLPixelFormatDesc( BGRA8Unorm_sRGB, RFCMRB, RFCMRB );
+	addMTLPixelFormatDesc( BGRA8Unorm, Color32, All, All );
+	addMTLPixelFormatDesc( BGRA8Unorm_sRGB, Color32, RFCMRB, RFCMRB );
 
 	// Packed 32-bit pixel formats
-	addMTLPixelFormatDesc( RGB10A2Unorm, RFCMRB, All );
-	addMTLPixelFormatDesc( RGB10A2Uint, RCM, RWCM );
-	addMTLPixelFormatDesc( RG11B10Float, RFCMRB, All );
-	addMTLPixelFormatDesc( RGB9E5Float, RFCMRB, RF );
+	addMTLPixelFormatDesc( RGB10A2Unorm, Color32, RFCMRB, All );
+	addMTLPixelFormatDesc( RGB10A2Uint, Color32, RCM, RWCM );
+	addMTLPixelFormatDesc( RG11B10Float, Color32, RFCMRB, All );
+	addMTLPixelFormatDesc( RGB9E5Float, Color32, RFCMRB, RF );
 
 	// Ordinary 64-bit pixel formats
-	addMTLPixelFormatDesc( RG32Uint, RC, RWCM );
-	addMTLPixelFormatDesc( RG32Sint, RC, RWCM );
-	addMTLPixelFormatDesc( RG32Float, RCB, All );
+	addMTLPixelFormatDesc( RG32Uint, Color64, RC, RWCM );
+	addMTLPixelFormatDesc( RG32Sint, Color64, RC, RWCM );
+	addMTLPixelFormatDesc( RG32Float, Color64, RCB, All );
 
-	addMTLPixelFormatDesc( RGBA16Unorm, RFWCMB, All );
-	addMTLPixelFormatDesc( RGBA16Snorm, RFWCMB, All );
-	addMTLPixelFormatDesc( RGBA16Uint, RWCM, RWCM );
-	addMTLPixelFormatDesc( RGBA16Sint, RWCM, RWCM );
-	addMTLPixelFormatDesc( RGBA16Float, All, All );
+	addMTLPixelFormatDesc( RGBA16Unorm, Color64, RFWCMB, All );
+	addMTLPixelFormatDesc( RGBA16Snorm, Color64, RFWCMB, All );
+	addMTLPixelFormatDesc( RGBA16Uint, Color64, RWCM, RWCM );
+	addMTLPixelFormatDesc( RGBA16Sint, Color64, RWCM, RWCM );
+	addMTLPixelFormatDesc( RGBA16Float, Color64, All, All );
 
 	// Ordinary 128-bit pixel formats
-	addMTLPixelFormatDesc( RGBA32Uint, RC, RWCM );
-	addMTLPixelFormatDesc( RGBA32Sint, RC, RWCM );
-	addMTLPixelFormatDesc( RGBA32Float, RC, All );
+	addMTLPixelFormatDesc( RGBA32Uint, Color128, RC, RWCM );
+	addMTLPixelFormatDesc( RGBA32Sint, Color128, RC, RWCM );
+	addMTLPixelFormatDesc( RGBA32Float, Color128, RC, All );
 
 	// Compressed pixel formats
-	addMTLPixelFormatDesc( PVRTC_RGBA_2BPP, RF, None );
-	addMTLPixelFormatDesc( PVRTC_RGBA_4BPP, RF, None );
-	addMTLPixelFormatDesc( PVRTC_RGBA_2BPP_sRGB, RF, None );
-	addMTLPixelFormatDesc( PVRTC_RGBA_4BPP_sRGB, RF, None );
+	addMTLPixelFormatDesc( PVRTC_RGBA_2BPP, PVRTC_RGBA_2BPP, RF, None );
+	addMTLPixelFormatDesc( PVRTC_RGBA_4BPP, PVRTC_RGBA_4BPP, RF, None );
+	addMTLPixelFormatDesc( PVRTC_RGBA_2BPP_sRGB, PVRTC_RGBA_2BPP, RF, None );
+	addMTLPixelFormatDesc( PVRTC_RGBA_4BPP_sRGB, PVRTC_RGBA_4BPP, RF, None );
 
-	addMTLPixelFormatDesc( ETC2_RGB8, RF, None );
-	addMTLPixelFormatDesc( ETC2_RGB8_sRGB, RF, None );
-	addMTLPixelFormatDesc( ETC2_RGB8A1, RF, None );
-	addMTLPixelFormatDesc( ETC2_RGB8A1_sRGB, RF, None );
-	addMTLPixelFormatDesc( EAC_RGBA8, RF, None );
-	addMTLPixelFormatDesc( EAC_RGBA8_sRGB, RF, None );
-	addMTLPixelFormatDesc( EAC_R11Unorm, RF, None );
-	addMTLPixelFormatDesc( EAC_R11Snorm, RF, None );
-	addMTLPixelFormatDesc( EAC_RG11Unorm, RF, None );
-	addMTLPixelFormatDesc( EAC_RG11Snorm, RF, None );
+	addMTLPixelFormatDesc( ETC2_RGB8, ETC2_RGB8, RF, None );
+	addMTLPixelFormatDesc( ETC2_RGB8_sRGB, ETC2_RGB8, RF, None );
+	addMTLPixelFormatDesc( ETC2_RGB8A1, ETC2_RGB8A1, RF, None );
+	addMTLPixelFormatDesc( ETC2_RGB8A1_sRGB, ETC2_RGB8A1, RF, None );
+	addMTLPixelFormatDesc( EAC_RGBA8, EAC_RGBA8, RF, None );
+	addMTLPixelFormatDesc( EAC_RGBA8_sRGB, EAC_RGBA8, RF, None );
+	addMTLPixelFormatDesc( EAC_R11Unorm, EAC_R11, RF, None );
+	addMTLPixelFormatDesc( EAC_R11Snorm, EAC_R11, RF, None );
+	addMTLPixelFormatDesc( EAC_RG11Unorm, EAC_RG11, RF, None );
+	addMTLPixelFormatDesc( EAC_RG11Snorm, EAC_RG11, RF, None );
 
-	addMTLPixelFormatDesc( ASTC_4x4_LDR, None, None );
-	addMTLPixelFormatDesc( ASTC_4x4_sRGB, None, None );
-	addMTLPixelFormatDesc( ASTC_5x4_LDR, None, None );
-	addMTLPixelFormatDesc( ASTC_5x4_sRGB, None, None );
-	addMTLPixelFormatDesc( ASTC_5x5_LDR, None, None );
-	addMTLPixelFormatDesc( ASTC_5x5_sRGB, None, None );
-	addMTLPixelFormatDesc( ASTC_6x5_LDR, None, None );
-	addMTLPixelFormatDesc( ASTC_6x5_sRGB, None, None );
-	addMTLPixelFormatDesc( ASTC_6x6_LDR, None, None );
-	addMTLPixelFormatDesc( ASTC_6x6_sRGB, None, None );
-	addMTLPixelFormatDesc( ASTC_8x5_LDR, None, None );
-	addMTLPixelFormatDesc( ASTC_8x5_sRGB, None, None );
-	addMTLPixelFormatDesc( ASTC_8x6_LDR, None, None );
-	addMTLPixelFormatDesc( ASTC_8x6_sRGB, None, None );
-	addMTLPixelFormatDesc( ASTC_8x8_LDR, None, None );
-	addMTLPixelFormatDesc( ASTC_8x8_sRGB, None, None );
-	addMTLPixelFormatDesc( ASTC_10x5_LDR, None, None );
-	addMTLPixelFormatDesc( ASTC_10x5_sRGB, None, None );
-	addMTLPixelFormatDesc( ASTC_10x6_LDR, None, None );
-	addMTLPixelFormatDesc( ASTC_10x6_sRGB, None, None );
-	addMTLPixelFormatDesc( ASTC_10x8_LDR, None, None );
-	addMTLPixelFormatDesc( ASTC_10x8_sRGB, None, None );
-	addMTLPixelFormatDesc( ASTC_10x10_LDR, None, None );
-	addMTLPixelFormatDesc( ASTC_10x10_sRGB, None, None );
-	addMTLPixelFormatDesc( ASTC_12x10_LDR, None, None );
-	addMTLPixelFormatDesc( ASTC_12x10_sRGB, None, None );
-	addMTLPixelFormatDesc( ASTC_12x12_LDR, None, None );
-	addMTLPixelFormatDesc( ASTC_12x12_sRGB, None, None );
+	addMTLPixelFormatDesc( ASTC_4x4_LDR, ASTC_4x4, None, None );
+	addMTLPixelFormatDesc( ASTC_4x4_sRGB, ASTC_4x4, None, None );
+	addMTLPixelFormatDesc( ASTC_5x4_LDR, ASTC_5x4, None, None );
+	addMTLPixelFormatDesc( ASTC_5x4_sRGB, ASTC_5x4, None, None );
+	addMTLPixelFormatDesc( ASTC_5x5_LDR, ASTC_5x5, None, None );
+	addMTLPixelFormatDesc( ASTC_5x5_sRGB, ASTC_5x5, None, None );
+	addMTLPixelFormatDesc( ASTC_6x5_LDR, ASTC_6x5, None, None );
+	addMTLPixelFormatDesc( ASTC_6x5_sRGB, ASTC_6x5, None, None );
+	addMTLPixelFormatDesc( ASTC_6x6_LDR, ASTC_6x6, None, None );
+	addMTLPixelFormatDesc( ASTC_6x6_sRGB, ASTC_6x6, None, None );
+	addMTLPixelFormatDesc( ASTC_8x5_LDR, ASTC_8x5, None, None );
+	addMTLPixelFormatDesc( ASTC_8x5_sRGB, ASTC_8x5, None, None );
+	addMTLPixelFormatDesc( ASTC_8x6_LDR, ASTC_8x6, None, None );
+	addMTLPixelFormatDesc( ASTC_8x6_sRGB, ASTC_8x6, None, None );
+	addMTLPixelFormatDesc( ASTC_8x8_LDR, ASTC_8x8, None, None );
+	addMTLPixelFormatDesc( ASTC_8x8_sRGB, ASTC_8x8, None, None );
+	addMTLPixelFormatDesc( ASTC_10x5_LDR, ASTC_10x5, None, None );
+	addMTLPixelFormatDesc( ASTC_10x5_sRGB, ASTC_10x5, None, None );
+	addMTLPixelFormatDesc( ASTC_10x6_LDR, ASTC_10x6, None, None );
+	addMTLPixelFormatDesc( ASTC_10x6_sRGB, ASTC_10x6, None, None );
+	addMTLPixelFormatDesc( ASTC_10x8_LDR, ASTC_10x8, None, None );
+	addMTLPixelFormatDesc( ASTC_10x8_sRGB, ASTC_10x8, None, None );
+	addMTLPixelFormatDesc( ASTC_10x10_LDR, ASTC_10x10, None, None );
+	addMTLPixelFormatDesc( ASTC_10x10_sRGB, ASTC_10x10, None, None );
+	addMTLPixelFormatDesc( ASTC_12x10_LDR, ASTC_12x10, None, None );
+	addMTLPixelFormatDesc( ASTC_12x10_sRGB, ASTC_12x10, None, None );
+	addMTLPixelFormatDesc( ASTC_12x12_LDR, ASTC_12x12, None, None );
+	addMTLPixelFormatDesc( ASTC_12x12_sRGB, ASTC_12x12, None, None );
 
-	addMTLPixelFormatDesc( BC1_RGBA, None, RF );
-	addMTLPixelFormatDesc( BC1_RGBA_sRGB, None, RF );
-	addMTLPixelFormatDesc( BC1_RGBA, None, RF );
-	addMTLPixelFormatDesc( BC1_RGBA_sRGB, None, RF );
-	addMTLPixelFormatDesc( BC2_RGBA, None, RF );
-	addMTLPixelFormatDesc( BC2_RGBA_sRGB, None, RF );
-	addMTLPixelFormatDesc( BC3_RGBA, None, RF );
-	addMTLPixelFormatDesc( BC3_RGBA_sRGB, None, RF );
-	addMTLPixelFormatDesc( BC4_RUnorm, None, RF );
-	addMTLPixelFormatDesc( BC4_RSnorm, None, RF );
-	addMTLPixelFormatDesc( BC5_RGUnorm, None, RF );
-	addMTLPixelFormatDesc( BC5_RGSnorm, None, RF );
-	addMTLPixelFormatDesc( BC6H_RGBUfloat, None, RF );
-	addMTLPixelFormatDesc( BC6H_RGBFloat, None, RF );
-	addMTLPixelFormatDesc( BC7_RGBAUnorm, None, RF );
-	addMTLPixelFormatDesc( BC7_RGBAUnorm_sRGB, None, RF );
+	addMTLPixelFormatDesc( BC1_RGBA, BC1_RGBA, None, RF );
+	addMTLPixelFormatDesc( BC1_RGBA_sRGB, BC1_RGBA, None, RF );
+	addMTLPixelFormatDesc( BC2_RGBA, BC2_RGBA, None, RF );
+	addMTLPixelFormatDesc( BC2_RGBA_sRGB, BC2_RGBA, None, RF );
+	addMTLPixelFormatDesc( BC3_RGBA, BC3_RGBA, None, RF );
+	addMTLPixelFormatDesc( BC3_RGBA_sRGB, BC3_RGBA, None, RF );
+	addMTLPixelFormatDesc( BC4_RUnorm, BC4_R, None, RF );
+	addMTLPixelFormatDesc( BC4_RSnorm, BC4_R, None, RF );
+	addMTLPixelFormatDesc( BC5_RGUnorm, BC5_RG, None, RF );
+	addMTLPixelFormatDesc( BC5_RGSnorm, BC5_RG, None, RF );
+	addMTLPixelFormatDesc( BC6H_RGBUfloat, BC6H_RGB, None, RF );
+	addMTLPixelFormatDesc( BC6H_RGBFloat, BC6H_RGB, None, RF );
+	addMTLPixelFormatDesc( BC7_RGBAUnorm, BC7_RGBA, None, RF );
+	addMTLPixelFormatDesc( BC7_RGBAUnorm_sRGB, BC7_RGBA, None, RF );
 
 	// YUV pixel formats
-	addMTLPixelFormatDesc( GBGR422, RF, RF );
-	addMTLPixelFormatDesc( BGRG422, RF, RF );
+	addMTLPixelFormatDesc( GBGR422, None, RF, RF );
+	addMTLPixelFormatDesc( BGRG422, None, RF, RF );
 
 	// Extended range and wide color pixel formats
-	addMTLPixelFormatDesc( BGRA10_XR, None, None );
-	addMTLPixelFormatDesc( BGRA10_XR_sRGB, None, None );
-	addMTLPixelFormatDesc( BGR10_XR, None, None );
-	addMTLPixelFormatDesc( BGR10_XR_sRGB, None, None );
-	addMTLPixelFormatDesc( BGR10A2Unorm, None, None );
+	addMTLPixelFormatDesc( BGRA10_XR, BGRA10_XR, None, None );
+	addMTLPixelFormatDesc( BGRA10_XR_sRGB, BGRA10_XR, None, None );
+	addMTLPixelFormatDesc( BGR10_XR, BGR10_XR, None, None );
+	addMTLPixelFormatDesc( BGR10_XR_sRGB, BGR10_XR, None, None );
+	addMTLPixelFormatDesc( BGR10A2Unorm, Color32, None, None );
 
 	// Depth and stencil pixel formats
-	addMTLPixelFormatDesc( Depth16Unorm, None, None );
-	addMTLPixelFormatDesc( Depth32Float, DRM, DRFMR );
-	addMTLPixelFormatDesc( Stencil8, DRM, DRMR );
-	addMTLPixelFormatDesc( Depth24Unorm_Stencil8, None, None );
-	addMTLPixelFormatDesc( Depth32Float_Stencil8, DRM, DRFMR );
-	addMTLPixelFormatDesc( X24_Stencil8, None, DRMR );
-	addMTLPixelFormatDesc( X32_Stencil8, DRM, DRMR );
+	addMTLPixelFormatDesc( Depth16Unorm, None, None, None );
+	addMTLPixelFormatDesc( Depth32Float, None, DRM, DRFMR );
+	addMTLPixelFormatDesc( Stencil8, None, DRM, DRMR );
+	addMTLPixelFormatDesc( Depth24Unorm_Stencil8, Depth24_Stencil8, None, None );
+	addMTLPixelFormatDesc( Depth32Float_Stencil8, Depth32_Stencil8, DRM, DRFMR );
+	addMTLPixelFormatDesc( X24_Stencil8, Depth24_Stencil8, None, DRMR );
+	addMTLPixelFormatDesc( X32_Stencil8, Depth32_Stencil8, DRM, DRMR );
 
 	// When adding to this list, be sure to ensure _mtlPixelFormatCount is large enough for the format count
 }
@@ -1032,7 +1042,7 @@
 	MVKAssert(fmtIdx < _mtlVertexFormatCount, "Attempting to describe %d MTLVertexFormats, but only have space for %d. Increase the value of _mtlVertexFormatCount", fmtIdx + 1, _mtlVertexFormatCount);  \
 	_mtlVertexFormatDescriptions[fmtIdx++] = { .mtlVertexFormat = MTLVertexFormat ##MTL_VTX_FMT, VK_FORMAT_UNDEFINED,  \
                                                mvkSelectPlatformValue<MVKMTLFmtCaps>(kMVKMTLFmtCaps ##MACOS_CAPS, kMVKMTLFmtCaps ##IOS_CAPS),  \
-                                               "MTLVertexFormat" #MTL_VTX_FMT }
+                                               MVKMTLViewClass::None, "MTLVertexFormat" #MTL_VTX_FMT }
 
 void MVKPixelFormats::initMTLVertexFormatCapabilities() {