@@ -102,15 +102,26 @@ static inline MTLSize mvkClampMTLSize(MTLSize size, MTLOrigin origin, MTLSize ma
102
102
return VK_SUCCESS;
103
103
}
104
104
105
+ static inline MTLPixelFormat getDepthStencilAspectFormat (const MTLPixelFormat format, const VkImageAspectFlags aspectMask) {
106
+ if (format == MTLPixelFormatDepth32Float_Stencil8 ) {
107
+ if (aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) return MTLPixelFormatDepth32Float ;
108
+ if (aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) return MTLPixelFormatStencil8 ;
109
+ }
110
+ return format;
111
+ }
112
+
105
113
template <size_t N>
106
114
inline VkResult MVKCmdCopyImage<N>::validate(MVKCommandBuffer* cmdBuff, const VkImageCopy2* region) {
107
115
uint8_t srcPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags (region->srcSubresource .aspectMask );
108
116
uint8_t dstPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags (region->dstSubresource .aspectMask );
109
117
118
+ auto srcFormat = getDepthStencilAspectFormat (_srcImage->getMTLPixelFormat (srcPlaneIndex), region->srcSubresource .aspectMask );
119
+ auto dstFormat = getDepthStencilAspectFormat (_dstImage->getMTLPixelFormat (dstPlaneIndex), region->dstSubresource .aspectMask );
120
+
110
121
// Validate
111
122
MVKPixelFormats* pixFmts = cmdBuff->getPixelFormats ();
112
123
if ((_dstImage->getSampleCount () != _srcImage->getSampleCount ()) ||
113
- (pixFmts->getBytesPerBlock (_dstImage-> getMTLPixelFormat (dstPlaneIndex)) != pixFmts->getBytesPerBlock (_srcImage-> getMTLPixelFormat (srcPlaneIndex) ))) {
124
+ (pixFmts->getBytesPerBlock (srcFormat) != pixFmts->getBytesPerBlock (dstFormat ))) {
114
125
return cmdBuff->reportError (VK_ERROR_FEATURE_NOT_PRESENT, " vkCmdCopyImage(): Cannot copy between incompatible formats, such as formats of different pixel sizes, or between images with different sample counts." );
115
126
}
116
127
return VK_SUCCESS;
@@ -133,17 +144,20 @@ static inline MTLSize mvkClampMTLSize(MTLSize size, MTLOrigin origin, MTLSize ma
133
144
134
145
MTLPixelFormat srcMTLPixFmt = _srcImage->getMTLPixelFormat (srcPlaneIndex);
135
146
bool isSrcCompressed = _srcImage->getIsCompressed ();
147
+ bool isSrcCombinedDepthStencil = srcMTLPixFmt == MTLPixelFormatDepth32Float_Stencil8 ;
136
148
bool canReinterpretSrc = _srcImage->hasPixelFormatView (srcPlaneIndex);
137
149
138
150
MTLPixelFormat dstMTLPixFmt = _dstImage->getMTLPixelFormat (dstPlaneIndex);
139
151
bool isDstCompressed = _dstImage->getIsCompressed ();
152
+ bool isDstCombinedDepthStencil = dstMTLPixFmt == MTLPixelFormatDepth32Float_Stencil8 ;
140
153
bool canReinterpretDst = _dstImage->hasPixelFormatView (dstPlaneIndex);
141
154
142
155
bool isEitherCompressed = isSrcCompressed || isDstCompressed;
156
+ bool isOneCombinedDepthStencil = isSrcCombinedDepthStencil != isDstCombinedDepthStencil;
143
157
bool canReinterpret = canReinterpretSrc || canReinterpretDst;
144
158
145
159
// If source and destination can't be reinterpreted to matching formats use a temporary intermediary buffer
146
- bool useTempBuffer = (srcMTLPixFmt != dstMTLPixFmt) && (isEitherCompressed || !canReinterpret);
160
+ bool useTempBuffer = (srcMTLPixFmt != dstMTLPixFmt) && (isEitherCompressed || isOneCombinedDepthStencil || !canReinterpret);
147
161
148
162
if (useTempBuffer) {
149
163
// Add copy from source image to temp buffer.
@@ -459,7 +473,6 @@ static inline MTLSize mvkClampMTLSize(MTLSize size, MTLOrigin origin, MTLSize ma
459
473
460
474
template <size_t N>
461
475
void MVKCmdBlitImage<N>::encode(MVKCommandEncoder* cmdEncoder, MVKCommandUse commandUse) {
462
-
463
476
auto & mtlFeats = cmdEncoder->getMetalFeatures ();
464
477
size_t vkIBCnt = _vkImageBlits.size ();
465
478
VkImageCopy vkImageCopies[vkIBCnt];
@@ -587,11 +600,23 @@ static inline MTLSize mvkClampMTLSize(MTLSize size, MTLOrigin origin, MTLSize ma
587
600
588
601
bool isLayeredBlit = blitKey.dstSampleCount > 1 ? mtlFeats.multisampleLayeredRendering : mtlFeats.layeredRendering ;
589
602
590
- uint32_t layCnt = mvkIBR.region .srcSubresource .layerCount == VK_REMAINING_ARRAY_LAYERS ?
603
+ uint32_t srcLayCnt = mvkIBR.region .srcSubresource .layerCount == VK_REMAINING_ARRAY_LAYERS ?
591
604
_srcImage->getLayerCount () - mvkIBR.region .srcSubresource .baseArrayLayer :
592
605
mvkIBR.region .srcSubresource .layerCount ;
606
+ uint32_t dstLayCnt = mvkIBR.region .dstSubresource .layerCount == VK_REMAINING_ARRAY_LAYERS ?
607
+ _dstImage->getLayerCount () - mvkIBR.region .dstSubresource .baseArrayLayer :
608
+ mvkIBR.region .dstSubresource .layerCount ;
609
+ uint32_t layCnt;
610
+ // If either image is 3D, the difference in z offset must:
611
+ // - Equal the difference in z offset of the other subresource, if it is also 3D.
612
+ // - Equal the number of layers in the other subresource, if it is not 3D.
613
+ // Otherwise, the number of layers should be the same.
593
614
if (_dstImage->getMTLTextureType () == MTLTextureType3D ) {
594
615
layCnt = mvkAbsDiff (mvkIBR.region .dstOffsets [1 ].z , mvkIBR.region .dstOffsets [0 ].z );
616
+ } else if (blitKey.srcMTLTextureType == MTLTextureType3D ) {
617
+ layCnt = mvkAbsDiff (mvkIBR.region .srcOffsets [1 ].z , mvkIBR.region .srcOffsets [0 ].z );
618
+ } else {
619
+ layCnt = srcLayCnt;
595
620
}
596
621
if (isLayeredBlit) {
597
622
// In this case, I can blit all layers at once with a layered draw.
@@ -629,14 +654,19 @@ static inline MTLSize mvkClampMTLSize(MTLSize size, MTLOrigin origin, MTLSize ma
629
654
// In this case, I need to interpolate along the third dimension manually.
630
655
VkExtent3D srcExtent = _srcImage->getExtent3D (srcPlaneIndex, mvkIBR.region .dstSubresource .mipLevel );
631
656
VkOffset3D so0 = mvkIBR.region .srcOffsets [0 ], so1 = mvkIBR.region .srcOffsets [1 ];
632
- VkOffset3D do0 = mvkIBR.region .dstOffsets [0 ], do1 = mvkIBR.region .dstOffsets [1 ];
657
+ // If the dst is also 3D use the z offsets, otherwise use the layers.
658
+ float do0z = mvkIBR.region .dstOffsets [0 ].z , do1z = mvkIBR.region .dstOffsets [1 ].z ;
659
+ if (_dstImage->getMTLTextureType () != MTLTextureType3D ) {
660
+ do0z = mvkIBR.region .dstSubresource .baseArrayLayer ;
661
+ do1z = do0z + dstLayCnt;
662
+ }
633
663
float startZ = (float )so0.z / (float )srcExtent.depth ;
634
664
float endZ = (float )so1.z / (float )srcExtent.depth ;
635
- if (isLayeredBlit && do0. z > do1. z ) {
665
+ if (isLayeredBlit && do0z > do1z ) {
636
666
// Swap start and end points so interpolation moves in the right direction.
637
667
std::swap (startZ, endZ);
638
668
}
639
- zIncr = (endZ - startZ) / mvkAbsDiff (do1. z , do0. z );
669
+ zIncr = (endZ - startZ) / mvkAbsDiff (do1z, do0z );
640
670
float z = startZ + (isLayeredBlit ? 0.0 : (layIdx + 0.5 )) * zIncr;
641
671
for (uint32_t i = 0 ; i < kMVKBlitVertexCount ; ++i) {
642
672
mvkIBR.vertices [i].texCoord .z = z;
0 commit comments