4.3 清空和填充图像
和缓冲区一样,也可以把数据直接复制到图像,或使用一个值填充。图像是更大、复杂、不透明的数据结构,所以原生的偏移量和数据通常对应用程序来说是不可见的。[2]
2. Of course, it’s possible to map the memory that is used for backing an image. In particular, when linear tiling is used for an image, this is standard practice. However, in general, this is not recommended.
通过vkCmdClearColorImage()函数调用,可清楚图像数据并填充,原型如下:
void vkCmdClearColorImage (
VkCommandBuffer commandBuffer,
VkImage image,
VkImageLayout imageLayout,
const VkClearColorValue* pColor,
uint32_t rangeCount,
const VkImageSubresourceRange* pRanges);
清除命令被提交到的命令缓冲区通过commandBuffer参数指定。需要被清除数据的图像通过image参数指定,执行清除操作时图像可选的布局通过imageLayout参数指定。
imageLayout可接受的布局为e VK_IMAGE_LAYOUT_GENERAL 和VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL。清除不同布局的图像,在执行清除命令之前,有必要使用管线屏障把它们转移到这两个布局中某一个。
清除图像数据并填充的数据是VkClearColorValue类型的实例,定义如下:
typedef union VkClearColorValue {
float float32[4];
int32_t int32[4];
uint32_t uint32[4];
} VkClearColorValue;VkClearColorValue是一个简单的union类型,有三个可选值,每个都是含有四个元素的数组。一个是浮点类型,一个是带符号整型,一个是无符号。Vulkan将会按照图像格式所明确的类型去读数据。应用程序可以可以按照既定数据类型写入数据。vkCmdClearColorImage()不会执行任何的数据转换,需要应用程序负责正确的填充VkClearColorValue类型的数据。
单次调用vkCmdClearColorImage()可以清除目标图像的任意大小的区域,虽然所有被清除的内存都会被填充相同的内容。如果你需要清除多个区域并填充不同的颜色值,你需要多次调用该函数。然而,如果你想要清除所有区域并填充同样颜色,通过rangeCount指定区域的数量,传入一个指针pRanges,指向大小为rangeCount、类型为VkImageSubresourceRange的数组。VkImageSubresourceRange定义如下:
typedef struct VkImageSubresourceRange {
VkImageAspectFlags aspectMask;
uint32_t baseMipLevel;
uint32_t levelCount;
uint32_t baseArrayLayer;
uint32_t layerCount;
} VkImageSubresourceRange;这个数据结构在第二章“内存和资源”有所介绍,讨论图像视图的创建的小节。这里,它被用来定义图像里你想清空并填充数据的区域。因为我们正在清空颜色图像,aspectMask须置为VK_IMAGE_ASPECT_COLOR_BIT。baseMipLevel 和 levelCount域用来指定mipmap起始层和需要被清空数据的层数,如果图像是array image,baseArrayLayer 和 layerCount域用来指定起始层和需要被清空的层数。如果图像不是array image,这些域应各置为0和1。
清空depth-stencil图像与清空颜色图像相似,除了一个VkClearDepthStencilValue类型的数据用来指定填充的数据。vkCmdClearDepthStencilImage()的原型和vkCmdClearColorImage()原型类似,其原型如下:
void vkCmdClearDepthStencilImage (
VkCommandBuffer commandBuffer,
VkImage image,
VkImageLayout imageLayout,
const VkClearDepthStencilValue* pDepthStencil,
uint32_t rangeCount,
const VkImageSubresourceRange * pRanges);
同样,将执行清除操作的命令缓冲区通过commandBuffer参数指定,需要被清空的图像由image参数指定,清空操作执行时期待的图像布局通过imageLayout参数指定。和vkCmdClearColorImage()一样,imageLayout值为VK_IMAGE_LAYOUT_GENERAL 或
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL二者其一。对于清空操作没有其他的有效可选。
清空后填充的数据通过一个VkClearDepthStencilValue类型的数据传递,它包含深度和stencil数值。它的定义如下:
typedef struct VkClearDepthStencilValue {
float depth;
uint32_t stencil;
} VkClearDepthStencilValue;
和vkCmdClearColorImage()一样,一次vkCmdClearDepthStencilImage()调用可以清空多个图像。可以清空的数量通过rangeCount指定,pRanges参数指向了一个大小为rangeCount、类型为VkImageSubresourceRange的数组,数组定义可以清空的范围。
因为depth-stencil图像包含深度和stencil aspect,pRanges的每一个成员的aspectMask都可包含VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_ASPECT_STENCIL_BIT中一个或者两个。如果aspectMask包含VK_IMAGE_ASPECT_DEPTH_BIT,那么存储在VkClearDepthStencilValue结构的深度域将会被用来填充深度aspect的那块区域。同样,如果aspectMask包含VK_IMAGE_ASPECT_STENCIL_BIT,那么深度aspect的那块区域将会被清空并填充VkClearDepthStencilValue类型数据stencil域的数据。
注意,通常给单个区域指定VK_IMAGE_ASPECT_DEPTH_BIT 和 VK_IMAGE_ASPECT_STENCIL_BIT属性,回避单独指定一个属性要高效率的多。