diff --git a/src/common/io/io.h b/src/common/io/io.h index c510c4e14..ca800dbe6 100644 --- a/src/common/io/io.h +++ b/src/common/io/io.h @@ -88,7 +88,16 @@ bool ffPathExists(const char* path, FFPathType pathType); #endif // Not thread safe! -void ffSuppressIO(bool suppress); +bool ffSuppressIO(bool suppress); + +static inline void ffUnsuppressIO(bool* suppressed) +{ + if (!*suppressed) return; + ffSuppressIO(false); + *suppressed = false; +} + +#define FF_SUPPRESS_IO() bool __attribute__((__cleanup__(ffUnsuppressIO), __unused__)) io_suppressed__ = ffSuppressIO(true) void ffListFilesRecursively(const char* path); diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index f343eb120..12afb7bc2 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -163,7 +163,7 @@ void ffGetTerminalResponse(const char* request, const char* format, ...) va_end(args); } -void ffSuppressIO(bool suppress) +bool ffSuppressIO(bool suppress) { static bool init = false; static int origOut = -1; @@ -173,7 +173,7 @@ void ffSuppressIO(bool suppress) if(!init) { if(!suppress) - return; + return true; origOut = dup(STDOUT_FILENO); origErr = dup(STDERR_FILENO); @@ -182,13 +182,14 @@ void ffSuppressIO(bool suppress) } if(nullFile == -1) - return; + return false; fflush(stdout); fflush(stderr); dup2(suppress ? nullFile : origOut, STDOUT_FILENO); dup2(suppress ? nullFile : origErr, STDERR_FILENO); + return true; } void listFilesRecursively(FFstrbuf* folder, uint8_t indentation, const char* folderName) diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c index 3a28f19be..152c7c9a4 100644 --- a/src/common/io/io_windows.c +++ b/src/common/io/io_windows.c @@ -111,9 +111,10 @@ bool ffPathExists(const char* path, FFPathType type) return false; } -void ffSuppressIO(bool suppress) +bool ffSuppressIO(bool suppress) { (void) suppress; //Not implemented. + return false; } void listFilesRecursively(FFstrbuf* folder, uint8_t indentation, const char* folderName) diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index 15b2de74b..13983a8a4 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -21,6 +21,12 @@ typedef enum FFGpuType FF_GPU_TYPE_DISCRETE, } FFGpuType; +typedef struct FFGPUMemory +{ + uint64_t total; + uint64_t used; +} FFGPUMemory; + typedef struct FFGPUResult { uint64_t id; @@ -30,10 +36,8 @@ typedef struct FFGPUResult FFstrbuf driver; double temperature; int coreCount; - uint64_t dedicatedTotal; - uint64_t dedicatedUsed; - uint64_t sharedTotal; - uint64_t sharedUsed; + FFGPUMemory dedicated; + FFGPUMemory shared; } FFGPUResult; const FFlist* ffDetectGPU(const FFinstance* instance); diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index bc571d7e2..fa514732e 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -61,7 +61,7 @@ const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance) FFGPUResult* gpu = ffListAdd(gpus); gpu->id = 0; - gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = FF_GPU_VMEM_SIZE_UNSET; + gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; ffStrbufInit(&gpu->vendor); diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 19f4b455a..d62d0e6cc 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -200,7 +200,7 @@ static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData FFGPUResult* gpu = ffListAdd(results); gpu->id = 0; - gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = FF_GPU_VMEM_SIZE_UNSET; + gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; ffStrbufInit(&gpu->vendor); pciDetectVendorName(gpu, pci, device); diff --git a/src/detection/gpu/gpu_windows.cpp b/src/detection/gpu/gpu_windows.cpp index 587ca96e0..0ff1ad43c 100644 --- a/src/detection/gpu/gpu_windows.cpp +++ b/src/detection/gpu/gpu_windows.cpp @@ -49,7 +49,7 @@ static const char* detectWithRegistry(FFlist* gpus) gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; gpu->id = 0; - gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = FF_GPU_VMEM_SIZE_UNSET; + gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; ffRegReadUint64(hSubKey, L"AdapterLuid", &gpu->id, nullptr); @@ -67,8 +67,8 @@ static const char* detectWithRegistry(FFlist* gpus) if(ffRegReadUint64(hSubKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, nullptr) && ffRegReadUint64(hSubKey, L"SharedSystemMemory", &sharedSystemMemory, nullptr)) { - gpu->dedicatedTotal = dedicatedVideoMemory + dedicatedSystemMemory; - gpu->sharedTotal = sharedSystemMemory; + gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory; + gpu->shared.total = sharedSystemMemory; } uint64_t driverVersion; @@ -102,7 +102,7 @@ static const char* detectWithDxgi(FFlist* gpus) continue; FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); - gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = FF_GPU_VMEM_SIZE_UNSET; + gpu->dedicated.total = gpu->dedicated.total = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; ffStrbufInit(&gpu->vendor); ffStrbufAppendS(&gpu->vendor, ffGetGPUVendorString(desc.VendorId)); @@ -115,8 +115,8 @@ static const char* detectWithDxgi(FFlist* gpus) ffStrbufInit(&gpu->driver); gpu->type = desc.DedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; - gpu->dedicatedTotal = desc.DedicatedVideoMemory + desc.DedicatedSystemMemory; - gpu->sharedTotal = desc.SharedSystemMemory; + gpu->dedicated.total = desc.DedicatedVideoMemory + desc.DedicatedSystemMemory; + gpu->shared.total = desc.SharedSystemMemory; adapter->Release(); @@ -149,13 +149,13 @@ static const char* detectMemoryUsage(FFlist* gpus) FF_LIST_FOR_EACH(FFGPUResult, gpu, *gpus) { if (gpu->id != luid) continue; - record.getUnsigned(L"DedicatedUsage", &gpu->dedicatedUsed); - record.getUnsigned(L"SharedUsage", &gpu->sharedUsed); + record.getUnsigned(L"DedicatedUsage", &gpu->dedicated.used); + record.getUnsigned(L"SharedUsage", &gpu->shared.used); break; } } - return NULL; + return nullptr; } extern "C" diff --git a/src/detection/vulkan.c b/src/detection/vulkan.c index 5d8b3f4f9..9a04e1dbb 100644 --- a/src/detection/vulkan.c +++ b/src/detection/vulkan.c @@ -8,6 +8,7 @@ #include "common/io/io.h" #include "common/parsing.h" #include "util/stringUtils.h" +#include "util/mallocHelper.h" #include #include @@ -42,19 +43,20 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu FF_LIBRARY_LOAD(vulkan, &instance->config.libVulkan, "dlopen libvulkan"FF_LIBRARY_EXTENSION " failed", #ifdef __APPLE__ "libMoltenVK"FF_LIBRARY_EXTENSION, -1 + #elif defined(_WIN32) + "vulkan-1"FF_LIBRARY_EXTENSION, -1 #else - "libvulkan"FF_LIBRARY_EXTENSION, 2, "vulkan-1"FF_LIBRARY_EXTENSION, -1 + "libvulkan"FF_LIBRARY_EXTENSION, 2 #endif ) FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkGetInstanceProcAddr, vkGetInstanceProcAddr@8) FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkCreateInstance, vkCreateInstance@12) FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkDestroyInstance, vkDestroyInstance@8) FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkEnumeratePhysicalDevices, vkEnumeratePhysicalDevices@12) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkGetPhysicalDeviceProperties, vkGetPhysicalDeviceProperties@8) //Some drivers (nvdc) print messages to stdout //and thats the best way i found to disable that - ffSuppressIO(true); + FF_SUPPRESS_IO(); FFVersion instanceVersion = FF_VERSION_INIT; @@ -74,37 +76,29 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu FASTFETCH_PROJECT_VERSION_PATCH ); - //We need to request 1.2 to get physicalDeviceDriverProperties - uint32_t requestedVkVersion = VK_API_VERSION_1_0; - if(instanceVersion.minor >= 2) - requestedVkVersion = VK_API_VERSION_1_2; - - const VkApplicationInfo applicationInfo = { - .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, - .pNext = NULL, - .pApplicationName = FASTFETCH_PROJECT_NAME, - .applicationVersion = projectVersion, - .pEngineName = "vulkanPrintGPUs", - .engineVersion = projectVersion, - .apiVersion = requestedVkVersion - }; - - const VkInstanceCreateInfo instanceCreateInfo = { + VkInstance vkInstance; + if(ffvkCreateInstance(&(VkInstanceCreateInfo) { .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .pNext = NULL, - .pApplicationInfo = &applicationInfo, + .pApplicationInfo = &(VkApplicationInfo) { + .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, + .pNext = NULL, + .pApplicationName = FASTFETCH_PROJECT_NAME, + .applicationVersion = projectVersion, + .pEngineName = "vulkanPrintGPUs", + .engineVersion = projectVersion, + + // We need to request 1.1 to get physicalDeviceDriverProperties + .apiVersion = instanceVersion.minor >= 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0 + }, .enabledLayerCount = 0, .ppEnabledLayerNames = NULL, .enabledExtensionCount = 0, .ppEnabledExtensionNames = NULL, .flags = 0 - }; - - VkInstance vkInstance; - if(ffvkCreateInstance(&instanceCreateInfo, NULL, &vkInstance) != VK_SUCCESS) + }, NULL, &vkInstance) != VK_SUCCESS) { dlclose(vulkan); - ffSuppressIO(false); return "ffvkCreateInstance() failed"; } @@ -114,26 +108,25 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu if(instanceVersion.major == 0 && instanceVersion.minor == 0 && instanceVersion.patch == 0) instanceVersion.major = 1; - uint32_t physicalDeviceCount; - if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, NULL) != VK_SUCCESS) - { - ffvkDestroyInstance(vkInstance, NULL); - dlclose(vulkan); - ffSuppressIO(false); - return "ffvkEnumeratePhysicalDevices() failed"; - } - - VkPhysicalDevice* physicalDevices = malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount); + VkPhysicalDevice physicalDevices[128]; + uint32_t physicalDeviceCount = (uint32_t) (sizeof(physicalDevices) / sizeof(*physicalDevices)); if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, physicalDevices) != VK_SUCCESS) { - free(physicalDevices); ffvkDestroyInstance(vkInstance, NULL); dlclose(vulkan); - ffSuppressIO(false); return "ffvkEnumeratePhysicalDevices() failed"; } - PFN_vkGetPhysicalDeviceProperties2 ffvkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceProperties2"); + PFN_vkGetPhysicalDeviceProperties ffvkGetPhysicalDeviceProperties = NULL; + PFN_vkGetPhysicalDeviceProperties2 ffvkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceProperties2"); // 1.1 + if(!ffvkGetPhysicalDeviceProperties2) + ffvkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceProperties"); + + PFN_vkGetPhysicalDeviceMemoryProperties ffvkGetPhysicalDeviceMemoryProperties = NULL; + PFN_vkGetPhysicalDeviceMemoryProperties2 ffvkGetPhysicalDeviceMemoryProperties2 = + instance->config.allowSlowOperations ? (PFN_vkGetPhysicalDeviceMemoryProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceMemoryProperties2") : NULL; // 1.1 + if(!ffvkGetPhysicalDeviceMemoryProperties2) + ffvkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceMemoryProperties"); FFVersion maxDeviceApiVersion = FF_VERSION_INIT; FFVersion maxDeviceConformanceVersion = FF_VERSION_INIT; @@ -141,18 +134,16 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu for(uint32_t i = 0; i < physicalDeviceCount; i++) { //Get device properties. - //On VK 1.2 and up, we use vkGetPhysicalDeviceProperties2, so we can put VkPhysicalDeviceDriverProperties in the pNext chain. + //On VK 1.1 and up, we use vkGetPhysicalDeviceProperties2, so we can put VkPhysicalDeviceDriverProperties in the pNext chain. //This is required to get the driver name and conformance version. - VkPhysicalDeviceDriverProperties driverProperties; - driverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; - driverProperties.pNext = NULL; - driverProperties.driverName[0] = '\0'; - driverProperties.conformanceVersion = (VkConformanceVersion) {0, 0, 0, 0}; - - VkPhysicalDeviceProperties2 physicalDeviceProperties; - physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - physicalDeviceProperties.pNext = &driverProperties; + VkPhysicalDeviceDriverProperties driverProperties = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES, + }; + VkPhysicalDeviceProperties2 physicalDeviceProperties = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + .pNext = &driverProperties, + }; if(ffvkGetPhysicalDeviceProperties2 != NULL) ffvkGetPhysicalDeviceProperties2(physicalDevices[i], &physicalDeviceProperties); @@ -162,6 +153,7 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu //If the device api version is higher than the current highest device api version, overwrite it //In this case, also use the current device driver name as the shown driver name + FFVersion deviceAPIVersion = FF_VERSION_INIT; applyVulkanVersion(physicalDeviceProperties.properties.apiVersion, &deviceAPIVersion); if(ffVersionCompare(&deviceAPIVersion, &maxDeviceApiVersion) > 0) @@ -171,14 +163,17 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu } //If the device conformance version is higher than the current highest device conformance version, overwrite it + if(ffvkGetPhysicalDeviceProperties2) + { + FFVersion deviceConformanceVersion = { + .major = driverProperties.conformanceVersion.major, + .minor = driverProperties.conformanceVersion.minor, + .patch = driverProperties.conformanceVersion.patch, + }; - FFVersion deviceConformanceVersion = FF_VERSION_INIT; - deviceConformanceVersion.major = driverProperties.conformanceVersion.major; - deviceConformanceVersion.minor = driverProperties.conformanceVersion.minor; - deviceConformanceVersion.patch = driverProperties.conformanceVersion.patch; - - if(ffVersionCompare(&deviceConformanceVersion, &maxDeviceConformanceVersion) > 0) - maxDeviceConformanceVersion = deviceConformanceVersion; + if(ffVersionCompare(&deviceConformanceVersion, &maxDeviceConformanceVersion) > 0) + maxDeviceConformanceVersion = deviceConformanceVersion; + } //Add the device to the list of devices shown by the GPU module @@ -191,18 +186,41 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu ffStrbufInit(&gpu->name); ffStrbufAppendS(&gpu->name, physicalDeviceProperties.properties.deviceName); - if(physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) - gpu->type = FF_GPU_TYPE_INTEGRATED; - else + if(physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) gpu->type = FF_GPU_TYPE_DISCRETE; + else + gpu->type = FF_GPU_TYPE_INTEGRATED; gpu->id = physicalDeviceProperties.properties.deviceID; ffStrbufInitS(&gpu->vendor, ffGetGPUVendorString(physicalDeviceProperties.properties.vendorID)); - ffStrbufInitF(&gpu->driver, "%X", (unsigned) physicalDeviceProperties.properties.driverVersion); + ffStrbufInitS(&gpu->driver, driverProperties.driverInfo); + + VkPhysicalDeviceMemoryBudgetPropertiesEXT budgetProperties = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT, + }; + VkPhysicalDeviceMemoryProperties2 memoryProperties2 = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2, + .pNext = &budgetProperties, + }; + + if(ffvkGetPhysicalDeviceMemoryProperties2) + ffvkGetPhysicalDeviceMemoryProperties2(physicalDevices[i], &memoryProperties2); + else + ffvkGetPhysicalDeviceMemoryProperties(physicalDevices[i], &memoryProperties2.memoryProperties); + + gpu->dedicated.total = gpu->shared.total = 0; + gpu->dedicated.used = gpu->shared.used = ffvkGetPhysicalDeviceMemoryProperties2 ? 0 : FF_GPU_VMEM_SIZE_UNSET; + for(uint32_t index = 0; index < memoryProperties2.memoryProperties.memoryHeapCount; ++index) + { + const VkMemoryHeap* heap = &memoryProperties2.memoryProperties.memoryHeaps[index]; + FFGPUMemory* vmem = gpu->type == FF_GPU_TYPE_DISCRETE && (heap->flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) ? &gpu->dedicated : &gpu->shared; + vmem->total += heap->size; + if(ffvkGetPhysicalDeviceMemoryProperties2) + vmem->used += heap->size - budgetProperties.heapBudget[index]; + } //No way to detect those using vulkan gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; - gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = 0; //VkPhysicalDeviceMemoryProperties? } //If the highest device version is lower than the instance version, use it as our vulkan version @@ -215,10 +233,8 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu //Use the highest device conformace version as our conformance version ffVersionToPretty(&maxDeviceConformanceVersion, &result->conformanceVersion); - free(physicalDevices); ffvkDestroyInstance(vkInstance, NULL); dlclose(vulkan); - ffSuppressIO(false); return NULL; } diff --git a/src/modules/gpu.c b/src/modules/gpu.c index 3ff02c5ff..0033d33be 100644 --- a/src/modules/gpu.c +++ b/src/modules/gpu.c @@ -33,20 +33,20 @@ static void printGPUResult(FFinstance* instance, uint8_t index, const FFGPUResul if(gpu->temperature == gpu->temperature) //FF_GPU_TEMP_UNSET ffStrbufAppendF(&output, " - %.1f°C", gpu->temperature); - if(gpu->dedicatedTotal != FF_GPU_VMEM_SIZE_UNSET) + if(gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET && gpu->dedicated.total != 0) { ffStrbufAppendS(&output, " ("); - if(gpu->dedicatedUsed != FF_GPU_VMEM_SIZE_UNSET) + if(gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) { - ffParseSize(gpu->dedicatedUsed, instance->config.binaryPrefixType, &output); + ffParseSize(gpu->dedicated.used, instance->config.binaryPrefixType, &output); ffStrbufAppendS(&output, " / "); } - ffParseSize(gpu->dedicatedTotal, instance->config.binaryPrefixType, &output); - if(gpu->dedicatedUsed != FF_GPU_VMEM_SIZE_UNSET) + ffParseSize(gpu->dedicated.total, instance->config.binaryPrefixType, &output); + if(gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) { ffStrbufAppendS(&output, ", "); - ffAppendPercentNum(instance, &output, (uint8_t) (gpu->dedicatedUsed * 100 / gpu->dedicatedTotal), 50, 80, false); + ffAppendPercentNum(instance, &output, (uint8_t) (gpu->dedicated.used * 100 / gpu->dedicated.total), 50, 80, false); } ffStrbufAppendC(&output, ')'); }