当前位置:网站首页>Vulkan规范笔记(一) 第一章至第六章
Vulkan规范笔记(一) 第一章至第六章
2022-06-09 17:46:00 【七Du°C糊涂】
目录
前言
学习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
边栏推荐
- The sisters sit in the bow of the boat while the brothers walk ashore
- idea卸载教程
- 外出旅行如何确保人身及财产安全
- 妹妹们坐船头,哥哥们岸上走
- How to learn the process of KD tree construction and search with cases?
- C语言选举人投票功能
- 运行代码,想加个进度条实时看以下代码运行进度,怎么破?
- Tencent cloud database tdsql | in fact, we experience such college entrance examinations every day
- Epigentek chromatin accessibility test kit principles and procedures
- 在页面中给元素添加事件的几种语法
猜你喜欢

自动化控制系统中滑环的应用

Reconstruction practice of complex C-end projects

得物复杂C端项目的重构实践

【工作随笔记】Tina 系统的 ADB、声卡、网卡、串口多路共存

Unity-获取XML文件的内容信息
![[long time series prediction] detailed explanation of aotoformer code [1] data preprocessing and data reading](/img/65/a3629909b1e9962416f23c9a07bf24.png)
[long time series prediction] detailed explanation of aotoformer code [1] data preprocessing and data reading

Some interesting b+ tree optimization experiments

I/o flow

Operation manual of abbexa PCR super mixture

华三IRF配置例子
随机推荐
C语言选举人投票功能
关于并发和并行,Go和Erlang之父都弄错了?
Parallel storage structure
Abbexa DUT ELISA 试剂盒测定原理
MySQL 8.0.29 decompressed version installation and configuration method graphic tutorial
Epigentek hi fi cDNA synthesis kit instructions
蓝桥杯2022年第十三届省赛真题-积木画
Memory concept
Virtual storage mechanism
图片搜索在 Dropbox 中的工作原理
君可归烈士寻亲系统开发实战
CPU program interrupt
Unity-代码绑定按钮功能
Word使用技巧
RSA加密和解密工具
Active prevention DWS key tool installation confirmation
谁说Redis不能存大key
二叉树遍历与线索化
UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0xad in position 2: illegal multibyte sequence
build sqllite from amalgamation version