2. physical devices与queue families中选择好了物理设备和queue family之后,我们与其交互并不是直接通过这两个实例,而是通过逻辑设备和queue。

而逻辑设备的创建和vulkan实例的创建类似,准备好createInfo,调用调用对应的create方法即可。对于逻辑设备来说,指定好使用的queue信息.

创建逻辑设备

VkDevice device;
 
VkDeviceCreateInfo createInfo{}; 
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
 
// 准备好要使用的queue信息
float queuePriority = 1.0f;
VkDeviceQueueCreateInfo queueCreateInfo{};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = queueFamily;
queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &queuePriority;
 
// 填充到逻辑设备的createInfo当中
createInfo.queueCreateInfoCount = 1;
createInfo.pQueueCreateInfos = &queueCreateInfo;
// 填充要使用的设备特性
VkPhysicalDeviceFeatures deviceFeatures{};
createInfo.pEnabledFeatures = &deviceFeatures;
 
// 设置设备要使用的扩展和校验层。和vulkan instance的用法相同。这是这里是特定设备级别的。不过扩展和校验层只在旧版才区分实例级别和设备级别,在新版之后就不区分了。这里的设置只是为了兼容旧版本,在新版的实现当中就算设置了也会被忽略的
createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size()); 
createInfo.ppEnabledLayerNames = validationLayers.data();
 
if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) { 
	throw std::runtime_error("failed to create logical device!"); 
}

退出之前销毁调用下面的代码即可

vkDestroyDevice(device, nullptr);

queue

queue是随着逻辑设备一起创建和销毁的。通过逻辑设备以及指定的queue family号就能够查询到

VkQueue graphicsQueue;
vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue);

有了逻辑设备和queue之后,可以真正开始做一些图形化的工作了。