src/ktx/libktx/vkloader.c
/**
 * @internal
 * @~English
 * @brief Callback for linear tiled textures with possible source row
 *        padding.
 *
 * Need to use this long method as row padding is different
 * between KTX (pad to 4) and Vulkan (none).
 *
 * In theory this should work for the no-padding case too but it is much
 * clearer and a bit faster to use the simple callback above. It also avoids
 * potential Vulkan implementation bugs.
 *
 * I have seen weird subResLayout results with a BC2_UNORM texture in the only
 * real Vulkan implementation I have available (Mesa). The reported row & image
 * strides appears to be for an R8G8B8A8_UNORM of the same texel size.
 */
@internal
@~English
@brief Callback for linear tiled textures with possible source row
padding.

Need to use this long method as row padding is different
between KTX (pad to 4) and Vulkan (none).

In theory this should work for the no-padding case too but it is much
clearer and a bit faster to use the simple callback above. It also avoids
potential Vulkan implementation bugs.

I have seen weird subResLayout results with a BC2_UNORM texture in the only
real Vulkan implementation I have available (Mesa). The reported row & image
strides appears to be for an R8G8B8A8_UNORM of the same texel size.
@internal @~English @brief Callback for linear tiled textures with possible source row padding . Need to use this long method as row padding is different between KTX ( pad to 4 ) and Vulkan ( none ) . In theory this should work for the no - padding case too but it is much clearer and a bit faster to use the simple callback above . It also avoids potential Vulkan implementation bugs . I have seen weird subResLayout results with a BC2_UNORM texture in the only real Vulkan implementation I have available ( Mesa ) . The reported row & image strides appears to be for an R8G8B8A8_UNORM of the same texel size .
KTX_error_code
linearTilingPadCallback(int miplevel, int face,
                      int width, int height, int depth,
                      ktx_uint64_t faceLodSize,
                      void* pixels, void* userdata)
{
    user_cbdata_linear* ud = (user_cbdata_linear*)userdata;
    VkSubresourceLayout subResLayout;
    VkImageSubresource subRes = {
      .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
      .mipLevel = miplevel,
      .arrayLayer = face
    };
    VkDeviceSize offset;
    ktx_size_t   imageSize = 0;
    VkDeviceSize imagePitch = 0;
    ktx_uint32_t srcRowPitch;
    ktx_uint32_t rowIterations;
    ktx_uint32_t imageIterations;
    ktx_uint32_t row, image;
    ktx_uint8_t* pSrc;
    ktx_size_t   copySize;
    vkGetImageSubresourceLayout(ud->device, ud->destImage, &subRes,
                                &subResLayout);
    srcRowPitch = ktxTexture_GetRowPitch(ud->texture, miplevel);
    if (subResLayout.rowPitch != srcRowPitch)
        rowIterations = height;
    else
        rowIterations = 1;
    imageIterations = 1;
    if (ud->texture->numLayers > 1 || ud->texture->numDimensions == 3) {
        imageSize = ktxTexture_GetImageSize(ud->texture, miplevel);
        if (ud->texture->numLayers > 1) {
            imagePitch = subResLayout.arrayPitch;
            if (imagePitch != imageSize)
                imageIterations
                        = ud->texture->numLayers * ud->texture->numFaces;
        } else {
            imagePitch = subResLayout.depthPitch;
            if (imagePitch != imageSize)
                imageIterations = depth;
        }
        assert(imageSize <= imagePitch);
    }
    if (rowIterations > 1) {
        if (subResLayout.rowPitch < srcRowPitch)
            copySize = subResLayout.rowPitch;
        else
            copySize = srcRowPitch;
    } else if (imageIterations > 1)
        copySize = faceLodSize / imageIterations;
    else
        copySize = faceLodSize;
    offset = subResLayout.offset;
    for (image = 0; image < imageIterations; image++) {
        pSrc = (ktx_uint8_t*)pixels + imageSize * image;
        for (row = 0; row < rowIterations; row++) {
            memcpy(ud->dest + offset, pSrc, copySize);
            offset += subResLayout.rowPitch;
            pSrc += srcRowPitch;
          }
        offset += imagePitch;
    }
    return KTX_SUCCESS;
}
KTX_error_code linearTilingPadCallback ( int miplevel , int face , int width , int height , int depth , ktx_uint64_t faceLodSize , void * pixels , void * userdata ) { user_cbdata_linear * ud = ( user_cbdata_linear * ) userdata ; VkSubresourceLayout subResLayout ; VkImageSubresource subRes = { . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT , . mipLevel = miplevel , . arrayLayer = face } ; VkDeviceSize offset ; ktx_size_t imageSize = 0 ; VkDeviceSize imagePitch = 0 ; ktx_uint32_t srcRowPitch ; ktx_uint32_t rowIterations ; ktx_uint32_t imageIterations ; ktx_uint32_t row , image ; ktx_uint8_t * pSrc ; ktx_size_t copySize ; vkGetImageSubresourceLayout ( ud -> device , ud -> destImage , & subRes , & subResLayout ) ; srcRowPitch = ktxTexture_GetRowPitch ( ud -> texture , miplevel ) ; if ( subResLayout . rowPitch != srcRowPitch ) rowIterations = height ; else rowIterations = 1 ; imageIterations = 1 ; if ( ud -> texture -> numLayers > 1 || ud -> texture -> numDimensions == 3 ) { imageSize = ktxTexture_GetImageSize ( ud -> texture , miplevel ) ; if ( ud -> texture -> numLayers > 1 ) { imagePitch = subResLayout . arrayPitch ; if ( imagePitch != imageSize ) imageIterations = ud -> texture -> numLayers * ud -> texture -> numFaces ; } else { imagePitch = subResLayout . depthPitch ; if ( imagePitch != imageSize ) imageIterations = depth ; } assert ( imageSize <= imagePitch ) ; } if ( rowIterations > 1 ) { if ( subResLayout . rowPitch < srcRowPitch ) copySize = subResLayout . rowPitch ; else copySize = srcRowPitch ; } else if ( imageIterations > 1 ) copySize = faceLodSize / imageIterations ; else copySize = faceLodSize ; offset = subResLayout . offset ; for ( image = 0 ; image < imageIterations ; image ++ ) { pSrc = ( ktx_uint8_t * ) pixels + imageSize * image ; for ( row = 0 ; row < rowIterations ; row ++ ) { memcpy ( ud -> dest + offset , pSrc , copySize ) ; offset += subResLayout . rowPitch ; pSrc += srcRowPitch ; } offset += imagePitch ; } return KTX_SUCCESS ; }
@internal
 @~English
 @brief Callback for linear tiled textures with possible source row
        padding.
@internal @~English @brief Callback for linear tiled textures with possible source row padding .
// Get sub resources layout. Includes row pitch, size, // offsets, etc. // Arrays, including cube map arrays, or 3D textures // Note from the Vulkan spec: //  *  arrayPitch is undefined for images that were not //     created as arrays. //  *  depthPitch is defined only for 3D images. // Copy the minimum of srcRowPitch, the GL_UNPACK_ALIGNMENT padded size, // and subResLayout.rowPitch. // Copy image data to destImage via its mapped memory.