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
.
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. When copying to a depth aspect, the data in buffer memory must be in the the range [0,1] or undefined results occur.
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; elementSize = <element size of the format of the src/dstImage>; address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * elementSize; 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 size.
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:
imageExtent.width
is not a multiple of the compressed texel
block width, then (imageExtent.width
+ imageOffset.x
)
must equal the image subresource width.
imageExtent.height
is not a multiple of the compressed texel
block height, then (imageExtent.height
+
imageOffset.y
) must equal the image subresource height.
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.