Vulkan实战之逻辑设备和队列

2023-05-16

文章目录

      • 介绍
      • 指定要创建的队列
      • 指定使用的设备特性
      • 创建逻辑设备
      • 检索队列句柄
      • 最终代码

介绍

在选择要使用的物理设备之后,我们需要设置一个逻辑设备来与它接口。逻辑设备创建过程类似于实例创建过程,并描述了我们想要使用的特性。在查询了哪些队列族可用之后,我们还需要指定要创建哪些队列。如果您有不同的需求,甚至可以从同一个物理设备创建多个逻辑设备。

首先添加一个新的类成员来存储逻辑设备句柄。

VkDevice device;

接下来,添加一个从initVulkan调用的createLogicalDevice函数。

void initVulkan() {
    createInstance();
    setupDebugMessenger();
    pickPhysicalDevice();
    createLogicalDevice();
}

void createLogicalDevice() {

}

指定要创建的队列

逻辑设备的创建涉及到在结构体中再次指定一堆细节,其中第一个将是VkDeviceQueueCreateInfo。该结构描述了单个队列族所需的队列数量。现在我们只对具有图形功能的队列感兴趣。

QueueFamilyIndices indices = findQueueFamilies(physicalDevice);

VkDeviceQueueCreateInfo queueCreateInfo{};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = indices.graphicsFamily.value();
queueCreateInfo.queueCount = 1;

当前可用的驱动程序只允许您为每个队列族创建少量队列,实际上不需要多个队列。这是因为您可以在多个线程上创建所有命令缓冲区,然后通过一个低开销的调用在主线程上一次性提交它们。

Vulkan允许您使用0.0到1.0之间的浮点数为队列分配优先级,以影响命令缓冲区执行的调度。即使只有一个队列,这也是必需的:

float queuePriority = 1.0f;
queueCreateInfo.pQueuePriorities = &queuePriority;

指定使用的设备特性

下一个要指定的信息是我们将使用的设备特性集。这些是我们在前一章中查询过的vkGetPhysicalDeviceFeatures支持的特性,比如几何着色器。现在我们不需要任何特殊的东西,所以我们可以简单地定义它,并将所有内容留给VK_FALSE。当我们开始对Vulkan做更有趣的事情时,我们会回到这个结构。

VkPhysicalDeviceFeatures deviceFeatures{};

创建逻辑设备

有了前面的两个结构,我们可以开始填充主VkDeviceCreateInfo结构。

VkDeviceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;

首先为队列创建info和设备特性结构体添加指针:

createInfo.pQueueCreateInfos = &queueCreateInfo;
createInfo.queueCreateInfoCount = 1;

createInfo.pEnabledFeatures = &deviceFeatures;

其余的信息与VkInstanceCreateInfo结构类似,需要您指定扩展和验证层。不同的是,这一次这些是特定于设备的。

设备特定扩展的一个例子是VK_KHR_swapchain,它允许您从该设备向窗口呈现渲染的图像。系统中可能存在缺乏这种能力的Vulkan设备,例如,因为它们只支持计算操作。我们将在交换链章节中回到这个扩展。

Vulkan以前的实现区分了实例和设备特定的验证层,但现在不再是这样了。这意味着VkDeviceCreateInfo的enabledLayerCount和ppEnabledLayerNames字段被最新的实现忽略。然而,设置它们与旧的实现兼容仍然是一个好主意:

createInfo.enabledExtensionCount = 0;

if (enableValidationLayers) {
    createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
    createInfo.ppEnabledLayerNames = validationLayers.data();
} else {
    createInfo.enabledLayerCount = 0;
}

我们现在不需要任何特定于设备的扩展。

就是这样,我们现在准备通过调用适当命名的vkCreateDevice函数来实例化逻辑设备。

if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
    throw std::runtime_error("failed to create logical device!");
}

