You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vulkan C程序跨平台判断设备供电状态的方法

跨平台检测供电类型并选择Vulkan呈现模式

C标准库没有原生的跨平台电源状态检测接口,但可以通过两种可靠方案实现你的需求:

方案一:使用成熟的跨平台图形/系统库

多数Vulkan应用会依赖跨平台窗口库(如SDL2、GLFW),这些库已封装电源状态检测逻辑,无需手动处理平台差异:

SDL2 实现

SDL提供SDL_GetPowerInfo()函数,支持Windows、Linux、macOS、Android等平台:

#include <SDL2/SDL.h>

int has_battery() {
    SDL_PowerState state;
    int seconds, percent;
    state = SDL_GetPowerInfo(&seconds, &percent);
    
    // 判断设备是否存在电池
    return state != SDL_POWERSTATE_NO_BATTERY;
}

根据检测结果选择呈现模式:

VkPresentModeKHR select_present_mode(const VkPresentModeKHR* available_modes, uint32_t mode_count) {
    int device_has_battery = has_battery();
    
    // 优先选择目标模式,兜底返回必支持的FIFO
    for (uint32_t i = 0; i < mode_count; i++) {
        if (!device_has_battery && available_modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
            return VK_PRESENT_MODE_MAILBOX_KHR;
        } else if (device_has_battery && available_modes[i] == VK_PRESENT_MODE_FIFO_RELAXED_KHR) {
            return VK_PRESENT_MODE_FIFO_RELAXED_KHR;
        }
    }
    return VK_PRESENT_MODE_FIFO_KHR;
}

GLFW 实现

GLFW的glfwGetPowerStatus()函数用法类似:

#include <GLFW/glfw3.h>

int has_battery() {
    int present, percent, seconds;
    glfwGetPowerStatus(&present, &percent, &seconds);
    // present为GLFW_TRUE表示设备存在电池
    return present == GLFW_TRUE;
}

呈现模式选择逻辑与SDL版本一致。

方案二:手动封装平台特定代码(无第三方依赖)

若不想引入额外库,可通过预编译宏分支,针对不同平台实现电源检测:

#include <stdbool.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>

#ifdef _WIN32
#include <windows.h>
#endif

#ifdef __APPLE__
#include <IOKit/ps/IOPowerSources.h>
#include <IOKit/ps/IOPSKeys.h>
#endif

bool has_battery() {
#ifdef _WIN32
    SYSTEM_POWER_STATUS status;
    if (GetSystemPowerStatus(&status)) {
        // BatteryFlag为128表示无电池,或BatteryLifePercent为255且AC供电(台式机特征)
        return !(status.BatteryFlag == 128 || (status.BatteryLifePercent == 255 && status.ACLineStatus == 1));
    }
    return false;
#elif __linux__ || __ANDROID__
    // 读取sysfs下的电源供应目录,查找电池类型设备
    DIR* dir = opendir("/sys/class/power_supply/");
    if (!dir) return false;
    
    struct dirent* entry;
    bool found = false;
    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_DIR && strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
            char path[256];
            snprintf(path, sizeof(path), "/sys/class/power_supply/%s/type", entry->d_name);
            FILE* f = fopen(path, "r");
            if (f) {
                char type[32];
                if (fgets(type, sizeof(type), f) && strstr(type, "Battery")) {
                    found = true;
                }
                fclose(f);
                if (found) break;
            }
        }
    }
    closedir(dir);
    return found;
#elif __APPLE__
    CFTypeRef info = IOPSCopyPowerSourcesInfo();
    CFArrayRef sources = IOPSCopyPowerSourcesList(info);
    bool has_bat = false;
    
    for (CFIndex i = 0; i < CFArrayGetCount(sources); i++) {
        CFDictionaryRef source = IOPSGetPowerSourceDescription(info, CFArrayGetValueAtIndex(sources, i));
        CFStringRef type = CFDictionaryGetValue(source, CFSTR(kIOPSPowerSourceTypeKey));
        if (CFStringCompare(type, CFSTR(kIOPSInternalBatteryType), 0) == kCFCompareEqualTo) {
            has_bat = true;
            break;
        }
    }
    
    CFRelease(sources);
    CFRelease(info);
    return has_bat;
#else
    // 其他平台默认假设无电池,可根据需求调整
    return false;
#endif
}

使用该函数选择呈现模式时,需先查询设备支持的VkPresentModeKHR列表,避免选择不兼容的模式。

关键注意事项

  • 必须先获取设备支持的呈现模式列表,不能直接硬编码选择(部分旧设备可能不支持RELAXED FIFO)。
  • 若需求是“插电用MAILBOX,电池供电用RELAXED FIFO”,可修改检测逻辑,增加当前供电状态的判断(如SDL的SDL_POWERSTATE_ON_AC、GLFW的电源状态返回值)。

内容的提问来源于stack exchange,提问作者Brain_driver_not_found

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 12:31:06