Reduce memory used by MVKPixelFormats lookups.

- Add MVKInflectionMap collection to manage lookups based on enums
  that have a large set of consecutive elements, plus additional enum
  values that are more sparsely assigned.
- Recognize every MTLPixelFormat value can be held in uint16_t.
- Reduce inflection-map sizes by calling shrink_to_fit().
- runcts script log completion time (unrelated).
diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md
index 36329b5..eb12a83 100644
--- a/Docs/MoltenVK_Runtime_UserGuide.md
+++ b/Docs/MoltenVK_Runtime_UserGuide.md
@@ -314,6 +314,8 @@
 - `VK_KHR_bind_memory2`
 - `VK_KHR_buffer_device_address`
   - *Requires GPU Tier 2 argument buffers support.*
+- `VK_KHR_calibrated_timestamp`
+  - *Requires Metal 2.2.*
 - `VK_KHR_copy_commands2`
 - `VK_KHR_create_renderpass2`
 - `VK_KHR_dedicated_allocation`
@@ -323,6 +325,7 @@
 - `VK_KHR_device_group_creation`
 - `VK_KHR_driver_properties`
 - `VK_KHR_dynamic_rendering`
+- `VK_KHR_format_feature_flags2`
 - `VK_KHR_fragment_shader_barycentric`
   - *Requires Metal 2.2 on Mac or Metal 2.3 on iOS.*
 - `VK_KHR_get_memory_requirements2`
@@ -358,6 +361,7 @@
 - `VK_KHR_timeline_semaphore`
 - `VK_KHR_uniform_buffer_standard_layout`
 - `VK_KHR_variable_pointers`
+- `VK_KHR_vertex_attribute_divisor`
 - `VK_EXT_4444_formats`
   - *Requires 16-bit formats and either native texture swizzling or manual swizzling to be enabled.*
 - `VK_EXT_buffer_device_address`
diff --git a/ExternalRevisions/Vulkan-Headers_repo_revision b/ExternalRevisions/Vulkan-Headers_repo_revision
index d9d0ec4..abc1880 100644
--- a/ExternalRevisions/Vulkan-Headers_repo_revision
+++ b/ExternalRevisions/Vulkan-Headers_repo_revision
@@ -1 +1 @@
-19a863ccce773ff393b186329478b1eb1a519fd3
+41263fc5aa994b8eafaca946583bfcceca8ca419
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index ec1bf9f..e6abcc0 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -762,6 +762,12 @@
 				portabilityProps->minVertexInputBindingStrideAlignment = (uint32_t)_metalFeatures.vertexStrideAlignment;
 				break;
 			}
