目录

  • 前言
  • 第一章
  • 第三章 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动态加载函数指针
  • 为了系统支持多个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中
  • 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
  • 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规范笔记(一) 第一章至第六章相关推荐

  1. 计算机组成原理笔记(王道考研) 第六章:总线

    内容基于中国大学MOOC的2023考研计算机组成原理课程所做的笔记. 感谢LY,他帮我做了一部分笔记.由于听的时间不一样,第四章前的内容看起来可能稍显啰嗦,后面会记得简略一些. 西电的计算机组织与体系 ...

  2. 计算机网络笔记(王道考研) 第六章:应用层

    内容基于中国大学MOOC的2023考研计算机网络课程所做的笔记. 感谢LY,他帮我做了一部分笔记.其中第四章网络层各小节的顺序稍微做了下调整,和上课老师讲的先后顺序稍有不同,但内容是完整的. 课程内容 ...

  3. 【西电—英美国家概况(英美概况/英美文化)2023第一学期】第六章参考课后答案

    #[西电-英美国家概况(英美概况/英美文化)2023第一学期]第六章参考课后答案 提示:第四.五题别看错了!

  4. 第一卷 第一百三十六章 好白菜

    第一卷 第一百三十六章 好白菜 其实我最恨两种人,一种是始乱终弃的小白脸,一种就是生孩子不养活的臭娘们儿.**  提供本书txt电子书下载 **既然你能生就要能养啊,虽然我不知道井里的那个死孩子的母亲 ...

  5. 数据挖掘导论Pangaea-Ning Tan 读书笔记——(第一,二,三章)

    <数据挖掘导论>Pang-Ning Tan ,Michael Steinbach,Vipin Kumar 读书笔记, 第一章 绪论 数据挖掘任务 预测任务 描述任务 分类任务 回归任务 聚 ...

  6. 工程光学第一、二、六章学习总结

    前言 我知道我不能停留在现在.......只有通过加强学习.工程光学的书从去年12月开始陆陆续续地看,到今年基本没看了,这两天我把条件都找齐了,最关键是合适的地方,找到了,还有X先生给我的电脑,给我的 ...

  7. 同济版高等数学复习笔记(上册第五、六章)

    第五章 定积分 第一节 定积分的概念与性质 一.定积分问题实例 曲边梯形面积 变速直线运动位移 二.定积分的定义 1. 定积分的定义 函数 f ( x ) f(x) f(x) 在 [ a , b ] ...

  8. 尔雅 科学通史(吴国盛) 个人笔记及课后习题 2018 第六章 自然的数学化和分析化

    科学通史 第六章 自然的数学化和分析化 6.1自然的数学化和分析化 希腊背景和基督教背景是欧洲科技革命必不可缺的背景 欧洲数理传统学科 哥白尼革命 6.1自然的数学化和分析化(习题) 6.2天文学的发 ...

  9. Windows核心编程(笔记13) 第十六章--第二十六章

    改变下记录方式,只写自己觉得需要注意一下的防止出错的地方,或者一些特别重要的点,或者一些感悟. 第十六章 线程栈 第十七章 内存映射文件 1.注意写时复制在内存映射文件中的用处. 2.#pagma d ...

最新文章

  1. python的gui库哪个好_常用的13 个Python开发者必备的Python GUI库
  2. Linux桌面环境与命令行环境切换快捷键,以及linux 图形界面 X Server 关闭 启动
  3. thinkpad密码忘记
  4. QCon北京2016启动筹备 众多热点专题诚征演讲嘉宾
  5. c语言多重括号,大佬在吗,我用C写了一个去多重括号的函数,结果。。。
  6. C# 8 新特性 - 异步流 Asynchronous Streams
  7. Java Syncrhonisers
  8. 使用Mybatis-plus更新null字段的解决方案
  9. AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
  10. postman测试登录后的接口_中文版Postman测试需要登陆才能访问的接口(基于Cookie)...
  11. 使用ZipCodeValidatorDomainType验证不同国家的邮编
  12. java隐式参数的作用_隐式参数_scala教程_田守枝Java技术博客
  13. java进度条_「java进度条」Java JProgressBar类(进度条) - seo实验室
  14. win10系统优化与防范策略
  15. python小游戏:剪刀,石头,布
  16. 算法时间复杂度分析(一)
  17. 小武与剑指offer的恩怨情仇
  18. 麦客服务器维修,麦客
  19. PSRAM 伪静态随机存取内存
  20. MAC M1/M2安装ADOBE等第三方软件问题终极解决 “开启任何来源”“无法检查更新,请确认您已接入互联网”“移除下载镜像的Quarantine属性” “闪退”【MACBOOK】

热门文章

  1. 公司企业邮箱登陆客户端,邮件服务器如何设置?
  2. 为什么要学习HashMap的底层原理?
  3. 计算机图形学之二维平移旋转缩放代码
  4. c语言程序(十八)——迭代计算
  5. 0002.css编写文档中的年月日/日期填写格式
  6. 关于nmap -O扫描中出现索尼手机的一份调研
  7. 汽车维修行业开发微信小程序的必要性
  8. [转] 如何用BSP树生成游戏地图
  9. 小米路由器刷Xiaomi Mi WiFi Mini openwrt
  10. ChatGPT官方鉴别器紧急发布!当代自相矛盾,不想却遭遇群嘲