@@ -505,7 +505,47 @@ DkGpuAddr dkImageGetGpuAddr(DkImage const* obj)
505505
506506void dkCmdBufCopyImage (DkCmdBuf obj, DkImageView const * srcView, DkImageRect const * srcRect, DkImageView const * dstView, DkImageRect const * dstRect, uint32_t flags)
507507{
508- DK_ENTRYPOINT_NOT_IMPLEMENTED (obj);
508+ DK_ENTRYPOINT (obj);
509+
510+ ImageInfo srcInfo, dstInfo;
511+ srcInfo.fromImageView (srcView, ImageInfo::TransferCopy);
512+ dstInfo.fromImageView (dstView, ImageInfo::TransferCopy);
513+
514+ [[maybe_unused]] const bool isSrcTexCompressed = srcView->pImage ->m_blockW > 1 ;
515+ [[maybe_unused]] const bool isDstTexCompressed = dstView->pImage ->m_blockW > 1 ;
516+ DK_DEBUG_BAD_INPUT (isSrcTexCompressed != isDstTexCompressed, " mismatched compression attributes" );
517+ DK_DEBUG_BAD_INPUT (isSrcTexCompressed && srcInfo.m_format != dstInfo.m_format , " compression formats must match" );
518+
519+ DK_DEBUG_BAD_INPUT (!srcRect || !srcRect->width || !srcRect->height || !srcRect->depth , " invalid srcRect" );
520+ DK_DEBUG_BAD_INPUT (srcRect->x + srcRect->width > srcView->pImage ->m_dimensions [0 ], " srcRect x/width out of bounds" );
521+ DK_DEBUG_BAD_INPUT (srcRect->y + srcRect->height > srcView->pImage ->m_dimensions [1 ], " srcRect y/height out of bounds" );
522+ DK_DEBUG_BAD_INPUT (srcRect->z + srcRect->depth > srcInfo.m_arrayMode , " srcRect z/depth out of bounds" );
523+
524+ DK_DEBUG_BAD_INPUT (!dstRect || !dstRect->width || !dstRect->height || !dstRect->depth , " invalid dstRect" );
525+ DK_DEBUG_BAD_INPUT (dstRect->x + dstRect->width > dstView->pImage ->m_dimensions [0 ], " dstRect x/width out of bounds" );
526+ DK_DEBUG_BAD_INPUT (dstRect->y + dstRect->height > dstView->pImage ->m_dimensions [1 ], " dstRect y/height out of bounds" );
527+ DK_DEBUG_BAD_INPUT (dstRect->z + dstRect->depth > dstInfo.m_arrayMode , " dstRect z/depth out of bounds" );
528+
529+ DK_DEBUG_BAD_INPUT (srcRect->width != dstRect->width , " srcRect/dstRect width must match" );
530+ DK_DEBUG_BAD_INPUT (srcRect->height != dstRect->height , " srcRect/dstRect height must match" );
531+ DK_DEBUG_BAD_INPUT (srcRect->depth != dstRect->depth , " srcRect/dstRect depth must match" );
532+
533+ BlitParams params;
534+ params.srcX = srcRect->x ;
535+ params.srcY = srcRect->y ;
536+ params.dstX = dstRect->x ;
537+ params.dstY = dstRect->y ;
538+ params.width = srcRect->width ;
539+ params.height = srcRect->height ;
540+
541+ for (uint32_t z = 0 ; z < dstRect->depth ; z ++)
542+ {
543+ uint32_t srcZ = z;
544+ uint32_t dstZ = dstRect->z + z;
545+ if (flags & DkBlitFlag_FlipZ)
546+ srcZ = dstRect->depth - z - 1 ;
547+ BlitCopyEngine (obj, srcInfo, dstInfo, params, srcZ, dstZ);
548+ }
509549}
510550
511551void dkCmdBufBlitImage (DkCmdBuf obj, DkImageView const * srcView, DkImageRect const * srcRect, DkImageView const * dstView, DkImageRect const * dstRect, uint32_t flags, uint32_t factor)
@@ -769,5 +809,118 @@ void dkCmdBufCopyBufferToImage(DkCmdBuf obj, DkCopyBuf const* src, DkImageView c
769809
770810void dkCmdBufCopyImageToBuffer (DkCmdBuf obj, DkImageView const * srcView, DkImageRect const * srcRect, DkCopyBuf const * dst, uint32_t flags)
771811{
772- DK_ENTRYPOINT_NOT_IMPLEMENTED (obj);
812+ DK_ENTRYPOINT (obj);
813+
814+ ImageInfo srcInfo;
815+ srcInfo.fromImageView (srcView, ImageInfo::TransferCopy);
816+
817+ DK_DEBUG_BAD_INPUT (!dst || dst->addr == DK_GPU_ADDR_INVALID, " invalid dst" );
818+ DK_DEBUG_BAD_INPUT (!srcRect || !srcRect->width || !srcRect->height || !srcRect->depth , " invalid dstView" );
819+ DK_DEBUG_BAD_INPUT (srcRect->x + srcRect->width > srcView->pImage ->m_dimensions [0 ], " srcRect x/width out of bounds" );
820+ DK_DEBUG_BAD_INPUT (srcRect->y + srcRect->height > srcView->pImage ->m_dimensions [1 ], " srcRect y/height out of bounds" );
821+ DK_DEBUG_BAD_INPUT (srcRect->z + srcRect->depth > srcInfo.m_arrayMode , " srcRect z/depth out of bounds" );
822+
823+ BlitParams params;
824+ params.srcX = srcRect->x ;
825+ params.srcY = srcRect->y ;
826+ params.dstX = 0 ;
827+ params.dstY = 0 ;
828+ params.width = srcRect->width ;
829+ params.height = srcRect->height ;
830+
831+ auto & traits = formatTraits[srcView->format ? srcView->format : srcView->pImage ->m_format ];
832+ const bool isCompressed = traits.blockWidth > 1 || traits.blockHeight > 1 ;
833+
834+ if (isCompressed)
835+ {
836+ // Horizontal/vertical flips can't be used with compressed formats for obvious reasons
837+ DK_DEBUG_BAD_FLAGS (flags & (DkBlitFlag_FlipX|DkBlitFlag_FlipY), " cannot use DkBlitFlag_FlipX/FlipY with compressed formats" );
838+
839+ params.srcX = adjustBlockSize (params.srcX , traits.blockWidth );
840+ params.srcY = adjustBlockSize (params.srcY , traits.blockHeight );
841+ params.width = adjustBlockSize (params.width , traits.blockWidth );
842+ params.height = adjustBlockSize (params.height , traits.blockHeight );
843+ }
844+
845+ ImageInfo dstInfo = {};
846+ dstInfo.m_iova = dst->addr ;
847+ dstInfo.m_horizontal = dst->rowLength ? dst->rowLength : params.width *srcInfo.m_bytesPerBlock ;
848+ dstInfo.m_vertical = srcRect->height ;
849+ dstInfo.m_format = srcInfo.m_format ;
850+ dstInfo.m_arrayMode = srcRect->depth ;
851+ dstInfo.m_layerStride = dst->imageHeight ? dst->imageHeight : params.height *dstInfo.m_horizontal ;
852+ dstInfo.m_width = srcRect->width ;
853+ dstInfo.m_height = srcRect->height ;
854+ dstInfo.m_widthMs = dstInfo.m_width ;
855+ dstInfo.m_heightMs = dstInfo.m_height ;
856+ dstInfo.m_bytesPerBlock = srcInfo.m_bytesPerBlock ;
857+ dstInfo.m_isLinear = true ;
858+ dstInfo.m_isLayered = true ;
859+
860+ bool needs2D = false ;
861+ if (flags & (DkBlitFlag_FlipX))
862+ needs2D = true ;
863+
864+ if (needs2D)
865+ {
866+ // Check whether we can really use the 2D engine
867+ DK_DEBUG_BAD_FLAGS (!(srcView->pImage ->m_flags & DkImageFlags_Usage2DEngine), " DkImageFlags_Usage2DEngine required in destination image" );
868+ DK_DEBUG_BAD_FLAGS (!(traits.flags & FormatTraitFlags_CanUse2DEngine), " specified format does not support DkImageFlags_Usage2DEngine" );
869+ DK_DEBUG_DATA_ALIGN (dstInfo.m_iova , DK_IMAGE_LINEAR_STRIDE_ALIGNMENT); // Technically there are ways to work around this by extending width a bit, but w/e
870+ DK_DEBUG_SIZE_ALIGN (dstInfo.m_horizontal , DK_IMAGE_LINEAR_STRIDE_ALIGNMENT);
871+ DK_DEBUG_BAD_INPUT (isCompressed, " cannot use 2D engine with compressed formats" ); // Technically the 2D engine *can* be used with compressed formats, but there isn't really any point in doing so
872+
873+ int dudx = 1 , dvdy = 1 ;
874+
875+ if (flags & DkBlitFlag_FlipX)
876+ {
877+ params.srcX = params.width ;
878+ dudx = -1 ;
879+ }
880+
881+ if (flags & DkBlitFlag_FlipY)
882+ {
883+ params.srcY = params.height ;
884+ dvdy = -1 ;
885+ }
886+
887+ params.srcX = (params.srcX <<SrcFractBits) + (dudx<<(SrcFractBits-1 ));
888+ params.srcY = (params.srcY <<SrcFractBits) + (dvdy<<(SrcFractBits-1 ));
889+ uint32_t blitFlags = Blit2D_SetupEngine | Blit2D_OriginCorner;
890+
891+ if (srcRect->z )
892+ srcInfo.m_iova += srcRect->z * srcInfo.m_layerStride ;
893+
894+ int64_t srcLayerStride = dstInfo.m_layerStride ;
895+ if (flags & DkBlitFlag_FlipZ)
896+ {
897+ srcInfo.m_iova += (srcRect->depth - 1 ) * srcInfo.m_layerStride ;
898+ srcLayerStride = -srcInfo.m_layerStride ;
899+ }
900+
901+ for (uint32_t z = 0 ; z < srcRect->depth ; z ++)
902+ {
903+ Blit2DEngine (obj, srcInfo, dstInfo, params, dudx<<DiffFractBits, dvdy<<DiffFractBits, blitFlags, 0 );
904+ srcInfo.m_iova += srcLayerStride;
905+ dstInfo.m_iova += srcInfo.m_layerStride ;
906+ blitFlags &= ~Blit2D_SetupEngine;
907+ }
908+ }
909+ else
910+ {
911+ if (flags & DkBlitFlag_FlipY)
912+ {
913+ dstInfo.m_iova += (params.height -1 )*dstInfo.m_horizontal ;
914+ dstInfo.m_horizontal = -dstInfo.m_horizontal ;
915+ }
916+
917+ for (uint32_t z = 0 ; z < srcRect->depth ; z ++)
918+ {
919+ uint32_t srcZ = srcRect->z + z;
920+ uint32_t dstZ = z;
921+ if (flags & DkBlitFlag_FlipZ)
922+ srcZ = srcRect->depth - z - 1 ;
923+ BlitCopyEngine (obj, srcInfo, dstInfo, params, srcZ, dstZ);
924+ }
925+ }
773926}
0 commit comments