+			case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_KHR: {
+				auto* divisorProps = (VkPhysicalDeviceVertexAttributeDivisorPropertiesKHR*)next;
+				divisorProps->maxVertexAttribDivisor = kMVKUndefinedLargeUInt32;
+				divisorProps->supportsNonZeroFirstInstance = VK_TRUE;
+				break;
+			}
 			case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT: {
 				auto* extDynState3Props = (VkPhysicalDeviceExtendedDynamicState3PropertiesEXT*)next;
 				extDynState3Props->dynamicPrimitiveTopologyUnrestricted = false;
@@ -888,6 +894,22 @@
 
 void MVKPhysicalDevice::getFormatProperties(VkFormat format, VkFormatProperties2KHR* pFormatProperties) {
 	pFormatProperties->sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR;
+
+    for (auto* next = (VkBaseOutStructure*)pFormatProperties->pNext; next; next = next->pNext) {
+        switch (next->sType) {
+            case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR: {
+                auto* properties3 = (VkFormatProperties3*)next;
+                auto& properties = _pixelFormats.getVkFormatProperties3(format);
+                properties3->linearTilingFeatures = properties.linearTilingFeatures;
+                properties3->optimalTilingFeatures = properties.optimalTilingFeatures;
+                properties3->bufferFeatures = properties.bufferFeatures;
+                break;
+            }
+            default:
+                break;
+        }
+    }
+
 	getFormatProperties(format, &pFormatProperties->formatProperties);
 }
 
@@ -999,15 +1021,14 @@
 				maxLayers = 1;
 				sampleCounts = VK_SAMPLE_COUNT_1_BIT;
 			} else {
-				VkFormatProperties fmtProps;
-				getFormatProperties(format, &fmtProps);
+				VkFormatProperties3& fmtProps = _pixelFormats.getVkFormatProperties3(format);
 				// Compressed multisampled textures aren't supported.
 				// Chroma-subsampled multisampled textures aren't supported.
 				// Multisampled cube textures aren't supported.
 				// Non-renderable multisampled textures aren't supported.
 				if (mvkFmt == kMVKFormatCompressed || isChromaSubsampled ||
 					mvkIsAnyFlagEnabled(flags, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) ||
-					!mvkIsAnyFlagEnabled(fmtProps.optimalTilingFeatures, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT|VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) ) {
+					!mvkIsAnyFlagEnabled(fmtProps.optimalTilingFeatures, VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT) ) {
 					sampleCounts = VK_SAMPLE_COUNT_1_BIT;
 				}
 				// BGRG and GBGR images may only have one mip level and one layer.
@@ -2520,7 +2541,11 @@
 		// to fill out the VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT struct.
         uint32_t maxStorage = 0, maxUniform = 0;
         bool singleTexelStorage = true, singleTexelUniform = true;
-        _pixelFormats.enumerateSupportedFormats({0, 0, VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT}, true, [&](VkFormat vk) {
+		
+		VkFormatProperties3 fmtProps = {}; // We don't initialize sType as enumerateSupportedFormats doesn't care.
+		fmtProps.bufferFeatures = VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT;
+		
+        _pixelFormats.enumerateSupportedFormats(fmtProps, true, [&](VkFormat vk) {
 			MTLPixelFormat mtlFmt = _pixelFormats.getMTLPixelFormat(vk);
 			if ( !mtlFmt ) { return false; }	// If format is invalid, avoid validation errors on MTLDevice format alignment calls
 
@@ -2530,7 +2555,7 @@
             } else {
                 alignment = [_mtlDevice minimumLinearTextureAlignmentForPixelFormat: mtlFmt];
             }
-            VkFormatProperties& props = _pixelFormats.getVkFormatProperties(vk);
+            VkFormatProperties3& props = _pixelFormats.getVkFormatProperties3(vk);
             // For uncompressed formats, this is the size of a single texel.
             // Note that no implementations of Metal support compressed formats
             // in a linear texture (including texture buffers). It's likely that even
@@ -2558,11 +2583,11 @@
                     break;
                 }
             }
-            if (mvkAreAllFlagsEnabled(props.bufferFeatures, VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)) {
+            if (mvkAreAllFlagsEnabled(props.bufferFeatures, VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT)) {
                 maxUniform = max(maxUniform, uint32_t(alignment));
                 if (alignment > texelSize) { singleTexelUniform = false; }
             }
-            if (mvkAreAllFlagsEnabled(props.bufferFeatures, VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT)) {
+            if (mvkAreAllFlagsEnabled(props.bufferFeatures, VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT)) {
                 maxStorage = max(maxStorage, uint32_t(alignment));
                 if (alignment > texelSize) { singleTexelStorage = false; }
             }
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index 61bb96b..d9d6a8b 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -931,7 +931,7 @@
 
 	_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) ||
-								 mvkAreAllFlagsEnabled(pixFmts->getVkFormatProperties(pCreateInfo->format).optimalTilingFeatures, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT));
+								 mvkAreAllFlagsEnabled(pixFmts->getVkFormatProperties3(pCreateInfo->format).optimalTilingFeatures, VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT));
 	_canSupportMTLTextureView = !_isDepthStencilAttachment || _device->_pMetalFeatures->stencilViews;
 	_rowByteAlignment = _isLinear || _isLinearForAtomics ? _device->getVkFormatTexelBufferAlignment(pCreateInfo->format, this) : mvkEnsurePowerOfTwo(pixFmts->getBytesPerBlock(pCreateInfo->format));
 
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
index c0d4e19..a681d87 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
@@ -705,6 +705,8 @@
 	ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkSetPrivateData, EXT, EXT_PRIVATE_DATA);
 
 	// Device extension functions.
