Vulkan: detect vmem (#416)

This commit is contained in:
李通洲
2023-02-11 12:34:57 +08:00
parent b90d543afc
commit 662ddac050
9 changed files with 119 additions and 88 deletions
+10 -1
View File
@@ -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);
+4 -3
View File
@@ -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)
+2 -1
View File
@@ -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)
+8 -4
View File
@@ -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);
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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);
+9 -9
View File
@@ -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"
+78 -62
View File
@@ -8,6 +8,7 @@
#include "common/io/io.h"
#include "common/parsing.h"
#include "util/stringUtils.h"
#include "util/mallocHelper.h"
#include <stdlib.h>
#include <vulkan/vulkan.h>
@@ -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;
}
+6 -6
View File
@@ -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, ')');
}