Vulkan规范:第五章 5.1

来源:互联网 发布:淘宝返利源码 编辑:程序博客网 时间:2024/06/05 17:04

5. 命令缓冲区

命令缓冲区是用来记录命令的对象,可以顺序的提交到队列以供执行。有两个级别的命令缓冲区: 主命令缓冲区(可以执行次命令缓冲区,被提交到队列),次命令缓冲区(可以被主命令缓冲区执行,不直接被提交到队列)。

命令缓冲区通过VkCommandBuffer handles表示:

VK_DEFINE_HANDLE(VkCommandBuffer)

记录的命令缓冲区包括绑定管线和描述符到命令缓冲区的命令、修改动态状态的命令、绘制命令,分发命令,执行次命令缓冲区的命令、 复制缓冲区和图像等命令。

每一个命令缓冲区都独立的管理状态。主、次命令缓冲区之间或者两个次级命令缓冲区之间并不继承状态。 当一个命令缓冲区开始记录,该命令缓冲区所有的状态是未定义的。 当次级命令缓冲区被记录以备在主命令缓冲区上执行时,次级命令缓冲区并不从主命令缓冲区继承状态, 在执行次级命令缓冲区后被记录后主命令缓冲区的所有状态是未定义的。 对于这条规则有一个例外—​如果主命令缓冲区在一个渲染pass实例中,那么这个renderpass和subpass状态 并不会被次级命令缓冲区的执行所干扰。 当命令缓冲区的状态是未定义时,应用程序必须在依赖诸如绘制、分发的命令被记录之前 设置命令缓冲区上的相关状态,否则执行命令缓冲区的导致的行为是未知的。

除非特别指定了,或者显式地进行同步,通过命令缓冲区把提交到队列的各种命令才能以任意的顺序, 或者同时执行。还有,若没有显式的内存依赖,这些命令带来的内存副作用可能并不会直接被其他命令看到。 在同一个命令缓冲区,提交到一个指定队列的不同命令缓冲区之间都是有效的。 查看the synchronization chapter 来获取命令之间隐式的 和显式同步的信息。

Each command buffer is always in one of three states:

  • Initial state: Before vkBeginCommandBuffer. Either vkBeginCommandBuffer has never been called, or the command buffer has been reset since it last recorded commands.

  • Recording state: Between vkBeginCommandBuffer and vkEndCommandBuffer. The command buffer is in a state where it can record commands.

  • Executable state: After vkEndCommandBuffer. The command buffer is in a state where it has finished recording commands and can be executed.

重置 一个命令缓冲区是一个把之前记录的命令抛弃并把命令缓冲区置为初始状态的操作。 重置是 vkResetCommandBuffervkResetCommandPool,或者 vkBeginCommandBuffer(当把一个命令缓冲区放到记录状态)调用的结果。

5.1. 命令池

命令缓存池是一个不透明对象,可从之分配出命令缓冲区内存,它可允许Vulkan实现均摊多个命令缓冲区 创建资源的开销。命令缓存池需要在外部保持同步,意味着一个命令缓存池不能同时被多个线程使用。 这包括通过记录命令到任何从缓存池中获取的命令缓冲区,和分配、释放、重置命令缓冲区或命令缓存池本身 等操作。

命令缓冲池是通过VkCommandPool 类型handle来表示的:

VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool)

可调用如下命令来创建目录缓存池:

VkResult vkCreateCommandPool(    VkDevice                                    device,    const VkCommandPoolCreateInfo*              pCreateInfo,    const VkAllocationCallbacks*                pAllocator,    VkCommandPool*                              pCommandPool);
  • device 是创建命令缓冲池的逻辑设备。

  • pCreateInfo 包含用来创建命令缓冲池的信息。

  • pAllocator 控制CPU端内存分配,如Memory Allocation 一章所讲。

  • pCommandPool 指向一个VkCommandPool handle ,用它接收被创建缓存池。

Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • pCreateInfo must be a pointer to a valid VkCommandPoolCreateInfo structure

  • If pAllocator is not NULLpAllocator must be a pointer to a valid VkAllocationCallbacks structure

  • pCommandPool must be a pointer to a VkCommandPool handle

Return Codes
Success
  • VK_SUCCESS

Failure
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

