diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f3fe20..8a14a24 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ set(infoware_version "0.6.0") project(infoware VERSION "${infoware_version}" LANGUAGES CXX) +option(INFOWARE_USE_VULKAN "Add public, transitive define to infoware to use Vulkan for GPU detection." OFF) option(INFOWARE_USE_D3D "Add public, transitive define to infoware to use Direct 3D for GPU detection." OFF) option(INFOWARE_USE_OPENGL "Add public, transitive define to infoware to use Open Graphics Language (OpenGL) for GPU detection." OFF) option(INFOWARE_USE_OPENCL "Add public, transitive define to infoware to use Open Compute Language (OpenCL) for GPU detection." OFF) @@ -22,6 +23,16 @@ option(INFOWARE_TESTS "Input tests for infoware." OFF) set(INFOWARE_PCI_IDS_PATH "" CACHE FILEPATH "pci.ids file to use. Overrides cloning from INFOWARE_PCI_IDS_REPOSITORY.") set(INFOWARE_PCI_IDS_REPOSITORY "https://github.com/pciutils/pciids" CACHE STRING "Path/URL to clone a pciids git repository from if override path not supplied. Defaults to https://github.com/pciutils/pciids.") +if(INFOWARE_USE_VULKAN) + if(INFOWARE_USE_D3D) + message(WARNING "INFOWARE_USE_D3D specified, but the higher-priority INFOWARE_USE_VULKAN was specified, too, and will be used instead.") + elseif(INFOWARE_USE_OPENCL) + message(WARNING "INFOWARE_USE_OPENCL specified, but the higher-priority INFOWARE_USE_VULKAN was specified, too, and will be used instead.") + elseif(INFOWARE_USE_OPENGL) + message(WARNING "INFOWARE_USE_OPENGL specified, but the higher-priority INFOWARE_USE_VULKAN was specified, too, and will be used instead.") + endif() +endif() + if(INFOWARE_USE_D3D) if(NOT WIN32) message(FATAL_ERROR "INFOWARE_USE_D3D only available on Win32.") @@ -167,7 +178,11 @@ if(APPLE) endif() -if(INFOWARE_USE_D3D) +if(INFOWARE_USE_VULKAN) + target_compile_definitions(infoware PUBLIC INFOWARE_USE_VULKAN) + find_package(Vulkan REQUIRED) + target_link_libraries(infoware PUBLIC Vulkan::Vulkan) +elseif(INFOWARE_USE_D3D) target_compile_definitions(infoware PUBLIC INFOWARE_USE_D3D) if (WIN32) target_link_libraries(infoware PUBLIC dxgi) diff --git a/README.md b/README.md index 964c877..27fd847 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ A usable `git` binary is required by default, to clone https://github.com/pciuti |CMake definition and C++ preprocessor macro| Meaning |Linker library| Priority | |-------------------------------------------|-----------------------------------|--------------|---------------| | `INFOWARE_USE_X11` | Use X11 for display detection | `X11` | D3D | | `INFOWARE_USE_D3D` | Use D3D for GPU detection | `dxgi` | >OpenCL | | `INFOWARE_USE_OPENCL` | Use OpenCL for GPU detection | `OpenCL` | Darwin | | `INFOWARE_USE_OPENGL` | Use OpenGL for GPU detection |OS-dependent\*| iware::gpu::device_properties() { #endif #endif +#endif diff --git a/src/gpu/OpenGL_non_windows_non_darwin.cpp b/src/gpu/OpenGL_non_windows_non_darwin.cpp index a805c2d..6dd6036 100644 --- a/src/gpu/OpenGL_non_windows_non_darwin.cpp +++ b/src/gpu/OpenGL_non_windows_non_darwin.cpp @@ -2,6 +2,7 @@ // infoware - C++ System information Library +#ifndef INFOWARE_USE_VULKAN #ifndef INFOWARE_USE_D3D #ifndef INFOWARE_USE_OPENCL #ifndef _WIN32 @@ -100,3 +101,4 @@ std::vector iware::gpu::device_properties() { #endif #endif #endif +#endif diff --git a/src/gpu/OpenGL_windows.cpp b/src/gpu/OpenGL_windows.cpp index 3bf3912..957f96b 100644 --- a/src/gpu/OpenGL_windows.cpp +++ b/src/gpu/OpenGL_windows.cpp @@ -2,6 +2,7 @@ // infoware - C++ System information Library +#ifndef INFOWARE_USE_VULKAN #ifndef INFOWARE_USE_D3D #ifndef INFOWARE_USE_OPENCL #ifdef _WIN32 @@ -20,3 +21,4 @@ std::vector iware::gpu::device_properties() { #endif #endif #endif +#endif diff --git a/src/gpu/blank_all.cpp b/src/gpu/blank_all.cpp index afc555a..71ad73a 100644 --- a/src/gpu/blank_all.cpp +++ b/src/gpu/blank_all.cpp @@ -5,6 +5,7 @@ #ifndef INFOWARE_USE_OPENGL #ifndef INFOWARE_USE_OPENCL #ifndef INFOWARE_USE_D3D +#ifndef INFOWARE_USE_VULKAN #ifndef __APPLE__ @@ -20,3 +21,4 @@ std::vector iware::gpu::device_properties() { #endif #endif #endif +#endif diff --git a/src/gpu/d3d.cpp b/src/gpu/d3d.cpp index 11326ca..8ffbb5b 100644 --- a/src/gpu/d3d.cpp +++ b/src/gpu/d3d.cpp @@ -2,6 +2,7 @@ // infoware - C++ System information Library +#ifndef INFOWARE_USE_VULKAN #ifdef INFOWARE_USE_D3D @@ -59,3 +60,4 @@ std::vector iware::gpu::device_properties() { #endif +#endif diff --git a/src/gpu/vulkan.cpp b/src/gpu/vulkan.cpp new file mode 100644 index 0000000..b1b0136 --- /dev/null +++ b/src/gpu/vulkan.cpp @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: CC0-1.0 +// infoware - C++ System information Library + + +#ifdef INFOWARE_USE_VULKAN + + +#include "infoware/detail/scope.hpp" +#include "infoware/gpu.hpp" +#include +#include +#include + + +std::vector iware::gpu::device_properties() { + VkApplicationInfo appInfo{}; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pApplicationName = "Hello Triangle"; + appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.pEngineName = "No Engine"; + appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.apiVersion = VK_API_VERSION_1_0; + + VkInstanceCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + createInfo.pApplicationInfo = &appInfo; + + VkInstance instance; + VkResult result = vkCreateInstance(&createInfo, nullptr, &instance); + if(result != VK_SUCCESS) + throw nullptr; + iware::detail::quickscope_wrapper instance_deleter{[&]() { vkDestroyInstance(instance, nullptr); }}; + + + uint32_t devices_len = 2; + std::vector devices(devices_len); + while((result = vkEnumeratePhysicalDevices(instance, &devices_len, devices.data())) == VK_INCOMPLETE) { + devices.emplace_back(); + devices_len = devices.size(); + } + if(result != VK_SUCCESS) + return {}; + devices.resize(devices_len); + + std::vector ret; + for(auto&& device : devices) { + VkPhysicalDeviceProperties props{}; + vkGetPhysicalDeviceProperties(device, &props); + + // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceProperties.html + // > If the vendor has a PCI vendor ID, the low 16 bits of vendorID must contain that PCI vendor ID, and the remaining bits must be set to zero. + // > Otherwise, the value returned must be a valid Khronos vendor ID, + // None of the s match anything in our enum. + auto vendor = vendor_t::unknown; + switch(props.vendorID) { + case 0x8086: // Intel Corporation + vendor = vendor_t::intel; + break; + case 0x1002: // Advanced Micro Devices, Inc. [AMD/ATI] + case 0x1022: // Advanced Micro Devices, Inc. [AMD] + vendor = vendor_t::amd; + break; + case 0x10de: // NVIDIA Corporation + case 0x12d2: // NVidia / SGS Thomson (Joint Venture) + vendor = vendor_t::nvidia; + break; + case 0x1414: // Microsoft Corporation + vendor = vendor_t::microsoft; + break; + case 0x168c: // Qualcomm Atheros + case 0x17cb: // Qualcomm + case 0x1969: // Qualcomm Atheros + case 0x5143: // Qualcomm Inc + vendor = vendor_t::qualcomm; + break; + case 0x106b: // Apple Inc. + vendor = vendor_t::apple; + break; + } + + VkPhysicalDeviceMemoryProperties mem{}; + vkGetPhysicalDeviceMemoryProperties(device, &mem); + + ret.emplace_back(device_properties_t{ + vendor, + props.deviceName, + std::accumulate(mem.memoryHeaps, mem.memoryHeaps + mem.memoryHeapCount, static_cast(0), [](auto i, auto&& heap) { return i + heap.size; }), + 0, + 0, + }); + } + return ret; +} + + +#endif