Vulkan 开发(五):Vulkan 逻辑设备

图片

图片来自《Vulkan 应用开发指南》

Vulkan 开发系列文章:

1. 开篇,Vulkan 概述

2. Vulkan 实例

3. Vulkan 物理设备

4. Vulkan 设备队列

在 Vulkan 中,逻辑设备(Logical Device)是与物理设备(Physical Device)交互的接口。它抽象了对特定 GPU (物理设备)的访问,使得应用程序能够提交命令并管理资源,而无需直接与物理硬件打交道。

举例来说,物理设备可能包含了三种队列:图形、计算和传输。但是逻辑设备创建的时候,可以只关联一个单独的队列(比如图形),这样我们就可以很方便地向队列提交指令缓存了。

创建逻辑设备

创建逻辑设备时,你需要指定你希望使用的队列族和队列、启用的扩展、以及一些其他特性。我们通过 vkCreateDevice() 函数创建逻辑设备。其定义如下:

vkCreateDevice

VkResult vkCreateDevice(
VkPhysicalDevice                            physicalDevice,
const VkDeviceCreateInfo*                   pCreateInfo,
const VkAllocationCallbacks*                pAllocator,
VkDevice*                                   pDevice);

  • physicalDevice 指定在哪一个物理设备上创建逻辑设备。

  • pCreateInfo 创建逻辑设备的配置信息。

  • pAllocator 内存分配器。为 nullptr 表示使用内部默认分配器,否则为自定义分配器。

  • pDevice 创建逻辑设备的结果。

其中 VkDeviceCreateInfo 定义如下:

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 是该结构体的类型枚举值, 必须 是 VkStructureType::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO 。

  • pNext 要么是 NULL 要么指向其他结构体来扩展该结构体。

  • flags 目前没用上,为将来做准备。

  • queueCreateInfoCount 指定 pQueueCreateInfos 数组元素个数。

  • pQueueCreateInfos 指定 VkDeviceQueueCreateInfo 数组。用于配置要创建的设备队列信息。

  • enabledLayerCount 指定 ppEnabledLayerNames 数组元素个数。该成员已被 遗弃 并 忽略 。

  • ppEnabledLayerNames 指定要开启的验证层。该成员已被 遗弃 并 忽略 。

  • enabledExtensionCount 指定 ppEnabledExtensionNames 数组中元素个数。

  • ppEnabledExtensionNames 指定要开启的扩展。该数组数量必须大于等于 enabledExtensionCount 。

  • pEnabledFeatures 配置要开启的特性。

其中 queueCreateInfoCount 和 pQueueCreateInfos 用于指定在逻辑设备中需要创建的 设备队列 。其中 VkDeviceQueueCreateInfo 定义如下:

VkDeviceQueueCreateInfo

// 由 VK_VERSION_1_0 提供
typedef struct VkDeviceQueueCreateInfo {
VkStructureType             sType;
const void*                 pNext;
VkDeviceQueueCreateFlags    flags;
uint32_t                    queueFamilyIndex;
uint32_t                    queueCount;
const float*                pQueuePriorities;
} VkDeviceQueueCreateInfo;

  • sType 是该结构体的类型枚举值, 必须 是 VkStructureType::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO 。

  • pNext 要么是 NULL 要么指向其他结构体来扩展该结构体。

  • flags 配置额外的信息。可设置的值定义在 VkDeviceQueueCreateFlagBits 枚举中。

  • queueFamilyIndex 指定目标设备队列族的索引。

  • queueCount 指定要在 queueFamilyIndex 中创建设备队列的数量。

  • pQueuePriorities 指向元素数量为 queueCount 的 float 数组。用于配置创建的每一个设备队列的优先级。

其中 queueFamilyIndex 必须 是目标物理设备中有效的设备队列族索引,并且 queueCount 必须小于等于 queueFamilyIndex 索引对应的设备队列族中的队列数量。

其中 pQueuePriorities 配置的优先级的有效等级范围为[0, 1] ,值越大,优先级越高。其中 0.0 是最低的优先级, 1.0 是最高的优先级。在某些设备中,优先级越高意味着将会得到更多的执行机会,具体的队列调由设备自身管理, Vulkan 并不规定调度规则。

