Vulkan规范笔记(一) 第一章至第六章
目录
- 前言
- 第一章
- 第三章 Fundamentals
- 主机和设备环境
- 执行模式
- Queue Operation
- object model
- object lifetime
- External Object Handle
- Application Binary Interface
- Command Syntax and Durati
- ThreadingBehavior
- Valid Usage
- Usage Validation
- Implicit Valid Usage
- VkResult Return Code
- Numeric Representation and Computa
- Floating-Point Computation
- Floating-Point Format Conversion
- 16-Bit Floating-Point Numbers
- Unsigned 11-Bit Floating-Point Number
- Unsigned 10-Bit Floating-Point Numbers
- General Requirement
- Fixed-Point Data Conversions
- Conversion from Normalized Fixed-Point to Floating-Point
- Conversion from Floating-Point to Normalized Fixed-Point
- Common Object Types
- Offsets
- Extents
- Rectangles
- Structure Types
- API Name Aliases
- 第四章 Initialization
- Command Function Pointers
- Extending Physical Device Core Functionality
- Extending Physical Device From Device Extensions
- Instances
- 第五章 Devices and Queue
- Physical Devices
- Devices
- Device Creation
- Device Use
- Lost Device
- Device Destruction
- Queues
- Queue Family Properties
- Queue Creation
- Queue Family Index
- Queue Priority
- Queue Submission
- Queue Destruction
- 第六章 Command Buffers
- Command Buffer Lifecycle
- Command Pools
- Command Buffer Allocation and Management
- Command Buffer Recording
- Command Buffer Submission
- Queue Forward Progress
- Secondary Command Buffer Execution
- Command Buffer Device Mask
前言
学习Vulkan已经一年多了,算是入门了。但是如果想要了解Vulkan的更多特性,单纯开发渲染引擎是无法深入理解的。毕竟引擎这种东西只会使用主流图形API通用的接口。这样 “backend” 才有意义。但像我这种严重偏科的人,还是更喜欢专精一种图形API。所以阅读Vulkan规范文档是必修课!总算是挤出点时间看了些,先把笔记整理一下。可能近三个月会停一下,抽时间补一下C++ 并行编程的基础。这样有助于深入理解Vulkan Command的底层逻辑。
Vulkan规范:https://www.khronos.org/registry/vulkan/specs/1.3-extensions/pdf/vkspec.pdf
注意:规范现在有中文版(http://spec.vulkan.org.cn/),但还是建议看官方地址中最新版本规范!
第一章
- Vulkan是c99 API
第三章 Fundamentals
主机和设备环境
- 必须支持8位、16位、32位、64位有符号和无符号位整数
- 必须支持16位和32位浮点数
执行模式
- Vulkan可以开启一个或多个device
- 每个device可以开启一个或多个queue
- 每个queue都可以异步执行(不同device的queue可独立、异步执行)
- device支持的queue进行分类----划分为families
- 每个family支持一个或多种类型的功能。
- 包含具有类似特征的多个queue
- 单个family中的queues是彼此兼容的、queue生成的工作可以在该family内的任何队列中执行
- queue可以支持以下类型的功能
- 视频解码
- 视频编码
- 图形绘制
- 计算
- transfer
- sparse memory management
- 单一device可以report多个类似的 queue family。虽然同一family的不同queue有相似的能力.但它们之间是不兼容的
- device memory是由应用程序明确管理的
- 每个device可以公布一个或多个堆、每个堆都代表不同的内存区域
- 堆可以是device-local或host-local、对device可见
- 堆常用的有
- device-local是物理上连接到device的内存
- device-local、 host visible是主机可见内存
- host-local、 host visible是主机本地、对主机和device可见的内存
Queue Operation
- queue是驱动 device的接口。命令在执行之前记录在命令缓冲区,然后写入 queue 中执行。命令一旦提交到queue,命令即开始执行,无须干预。
- 命令执行顺序取决于隐式和显式排序约束
- 提交命令后可获取一个信号量列表、用于等待和完成后发出信号
- 不同队列中的命令是相互独立的、不同队列之间或主机与队列之间的显式排序可以使用semaphores和fences
- 命令有以下几种
- 执行操作
- draw
- dispatch调度
- clear
- copy
- query /timestamp operations
- begin /end
- subpass operations
- 设置状态
- bind pipelines
- descriptor sets and buffers
- set dynamic state
- push constants
- set render
- pass /subpass state
- 执行同步
- set/wait事件
- pipeline barrier
- render pass /subpass 依赖
- 执行操作
object model
- 有两种类型的Handel
- 可调度
- 是一个不透明类型指针,可做为API命令的一部分。并作为该API的第一个参数
- 可调度对象在其生命周期中只能有一个Handel
- 不可调度
- Handel是由依赖于实现的一个64位整型类型
- 如果VkDevice开启privateData特性
- 每个在该device上创建的不可调度类型的对象在该对象的生命周期中,必须只有一个Handel
- 如果Handel不唯一,销毁时不得使其他相同类型的Handel无效
- 可调度
- VkDevice创建的所有对象都是私有的,不能用于其他 device
object lifetime
- 通过vkCreate…和vkAllocate…命令创建或分配对象
- 在创建或分配后,仅管某些对象的内容是可以自由更改的,但对象的结构大部分被认为是不可变的
- vkDestroy…和vkFree…命令分别是销毁或释放对象
- 下列object类型在任何API命令使用期间内不能被销毁
- VkShaderModule
- VkPipelineCache
- VkValidationCacheEXT
- 命令中VkRenderPass的使用规则
- 可以通过使用已分配的descriptor sets上的操作命令获取VkDescriptorSetLayout objects
- 当descriptor set layout被销毁时,这些descriptor sets不能使用vkUpdateDescriptorSets进行更新
- 使用VkDescriptorSetLayout objec作为一个参数去创建别一个对象时,在命令结束后,该对象无法进一步访问
- 在所有使用的object未执行完成之前,应用程序不得销毁任何其它类型的Vulkan对象
- 当任何command buffer 正在使用时不能被销毁的Vulkan对象
- VkEvent
- VkQueryPool
- VkBuffer
- VkBufferView
- VkImage
- VkImageView
- VkPipeline
- VkSampler
- VkSamplerYcbcrConversion
- VkDescriptorPool
- VkFramebuffer
- VkRenderPass
- VkCommandBuffer
- VkCommandPool
- VkDeviceMemory
- VkDescriptorSet
- VkIndirectCommandsLayoutNV
- VkAccelerationStructureNV
- VkAccelerationStructureKHR
- 当queue执行时不能销毁的对象
- VkFence
- VkSemaphore
- VkCommandBuffer
- VkCommandPool
- 何时都可以销毁的对象(page 11)
- VkPhysicalDevice会被隐式销毁
- VkInstance会在VkDevice销毁后才能被销毁
External Object Handle
- 外部handle的导入方式
Application Binary Interface
- 公共库接口定义,暂时不关心
Command Syntax and Durati
- 参数说,都是基础内容
ThreadingBehavior
- 外部同步命令:虽然Vulkan支持多线程,但是有些命令必须在单线程中执行
- 这些命令在(page 16)
Valid Usage
- 定义了一组必须满足的条件,以便在应用程中实现明确定义的运行时行为
- 这些条件只取决于 Vulkan状态,参数和对象的状态受到这些条件的限制
Usage Validation
- Vulkan是一个分层结构的API、最低层为本规范定义的核心API
- 应用程序可以使用在核心API之上的层级进行调试、验证,或其它用途
- 正确使用 API的方法是:在开发时启用验证层,发布时关闭验证层
Implicit Valid Usage
- 暂时不关注
VkResult Return Code
* 返值类型可以在这里查到
Numeric Representation and Computa
* 数值类型和转换可在本节查阅
Floating-Point Computation
Floating-Point Format Conversion
16-Bit Floating-Point Numbers
Unsigned 11-Bit Floating-Point Number
Unsigned 10-Bit Floating-Point Numbers
General Requirement
Fixed-Point Data Conversions
Conversion from Normalized Fixed-Point to Floating-Point
- 这里有类型转换的具体公式
Conversion from Floating-Point to Normalized Fixed-Point
- 这里有类型转换的具体公式
Common Object Types
Offsets
- 用于表示图像和 framebuffer的像素位置
- VkOffset2D
- VkOffset3D
Extents
- 用于表示图像或 framebuffer内像素矩型区域的大小
- VkExtent2D
- VkExtent3D
Rectangles
- 用于描述图像或 framebuffer内像素的指定矩形区域
- VkRect2D
- 里面就是一个offsets和extents
Structure Types
- 类型和结构体的对应关系
- 类型名去悼vk,剩下的名称大写并用_分隔,最后在前面加上VK_STRUCTURE_TYPE_
- VkImageCreateInfo->VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
- 结构体类型可在(page 47)查询
API Name Aliases
- 别名不关心
第四章 Initialization
- 使用 Vulkan前必须加载命令并且创建VkInstance对象
Command Function Pointers
- Vulkan命令不需要使用静态链接、Vulkan命令的函数指针可以使用如下函数获取
- vkGetInstanceProcAddr
- 其会加载对应平台的函数指针
- 也可以使用特定于平台的API动态加载函数指针
- vkGetInstanceProcAddr
- 为了系统支持多个Vulkan实现、vkGetInstanceProcAddr返回的函数指针可能指向为不同VkDevice对象或其子对象实现的不同调度代码
- 通过使用VkDevice或VkDevice子对象作为其可调度对象,获取特定于设备的函数指针,可以避免 VkDevice 对象的内部调度开销。
- 可以使用以下命令获取此类函数指针:
- vkGetDeviceProcAddr
Extending Physical Device Core Functionality
- 当physical-device版本大于或等于添加新功能的 Vulkan 版本时,可以使用新的physical-device-level函数。physical dev支持的 Vulkan 版本可以通过调用 vkGetPhysicalDeviceProperties 来获取。
Extending Physical Device From Device Extensions
- 当VK_KHR_get_physical_device_properties2扩展被启用,或instance 和 physical-device的版本大于等于1.1时,device的physical-device-level 函数可以被使用
- 若要从device extension中获取physical-device-level命令的函数指针,可以使用vkGetInstanceProcAddr。 获得的函数指针可指向为不同VkPhysicalDevice对象调用不同实现的调度代码
- 应用程序不得使用在该physical device的扩展或核心版本不支持的由VkPhysicalDevice添加的任何命令
- Device extensions可以定义结构体并添加到physical-device-level命令的pNext中
Instances
- Vulkan 中没有全局状态,所有per-application的状态都存储在 一个VkInstance对象中。
- 创建 VkInstance 对象将初始化 Vulkan 库,并允许应用程序将有关自身的信息传递给实现。
- Instances由 VkInstance 句柄表示:
- VK_DEFINE_HANDLE(VkInstance)
- 要查询实现支持的instance-level函数的版本,请调用:
- vkEnumerateInstanceVersion
- 要创建Instances对象
- vkCreateInstance
- 如果需要捕获创建或销毁Instances时发生的事件,可以在VkInstanceCreateInfo的pNext填加VkDebugReportCallbackCreateInfoEXT或VkDebugUtilsMessengerCreateInfoEXT
- VkInstanceCreateFlagBits
- VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR指定instance将枚举符合 Vulkan 可移植性的可用物理设备和组,以及默认情况下枚举的 Vulkan 物理设备和组。
- 需要禁用验证检查可以在VkInstanceCreateInfo的pNext中填加VkValidationFlagsEXT
- 要启用或禁用特定验证功能的 Vulkan 实例时,将 VkValidationFeaturesEXT添加到 VkInstanceCreateInfo的pNext中
- 由于 Vulkan 1.0 实现可能会因VK_ERROR_INCOMPATIBLE_DRIVER而失败,因此应用程序应在调用 vkCreateInstance 之前确定可用的 Vulkan 版本。如果 vkGetInstanceProcAddr 为 vkEnumerateInstanceVersion 返回 NULL,则它是 Vulkan 1.0 实现。否则,应用程序可以调用 vkEnumerateInstanceVersion 来确定 Vulkan 的版本。
- 只要instance至少支持 Vulkan 1.1,应用程序就可以对instance使用不同版本的 Vulkan,而不是对device或physical device使用不同版本。
- instance支持版本和physical device支持版本不同时的逻辑可从 (page 99)查看
- Host Synchronizatio
- 主机对instance的访问必须在外部同步
- 主机对从instance枚举的所有VkPhysicalDevice对象的访问必须在外部同步
第五章 Devices and Queue
- 一旦 Vulkan 被初始化,device和queue就是用于与 Vulkan 实现交互的主要对象。
- Vulkan有physical and logical device 之分、physical device表示GPU、而logical device表示该GPU的一个具有独立于其它logical device的状态和资源的实例
- VkPhysicalDevice handles
- VK_DEFINE_HANDLE(VkPhysicalDevice)
Physical Devices
- 列出系统中安装的GPU列表,调用:
- vkEnumeratePhysicalDevices
- 要查询枚举后的GPU的属性,调用:
- vkGetPhysicalDeviceProperties
- vkGetPhysicalDeviceProperties2
- vkGetPhysicalDeviceProperties2KHR
- 查询结果中 vendorID 和 deviceID是为了允许应用程序适应由其他 Vulkan 查询未充分公开的设备特征。
- 这些可能包括性能配置文件,硬件勘误表或其他特征。
- GPU的具体可查询信息在(page 105)查询
- VkPhysicalDeviceVulkan13Properties
- 该系列函数会根据Vulkan版本升级增加新的函数
- VkPhysicalDeviceVulkan**Properties
- 应用程序可以跨instance和进程比较driverUUID的值,可以在外部 API 中进行类似的查询,以确定它们是否能够与device共享内存对象和资源。
- 要想了解driverUUID相关事宜可以阅读本节,暂时不需要了解
- VkPhysicalDevicePCIBusInfoPropertiesEXT可以查询PCI总线信息
- VkPhysicalDeviceDrmPropertiesEXT可以查询DRM信息
- DRM是一个内核级的设备驱动
- VkPhysicalDeviceShaderIntegerDotProductProperties查询计算支持
- 优化点乘
- vkGetPhysicalDeviceQueueFamilyProperties查询query属性
- 如果实现公开了支持图形操作的任何queue family,则该实现公开的至少一个physical device的一个queue family必须同时支持图形和计算操作。
- 如果支持protected memory physical device feature,则该实现公开的至少一个physical device的一个queue family必须同时支持graphics operations, compute operations,和 protected memory operations
- 要查询physical device上可用queue的属性,调用:
- vkGetPhysicalDeviceQueueFamilyProperties2
- vkGetPhysicalDeviceQueueFamilyProperties2
- queues family相关属性可在(page 141)查询
Devices
- Device对象表示与physical device的逻辑连接。
- 创建的logical device是physical device的接口。
- 如果多个physical device属于同一device group,可以由该组multiple physical device创建单个logical device
- device group
- 是指一组physical device,支持相互访问彼此的内存并且单个command buffer可以在所有physical device上执行
- 调用 vkEnumeratePhysicalDeviceGroups 枚举device group,
- 通过 VkDeviceGroupDeviceCreateInfo 设置physical device,从device group中physical device的子集创建logical device
- 要使两个physical device位于同一设备组中,它们必须支持相同的扩展,函数和属性。
- 检索系统中存在的设备组的列表,调用:
- vkEnumeratePhysicalDeviceGroups
- vkEnumeratePhysicalDeviceGroupsKHR
Device Creation
- Logical device句柄表示:
- VK_DEFINE_HANDLE(VkDevice)
- 要创建逻辑设备,调用:
- vkCreateDevice
- 想要设置Logical device支持的扩展可在本节查询
- 可以从同一physical device创建多个Logical device。
- 若要指定是否允许设备内存分配超出 VkPhysicalDeviceMemoryProperties 报告的大小,请将 VkDeviceMemoryOverallocationCreateInfoAMD 结构体添加到 VkDeviceCreateInfo 结构体的 pNext 链中。
- 使用 NsightTM Aftermath SDK 时,要配置设备故障转储的创建方式,请将 VkDeviceDiagnosticsConfigCreateInfoNV 结构体添加到 VkDeviceCreateInfo 结构体的 pNext 链中
- 可以同时从多个线程调用回调。
- 当 VkDeviceMemoryReportEventTypeEXT 事件发生时,实现只能调用回调一次。
- 回调可以从调用 Vulkan 命令的线程以外的后台线程调用。
- 回调不得调用任何 Vulkan 命令。
- 内存事件回调可以在(page 165)查询
- 如果要使用private data storage slots添加VkDevicePrivateDataCreateInfo
Device Use
- 以下是VkDevice使用的高级列表
- 创建queue
- 创建和跟踪各类同步结构体
- 分配、释放和管理内存
- 创建和销毁command buffer和command buffer pool
- 创建、销毁和管理graphics状态
Lost Device
- logical device可能会由于某些特定实现的原因而丢失,可能使正确准备执行的命令运行败,并导致资源和已分配的内存变为未定义。
- logical device丢失的原因
- 运行超时
- 电源管理事件
- 平台资源管理
- 实现错误
- logical device的丢失不会影响VkPhysicalDevice
- physical device也可能丢失,可能是基础实现或与主机的连接存在问题
- 当device丢失时,其子对象不会被隐式销毁,在销毁对象或device时必须销毁这些对象
- 当device丢失时,与使用vkMapMemory映射的设备内存对应的主机地址空间仍然有效。并且对这些映射区域的主机内存访向仍然有效,但内容未定义。而且在device和其子对象上调用任何访问命令仍是合法的
- device执行的无很期等待命令如
vkDeviceWaitIdle、vkQueueWaitIdle、vkWaitForFences或vkAcquireNextImageKHR
需设置超时时间,并且vkGetQueryPoolResults的flags必须包含VK_QUERY_RESULT_WAIT_BIT - device 执行的无很期等待命令在device 丢失的情况下也必须在有限时间内返回VK_SUCCESS或VK_ERROR_DEVICE_LOST
- 任何命令都可能返回VK_ERROR_DEVICE_LOST,以确定一个command buffer是挂起状态还是认为资源正在使用中
Device Destruction
- 销毁Device
- vkDestroyDevice
- 为确保device上没有工作处于活动状态,可以使用 vkDeviceWaitIdle 来阻止device的销毁。
- 每个对象的生存期都受 VkDevice 对象的生存期约束。因此,为了避免资源泄漏,应用程序在调用 vkDestroyDevice 之前显式释放所有这些资源
Queues
Queue Family Properties
- 可以使用命令获取Queue Family和Queue 支持相关信息
- physical device 中 queue familie组取决于实现。
- 一旦应用程序选持它要使用的queue标识了physical device,physical device将与logical device一起创建这些queue
Queue Creation
- 创建logical device还会创建与该device关联的queue 。需创建的queue 由 VkDeviceQueueCreateInfo 描述,设置在vkCreateDevice的pQueueCreateInfos 中
- VkQueue handles
- VK_DEFINE_HANDLE(VkQueue)
- queue 优先级
- 优先级值按升序排序
- 可设置优先级
- VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR
- VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR
- VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR
- VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR
- 与优先级较低的queue 相比,系统优先级较高的queue 可能会分配更多的处理时间
- 实现可能允许较高优先级的queue 使较低优先级的queue 阻塞,直到较高优先级的queue 没有要执行的命令为止。
- 全局优先级 queue 优先于per-process优先级的queue (VkDeviceQueueCreateInfo::pQueuePriorities)
- 获取vkqueue对象的句柄
- vkGetDeviceQueue
- 获取带有VkDeviceQueueCreateFlags信息的vkqueue对象句柄
- vkGetDeviceQueue2
Queue Family Index
- The queue family index在Vulkan的多个位置被使用。以便将操作绑定到特定family的queue上
- 当使用vkGetDeviceQueue查询一个queue handle时,Queue Family Index用于选择要查询哪个queue family的VkQueue handle
- 当创建VkCommandPool对象时,Queue Family Index 填加到VkCommandPoolCreateInfo中。此池中的命令缓冲区只能在与该queue family对应的queue 上进行提交。
- 当创建VkImage和VkBuffer资源时,一组queue family包含在VkImageCreateInfo和VkBufferCreateInfo中。用于指定可以访问这些资源的queue families。
- 插入 VkBufferMemoryBarrier 或 VkImageMemoryBarrier 时,将指定源和目标Queue Family Index,以允许将缓冲区或图像的所有权从一个queue family转移到另一个queue family上。
Queue Priority
- 每个queue 都分配有一个优先级,如创建device时 VkDeviceQueueCreateInfo 结构体中设置的那样。每个队列的优先级是介于 0.0 和 1.0 之间的浮点数
- 0.0表示最低优先级、1.0表示最高优先级
- 在同一device中,优先级较高的queue 可能比优先级较低的queue 分配更多的处理时间。该实现不保证在具有相同优先级的队列之间进行排序或调度,
- explicit synchronization primitives可以显式的定义优先级调度顺序
- 实现不保证不同device上queue 的执行优先级
- 实现可能允许优先级较高的queue 在同一 VkDevice 上使优先级较低的queue 阻塞,直到优先级较高的queue 没有要执行的其他命令。queue 优先级的关系不得导致一个 VkDevice上的queue 使另一个 VkDevice的queue 阻塞。
- 实现不保证优先级较高的queue 比优先级较低的queue 获得更多的处理时间或更好的服务质量
Queue Submission
- 通过使用 queue submission commands 将要执行的任务提交到队列中
- 如vkQueueSubmit和vkQueueSubmit2
- queue submission commands (队列提交命令) 定义一组由 physical device 执行的队列操作
- 包括同步使用的 semaphores 和 fences
- 提交命令时将目标队列、零次或多batches工作、可选的 fence 作为参数,以便完成时发出信号
- 每个 batch 由三个不同部分组成
- 在执行批处理的其余部分之前,要等待零个或多个semaphores。
- 要执行的零个或多个工作项。
- 零个或多个信号量,用于在工作项完成时发出信号。
- 如果队列提交中存在 fence,则它描述 fence 信号操作。
- 在命令返回之前,必须将队列提交命令描述的所有工作提交到队列中
- Sparse Memory Binding
- 在Vulkan中,可以将内存稀疏地与buffers和images进行绑定
- Sparse Memory Binding是队列操作
- 包含VK_QUEUE_SPARSE_BINDING_BIT的队列必须能够支持将虚拟地址映射到设备上的物理地址。
- 该操作会更新device上的页表映射。必须在队列上同步该更新,以避免在执行图形命令期间损坏页表映射。
Queue Destruction
- 队列是在 vkCreateDevice 期间与 logical device 一起创建的。在 logical device 上调用。 vkDestroyDevice 时,与该logical device关联的所有队列都将被销毁。
第六章 Command Buffers
- Command buffers是用于记录命令的对象、这些命令随后可以提交到device queue中执行
- Command buffers有两个等级
- primary command buffers
- 可以执行secondary command buffers,并能提交到queue中,
- secondary command buffers
- 可由primary command buffers执行,并且不能直接提交到queue中
- primary command buffers
- Command buffers由 VkCommandBuffer 句柄表示:
- VK_DEFINE_HANDLE(VkCommandBuffer)
- 记录的命令包括
- 将pipelines和descriptor sets绑定到command buffer的命令
- 用于修改动态状态(dynamic state)的命令
- 绘制命令(用于渲染)
- 调度命令 (dispatch)、用于计算
- 用于执行secondary command buffers的命令(仅适用于primary command buffer)
- 用于复制buffers和images的命令
- 其他命令
- 每个command buffer独立于其他command buffer的管理状态
- 在primary command buffers和secondary command buffers之间,或在secondary command buffers之间,没有状态继承
- 例外
- 如果primary command buffer位于render pass实例内,则secondary command buffers不会干扰render pass和subpass状态。
- 当command buffers开始recording、command buffer中所有状态都是未定义的
- 对于与状态相关的命令(如绘制和调度),这些命令使用的任何状态都不得是未定义的
- VkCommandBufferInheritanceViewportScissorInfoNV 定义了一个异常(exception、我觉得应该翻译成例外),允许对动态viewport和scissor状态进行有限的继承。
Command Buffer Lifecycle
- 每个 command buffer 始终处于以下状态之一:
- Initial
- 分配 command buffer 时,它处于初始状态。某些命令能够将command buffer(或一组command buffer)Executable、Recording 或 Invalid 重置回此状态。
- 在 Initial 状态下的 command buffer 只能改变状态为 recording 或者释放
- Recording
- vkBeginCommandBuffer将command buffer的状态从初始状态更改为录制状态。command buffer 处于录制状态后,可以使用 vkCmd* 命令将命令录制到command buffer
- Executable
- vkEndCommandBuffer 结束 command buffer 的记录,并将其从录制状态移动到可执行状态。可执行的 command buffer 可以提交、重置或录制到另一个command buffer。
- Pending
- command buffer 的队列提交会将 command buffer 的状态从可执行状态更改为挂起状态。处于挂起状态时,应用程序不得尝试以任何方式修改 command buffer
- command buffer 执行完成后,命令缓冲区将恢复为可执行状态
- 如果使用VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT记录,command buffer 将移动到无效状态。应使用synchronization 命令来检测何时发生这种情况。
- Invalid
- 某些操作(如修改或删除在记录到 command buffer 的命令中使用的资源)会将该command buffer的状态转换为无效状态。处于无效状态的command buffer只能重置或释放。
- 重置 command buffer
- vkResetCommandBuffer
- vkResetCommandPool
- Initial
- Secondary command buffers 可以通过 vkCmdExecuteCommands 记录到 primary command buffer
- Secondary command buffers 的执行状态会跟随 primary command buffer 变化
- 如果 primary command buffer 提交到队列,则 primary command buffer 和记录到队列中的任何Secondary command buffers都将进入挂起状态。
- 一旦 primary command buffer 执行完成,其中记录的任何 Secondary command buffers 也被执行完成。
- 如果 Secondary command buffers 置为无效状态或初始状态,则所有 primary command buffer 将改变为无效状态。(??? 暂时无法确定翻译是否正确)
- primary command buffer 置为任何其他状态不会影响其中记录的 Secondary command buffers 状态。
- 重置或释放 primary command buffer 将删除与记录在其中的所有 Secondary command buffers 的生命周期链接。
Command Pools
- Command pools 是 command buffer memory 分配内存中的不透明对象,它允许实现在多个 command buffer 之间分摊资源创建成本
- Command pools 是外部同步(externally synchronized)的,这意味着不得在多个线程中同时使用 command pool
- 其中包括通过从 command pool 分配的任何command buffer进行记录操作、以及分配,销毁和重置 command buffer 或 command pool本身的操作
- Command Pools 由VkCommandPool 句柄表示:
- VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool)
- 要创建一个Command Pools
- vkCreateCommandPool
- 要修剪(trim) CommandPool,call:
- vkTrimCommandPool
- vkTrimCommandPoolKHR
- 修剪 CommandPool 是从 Command Pools 中将未使用的内存回收到系统中
- 从Pool分配的Command buffers不受该命令的影响。
- 该命令为应用程序提供了对Command Pool使用的内部内存分配的某种程度的控制。
- command buffers未使用的内存(包括recorded、稍后reset)在 reset时,command buffer 使用的内存会返还给Command Pool
- 要将Command Pool的内存返还给操作系统必须使用VKResetCommandPool
- 当Command Pool中有 command buffer 正在使用时无法执行
- command buffer 操作重复使用 Command Pool中的内存,因此会产生内存碎片
- 在这种情况下,裁剪(trimming)Command Pool可以将内存碎片返回给操作系统。将pool分配的总内存重置到更平均的大小以减少碎片的产生
- Vulkan实现使用了很多内部分配策略。使得无法确保所有未使用的内存都释放回系统
- 例如Command Pool的sub-allocating可能从操作系统中分配内存,既使只有小部分内存正在使用,也会阻止内存释放
- 在大多数情况下,修剪会导致分配但未使用的内存减少,但不能保证“理想”行为
- 修剪是一个昂贵的操作,不应经常调用。当存在足够未使用的内存时,应将修剪作为减轻内存压力的一种方法。注意权衡
- 要重置Command Pool
- vkResetCommandPool
- 重置Command Pool会回收所有资源。从Command Pool分配的所有command buffer都恢复到初始状态。
- 从其他VkCommandPool recording或executable状态分配的primary command buffer和 有从commandPool获得的recording状态的secondary command buffer,重置无效
- 销毁命令池
- vkDestroyCommandPool
- 当pool被销毁时,所有从pool中分配的command buffer都将释放。
- 从其他VkCommandPool recording 或 executable 状态分配的 primary command buffer 和 有从commandPool获得的recording状态的secondary command buffer,销毁命令无效
Command Buffer Allocation and Management
- 分配 command buffers
- vkAllocateCommandBuffers
- VkallocateCommandBuffers 可以用于分配多个 command buffers。如果任何一个command buffer的分配失败,则实现必须从此命令中释放所有成功分配的command buffer对象,将PCommandBuffers集合的所有元素设置为null并返回错误。
- 分配command buffer后,其初始化状态为initial state
- 重置command buffer,
- vkResetCommandBuffer
- 在recording或executable状态中并已进入commandBuffer中的任何primary command buffer,重置命令将无效。
- 释放command buffer
- vkFreeCommandBuffers
Command Buffer Recording
- 开始录制命令缓冲区
- vkBeginCommandBuffer
- 录制开始后,应用程序记录了一个命令序列(vkCmd*),以在命令缓冲区、绘制、调度和其他命令中设置状态。
- 也可以间接从vkbuffer内容记录一些命令
- 完成命令缓冲区的记录
- vkEndCommandBuffer
- 如果在录制过程中存在错误,则将通过vkEndCommandBuffer返回不成功,来通知该应用程序。如果应用程序希望进一步使用命令缓冲区,则必须重置命令缓冲区。
- 当命令缓冲区处于可执行状态时,可以将其提交给队列以进行执行。
Command Buffer Submission
- 提交是高代价(high overhead)操作,应用程序应分批提交,以尽可减少使用vkQueueSubmit或vkQueueSubmit2。
- 将命令缓冲区提交给队列
- vkQueueSubmit2
- vkQueueSubmit2KHR
- 与其他提交命令相比,使用vkQueueSubmit2提交的信号量操作具有额外的约束,其依赖性涉及以前的和后续的队列操作。
- 如果提交给此队列的任何命令缓冲区处于可执行状态,则将其移至待处理状态。执行所有命令缓冲区的所有提交后,它将从pending状态移至可执行状态。如果使用VK_Command_Buffer_USAGE_ONE_TIME_SUBMIT_BIT FLAG记录命令缓冲区,则将移回无效状态。
- 要将命令缓冲区提交到某个队列
- vkQueueSubmit
- 该提交用按照提交顺序依次开始执行,但不保证完成须序
- 命令缓冲区出现在PCommandBuffers中的顺序用于确定提交顺序,
- 指定等待时的信号量
- VkTimelineSemaphoreSubmitInfo
Queue Forward Progress
- 提交中的命令缓冲区可以包括vkCmdWaitEvents命令,该命令在队列中不会由早期命令发出的事件等待。此类事件必须使用VKSetEvent的应用程序发出信号,并且等待它们的vkCmdWaitEvents命令不得在 render pass 实例中。必须在执行vkCmdWaitEvents命令之前设置该事件。
Secondary Command Buffer Execution
- secondary command buffer不得直接提交给队列。相反,将secondary command buffer作为primary command buffer一部分执行
- vkCmdExecuteCommands
Command Buffer Device Mask
- 每个command buffe都有一个状态存储命令缓冲区的当前设备掩码。该掩码控制 logical device 中的哪些 physical device 所有后续命令将执行,包括状态设置命令,操作命令和同步命令。
- 要更新 command buffe 的当前设备掩码
- vkCmdSetDeviceMask
- vkCmdSetDeviceMaskKHR
Vulkan规范笔记(一) 第一章至第六章相关推荐
- 计算机组成原理笔记(王道考研) 第六章:总线
内容基于中国大学MOOC的2023考研计算机组成原理课程所做的笔记. 感谢LY,他帮我做了一部分笔记.由于听的时间不一样,第四章前的内容看起来可能稍显啰嗦,后面会记得简略一些. 西电的计算机组织与体系 ...
- 计算机网络笔记(王道考研) 第六章:应用层
内容基于中国大学MOOC的2023考研计算机网络课程所做的笔记. 感谢LY,他帮我做了一部分笔记.其中第四章网络层各小节的顺序稍微做了下调整,和上课老师讲的先后顺序稍有不同,但内容是完整的. 课程内容 ...
- 【西电—英美国家概况(英美概况/英美文化)2023第一学期】第六章参考课后答案
#[西电-英美国家概况(英美概况/英美文化)2023第一学期]第六章参考课后答案 提示:第四.五题别看错了!
- 第一卷 第一百三十六章 好白菜
第一卷 第一百三十六章 好白菜 其实我最恨两种人,一种是始乱终弃的小白脸,一种就是生孩子不养活的臭娘们儿.** 提供本书txt电子书下载 **既然你能生就要能养啊,虽然我不知道井里的那个死孩子的母亲 ...
- 数据挖掘导论Pangaea-Ning Tan 读书笔记——(第一,二,三章)
<数据挖掘导论>Pang-Ning Tan ,Michael Steinbach,Vipin Kumar 读书笔记, 第一章 绪论 数据挖掘任务 预测任务 描述任务 分类任务 回归任务 聚 ...
- 工程光学第一、二、六章学习总结
前言 我知道我不能停留在现在.......只有通过加强学习.工程光学的书从去年12月开始陆陆续续地看,到今年基本没看了,这两天我把条件都找齐了,最关键是合适的地方,找到了,还有X先生给我的电脑,给我的 ...
- 同济版高等数学复习笔记(上册第五、六章)
第五章 定积分 第一节 定积分的概念与性质 一.定积分问题实例 曲边梯形面积 变速直线运动位移 二.定积分的定义 1. 定积分的定义 函数 f ( x ) f(x) f(x) 在 [ a , b ] ...
- 尔雅 科学通史(吴国盛) 个人笔记及课后习题 2018 第六章 自然的数学化和分析化
科学通史 第六章 自然的数学化和分析化 6.1自然的数学化和分析化 希腊背景和基督教背景是欧洲科技革命必不可缺的背景 欧洲数理传统学科 哥白尼革命 6.1自然的数学化和分析化(习题) 6.2天文学的发 ...
- Windows核心编程(笔记13) 第十六章--第二十六章
改变下记录方式,只写自己觉得需要注意一下的防止出错的地方,或者一些特别重要的点,或者一些感悟. 第十六章 线程栈 第十七章 内存映射文件 1.注意写时复制在内存映射文件中的用处. 2.#pagma d ...
最新文章
- python的gui库哪个好_常用的13 个Python开发者必备的Python GUI库
- Linux桌面环境与命令行环境切换快捷键,以及linux 图形界面 X Server 关闭 启动
- thinkpad密码忘记
- QCon北京2016启动筹备 众多热点专题诚征演讲嘉宾
- c语言多重括号,大佬在吗,我用C写了一个去多重括号的函数,结果。。。
- C# 8 新特性 - 异步流 Asynchronous Streams
- Java Syncrhonisers
- 使用Mybatis-plus更新null字段的解决方案
- AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
- postman测试登录后的接口_中文版Postman测试需要登陆才能访问的接口(基于Cookie)...
- 使用ZipCodeValidatorDomainType验证不同国家的邮编
- java隐式参数的作用_隐式参数_scala教程_田守枝Java技术博客
- java进度条_「java进度条」Java JProgressBar类(进度条) - seo实验室
- win10系统优化与防范策略
- python小游戏:剪刀,石头,布
- 算法时间复杂度分析(一)
- 小武与剑指offer的恩怨情仇
- 麦客服务器维修,麦客
- PSRAM 伪静态随机存取内存
- MAC M1/M2安装ADOBE等第三方软件问题终极解决 “开启任何来源”“无法检查更新,请确认您已接入互联网”“移除下载镜像的Quarantine属性” “闪退”【MACBOOK】