参数是要与之交互的物理设备、我们刚刚指定的队列和使用信息、可选的分配回调指针和指向存储逻辑设备句柄的变量的指针。与实例创建函数类似,此调用可以基于启用不存在的扩展或指定不受支持的特性的期望用法返回错误。

应该使用vkDestroyDevice函数在清理时销毁该设备:

void cleanup() {
    vkDestroyDevice(device, nullptr);
    ...
}

逻辑设备不直接与实例交互,这就是它不作为参数包含的原因。

检索队列句柄

队列是与逻辑设备一起自动创建的,但是我们还没有一个句柄来与它们交互。首先添加一个类成员来存储图形队列的句柄:

VkQueue graphicsQueue;

当设备被销毁时,设备队列会被隐式清理,所以我们不需要在清理中做任何事情。

我们可以使用vkGetDeviceQueue函数来检索每个队列族的队列句柄。参数包括逻辑设备、队列族、队列索引和指向存储队列句柄的变量的指针。因为我们只从这个家族中创建一个队列,所以我们只使用索引0。

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

有了逻辑设备和队列句柄,我们现在可以实际开始使用显卡做事情了!在接下来的几章中,我们将设置向窗口系统显示结果的资源。

最终代码

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>

#include <iostream>
#include <stdexcept>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <optional>

const uint32_t WIDTH = 800;
const uint32_t HEIGHT = 600;

const std::vector<const char*> validationLayers = {
    "VK_LAYER_KHRONOS_validation"
};

#ifdef NDEBUG
const bool enableValidationLayers = false;
#else
const bool enableValidationLayers = true;
#endif

VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) {
    auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
    if (func != nullptr) {
        return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
    }
    else {
        return VK_ERROR_EXTENSION_NOT_PRESENT;
    }
}

void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) {
    auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
    if (func != nullptr) {
        func(instance, debugMessenger, pAllocator);
    }
}

struct QueueFamilyIndices {
    std::optional<uint32_t> graphicsFamily;

    bool isComplete() {
        return graphicsFamily.has_value();
    }
};

class HelloTriangleApplication {
public:
    void run() {
        initWindow();
        initVulkan();
        mainLoop();
        cleanup();
    }

private:
    GLFWwindow* window;

    VkInstance instance;
    VkDebugUtilsMessengerEXT debugMessenger;

    VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
    VkDevice device;

    VkQueue graphicsQueue;

    void initWindow() {
        glfwInit();

        glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
        glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);