设备扩展

前文创建实例的时候可以设置实例的扩展,在 VkDeviceCreateInfo 我们需要通过 enabledExtensionCount 和 ppEnabledExtensionNames 来指定该逻辑设备要开启的 设备扩展 ( Device Extension )。

在开启设备扩展之前,我们需要通过 vkEnumerateDeviceExtensionProperties(...) 函数获取目标设备支持的扩展。其定义如下:

vkEnumerateDeviceExtensionProperties

// 由 VK_VERSION_1_0 提供
VkResult vkEnumerateDeviceExtensionProperties(
VkPhysicalDevice                            physicalDevice,
const char*                                 pLayerName,
uint32_t*                                   pPropertyCount,
VkExtensionProperties*                      pProperties);

  • physicalDevice 要查询扩展的目标物理设备。

  • pLayerName 要么为 空 要么为 层 的名称。

  • pPropertyCount 要么为 空 要么为 pProperties 中元素的数量。

  • pProperties 为扩展信息数组。元素个数 必须 大于等于 pPropertyCount 中指定数量。

枚举设备扩展:

VkPhysicalDevice physicalDevice;//之前获取的物理设备;

uint32_t extension_property_count = 0;
vkEnumerateDeviceExtensionProperties(physicalDevice, &extension_property_count, nullptr);

std::vector<VkExtensionProperties> extension_properties(extension_property_count);
vkEnumerateDeviceExtensionProperties(physicalDevice, &extension_property_count, extension_properties.data());

有 几个常用的设备扩展:

  • VK_KHR_swapchain 交换链。用于与VK_KHR_surface 和平台相关的 VK_{vender}_{platform}_surface 扩展配合使用。用于窗口化显示渲染结果。

  • VK_KHR_display 某些平台支持直接全屏显示渲染结果(比如嵌入式平台:车载、移动平台等)。

  • VK_KHR_display_swapchain 全屏显示交换链。与 VK_KHR_display 扩展配合使用。

获取设备队列

在创建完逻辑设备后,就可以通过 vkGetDeviceQueue() 函数获取设备队列。其定义如下:

void vkGetDeviceQueue(
VkDevice                                    device,
uint32_t                                    queueFamilyIndex,
uint32_t                                    queueIndex,
VkQueue*                                    pQueue);

  • device 目标逻辑设备。

  • queueFamilyIndex 是前面获取的目标设备队列的队列族索引。

  • queueIndex 对应 VkDeviceQueueCreateInfo::queueCount 的对应设备队列索引, 用于区分创建的多个队列。

  • pQueue 对应 VkDeviceQueueCreateInfo::queueCount 创建的第 queueIndex 的设备队列。

创建逻辑设备示例

//获取目标队列族索引
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, queueFamilies.data());

// 找到支持图形操作的队列族
int graphicsQueueFamilyIndex = -1;
for (uint32_t i = 0; i < queueFamilyCount; i++) {
    if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
        graphicsQueueFamilyIndex = i;
        break;
    }
}

//定义队列创建信息
float queuePriority = 1.0f;
VkDeviceQueueCreateInfo queueCreateInfo = {};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = graphicsQueueFamilyIndex;
queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &queuePriority;

//定义逻辑设备创建信息

//设备扩展
std::vector<const char*> device_extensions;
device_extensions.push_back("VK_KHR_swapchain");

VkDeviceCreateInfo deviceCreateInfo = {};
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
deviceCreateInfo.queueCreateInfoCount = 1;
deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
deviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(device_extensions.size());
deviceCreateInfo.ppEnabledExtensionNames = device_extensions.data();

// 你可以在这里指定设备特性和扩展
VkPhysicalDeviceFeatures deviceFeatures = {};
deviceCreateInfo.pEnabledFeatures = &deviceFeatures;

//调用 vkCreateDevice 函数创建逻辑设备,并获取设备句柄。
VkDevice device;
if (vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device) != VK_SUCCESS) {
    throw std::runtime_error("failed to create logical device!");
}