+	ADD_DVC_EXT_ENTRY_POINT(vkGetCalibratedTimestampsKHR, KHR_CALIBRATED_TIMESTAMPS);
+	ADD_DVC_EXT_ENTRY_POINT(vkGetPhysicalDeviceCalibrateableTimeDomainsKHR, KHR_CALIBRATED_TIMESTAMPS);
     ADD_DVC_EXT_ENTRY_POINT(vkCreateDeferredOperationKHR, KHR_DEFERRED_HOST_OPERATIONS);
     ADD_DVC_EXT_ENTRY_POINT(vkDeferredOperationJoinKHR, KHR_DEFERRED_HOST_OPERATIONS);
     ADD_DVC_EXT_ENTRY_POINT(vkDestroyDeferredOperationKHR, KHR_DEFERRED_HOST_OPERATIONS);
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h
index 2d446eb..d4cab79 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h
@@ -140,7 +140,7 @@
 	VkExtent2D blockTexelSize;
 	uint32_t bytesPerBlock;
 	MVKFormatType formatType;
-	VkFormatProperties properties;
+    VkFormatProperties3 properties;
 	VkComponentMapping componentMapping;
 	const char* name;
 	bool hasReportedSubstitution;
@@ -337,7 +337,8 @@
 	MTLTextureSwizzleChannels getMTLTextureSwizzleChannels(VkFormat vkFormat);
 
 	/** Returns the default properties for the specified Vulkan format. */
-	VkFormatProperties& getVkFormatProperties(VkFormat vkFormat);
+    VkFormatProperties getVkFormatProperties(VkFormat format);
+	VkFormatProperties3& getVkFormatProperties3(VkFormat vkFormat);
 
 	/** Returns the Metal format capabilities supported by the specified Vulkan format, without substitution. */
 	MVKMTLFmtCaps getCapabilities(VkFormat vkFormat, bool isExtended = false);
@@ -390,15 +391,15 @@
                                        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);
+	void enumerateSupportedFormats(const VkFormatProperties3& properties, bool any, std::function<bool(VkFormat)> func);
 
 	/**
 	 * Returns the Metal MTLVertexFormat corresponding to the specified
 	 * Vulkan VkFormat as used as a vertex attribute format.
 	 */
 	MTLVertexFormat getMTLVertexFormat(VkFormat vkFormat);
-
-
+    
+    static VkFormatFeatureFlags convertFormatPropertiesFlagBits(VkFormatFeatureFlags2 flags);
 #pragma mark Construction
 
 	MVKPixelFormats(MVKPhysicalDevice* physicalDevice = nullptr);
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
index 60fcc09..9a6e1a8 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
@@ -420,10 +420,19 @@
 	return mvkMTLTextureSwizzleChannelsFromVkComponentMapping(getVkComponentMapping(vkFormat));
 }
 
-VkFormatProperties& MVKPixelFormats::getVkFormatProperties(VkFormat vkFormat) {
+VkFormatProperties3& MVKPixelFormats::getVkFormatProperties3(VkFormat vkFormat) {
 	return getVkFormatDesc(vkFormat).properties;
 }
 
+VkFormatProperties MVKPixelFormats::getVkFormatProperties(VkFormat vkFormat) {
+    auto& properties = getVkFormatProperties3(vkFormat);
+    VkFormatProperties ret;
+    ret.linearTilingFeatures = MVKPixelFormats::convertFormatPropertiesFlagBits(properties.linearTilingFeatures);
+    ret.optimalTilingFeatures = MVKPixelFormats::convertFormatPropertiesFlagBits(properties.optimalTilingFeatures);
+    ret.bufferFeatures = MVKPixelFormats::convertFormatPropertiesFlagBits(properties.bufferFeatures);
+    return ret;
+}
+
 MVKMTLFmtCaps MVKPixelFormats::getCapabilities(VkFormat vkFormat, bool isExtended) {
 	return getCapabilities(getVkFormatDesc(vkFormat).mtlPixelFormat, isExtended);
 }
@@ -459,8 +468,8 @@
     return getMTLVertexFormatDesc(mtlFormat).name;
 }
 