        window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
    }

    void initVulkan() {
        createInstance();
        setupDebugMessenger();
        pickPhysicalDevice();
        createLogicalDevice();
    }

    void mainLoop() {
        while (!glfwWindowShouldClose(window)) {
            glfwPollEvents();
        }
    }

    void cleanup() {
        vkDestroyDevice(device, nullptr);

        if (enableValidationLayers) {
            DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
        }

        vkDestroyInstance(instance, nullptr);

        glfwDestroyWindow(window);

        glfwTerminate();
    }

    void createInstance() {
        if (enableValidationLayers && !checkValidationLayerSupport()) {
            throw std::runtime_error("validation layers requested, but not available!");
        }

        VkApplicationInfo appInfo{};
        appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
        appInfo.pApplicationName = "Hello Triangle";
        appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
        appInfo.pEngineName = "No Engine";
        appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
        appInfo.apiVersion = VK_API_VERSION_1_0;

        VkInstanceCreateInfo createInfo{};
        createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
        createInfo.pApplicationInfo = &appInfo;

        auto extensions = getRequiredExtensions();
        createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
        createInfo.ppEnabledExtensionNames = extensions.data();

        VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{};
        if (enableValidationLayers) {
            createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
            createInfo.ppEnabledLayerNames = validationLayers.data();

            populateDebugMessengerCreateInfo(debugCreateInfo);
            createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*)&debugCreateInfo;
        }
        else {
            createInfo.enabledLayerCount = 0;

            createInfo.pNext = nullptr;
        }

        if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
            throw std::runtime_error("failed to create instance!");
        }
    }

    void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) {
        createInfo = {};
        createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
        createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
        createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
        createInfo.pfnUserCallback = debugCallback;
    }

    void setupDebugMessenger() {
        if (!enableValidationLayers) return;

        VkDebugUtilsMessengerCreateInfoEXT createInfo;
        populateDebugMessengerCreateInfo(createInfo);

        if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) {
            throw std::runtime_error("failed to set up debug messenger!");
        }
    }

    void pickPhysicalDevice() {
        uint32_t deviceCount = 0;
        vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);

        if (deviceCount == 0) {
            throw std::runtime_error("failed to find GPUs with Vulkan support!");
        }

        std::vector<VkPhysicalDevice> devices(deviceCount);
        vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());

        for (const auto& device : devices) {
            if (isDeviceSuitable(device)) {
                physicalDevice = device;
                break;
            }
        }

        if (physicalDevice == VK_NULL_HANDLE) {
            throw std::runtime_error("failed to find a suitable GPU!");
        }
    }

    void createLogicalDevice() {
        QueueFamilyIndices indices = findQueueFamilies(physicalDevice);

        VkDeviceQueueCreateInfo queueCreateInfo{};
        queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
        queueCreateInfo.queueFamilyIndex = indices.graphicsFamily.value();
        queueCreateInfo.queueCount = 1;

        float queuePriority = 1.0f;
        queueCreateInfo.pQueuePriorities = &queuePriority;

        VkPhysicalDeviceFeatures deviceFeatures{};

        VkDeviceCreateInfo createInfo{};
        createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;

        createInfo.pQueueCreateInfos = &queueCreateInfo;
        createInfo.queueCreateInfoCount = 1;

        createInfo.pEnabledFeatures = &deviceFeatures;

        createInfo.enabledExtensionCount = 0;

        if (enableValidationLayers) {
            createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
            createInfo.ppEnabledLayerNames = validationLayers.data();
        }
        else {
            createInfo.enabledLayerCount = 0;
        }

        if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
            throw std::runtime_error("failed to create logical device!");
        }

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

    bool isDeviceSuitable(VkPhysicalDevice device) {
        QueueFamilyIndices indices = findQueueFamilies(device);

        return indices.isComplete();
    }

    QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) {
        QueueFamilyIndices indices;

        uint32_t queueFamilyCount = 0;
        vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);

        std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
        vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());

        int i = 0;
        for (const auto& queueFamily : queueFamilies) {
            if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
                indices.graphicsFamily = i;
            }

            if (indices.isComplete()) {
                break;
            }

            i++;
        }

        return indices;
    }

    std::vector<const char*> getRequiredExtensions() {
        uint32_t glfwExtensionCount = 0;
        const char** glfwExtensions;
        glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);

        std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);

        if (enableValidationLayers) {
            extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
        }

        return extensions;
    }

    bool checkValidationLayerSupport() {
        uint32_t layerCount;
        vkEnumerateInstanceLayerProperties(&layerCount, nullptr);

        std::vector<VkLayerProperties> availableLayers(layerCount);
        vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());

        for (const char* layerName : validationLayers) {
            bool layerFound = false;

            for (const auto& layerProperties : availableLayers) {
                if (strcmp(layerName, layerProperties.layerName) == 0) {
                    layerFound = true;
                    break;
                }
            }

            if (!layerFound) {
                return false;
            }
        }

        return true;
    }

    static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) {
        std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl;

        return VK_FALSE;
    }
};