// 获取图形队列句柄
VkQueue graphicsQueue;
vkGetDeviceQueue(device, graphicsQueueFamilyIndex, 0, &graphicsQueue);

//Vulkan 编程...

//销毁逻辑设备
vkDestroyDevice(device, nullptr);

技术交流

进技术交流群/获取源码,添加我的微信:Byte-Flow

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/903868.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Hue3.9.0-cdh5.14.0安装

hue的安装需要准备如下的前置条件 1、Java-jdk8 2、python2.6 3、安装时非root用户 4、另行安装maven和ant&#xff0c;并配置HOME 5、hue安装节点需要hadoop、hive的配置文件 6、准备一个mysql库来做hue的元数据库 第一步&#xff1a;前置准备中的Javajdk和python准备本简单就…

自动驾驶-传感器简述

自动驾驶车辆上的传感器类型包含激光雷达、毫米波雷达、相机、imu、rtk、超声波雷达等&#xff0c;这些传感器用来接收外部世界多姿多彩的信号&#xff0c;根据接收到的信号&#xff0c;车载大脑对信号进行处理&#xff0c;那信号的准确程度就尤为重要。 本文将各个传感器的特性…

OpenCV图像处理方法:腐蚀操作

腐蚀操作 前提 图像数据为二值的&#xff08;黑/白&#xff09; 作用 去掉图片中字上的毛刺 显示图片 读取一个图像文件&#xff0c;并在一个窗口中显示它。用户可以查看这个图像&#xff0c;直到按下任意键&#xff0c;然后程序会关闭显示图像的窗口 # cv2是OpenCV库的P…

HarmonyOS开发 - 本地持久化之实现LocalStorage支持多实例

用户首选项为应用提供Key-Value键值型的数据处理能力&#xff0c;支持应用持久化轻量级数据&#xff0c;并对其修改和查询。数据存储形式为键值对&#xff0c;键的类型为字符串型&#xff0c;值的存储数据类型包括数字型、字符型、布尔型以及这3种类型的数组类型。 在上一篇中&…

深度学习Pytorch-Tensor的属性、算术运算

深度学习Pytorch-Tensor的属性、算术运算 Tensor的属性Tensor的算术运算Pytorch中的in-place操作Pytorch中的广播机制Tensor的取整/取余运算Tensor的比较运算Tensor的取前k个大/前k小/第k小的数值及其索引Tensor判定是否为finite/inf/nan Tensor的属性 每一个Tensor对象都有以…

记录一个容器间访问不通问题

docker-compose装了zookeeper和一个服务。 zk服务如下&#xff1a; szxc-zk:image: "image.sd001.cn:30003/base/zookeeper:3.8"privileged: trueenvironment:- "TZAsia/Shanghai"#- "ALLOW_ANONYMOUS_LOGINyes"- "ZOO_MY_ID1"- &qu…

vue+spreadjs开发

创建vue3项目 pnpm create vite --registryhttp://registry.npm.taobao.org安装spreadjs包 pnpm install "grapecity-software/spread-sheets17.1.7" "grapecity-software/spread-sheets-resources-zh17.1.7" "grapecity-software/spread-sheets-vu…

使用pytest单元测试框架执行单元测试

Pytest 是一个功能强大且灵活的 Python 单元测试框架&#xff0c;它使编写、组织和运行测试变得更加简单。以下是 Pytest 的一些主要特点和优点&#xff1a; 简单易用&#xff1a;Pytest 提供了简洁而直观的语法&#xff0c;使编写测试用例变得非常容易。它支持使用 assert 语…

WPF+MVVM案例实战(十)- 水波纹按钮实现与控件封装

文章目录 1、运行效果1、封装用户控件1、创建文件2、依赖属性实现2、使用封装的按钮控件1.主界面引用2.按钮属性设置3 总结1、运行效果 1、封装用户控件 1、创建文件 打开 Wpf_Examples 项目,在 UserControlLib 用户控件库中创建按钮文件 WaterRipplesButton.xaml ,修改 Us…

使用DeepLabV3实现植叶病害检测

