MVKImage: Use the plane's MTLPixelFormat to calculate memory sizes.

We really don't want to use the `VkFormat` for the whole image. That has
a block size set on it, which causes the size to be reduced by a factor
of two or even four, in the case of a 420 format whose pitch exceeds the
required alignment. If instead we use the plane `MTLPixelFormat`, we can
sidestep that.
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index ca24eb1..7ac270a 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -2986,11 +2986,7 @@
 		if (mvkPixFmts->getChromaSubsamplingPlaneCount(format) >= 2) {
 			// Use plane 1 to get the alignment requirements. In a 2-plane format, this will
 			// typically have stricter alignment requirements due to it being a 2-component format.
-			VkExtent2D blockTexelSize[3];
-			uint32_t bytesPerBlock[3];
-			MTLPixelFormat planePixFmts[3];
-			mvkPixFmts->getChromaSubsamplingPlanes(format, blockTexelSize, bytesPerBlock, planePixFmts);
-			mtlPixFmt = planePixFmts[1];
+			mtlPixFmt = mvkPixFmts->getChromaSubsamplingPlaneMTLPixelFormat(format, 1);
 		}
 		deviceAlignment = [mtlDev minimumLinearTextureAlignmentForPixelFormat: mtlPixFmt];
 	}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index 5407e26..72bde4e 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -537,14 +537,16 @@
 }
 
 VkDeviceSize MVKImage::getBytesPerRow(uint8_t planeIndex, uint32_t mipLevel) {
-    size_t bytesPerRow = getPixelFormats()->getBytesPerRow(_vkFormat, getExtent3D(planeIndex, mipLevel).width);
+    MTLPixelFormat planeMTLPixFmt = getPixelFormats()->getChromaSubsamplingPlaneMTLPixelFormat(_vkFormat, planeIndex);
+    size_t bytesPerRow = getPixelFormats()->getBytesPerRow(planeMTLPixFmt, getExtent3D(planeIndex, mipLevel).width);
     return mvkAlignByteCount(bytesPerRow, _rowByteAlignment);
 }
 
 VkDeviceSize MVKImage::getBytesPerLayer(uint8_t planeIndex, uint32_t mipLevel) {
+    MTLPixelFormat planeMTLPixFmt = getPixelFormats()->getChromaSubsamplingPlaneMTLPixelFormat(_vkFormat, planeIndex);
     VkExtent3D extent = getExtent3D(planeIndex, mipLevel);
     size_t bytesPerRow = getBytesPerRow(planeIndex, mipLevel);
-    return getPixelFormats()->getBytesPerLayer(_vkFormat, bytesPerRow, extent.height);
+    return getPixelFormats()->getBytesPerLayer(planeMTLPixFmt, bytesPerRow, extent.height);
 }
 
 VkResult MVKImage::getSubresourceLayout(const VkImageSubresource* pSubresource,
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h
index e87063e..c75ec09 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h
@@ -256,6 +256,9 @@
 	/** Returns the MSLFormatResolution of the specified chroma-subsampling (YCbCr) VkFormat */
 	SPIRV_CROSS_NAMESPACE::MSLFormatResolution getChromaSubsamplingResolution(VkFormat vkFormat);
 
+	/** Returns the MTLPixelFormat of the specified chroma-subsampling (YCbCr) VkFormat for the specified plane. */
+	MTLPixelFormat getChromaSubsamplingPlaneMTLPixelFormat(VkFormat vkFormat, uint8_t planeIndex);
+
     /** Returns the number of planes, blockTexelSize,  bytesPerBlock and mtlPixFmt of each plane of the specified chroma-subsampling (YCbCr) VkFormat into the given arrays */
     uint8_t getChromaSubsamplingPlanes(VkFormat vkFormat, VkExtent2D blockTexelSize[3], uint32_t bytesPerBlock[3], MTLPixelFormat mtlPixFmt[3]);
 
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
index f758b4a..7d71cbe 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
@@ -250,6 +250,23 @@
                                        : SPIRV_CROSS_NAMESPACE::MSL_FORMAT_RESOLUTION_420;
 }
 
+MTLPixelFormat MVKPixelFormats::getChromaSubsamplingPlaneMTLPixelFormat(VkFormat vkFormat, uint8_t planeIndex) {
+    uint8_t planes = getChromaSubsamplingPlaneCount(vkFormat);
+    uint8_t bits = getChromaSubsamplingComponentBits(vkFormat);
+    switch(planes) {
+        default:
+        case 1:
+            return getMTLPixelFormat(vkFormat);
+        case 2:
+            if (planeIndex == 1) {
+                return (bits == 8) ? MTLPixelFormatRG8Unorm : MTLPixelFormatRG16Unorm;
+            }
+            /* fallthrough */
+        case 3:
+            return (bits == 8) ? MTLPixelFormatR8Unorm : MTLPixelFormatR16Unorm;
+    }
+}
+
 uint8_t MVKPixelFormats::getChromaSubsamplingPlanes(VkFormat vkFormat, VkExtent2D blockTexelSize[3], uint32_t bytesPerBlock[3], MTLPixelFormat mtlPixFmt[3]) {
     uint8_t planes = getChromaSubsamplingPlaneCount(vkFormat);
     uint8_t bits = getChromaSubsamplingComponentBits(vkFormat);