To copy data from a buffer object to an image object, call:
void vkCmdCopyBufferToImage( VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions);
commandBuffer
is the command buffer into which the command will be
recorded.
srcBuffer
is the source buffer.
dstImage
is the destination image.
dstImageLayout
is the layout of the destination image subresources
for the copy.
regionCount
is the number of regions to copy.
pRegions
is a pointer to an array of VkBufferImageCopy
structures specifying the regions to copy.
Each region in pRegions
is copied from the specified region of the
source buffer to the specified region of the destination image.
To copy data from an image object to a buffer object, call:
void vkCmdCopyImageToBuffer( VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions);
commandBuffer
is the command buffer into which the command will be
recorded.
srcImage
is the source image.
srcImageLayout
is the layout of the source image subresources for
the copy.
dstBuffer
is the destination buffer.
regionCount
is the number of regions to copy.
pRegions
is a pointer to an array of VkBufferImageCopy
structures specifying the regions to copy.
Each region in pRegions
is copied from the specified region of the
source image to the specified region of the destination buffer.
For both vkCmdCopyBufferToImage
and vkCmdCopyImageToBuffer
, each
element of pRegions
is a structure defined as:
typedef struct VkBufferImageCopy { VkDeviceSize bufferOffset; uint32_t bufferRowLength; uint32_t bufferImageHeight; VkImageSubresourceLayers imageSubresource; VkOffset3D imageOffset; VkExtent3D imageExtent; } VkBufferImageCopy;
bufferOffset
is the offset in bytes from the start of the
buffer object where the image data is copied from or to.
bufferRowLength
and bufferImageHeight
specify the
data in buffer memory as a subregion of a larger two- or
three-dimensional image, and control the addressing calculations of data
in buffer memory. If either of these values is zero, that aspect of the
buffer memory is considered to be tightly packed according to the
imageExtent
.
imageSubresource
is a VkImageSubresourceLayers
used to
specify the specific image subresources of the image used for the source
or destination image data.
imageOffset
selects the initial x, y, z offsets in texels of the
sub-region of the source or destination image data.
imageExtent
is the size in texels of the image to copy in
width
, height
and depth
. 1D images use only x
and width
. 2D images use x
, y
, width
and
height
. 3D images use x
, y
, z
, width
,
height
and depth
.
When copying to or from a depth or stencil aspect, the data in buffer memory uses a layout that is a (mostly) tightly packed representation of the depth or stencil data. Specifically:
VK_FORMAT_S8_UINT
value per texel.
VK_FORMAT_D16_UNORM
or VK_FORMAT_D16_UNORM_S8_UINT
format is tightly packed with one
VK_FORMAT_D16_UNORM
value per texel.
VK_FORMAT_D32_SFLOAT
or VK_FORMAT_D32_SFLOAT_S8_UINT
format is tightly packed with
one VK_FORMAT_D32_SFLOAT
value per texel.
VK_FORMAT_X8_D24_UNORM_PACK32
or
VK_FORMAT_D24_UNORM_S8_UINT
format is packed with one 32-bit word
per texel with the D24 value in the LSBs of the word, and undefined
values in the eight MSBs.
![]() | Note |
---|---|
To copy both the depth and stencil aspects of a depth/stencil format, two
entries in |
Because depth or stencil aspect buffer to image copies may require format conversions on some implementations, they are not supported on queues that do not support graphics.
Copies are done layer by layer starting with image layer
baseArrayLayer
member of imageSubresource
. layerCount
layers are copied from the source image or to the destination image.
Pseudocode for image/buffer addressing is:
rowLength = region->bufferRowLength; if (rowLength == 0) rowLength = region->imageExtent.width; imageHeight = region->bufferImageHeight; if (imageHeight == 0) imageHeight = region->imageExtent.height; texelSize = <texel size taken from the src/dstImage>; address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelSize; where x,y,z range from (0,0,0) to region->imageExtent.{width,height,depth}.
Note that imageOffset
does not affect addressing calculations for
buffer memory. Instead, bufferOffset
can be used to
select the starting address in buffer memory.
For block-compression formats, all parameters are still specified in texels rather than compressed texel blocks, but the addressing math operates on whole compressed texel blocks. Pseudocode for compressed copy addressing is:
rowLength = region->bufferRowLength; if (rowLength == 0) rowLength = region->imageExtent.width; imageHeight = region->bufferImageHeight; if (imageHeight == 0) imageHeight = region->imageExtent.height; compressedTexelBlockSizeInBytes = <compressed texel block size taken from the src/dstImage>; rowLength /= compressedTexelBlockWidth; imageHeight /= compressedTexelBlockHeight; address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * compressedTexelBlockSizeInBytes; where x,y,z range from (0,0,0) to region->imageExtent.{width/compressedTexelBlockWidth,height/compressedTexelBlockHeight,depth/compressedTexelBlockDepth}.
Copying to or from block-compressed images is typically done in multiples of
the compressed texel block. For this reason the imageExtent
must be a
multiple of the compressed texel block dimension. There is one exception to
this rule which is required to handle compressed images created with
dimensions that are not a multiple of the compressed texel block dimensions.
If imageExtent.width
is not a multiple of the compressed texel block
width then (imageExtent.width
+ imageOffset.x
) must equal the
image subresource width, if imageExtent.height
is not a multiple of
the compressed texel block height then (imageExtent.height
imageOffset.y
) must equal the image subresource height and if
imageExtent.depth
is not a multiple of the compressed texel block
depth then (imageExtent.depth
+ imageOffset.z
) must equal the
image subresource depth. This allows the last compressed texel block of the
image in each non-multiple dimension to be included as a source or
destination of the copy.