Choose Vulkan physical device

This commit is contained in:
Grayson Riffe 2025-02-09 01:09:14 -06:00
parent d53fb94e4c
commit 89cdf712b8
2 changed files with 87 additions and 3 deletions

View File

@ -10,13 +10,17 @@ namespace nf::cli::render {
, m_display(display)
, m_instance()
, m_surface()
, m_physicalDevice()
, m_queueFIGraphics()
, m_queueFIPresent()
{
NFLog("Initializing render engine");
createInstance();
createSurface(m_window->getHandle());
m_window->setDisplay(m_display);
m_window->show();
createInstance();
createSurface(m_window->getHandle());
pickPhysicalDevice();
}
void RenderEngine::createInstance() {
@ -44,6 +48,83 @@ namespace nf::cli::render {
NFError("Could not create Vulkan surface");
}
void RenderEngine::pickPhysicalDevice() {
// TODO: Save GPU choice in DisplayConfig
// First, get list of all GPUs
uint32_t numPhysicalDevices = 0;
vkEnumeratePhysicalDevices(m_instance, &numPhysicalDevices, nullptr);
if (numPhysicalDevices == 0)
NFError("No Vulkan GPUs found");
std::vector<VkPhysicalDevice> physicalDevices(numPhysicalDevices);
vkEnumeratePhysicalDevices(m_instance, &numPhysicalDevices, physicalDevices.data());
// Then gather information on them and save first dedicated
std::optional<int> firstDedicatedPhysicalDeviceIndex;
std::vector<VkPhysicalDeviceProperties> physicalDeviceProperties;
for (int i = 0; i < numPhysicalDevices; i++) {
VkPhysicalDeviceProperties currentPhysicalDeviceProperties = {};
vkGetPhysicalDeviceProperties(physicalDevices[i], &currentPhysicalDeviceProperties);
if (currentPhysicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && !firstDedicatedPhysicalDeviceIndex.has_value())
firstDedicatedPhysicalDeviceIndex = i;
physicalDeviceProperties.push_back(currentPhysicalDeviceProperties);
}
// Try dedicated first, then try every GPU in order
if (firstDedicatedPhysicalDeviceIndex.has_value()) {
int dedicatedIndex = firstDedicatedPhysicalDeviceIndex.value();
physicalDevices.insert(physicalDevices.begin(), physicalDevices[dedicatedIndex]);
physicalDevices.erase(physicalDevices.begin() + dedicatedIndex + 1);
physicalDeviceProperties.insert(physicalDeviceProperties.begin(), physicalDeviceProperties[dedicatedIndex]);
physicalDeviceProperties.erase(physicalDeviceProperties.begin() + dedicatedIndex + 1);
}
struct PhysicalDeviceQueueFamilyIndices {
uint32_t graphics, present;
};
auto getQueueFamilyIndices = [&](int currentPhysicalDeviceIndex) -> std::optional<PhysicalDeviceQueueFamilyIndices> {
uint32_t numQueueFamilies = 0;
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevices[currentPhysicalDeviceIndex], &numQueueFamilies, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilyProperties(numQueueFamilies);
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevices[currentPhysicalDeviceIndex], &numQueueFamilies, queueFamilyProperties.data());
std::optional<uint32_t> graphicsIndex, presentIndex;
for (int i = 0; i < numQueueFamilies; i++) {
if (queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT && !graphicsIndex.has_value())
graphicsIndex = i;
VkBool32 hasPresentSupport = VK_FALSE;
vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevices[currentPhysicalDeviceIndex], i, m_surface, &hasPresentSupport);
if (hasPresentSupport && !presentIndex.has_value())
presentIndex = i;
}
if (graphicsIndex.has_value() && presentIndex.has_value())
return PhysicalDeviceQueueFamilyIndices{ graphicsIndex.value(), presentIndex.value() };
return std::nullopt;
};
std::optional<PhysicalDeviceQueueFamilyIndices> chosenPhysicalDeviceIndices;
for (int i = 0; i < numPhysicalDevices; i++) {
chosenPhysicalDeviceIndices = getQueueFamilyIndices(i);
if (chosenPhysicalDeviceIndices.has_value()) {
// GPU found!
m_physicalDevice = physicalDevices[i];
m_queueFIGraphics = chosenPhysicalDeviceIndices->graphics;
m_queueFIPresent = chosenPhysicalDeviceIndices->present;
NFLog(std::format("GPU - {}", physicalDeviceProperties[i].deviceName));
break;
}
}
if (m_physicalDevice == nullptr)
NFError("No Vulkan GPUs were found to be compatible");
}
RenderEngine::~RenderEngine() {
vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
vkDestroyInstance(m_instance, nullptr);

View File

@ -13,11 +13,14 @@ namespace nf::cli::render {
private:
void createInstance();
void createSurface(HWND window);
void pickPhysicalDevice();
std::shared_ptr<Window> m_window;
DisplayConfig m_display;
VkInstance m_instance;
VkSurfaceKHR m_surface;
VkPhysicalDevice m_physicalDevice;
uint32_t m_queueFIGraphics, m_queueFIPresent;
};
}