返回> 网站首页
vulkan功能支持检测 - 编译安卓应用程序
yoours2025-09-11 18:27:10
简介一边听听音乐,一边写写文章。
一、vulkan功能支持检测
//#define VK_NO_PROTOTYPES
#include <vulkan/vulkan.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <android/log.h>
// Android日志标签
#define LOG_TAG "VulkanInfo"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
// 打印Vulkan版本信息
void print_vulkan_version() {
uint32_t api_version = VK_API_VERSION_1_0;
VkResult result = vkEnumerateInstanceVersion(&api_version);
if (result != VK_SUCCESS) {
LOGI("获取Vulkan版本失败: %d", result);
api_version = VK_API_VERSION_1_0;
}
LOGI("Vulkan API版本: %d.%d.%d",
VK_API_VERSION_MAJOR(api_version),
VK_API_VERSION_MINOR(api_version),
VK_API_VERSION_PATCH(api_version));
}
// 检查扩展是否可用
int check_extension_available(const char* extension_name, VkPhysicalDevice device) {
uint32_t extension_count = 0;
VkResult result = vkEnumerateDeviceExtensionProperties(device, NULL, &extension_count, NULL);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return 0;
}
if (extension_count == 0) {
return 0;
}
VkExtensionProperties* extensions = malloc(sizeof(VkExtensionProperties) * extension_count);
result = vkEnumerateDeviceExtensionProperties(device, NULL, &extension_count, extensions);
if (result != VK_SUCCESS) {
free(extensions);
return 0;
}
int found = 0;
for (uint32_t i = 0; i < extension_count; i++) {
if (strcmp(extensions[i].extensionName, extension_name) == 0) {
found = 1;
break;
}
}
free(extensions);
return found;
}
// 安全地打印数据类型支持信息
void print_datatype_support(VkPhysicalDevice device) {
VkPhysicalDeviceFeatures features;
vkGetPhysicalDeviceFeatures(device, &features);
LOGI(" 基本数据类型支持:");
LOGI(" float32: 支持"); // float32 总是支持
LOGI(" float64: %s", features.shaderFloat64 ? "支持" : "不支持");
LOGI(" int32: 支持"); // int32 总是支持
LOGI(" int64: %s", features.shaderInt64 ? "支持" : "不支持");
// 检查是否支持VK_KHR_get_physical_device_properties2扩展
int has_properties2 = check_extension_available(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, device);
if (has_properties2) {
LOGI(" 扩展数据类型支持 (使用VK_KHR_get_physical_device_properties2):");
// 使用VK_KHR_get_physical_device_properties2扩展安全地获取特性
VkPhysicalDeviceFeatures2 features2 = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2
};
// 检查是否支持VK_KHR_shader_float16_int8扩展
if (check_extension_available(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, device)) {
VkPhysicalDeviceShaderFloat16Int8FeaturesKHR float16_int8_features = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR
};
features2.pNext = &float16_int8_features;
vkGetPhysicalDeviceFeatures2(device, &features2);
LOGI(" float16: %s", float16_int8_features.shaderFloat16 ? "支持" : "不支持");
LOGI(" int8: %s", float16_int8_features.shaderInt8 ? "支持" : "不支持");
} else {
LOGI(" float16: 扩展不可用");
LOGI(" int8: 扩展不可用");
}
} else {
LOGI(" 扩展数据类型支持: VK_KHR_get_physical_device_properties2 不可用");
LOGI(" float16: 需要扩展支持");
LOGI(" int8: 需要扩展支持");
}
}
// 打印物理设备信息
void print_physical_devices(VkInstance instance) {
uint32_t device_count = 0;
VkResult result = vkEnumeratePhysicalDevices(instance, &device_count, NULL);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
LOGE("枚举物理设备失败: %d", result);
return;
}
if (device_count == 0) {
LOGI("未找到支持Vulkan的物理设备");
return;
}
VkPhysicalDevice* devices = malloc(sizeof(VkPhysicalDevice) * device_count);
result = vkEnumeratePhysicalDevices(instance, &device_count, devices);
if (result != VK_SUCCESS) {
LOGE("获取物理设备失败: %d", result);
free(devices);
return;
}
LOGI("找到 %d 个Vulkan物理设备:", device_count);
for (uint32_t i = 0; i < device_count; i++) {
VkPhysicalDeviceProperties props;
vkGetPhysicalDeviceProperties(devices[i], &props);
LOGI("设备 %d: %s", i, props.deviceName);
LOGI(" 类型: ");
switch (props.deviceType) {
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: LOGI("集成GPU"); break;
case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: LOGI("独立GPU"); break;
case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: LOGI("虚拟GPU"); break;
case VK_PHYSICAL_DEVICE_TYPE_CPU: LOGI("CPU"); break;
default: LOGI("其他"); break;
}
LOGI(" API版本: %d.%d.%d",
VK_API_VERSION_MAJOR(props.apiVersion),
VK_API_VERSION_MINOR(props.apiVersion),
VK_API_VERSION_PATCH(props.apiVersion));
LOGI(" 驱动程序版本: %d", props.driverVersion);
LOGI(" 供应商ID: 0x%04X", props.vendorID);
LOGI(" 设备ID: 0x%04X", props.deviceID);
// 打印设备特性
VkPhysicalDeviceFeatures features;
vkGetPhysicalDeviceFeatures(devices[i], &features);
LOGI(" 设备特性:");
LOGI(" 几何着色器: %s", features.geometryShader ? "支持" : "不支持");
LOGI(" 曲面细分着色器: %s", features.tessellationShader ? "支持" : "不支持");
LOGI(" 多视口: %s", features.multiViewport ? "支持" : "不支持");
LOGI(" 采样率遮罩: %s", features.sampleRateShading ? "支持" : "不支持");
// 打印数据类型支持
print_datatype_support(devices[i]);
// 打印队列家族属性
uint32_t queue_family_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties(devices[i], &queue_family_count, NULL);
VkQueueFamilyProperties* queue_families = malloc(sizeof(VkQueueFamilyProperties) * queue_family_count);
vkGetPhysicalDeviceQueueFamilyProperties(devices[i], &queue_family_count, queue_families);
LOGI(" 队列家族 (%d):", queue_family_count);
for (uint32_t j = 0; j < queue_family_count; j++) {
char queue_info[256];
snprintf(queue_info, sizeof(queue_info), "家族 %d: %d 个队列", j, queue_families[j].queueCount);
if (queue_families[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) strcat(queue_info, " [图形]");
if (queue_families[j].queueFlags & VK_QUEUE_COMPUTE_BIT) strcat(queue_info, " [计算]");
if (queue_families[j].queueFlags & VK_QUEUE_TRANSFER_BIT) strcat(queue_info, " [传输]");
if (queue_families[j].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) strcat(queue_info, " [稀疏绑定]");
LOGI(" %s", queue_info);
}
free(queue_families);
}
free(devices);
}
int main() {
LOGI("=== Vulkan 支持检测程序 (Android) ===");
// 打印Vulkan版本
print_vulkan_version();
// 创建Vulkan实例
VkApplicationInfo app_info = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pApplicationName = "VulkanInfo",
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
.pEngineName = "No Engine",
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
.apiVersion = VK_API_VERSION_1_0
};
VkInstanceCreateInfo instance_info = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pApplicationInfo = &app_info
};
VkInstance instance;
VkResult result = vkCreateInstance(&instance_info, NULL, &instance);
if (result != VK_SUCCESS) {
LOGE("创建Vulkan实例失败: %d", result);
return 1;
}
// 打印物理设备信息
print_physical_devices(instance);
// 清理
vkDestroyInstance(instance, NULL);
LOGI("=== 检测完成 ===");
return 0;
}
二、编写 CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
project(vulkaninfo)
add_executable(vulkaninfo
vulkan_info.c
)
find_library(VULKAN_LIBRARY vulkan)
if(NOT VULKAN_LIBRARY)
message(WARNING "vulkan library not found - Vulkan support may not be available")
else()
message(STATUS "vulkan library found: " ${VULKAN_LIBRARY})
endif()
# 设置编译选项
target_compile_options(vulkaninfo PRIVATE
-Wimplicit-function-declaration
-Werror
-O2
)
target_link_libraries(vulkaninfo
android
log
${VULKAN_LIBRARY}
dl
)
set_target_properties(vulkaninfo PROPERTIES
C_STANDARD 11
C_STANDARD_REQUIRED ON
)
四、adb连接android失败
adb默认端口为 5037,检查360的360MobileSrv.exe是否启动,它会占用5037端口导致adb无法使用。
可使用命令 netstat -ano | findstr 5037 查看占用进程pid,再根据pid查询是哪个程序。