diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index ca24eb19..7ac270a7 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -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]; } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index 5407e263..72bde4e0 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -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, diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h index e87063e0..c75ec09f 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h @@ -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]); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm index f758b4a4..7d71cbe7 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm @@ -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);