-void MVKPixelFormats::enumerateSupportedFormats(VkFormatProperties properties, bool any, std::function<bool(VkFormat)> func) {
-	static const auto areFeaturesSupported = [any](uint32_t a, uint32_t b) {
+void MVKPixelFormats::enumerateSupportedFormats(const VkFormatProperties3& properties, bool any, std::function<bool(VkFormat)> func) {
+	static const auto areFeaturesSupported = [any](VkFlags64 a, VkFlags64 b) {
 		if (b == 0) return true;
 		if (any)
 			return mvkIsAnyFlagEnabled(a, b);
@@ -785,6 +794,11 @@
 	return _mtlVertexFormatDescriptions[mtlFormat];
 }
 
+VkFormatFeatureFlags MVKPixelFormats::convertFormatPropertiesFlagBits(VkFormatFeatureFlags2 flags) {
+    // Truncate to 32-bits and just return. All current values are identical.
+    return static_cast<VkFormatFeatureFlags>(flags);
+}
+
 
 #pragma mark Construction
 
@@ -803,7 +817,7 @@
 #define addVkFormatDescFull(VK_FMT, MTL_FMT, MTL_FMT_ALT, MTL_VTX_FMT, MTL_VTX_FMT_ALT, CSPC, CSCB, BLK_W, BLK_H, BLK_BYTE_CNT, MVK_FMT_TYPE, SWIZ_R, SWIZ_G, SWIZ_B, SWIZ_A)  \
 	vkFmt = VK_FORMAT_ ##VK_FMT;  \
 	_vkFormatDescriptions[vkFmt] = { vkFmt, MTLPixelFormat ##MTL_FMT, MTLPixelFormat ##MTL_FMT_ALT, MTLVertexFormat ##MTL_VTX_FMT, MTLVertexFormat ##MTL_VTX_FMT_ALT,  \
-									 CSPC, CSCB, { BLK_W, BLK_H }, BLK_BYTE_CNT, kMVKFormat ##MVK_FMT_TYPE, { 0, 0, 0 }, \
+									 CSPC, CSCB, { BLK_W, BLK_H }, BLK_BYTE_CNT, kMVKFormat ##MVK_FMT_TYPE, { VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3, nullptr, 0, 0, 0 }, \
 									 { VK_COMPONENT_SWIZZLE_ ##SWIZ_R, VK_COMPONENT_SWIZZLE_ ##SWIZ_G, VK_COMPONENT_SWIZZLE_ ##SWIZ_B, VK_COMPONENT_SWIZZLE_ ##SWIZ_A }, \
 									 "VK_FORMAT_" #VK_FMT, false }
 
@@ -818,6 +832,7 @@
 
 void MVKPixelFormats::initVkFormatCapabilities() {
 	VkFormat vkFmt;
+	_vkFormatDescriptions.reserve(512);	// High estimate to future-proof against allocations as elements are added. shrink_to_fit() below will collapse.
 
 	// UNDEFINED must come first.
 	addVkFormatDesc( UNDEFINED, Invalid, Invalid, Invalid, Invalid, 1, 1, 0, None );
@@ -1126,6 +1141,7 @@
 
 void MVKPixelFormats::initMTLPixelFormatCapabilities() {
 	MTLPixelFormat mtlPixFmt;
+	_mtlPixelFormatDescriptions.reserve(512);	// High estimate to future-proof against allocations as elements are added. shrink_to_fit() below will collapse.
 
 	// MTLPixelFormatInvalid must come first.
 	addMTLPixelFormatDesc    ( Invalid, None, None, None );
@@ -1307,7 +1323,6 @@
 
 void MVKPixelFormats::initMTLVertexFormatCapabilities() {
 	MTLVertexFormat mtlVtxFmt;
-
 	_mtlVertexFormatDescriptions.resize(MTLVertexFormatHalf + 3, {});
 
 	addMTLVertexFormatDesc( Invalid, None, None );  // MTLVertexFormatInvalid must come first.
@@ -2026,33 +2041,33 @@
 }
 
 // Enumeration of Vulkan format features aligned to the MVKMTLFmtCaps enumeration.
-typedef enum : VkFormatFeatureFlags {
+typedef enum : VkFormatFeatureFlags2 {
 	kMVKVkFormatFeatureFlagsTexNone     = 0,
-	kMVKVkFormatFeatureFlagsTexRead     = (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
-										   VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
-										   VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
-										   VK_FORMAT_FEATURE_BLIT_SRC_BIT),
-	kMVKVkFormatFeatureFlagsTexFilter   = (VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT),
-	kMVKVkFormatFeatureFlagsTexWrite    = (VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT),
-	kMVKVkFormatFeatureFlagsTexAtomic   = (VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT),
-	kMVKVkFormatFeatureFlagsTexColorAtt = (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
-										   VK_FORMAT_FEATURE_BLIT_DST_BIT),
-	kMVKVkFormatFeatureFlagsTexDSAtt    = (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT |
-										   VK_FORMAT_FEATURE_BLIT_DST_BIT),
-	kMVKVkFormatFeatureFlagsTexBlend    = (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT),
-    kMVKVkFormatFeatureFlagsTexTransfer          = (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
-                                                    VK_FORMAT_FEATURE_TRANSFER_DST_BIT),
-    kMVKVkFormatFeatureFlagsTexChromaSubsampling = (VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT_KHR |
-                                                    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR),
-    kMVKVkFormatFeatureFlagsTexMultiPlanar       = (VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT_KHR |
-                                                    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR |
-                                                    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR |
-                                                    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR |
-                                                    VK_FORMAT_FEATURE_DISJOINT_BIT_KHR),
-	kMVKVkFormatFeatureFlagsBufRead     = (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT),
-	kMVKVkFormatFeatureFlagsBufWrite    = (VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT),
-	kMVKVkFormatFeatureFlagsBufAtomic   = (VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT),
-	kMVKVkFormatFeatureFlagsBufVertex   = (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT),
+	kMVKVkFormatFeatureFlagsTexRead     = (VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT |
+										   VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT |
+										   VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT |
+										   VK_FORMAT_FEATURE_2_BLIT_SRC_BIT),
+	kMVKVkFormatFeatureFlagsTexFilter   = (VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT),
+	kMVKVkFormatFeatureFlagsTexWrite    = (VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT),
+	kMVKVkFormatFeatureFlagsTexAtomic   = (VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT),
+	kMVKVkFormatFeatureFlagsTexColorAtt = (VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
+										   VK_FORMAT_FEATURE_2_BLIT_DST_BIT),
+	kMVKVkFormatFeatureFlagsTexDSAtt    = (VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT |
+										   VK_FORMAT_FEATURE_2_BLIT_DST_BIT),
+	kMVKVkFormatFeatureFlagsTexBlend    = (VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT),
+    kMVKVkFormatFeatureFlagsTexTransfer          = (VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT |
+                                                    VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT),
+    kMVKVkFormatFeatureFlagsTexChromaSubsampling = (VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT_KHR |
+                                                    VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR),
+    kMVKVkFormatFeatureFlagsTexMultiPlanar       = (VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT_KHR |
+                                                    VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR |
+                                                    VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR |
+                                                    VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR |
+                                                    VK_FORMAT_FEATURE_2_DISJOINT_BIT_KHR),
+	kMVKVkFormatFeatureFlagsBufRead     = (VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT),
+	kMVKVkFormatFeatureFlagsBufWrite    = (VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT),
+	kMVKVkFormatFeatureFlagsBufAtomic   = (VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT),
+	kMVKVkFormatFeatureFlagsBufVertex   = (VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT),
 } MVKVkFormatFeatureFlags;
 
 // Sets the VkFormatProperties (optimal/linear/buffer) for the Vulkan format.
@@ -2063,7 +2078,7 @@
 		mvkEnableFlags(VK_FEATS, kMVKVkFormatFeatureFlags ##TYPE ##CAP);  \
 	}
 
-	VkFormatProperties& vkProps = vkDesc.properties;
+	VkFormatProperties3& vkProps = vkDesc.properties;
 	MVKMTLFmtCaps mtlPixFmtCaps = getMTLPixelFormatDesc(vkDesc.mtlPixelFormat).mtlFmtCaps;
     vkProps.optimalTilingFeatures = kMVKVkFormatFeatureFlagsTexNone;
     vkProps.linearTilingFeatures = kMVKVkFormatFeatureFlagsTexNone;
@@ -2110,7 +2125,7 @@
 	// Vulkan forbids blits between chroma-subsampled formats.
 	// If we can't write the stencil reference from the shader, we can't blit stencil.
 	if (chromaSubsamplingComponentBits > 0 || (isStencilFormat(vkDesc.mtlPixelFormat) && !supportsStencilFeedback)) {
-		mvkDisableFlags(vkProps.optimalTilingFeatures, (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT));
+		mvkDisableFlags(vkProps.optimalTilingFeatures, (VK_FORMAT_FEATURE_2_BLIT_SRC_BIT | VK_FORMAT_FEATURE_2_BLIT_DST_BIT));
 	}
 
 	// These formats require swizzling. In order to support rendering, we'll have to swizzle
diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.def b/MoltenVK/MoltenVK/Layers/MVKExtensions.def
index c9917b7..7279665 100644
--- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def
+++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def
@@ -45,6 +45,7 @@
 MVK_EXTENSION(KHR_8bit_storage,                       KHR_8BIT_STORAGE,                       DEVICE,   10.11,  8.0,  1.0)
 MVK_EXTENSION(KHR_bind_memory2,                       KHR_BIND_MEMORY_2,                      DEVICE,   10.11,  8.0,  1.0)
 MVK_EXTENSION(KHR_buffer_device_address,              KHR_BUFFER_DEVICE_ADDRESS,              DEVICE,   13.0,  16.0,  1.0)
+MVK_EXTENSION(KHR_calibrated_timestamps,              KHR_CALIBRATED_TIMESTAMPS,              DEVICE,   10.15, 14.0,  1.0)
 MVK_EXTENSION(KHR_copy_commands2,                     KHR_COPY_COMMANDS_2,                    DEVICE,   10.11,  8.0,  1.0)
 MVK_EXTENSION(KHR_create_renderpass2,                 KHR_CREATE_RENDERPASS_2,                DEVICE,   10.11,  8.0,  1.0)
 MVK_EXTENSION(KHR_dedicated_allocation,               KHR_DEDICATED_ALLOCATION,               DEVICE,   10.11,  8.0,  1.0)
@@ -63,6 +64,7 @@
 MVK_EXTENSION(KHR_external_semaphore,                 KHR_EXTERNAL_SEMAPHORE,                 DEVICE,   10.11,  8.0,  1.0)
 MVK_EXTENSION(KHR_external_semaphore_capabilities,    KHR_EXTERNAL_SEMAPHORE_CAPABILITIES,    INSTANCE, 10.11,  8.0,  1.0)
 MVK_EXTENSION(KHR_fragment_shader_barycentric,        KHR_FRAGMENT_SHADER_BARYCENTRIC,        DEVICE,   10.15, 14.0,  1.0)
+MVK_EXTENSION(KHR_format_feature_flags2,              KHR_FORMAT_FEATURE_FLAGS_2,             DEVICE,   10.11,  8.0,  1.0)
 MVK_EXTENSION(KHR_get_memory_requirements2,           KHR_GET_MEMORY_REQUIREMENTS_2,          DEVICE,   10.11,  8.0,  1.0)
 MVK_EXTENSION(KHR_get_physical_device_properties2,    KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2,   INSTANCE, 10.11,  8.0,  1.0)
 MVK_EXTENSION(KHR_get_surface_capabilities2,          KHR_GET_SURFACE_CAPABILITIES_2,         INSTANCE, 10.11,  8.0,  1.0)
@@ -95,6 +97,7 @@
 MVK_EXTENSION(KHR_timeline_semaphore,                 KHR_TIMELINE_SEMAPHORE,                 DEVICE,   10.11,  8.0,  1.0)
 MVK_EXTENSION(KHR_uniform_buffer_standard_layout,     KHR_UNIFORM_BUFFER_STANDARD_LAYOUT,     DEVICE,   10.11,  8.0,  1.0)
 MVK_EXTENSION(KHR_variable_pointers,                  KHR_VARIABLE_POINTERS,                  DEVICE,   10.11,  8.0,  1.0)
+MVK_EXTENSION(KHR_vertex_attribute_divisor,           KHR_VERTEX_ATTRIBUTE_DIVISOR,           DEVICE,   10.11,  8.0,  1.0)
 MVK_EXTENSION(KHR_vulkan_memory_model,                KHR_VULKAN_MEMORY_MODEL,                DEVICE,   MVK_NA, MVK_NA, MVK_NA)
 MVK_EXTENSION(EXT_4444_formats,                       EXT_4444_FORMATS,                       DEVICE,   11.0,  13.0,  1.0)
 MVK_EXTENSION(EXT_buffer_device_address,              EXT_BUFFER_DEVICE_ADDRESS,              DEVICE,   13.0,  16.0,  1.0)
diff --git a/MoltenVK/MoltenVK/Utility/MVKInflectionMap.h b/MoltenVK/MoltenVK/Utility/MVKInflectionMap.h
index b536451..afac8ca 100755
--- a/MoltenVK/MoltenVK/Utility/MVKInflectionMap.h
+++ b/MoltenVK/MoltenVK/Utility/MVKInflectionMap.h
@@ -81,6 +81,7 @@
 

 	bool empty() { return _values.size() == 0; }

 	size_t size() { return _values.size(); }

+	void reserve(const size_t new_cap) { _values.reserve(new_cap); }

 	void shrink_to_fit() { _values.shrink_to_fit(); }

 

 protected:

diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
index 1d228fa..8c1c24f 100644
--- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm
+++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
@@ -2876,6 +2876,33 @@
 
 
 #pragma mark -
+#pragma mark VK_KHR_calibrated_timestamps
+
+MVK_PUBLIC_VULKAN_SYMBOL VkResult vkGetPhysicalDeviceCalibrateableTimeDomainsKHR(
+	VkPhysicalDevice							physicalDevice,
+	uint32_t*									pTimeDomainCount,
+	VkTimeDomainEXT*							pTimeDomains) {
+	MVKTraceVulkanCallStart();
+	MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
+	mvkPD->getCalibrateableTimeDomains(pTimeDomainCount, pTimeDomains);
+	MVKTraceVulkanCallEnd();
+	return VK_SUCCESS;
+}
+
+MVK_PUBLIC_VULKAN_SYMBOL VkResult vkGetCalibratedTimestampsKHR(
+	VkDevice									device,
+	uint32_t									timestampCount,
+	const VkCalibratedTimestampInfoEXT*			pTimestampInfos,
+	uint64_t*									pTimestamps,
+	uint64_t*									pMaxDeviation) {
+	MVKTraceVulkanCallStart();
+	MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
+	mvkDev->getCalibratedTimestamps(timestampCount, pTimestampInfos, pTimestamps, pMaxDeviation);
+	MVKTraceVulkanCallEnd();
+	return VK_SUCCESS;
+}
+
+#pragma mark -
 #pragma mark VK_KHR_copy_commands2 extension
 
 MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdBlitImage2, KHR);
@@ -3371,29 +3398,9 @@
 #pragma mark -
 #pragma mark VK_EXT_calibrated_timestamps extension
 
-MVK_PUBLIC_VULKAN_SYMBOL VkResult vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(
-	VkPhysicalDevice							physicalDevice,
-	uint32_t*									pTimeDomainCount,
-	VkTimeDomainEXT*							pTimeDomains) {
-	MVKTraceVulkanCallStart();
-	MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
-	mvkPD->getCalibrateableTimeDomains(pTimeDomainCount, pTimeDomains);
-	MVKTraceVulkanCallEnd();
-	return VK_SUCCESS;
-}
 
-MVK_PUBLIC_VULKAN_SYMBOL VkResult vkGetCalibratedTimestampsEXT(
-	VkDevice									device,
-	uint32_t									timestampCount,
-	const VkCalibratedTimestampInfoEXT*			pTimestampInfos,
-	uint64_t*									pTimestamps,
-	uint64_t*									pMaxDeviation) {
-	MVKTraceVulkanCallStart();
-	MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
-	mvkDev->getCalibratedTimestamps(timestampCount, pTimestampInfos, pTimestamps, pMaxDeviation);
-	MVKTraceVulkanCallEnd();
-	return VK_SUCCESS;
-}
+MVK_PUBLIC_VULKAN_ALIAS(vkGetCalibratedTimestampsEXT, vkGetCalibratedTimestampsKHR);
+MVK_PUBLIC_VULKAN_ALIAS(vkGetPhysicalDeviceCalibrateableTimeDomainsEXT, vkGetPhysicalDeviceCalibrateableTimeDomainsKHR);
 
 
 #pragma mark -