Choose Vulkan physical device
This commit is contained in:
parent
d53fb94e4c
commit
89cdf712b8
@ -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], ¤tPhysicalDeviceProperties);
|
||||
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);
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user