天天看點

Vulkan Tutorial 3 建立邏輯裝置

Vulkan邏輯裝置其實就對應一個相應的實體裝置。邏輯裝置用于向硬體裝置發送繪制指令。

因為我的電腦目前隻有一個實體裝置,同時為了簡單起見,gpus指定第0個元素。

裝置隊列和隊列族

Vulkan将裝置隊列暴露給外部,是以,程式員可知道目前哪些隊列正在使用,哪些類型的隊列正在被使用。這點跟其他圖形api不一樣。是以程式員可以更靈活的控制。

隊列是向硬體送出指令的抽象概念。

Vulkan将相同類型和特征的隊列歸入一個隊列族。可以從實體裝置查詢想要的隊列的類型和特征。

Vulkan Tutorial 3 建立邏輯裝置

隊列族屬性QueueFamilyProperties聲明如下:

typedef struct VkQueueFamilyProperties {
    VkQueueFlags    queueFlags;
    uint32_t        queueCount;
    uint32_t        timestampValidBits;
    VkExtent3D      minImageTransferGranularity;
} VkQueueFamilyProperties;

typedef enum VkQueueFlagBits {
    VK_QUEUE_GRAPHICS_BIT = 0x00000001,
    VK_QUEUE_COMPUTE_BIT = 0x00000002,
    VK_QUEUE_TRANSFER_BIT = 0x00000004,
    VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008,
} VkQueueFlagBits;
           

查找隊列族方法如下:

vkGetPhysicalDeviceQueueFamilyProperties(info.gpus[0], &info.queue_family_count, NULL);
info.queue_props.resize(info.queue_family_count);
vkGetPhysicalDeviceQueueFamilyProperties(info.gpus[0], &info.queue_family_count, info.queue_props.data());
           

 一個裝置可能會有多個隊列族,一個隊列族裡面可能會有多個隊列。如下所示:

Vulkan Tutorial 3 建立邏輯裝置

VkQueueFlagBits表示每個硬體隊列可以處理的負載類型。

有一些硬體可能會隻有一個隊列族,但是有多個隊列類型标志。如下所示:

Vulkan Tutorial 3 建立邏輯裝置

查找感興趣的隊列族的代碼如下:

VkDeviceQueueCreateInfo queue_info = {};
bool found = false;
for (unsigned int i = 0; i < info.queue_family_count; i++) {
    if (info.queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
        queue_info.queueFamilyIndex = i;
        found = true;
        break;
    }
}
           

找到想要的隊列族後,就是建立一個邏輯裝置了:

float queue_priorities[1] = {0.0};
    queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
    queue_info.pNext = NULL;
    queue_info.queueCount = 1;
    queue_info.pQueuePriorities = queue_priorities;

    VkDeviceCreateInfo device_info = {};
    device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    device_info.pNext = NULL;
    device_info.queueCreateInfoCount = 1;
    device_info.pQueueCreateInfos = &queue_info;
    device_info.enabledExtensionCount = 0;
    device_info.ppEnabledExtensionNames = NULL;
    device_info.enabledLayerCount = 0;
    device_info.ppEnabledLayerNames = NULL;
    device_info.pEnabledFeatures = NULL;

    VkDevice device;
    VkResult U_ASSERT_ONLY res = vkCreateDevice(info.gpus[0], &device_info, NULL, &device);
           

另外,教程裡面提到一點,裝置Layer将會被棄用,以後都不需要考慮裝置Layer的問題。