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
相关产品推荐
相关产品推荐

