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. EithervkBeginCommandBufferhas never been called, or the command buffer has been reset since it last recorded commands. -
Recording state: Between
vkBeginCommandBufferandvkEndCommandBuffer. 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.
重置 一个命令缓冲区是一个把之前记录的命令抛弃并把命令缓冲区置为初始状态的操作。 重置是 vkResetCommandBuffer、vkResetCommandPool,或者 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指向一个VkCommandPoolhandle ,用它接收被创建缓存池。
VkCommandPoolCreateInfo 类型数据结构定义如下:
typedef struct VkCommandPoolCreateInfo {
VkStructureType sType;
const void* pNext;
VkCommandPoolCreateFlags flags;
uint32_t queueFamilyIndex;
} VkCommandPoolCreateInfo;
-
sType是这个数据结构的类型。 -
pNext是NULL或者一个指向拓展特定的数据结构的指针。 -
flagsis 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_BITindicates 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_BITcontrols 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 callingvkResetCommandBuffer, or implicitly, by callingvkBeginCommandBufferon an executable command buffer. If this flag is not set, thenvkResetCommandBufferandvkBeginCommandBuffer(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 callingvkResetCommandPool.-
queueFamilyIndexdesignates 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.
-
-
可调用如下命令来重置命令缓存池:
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
flagsincludesVK_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.
可调用如下命令来销毁命令缓存池:
void vkDestroyCommandPool(
VkDevice device,
VkCommandPool commandPool,
const VkAllocationCallbacks* pAllocator);
-
device是需要销毁命令缓存池的逻辑设备。 -
commandPool是需被销毁的命令缓存池的handle。 -
pAllocatorcontrols host memory allocation as described in the Memory Allocation chapter.
当一个缓存池被销毁了,所有从之分配命令缓冲区都被释放了,变得无效了。 从一个给定的缓存池分配而来的命令缓冲区并不需要在销毁命令缓存池之前被释放。
本文介绍了Vulkan中的命令缓冲区与命令池的概念及其使用方式。详细讲解了命令缓冲区的不同状态、如何创建及重置命令池,并探讨了命令缓冲区与命令池之间的关系。
438

被折叠的 条评论
为什么被折叠?



