Test if Vulkan device is supported

This commit is contained in:
Inforithmics 2025-09-25 03:22:01 +02:00
parent 66bdd882f5
commit 3a45922c01
3 changed files with 129 additions and 0 deletions

View File

@ -466,6 +466,15 @@ func GetGPUInfo() GpuInfoList {
continue
}
if C.vk_device_is_supported(*vHandles.vulkan, C.int(i)) == 0 {
unsupportedGPUs = append(unsupportedGPUs,
UnsupportedGPUInfo{
GpuInfo: gpuInfo.GpuInfo,
})
slog.Info(fmt.Sprintf("[%d] Vulkan GPU does not support required Vulkan features. (StorageBuffer16BitAccess)", i))
continue
}
gpuInfo.TotalMemory = uint64(memInfo.total)
gpuInfo.FreeMemory = uint64(memInfo.free)
gpuInfo.ID = C.GoString(&memInfo.gpu_id[0])

View File

@ -48,6 +48,7 @@ void vk_init(char* vk_lib_path, vk_init_resp_t *resp) {
{"vkEnumeratePhysicalDevices", (void *)&resp->ch.vkEnumeratePhysicalDevices},
{"vkGetPhysicalDeviceMemoryProperties2", (void *)&resp->ch.vkGetPhysicalDeviceMemoryProperties2},
{"vkDestroyInstance", (void *)&resp->ch.vkDestroyInstance},
{"vkGetPhysicalDeviceFeatures2", (void *)&resp->ch.vkGetPhysicalDeviceFeatures2},
{NULL, NULL},
};
@ -117,6 +118,38 @@ void vk_init(char* vk_lib_path, vk_init_resp_t *resp) {
resp->num_devices = deviceCount;
}
int vk_device_is_supported(vk_handle_t rh, int i) {
VkInstance instance = rh.vk;
uint32_t deviceCount = rh.num_devices;
VkPhysicalDevice* devices = malloc(deviceCount * sizeof(VkPhysicalDevice));
if (devices == NULL) {
return 0;
}
VkResult result = (*rh.vkEnumeratePhysicalDevices)(instance, &deviceCount, devices);
if (result != VK_SUCCESS) {
free(devices);
return 0;
}
VkPhysicalDeviceVulkan11Features vk11_features = {};
vk11_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
vk11_features.pNext = NULL;
VkPhysicalDeviceFeatures2 device_features2 = {};
device_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
device_features2.pNext = &vk11_features;
// make sure you have the right function pointer from your loader
(*rh.vkGetPhysicalDeviceFeatures2)(devices[i], &device_features2);
int supported = vk11_features.storageBuffer16BitAccess ? 1 : 0;
free(devices);
return supported;
}
int vk_check_flash_attention(vk_handle_t rh, int i) {
VkInstance instance = rh.vk;
uint32_t deviceCount = rh.num_devices;

View File

@ -95,6 +95,8 @@ typedef enum VkResult {
typedef enum VkStructureType {
VK_STRUCTURE_TYPE_APPLICATION_INFO = 0,
VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 1,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES = 49,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 = 1000059000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 = 1000059001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2 = 1000059006,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES = 1000071004,
@ -284,6 +286,87 @@ typedef struct VkPhysicalDeviceIDProperties {
VkBool32 deviceLUIDValid;
} VkPhysicalDeviceIDProperties;
typedef struct VkPhysicalDeviceFeatures {
VkBool32 robustBufferAccess;
VkBool32 fullDrawIndexUint32;
VkBool32 imageCubeArray;
VkBool32 independentBlend;
VkBool32 geometryShader;
VkBool32 tessellationShader;
VkBool32 sampleRateShading;
VkBool32 dualSrcBlend;
VkBool32 logicOp;
VkBool32 multiDrawIndirect;
VkBool32 drawIndirectFirstInstance;
VkBool32 depthClamp;
VkBool32 depthBiasClamp;
VkBool32 fillModeNonSolid;
VkBool32 depthBounds;
VkBool32 wideLines;
VkBool32 largePoints;
VkBool32 alphaToOne;
VkBool32 multiViewport;
VkBool32 samplerAnisotropy;
VkBool32 textureCompressionETC2;
VkBool32 textureCompressionASTC_LDR;
VkBool32 textureCompressionBC;
VkBool32 occlusionQueryPrecise;
VkBool32 pipelineStatisticsQuery;
VkBool32 vertexPipelineStoresAndAtomics;
VkBool32 fragmentStoresAndAtomics;
VkBool32 shaderTessellationAndGeometryPointSize;
VkBool32 shaderImageGatherExtended;
VkBool32 shaderStorageImageExtendedFormats;
VkBool32 shaderStorageImageMultisample;
VkBool32 shaderStorageImageReadWithoutFormat;
VkBool32 shaderStorageImageWriteWithoutFormat;
VkBool32 shaderUniformBufferArrayDynamicIndexing;
VkBool32 shaderSampledImageArrayDynamicIndexing;
VkBool32 shaderStorageBufferArrayDynamicIndexing;
VkBool32 shaderStorageImageArrayDynamicIndexing;
VkBool32 shaderClipDistance;
VkBool32 shaderCullDistance;
VkBool32 shaderFloat64;
VkBool32 shaderInt64;
VkBool32 shaderInt16;
VkBool32 shaderResourceResidency;
VkBool32 shaderResourceMinLod;
VkBool32 sparseBinding;
VkBool32 sparseResidencyBuffer;
VkBool32 sparseResidencyImage2D;
VkBool32 sparseResidencyImage3D;
VkBool32 sparseResidency2Samples;
VkBool32 sparseResidency4Samples;
VkBool32 sparseResidency8Samples;
VkBool32 sparseResidency16Samples;
VkBool32 sparseResidencyAliased;
VkBool32 variableMultisampleRate;
VkBool32 inheritedQueries;
} VkPhysicalDeviceFeatures;
typedef struct VkPhysicalDeviceFeatures2 {
VkStructureType sType;
void* pNext;
VkPhysicalDeviceFeatures features;
} VkPhysicalDeviceFeatures2;
typedef struct VkPhysicalDeviceVulkan11Features {
VkStructureType sType;
void* pNext;
VkBool32 storageBuffer16BitAccess;
VkBool32 uniformAndStorageBuffer16BitAccess;
VkBool32 storagePushConstant16;
VkBool32 storageInputOutput16;
VkBool32 multiview;
VkBool32 multiviewGeometryShader;
VkBool32 multiviewTessellationShader;
VkBool32 variablePointersStorageBuffer;
VkBool32 variablePointers;
VkBool32 protectedMemory;
VkBool32 samplerYcbcrConversion;
VkBool32 shaderDrawParameters;
} VkPhysicalDeviceVulkan11Features;
typedef struct VkMemoryType {
VkMemoryPropertyFlags propertyFlags;
uint32_t heapIndex;
@ -376,6 +459,9 @@ typedef struct {
void (*vkDestroyInstance)(
VkInstance instance,
const VkAllocationCallbacks* pAllocator);
void (*vkGetPhysicalDeviceFeatures2)(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceFeatures2* pFeatures);
} vk_handle_t;
typedef struct vk_init_resp
@ -388,6 +474,7 @@ typedef struct vk_init_resp
void vk_init(char* vk_lib_path, vk_init_resp_t *resp);
void vk_check_vram(vk_handle_t rh, int i, mem_info_t *resp);
int vk_check_flash_attention(vk_handle_t rh, int i);
int vk_device_is_supported(vk_handle_t rh, int i);
void vk_release(vk_handle_t rh);
#endif