-
Notifications
You must be signed in to change notification settings - Fork 100
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create and delete Vulkan context to gather its capabilities
- Loading branch information
Showing
10 changed files
with
275 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
source /vulkan-sdk/setup-env.sh | ||
COMMAND=$1 | ||
shift | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
#include "VkInfo.h" | ||
#include "VkInit.h" | ||
|
||
#include "System/Log/ILog.h" | ||
#include "fmt/format.h" | ||
|
||
#ifndef HEADLESS | ||
void VkInfo::PrintInfoImpl(const char* funcName) | ||
{ | ||
LOG("[VkInfo::%s]", funcName); | ||
|
||
const auto& vkc = VkCoreObjects::GetInstance(); | ||
|
||
LOG("\tInstance VK API version : %s", vkc.GetVulkanAPI().c_str()); | ||
|
||
LOG("\tFound the following VK devices:"); | ||
for (const auto& pd : vkc.GetPhysDevices()) { | ||
const auto& prop = pd.getProperties(); | ||
LOG("\t\t%s (%s)", &prop.deviceName[0], vk::to_string(prop.deviceType).c_str()); | ||
} | ||
|
||
{ | ||
const auto& prop = vkc.GetBestPhysDevice().getProperties(); | ||
LOG("\tSelected best device: %s", &prop.deviceName[0]); | ||
LOG("\t\tDevice VK API version : %s", vkc.GetVulkanAPI(prop.apiVersion).c_str()); | ||
//prop.limits | ||
} | ||
|
||
const auto& instanceExtensions = vkc.GetInstanceExtensions(); | ||
const auto& phDeviceExtensions = vkc.GetPhysDeviceExtensions(); | ||
|
||
const bool mem2 = | ||
vkc.HasExtension(instanceExtensions, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) && | ||
vkc.HasExtension(phDeviceExtensions, VK_EXT_MEMORY_BUDGET_EXTENSION_NAME); | ||
|
||
std::array<uint32_t, 3> heapMemInfo = {0u, 0u, 0u}; //used, budget, total | ||
if (mem2) { | ||
const auto memoryProperties2 = vkc.GetBestPhysDevice().getMemoryProperties2<vk::PhysicalDeviceMemoryProperties2, vk::PhysicalDeviceMemoryBudgetPropertiesEXT>(); | ||
const auto& memoryProperties = memoryProperties2.get<vk::PhysicalDeviceMemoryProperties2>().memoryProperties; | ||
const auto& memoryBudgetProperties = memoryProperties2.get<vk::PhysicalDeviceMemoryBudgetPropertiesEXT>(); | ||
|
||
for (uint32_t i = 0; i < memoryProperties.memoryHeapCount; ++i) { | ||
if (!(memoryProperties.memoryHeaps[i].flags & vk::MemoryHeapFlagBits::eDeviceLocal)) | ||
continue; | ||
|
||
heapMemInfo[0] += memoryBudgetProperties.heapUsage[i] / 1024 / 1024; | ||
heapMemInfo[1] += memoryBudgetProperties.heapBudget[i] / 1024 / 1024; | ||
heapMemInfo[2] += memoryProperties.memoryHeaps[i].size / 1024 / 1024; | ||
} | ||
} | ||
else { | ||
const auto memoryProperties = vkc.GetBestPhysDevice().getMemoryProperties(); | ||
for (uint32_t i = 0; i < memoryProperties.memoryHeapCount; ++i) { | ||
if (!(memoryProperties.memoryHeaps[i].flags & vk::MemoryHeapFlagBits::eDeviceLocal)) | ||
continue; | ||
|
||
heapMemInfo[2] += memoryProperties.memoryHeaps[i].size / 1024 / 1024; | ||
} | ||
} | ||
|
||
const std::string memStr = fmt::format("{}/{}/{}", | ||
heapMemInfo[0] > 0 ? std::to_string(heapMemInfo[0]) : "-", | ||
heapMemInfo[1] > 0 ? std::to_string(heapMemInfo[1]) : "-", | ||
heapMemInfo[2] | ||
); | ||
|
||
LOG("\t\tVRAM : %s MB (used/budget/total)", memStr.c_str()); | ||
|
||
static constexpr std::array requiredDeviceExtensions { | ||
"VK_KHR_dedicated_allocation", | ||
"VK_KHR_create_renderpass2", | ||
"VK_KHR_draw_indirect_count", | ||
"VK_KHR_imageless_framebuffer", | ||
"VK_KHR_uniform_buffer_standard_layout", | ||
"VK_EXT_descriptor_indexing", | ||
"VK_EXT_shader_viewport_index_layer", | ||
"VK_KHR_dynamic_rendering", | ||
"VK_KHR_synchronization2", | ||
"VK_EXT_extended_dynamic_state", | ||
"VK_EXT_extended_dynamic_state2", | ||
}; | ||
|
||
static constexpr size_t paddingMaxSize = 40; | ||
for (const auto& rde : requiredDeviceExtensions) { | ||
const std::string padding(paddingMaxSize - std::string_view(rde).size(), ' '); | ||
LOG("\t\t%s%s : %i", rde, padding.c_str(), vkc.HasExtension(phDeviceExtensions, rde)); | ||
} | ||
|
||
VkCoreObjects::KillInstance(); | ||
} | ||
#else | ||
void VkInfo::PrintInfoImpl(const char* funcName) {} | ||
#endif | ||
|
||
|
||
|
||
void VkInfo::PrintInfo() | ||
{ | ||
#ifndef HEADLESS | ||
#ifndef HAS_VULKAN | ||
LOG("[VkInfo::%s] Compiled without VULKAN support", __func__); | ||
#else | ||
try { | ||
PrintInfoImpl(__func__); | ||
} catch (const std::exception& e) { | ||
LOG("[VkInfo::%s] Runtime error: \"%s\"", __func__, e.what()); | ||
} | ||
#endif | ||
#endif | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#pragma once | ||
|
||
class VkInfo { | ||
public: | ||
static void PrintInfo(); | ||
private: | ||
static void PrintInfoImpl(const char* funcName); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
#ifdef HAS_VULKAN | ||
|
||
#include <string_view> | ||
|
||
#include "VkInit.h" | ||
#include "fmt/format.h" | ||
|
||
bool VkPhysicalDevicesCompare(const vk::PhysicalDevice& lhs, const vk::PhysicalDevice& rhs) | ||
{ | ||
const auto lhsDiscrete = static_cast<uint8_t>(lhs.getProperties().deviceType == vk::PhysicalDeviceType::eDiscreteGpu); | ||
const auto rhsDiscrete = static_cast<uint8_t>(rhs.getProperties().deviceType == vk::PhysicalDeviceType::eDiscreteGpu); | ||
|
||
if (lhsDiscrete > rhsDiscrete) return true; | ||
if (lhsDiscrete < rhsDiscrete) return false; | ||
|
||
VkDeviceSize lhsMS = VkCoreObjects::GetVRAMSize(lhs); | ||
VkDeviceSize rhsMS = VkCoreObjects::GetVRAMSize(rhs); | ||
|
||
if (lhsMS > rhsMS) return true; | ||
if (lhsMS < rhsMS) return false; | ||
|
||
return false; | ||
}; | ||
|
||
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE | ||
VkCoreObjects::VkCoreObjects() | ||
{ | ||
dl = std::make_unique<vk::DynamicLoader>(); | ||
|
||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl->getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr"); | ||
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr); | ||
|
||
// Determine what API version is available | ||
apiVersion = vk::enumerateInstanceVersion(); | ||
|
||
vk::ApplicationInfo applicationInfo("spring", 1, "spring", 1, apiVersion); | ||
vk::InstanceCreateInfo instanceCreateInfo({}, &applicationInfo); | ||
instance = vk::createInstance(instanceCreateInfo); | ||
VULKAN_HPP_DEFAULT_DISPATCHER.init(instance); | ||
|
||
instExtensionProperties = vk::enumerateInstanceExtensionProperties(); | ||
|
||
physicalDevices = instance.enumeratePhysicalDevices(); | ||
std::sort(physicalDevices.begin(), physicalDevices.end(), VkPhysicalDevicesCompare); | ||
|
||
physicalDevice = physicalDevices.front(); | ||
pdevExtensionProperties = physicalDevice.enumerateDeviceExtensionProperties(); | ||
} | ||
|
||
std::string VkCoreObjects::GetVulkanAPI(uint32_t apiVersion) | ||
{ | ||
return fmt::format("{}.{}.{}", VK_API_VERSION_MAJOR(apiVersion), VK_API_VERSION_MINOR(apiVersion), VK_API_VERSION_PATCH(apiVersion)); | ||
} | ||
|
||
std::string VkCoreObjects::GetVulkanAPI() const | ||
{ | ||
return GetVulkanAPI(apiVersion); | ||
} | ||
|
||
VkDeviceSize VkCoreObjects::GetVRAMSize(const vk::PhysicalDevice& phd) | ||
{ | ||
VkDeviceSize memSize = 0; | ||
const auto memProp = phd.getMemoryProperties(); | ||
for (auto hi = 0; hi < memProp.memoryHeapCount; ++hi) { | ||
if (memProp.memoryHeaps[hi].flags & vk::MemoryHeapFlagBits::eDeviceLocal) | ||
memSize += memProp.memoryHeaps[hi].size; | ||
} | ||
|
||
return memSize; | ||
} | ||
|
||
bool VkCoreObjects::HasExtension(const std::vector<vk::ExtensionProperties>& es, const char* e) | ||
{ | ||
return std::find_if(es.begin(), es.end(), | ||
[e](const auto& item) { | ||
return std::string_view(item.extensionName).compare(e) == 0; | ||
} | ||
) != es.end(); | ||
} | ||
|
||
VkCoreObjects::~VkCoreObjects() | ||
{ | ||
instance.destroy(); | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#pragma once | ||
#ifdef HAS_VULKAN | ||
|
||
#include <vector> | ||
#include <memory> | ||
|
||
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 | ||
#include <vulkan/vulkan.hpp> | ||
|
||
class VkCoreObjects { | ||
public: | ||
VkCoreObjects(); | ||
~VkCoreObjects(); | ||
|
||
const auto& GetInstanceExtensions() const { return instExtensionProperties; } | ||
const auto& GetPhysDeviceExtensions() const { return pdevExtensionProperties; } | ||
const auto& GetPhysDevices() const { return physicalDevices; } | ||
const auto& GetBestPhysDevice() const { return physicalDevice; } | ||
|
||
std::string GetVulkanAPI() const; | ||
static std::string GetVulkanAPI(uint32_t apiVersion); | ||
|
||
static VkDeviceSize GetVRAMSize(const vk::PhysicalDevice& phd); | ||
static bool HasExtension(const std::vector<vk::ExtensionProperties>& es, const char* e); | ||
|
||
static VkCoreObjects& GetInstance() { | ||
if (!vkCoreObjects) { | ||
vkCoreObjects = std::make_unique<VkCoreObjects>(); | ||
} | ||
return *vkCoreObjects; | ||
} | ||
static void KillInstance() { vkCoreObjects = nullptr; } | ||
private: | ||
static inline std::unique_ptr<VkCoreObjects> vkCoreObjects = nullptr; | ||
|
||
std::unique_ptr<vk::DynamicLoader> dl; | ||
|
||
vk::Instance instance; | ||
std::vector<vk::ExtensionProperties> instExtensionProperties; | ||
std::vector<vk::ExtensionProperties> pdevExtensionProperties; | ||
|
||
std::vector<vk::PhysicalDevice> physicalDevices; | ||
vk::PhysicalDevice physicalDevice; | ||
|
||
uint32_t apiVersion; | ||
|
||
//static constexpr | ||
}; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters