现代 C++ 部分的学习和总结也差不多了。最后以 Vulkan 总结来收尾吧!Vulkan 已经玩了快两年了,官方教程和官方示例也算是被我玩烂了。自己也写了几版基于 Vulkan 的渲染接口。然而最近发现 Vulkan 支持了 RAII,再重写一版吧!毕竟相比自己设计的 RAII,还是官方的更香。Vulkan 规范只看完了前六章,暂时放一下,以后再找时间看吧。毕竟学函数式编程和模板元编程花了太多的时间。好在买《Template》的时候看到了《Vulkan应用开发指南》这本书。正好可以作为 Vulkan 阶段性总结的资料。
VkResult vkCreateInstance (
const VkInstanceCreateInfo* pCreateInfo,
//指向主机内存分配器的指针
//该分配器由应用程序提供,用于管理 Vulkan 系统使用的主机内存
//设置为 nullptr 会导致 Vulkan 系统使用它内置的分配器
const VkAllocationCallbacks* pAllocator,
//64 位宽,与主机系统的位数无关
VkInstance* pInstance
);
VkInstanceCreateInfo
typedef struct VkInstanceCreateInfo
{
//结构体的类型
//默认 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
VkStructureType sType;
//将一个相连的结构体链表传入函数
//默认 nullptr,但是推荐填充为有用的信息
const void* pNext;
//保留字段,设置为 0
VkInstanceCreateFlags flags;
const VkApplicationInfo* pApplicationInfo;
//激活的实例层的个数,不需要层,将其设置为 0
//提供日志、性能分析、调试或者其他特性
uint32_t enabledLayerCount;
//激活的实例层的名称,不需要层,将其设置为 nullptr
const char* const* ppEnabledLayerNames;
//激活的扩展的个数,不需要扩展,将其设置为 0
uint32_t enabledExtensionCount;
//激活的扩展的名称,不需要扩展,将其设置为 nullptr
const char* const* ppEnabledExtensionNames;
} VkInstanceCreateInfo;
VkApplicationInfo
typedef struct VkApplicationInfo
{
//默认值 VK_STRUCTURE_TYPE_APPLICATION_INFO
VkStructureType sType;
//默认值 nullptr
const void* pNext;
//应用程序名称,字符串类型
const char* pApplicationName;
//应用程序的版本号
//用于标识正在执行的程序,以便工具和驱动识别
uint32_t applicationVersion;
//引擎或中间件的名称与版本号
const char* pEngineName;
uint32_t engineVersion;
//使用 Vulkan API 的版本号
uint32_t apiVersion;
} VkApplicationInfo;
VkResult vkEnumeratePhysicalDevices (
VkInstance instance,
//同时作为输入和输出
//作为输出, Vulkan 将系统里的物理设备数量写入该指针变量
//作为输入, 它会初始化为应用程序能够处理的设备的最大数量
uint32_t* pPhysicalDeviceCount,
//指向 VkPhysicalDevice 句柄数组的指针
VkPhysicalDevice* pPhysicalDevices
);
vkEnumeratePhysicalDevices()
两次,动态调整 VkPhysicalDevice
数组的大小
pPhysicalDevices
设置为 nullptr
pPhysicalDevices
设置为一个数组
void vkGetPhysicalDeviceProperties (
VkPhysicalDevice physicalDevice,
//包含大量描述物理设备属性的字段
VkPhysicalDeviceProperties* pProperties
);
VkPhysicalDeviceProperties
typedef struct VkPhysicalDeviceProperties
{
//设备支持 Vulkan 的最高版本
uint32_t apiVersion;
//了用于控制设备的驱动的版本号, 硬件生产商特定的
uint32_t driverVersion;
//标识生产商, 通常是 PCI 生产商
uint32_t vendorID;
//标识设备标识符
uint32_t deviceID;
VkPhysicalDeviceType deviceType;
//设备名称
char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE];
//用于管线缓存
uint8_t pipelineCacheUUID[VK_UUID_SIZE];
//包含物理设备的最大和最小限制
VkPhysicalDeviceLimits limits;
//稀疏纹理有关的属性
VkPhysicalDeviceSparseProperties sparseProperties;
} VkPhysicalDeviceProperties;
void vkGetPhysicalDeviceFeatures (
VkPhysicalDevice physicalDevice,
//Vulkan 支持的每一个可选特性都有一个布尔类型的字段
VkPhysicalDeviceFeatures* pFeatures
);
void vkGetPhysicalDeviceMemoryProperties (
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceMemoryProperties* pMemoryProperties
);
VkPhysicalDeviceMemoryProperties
typedef struct VkPhysicalDeviceMemoryProperties
{
//内存类型数量
//可能为内存类型的最大数量 VK_MAX_MEMORY_TYPES 定义的值 (定义为 32)
uint32_t memoryTypeCount;
//VkMemoryType 描述内存类型
VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES];
uint32_t memoryHeapCount;
//每一个元素描述了设备的一个内存堆
VkMemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS];
} VkPhysicalDeviceMemoryProperties;
VkMemoryType
typedef struct VkMemoryType
{
//标志位描述内存的类型
//由 VkMemoryPropertyFlagBits 类型的标志位组合而成
VkMemoryPropertyFlags propertyFlags;
//每种内存类型都指定了从哪个堆上使用空间
//内存类型的堆栈索引
uint32_t heapIndex;
} VkMemoryType;
VkMemoryPropertyFlagBits
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
VkMemoryHeap
typedef struct VkMemoryHeap
{
//堆的大小(单位是字节)
VkDeviceSize size;
//描述堆的标识符
//在 Vulkan 1.0 中,唯一标识符是 VK_MEMORY_HEAP_DEVICE_LOCAL_BIT
//如果定义,堆对于设备来说就是本地的
VkMemoryHeapFlags flags;
} VkMemoryHeap;
//调用方式与 vkEnumeratePhysicalDevices 相似,支持两次调用
void vkGetPhysicalDeviceQueueFamilyProperties
(
VkPhysicalDevice physicalDevice,
uint32_t* pQueueFamilyPropertyCount,
VkQueueFamilyProperties* pQueueFamilyProperties
);
VkQueueFamilyProperties
typedef struct VkQueueFamilyProperties
{
//描述队列的所有功能, VkQueueFlagBits 类型的标志位的组合组成
VkQueueFlags queueFlags;
//族里的队列数量
uint32_t queueCount;
//表示当从队列里取时间戳时,多少位有效
//如果为 0,队列不支持时间戳
//如果不是 0,保证最少支持 36 位
uint32_t timestampValidBits;
//队列传输图像时支持多少单位(如果有的话)
VkExtent3D minImageTransferGranularity;
} VkQueueFamilyProperties;
VkPhysicalDeviceLimits
里的字段 timestampComputeAndGraphics
是 VK_TRUE
,那么所有支持 VK_QUEUE_GRAPHICS_BIT
或 VK_QUEUE_COMPUTE_BIT
的队列都能保证支持 36 位的时间戳
VkQueueFlagBits
VK_QUEUE_GRAPHICS_BIT
VK_QUEUE_COMPUTE_BIT
VK_QUEUE_TRANSFER_BIT
VK_QUEUE_SPARSE_BINDING_BIT
VkResult vkCreateDevice (
VkPhysicalDevice physicalDevice,
const VkDeviceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDevice* pDevice
);
VkDeviceCreateInfo
typedef struct VkDeviceCreateInfo
{
//VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO
VkStructureType sType;
//除非希望使用扩展,否则 pNext 应设置为 nullptr
const void* pNext;
//设置为 0
VkDeviceCreateFlags flags;
uint32_t queueCreateInfoCount;
//描述一个或者多个队列
const VkDeviceQueueCreateInfo* pQueueCreateInfos;
//下面四个字段激活层和扩展
uint32_t enabledLayerCount;
const char* const* ppEnabledLayerNames;
uint32_t enabledExtensionCount;
const char* const* ppEnabledExtensionNames;
//指明哪些可选扩展是应用程序希望使用的
//设置为 nullpt,不使用
//激活不会使用的特性会影响程序性能
const VkPhysicalDeviceFeatures* pEnabledFeatures;
} VkDeviceCreateInfo;
VkDeviceQueueCreateInfo
typedef struct VkDeviceQueueCreateInfo
{
//VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO
VkStructureType sType;
const void* pNext;
//设置为 0
VkDeviceQueueCreateFlags flags;
//指定希望创建的队列所属的族
uint32_t queueFamilyIndex;
//创建的队列个数
//设备支持的队列数量必须不小于这个值
uint32_t queueCount;
//可选的指针, 指向浮点数数组,表示提交给每个队列的工作的相对优先级
//取值范围是 0.0~1.0
//设置为 nullptr 所有的队列都指定相同的默认优先级
//所有设备最少支持两个离散的优先级
const float* pQueuePriorities;
} VkDeviceQueueCreateInfo;
VkResult vkEnumerateInstanceLayerProperties (
//pProperties 是 nullptr, pPropertyCount 应该指向一个变量
//返回数量
//pProperties 不是 nullptr
//为 pProperties 数组的长度
uint32_t* pPropertyCount,
//不是 nullptr 会向这个数组填充关于系统里注册的层的信息
VkLayerProperties* pProperties
);
VkLayerProperties
typedef struct VkLayerProperties
{
//名称
char layerName[VK_MAX_EXTENSION_NAME_SIZE];
//层实现的版本号
uint32_t specVersion;
//具体实现的版本号
uint32_t implementationVersion;
//描述层的可读字符串
char description[VK_MAX_DESCRIPTION_SIZE];
} VkLayerProperties;
VkResult vkEnumerateDeviceLayerProperties (
VkPhysicalDevice physicalDevice,
uint32_t* pPropertyCount,
VkLayerProperties* pProperties
);
VK_LAYER_LUNARG_api_dump
VK_LAYER_LUNARG_core_validation
VK_LAYER_LUNARG_device_limits
VK_LAYER_LUNARG_image
VK_LAYER_LUNARG_object_tracker
VK_LAYER_LUNARG_parameter_validation
VK_LAYER_LUNARG_swapchain
VK_LAYER_GOOGLE_threading
VK_LAYER_GOOGLE_unique_objects
VK_LAYER_LUNARG_standard_validation
//用法与vkEnumerateInstanceLayerProperties类似
VkResult vkEnumerateInstanceExtensionProperties (
//可能提供扩展的层的名字, 该字段设置为 nullptr。
const char* pLayerName,
//扩展的数量
uint32_t* pPropertyCount,
//填充支持的扩展的信息
VkExtensionProperties* pProperties
);
VkExtensionProperties
typedef struct VkExtensionProperties
{
//扩展名
char extensionName[VK_MAX_EXTENSION_NAME_SIZE];
//版本号
uint32_t specVersion;
} VkExtensionProperties;
//类似 vkEnumerateInstanceExtensionProperties
VkResult vkEnumerateDeviceExtensionProperties (
VkPhysicalDevice physicalDevice,
const char* pLayerName,
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties
);
PFN_vkVoidFunction vkGetInstanceProcAddr (
//需要获取函数指针的实例的句柄
VkInstance instance,
//函数名, UTF-8 类型的字符串
const char* pName
);
PFN_vkVoidFunction vkGetDeviceProcAddr (
VkDevice device,
const char* pName
);
vkDeviceWaitIdle(VkDevice device)
void vkDestroyDevice (
VkDevice device,
const VkAllocationCallbacks* pAllocator
);
void vkDestroyInstance (
VkInstance instance,
const VkAllocationCallbacks* pAllocator
);
主机内存
只有存储在 CPU 端的数据结构是对齐的,Vulkan 才可以使用高性能指令,提升性能
vkCreateInstance()
的 VkAllocationCallbacks
typedef struct VkAllocationCallbacks
{
//指针供应用程序使用
//可以指向任何位置
//Vulkan 不会解引用它
//可以放任何东西,需适配一个指针大小的 blob
//传回 VkAllocationCallback 其余成员指向的回调函数
void* pUserData;
//用于普通的、对象级别的内存管理
PFN_vkAllocationFunction pfnAllocation;
//用于普通的、对象级别的内存管理
PFN_vkReallocationFunction pfnReallocation;
//用于普通的、对象级别的内存管理
PFN_vkFreeFunction pfnFree;
//指向代替 Vulkan 自带分配器的替换函数
//不返回值
//仅仅用于通知
//作用:程序可以跟踪 Vulkan 的内存使用量
PFN_vkInternalAllocationNotification pfnInternalAllocation;
//指向代替 Vulkan 自带分配器的替换函数
//不应真的释放内存
//仅仅用于通知
PFN_vkInternalFreeNotification pfnInternalFree;
} VkAllocationCallbacks;
pfnAllocation
函数指针所指的函数
//负责新的内存分配
void* VKAPI_CALL Allocation(
void* pUserData,
//指定分配多少字节
size_t size,
//指定以多少字节进行内存对齐
size_t alignment,
//内存分配的范围和生命周期是什么样的
VkSystemAllocationScope allocationScope
);
pfnReallocation
函数指针所指的函数
void* VKAPI_CALL Reallocation(
void* pUserData,
void* pOriginal
size_t size,
size_t alignment,
VkSystemAllocationScope allocationScope
);
pfnFree
函数指针所指的函数
void VKAPI_CALL Free(
void* pUserData,
void* pMemory
);
pUserData
的合理实现
VkSystemAllocationScope
VkPipelineCache
对象相关联vkCreateInstance()
, vkEnumeratePhysicalDevices()
pfnInternalAllocation
void VKAPI_CALL InternalAllocationNotification(
void* pUserData,
size_t size,
VkInternalAllocationType allocationType,
VkSystemAllocationScope allocationScope
);
pfnInternalFree
void VKAPI_CALL InternalFreeNotification(
void* pUserData,
size_t size,
VkInternalAllocationType allocationType,
VkSystemAllocationScope allocationScope
);
pfnInternalAllocation
和 pfnInternalFree
声明一个能够用作分配器的 C++ 类
VkResult vkCreateBuffer (
VkDevice device,
const VkBufferCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkBuffer* pBuffer
);
pCreateInfo
typedef struct VkBufferCreateInfo
{
//VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO
VkStructureType sType;
//默认使用 nullptr,使用扩展除外
const void* pNext;
//缓冲区的属性信息
VkBufferCreateFlags flags;
//缓冲区的大小,以字节为单位
VkDeviceSize size;
//你如何使用缓冲区
VkBufferUsageFlags usage;
//缓冲区在设备支持的多个缓冲区队列中如何使用
VkSharingMode sharingMode;
uint32_t queueFamilyIndexCount;
//sharingMode 当设置为 VK_SHARING_MODE_CONCURRENT
//告诉 Vulkan 哪些队列将使用这个缓冲区
//sharingMode 当设置为 VK_SHARING_MODE_EXCLUSIVE
//这两个字段被忽略
const uint32_t* pQueueFamilyIndices;
} VkBufferCreateInfo;
VkBufferUsageFlagBits
sharingMode
确定各种格式的属性和支持级别
void vkGetPhysicalDeviceFormatProperties (
VkPhysicalDevice physicalDevice,
//待检查的格式
VkFormat format,
//如果设备能识别格式,将把支持级别写入
VkFormatProperties* pFormatProperties
);
如果应用程序必须要求支持某些格式,可以在创建逻辑设备之前做检查并且在应用程序启动时拒用特定的物理设备
VkFormatProperties
typedef struct VkFormatProperties
{
//对图像线性平铺格式的支持级别
VkFormatFeatureFlags linearTilingFeatures;
//对图像优化平铺格式的支持级别
VkFormatFeatureFlags optimalTilingFeatures;
//这种格式在缓冲区里使用时支持的级别
VkFormatFeatureFlags bufferFeatures;
} VkFormatProperties;
图像可以是两种基本平铺模式之一
VkFormatFeatureFlags
当用于图像时,获取更多对某种格式的支持情况的信息
VkResult vkGetPhysicalDeviceImageFormatProperties (
VkPhysicalDevice physicalDevice,
VkFormat format,
//要询问的图像类型
//VK_IMAGE_TYPE_1D
//VK_IMAGE_TYPE_2D
//VK_IMAGE_TYPE_3D
VkImageType type,
//图像的平铺模式
//VK_IMAGE_TILING_LINEAR
//VK_IMAGE_TILING_OPTIMAL
VkImageTiling tiling,
//图像的用途
VkImageUsageFlags usage,
//设置为在创建图像时使用的相同值
VkImageCreateFlags flags,
//如果 Vulkan 实现识别和支持这种格式,会把支持级别写入
VkImageFormatProperties* pImageFormatProperties
);
VkImageFormatProperties
typedef struct VkImageFormatProperties
{
//某个格式的图像在创建时的最大尺寸
VkExtent3D maxExtent;
//支持的最大 mipmap 层级数
//如果不支持,为 1
uint32_t maxMipLevels;
//图像支持的数组层的最大数量
//如果不支持,为 1
uint32_t maxArrayLayers;
//支持多重采样数
VkSampleCountFlags sampleCounts;
//这种格式的资源的最大尺寸
VkDeviceSize maxResourceSize;
} VkImageFormatProperties;
创建图像
VkResult vkCreateImage (
VkDevice device,
const VkImageCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkImage* pImage
);
VkImageCreateInfo
typedef struct VkImageCreateInfo {
//VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
VkStructureType sType;
const void* pNext;
//描述图像部分属性信息的标志位
VkImageCreateFlags flags;
//创建的图像的类型
//VK_IMAGE_TYPE_1D
//VK_IMAGE_TYPE_2D
//VK_IMAGE_TYPE_3D
VkImageType imageType;
VkFormat format;
//像素为单位的大小
//能够创建的图像的最大尺寸依赖于每个 GPU 设备
VkExtent3D extent;
//mipmap 层级的个数
//最小的层级 0
uint32_t mipLevels;
uint32_t arrayLayers;
//采样的次数
VkSampleCountFlagBits samples;
//平铺模式
//VK_IMAGE_TILING_LINEAR
//VK_IMAGE_TILING_OPTIMAL
VkImageTiling tiling;
//描述图像在哪里使用
VkImageUsageFlags usage;
//VK_SHARING_MODE_EXCLUSIVE 在某个时刻只能被一个队列使用
//VK_SHARING_MODE_CONCURRENT 可以同时被多个队列访问
VkSharingMode sharingMode;
//VK_SHARING_MODE_CONCURRENT 时设置哪些队列将使用
//其他值,忽略这两个参数
uint32_t queueFamilyIndexCount;
const uint32_t* pQueueFamilyIndices;
//任意时刻图像将会如何使用
//决定了图像以哪种布局创建
VkImageLayout initialLayout;
} VkImageCreateInfo;
VkImageCreateFlags
能够创建的图像的最大尺寸依赖于每个 GPU 设备
*
对比了规范文档,该部分内容书中描述有误,这里更正了vkGetPhysicalDeviceFeatures
VkImageUsageFlags
VkImageLayout
改变图像布局的机制也称为“管线屏障”,或简称“屏障”
线性图像
void vkGetImageSubresourceLayout (
VkDevice device,
//带查询的图像
VkImage image,
//查询的信息
const VkImageSubresource* pSubresource,
//写入子资源的布局参数
VkSubresourceLayout* pLayout
);
VkImageSubresource
typedef struct VkImageSubresource
{
//一个或者多个层面
//color 图像为 VK_IMAGE_ASPECT_COLOR_BIT
//深度图像为 VK_IMAGE_ASPECT_DEPTH_BIT
//模板图像为 VK_IMAGE_ASPECT_STENCIL_BIT
//深度-模板图像为 VK_IMAGE_ASPECT_DEPTH_BIT||VK_IMAGE_ASPECT_STENCIL_BIT
VkImageAspectFlags aspectMask;
uint32_t mipLevel;
//阵列的层,默认填0
uint32_t arrayLayer;
} VkImageSubresource;
VkSubresourceLayout
typedef struct VkSubresourceLayout
{
//资源中的偏移量, 子资源的开始位置
VkDeviceSize offset;
//消耗的内存区的大小
VkDeviceSize size;
//行间距
VkDeviceSize rowPitch;
//阵列间距
VkDeviceSize arrayPitch;
//深度间距
VkDeviceSize depthPitch;
} VkSubresourceLayout;
非线性编码
压缩图像的格式
vkGetPhysicalDeviceProperties()
VkPhysicalDeviceFeatures
textureCompressionBC
为 VK_TRUE
,则块状压缩格式
textureCompressionETC2
为 VK_TRUE
,则支持 ETC 格式 (包含 ETC2、EAC)textureCompressionASTC_LDR
为 VK_TRUE
,则支持 ASTC 格式VK_FORMAT_ASTC_{N}×{M}_{encoding}_BLOCK
格式的
{N}
与 {M}
代表压缩块的宽度和高度{encoding}
是 UNORM 或 SRGBVK_FORMAT_ASTC_8x6_SRGB_BLOCK
VkResult vkCreateBufferView (
VkDevice device,
const VkBufferViewCreateInfo* pCreateInfo,
//如果不是nullptr 指定的分配回调函数用于为新对象分配任何所需的主机内存
const VkAllocationCallbacks* pAllocator,
//新创建的缓冲区视图的句柄
VkBufferView* pView
);
VkBufferViewCreateInfo
typedef struct VkBufferViewCreateInfo
{
//VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO
VkStructureType sType;
//设置为 nullptr
const void* pNext;
//保留, 设置为0
VkBufferViewCreateFlags flags;
//父缓冲区
VkBuffer buffer;
//格式
VkFormat format;
//从 offset 字节开始
VkDeviceSize offset;
//范围
VkDeviceSize range;
} VkBufferViewCreateInfo;
maxTexelBufferElements
至少为 65 536
VkResult vkCreateImageView (
VkDevice device,
const VkImageViewCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkImageView* pView
);
VkImageViewCreateInfo
typedef struct VkImageViewCreateInfo
{
//VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
VkStructureType sType;
//nullptr
const void* pNext;
//设置为 0
VkImageViewCreateFlags flags;
//父图像
VkImage image;
//创建的视图类型
//视图类型必须和父图像类型兼容
VkImageViewType viewType;
//新视图的格式
VkFormat format;
//重映射,如 BGRA 图像创建 RGBA 视图
VkComponentMapping components;
//子图像可以是父图像的一个子集
//子集指定
VkImageSubresourceRange subresourceRange;
} VkImageViewCreateInfo;
VkImageViewType
VkComponentMapping
typedef struct VkComponentMapping
{
VkComponentSwizzle r;
VkComponentSwizzle g;
VkComponentSwizzle b;
VkComponentSwizzle a;
} VkComponentMapping;
VkComponentSwizzle
VkImageSubresourceRange
typedef struct VkImageSubresourceRange
{
//指定了哪些层面受屏障影响
VkImageAspectFlags aspectMask;
//指定视图从 mip 链的哪个位置开始
//如果父图像并没有 mipmap,设置为 0
uint32_t baseMipLevel;
//包含多少个 mip 层级
//如果父图像并没有 mipmap,设置为 1
uint32_t levelCount;
//指定起始层
//父图像并不是阵列图像 设置为 0
uint32_t baseArrayLayer;
//指定起始层与层数
//父图像并不是阵列图像 设置为 1
uint32_t layerCount;
} VkImageSubresourceRange;
VkImageAspectFlagBits
void vkDestroyBuffer (
VkDevice device,
VkBuffer buffer,
const VkAllocationCallbacks* pAllocator
);
pAllocator
就应该指向兼容的内存分配器;pAllocator
应设置为 nullptr
void vkDestroyBufferView (
VkDevice device,
VkBufferView bufferView,
const VkAllocationCallbacks* pAllocator
);
void vkDestroyImage (
VkDevice device,
VkImage image,
const VkAllocationCallbacks* pAllocator
);
void vkDestroyImageView (
VkDevice device,
VkImageView imageView,
const VkAllocationCallbacks* pAllocator
);
VkResult vkAllocateMemory (
VkDevice device,
//描述新分配的内存对象
const VkMemoryAllocateInfo* pAllocateInfo,
const VkAllocationCallbacks* pAllocator,
//指向新分配的内存
VkDeviceMemory* pMemory
);
VkMemoryAllocateInfo
typedef struct VkMemoryAllocateInfo
{
//VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
VkStructureType sType;
//nullptr
const void* pNext;
//指定需要分配的内存的大小
VkDeviceSize allocationSize;
//内存的类型
uint32_t memoryTypeIndex;
} VkMemoryAllocateInfo;
void vkFreeMemory (
VkDevice device,
VkDeviceMemory memory,
const VkAllocationCallbacks* pAllocator
);
maxMemoryAllocationCoun
void vkGetDeviceMemoryCommitment (
VkDevice device,
VkDeviceMemory memory,
//返回实际为这个内存对象分配的字节数
VkDeviceSize* pCommittedMemoryInBytes
);
VkResult vkMapMemory (
VkDevice device,
//内存对象
//一定要在外部同步访问这个内存对象
VkDeviceMemory memory,
//映射一个内存对象的一部分确定起始位置
//映射整个内存对象为 0
VkDeviceSize offset,
//指定区域的大小
//映射整个内存对象为 VK_WHOLE_SIZE
VkDeviceSize size,
//设置为 0
VkMemoryMapFlags flags,
//返回映射区域的指针
void** ppData
);
vkMapMemory()
返回的指针减去 offset
时,所得数值是设备内存映射的最小对齐值的倍数
minMemoryMapAlignment
void vkUnmapMemory (
VkDevice device,
VkDeviceMemory memory
);
VkResult vkFlushMappedMemoryRanges (
VkDevice device,
//需要刷新的区域大小
uint32_t memoryRangeCount,
//范围的信息
const VkMappedMemoryRange* pMemoryRanges
);
VkMappedMemoryRange
typedef struct VkMappedMemoryRange
{
//VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE
VkStructureType sType;
//nullptr
const void* pNext;
//被映射的内存对象
VkDeviceMemory memory;
//映射区间
//刷新一个内存对象的任何映射区
//把 offset 设置为 0,把 size 设置为 VK_WHOLE_SIZE 即可
VkDeviceSize offset;
VkDeviceSize size;
} VkMappedMemoryRange;
VkResult vkInvalidateMappedMemoryRanges (
VkDevice device,
uint32_t memoryRangeCount,
const VkMappedMemoryRange* pMemoryRanges
);
vkFlushMappedMemoryRanges()
和 vkInvalidateMappedMemoryRanges()
只会影响到缓存与主机访问的一致性,而不会影响到设备void vkGetBufferMemoryRequirements (
VkDevice device,
VkBuffer buffer,
//内存要求的信息
VkMemoryRequirements* pMemoryRequirements
);
void vkGetImageMemoryRequirements (
VkDevice device,
VkImage image,
//内存要求的信息
VkMemoryRequirements* pMemoryRequirements
);
VkMemoryRequirements
typedef struct VkMemoryRequirements
{
//资源所需内存量
VkDeviceSize size;
//内存对齐的信息
VkDeviceSize alignment;
//资源所能够绑定的所有内存类型
uint32_t memoryTypeBits;
} VkMemoryRequirements;
VkResult vkBindBufferMemory (
VkDevice device,
VkBuffer buffer,
VkDeviceMemory memory,
//内存对象中资源存在的位置
VkDeviceSize memoryOffset
);
VkResult vkBindImageMemory (
VkDevice device,
VkImage image,
VkDeviceMemory memory,
//内存对象中资源存在的位置
VkDeviceSize memoryOffset
);
vkBindBufferMemory()
和 vkBindImageMemory()
分别对缓冲区与图像进行访问,必须在外部保持同步void vkGetImageSparseMemoryRequirements (
VkDevice device,
VkImage image,
uint32_t* pSparseMemoryRequirementCount,
//填充该图像的限制条件
VkSparseImageMemoryRequirements* pSparseMemoryRequirements
);
VkSparseImageMemoryRequirements
typedef struct VkSparseImageMemoryRequirements
{
VkSparseImageFormatProperties formatProperties;
//指定的层级开始
uint32_t imageMipTailFirstLod;
//tail 的大小
VkDeviceSize imageMipTailSize;
//指定的位置开始
VkDeviceSize imageMipTailOffset;
//距离
VkDeviceSize imageMipTailStride;
} VkSparseImageMemoryRequirements;
VkSparseImageFormatProperties
typedef struct VkSparseImageFormatProperties
{
//属性将要应用到哪个图像层面
VkImageAspectFlags aspectMask;
//当把内存绑定到稀疏图像上时,它是绑定到多个块上的,而不是一次绑定到整个资源上的
//内存必须在特定大小的块中进行绑定
VkExtent3D imageGranularity;
//图像的更多行为
VkSparseImageFormatFlags flags;
} VkSparseImageFormatProperties;
VkSparseImageFormatFlags
void vkGetPhysicalDeviceSparseImageFormatProperties (
VkPhysicalDevice physicalDevice,
VkFormat format,
VkImageType type,
VkSampleCountFlagBits samples,
//用途
VkImageUsageFlags usage,
//平铺模式
VkImageTiling tiling,
uint32_t* pPropertyCount,
VkSparseImageFormatProperties* pProperties
);
VkResult vkQueueBindSparse (
VkQueue queue,
uint32_t bindInfoCount,
const VkBindSparseInfo* pBindInfo,
VkFence fence
);
VkBindSparseInfo
typedef struct VkBindSparseInfo
{
//VK_STRUCTURE_TYPE_BIND_SPARSE_INFO
VkStructureType sType;
//nullptr
const void* pNext;
//需要等待的信号量的个数
uint32_t waitSemaphoreCount;
//需要等待的信号量的句柄数组的指针
const VkSemaphore* pWaitSemaphores;
//缓冲区绑定更新的数量
uint32_t bufferBindCount;
//缓冲区对象绑定操作
const VkSparseBufferMemoryBindInfo* pBufferBinds;
uint32_t imageOpaqueBindCount;
//定义不透明内存绑定
//图像资源使用同一个结构体 VkSparseMemoryBind 来影响直接绑定到图像的内存称不透明图像内存绑定
const VkSparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds;
uint32_t imageBindCount;
//绑定内存到一个显式的图像区域来执行不透明的图像内存绑定。
const VkSparseImageMemoryBindInfo* pImageBinds;
//需要发送的信号量个数
uint32_t signalSemaphoreCount;
//需要发送的信号量的句柄数组的指针
const VkSemaphore* pSignalSemaphores;
} VkBindSparseInfo;
VkSparseBufferMemoryBindInfo
typedef struct VkSparseBufferMemoryBindInfo
{
VkBuffer buffer;
//内存区域的大小
uint32_t bindCount;
const VkSparseMemoryBind* pBinds;
} VkSparseBufferMemoryBindInfo;
VkSparseMemoryBind
typedef struct VkSparseMemoryBind
{
//资源内存块的偏移量
VkDeviceSize resourceOffset;
//内存块的尺寸
VkDeviceSize size;
//作为绑定的存储源的内存对象
VkDeviceMemory memory;
//内存对象内存块的偏移量
VkDeviceSize memoryOffset;
//包含用来控制绑定过程的额外信息
//缓冲区资源来说,无须使用标志位
//
VkSparseMemoryBindFlags flags;
} VkSparseMemoryBind;
VkSparseImageOpaqueMemoryBindInfo
typedef struct VkSparseImageOpaqueMemoryBindInfo
{
VkImage image;
uint32_t bindCount;
const VkSparseMemoryBind* pBinds;
} VkSparseImageOpaqueMemoryBindInfo;
typedef struct VkSparseImageMemoryBindInfo
{
VkImage image;
uint32_t bindCount;
const VkSparseImageMemoryBind* pBinds;
} VkSparseImageMemoryBindInfo;
VkSparseImageMemoryBind
typedef struct VkSparseImageMemoryBind
{
VkImageSubresource subresource;
//要绑定图像纹素区域的偏移量
VkOffset3D offset;
//要绑定图像纹素区域的大小
VkExtent3D extent;
//供绑定内存的内存对象
VkDeviceMemory memory;
//内存中的偏移量
VkDeviceSize memoryOffset;
VkSparseMemoryBindFlags flags;
} VkSparseImageMemoryBind;
VkImageSubresource
typedef struct VkImageSubresource
{
VkImageAspectFlags aspectMask;
uint32_t mipLevel;
//于非阵列图像, 应设置为 0
uint32_t arrayLayer;
} VkImageSubresource;