VkCommandPoolCreateInfo 类型数据结构定义如下:

typedef struct VkCommandPoolCreateInfo {    VkStructureType             sType;    const void*                 pNext;    VkCommandPoolCreateFlags    flags;    uint32_t                    queueFamilyIndex;} VkCommandPoolCreateInfo;
  • sType 是这个数据结构的类型。

  • pNext 是 NULL 或者一个指向拓展特定的数据结构的指针。

  • flags is a bit标志位,表示缓存池和从它分配出来的命令缓冲区的用途。 bit位可选如下:

    typedef enum VkCommandPoolCreateFlagBits {    VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001,    VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002,} VkCommandPoolCreateFlagBits;
    • VK_COMMAND_POOL_CREATE_TRANSIENT_BIT indicates that command buffers allocated from the pool will be short-lived, meaning that they will be reset or freed in a relatively short timeframe. This flag may be used by the implementation to control memory allocation behavior within the pool.

    • VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT controls whether command buffers allocated from the pool can be individually reset. If this flag is set, individual command buffers allocated from the pool can be reset either explicitly, by calling vkResetCommandBuffer, or implicitly, by calling vkBeginCommandBuffer on an executable command buffer. If this flag is not set, then vkResetCommandBuffer and vkBeginCommandBuffer (on an executable command buffer) must not be called on the command buffers allocated from the pool, and they canonly be reset in bulk by calling vkResetCommandPool.

      • queueFamilyIndex designates a queue family as described in section Queue Family Properties. All command buffers allocated from this command pool must be submitted on queues from the same queue family.

正确使用
  • queueFamilyIndex must be the index of a queue family available in the calling command’s device parameter

Valid Usage (Implicit)
  • sType must be VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO

  • pNext must be NULL

  • flags must be a valid combination of VkCommandPoolCreateFlagBits values

可调用如下命令来重置命令缓存池:

VkResult vkResetCommandPool(    VkDevice                                    device,    VkCommandPool                               commandPool,    VkCommandPoolResetFlags                     flags);
  • device 是拥有命令缓存池的逻辑设备。

  • commandPool 是需要被重置的命令缓存池。

  • flags 包那好附加的标志位,可控制重置行为。 Bits which can be set include:

    typedef enum VkCommandPoolResetFlagBits {    VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 0x00000001,} VkCommandPoolResetFlagBits;

    If flags includes VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT, resetting a command pool recycles all of the resources from the command pool back to the system.

Resetting a command pool recycles all of the resources from all of the command buffers allocated from the command pool back to the command pool. All command buffers that have been allocated from the command pool are put in the initial state.

正确使用
  • All VkCommandBuffer objects allocated from commandPool must not currently be pending execution

Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • commandPool must be a valid VkCommandPool handle

  • flags must be a valid combination of VkCommandPoolResetFlagBits values

  • commandPool must have been created, allocated, or retrieved from device

Host Synchronization
  • Host access to commandPool must be externally synchronized

Return Codes
Success
  • VK_SUCCESS

Failure
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

可调用如下命令来销毁命令缓存池:

void vkDestroyCommandPool(    VkDevice                                    device,    VkCommandPool                               commandPool,    const VkAllocationCallbacks*                pAllocator);
  • device 是需要销毁命令缓存池的逻辑设备。

  • commandPool 是需被销毁的命令缓存池的handle。

  • pAllocator controls host memory allocation as described in the Memory Allocation chapter.

当一个缓存池被销毁了,所有从之分配命令缓冲区都被释放了,变得无效了。 从一个给定的缓存池分配而来的命令缓冲区并不需要在销毁命令缓存池之前被释放。

正确使用
  • All VkCommandBuffer objects allocated from commandPool must not be pending execution

  • If VkAllocationCallbacks were provided when commandPool was created, a compatible set of callbacks must be provided here

  • If no VkAllocationCallbacks were provided when commandPool was created, pAllocator must be NULL

Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • If commandPool is not VK_NULL_HANDLEcommandPool must be a valid VkCommandPool handle

  • If pAllocator is not NULLpAllocator must be a pointer to a valid VkAllocationCallbacks structure

  • If commandPool is a valid handle, it must have been created, allocated, or retrieved from device

Host Synchronization
  • Host access to commandPool must be externally synchronized

原创粉丝点击