vulkan从小白到专家——VulkanDevice
0关于vulkan
1)定义了一堆的概念,跟opengl太不一样了,以至于出来很多年了,实际普及率很低。
2)驱动极大简化,很多工作都丢给了开发者维护。
Vulkan不像opengl,一个Context太过于抽象和笼统。vulkan的概念更加切合实际,走进vulkan,首先要理解device。

0.1 vulkan pattern
获取属性接口的pattern,
XXXGet(int* counter, XXXProperty* arr); 参数可能还包含一个作用域 比较device,之类。
一般两次调用,
- 获取个数:后面array传nullptr,第一个参数传入counter的地址,
- 创建动态数组以后,
- 精准填充数组,传入参数和数组地址即可,
0.2 name pattern
结构体V大写,函数vk都小写,
1 ApplicationCreateInfo,
填充VkApplicationInfo结构体,
apiVersion
- apiVersion = VK_MAKE_VERSION(1, 0, 0);
- 或者 apiVersion = VK_API_VERSION_1_1
2 Instance
创建Instance之前,先一顿骚操作,查询各种关联信息。
1、获取instance个数,
android上测试获取instance个数失败,始终为0,
uint32_t instance_layer_count = 0;
// use nullptr for second parameters in order to get all the layer count
vkEnumerateInstanceLayerProperties(&instance_layer_count, nullptr);
if (instance_layer_count == 0) {
// return;
}
VkLayerProperties instance_properties[50]; // 方便调试所以用栈
vkEnumerateInstanceLayerProperties(&instance_layer_count, instance_properties);
2、获取扩展信息ok的,
uint32_t extension_count = 0;
auto xxhr = vkEnumerateInstanceExtensionProperties(
nullptr, &extension_count, nullptr);
VkExtensionProperties extension_availables[extension_count];
vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_availables);
p40pro上获取到信息如下:
(VkExtensionProperties[50]) {
[0] = (extensionName = “VK_KHR_surface”, specVersion = 25)
[1] = (extensionName = “VK_KHR_android_surface”, specVersion = 6)
[2] = (extensionName = “VK_EXT_swapchain_colorspace”, specVersion = 4)
[3] = (extensionName = “VK_KHR_get_surface_capabilities2”, specVersion = 1)
[4] = (extensionName = “VK_EXT_debug_report”, specVersion = 9)
[5] = (extensionName = “VK_KHR_device_group_creation”, specVersion = 1)
[6] = (extensionName = “VK_KHR_external_fence_capabilities”, specVersion = 1)
[7] = (extensionName = “VK_KHR_external_memory_capabilities”, specVersion = 1)
[8] = (extensionName = “VK_KHR_external_semaphore_capabilities”, specVersion = 1)
[9] = (extensionName = “VK_KHR_get_physical_device_properties2”, specVersion = 2)
3、创建Instance
先填充VkInstanceCreateInfo结构体,要引用上面ApplicationInfo,
Instance的扩展属性需要分平台填充,一些demo中都是如下代码直接给出的,不科学。
instance_extensions.push_back("VK_KHR_surface");
instance_extensions.push_back("VK_KHR_android_surface");
正确分平台获取方式
instance_extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); //
#ifdef __ANDROID
instance_extensions.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME); // vulkan_android.h 中
#elif defined(__WIN32)
instance_extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
#elif defined(__linux)
instance_extensions.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
#elif defined(__APPLE__)
instance_extensions.push_back(VK_KHR_MACOS_SURFACE_EXTENSION_NAME);
#endif
3 创建surface
pattern=AndroidSurface
填充结构体:Vk{pattern}CreateInfoKHR
创建函数,vkCreate{pattern}KHR
4 GPU/physical Device
创建之前,还是先查询,
4.1 穷举物理设备的个数
还是相同套路,先获取个数,再获取数组内容,
一般android上就一个GPU设备,
// Find one GPU to use:
// On Android, every GPU device is equal -- supporting
// graphics/compute/present
// for this sample, we use the very first GPU device found on the system
uint32_t gpuCount = 0;
CALL_VK(vkEnumeratePhysicalDevices(device.instance_, &gpuCount, nullptr));
VkPhysicalDevice tmpGpus[gpuCount];
CALL_VK(vkEnumeratePhysicalDevices(device.instance_, &gpuCount, tmpGpus));
device.gpuDevice_ = tmpGpus[0]; // Pick up the first GPU Device
4.2 获取属性
// 获取属性 deviceName是厂家GPU型号
VkPhysicalDeviceProperties vk_physical_device_properties;
vkGetPhysicalDeviceProperties(device.gpuDevice_, &vk_physical_device_properties);
// 获取特性
VkPhysicalDeviceFeatures vk_physical_device_features;
vkGetPhysicalDeviceFeatures(device.gpuDevice_, &vk_physical_device_features);
vkGetPhysicalDeviceMemoryProperties(device.gpuDevice_,
&device.gpuMemoryProperties_);
DeviceProperty是gpu厂商名称,vendorID,驱动版本。
(lldb) p vk_physical_device_properties
(VkPhysicalDeviceProperties) {
apiVersion = 4198591
driverVersion = 142606336
vendorID = 5045
deviceID = 1913716736
deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
deviceName = "Mali-G76\0"
pipelineCacheUUID = "\x8b\r\x85ց\xecb#\xde\xf6>ݮb\xc7\U00000011"
limits = // 其他扩展信息
}
DeviceFeature和MemoryProoerty都是一些专业参数,
5 QueueFamily
队列的类型如下:
typedef enum VkQueueFlagBits {
VK_QUEUE_GRAPHICS_BIT = 0x00000001,
VK_QUEUE_COMPUTE_BIT = 0x00000002,
VK_QUEUE_TRANSFER_BIT = 0x00000004,
VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008,
VK_QUEUE_PROTECTED_BIT = 0x00000010,
VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkQueueFlagBits;
至少得有一个graphics队列才能正常渲染,否则就得退出程序了。
p40上测试,最多支持16个队列,实际获取的只有一个队列,类型为graphics。
// Find a GFX queue family
uint32_t queueFamilyCount;
vkGetPhysicalDeviceQueueFamilyProperties(device.gpuDevice_, &queueFamilyCount,
nullptr);
assert(queueFamilyCount);
std::vector<VkQueueFamilyProperties> queueFamilyProperties(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device.gpuDevice_, &queueFamilyCount,
queueFamilyProperties.data());
VkQueueFamilyProperties::queueFlags 代表队列类型,上文的VkQueueFlagBits
6 创建Device
vkCreateDevice,在制定物理设备(GPU)上创建一个逻辑设备,参数如下:
- physicalDevice 指定在哪一个物理设备上创建逻辑设备。
- pCreateInfo 创建逻辑设备的配置信息。
- pAllocator 内存分配器。为 nullptr 表示使用内部默认分配器,否则为自定义分配器。
- pDevice 创建逻辑设备的结果
VkDeviceCreateInfo 要关联VkDeviceQueueCreateInfo数组,
VkDeviceQueueCreateInfo::queueFamilyIndex 必须 是目标物理设备中有效的设备队列族索引,
6.2 获取queue
获取队列保存handle,
vkGetDeviceQueue(device.device_, 0, 0, &device.queue_);
queueFamilyIndex=0
graphics_queueIndex=0
附录
CreateVulkanDevice代码
// Create vulkan device
void CreateVulkanDevice(ANativeWindow *platformWindow,
VkApplicationInfo *appInfo) {
std::vector<const char *> instance_extensions;
std::vector<const char *> device_extensions;
//instance_extensions.push_back("VK_KHR_surface");
//instance_extensions.push_back("VK_KHR_android_surface");
instance_extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); //
instance_extensions.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
device_extensions.push_back("VK_KHR_swapchain");
// #Section1 Instance
uint32_t instance_layer_count = 0;
// use nullptr for second parameters in order to get all the layer count
vkEnumerateInstanceLayerProperties(&instance_layer_count, nullptr);
if (instance_layer_count == 0) {
// return;
}
VkLayerProperties instance_properties[5]; // 方便调试所以用栈
vkEnumerateInstanceLayerProperties(&instance_layer_count, instance_properties);
uint32_t extension_count = 0;
auto xxhr = vkEnumerateInstanceExtensionProperties(
nullptr, &extension_count, nullptr);
VkExtensionProperties extension_availables[extension_count];
vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_availables);
// **********************************************************
// Create the Vulkan instance
VkInstanceCreateInfo instanceCreateInfo{
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pNext = nullptr,
.pApplicationInfo = appInfo,
.enabledLayerCount = 0,
.ppEnabledLayerNames = nullptr,
.enabledExtensionCount =
static_cast<uint32_t>(instance_extensions.size()),
.ppEnabledExtensionNames = instance_extensions.data(),
};
CALL_VK(vkCreateInstance(&instanceCreateInfo, nullptr, &device.instance_));
// #Section2 surface
VkAndroidSurfaceCreateInfoKHR createInfo{
.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR,
.pNext = nullptr,
.flags = 0,
.window = platformWindow};
CALL_VK(vkCreateAndroidSurfaceKHR(device.instance_, &createInfo, nullptr,
&device.surface_));
// #Section3 physical devices
// Find one GPU to use:
// On Android, every GPU device is equal -- supporting
// graphics/compute/present
// for this sample, we use the very first GPU device found on the system
uint32_t gpuCount = 0;
CALL_VK(vkEnumeratePhysicalDevices(device.instance_, &gpuCount, nullptr));
VkPhysicalDevice tmpGpus[gpuCount];
CALL_VK(vkEnumeratePhysicalDevices(device.instance_, &gpuCount, tmpGpus));
device.gpuDevice_ = tmpGpus[0]; // Pick up the first GPU Device
// 获取属性 deviceName是厂家GPU型号
VkPhysicalDeviceProperties vk_physical_device_properties;
vkGetPhysicalDeviceProperties(device.gpuDevice_, &vk_physical_device_properties);
// 获取特性
VkPhysicalDeviceFeatures vk_physical_device_features;
vkGetPhysicalDeviceFeatures(device.gpuDevice_, &vk_physical_device_features);
vkGetPhysicalDeviceMemoryProperties(device.gpuDevice_,
&device.gpuMemoryProperties_);
// #Section4 queue family
// Find a GFX queue family
uint32_t queueFamilyCount;
vkGetPhysicalDeviceQueueFamilyProperties(device.gpuDevice_, &queueFamilyCount,
nullptr);
assert(queueFamilyCount);
std::vector<VkQueueFamilyProperties> queueFamilyProperties(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device.gpuDevice_, &queueFamilyCount,
queueFamilyProperties.data());
uint32_t queueFamilyIndex;
for (queueFamilyIndex = 0; queueFamilyIndex < queueFamilyCount; queueFamilyIndex++) {
if (queueFamilyProperties[queueFamilyIndex].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
break;
}
}
// {{ 遍历queueFamily
auto fill_index = [&](VkQueueFlagBits filter, int& dstSlot) {
for (int k = 0; k < queueFamilyCount; k++) {
if (queueFamilyProperties[k].queueFlags & filter) {
dstSlot = k;
break;
}
}
};
int graphics_queue_index = -1;
int compute_queue_index = -1;
int sparse_queue_index = -1;
fill_index(VK_QUEUE_GRAPHICS_BIT, graphics_queue_index);
fill_index(VK_QUEUE_COMPUTE_BIT, compute_queue_index);
fill_index(VK_QUEUE_SPARSE_BINDING_BIT, sparse_queue_index);
VkQueue graphics_queue;
VkQueue compute_queue;
VkQueue sparse_queue;
// 遍历queueFamily }}
assert(queueFamilyIndex < queueFamilyCount);
device.queueFamilyIndex_ = queueFamilyIndex;
// Create a logical device (vulkan device)
float priorities[] = {
1.0f,
};
VkDeviceQueueCreateInfo queueCreateInfo{
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.queueFamilyIndex = device.queueFamilyIndex_,
.queueCount = 1,
.pQueuePriorities = priorities,
};
VkDeviceCreateInfo deviceCreateInfo{
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.pNext = nullptr,
.queueCreateInfoCount = 1,
.pQueueCreateInfos = &queueCreateInfo,
.enabledLayerCount = 0,
.ppEnabledLayerNames = nullptr,
.enabledExtensionCount = static_cast<uint32_t>(device_extensions.size()),
.ppEnabledExtensionNames = device_extensions.data(),
.pEnabledFeatures = &vk_physical_device_features,
};
CALL_VK(vkCreateDevice(device.gpuDevice_, &deviceCreateInfo, nullptr,
&device.device_));
vkGetDeviceQueue(device.device_, 0, 0, &device.queue_);
}
更多推荐



所有评论(0)