int main() {
    HelloTriangleApplication app;

    try {
        app.run();
    }
    catch (const std::exception& e) {
        std::cerr << e.what() << std::endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Vulkan实战之逻辑设备和队列 的相关文章

  • python奇im巧技大合集

    1 嵌套函数下层函数修改上层函数变量值 问题 xff1a 在嵌套函数 xff0c 即def fun1 def fun2 类型的函数中 xff0c 如果函数fun2想要修改fun1中的变量 xff0c 就不能用global 来声明变量了 xf
  • linux系统下编译错误大合集

    1 pcl库相关报错 error divscalar is not a member of pcl traits error plus is not a member of pcl traits 后面一定还有一长串报错 xff09 解法 x
  • VSCode使用git-【界面化处理】

    此教程从创建一个git项目开始处理 xff0c 内容比较细致 xff0c 可以摘取需要的部分观看 目录 在gitee上创建一个git项目 VSCode同步远程代码仓库 git的提交操作 中途的小问题 回归正题 git的拉取操作 1 两个人在
  • 【ROS】Ubuntu18.04下安装ROS-Melodic的步骤及rosdep update报错的解决方案

    写在前面 xff1a 笔者从大二就开始接触ROS操作系统 xff0c 期间经历过多次ROS的安装与重装 xff0c 每一次都痛苦不堪 每一次的安装都会重复踩很多坑 xff0c 也会踩一些新坑 xff0c 因此借此机会打算把安装ROS Mel
  • 【C++】for循环中带冒号(:)用法简介

    基本用法 正常我们想要输出一个数组的全部元素时 xff0c 需要采用以下的方法 xff1a span class token comment 随机定义的数组 span span class token keyword int span ar
  • 阿里云物联网平台web端,可视化开发,简单实例

    Web可视化 阿里云物联网平台提供了一种可快速开发的web服务 xff0c 只需要拖入一些控件 xff0c 做一些配置就可以完成一个简单的物联网web应用 xff0c 对单一场景 xff0c 需求简单的项目非常实用 首先进入物联网平台 xf
  • K8s kubectl 报错 c-bash: _get_comp_words_by_ref: command not found解决过程

    K8s kubectl error xff1a c bash get comp words by ref command not found 故障现象 xff1a 新搭了个测试环境 xff0c 准备cka的考试 source lt kube
  • OpenSSH权限提升漏洞(CVE-2021-41617)修复 Centos 7升级Openssh 8.8

    OpenSSH权限提升漏洞 xff08 CVE 2021 41617 xff09 修复 1 准备工作2 安装必须的包3 下载OpenSsh 8 8p14 OpenSsh 解压安装5 配置文件修改6 重启服务7 意外 Centos 7升级Op
  • Jenkins 构建报错:Couldn‘t find any revision to build. Verify the repository and branch configuration for

    Jenkins 构建报错 Couldn 39 t find any revision to build Verify the repository and branch configuration for 1 错误信息 2 错误原因3 解决
  • 利用阿里云下载国外镜像,国内顺畅下载k8s.gcr.io的镜像

    国内顺畅下载k8s gcr io的镜像 1 起因 配置kube dns是3个k8s gcr io的镜像无法下载 报错如下 Error response from daemon Get https k8s gcr io v2 net http
  • PX4之启动脚本

    PX4通过rcS脚本来设定需要启动的程序 xff0c 比如设备驱动 控制模块 数据通讯等 rcS脚本在项目中的文件位置 ROMFS px4fmu common rcS 对应硬件平台固件上的位置 etc init d rcS 启动脚本流程如下
  • pip 使用阿里源

    pip 使用阿里源 使用pip install 的时候默认会去国外服务器下载 所以经常断开或者速度很慢 只需要在原来的命令后加上 i https mirrors aliyun com pypi simple即可直接从阿里源上安装 pip s
  • npm安装vue报错:npm ERR! code ETIMEDOUT

    npm安装vue报错 信息如下 C span class token punctuation span Users span class token punctuation span Q span class token operator
  • 将element-plus分页组件由默认英文,改为中文

    1 现象 分页组件默认显示为英文 但实际页面中大多都是中文 弄个英文显得比较突兀 2 配置 在main js中添加以下两句语句 span class token function import span locale from span c
  • Nginx第三方模块nginx_upstream_check_module实现http检测

    1 故障现象 架构如下 当时servera的容器oom了 开始不停重启 造成80端口是活着的 但没法正常提供http服务 原先的配置如下 upstream aaa span class token punctuation span serv
  • 【云原生 | Kubernetes 系列】---Prometheus监控mysql

    1 Prometheus监控mysql 对mysql的版本要求 MySQL gt 61 5 6 MariaDB gt 61 10 3 1 1 测试环境准备 span class token comment apt install maria
  • [Gitops--2]Argocd和Gitlab-runner安装配置

    ArgoCd Argo是一组k8s原生工具集 用于运行和管理k8s上的作业和应用程序 Argo提供了一种在k8s上创建工作和应用的三种计算模式 服务模式 工作流模式和基于事件模式 所有的Argo工具都实现为了创建控制器和自定义资源 为什么选
  • Windows update 0x8024401c 0x80244019

    Windows 更新失败 报错 0x8024401c 0x80244019 以系统管理员身份运行 net stop wuauserv reg delete f HKEY LOCAL MACHINE span class token punc
  • K8s常见面试题20问

    K8s常见面试题19问 收集了一些K8s常见问题和同学们面试常被问到的问题 如果有新的面试题私聊或者留言给我 1 Docker和虚拟机有那些不同 虚拟化环境下每个 VM 是一台完整的计算机 xff0c 在虚拟化硬件之上运行所有组件 xff0
  • Dockerfile常用命令

    Dockerfile常用命令 1 Dockerfile Dockerfile是一个文本文件 用一组指令来完成镜像的构建 每一条指令构建一层镜像 所有尽量将相同的命令合并成一行以减少中间镜像的层数 2 From 必须 指定基础镜像即我从哪里可

随机推荐

  • Kubesphere流水线实现蓝绿发布

    Kubesphere流水线实现蓝绿发布 1 Gitlab仓库准备 1 1 创建仓库 新建空白项目 名字随便取 greenweb 复制克隆地址 http 192 168 31 199 deploy greenweb git 1 2 初始化并上
  • PX4之代码结构

    PX4开源飞控是目前主流的开源飞控项目 xff0c 被很多公司作为飞控开发的参考 也广泛被用于现在流行的evtol验证机的飞控 xff0c 进行初步的飞行验证 可能大多数AAM以及UAM都离不开PX4 项目代码可以从github下载 git
  • docker更改默认仓库地址

    docker更改默认仓库地址 复制代码 zq 64 ubuntu docker pull h Flag shorthand h has been deprecated please use help Usage docker pull OP
  • 关于Proteus仿真stm32时出现电源与地对接错误的解决方案

    最近开始了stm32的学习 xff0c 但发现在Proteus仿真时总是出现 PROTEUS显示 电路图如下 xff1a 经过一段时间的研究 xff0c 除了之前的要将Design gt Configure Power Rails中的VSS
  • 【ssh】ssh密钥配置无效(如git@github.com: Permission denied (publickey).)

    使用ssh keygen创建密钥后 xff0c 默认会将公司钥保存至 ssh目录下 xff0c 文件名分别为id rsa和id rsa pub xff08 如果你使用的是rsa加密 xff09 这种情况下 xff0c 一般不需要配置其他内容
  • 【Python】NameError: name ‘self‘ is not defined

    NameError name 39 self 39 is not defined 最近开发Python包 xff0c 遇到一个 NameError name self is not defined 问题 在执行 span class tok
  • C/C++关于strcpy、strcat函数使用

    char p1 15 61 34 abcd 34 p2 61 34 ABCD 34 str 50 61 34 xyz 34 strcpy str 43 2 strcat p1 43 2 p2 43 1 printf 34 s 34 str
  • intel RealSense摄像头比较

    1 D415 xff0c D435和D435i xff08 1 xff09 总体对比 xff08 2 xff09 具体对比 相机细节 三个深度相机大小相同 xff08 在毫米内 xff09 xff0c 它们都使用相同的视觉处理器通过USB
  • shell中的#!/bin/bash

    bin bash是指此脚本使用 bin bash来解释执行 其中 xff0c 是一个特殊的表示符 xff0c 其后 xff0c 跟着解释此脚本的shell路径
  • 嵌入式控制器EC是如何运行起来的

    EC的作用在本文中就不谈了 xff0c 百度里面可以找到很多 xff0c 反正像笔记本这样的移动设备 xff0c 都需要EC来做相关的控制 xff0c 具体可以自己去百度 这里主要介绍EC是如何运行起来的 xff0c 其实和CPU是如何运行
  • 如何在C/C++中利用变量来创建变化长度的数组

    在C C 43 43 中可以直接使用 xff1a int a n 创建长度为n的整型数组 xff0c 这种定义数组的方法需要事先确定好数组的长度 xff0c 即 n 必须为常量 xff0c 这意味着 xff0c 如果在实际应用中无法确定数组
  • Host是如何与EC通信的(BIOS通过ACPI协议对EC RAM进行读写)

    文章目录 一 EC RAM是什么 二 使用步骤 1 高级配置和电源接口 ACPI 规范 2 EC RAM读写过程 总结 一 EC RAM是什么 EC提供256字节的可被系统读写的RAM空间 EC的资源 包括电池信息 EC版本等信息 在该RA
  • PX4之飞行控制框架

    PX4的飞行控制程序通过模块来实现 xff0c 与飞控相关的模块主要有commander xff0c navigator xff0c pos control xff0c att control这几个 xff0c 分别可以在src modul
  • 使用树莓派学习Linux驱动开发-02 面向对象/分层/分离驱动设计思想编写LED驱动程序

    系列文章目录 此博客内容根据韦东山嵌入式Linux驱动开发课程书写而来 将课程中用到的代码移植到树莓派4B板子 文章目录 系列文章目录 前言 一 驱动设计思想 分离 二 示例代码 三 操作步骤如下 前言 在上一篇内容中 书写了一个设备驱动程
  • 0.嵌入式控制器EC实战 Embedded Controller开发概述

    文章目录 1 嵌入式控制器EC概述2 EC芯片框图 xff08 IT8502为例 xff09 3 General Purpose I O Port GPIO 4 SMBus xff08 System Management Bus xff0c
  • 12.嵌入式控制器EC实战 SMBus概述

    文章目录 SMBus概述 ACPI规范中的函数返回值含义 SMBus h中的宏定义含义 EC中SMBus各个读写函数分析 bRWSMBus读写函数 在嵌入式控制器EC中 SMBus的起到的作用有两个 第一个是通过SMBus读取智能电池中的相
  • Win10下开机自动启动运行bat脚本并打开cmd运行命令

    场景 xff1a 本菜鸟有一台工作站安装了windows10操作系统 xff0c 机器设置的是开机自动启动 xff0c 但是维护人员无法一直在机房 xff0c 一旦机房断电重启就会导致工作站中运行的程序无法重新启动 xff0c 需要维护人员
  • 银河麒麟V10系统 syslog和kern.log文件过大问题解决,定时清理日志文件

    文章目录 1 新建clear log sh脚本文件 2 设置cron任务 3 解决不执行的方法 需求 在使用银河麒麟V10系统时 var log kern log 和 var log syslog两个文件随着使用的时间增长会一直增大 最后可
  • 2.龙芯2k1000 linux3.10内核编译过程

    龙芯2k1000 linux3 10内核编译过程 文章目录 龙芯2k1000 linux3 10内核编译过程 xff08 一 xff09 在Ubuntu环境下载并配置交叉编译链 xff08 二 xff09 下载linux3 10内核源码 x
  • Vulkan实战之逻辑设备和队列

    文章目录 介绍指定要创建的队列指定使用的设备特性创建逻辑设备检索队列句柄最终代码 介绍 在选择要使用的物理设备之后 xff0c 我们需要设置一个逻辑设备来与它接口 逻辑设备创建过程类似于实例创建过程 xff0c 并描述了我们想要使用的特性