实战 | 使用DeepLabV3实现植叶病害检测 数据集 数据集下载地址 训练后的数据集地址 如果打不开可以去我的资源下载 演示 原文章 原文章及原代码基础代码 我对源代码进行适配也可以找我要我改过的代码进行学习 我的代码

全国产 V7 690T+FT6678 高性能实时信号处理平台设计原理

1、概述 全国产 V7 690TFT6678 高性能实时信号处理平台组成如图 1 所示&#xff0c;包含 1 片SMQ7VX690TFFG1761 和两片 FT-6678&#xff08;国防科大&#xff09;的 DSP&#xff0c;总共 3 个主芯片&#xff1b;每个主芯片外部各搭配 1 组 64bit 的 DDR3 内存模组以及各芯片启…

安装双系统后ubuntu无法联网(没有wifi标识)网卡驱动为RTL8852BE

安装双系统后ubuntu没有办法联网&#xff0c;&#xff08;本篇博客适用的版本为ubuntu20.04&#xff09;且针对情况为无线网卡驱动未安装的情况 此时没有网络&#xff0c;可以使用手机数据线连接&#xff0c;使用USB共享网络便可解决无法下载的问题。 打开终端使用命令lshw -C …

cesium 加载本地json、GeoJson数据

GeoJSON是一种用于编码地理数据结构的格式 {"type": "Feature","geometry": {"type": "Point","coordinates": [125.6, 10.1]},"properties": {"name": "某地点"} } 一、直接加载…

数据库基础介绍

前言&#xff1a; 在当今信息化、数字化的时代&#xff0c;数据库是支撑一切信息系统的核心基础设施。无论是金融机构的账户管理、电商平台的商品库存&#xff0c;还是社交媒体的用户信息&#xff0c;数据库都在背后扮演着关键角色数据库不仅用于存储和管理数据&#xff0c;更…

《链表篇》---环形链表II(返回节点)

题目传送门 方法一&#xff1a;哈希表&#xff08;与环形链表类似&#xff09; 很容易就可以找到链表的相交位置。 public class Solution {public ListNode detectCycle(ListNode head) {if(head null || head.next null){return null;}Set<ListNode> visited new Ha…

使用Kubernetes管理容器化应用

使用Kubernetes管理容器化应用 Kubernetes简介 安装Kubernetes 安装Minikube 启动Minikube集群 创建一个简单的Web应用 创建项目目录 初始化项目 安装Node.js依赖 创建Docker镜像 编写Dockerfile 构建并推送Docker镜像 创建Kubernetes配置文件 创建Deployment 创建Service …

Java知识巩固(十二)

I/O JavaIO流了解吗&#xff1f; IO 即 Input/Output&#xff0c;输入和输出。数据输入到计算机内存的过程即输入&#xff0c;反之输出到外部存储&#xff08;比如数据库&#xff0c;文件&#xff0c;远程主机&#xff09;的过程即输出。数据传输过程类似于水流&#xff0c;因…

Android中的epoll机制

深入理解Android中的epoll机制 在Android系统中&#xff0c;epoll广泛用于高效管理网络和文件的I/O操作。它通过减少CPU资源消耗和避免频繁的内核态-用户态切换&#xff0c;实现了在多连接、多任务环境中的高性能。epoll的特性使其非常适合Android系统中网络服务器、Socket通信…

Hash表算法

哈希表 理论知识&#xff08;本文来自于代码随想录摘抄&#xff09;什么是哈希常见的三种哈希结数组&#xff1a;set:map:其他常用方法或者技巧&#xff08;自己总结的&#xff09; 练习题和讲解有效的字母移位词349. 两个数组的交集1. 两数之和454. 四数相加 II15. 三数之和 总…

Java SPI 机制详解

面向对象设计鼓励模块间基于接口而非具体实现编程&#xff0c;以降低模块间的耦合&#xff0c;遵循依赖倒置原则&#xff0c;并支持开闭原则&#xff08;对扩展开放&#xff0c;对修改封闭&#xff09;。然而&#xff0c;直接依赖具体实现会导致在替换实现时需要修改代码&#…