vkCmdSetEvent,vkCmdResetEvent —— 设备端发送信号或者重置信号给事件
设备端的事件可以通过指令缓存更新为“已设置”或者“已重置”这里用到了 vkCmdSetEvent() 和 vkCmdResetEvent() 函数来向事件发送信号或者重置信号。
这两个函数都有三个参数:第一个参数 commandBuffer 设置了录制指令时用到的指令缓存;第二个参数 event 设置了事件对象的句柄,我们可以向它发送信号或者重置;最后一个参数 stageMask 的类型为 VkPipelineStageFlags,即流水线阶段。表示这个事件需要在什么阶段进行更新。
VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent( VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask); VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent( VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask);
vkCmdWaitEvents —— 等待事件对象
VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents( VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers);
理解描述符的概念
描述符由描述符集对象构成。这些对象的内部负责记录一组描述符。描述符集可以关联着色器和相关用户资源,例如一致变量缓存、采样图像、存储图像等,进而在着色器中读取和解析资源中的数据,着色器中需要通过描述符集布局来定义对应的布局绑定信息。例如,我们可以通过描述符实现图像纹理、采样器以及缓存等资源与着色器的绑定。描述符是一种不透明的对象,它定义了一种通信协议和着色器进行通信。在系统内部,描述符提供了一种静默的机制,通过位置绑定的方式来关联资源内存和着色器。
描述符集布局
描述符集布局指的是一组描述符绑定信息,可以是 0 个元素或者更多。它提供了一个在着色器中读取特定位置的资源的接口。每个描述符绑定信息都有自己特定的类型,对应于准备处理的资源类型,其中包含了绑定中的描述符数量,采样描述符的数组,以及与之相关联的着色器阶段。这些元数据都是在 VkDescriptorSetLayoutBinding 中定义的。如下图所示为描述符集的布局内容,其中包含了多种不同的资源布局绑定信息,在描述符布局中定义的每个资源都设置了一个唯一的标识绑定数字。
vkCreateDescriptorSetLayout —— 创建描述符集布局
描述符集布局的创建可以通过 API 函数 vkCreateDescriptorSetLayout() 来完成。这个函数的输入参数包括一个 VkDescriptorSetLayoutCreateInfo 结构体,用于处理零个到多个描述符集的元数据信息,其中还包含了一个 VkDescriptorSetLayoutBinding 结构体。
VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorSetLayout( VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout);
- VkDescriptorSetLayoutCreateInfo
typedef struct VkDescriptorSetLayoutCreateInfo { VkStructureType sType; const void* pNext; VkDescriptorSetLayoutCreateFlags flags; // 描述符集布局绑定数量 uint32_t bindingCount; // 描述符集布局绑定对象 const VkDescriptorSetLayoutBinding* pBindings; } VkDescriptorSetLayoutCreateInfo;
- VkDescriptorSetLayoutBinding
typedef struct VkDescriptorSetLayoutBinding { // 设置绑定索引值,即当前资源类型,这个索引值必须和对应着色器阶段中标识的绑定数值相同 uint32_t binding; // 设置绑定所用的描述符类型 VkDescriptorType descriptorType; // 设置着色器中用到的描述符的数组元素数量 uint32_t descriptorCount; // 设置当前可以访问描述符的着色器阶段类型 VkShaderStageFlags stageFlags; // 设置采样器句柄的数组指针 const VkSampler* pImmutableSamplers; } VkDescriptorSetLayoutBinding;
vkDestroyDescriptorSetLayout —— 销毁描述符集布局
VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorSetLayout( VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator);
流水线布局
理解流水线布局
流水线布局允许一个流水线(图形或者计算)对象直接访问描述符集。流水线布局对象包含了一组描述符集布局和推送常数,它代表了底层流水线可以访问的所有资源的集合。
流水线布局对象的属性信息通过结构体 VkGraphicsPipelineCreateInfo 来提供,然后传递给 API 函数 vkCreateGraphicsPipelines() 来创建流水线。这些属性信息是通过参数 VkGraphicsPipelineCreateInfo::layout 设置的。这个参数是必须设置的。如果应用程序没有用到描述符集,那么这里必须设置一个空的描述符布局并且将对应的流水线布局设置给流水线对象 (VkPipeline)的创建函数。
流水线布局中可以连续包含零个或者多个描述符集,每个集合中都包含了一个特定的布局对象。布局定义了着色器阶段和着色器资源之间的接口。如下图所示为流水线布局的内容,其中包括了多个描述符布局,每个布局中包含了针对多种不同的资源类型的布局绑定。
vkCreatePipelineLayout —— 创建流水线布局
VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineLayout( VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout);
- VkPipelineLayoutCreateInfo
typedef struct VkPipelineLayoutCreateInfo { VkStructureType sType; const void* pNext; VkPipelineLayoutCreateFlags flags; uint32_t setLayoutCount; const VkDescriptorSetLayout* pSetLayouts; uint32_t pushConstantRangeCount; const VkPushConstantRange* pPushConstantRanges; } VkPipelineLayoutCreateInfo; typedef enum VkPipelineLayoutCreateFlagBits { VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT = 0x00000002, VK_PIPELINE_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkPipelineLayoutCreateFlagBits; typedef VkFlags VkPipelineLayoutCreateFlags; typedef VkFlags VkShaderStageFlags; typedef struct VkPushConstantRange { // 定义了推送常数范围所对应的着色器阶段,如 VK_SHADER_STAGE_FRAGMENT_BIT // VK_SHADER_STAGE_VERTEX_BIT,VK_SHADER_STAGE_COMPUTE_BIT VkShaderStageFlags stageFlags; // 这个参数设置了推送常数范围的起始偏移值,单位为字节,且必须是 4 的倍数 uint32_t offset; // 这个参数单位也是字节,且必须是 4 的倍数,它设置了推送常数范围的数据大小 uint32_t size; } VkPushConstantRange;
vkDestroyPipelineLayout —— 销毁流水线布局
VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineLayout( VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator);
描述符池
vkCreateDescriptorPool —— 创建描述符池
Vulkan 当中的描述符集是不能被直接创建的。它们首先需要从一个特定的缓冲池中被分配得到,这个池叫作描述符池。描述符池负责分配新的描述符对象。换句话说,它相当于一组描述符的集合,新的描述符集就是从这些描述符中分配得到的。
VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorPool( VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool);
- VkDescriptorPoolCreateInfo
typedef struct VkDescriptorPoolCreateInfo { VkStructureType sType; const void* pNext; VkDescriptorPoolCreateFlags flags; uint32_t maxSets; uint32_t poolSizeCount; const VkDescriptorPoolSize* pPoolSizes; } VkDescriptorPoolCreateInfo; typedef enum VkDescriptorPoolCreateFlagBits { VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001, VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT = 0x00000002, VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT = 0x00000004, VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT, VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE = VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT, VK_DESCRIPTOR_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkDescriptorPoolCreateFlagBits; typedef VkFlags VkDescriptorPoolCreateFlags; typedef VkFlags VkDescriptorPoolResetFlags;
创建描述符集的资源
在描述符集创建之前,我们必须首先创建与它绑定的资源对象。我们将创建一个一致变量缓存资源,之后将它与描述符集进行关联。
在现在的示例程序中,我们通过 VulkanDrawable 类实现上面的函数接口,从而创建一个一致变量缓存并向其中保存一个 4×4 的变换矩阵。为此,我们需要首先创建缓存类型的资源。注意,Vulkan 中的资源有两种类型:缓存和图像。
创建描述符集
描述符集的创建主要包括两个步骤:
- 描述符集的分配:从描述符池中分配新的描述符集。
- 资源的关联:将描述符集关联到刚创建的资源数据。
vkAllocateDescriptorSets —— 从描述符池中分配新的描述符集
描述符集是通过 API 函数 vkAllocateDescriptorSets() 从描述符池中分配得到的。这个函数需要三个输入参数:第一个参数 device 设置了描述符池所在的逻辑设备(类型为 VkDevice);第二个参数 pAllocateInfo 是结构体 VkDescriptorSetAllocateInfo 的对象指针,它记录了从描述符池中进行分配所需的各种参数;最后一个参数 pDescriptorSets 是 VkDescriptorSet 数组的指针,它返回了分配得到的各个描述符集的句柄
VKAPI_ATTR VkResult VKAPI_CALL vkAllocateDescriptorSets( VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets);
- VkDescriptorSetAllocateInfo
typedef struct VkDescriptorSetAllocateInfo { VkStructureType sType; const void* pNext; VkDescriptorPool descriptorPool; uint32_t descriptorSetCount; const VkDescriptorSetLayout* pSetLayouts; } VkDescriptorSetAllocateInfo;
vkFreeDescriptorSets —— 从描述符池中分配新的描述符集
VKAPI_ATTR VkResult VKAPI_CALL vkFreeDescriptorSets( VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets);
vkUpdateDescriptorSets —— 关联资源与描述符集
描述符集可以与资源信息直接进行关联,并且通过 API 函数 vkUpdateDescriptorSets() 进行更新。这个函数有四个参数:第一个参数 device 是负责更新描述符集的逻辑设备。这个逻辑设备同时也应当是拥有这些描述符集的设备;第二个参数 descriptorWriteCount 设置了 pDescriptorWrites 数组(类型为 VkCopyDescriptorSet )中的元素个数。第三个参数 pDescriptorWrites 是一个 VkWriteDescriptorSet 对象数组的指针;第四个参数 descriptorCopyCount 设置了 pDescriptorCopies 数组中的元素个数;最后一个参数 pDescriptorCopies 设置的是我们需要复制的 VkCopyDescriptorSet 数组对象的指针。
VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSets( VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies);
整个更新的过程包括了两类操作,也就是写入和复制操作。
写入:分配后的描述符集的更新可以通过填充零个或多个 VkWriteDescriptorSet 结构体对象组成的元素数组的方式来完成,其中包含了资源相关的信息,包括缓存数据、绑定索引等。写入的操作是在 API 函数 vkUpdateDescriptorSets() 中完成的。这个函数直接将填充后的 VkWriteDescriptorSet 结构体对象作为参数传入。
复制:复制操作需要用到目前已有的描述符集,并且将它们的信息复制到目标描述符集中。复制操作是通过结构体 VkCopyDescriptorSet 来具体设置的。我们同样可能用到零个或者多个复制操作的结构体对象。
VkWriteDescriptorSet
typedef struct VkWriteDescriptorSet { VkStructureType sType; const void* pNext; // 设置更新对应的目标描述符集 VkDescriptorSet dstSet; /// 设置集合内的描述符绑定参数 uint32_t dstBinding; // 设置描述符数组中的起始元素索引 uint32_t dstArrayElement; // 设置要更新的描述符的数量,如果设置了以下参数的话:pImageInfo、pBufferInfo // 或 pTexelBufferView uint32_t descriptorCount; // 设置每个参与计算的描述符的类型(pImageInfo、pBufferInfo或 pTexelBufferView) VkDescriptorType descriptorType; // 设置一个 VkDescriptorImageInfo 结构体数组,表示图像资源 const VkDescriptorImageInfo* pImageInfo; const VkDescriptorBufferInfo* pBufferInfo; const VkBufferView* pTexelBufferView; } VkWriteDescriptorSet;
VkCopyDescriptorSet
typedef struct VkCopyDescriptorSet { VkStructureType sType; const void* pNext; // 设置复制操作的源描述符集数组 VkDescriptorSet srcSet; // 设置源描述符集的绑定索引 uint32_t srcBinding; // 设置源描述符集数组中的起始元素索引 uint32_t srcArrayElement; // 设置复制操作的目标描述符集数组 VkDescriptorSet dstSet; // 设置目标描述符集的绑定索引 uint32_t dstBinding; // 设置目标描述符集数组中的起始元素索引 uint32_t dstArrayElement; // 设置准备从源复制到目标数组中的描述符集总数 uint32_t descriptorCount; } VkCopyDescriptorSet;
vkCmdPushConstants —— 更新资源数据
VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants( VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues);
示例:
unsigned pushConstants[2] = {}; pushConstants[0] = constColorRGBFlag; memcpy(&pushConstants[1], &mixerValue, sizeof(float)); vkCmdPushConstants(cmdPushConstant, drawableObj->pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(pushConstants), pushConstants);
纹理
vkGetImageSubresourceLayout —— 查询资源的布局信息
VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout( VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout);
- VkImageSubresource
typedef struct VkImageSubresource { VkImageAspectFlags aspectMask; uint32_t mipLevel; uint32_t arrayLayer; } VkImageSubresource;
vkCreateSampler —— 创建一个图像采样器
采样器是一个包含了一系列算法的对象,这些算法用来控制格式化图像数据的显示方法,其中包含了多种不同的参数。这些参数可以用来控制图像的变换、缩小和放大滤波、mipmap 分级、边界裁切方式,并最终生成图像纹素的采样结果。
Vulkan 中的图像采样器创建需要用到 API 函数 vkCreateSampler() 。这个 API 函数支持四个输入参数:第一个参数 device 是创建采样器对象所用的逻辑设备;第二个参数是图像属性的控制结构体,类型为 VkSamplerCreateInfo,在最后一个参数 pSampler 是图像采样器;第三个参数 pAllocator 负责控制宿主机内存的分配;这个函数将创建并返回一个采样器对象。
VKAPI_ATTR VkResult VKAPI_CALL vkCreateSampler( VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler);
- VkSamplerCreateInfo
typedef struct VkSamplerCreateInfo { VkStructureType sType; const void* pNext; VkSamplerCreateFlags flags; VkFilter magFilter; // 放大滤波 VkFilter minFilter; // 缩小滤波 VkSamplerMipmapMode mipmapMode; // 滤波模式,线性模式、临近模式 // 当纹理坐标超过了[0..1]范围的时候,这个参数控制图像在U坐标轴上的截取方式 VkSamplerAddressMode addressModeU; // 当纹理坐标超过了[0..1]范围的时候,这个参数控制图像在V坐标轴上的截取方式 VkSamplerAddressMode addressModeV; // 当纹理坐标超过了[0..1]范围的时候,这个参数控制图像在W坐标轴上的截取方式 VkSamplerAddressMode addressModeW; float mipLodBias; // 浮点数偏移量 VkBool32 anisotropyEnable; // 控制各向异性滤波是否开启 float maxAnisotropy; // 截取时的最大各向异性滤波值 // 控制滤波查找过程中是否要和一个参考值进行比较计算 VkBool32 compareEnable; VkCompareOp compareOp; // 比较函数 float minLod; // 设置 LOD 计算过程中所使用的最小截取值 float maxLod; // 设置 LOD 计算过程中所使用的最大截取值 VkBorderColor borderColor; // 预定义颜色 VkBool32 unnormalizedCoordinates; // 控制否是使用归一化的纹素坐标查找 } VkSamplerCreateInfo;
- VkSamplerCreateFlags
typedef enum VkSamplerCreateFlagBits { VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT = 0x00000001, VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT = 0x00000002, VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT = 0x00000004, VK_SAMPLER_CREATE_IMAGE_PROCESSING_BIT_QCOM = 0x00000010, VK_SAMPLER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkSamplerCreateFlagBits; typedef VkFlags VkSamplerCreateFlags;
- VkFilter
typedef enum VkFilter { VK_FILTER_NEAREST = 0, VK_FILTER_LINEAR = 1, VK_FILTER_CUBIC_EXT = 1000015000, VK_FILTER_CUBIC_IMG = VK_FILTER_CUBIC_EXT, VK_FILTER_MAX_ENUM = 0x7FFFFFFF } VkFilter;
- VkSamplerMipmapMode
typedef enum VkSamplerMipmapMode { VK_SAMPLER_MIPMAP_MODE_NEAREST = 0, VK_SAMPLER_MIPMAP_MODE_LINEAR = 1, VK_SAMPLER_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF } VkSamplerMipmapMode;
- VkSamplerAddressMode
typedef enum VkSamplerAddressMode { VK_SAMPLER_ADDRESS_MODE_REPEAT = 0, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE_KHR = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF } VkSamplerAddressMode;
- VkCompareOp
typedef enum VkCompareOp { VK_COMPARE_OP_NEVER = 0, VK_COMPARE_OP_LESS = 1, VK_COMPARE_OP_EQUAL = 2, VK_COMPARE_OP_LESS_OR_EQUAL = 3, VK_COMPARE_OP_GREATER = 4, VK_COMPARE_OP_NOT_EQUAL = 5, VK_COMPARE_OP_GREATER_OR_EQUAL = 6, VK_COMPARE_OP_ALWAYS = 7, VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF } VkCompareOp;
- VkBorderColor
typedef enum VkBorderColor { VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0, VK_BORDER_COLOR_INT_TRANSPARENT_BLACK = 1, VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK = 2, VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3, VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4, VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5, VK_BORDER_COLOR_FLOAT_CUSTOM_EXT = 1000287003, VK_BORDER_COLOR_INT_CUSTOM_EXT = 1000287004, VK_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF } VkBorderColor;
- VkAllocationCallbacks
typedef struct VkAllocationCallbacks { void* pUserData; PFN_vkAllocationFunction pfnAllocation; PFN_vkReallocationFunction pfnReallocation; PFN_vkFreeFunction pfnFree; PFN_vkInternalAllocationNotification pfnInternalAllocation; PFN_vkInternalFreeNotification pfnInternalFree; } VkAllocationCallbacks;
滤波
当纹理被放大或者缩小的时候,纹理滤波方式可以控制纹理显示的质量。在某个深度值上,一个纹素可能正好等于屏幕上一个像素的大小。但是,如果我们贴敷一个较小的纹理到较大的几何体上,那么纹理将被拉伸。这一过程被称作放大。换句话说,这个时候图像的尺寸小于被映射的几何体的尺寸。反之,如果几何体尺寸小于图像的尺寸,那么多个纹素将共享同一个像素,此时显示的图像将被压缩,称作缩小。
放大和缩小的图像效果可以通过滤波模式参数来设置。Vulkan 中使用 VkFilter 枚举量来完成这一操作。这个枚举量的两个取值如下所示:
VK_FILTER_NEAREST:采样器将使用给定的纹理坐标附近最近的纹素值。
VK_FILTER_LINEAR:采样器将计算给定纹理坐标附近四个最近的像素的加权平均值。
边界截取方式
如果纹理映射的 U、V、W 坐标超出了 1.0,那么 Vulkan 支持多种采样寻址模式,类型为 VkSamplerAddressMode。Vulkan 采样时可以支持下面几种不同的边界截取寻址方式:
VK_SAMPLER_ADDRESS_MODE_REPEAT:产生重复的花纹。
VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT:产生重复的花纹,邻接的纹素采用镜像的方式。
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:产生重复的边界纹素直到边缘位置;
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER:直接截断边界之外的纹素。
如图11-2所示,我们设置纹理坐标范围比[0…1]更大,并且演示
了几种不同的截取方式的执行结果。
vkCmdCopyBuffer —— 数据内容从源缓存对象复制到目标缓存对象的设备内存中
VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer( VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions);
vkCmdCopyImage —— 源图像对象的一部分复制到目标图像区域中
VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage( VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions);
vkCmdCopyBufferToImage —— 缓存对象的数据内容被复制到图像对象中
VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage( // 指令缓存对象 VkCommandBuffer commandBuffer, // 数据内容复制的数据源 VkBuffer srcBuffer, // 数据内容将被复制到其中 VkImage dstImage, // 设置 dstImage 对象的图像布局对象 VkImageLayout dstImageLayout, // 设置传输数据内容时要复制的区域的总数 uint32_t regionCount, // 数组指针,包含了所有需要复制数据的区域信息 const VkBufferImageCopy* pRegions);
- VkImageLayout
typedef enum VkImageLayout { VK_IMAGE_LAYOUT_UNDEFINED = 0, VK_IMAGE_LAYOUT_GENERAL = 1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7, VK_IMAGE_LAYOUT_PREINITIALIZED = 8, ... VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF } VkImageLayout;
- VkBufferImageCopy
typedef struct VkBufferImageCopy { VkDeviceSize bufferOffset; uint32_t bufferRowLength; uint32_t bufferImageHeight; VkImageSubresourceLayers imageSubresource; VkOffset3D imageOffset; VkExtent3D imageExtent; } VkBufferImageCopy;
- VkImageSubresourceLayers
typedef struct VkImageSubresourceLayers { VkImageAspectFlags aspectMask; uint32_t mipLevel; uint32_t baseArrayLayer; uint32_t layerCount; } VkImageSubresourceLayers;
- VkOffset3D
typedef struct VkOffset3D { int32_t x; int32_t y; int32_t z; } VkOffset3D;
- VkExtent3D
typedef struct VkExtent3D { uint32_t width; uint32_t height; uint32_t depth; } VkExtent3D;
vkCmdCopyImageToBuffer —— 图像对象的数据内容被复制到缓存对象中
VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer( VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions);