复制命令
应用程序可以使用本章中描述的几种方法复制缓冲区和图像数据,具体取决于数据传输的类型。
所有复制命令都被视为同步屏障的“传输”操作。
所有源格式在其格式描述中具有 X 分量的复制命令都将从这些位读取未定义的值。
所有目标格式在其格式描述中具有 X 分量的复制命令都将向这些位写入未定义的值。
在缓冲区之间复制数据
要在缓冲区对象之间复制数据,请调用
// Provided by VK_VERSION_1_0
void vkCmdCopyBuffer(
VkCommandBuffer commandBuffer,
VkBuffer srcBuffer,
VkBuffer dstBuffer,
uint32_t regionCount,
const VkBufferCopy* pRegions);
-
commandBuffer
是将记录命令的命令缓冲区。 -
srcBuffer
是源缓冲区。 -
dstBuffer
是目标缓冲区。 -
regionCount
是要复制的区域数。 -
pRegions
是指向指定要复制的区域的 VkBufferCopy 结构数组的指针。
pRegions
指定的每个源区域都从源缓冲区复制到目标缓冲区的目标区域。如果 srcBuffer
中指定的任何区域在内存中与 dstBuffer
中指定的任何区域重叠,则从这些重叠区域读取的值是未定义的。
VkBufferCopy
结构定义为
// Provided by VK_VERSION_1_0
typedef struct VkBufferCopy {
VkDeviceSize srcOffset;
VkDeviceSize dstOffset;
VkDeviceSize size;
} VkBufferCopy;
-
srcOffset
是从srcBuffer
开头起的起始偏移量(以字节为单位)。 -
dstOffset
是从dstBuffer
开头起的起始偏移量(以字节为单位)。 -
size
是要复制的字节数。
下面定义了复制缓冲区命令的更可扩展的版本。
要在缓冲区对象之间复制数据,请调用
// Provided by VK_VERSION_1_3
void vkCmdCopyBuffer2(
VkCommandBuffer commandBuffer,
const VkCopyBufferInfo2* pCopyBufferInfo);
或等效的命令
// Provided by VK_KHR_copy_commands2
void vkCmdCopyBuffer2KHR(
VkCommandBuffer commandBuffer,
const VkCopyBufferInfo2* pCopyBufferInfo);
-
commandBuffer
是将记录命令的命令缓冲区。 -
pCopyBufferInfo
是指向描述复制参数的 VkCopyBufferInfo2 结构的指针。
由 pCopyBufferInfo->pRegions
指定的每个源区域都从源缓冲区复制到目标缓冲区的目标区域。如果 pCopyBufferInfo->srcBuffer
中指定的任何区域在内存中与 pCopyBufferInfo->dstBuffer
中指定的任何区域重叠,则从这些重叠区域读取的值是未定义的。
VkCopyBufferInfo2
结构定义为
// Provided by VK_VERSION_1_3
typedef struct VkCopyBufferInfo2 {
VkStructureType sType;
const void* pNext;
VkBuffer srcBuffer;
VkBuffer dstBuffer;
uint32_t regionCount;
const VkBufferCopy2* pRegions;
} VkCopyBufferInfo2;
或等效的
// Provided by VK_KHR_copy_commands2
typedef VkCopyBufferInfo2 VkCopyBufferInfo2KHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
srcBuffer
是源缓冲区。 -
dstBuffer
是目标缓冲区。 -
regionCount
是要复制的区域数。 -
pRegions
是指向指定要复制的区域的 VkBufferCopy2 结构数组的指针。
VkBufferCopy2
结构定义如下:
// Provided by VK_VERSION_1_3
typedef struct VkBufferCopy2 {
VkStructureType sType;
const void* pNext;
VkDeviceSize srcOffset;
VkDeviceSize dstOffset;
VkDeviceSize size;
} VkBufferCopy2;
或等效的
// Provided by VK_KHR_copy_commands2
typedef VkBufferCopy2 VkBufferCopy2KHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
srcOffset
是从srcBuffer
开头起的起始偏移量(以字节为单位)。 -
dstOffset
是从dstBuffer
开头起的起始偏移量(以字节为单位)。 -
size
是要复制的字节数。
在图像之间复制数据
要将数据在图像对象之间复制,请调用:
// Provided by VK_VERSION_1_0
void vkCmdCopyImage(
VkCommandBuffer commandBuffer,
VkImage srcImage,
VkImageLayout srcImageLayout,
VkImage dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageCopy* pRegions);
-
commandBuffer
是将记录命令的命令缓冲区。 -
srcImage
是源图像。 -
srcImageLayout
是源图像子资源的当前布局。 -
dstImage
是目标图像。 -
dstImageLayout
是目标图像子资源的当前布局。 -
regionCount
是要复制的区域数。 -
pRegions
是一个指向 VkImageCopy 结构体数组的指针,该数组指定要复制的区域。
由 pRegions
指定的每个源区域都从源图像复制到目标图像的目标区域。如果 srcImage
中指定的任何区域在内存中与 dstImage
中指定的任何区域重叠,则从这些重叠区域读取的值是未定义的。如果任何区域访问 dstImage
中的深度方面,并且未启用 VK_EXT_depth_range_unrestricted
扩展,则从范围 [0,1] 之外的 srcBuffer
复制的值将被写入目标图像,作为未定义的值。
多平面图像只能在每个平面的基础上进行复制,并且在复制到或从这些图像复制时,每个区域中使用的子资源必须仅指定一个平面,但是不同的区域可以指定不同的平面。在复制多平面图像的平面时,所考虑的格式是该平面的兼容格式,而不是多平面图像的格式。
如果目标图像的格式与源图像的格式具有不同的块范围(例如,一个是压缩格式),则为每个指定区域的偏移量和范围将根据每个格式的块范围进行缩放以匹配大小。每个图像的复制区域必须与每个维度中的纹素块范围的倍数对齐,但在图像的边缘,区域范围必须与图像的边缘匹配。
图像数据可以在具有不同图像类型的图像之间复制。如果一个图像是 VK_IMAGE_TYPE_3D
,而另一个图像是具有多个图层的 VK_IMAGE_TYPE_2D
,则每个切片都复制到不同的图层或从不同的图层复制;3D 图像中的 depth
切片对应于 2D 图像中的 layerCount
层,2D 图像的有效 depth
为 1
。如果启用了maintenance5
功能,则允许所有其他组合,并且其功能就像1D图像是高度为1的2D图像一样。否则,不允许其他图像类型的组合。
VkImageCopy
结构定义如下
// Provided by VK_VERSION_1_0
typedef struct VkImageCopy {
VkImageSubresourceLayers srcSubresource;
VkOffset3D srcOffset;
VkImageSubresourceLayers dstSubresource;
VkOffset3D dstOffset;
VkExtent3D extent;
} VkImageCopy;
-
srcSubresource
和dstSubresource
是 VkImageSubresourceLayers 结构,分别指定用于源和目标图像数据的图像子资源。 -
srcOffset
和dstOffset
选择源和目标图像数据子区域中纹素的初始x
、y
和z
偏移量。 -
extent
是要复制的图像的纹素大小,包括width
、height
和depth
。
VkImageSubresourceLayers
结构体定义如下:
// Provided by VK_VERSION_1_0
typedef struct VkImageSubresourceLayers {
VkImageAspectFlags aspectMask;
uint32_t mipLevel;
uint32_t baseArrayLayer;
uint32_t layerCount;
} VkImageSubresourceLayers;
-
aspectMask
是 VkImageAspectFlagBits 的组合,用于选择要复制的颜色、深度和/或模板方面。 -
mipLevel
是要复制的 mipmap 级别 -
baseArrayLayer
和layerCount
是要复制的起始层和层数。
下面定义了复制图像命令的更可扩展版本。
要将数据在图像对象之间复制,请调用:
// Provided by VK_VERSION_1_3
void vkCmdCopyImage2(
VkCommandBuffer commandBuffer,
const VkCopyImageInfo2* pCopyImageInfo);
或等效的命令
// Provided by VK_KHR_copy_commands2
void vkCmdCopyImage2KHR(
VkCommandBuffer commandBuffer,
const VkCopyImageInfo2* pCopyImageInfo);
-
commandBuffer
是将记录命令的命令缓冲区。 -
pCopyImageInfo
是指向 VkCopyImageInfo2 结构体的指针,该结构体描述了复制参数。
此命令在功能上与 vkCmdCopyImage 相同,但包含可扩展的子结构,其中包括 sType
和 pNext
参数,从而可以更轻松地进行扩展。
VkCopyImageInfo2
结构体定义如下:
// Provided by VK_VERSION_1_3
typedef struct VkCopyImageInfo2 {
VkStructureType sType;
const void* pNext;
VkImage srcImage;
VkImageLayout srcImageLayout;
VkImage dstImage;
VkImageLayout dstImageLayout;
uint32_t regionCount;
const VkImageCopy2* pRegions;
} VkCopyImageInfo2;
或等效的
// Provided by VK_KHR_copy_commands2
typedef VkCopyImageInfo2 VkCopyImageInfo2KHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
srcImage
是源图像。 -
srcImageLayout
是源图像子资源的当前布局。 -
dstImage
是目标图像。 -
dstImageLayout
是目标图像子资源的当前布局。 -
regionCount
是要复制的区域数。 -
pRegions
是指向 VkImageCopy2 结构体数组的指针,该数组指定要复制的区域。
VkImageCopy2
结构定义如下:
// Provided by VK_VERSION_1_3
typedef struct VkImageCopy2 {
VkStructureType sType;
const void* pNext;
VkImageSubresourceLayers srcSubresource;
VkOffset3D srcOffset;
VkImageSubresourceLayers dstSubresource;
VkOffset3D dstOffset;
VkExtent3D extent;
} VkImageCopy2;
或等效的
// Provided by VK_KHR_copy_commands2
typedef VkImageCopy2 VkImageCopy2KHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
srcSubresource
和dstSubresource
是 VkImageSubresourceLayers 结构,分别指定用于源和目标图像数据的图像子资源。 -
srcOffset
和dstOffset
选择源和目标图像数据子区域中纹素的初始x
、y
和z
偏移量。 -
extent
是要复制的图像的纹素大小,包括width
、height
和depth
。
在缓冲区和图像之间复制数据
数据可以在缓冲区和图像之间复制,使应用程序能够在图像和缓冲区内存中应用程序定义的偏移量之间加载和存储数据。
在缓冲区和图像之间复制时,图像中的纹素和缓冲区中的字节按如下方式访问。
在图像子资源中,访问每个坐标 (x,y,z,layer) 的纹素,其中
-
x 的范围为 [
imageOffset.x
,imageOffset.x
+imageExtent.width
), -
y 的范围为 [
imageOffset.y
,imageOffset.y
+imageExtent.height
), -
z 的范围为 [
imageOffset.z
,imageOffset.z
+imageExtent.depth
), -
layer 的范围为 [
imageSubresource.baseArrayLayer
,imageSubresource.baseArrayLayer
+imageSubresource.layerCount
)
对于图像中的每个坐标 (x,y,z,layer),访问缓冲区中偏移量范围为 [texelOffset, texelOffset + blockSize) 的字节,其中
-
texelOffset =
bufferOffset
+ (⌊(x - imageOffset.x) / blockWidth⌋ × blockSize) + (⌊(y - imageOffset.y) / blockHeight⌋ × rowExtent) + (⌊(z - imageOffset.z) / blockDepth⌋ × sliceExtent) + ((layer -imageSubresource.baseArrayLayer
) × layerExtent) -
rowExtent = ⌈ max(
bufferRowLength
,imageExtent.width
) / blockWidth ⌉ × blockSize -
sliceExtent = ⌈ max(
bufferImageHeight
,imageExtent.height
) / blockHeight ⌉ × rowExtent -
layerExtent = ⌈
imageExtent.depth
/ blockDepth ⌉ × sliceExtent
其中 blockSize、blockWidth、blockHeight 和 blockDepth 是图像格式的纹素块大小和范围。
如果 VkCopyCommandTransformInfoQCOM 指定了旋转,则围绕偏移量旋转正在寻址的图像的 2D 区域,并在图像子资源中访问每个坐标 (x',y',z',layer) 的纹素,其中
-
如果指定了
VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR
,则不执行旋转-
x' 与 x 的范围相同
-
y' 与 y 的范围相同
-
-
如果指定了
VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR
-
x' 的范围为 [
imageOffset.x
-imageExtent.height
,imageOffset.x
) -
y' 的范围为 [
imageOffset.y
,imageOffset.y
+imageExtent.width
)
-
-
如果指定了
VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR
-
x' 的范围为 [
imageOffset.x
-imageExtent.width
,imageOffset.x
) -
y' 的范围为 [
imageOffset.y
-imageExtent.height
,imageOffset.y
)
-
-
如果指定了
VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR
-
x' 的范围为 [
imageOffset.x
,imageOffset.x
+imageExtent.height
) -
y' 的范围为 [
imageOffset.y
-imageExtent.width
,imageOffset.y
)
-
缓冲区寻址计算不受此旋转的影响。
当在缓冲区和图像的深度或模板方面之间复制时,假定缓冲区中的数据以单独的平面而不是交错的方式排列。因此,根据方面,为与基本图像不同的格式执行寻址计算,如下表所述
基本格式 | 深度方面格式 | 模板方面格式 |
---|---|---|
|
|
- |
|
|
- |
|
|
- |
|
- |
|
|
|
|
|
|
|
|
|
|
每个纹素块根据上述寻址公式从一个资源复制到另一个资源。
要将数据从缓冲区对象复制到图像对象,请调用
// Provided by VK_VERSION_1_0
void vkCmdCopyBufferToImage(
VkCommandBuffer commandBuffer,
VkBuffer srcBuffer,
VkImage dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkBufferImageCopy* pRegions);
-
commandBuffer
是将记录命令的命令缓冲区。 -
srcBuffer
是源缓冲区。 -
dstImage
是目标图像。 -
dstImageLayout
是用于复制的目标图像子资源的布局。 -
regionCount
是要复制的区域数。 -
pRegions
是指向 VkBufferImageCopy 结构数组的指针,该结构指定要复制的区域。
根据每个资源的寻址计算,从源缓冲区将 pRegions
指定的每个源区域复制到目标图像的目标区域。如果 srcBuffer
中指定的任何区域与 dstImage
中指定的任何区域在内存中重叠,则从这些重叠区域读取的值是未定义的。如果任何区域访问 dstImage
中的深度方面,并且未启用 VK_EXT_depth_range_unrestricted
扩展,则从 srcBuffer
复制的范围 [0,1] 之外的值将作为未定义的值写入目标图像。
图像的复制区域必须在每个维度上与纹素块范围的倍数对齐,但图像边缘除外,在图像边缘,区域范围必须与图像边缘匹配。
要将数据从图像对象复制到缓冲区对象,请调用
// Provided by VK_VERSION_1_0
void vkCmdCopyImageToBuffer(
VkCommandBuffer commandBuffer,
VkImage srcImage,
VkImageLayout srcImageLayout,
VkBuffer dstBuffer,
uint32_t regionCount,
const VkBufferImageCopy* pRegions);
-
commandBuffer
是将记录命令的命令缓冲区。 -
srcImage
是源图像。 -
srcImageLayout
是复制的源图像子资源的布局。 -
dstBuffer
是目标缓冲区。 -
regionCount
是要复制的区域数。 -
pRegions
是指向 VkBufferImageCopy 结构数组的指针,该结构指定要复制的区域。
根据每个资源的寻址计算,pRegions
指定的每个源区域都从源图像复制到目标缓冲区的目标区域。如果 srcImage
中指定的任何区域在内存中与 dstBuffer
中指定的任何区域重叠,则从这些重叠区域读取的值是 未定义的。
图像的复制区域必须在每个维度上与纹素块范围的倍数对齐,但图像边缘除外,在图像边缘,区域范围必须与图像边缘匹配。
对于 vkCmdCopyBufferToImage 和 vkCmdCopyImageToBuffer,pRegions
的每个元素都是一个定义为以下内容的结构:
// Provided by VK_VERSION_1_0
typedef struct VkBufferImageCopy {
VkDeviceSize bufferOffset;
uint32_t bufferRowLength;
uint32_t bufferImageHeight;
VkImageSubresourceLayers imageSubresource;
VkOffset3D imageOffset;
VkExtent3D imageExtent;
} VkBufferImageCopy;
-
bufferOffset
是从缓冲区对象的开始到复制或从中复制图像数据的字节偏移量。 -
bufferRowLength
和bufferImageHeight
在纹素中指定缓冲区内存中较大的二维或三维图像的子区域,并控制寻址计算。如果这些值中的任何一个为零,则认为缓冲区内存的该方面根据imageExtent
紧密打包。 -
imageSubresource
是一个 VkImageSubresourceLayers,用于指定用于源或目标图像数据的图像的特定图像子资源。 -
imageOffset
选择源或目标图像数据子区域中纹素的初始x
、y
、z
偏移量。 -
imageExtent
是要复制的图像的大小,以纹素为单位,包括width
、height
和depth
。
下面定义了在缓冲区和图像之间复制的命令的更可扩展的版本。
要将数据从缓冲区对象复制到图像对象,请调用
// Provided by VK_VERSION_1_3
void vkCmdCopyBufferToImage2(
VkCommandBuffer commandBuffer,
const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo);
或等效的命令
// Provided by VK_KHR_copy_commands2
void vkCmdCopyBufferToImage2KHR(
VkCommandBuffer commandBuffer,
const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo);
-
commandBuffer
是将记录命令的命令缓冲区。 -
pCopyBufferToImageInfo
是一个指向 VkCopyBufferToImageInfo2 结构体的指针,该结构体描述了复制参数。
此命令在功能上与 vkCmdCopyBufferToImage 相同,但包含可扩展的子结构,其中包括 sType
和 pNext
参数,从而可以更轻松地进行扩展。
VkCopyBufferToImageInfo2
结构定义如下:
// Provided by VK_VERSION_1_3
typedef struct VkCopyBufferToImageInfo2 {
VkStructureType sType;
const void* pNext;
VkBuffer srcBuffer;
VkImage dstImage;
VkImageLayout dstImageLayout;
uint32_t regionCount;
const VkBufferImageCopy2* pRegions;
} VkCopyBufferToImageInfo2;
或等效的
// Provided by VK_KHR_copy_commands2
typedef VkCopyBufferToImageInfo2 VkCopyBufferToImageInfo2KHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
srcBuffer
是源缓冲区。 -
dstImage
是目标图像。 -
dstImageLayout
是用于复制的目标图像子资源的布局。 -
regionCount
是要复制的区域数。 -
pRegions
是一个指向 VkBufferImageCopy2 结构体数组的指针,该数组指定要复制的区域。
要将数据从图像对象复制到缓冲区对象,请调用
// Provided by VK_VERSION_1_3
void vkCmdCopyImageToBuffer2(
VkCommandBuffer commandBuffer,
const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo);
或等效的命令
// Provided by VK_KHR_copy_commands2
void vkCmdCopyImageToBuffer2KHR(
VkCommandBuffer commandBuffer,
const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo);
-
commandBuffer
是将记录命令的命令缓冲区。 -
pCopyImageToBufferInfo
是指向 VkCopyImageToBufferInfo2 结构的指针,该结构描述了复制参数。
此命令在功能上与 vkCmdCopyImageToBuffer 相同,但包括可扩展的子结构,其中包含 sType
和 pNext
参数,从而可以更容易地扩展它们。
VkCopyImageToBufferInfo2
结构定义如下:
// Provided by VK_VERSION_1_3
typedef struct VkCopyImageToBufferInfo2 {
VkStructureType sType;
const void* pNext;
VkImage srcImage;
VkImageLayout srcImageLayout;
VkBuffer dstBuffer;
uint32_t regionCount;
const VkBufferImageCopy2* pRegions;
} VkCopyImageToBufferInfo2;
或等效的
// Provided by VK_KHR_copy_commands2
typedef VkCopyImageToBufferInfo2 VkCopyImageToBufferInfo2KHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
srcImage
是源图像。 -
srcImageLayout
是复制的源图像子资源的布局。 -
dstBuffer
是目标缓冲区。 -
regionCount
是要复制的区域数。 -
pRegions
是一个指向 VkBufferImageCopy2 结构体数组的指针,该数组指定要复制的区域。
对于 vkCmdCopyBufferToImage2 和 vkCmdCopyImageToBuffer2,pRegions
的每个元素都定义为一个结构体,如下:
// Provided by VK_VERSION_1_3
typedef struct VkBufferImageCopy2 {
VkStructureType sType;
const void* pNext;
VkDeviceSize bufferOffset;
uint32_t bufferRowLength;
uint32_t bufferImageHeight;
VkImageSubresourceLayers imageSubresource;
VkOffset3D imageOffset;
VkExtent3D imageExtent;
} VkBufferImageCopy2;
或等效的
// Provided by VK_KHR_copy_commands2
typedef VkBufferImageCopy2 VkBufferImageCopy2KHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
bufferOffset
是从缓冲区对象的开始到复制或从中复制图像数据的字节偏移量。 -
bufferRowLength
和bufferImageHeight
在纹素中指定缓冲区内存中较大的二维或三维图像的子区域,并控制寻址计算。如果这些值中的任何一个为零,则认为缓冲区内存的该方面根据imageExtent
紧密打包。 -
imageSubresource
是一个 VkImageSubresourceLayers,用于指定用于源或目标图像数据的图像的特定图像子资源。 -
imageOffset
选择源或目标图像数据子区域中纹素的初始x
、y
、z
偏移量。 -
imageExtent
是要复制的图像的大小,以纹素为单位,包括width
、height
和depth
。
此结构体在功能上与 VkBufferImageCopy 相同,但添加了 sType
和 pNext
参数,使其更易于扩展。
VkCopyCommandTransformInfoQCOM
结构体定义如下:
// Provided by VK_QCOM_rotated_copy_commands
typedef struct VkCopyCommandTransformInfoQCOM {
VkStructureType sType;
const void* pNext;
VkSurfaceTransformFlagBitsKHR transform;
} VkCopyCommandTransformInfoQCOM;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
transform
是一个 VkSurfaceTransformFlagBitsKHR 值,描述要应用的变换。
在 VkBufferImageCopy2 的 pNext
链中包含此结构体,定义了在图像和缓冲区之间复制时要执行的旋转。在 VkBlitImageInfo2 的 pNext
链中包含此结构体,定义了在两个图像之间 blit 时要执行的旋转。如果在这两种情况下都没有指定此结构体,则实现的行为就像指定了一个 transform
等于 VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR
的结构体一样。
为图像和缓冲区之间的复制指定变换 会使图像中访问的区域围绕偏移量旋转。为 blit 指定变换执行类似于 具有缩放和旋转的图像 Blit 中描述的变换。
除了 VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR
之外的旋转只能为具有 1x1x1 纹素块范围 的单平面 2D 图像指定。
以下命令可用于在主机内存和图像之间进行复制。主机内存中的字节和图像中的纹素按照 在缓冲区和图像之间复制数据 中指定的方式访问,其中缓冲区替换为主机内存。
在主机上进出图像的复制不会在内部同步。同时访问(涉及写入)主机上重叠的图像内存构成 数据竞争。 |
要将数据从主机内存复制到图像对象,请调用
// Provided by VK_VERSION_1_4
VkResult vkCopyMemoryToImage(
VkDevice device,
const VkCopyMemoryToImageInfo* pCopyMemoryToImageInfo);
或等效的命令
// Provided by VK_EXT_host_image_copy
VkResult vkCopyMemoryToImageEXT(
VkDevice device,
const VkCopyMemoryToImageInfo* pCopyMemoryToImageInfo);
-
device
是拥有pCopyMemoryToImageInfo->dstImage
的设备。 -
pCopyMemoryToImageInfo
是指向描述复制参数的 VkCopyMemoryToImageInfo 结构体的指针。
此命令在功能上类似于 vkCmdCopyBufferToImage2,只是它在主机上执行,并从主机内存而不是缓冲区读取。主机访问 pCopyMemoryToImageInfo->dstImage
的内存,就好像它是 一致的。
由于队列提交 自动使主机内存对设备可见,因此在使用设备上此复制操作的结果之前,无需进行内存屏障。 |
VkCopyMemoryToImageInfo
结构体的定义如下:
// Provided by VK_VERSION_1_4
typedef struct VkCopyMemoryToImageInfo {
VkStructureType sType;
const void* pNext;
VkHostImageCopyFlags flags;
VkImage dstImage;
VkImageLayout dstImageLayout;
uint32_t regionCount;
const VkMemoryToImageCopy* pRegions;
} VkCopyMemoryToImageInfo;
或等效的
// Provided by VK_EXT_host_image_copy
typedef VkCopyMemoryToImageInfo VkCopyMemoryToImageInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
flags
是一个 VkHostImageCopyFlagBits 值的位掩码,描述了额外的复制参数。 -
dstImage
是目标图像。 -
dstImageLayout
是用于复制的目标图像子资源的布局。 -
regionCount
是要复制的区域数。 -
pRegions
是指向 VkMemoryToImageCopy 结构体数组的指针,指定要复制的区域。
vkCopyMemoryToImage
在执行复制之前不检查与 dstImage
关联的设备内存当前是否正在使用。应用程序必须保证任何先前提交的从复制区域读取或写入的命令在主机执行复制之前已完成。
图像的复制区域必须在每个维度上与纹素块范围的倍数对齐,但图像边缘除外,在图像边缘,区域范围必须与图像边缘匹配。
VkCopyMemoryToImageInfo::pRegions
的每个元素都是一个定义如下的结构体:
// Provided by VK_VERSION_1_4
typedef struct VkMemoryToImageCopy {
VkStructureType sType;
const void* pNext;
const void* pHostPointer;
uint32_t memoryRowLength;
uint32_t memoryImageHeight;
VkImageSubresourceLayers imageSubresource;
VkOffset3D imageOffset;
VkExtent3D imageExtent;
} VkMemoryToImageCopy;
或等效的
// Provided by VK_EXT_host_image_copy
typedef VkMemoryToImageCopy VkMemoryToImageCopyEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
pHostPointer
是主机内存地址,它是复制操作的源。 -
memoryRowLength
和memoryImageHeight
在纹素中指定主机内存中较大的二维或三维图像的子区域,并控制寻址计算。如果这些值中的任何一个为零,则认为主机内存的该方面根据imageExtent
紧密打包。 -
imageSubresource
是一个 VkImageSubresourceLayers,用于指定用于源或目标图像数据的图像的特定图像子资源。 -
imageOffset
选择目标图像数据的子区域中初始的x
、y
、z
纹素偏移量。 -
imageExtent
是要复制的图像的大小,以纹素为单位,包括width
、height
和depth
。
此结构在功能上类似于 VkBufferImageCopy2,不同之处在于它定义主机内存作为复制的源,而不是缓冲区。特别是,与该结构相同的 数据打包规则 和限制也适用于此处。
要将数据从图像对象复制到主机内存,请调用:
// Provided by VK_VERSION_1_4
VkResult vkCopyImageToMemory(
VkDevice device,
const VkCopyImageToMemoryInfo* pCopyImageToMemoryInfo);
或等效的命令
// Provided by VK_EXT_host_image_copy
VkResult vkCopyImageToMemoryEXT(
VkDevice device,
const VkCopyImageToMemoryInfo* pCopyImageToMemoryInfo);
-
device
是拥有pCopyImageToMemoryInfo->srcImage
的设备。 -
pCopyImageToMemoryInfo
是指向 VkCopyImageToMemoryInfo 结构的指针,该结构描述了复制参数。
此命令在功能上类似于 vkCmdCopyImageToBuffer2,不同之处在于它在主机上执行并写入主机内存而不是缓冲区。主机访问 pCopyImageToMemoryInfo->srcImage
的内存,就像 一致的 一样。
如果设备已写入图像内存,则它不会自动对主机可用。在调用此复制命令之前,必须已在设备上发布此图像的内存屏障,其中第二个同步范围包括 |
VkCopyImageToMemoryInfo
结构的定义如下:
// Provided by VK_VERSION_1_4
typedef struct VkCopyImageToMemoryInfo {
VkStructureType sType;
const void* pNext;
VkHostImageCopyFlags flags;
VkImage srcImage;
VkImageLayout srcImageLayout;
uint32_t regionCount;
const VkImageToMemoryCopy* pRegions;
} VkCopyImageToMemoryInfo;
或等效的
// Provided by VK_EXT_host_image_copy
typedef VkCopyImageToMemoryInfo VkCopyImageToMemoryInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
flags
是一个 VkHostImageCopyFlagBits 值的位掩码,描述了额外的复制参数。 -
srcImage
是源图像。 -
srcImageLayout
是复制的源图像子资源的布局。 -
regionCount
是要复制的区域数。 -
pRegions
是指向 VkImageToMemoryCopy 结构体数组的指针,该数组指定要复制的区域。
vkCopyImageToMemory
在执行复制之前,不检查与 srcImage
关联的设备内存当前是否正在使用。应用程序必须保证,任何先前提交的写入复制区域的命令在主机执行复制之前已完成。
图像的复制区域必须在每个维度上与纹素块范围的倍数对齐,但图像边缘除外,在图像边缘,区域范围必须与图像边缘匹配。
VkCopyImageToMemoryInfo::pRegions
的每个元素都是一个定义为
// Provided by VK_VERSION_1_4
typedef struct VkImageToMemoryCopy {
VkStructureType sType;
const void* pNext;
void* pHostPointer;
uint32_t memoryRowLength;
uint32_t memoryImageHeight;
VkImageSubresourceLayers imageSubresource;
VkOffset3D imageOffset;
VkExtent3D imageExtent;
} VkImageToMemoryCopy;
或等效的
// Provided by VK_EXT_host_image_copy
typedef VkImageToMemoryCopy VkImageToMemoryCopyEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
pHostPointer
是主机内存地址,它是复制的目标。 -
memoryRowLength
和memoryImageHeight
在纹素中指定主机内存中较大的二维或三维图像的子区域,并控制寻址计算。如果这些值中的任何一个为零,则认为主机内存的该方面根据imageExtent
紧密打包。 -
imageSubresource
是一个 VkImageSubresourceLayers,用于指定用于源或目标图像数据的图像的特定图像子资源。 -
imageOffset
选择源图像数据子区域中以纹素为单位的初始x
、y
、z
偏移量。 -
imageExtent
是要复制的图像的大小,以纹素为单位,包括width
、height
和depth
。
此结构在功能上类似于 VkBufferImageCopy2,除了它定义主机内存作为复制的目标而不是缓冲区。特别是,这里也适用与该结构相同的数据打包规则和限制。
在 VkCopyMemoryToImageInfo::flags
、 VkCopyImageToMemoryInfo::flags
和 VkCopyImageToImageInfo::flags
中,可以设置的位(用于指定额外的复制参数)包括:
// Provided by VK_VERSION_1_4
typedef enum VkHostImageCopyFlagBits {
VK_HOST_IMAGE_COPY_MEMCPY = 0x00000001,
// Provided by VK_EXT_host_image_copy
VK_HOST_IMAGE_COPY_MEMCPY_EXT = VK_HOST_IMAGE_COPY_MEMCPY,
} VkHostImageCopyFlagBits;
或等效的
// Provided by VK_EXT_host_image_copy
typedef VkHostImageCopyFlagBits VkHostImageCopyFlagBitsEXT;
-
VK_HOST_IMAGE_COPY_MEMCPY
指定在数据复制期间不应用内存布局的置换。对于内存和图像之间的复制,此标志表示主机内存中的图像数据与设备上的图像数据以完全相同的方式进行置换。使用此标志表示实现**可能**使用简单的内存复制来在主机内存和设备内存之间传输数据。主机内存中置换数据的格式取决于平台,并且在此规范中未定义。
// Provided by VK_VERSION_1_4
typedef VkFlags VkHostImageCopyFlags;
或等效的
// Provided by VK_EXT_host_image_copy
typedef VkHostImageCopyFlags VkHostImageCopyFlagsEXT;
VkHostImageCopyFlags
是一个位掩码类型,用于设置零个或多个 VkHostImageCopyFlagBits 的掩码。
要使用主机将数据从一个图像对象复制到另一个图像对象,请调用:
// Provided by VK_VERSION_1_4
VkResult vkCopyImageToImage(
VkDevice device,
const VkCopyImageToImageInfo* pCopyImageToImageInfo);
或等效的命令
// Provided by VK_EXT_host_image_copy
VkResult vkCopyImageToImageEXT(
VkDevice device,
const VkCopyImageToImageInfo* pCopyImageToImageInfo);
-
device
是拥有pCopyImageToImageInfo->srcImage
和pCopyImageToImageInfo->dstImage
的设备。 -
pCopyImageToImageInfo
是指向 VkCopyImageToImageInfo 结构的指针,该结构描述了复制参数。
此命令的功能与 vkCmdCopyImage2 类似,但它在主机上执行。主机访问 pCopyImageToImageInfo->srcImage
和 pCopyImageToImageInfo->dstImage
的内存,如同它们是一致的。
如果设备已写入 由于队列提交会自动使主机内存对设备可见,因此在设备上使用 |
VkCopyImageToImageInfo
结构定义如下:
// Provided by VK_VERSION_1_4
typedef struct VkCopyImageToImageInfo {
VkStructureType sType;
const void* pNext;
VkHostImageCopyFlags flags;
VkImage srcImage;
VkImageLayout srcImageLayout;
VkImage dstImage;
VkImageLayout dstImageLayout;
uint32_t regionCount;
const VkImageCopy2* pRegions;
} VkCopyImageToImageInfo;
或等效的
// Provided by VK_EXT_host_image_copy
typedef VkCopyImageToImageInfo VkCopyImageToImageInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
flags
是一个 VkHostImageCopyFlagBits 值的位掩码,描述了额外的复制参数。 -
srcImage
是源图像。 -
srcImageLayout
是复制的源图像子资源的布局。 -
dstImage
是目标图像。 -
dstImageLayout
是用于复制的目标图像子资源的布局。 -
regionCount
是要复制的区域数。 -
pRegions
是指向 VkImageCopy2 结构体数组的指针,该数组指定要复制的区域。
在执行复制之前,vkCopyImageToImage
不会检查与 srcImage
或 dstImage
关联的设备内存当前是否正在使用。应用程序**必须**保证在主机执行复制之前,任何先前提交的写入复制区域的命令都已完成。
间接复制
当复制参数在命令缓冲区创建时未知时,应用程序可以使用间接复制。
要通过在缓冲区中间接指定复制参数来在两个内存区域之间复制数据,请调用
// Provided by VK_NV_copy_memory_indirect
void vkCmdCopyMemoryIndirectNV(
VkCommandBuffer commandBuffer,
VkDeviceAddress copyBufferAddress,
uint32_t copyCount,
uint32_t stride);
-
commandBuffer
是将记录命令的命令缓冲区。 -
copyBufferAddress
是指定复制参数的缓冲区地址。此缓冲区在内存中布局为 VkCopyMemoryIndirectCommandNV 结构的数组。 -
copyCount
是要执行的复制次数,可以为零。 -
stride
是连续的复制参数集之间的步长(以字节为单位)。
从 copyBufferAddress
读取的每个区域都从源区域复制到指定的目的地区域。如果任何源区域和目的地区域在内存中重叠,则结果是未定义的。
描述源和目标内存区域的结构 VkCopyMemoryIndirectCommandNV
定义为
// Provided by VK_NV_copy_memory_indirect
typedef struct VkCopyMemoryIndirectCommandNV {
VkDeviceAddress srcAddress;
VkDeviceAddress dstAddress;
VkDeviceSize size;
} VkCopyMemoryIndirectCommandNV;
-
srcAddress
是要从中复制的源设备内存的起始地址。 -
dstAddress
是要复制到的目标设备内存的起始地址。 -
size
是复制的大小(以字节为单位)。
要通过在缓冲区中指定复制参数来将数据从内存区域复制到图像对象,请调用
// Provided by VK_NV_copy_memory_indirect
void vkCmdCopyMemoryToImageIndirectNV(
VkCommandBuffer commandBuffer,
VkDeviceAddress copyBufferAddress,
uint32_t copyCount,
uint32_t stride,
VkImage dstImage,
VkImageLayout dstImageLayout,
const VkImageSubresourceLayers* pImageSubresources);
-
commandBuffer
是将记录命令的命令缓冲区。 -
copyBufferAddress
是指定复制参数的缓冲区地址。此缓冲区在内存中布局为 VkCopyMemoryToImageIndirectCommandNV 结构的数组。 -
copyCount
是要执行的复制次数,可以为零。 -
stride
是连续的复制参数集之间的字节步长。 -
dstImage
是目标图像。 -
dstImageLayout
是用于复制的目标图像子资源的布局。 -
pImageSubresources
是一个指向大小为copyCount
的 VkImageSubresourceLayers 数组的指针,用于指定该复制操作的目标图像数据的特定图像子资源。
copyBufferAddress
中的每个区域都从源内存区域复制到目标图像中的一个区域。如果目标图像类型为 VK_IMAGE_TYPE_3D
,则要复制的起始切片和切片数量分别在 pImageSubresources->baseArrayLayer
和 pImageSubresources->layerCount
中指定。该复制操作必须在支持间接复制操作的队列上执行,请参阅 VkPhysicalDeviceCopyMemoryIndirectPropertiesNV。
VkCopyMemoryToImageIndirectCommandNV
定义为
// Provided by VK_NV_copy_memory_indirect
typedef struct VkCopyMemoryToImageIndirectCommandNV {
VkDeviceAddress srcAddress;
uint32_t bufferRowLength;
uint32_t bufferImageHeight;
VkImageSubresourceLayers imageSubresource;
VkOffset3D imageOffset;
VkExtent3D imageExtent;
} VkCopyMemoryToImageIndirectCommandNV;
-
srcAddress
是要从中复制的源设备内存的起始地址。 -
bufferRowLength
和bufferImageHeight
在纹素中指定缓冲区内存中较大的二维或三维图像的子区域,并控制寻址计算。如果这些值中的任何一个为零,则认为缓冲区内存的该方面根据imageExtent
紧密打包。 -
imageSubresource
是一个 VkImageSubresourceLayers,用于指定目标图像数据所使用的特定图像子资源,它必须与命令记录期间 vkCmdCopyMemoryToImageIndirectNV 的pImageSubresources
参数中指定的值相匹配。 -
imageOffset
选择目标图像数据的子区域中初始的x
、y
、z
纹素偏移量。 -
imageExtent
是目标图像在width
、height
和depth
中的纹素大小。
图像复制与缩放
要将源图像的区域复制到目标图像,可能会执行格式转换、任意缩放和过滤,请调用
// Provided by VK_VERSION_1_0
void vkCmdBlitImage(
VkCommandBuffer commandBuffer,
VkImage srcImage,
VkImageLayout srcImageLayout,
VkImage dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageBlit* pRegions,
VkFilter filter);
-
commandBuffer
是将记录命令的命令缓冲区。 -
srcImage
是源图像。 -
srcImageLayout
是用于 blit 的源图像子资源的布局。 -
dstImage
是目标图像。 -
dstImageLayout
是用于 blit 的目标图像子资源的布局。 -
regionCount
是要 blit 的区域数量。 -
pRegions
是指向 VkImageBlit 结构数组的指针,这些结构指定要 blit 的区域。 -
filter
是一个 VkFilter,指定如果 blit 需要缩放时要应用的过滤器。
vkCmdBlitImage
不得用于多重采样的源或目标图像。 请为此目的使用 vkCmdResolveImage。
由于源和目标范围的大小在任何维度上可以不同,因此源范围中的纹素会缩放并过滤到目标范围。 缩放通过以下操作进行
-
对于每个目标纹素,该纹素的整数坐标会使用 非规范化到整数转换 中描述的公式的有效逆向转换为非规范化纹理坐标。
-
ubase = i + ½
-
vbase = j + ½
-
wbase = k + ½
-
-
这些基本坐标然后通过第一个目标偏移量进行偏移
-
uoffset = ubase - xdst0
-
voffset = vbase - ydst0
-
woffset = wbase - zdst0
-
aoffset = a -
baseArrayCount
dst
-
-
缩放比例由源和目标区域确定,并应用于偏移坐标
-
scaleu = (xsrc1 - xsrc0) / (xdst1 - xdst0)
-
scalev = (ysrc1 - ysrc0) / (ydst1 - ydst0)
-
scalew = (zsrc1 - zsrc0) / (zdst1 - zdst0)
-
uscaled = uoffset × scaleu
-
vscaled = voffset × scalev
-
wscaled = woffset × scalew
-
-
最后,将源偏移量添加到缩放后的坐标,以确定用于从
srcImage
采样的最终非规范化坐标-
u = uscaled + xsrc0
-
v = vscaled + ysrc0
-
w = wscaled + zsrc0
-
q =
mipLevel
-
a = aoffset +
baseArrayCount
src
-
这些坐标用于从源图像进行采样,如 图像操作章节 中所述,其中过滤模式等于 filter
的过滤模式,mipmap 模式为 VK_SAMPLER_MIPMAP_MODE_NEAREST
,地址模式为 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE
。 实现必须钳制在源图像的边缘,并且可以额外钳制在源区域的边缘。
由于在生成源纹理坐标时允许的舍入误差,因此无法始终保证为给定的 blit 采样哪些源纹素。 由于舍入误差与实现相关,因此 blit 操作的确切结果也与实现相关。 |
Blit 逐层执行,从源的 srcSubresource
的 baseArrayLayer
成员和目标的 dstSubresource
开始。 layerCount
层 blit 到目标图像。
当 blit 3D 纹理时,目标区域中由 dstOffsets
[0].z 和 dstOffsets
[1].z 限定的切片是从源区域中由 srcOffsets
[0].z 和 srcOffsets
[1].z 限定的切片采样的。 如果 filter
参数是 VK_FILTER_LINEAR
,则从源图像采样的值是通过使用先前方程中由 w 表示的插值 z 坐标执行线性滤波来获得的。 如果 filter
参数是 VK_FILTER_NEAREST
,则从源图像采样的值取自单个最近的切片,其实现相关的算术舍入模式。
以下过滤和转换规则适用
-
整数格式只能转换为具有相同符号的其他整数格式。
-
深度/模板图像之间不支持格式转换。 格式必须匹配。
-
图像的复制方面上的 unorm、snorm、缩放和打包浮点格式的格式转换是通过首先将像素转换为浮点值来执行的。
-
对于 sRGB 源格式,非线性 RGB 值会在过滤之前转换为线性表示形式。
-
过滤后,浮点值首先被钳制,然后强制转换为目标图像格式。 在 sRGB 目标格式的情况下,线性 RGB 值在将像素写入图像之前转换为非线性表示形式。
有符号和无符号整数的转换方式是:首先钳制到目标格式的可表示范围内,然后强制转换该值。
VkImageBlit
结构定义如下
// Provided by VK_VERSION_1_0
typedef struct VkImageBlit {
VkImageSubresourceLayers srcSubresource;
VkOffset3D srcOffsets[2];
VkImageSubresourceLayers dstSubresource;
VkOffset3D dstOffsets[2];
} VkImageBlit;
-
srcSubresource
是要从中进行位块传输的子资源。 -
srcOffsets
是指向两个 VkOffset3D 结构体的数组的指针,指定了srcSubresource
内源区域的边界。 -
dstSubresource
是要将位块传输到的子资源。 -
dstOffsets
是指向两个 VkOffset3D 结构体的数组的指针,指定了dstSubresource
内目标区域的边界。
对于 pRegions
数组的每个元素,都会为指定的源区域和目标区域执行位块传输操作。
下面定义了位块传输图像命令的更可扩展的版本。
要将源图像的区域复制到目标图像,可能会执行格式转换、任意缩放和过滤,请调用
// Provided by VK_VERSION_1_3
void vkCmdBlitImage2(
VkCommandBuffer commandBuffer,
const VkBlitImageInfo2* pBlitImageInfo);
或等效的命令
// Provided by VK_KHR_copy_commands2
void vkCmdBlitImage2KHR(
VkCommandBuffer commandBuffer,
const VkBlitImageInfo2* pBlitImageInfo);
-
commandBuffer
是将记录命令的命令缓冲区。 -
pBlitImageInfo
是指向 VkBlitImageInfo2 结构体的指针,该结构体描述了位块传输参数。
此命令在功能上与 vkCmdBlitImage 相同,但包含可扩展的子结构体,其中包括 sType
和 pNext
参数,从而可以更轻松地对其进行扩展。
VkBlitImageInfo2
结构定义如下:
// Provided by VK_VERSION_1_3
typedef struct VkBlitImageInfo2 {
VkStructureType sType;
const void* pNext;
VkImage srcImage;
VkImageLayout srcImageLayout;
VkImage dstImage;
VkImageLayout dstImageLayout;
uint32_t regionCount;
const VkImageBlit2* pRegions;
VkFilter filter;
} VkBlitImageInfo2;
或等效的
// Provided by VK_KHR_copy_commands2
typedef VkBlitImageInfo2 VkBlitImageInfo2KHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
srcImage
是源图像。 -
srcImageLayout
是用于 blit 的源图像子资源的布局。 -
dstImage
是目标图像。 -
dstImageLayout
是用于 blit 的目标图像子资源的布局。 -
regionCount
是要 blit 的区域数量。 -
pRegions
是一个指向 VkImageBlit2 结构数组的指针,用于指定要 blit 的区域。 -
filter
是一个 VkFilter,指定如果 blit 需要缩放时要应用的过滤器。
如果 filter
为 VK_FILTER_CUBIC_EXT
并且如果 VkBlitImageInfo2 的 pNext
链包含 VkBlitImageCubicWeightsInfoQCOM
结构,则该结构指定在 blit 中使用的立方权重。如果该结构不存在,则立方权重被视为 VK_CUBIC_FILTER_WEIGHTS_CATMULL_ROM_QCOM
。
VkBlitImageCubicWeightsInfoQCOM
结构定义如下:
// Provided by VK_QCOM_filter_cubic_weights
typedef struct VkBlitImageCubicWeightsInfoQCOM {
VkStructureType sType;
const void* pNext;
VkCubicFilterWeightsQCOM cubicWeights;
} VkBlitImageCubicWeightsInfoQCOM;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
cubicWeights
是一个 VkCubicFilterWeightsQCOM 值,用于控制 blit 的三次滤波权重。
VkImageBlit2
结构定义如下:
// Provided by VK_VERSION_1_3
typedef struct VkImageBlit2 {
VkStructureType sType;
const void* pNext;
VkImageSubresourceLayers srcSubresource;
VkOffset3D srcOffsets[2];
VkImageSubresourceLayers dstSubresource;
VkOffset3D dstOffsets[2];
} VkImageBlit2;
或等效的
// Provided by VK_KHR_copy_commands2
typedef VkImageBlit2 VkImageBlit2KHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
srcSubresource
是要从中进行位块传输的子资源。 -
srcOffsets
是指向两个 VkOffset3D 结构体的数组的指针,指定了srcSubresource
内源区域的边界。 -
dstSubresource
是要将位块传输到的子资源。 -
dstOffsets
是指向两个 VkOffset3D 结构体的数组的指针,指定了dstSubresource
内目标区域的边界。
对于 pRegions
数组的每个元素,都会为指定的源区域和目标区域执行位块传输操作。
对于 vkCmdBlitImage2,复制的每个区域都可以包含旋转。要指定旋转区域,请将 VkCopyCommandTransformInfoQCOM 添加到 VkImageBlit2 的 pNext
链中。对于每个指定了旋转的区域,具有缩放和旋转的图像 Blit 指定了在从源图像采样之前如何旋转坐标。当指定旋转时,源图像和目标图像必须均为 2D 图像,具有 1x1x1 的纹素块范围,且仅有一个平面。
具有缩放和旋转的图像 Blit
当 VkCopyCommandTransformInfoQCOM 在 VkImageBlit2 的 pNext
链中时,指定的区域在 blit 期间会旋转。以下关于旋转寻址的描述将替换 vkCmdBlitImage 中的描述。
以下代码计算归一化坐标的旋转。
// rotation of normalized coordinates
VkOffset2D RotateNormUV(VkOffset2D in, VkSurfaceTransformFlagBitsKHR flags)
{
VkOffset2D output;
switch (flags)
{
case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
out.x = in.x;
out.y = in.y;
break;
case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
out.x = in.y;
out.y = 1.0 - in.x;
break;
case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
out.x = 1.0 - in.x;
out.y = 1.0 - in.y;
break;
case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
out.x = 1.0 - in.y;
out.y = in.x;
break;
}
return out;
}
-
对于每个目标纹素,该纹素的整数坐标会使用 非规范化到整数转换 中描述的公式的有效逆向转换为非规范化纹理坐标。
-
ubase = i + ½
-
vbase = j + ½
-
wbase = k + ½
-
-
这些基本坐标然后通过第一个目标偏移量进行偏移
-
uoffset = ubase - xdst0
-
voffset = vbase - ydst0
-
woffset = wbase - zdst0
-
aoffset = a -
baseArrayCount
dst
-
-
UV 目标坐标按目标区域缩放,旋转,然后按源区域缩放。
-
udest_scaled = uoffset / (xdst1 - xdst0)
-
vdest_scaled = voffset / (ydst1 - ydst0)
-
(usrc_scaled, vsrc_scaled) =
RotateNormUV
(udest_scaled, vdest_scaled,transform
) -
uscaled = usrc_scaled × (xSrc1 - xSrc0)
-
vscaled = vsrc_scaled × (ySrc1 - ySrc0)
-
-
W 坐标不受旋转影响。比例尺由源区域和目标区域的比率确定,并应用于偏移坐标
-
scalew = (zSrc1 - zSrc0) / (zdst1 - zdst0)
-
wscaled = woffset × scalew
-
-
最后,将源偏移量添加到缩放的源坐标,以确定用于从
srcImage
采样的最终非归一化坐标-
u = uscaled + xSrc0
-
v = vscaled + ySrc0
-
w = wscaled + zSrc0
-
q =
mipLevel
-
a = aoffset +
baseArrayCount
src
-
这些坐标用于从源图像中采样,如 图像操作 中所述,其过滤模式等于 filter
的模式;mipmap 模式为 VK_SAMPLER_MIPMAP_MODE_NEAREST
;地址模式为 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE
。实现必须在源图像的边缘处进行钳制,并且可以另外在源区域的边缘处进行钳制。
解析多重采样图像
要将多重采样颜色图像解析为非多重采样颜色图像,请调用
// Provided by VK_VERSION_1_0
void vkCmdResolveImage(
VkCommandBuffer commandBuffer,
VkImage srcImage,
VkImageLayout srcImageLayout,
VkImage dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageResolve* pRegions);
-
commandBuffer
是将记录命令的命令缓冲区。 -
srcImage
是源图像。 -
srcImageLayout
是用于解析的源图像子资源的布局。 -
dstImage
是目标图像。 -
dstImageLayout
是用于解析的目标图像子资源的布局。 -
regionCount
是要解析的区域的数量。 -
pRegions
是指向 VkImageResolve 结构的数组的指针,该结构指定要解析的区域。
在解析期间,源中每个像素位置对应的样本在写入目标之前被转换为单个样本。如果源格式为浮点或归一化类型,则每个像素的样本值以实现相关的方式解析。如果源格式为整数类型,则为每个像素选择单个样本的值。
srcOffset
和 dstOffset
选择源和目标图像数据的子区域中纹素的初始 x
、y
和 z
偏移量。extent
是要解析的源图像的大小(以纹素为单位),单位为 width
、height
和 depth
。pRegions
的每个元素必须是包含在其对应图像内的区域。
解析是逐层进行的,从源的 srcSubresource
的 baseArrayLayer
成员和目标的 dstSubresource
开始。layerCount
层被解析到目标图像。
VkImageResolve
结构的定义如下
// Provided by VK_VERSION_1_0
typedef struct VkImageResolve {
VkImageSubresourceLayers srcSubresource;
VkOffset3D srcOffset;
VkImageSubresourceLayers dstSubresource;
VkOffset3D dstOffset;
VkExtent3D extent;
} VkImageResolve;
-
srcSubresource
和dstSubresource
是 VkImageSubresourceLayers 结构,分别指定用于源和目标图像数据的图像子资源。不支持深度/模板图像的解析。 -
srcOffset
和dstOffset
选择源和目标图像数据子区域中纹素的初始x
、y
和z
偏移量。 -
extent
是要解析的源图像在width
、height
和depth
中的纹素大小。
下面定义了更可扩展版本的解析图像命令。
要将多采样图像解析为非多采样图像,请调用
// Provided by VK_VERSION_1_3
void vkCmdResolveImage2(
VkCommandBuffer commandBuffer,
const VkResolveImageInfo2* pResolveImageInfo);
或等效的命令
// Provided by VK_KHR_copy_commands2
void vkCmdResolveImage2KHR(
VkCommandBuffer commandBuffer,
const VkResolveImageInfo2* pResolveImageInfo);
-
commandBuffer
是将记录命令的命令缓冲区。 -
pResolveImageInfo
是指向描述解析参数的 VkResolveImageInfo2 结构的指针。
此命令的功能与 vkCmdResolveImage 相同,但包含可扩展的子结构,其中包括 sType
和 pNext
参数,使它们更容易扩展。
VkResolveImageInfo2
结构的定义如下
// Provided by VK_VERSION_1_3
typedef struct VkResolveImageInfo2 {
VkStructureType sType;
const void* pNext;
VkImage srcImage;
VkImageLayout srcImageLayout;
VkImage dstImage;
VkImageLayout dstImageLayout;
uint32_t regionCount;
const VkImageResolve2* pRegions;
} VkResolveImageInfo2;
或等效的
// Provided by VK_KHR_copy_commands2
typedef VkResolveImageInfo2 VkResolveImageInfo2KHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
srcImage
是源图像。 -
srcImageLayout
是用于解析的源图像子资源的布局。 -
dstImage
是目标图像。 -
dstImageLayout
是用于解析的目标图像子资源的布局。 -
regionCount
是要解析的区域的数量。 -
pRegions
是指向指定要解析的区域的 VkImageResolve2 结构数组的指针。
VkImageResolve2
结构体定义如下:
// Provided by VK_VERSION_1_3
typedef struct VkImageResolve2 {
VkStructureType sType;
const void* pNext;
VkImageSubresourceLayers srcSubresource;
VkOffset3D srcOffset;
VkImageSubresourceLayers dstSubresource;
VkOffset3D dstOffset;
VkExtent3D extent;
} VkImageResolve2;
或等效的
// Provided by VK_KHR_copy_commands2
typedef VkImageResolve2 VkImageResolve2KHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
srcSubresource
和dstSubresource
是 VkImageSubresourceLayers 结构,分别指定用于源和目标图像数据的图像子资源。不支持深度/模板图像的解析。 -
srcOffset
和dstOffset
选择源和目标图像数据子区域中纹素的初始x
、y
和z
偏移量。 -
extent
是要解析的源图像在width
、height
和depth
中的纹素大小。
缓冲区标记
要将 32 位标记值作为流水线操作写入缓冲区,请调用
// Provided by VK_AMD_buffer_marker with VK_VERSION_1_3 or VK_KHR_synchronization2
void vkCmdWriteBufferMarker2AMD(
VkCommandBuffer commandBuffer,
VkPipelineStageFlags2 stage,
VkBuffer dstBuffer,
VkDeviceSize dstOffset,
uint32_t marker);
-
commandBuffer
是将记录命令的命令缓冲区。 -
stage
指定触发标记写入的管线阶段的完成。 -
dstBuffer
是将写入标记的缓冲区。 -
dstOffset
是将写入标记的缓冲区中的字节偏移量。 -
marker
是标记的 32 位值。
只有在所有前面的命令至少在指定的管线阶段完成执行后,该命令才会将 32 位标记值写入缓冲区。这包括其他先前的 vkCmdWriteBufferMarker2AMD
命令的完成,只要它们指定的管线阶段与此命令指定的 stage
同时或更早发生。
虽然具有相同 stage
参数的连续缓冲区标记写入会按照提交顺序隐式完成,但缓冲区标记写入和其他操作之间的内存和执行依赖关系必须仍然使用同步命令显式排序。缓冲区标记写入的访问范围属于 VK_ACCESS_TRANSFER_WRITE_BIT
,并且用于标识同步范围的管线阶段必须同时包括 stage
和 VK_PIPELINE_STAGE_TRANSFER_BIT
。
类似于 |
实现可能仅支持在给定时间内进行有限数量的正在进行中的流水线标记写入操作。因此,过多的标记写入操作可能会降低命令执行性能。 |
要将 32 位标记值作为流水线操作写入缓冲区,请调用
// Provided by VK_AMD_buffer_marker
void vkCmdWriteBufferMarkerAMD(
VkCommandBuffer commandBuffer,
VkPipelineStageFlagBits pipelineStage,
VkBuffer dstBuffer,
VkDeviceSize dstOffset,
uint32_t marker);
-
commandBuffer
是将记录命令的命令缓冲区。 -
pipelineStage
是一个 VkPipelineStageFlagBits 值,指定完成时触发标记写入的管线阶段。 -
dstBuffer
是将写入标记的缓冲区。 -
dstOffset
是将写入标记的缓冲区中的字节偏移量。 -
marker
是标记的 32 位值。
只有在所有前面的命令至少执行到指定的管线阶段之后,该命令才会将 32 位标记值写入缓冲区。 这包括完成其他先前 vkCmdWriteBufferMarkerAMD
命令,只要它们指定的管线阶段与此命令指定的 pipelineStage
同时或更早发生。
虽然具有相同 pipelineStage
参数的连续缓冲区标记写入在提交顺序中隐式完成,但缓冲区标记写入和其他操作之间的内存和执行依赖关系必须仍使用同步命令显式排序。 缓冲区标记写入的访问范围属于 VK_ACCESS_TRANSFER_WRITE_BIT
,用于标识同步范围的管线阶段必须包括 pipelineStage
和 VK_PIPELINE_STAGE_TRANSFER_BIT
。
与 |
实现可能仅支持在给定时间内有限数量的流水线标记写入操作,因此过多的标记写入操作可能会降低命令执行性能。 |