MVKCmdCopyImage: Support copies between 3D and 2D images.

This can be done by copying between each slice of the 2D image and each
plane of the 3D image individually.

This was actually quite simple to implement. I don't know why I punted
on this.
This commit is contained in:
Chip Davis 2020-09-12 15:55:41 -05:00
parent 061f4ee6c5
commit fa862c46a3

View File

@ -77,11 +77,6 @@ VkResult MVKCmdCopyImage<N>::setContent(MVKCommandBuffer* cmdBuff,
_vkImageCopies.push_back(vkIR);
}
// Validate
if ((_srcImage->getMTLTextureType() == MTLTextureType3D) != (_dstImage->getMTLTextureType() == MTLTextureType3D)) {
return cmdBuff->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdCopyImage(): Metal does not support copying to or from slices of a 3D texture.");
}
return VK_SUCCESS;
}
@ -160,25 +155,62 @@ void MVKCmdCopyImage<N>::encode(MVKCommandEncoder* cmdEncoder, MVKCommandUse com
// If copies can be performed using direct texture-texture copying, do so
uint32_t srcLevel = vkIC.srcSubresource.mipLevel;
MTLOrigin srcOrigin = mvkMTLOriginFromVkOffset3D(vkIC.srcOffset);
MTLSize srcSize = mvkClampMTLSize(mvkMTLSizeFromVkExtent3D(vkIC.extent),
srcOrigin,
mvkMTLSizeFromVkExtent3D(_srcImage->getExtent3D(srcPlaneIndex, srcLevel)));
MTLSize srcSize;
uint32_t layCnt;
if ((_srcImage->getMTLTextureType() == MTLTextureType3D) != (_dstImage->getMTLTextureType() == MTLTextureType3D)) {
// In the case, the number of layers to copy is in extent.depth. Use that value,
// then clamp the depth so we don't try to copy more than Metal will allow.
layCnt = vkIC.extent.depth;
srcSize = mvkClampMTLSize(mvkMTLSizeFromVkExtent3D(vkIC.extent),
srcOrigin,
mvkMTLSizeFromVkExtent3D(_srcImage->getExtent3D(srcPlaneIndex, srcLevel)));
srcSize.depth = 1;
} else {
layCnt = vkIC.srcSubresource.layerCount;
srcSize = mvkClampMTLSize(mvkMTLSizeFromVkExtent3D(vkIC.extent),
srcOrigin,
mvkMTLSizeFromVkExtent3D(_srcImage->getExtent3D(srcPlaneIndex, srcLevel)));
}
uint32_t dstLevel = vkIC.dstSubresource.mipLevel;
MTLOrigin dstOrigin = mvkMTLOriginFromVkOffset3D(vkIC.dstOffset);
uint32_t srcBaseLayer = vkIC.srcSubresource.baseArrayLayer;
uint32_t dstBaseLayer = vkIC.dstSubresource.baseArrayLayer;
uint32_t layCnt = vkIC.srcSubresource.layerCount;
for (uint32_t layIdx = 0; layIdx < layCnt; layIdx++) {
[mtlBlitEnc copyFromTexture: srcMTLTex
sourceSlice: srcBaseLayer + layIdx
sourceLevel: srcLevel
sourceOrigin: srcOrigin
sourceSize: srcSize
toTexture: dstMTLTex
destinationSlice: dstBaseLayer + layIdx
destinationLevel: dstLevel
destinationOrigin: dstOrigin];
// We can copy between a 3D and a 2D image easily. Just copy between
// one slice of the 2D image and one plane of the 3D image at a time.
if ((_srcImage->getMTLTextureType() == MTLTextureType3D) == (_dstImage->getMTLTextureType() == MTLTextureType3D)) {
[mtlBlitEnc copyFromTexture: srcMTLTex
sourceSlice: srcBaseLayer + layIdx
sourceLevel: srcLevel
sourceOrigin: srcOrigin
sourceSize: srcSize
toTexture: dstMTLTex
destinationSlice: dstBaseLayer + layIdx
destinationLevel: dstLevel
destinationOrigin: dstOrigin];
} else if (_srcImage->getMTLTextureType() == MTLTextureType3D) {
[mtlBlitEnc copyFromTexture: srcMTLTex
sourceSlice: srcBaseLayer
sourceLevel: srcLevel
sourceOrigin: MTLOriginMake(srcOrigin.x, srcOrigin.y, srcOrigin.z + layIdx)
sourceSize: srcSize
toTexture: dstMTLTex
destinationSlice: dstBaseLayer + layIdx
destinationLevel: dstLevel
destinationOrigin: dstOrigin];
} else {
assert(_dstImage->getMTLTextureType() == MTLTextureType3D);
[mtlBlitEnc copyFromTexture: srcMTLTex
sourceSlice: srcBaseLayer + layIdx
sourceLevel: srcLevel
sourceOrigin: srcOrigin
sourceSize: srcSize
toTexture: dstMTLTex
destinationSlice: dstBaseLayer
destinationLevel: dstLevel
destinationOrigin: MTLOriginMake(dstOrigin.x, dstOrigin.y, dstOrigin.z + layIdx)];
}
}
}
}