说明
在创建了Vulkan Instance 对象后,下一步就是枚举physical devices,选择其中一个,并根据它创建又给logical device,这些操作通过instance-level级函数进行执行.
Vulkan里几乎所有工作都是在logical device上执行的:在其上创建资源,管理他们的内存,记录由它们创建的command buffers,向他们的queues提交处理commands.
physical device
枚举所有可以使用的physical devices
1 | uint32_t devices_count = 0; |
extensions
1 | uint32_t extensions_count = 0; |
获取pyhsical device的features和properties
1 | vkEnumeratePhysicalDevices() |
logic device
检查可用的queue families和他们的properties
在vulkan里,对硬件的所有操作都是通过提交到queues里进行的.提交到同一个queue里的命令是一个接着一个执行的,提交到不同queue里的命令是独立的(需要同步他们)
不同的queues可能表示硬件的不同部分,因此会支持不同的操作,并非所有操作都可以在所有queue上执行.
有相同策略的queue被聚合在同样的family里,一个device可能暴露任意数量的queue families,每一个family可能包括一个或多个queues.要想检查硬件能执行什么操作,需要便利所有queue families的属性.
步骤
1 | uint32_t queue_families_count = 0; |
从properties中能获取到的最重要的信息是能在已给family的queues里进行的操作类型,操作类型被分为:
- Graphics:创建graphics pipelines和drawing
- Compute:创建compute pipelines和dispatching compute shaders
- Transfer:用于非常快速的memory-copying操作
- Sparse:允许附加的内存管理功能
family的queues可能支持不知一种操作,可能不同的queue families支持相同类型的操作.
family属性也告知了queues的数量,是否支持时间戳,图像传输操作的粒度(在copy/blit操作时能控制的图像的最小部分).
创建logic device需要的queue families数量,属性,每个family可用的queues数量准备好后,只在创建logical device时请求他们,需要制定需要多少queue以及来自哪些families,当创建好logic device后,对应的queue也自动被创建,我们只需要获得请求的queue的handles.
重要属性 TODO
选择期望的queue family
选择一个physical device
1 | uint32_t queue_family_index = 0; |
创建logical devcie
logical device是app里创建的最重要的object,它代表了真实硬件,包括所有的扩展和激活的特性,以及向它请求的所有队列.
logical device允许我们做渲染软件里的所有工作,比如创建images和buffers,设置pipeline state或者加载shaders.最终要的是记录commands(比如draw calls或者分发computational works)和提交它们到queues.
准备
1 | struct QueueInfo { |
1 | std::vector<VkExtensionProperties> available_extensions; |
获取device queue
device queue是硬件资源,只能获取已有数量的
前提
1 | 获取到VkDvice logical_dvice |
1 | 调用 |
重复上述操作可以获取到所有queue families里的所有queues
创建有geometry shaders,graphics和compute queues的logical device
现在现需要美剧所有physical device找到其中支持geometry shaders,graphics和compute queues的来创建logical device
前期准备
1 | 声明变量 |
1 | std::vector<VkPhysicalDevice> physical_devices; |
对每一个physical device进行如下操作
1 | for( auto & physical_device : physical_devices ) { |
如果graphics和computee queue families有相同的index,我们能使用同一个queue,如果不同就要用两个
创建logical device
1 | if( !CreateLogicalDevice( physical_device, requested_queues, {}, |
Destroying a logical device
按照创建的相反顺序销毁资源
1 | if( logical_device ) { |