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.
This commit is contained in:
Chip Davis 2020-09-19 02:12:26 -05:00
parent f3eda6218e
commit 400781e950
4 changed files with 25 additions and 7 deletions

View File

@ -2986,11 +2986,7 @@ VkDeviceSize MVKDevice::getVkFormatTexelBufferAlignment(VkFormat format, MVKBase
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];
}

View File

@ -537,14 +537,16 @@ VkExtent3D MVKImage::getExtent3D(uint8_t planeIndex, uint32_t mipLevel) {
}
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,

View File

@ -256,6 +256,9 @@ public:
/** 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]);

View File

@ -250,6 +250,23 @@ SPIRV_CROSS_NAMESPACE::MSLFormatResolution MVKPixelFormats::getChromaSubsampling
: 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);