4.2. 设备
设备对象表示和物理设备之间的一个连接。每一个设备对外暴露一些 队列族,每一个都有一个或多个_队列_。 在一个队列族中的所有队列都支持相同的操作。
如在Physical Devices中所描述的,一个Vulkan应用程序将首先查询 一个系统中所有的物理设备。 每一个物理设备可以被查询它的能力,包含队列和队列族的属性。一旦一个可接受的物理设备被确认了,应用程序将创建对应的 逻辑设备。应用程序必须对每一个使用的物理设备创建单独的逻辑设备。被创建的逻辑设备然后就是和物理设备之间的接口了。
如何遍历一个系统中的物理设备并查询这些物理设备的队列族属性在之前的 Physical Device Enumeration小节讲解过。
4.2.1. 设备创建
逻辑设备通过VkDevice
handles表示:
VK_DEFINE_HANDLE(VkDevice)
一个逻辑设备被当作和物理设备的连接被创建。调用下面的命令来创建逻辑设备:
VkResult vkCreateDevice(
VkPhysicalDevice physicalDevice,
const VkDeviceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDevice* pDevice);
-
physicalDevice
必须: 是vkEnumeratePhysicalDevices
调用返回的多个队列中的一个的handle(参考 Physical Device Enumeration)。 -
pCreateInfo
是一个指针,指向一个类型为VkDeviceCreateInfo
的数据结构,包含如何创建设备的信息。 -
pAllocator
控制了CPU端内存分配,如 Memory Allocation 一章所描述。 -
pDevice
指向了创建得到的VkDevice
的handle。
可以在同一个物理设备上创建多个逻辑设备。因为物理资源的缺乏(和其他错误),逻辑设备的创建可能失败。 如果发生了失败,vkCreateDevice
将返回VK_ERROR_TOO_MANY_OBJECTS
。
VkDeviceCreateInfo
数据结构定义如下:
typedef struct VkDeviceCreateInfo {
VkStructureType sType;
const void* pNext;
VkDeviceCreateFlags flags;
uint32_t queueCreateInfoCount;
const VkDeviceQueueCreateInfo* pQueueCreateInfos;
uint32_t enabledLayerCount;
const char* const* ppEnabledLayerNames;
uint32_t enabledExtensionCount;
const char* const* ppEnabledExtensionNames;
const VkPhysicalDeviceFeatures* pEnabledFeatures;
} VkDeviceCreateInfo;
-
sType
是数据结构的类型。 -
pNext
是NULL
或者一个指向拓展特定的数据结构。 -
flags
被保留使用。 -
queueCreateInfoCount
是pQueueCreateInfos
数组的大小。参考 下面的Queue Creation 一节来获取更多信息。 -
pQueueCreateInfos
是一个指针,指向一个元素类型为VkDeviceQueueCreateInfo
的数组,描述了 describing the queues that are requested to be created along with the logical device. Refer to the Queue Creation section below for further details. -
enabledLayerCount
已弃用,被忽略。 -
ppEnabledLayerNames
已弃用,被忽略。参考 Device Layer Deprecation. -
enabledExtensionCount
是启用的设备拓展的个数。 -
ppEnabledExtensionNames
是一个指针,指向了一个长度为enabledExtensionCount
,null-terminated UTF-8 字符串, 包含了将对创建的设备所启用的拓展名字。 参考Extensions 一节来获取更多细节。 -
pEnabledFeatures
是NULL
,或者是一个指针,指向一个VkPhysicalDeviceFeatures
数据结构,其包含了所有将被启用的特征的 boolean标志位。 参考Features 一节获取更多细节。
4.2.2. 使用设备
下面是如何使用 VkDevice
的上层列表,还有详细信息的参考点:
-
创建队列。 请参考下面的Queues 一节来获取更多细节。
-
创建并跟踪各种同步对象。 参考 Synchronization and Cache Control 来获取更多细节。
-
分配,释放和管理内存。 参考 Memory Allocation 和 Resource Creation 以获取更多细节。
-
创建和销毁命令缓冲区、命令缓存池。 参考 Command Buffers 以获取更多细节。
-
创建,销毁和管理图形状态。 参考 Pipelines 和 Resource Descriptors还有其他的小节,以获取更多细节。
4.2.3. 设备丢失
逻辑设备可能因为硬件错误、执行超时、电源管理事件和平台某些事件而丢失。这会导致待执行的命令执行失败和硬件资源损坏。 当发生这种情况时,某些命令会返回name:VK_ERROR_DEVICE_LOST(参考Error Codes)。 发生了这种情况后,逻辑设备被认为已经丢失了。 不可能重置逻辑设备到非丢失状态,然而,这个丢失状态只是针对逻辑设备而言的,对应的物理设备(VkPhysicalDevice
)可能不受影响。 一些情况下,物理设备也可能丢失,尝试创建逻辑设备会失败,返回VK_ERROR_DEVICE_LOST
。这通常意味着潜在的硬件问题,或者和 CPU端的连接问题。 如果物理设备没有被丢失,在它上面一个新的逻辑设备成功的被创建了,物理设备一定是非丢失状态。
注意
同时,逻辑设备丢失是可恢复的,物理设备丢失的情况下,除非系统中有另外未受影响的物理设备,否则应用程序不可能会恢复。 错误大体上是信息性的,试图通知用户他们的硬件可能产生了错误或连接不良,应该自己调查一下。一些情况下,物理设备丢失可能导致 其他严重的问题,比如操作系统崩溃,这样的话Vulkan API就不会给出原因了。 |
注意
应用程序导致的未知行为可能导致设备丢失。然而,这些未定义行为也会导致进程内存损坏,此时就不能保证API对象,包括 |
当设备丢失了,它的子对象并没有隐式的被销毁,它们的handle仍然有效。这些对象必须要在他们父对象 或者设备被销毁之前被销毁(参考 Object Lifetime 小节 )。 使用vkMapMemory
把设备内存映射到CPU端寻址空间的内存依然有效,对于被映射区域的CPU端内存访问仍然是有效的,但是内存内容是未定义的。 仍然可以对设备和它的子对象调用任何API命令。
一旦设备丢失,命令执行可能失败:,返回VkResult
的命令有可能: 返回VK_ERROR_DEVICE_LOST
。 不允许运行时错误的命令有可能仍然正常使用中,有可能的话,仍返回有效的数据。
Commands that wait indefinitely for device execution (namely vkDeviceWaitIdle
, vkQueueWaitIdle
, vkWaitForFences
with a maximum timeout
, and vkGetQueryPoolResults
with the VK_QUERY_RESULT_WAIT_BIT
bit set in flags
) must return in finite time even in the case of a lost device, and return either VK_SUCCESS
or VK_ERROR_DEVICE_LOST
. For any command that may return VK_ERROR_DEVICE_LOST
, for the purpose of determining whether a command buffer is pending execution, or whether resources are considered in-use by the device, a return value of VK_ERROR_DEVICE_LOST
is equivalent to VK_SUCCESS
.
editing-note
TODO (piman) - I do not think we are very clear about what “in-use by the device” means. |
4.2.4. 设备销毁
可调用如下命令来销毁设备:
void vkDestroyDevice(
VkDevice device,
const VkAllocationCallbacks* pAllocator);
-
device
是需要被销毁的逻辑设备。 -
pAllocator
控制CPU内存分配,如 Memory Allocation 一章讲解。
为了保证在设备上没有正在进行的工作,vkDeviceWaitIdle 可以: 用来守护设备的销毁。 在销毁设备之前,应用程序需要负责销毁/释放从该设备上创建出来的Vulkan对象(使用vkCreate
* 、vkAllocate
* 等命令并以该device作为第一个参数)。
注意
The lifetime of each of these objects is bound by the lifetime of the |