mirror of
https://github.com/valentderah/totk-pc-recomp.git
synced 2026-11-13 02:41:02 +00:00
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
66 lines
2.8 KiB
C
66 lines
2.8 KiB
C
// Host check of the installer's first step, compiled with the bundled clang at install time: does the CPU run
|
|
// -march=x86-64-v3 code, and does a Vulkan 1.3 device exist. Prints one JSON object on stdout.
|
|
// The Vulkan loader is opened at run time, so a machine without one gets "loader": false instead of a failed start.
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <vulkan/vulkan.h>
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#define open_lib() LoadLibraryA("vulkan-1.dll")
|
|
#define lib_sym(l, n) ((void *)GetProcAddress((l), (n)))
|
|
#else
|
|
#include <dlfcn.h>
|
|
#define open_lib() dlopen("libvulkan.so.1", RTLD_NOW)
|
|
#define lib_sym(l, n) dlsym((l), (n))
|
|
#endif
|
|
|
|
static void json_string(const char *s) {
|
|
putchar('"');
|
|
for (; *s; s++) {
|
|
if (*s == '"' || *s == '\\') printf("\\%c", *s);
|
|
else if ((unsigned char)*s < 0x20) printf("\\u%04x", *s);
|
|
else putchar(*s);
|
|
}
|
|
putchar('"');
|
|
}
|
|
|
|
int main(void) {
|
|
__builtin_cpu_init();
|
|
printf("{\"x86_64_v3\": %s, ", __builtin_cpu_supports("x86-64-v3") ? "true" : "false");
|
|
void *lib = open_lib();
|
|
PFN_vkGetInstanceProcAddr gipa = lib ? (PFN_vkGetInstanceProcAddr)lib_sym(lib, "vkGetInstanceProcAddr") : NULL;
|
|
if (!gipa) {
|
|
printf("\"loader\": false, \"devices\": []}\n");
|
|
return 0;
|
|
}
|
|
printf("\"loader\": true, ");
|
|
PFN_vkCreateInstance create = (PFN_vkCreateInstance)gipa(NULL, "vkCreateInstance");
|
|
VkApplicationInfo app = {.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pApplicationName = "totk-install",
|
|
.apiVersion = VK_API_VERSION_1_3};
|
|
VkInstanceCreateInfo ci = {.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .pApplicationInfo = &app};
|
|
VkInstance inst = VK_NULL_HANDLE;
|
|
VkResult r = create ? create(&ci, NULL, &inst) : VK_ERROR_INITIALIZATION_FAILED;
|
|
if (r != VK_SUCCESS) {
|
|
printf("\"instance\": %d, \"devices\": []}\n", (int)r);
|
|
return 0;
|
|
}
|
|
PFN_vkEnumeratePhysicalDevices enumerate = (PFN_vkEnumeratePhysicalDevices)gipa(inst, "vkEnumeratePhysicalDevices");
|
|
PFN_vkGetPhysicalDeviceProperties props = (PFN_vkGetPhysicalDeviceProperties)gipa(inst, "vkGetPhysicalDeviceProperties");
|
|
PFN_vkDestroyInstance destroy = (PFN_vkDestroyInstance)gipa(inst, "vkDestroyInstance");
|
|
VkPhysicalDevice devs[16];
|
|
uint32_t n = 16;
|
|
if (enumerate(inst, &n, devs) < 0) n = 0;
|
|
printf("\"instance\": 0, \"devices\": [");
|
|
for (uint32_t i = 0; i < n; i++) {
|
|
VkPhysicalDeviceProperties p;
|
|
props(devs[i], &p);
|
|
printf("%s{\"name\": ", i ? ", " : "");
|
|
json_string(p.deviceName);
|
|
printf(", \"api\": [%u, %u, %u], \"type\": %d}", VK_API_VERSION_MAJOR(p.apiVersion),
|
|
VK_API_VERSION_MINOR(p.apiVersion), VK_API_VERSION_PATCH(p.apiVersion), (int)p.deviceType);
|
|
}
|
|
printf("]}\n");
|
|
destroy(inst, NULL);
|
|
return 0;
|
|
}
|