Commit 20b2546f authored by Florian Oetke's avatar Florian Oetke
Browse files

added option for GPU selection

parent a197ae55
......@@ -28,6 +28,7 @@ namespace mirrage::graphic {
struct Graphics_settings {
std::unordered_map<std::string, Window_settings> windows;
std::string gpu_preference;
};
......@@ -41,7 +42,9 @@ namespace mirrage::graphic {
return settings;
}
inline constexpr auto make_version_number(std::uint32_t major, std::uint32_t minor, std::uint32_t patch) {
inline constexpr auto make_version_number(std::uint32_t major,
std::uint32_t minor,
std::uint32_t patch) {
return (((major) << 22) | ((minor) << 12) | (patch));
}
......@@ -49,6 +52,6 @@ namespace mirrage::graphic {
#ifdef sf2_structDef
sf2_enumDef(Fullscreen, no, yes, yes_borderless);
sf2_structDef(Window_settings, width, height, display, fullscreen);
sf2_structDef(Graphics_settings, windows);
sf2_structDef(Graphics_settings, windows, gpu_preference);
#endif
} // namespace mirrage::graphic
......@@ -22,8 +22,8 @@ VkResult vkCreateDebugReportCallbackEXT(VkInstance
const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDebugReportCallbackEXT* pCallback) {
auto func = (PFN_vkCreateDebugReportCallbackEXT) vkGetInstanceProcAddr(instance,
"vkCreateDebugReportCallbackEXT");
auto func = (PFN_vkCreateDebugReportCallbackEXT) vkGetInstanceProcAddr(
instance, "vkCreateDebugReportCallbackEXT");
if(func != nullptr) {
return func(instance, pCreateInfo, pAllocator, pCallback);
} else {
......@@ -59,7 +59,8 @@ namespace mirrage::graphic {
void add_present_extensions(std::vector<const char*>& extensions) {
auto present_extensions = std::vector<const char*>(4);
auto present_extensions_size = static_cast<unsigned int>(present_extensions.size());
if(!SDL_GetVulkanInstanceExtensions(&present_extensions_size, present_extensions.data())) {
if(!SDL_GetVulkanInstanceExtensions(&present_extensions_size,
present_extensions.data())) {
MIRRAGE_FAIL("Unable to determine present extensions: " << SDL_GetError());
}
......@@ -71,7 +72,8 @@ namespace mirrage::graphic {
}
auto check_extensions(const std::vector<const char*>& required,
const std::vector<const char*>& optional) -> std::vector<const char*> {
const std::vector<const char*>& optional)
-> std::vector<const char*> {
auto extensions = std::vector<const char*>();
extensions.reserve(required.size() + optional.size());
......@@ -105,7 +107,8 @@ namespace mirrage::graphic {
}
if(!all_supported) {
MIRRAGE_FAIL("At least one required extension is not supported (see log for details)!");
MIRRAGE_FAIL(
"At least one required extension is not supported (see log for details)!");
}
return extensions;
......@@ -127,8 +130,9 @@ namespace mirrage::graphic {
}
if(!layer_requested) {
MIRRAGE_DEBUG("Additional validation layer is available, that hasn't been requested: "
<< l.layerName);
MIRRAGE_DEBUG(
"Additional validation layer is available, that hasn't been requested: "
<< l.layerName);
}
}
......@@ -236,7 +240,8 @@ namespace mirrage::graphic {
if(debug) {
_debug_callback = _instance->createDebugReportCallbackEXTUnique(
{/* vk::DebugReportFlagBitsEXT::eDebug | vk::DebugReportFlagBitsEXT::eInformation | */
vk::DebugReportFlagBitsEXT::eError | vk::DebugReportFlagBitsEXT::ePerformanceWarning
vk::DebugReportFlagBitsEXT::eError
| vk::DebugReportFlagBitsEXT::ePerformanceWarning
| vk::DebugReportFlagBitsEXT::eWarning,
debugCallback});
}
......@@ -270,11 +275,13 @@ namespace mirrage::graphic {
settings.height,
settings.fullscreen);
}
auto Context::_find_window_settings(const std::string& name, int width, int height) -> Window_settings {
auto Context::_find_window_settings(const std::string& name, int width, int height)
-> Window_settings {
auto& cfg = settings();
auto win_cfg = std::find_if(
std::begin(cfg.windows), std::end(cfg.windows), [&](auto& w) { return w.first == name; });
auto win_cfg = std::find_if(std::begin(cfg.windows), std::end(cfg.windows), [&](auto& w) {
return w.first == name;
});
if(win_cfg == std::end(cfg.windows)) { // no config create new
auto new_settings = cfg;
......@@ -296,9 +303,10 @@ namespace mirrage::graphic {
namespace {
bool supports_present(vk::PhysicalDevice& gpu, const std::vector<Window*>& can_present_to) {
auto supported_extensions = gpu.enumerateDeviceExtensionProperties();
auto sc_ext = std::find_if(supported_extensions.begin(), supported_extensions.end(), [](auto& e) {
return std::strcmp(e.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0;
});
auto sc_ext = std::find_if(
supported_extensions.begin(), supported_extensions.end(), [](auto& e) {
return std::strcmp(e.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0;
});
if(sc_ext == supported_extensions.end()) {
return false;
......@@ -315,16 +323,18 @@ namespace mirrage::graphic {
return true;
}
auto find_graphics_queue(vk::PhysicalDevice& gpu, const std::vector<Window*>& can_present_to)
auto find_graphics_queue(vk::PhysicalDevice& gpu,
const std::vector<Window*>& can_present_to)
-> util::maybe<std::uint32_t> {
auto i = 0;
for(auto& queue_family : gpu.getQueueFamilyProperties()) {
auto can_present =
can_present_to.empty()
|| std::all_of(can_present_to.begin(), can_present_to.end(), [&](auto window) {
return gpu.getSurfaceSupportKHR(i, window->surface());
});
|| std::all_of(
can_present_to.begin(), can_present_to.end(), [&](auto window) {
return gpu.getSurfaceSupportKHR(i, window->surface());
});
if(queue_family.queueCount > 0 && can_present
&& queue_family.timestampValidBits
......@@ -346,7 +356,8 @@ namespace mirrage::graphic {
// check for transfer-only queue
for(auto& queue_family : families) {
if(queue_family.queueCount > 0 && (queue_family.queueFlags & vk::QueueFlagBits::eTransfer)
if(queue_family.queueCount > 0
&& (queue_family.queueFlags & vk::QueueFlagBits::eTransfer)
&& !(queue_family.queueFlags & vk::QueueFlagBits::eGraphics)) {
return i;
}
......@@ -386,15 +397,17 @@ namespace mirrage::graphic {
return {target_format, target_space};
}
opt_found = std::find_if(
formats.begin(), formats.end(), [&](auto& f) { return f.format == target_format; });
opt_found = std::find_if(formats.begin(), formats.end(), [&](auto& f) {
return f.format == target_format;
});
if(opt_found != formats.end()) {
return *opt_found;
}
if(!formats.empty()) {
MIRRAGE_WARN(
"Requested format is not supported by the device, fallback to first reported "
"Requested format is not supported by the device, fallback to first "
"reported "
"format");
return formats.front();
} else {
......@@ -419,14 +432,16 @@ namespace mirrage::graphic {
sc_info.setImageUsage(vk::ImageUsageFlagBits::eColorAttachment);
sc_info.setImageArrayLayers(1);
sc_info.setMinImageCount(std::max(2u, capabilities.minImageCount));
if(capabilities.maxImageCount > 0 && capabilities.maxImageCount < sc_info.minImageCount) {
if(capabilities.maxImageCount > 0
&& capabilities.maxImageCount < sc_info.minImageCount) {
sc_info.setMinImageCount(capabilities.maxImageCount);
}
auto present_modes = gpu.getSurfacePresentModesKHR(window->surface());
auto mailbox_supported =
std::find(present_modes.begin(), present_modes.end(), vk::PresentModeKHR::eMailbox)
!= present_modes.end();
auto present_modes = gpu.getSurfacePresentModesKHR(window->surface());
auto mailbox_supported = std::find(present_modes.begin(),
present_modes.end(),
vk::PresentModeKHR::eMailbox)
!= present_modes.end();
if(mailbox_supported) {
sc_info.setPresentMode(vk::PresentModeKHR::eMailbox);
} else {
......@@ -447,11 +462,11 @@ namespace mirrage::graphic {
sc_info.setImageExtent(capabilities.currentExtent);
auto format =
find_surface_format(gpu,
*window,
srgb ? vk::Format::eB8G8R8A8Srgb : vk::Format::eB8G8R8A8Unorm,
vk::ColorSpaceKHR::eSrgbNonlinear);
auto format = find_surface_format(gpu,
*window,
srgb ? vk::Format::eB8G8R8A8Srgb
: vk::Format::eB8G8R8A8Unorm,
vk::ColorSpaceKHR::eSrgbNonlinear);
sc_info.setImageFormat(format.format);
sc_info.setImageColorSpace(format.colorSpace);
......@@ -477,6 +492,14 @@ namespace mirrage::graphic {
auto graphics_queue = find_graphics_queue(gpu, can_present_to);
auto score = selector(gpu, graphics_queue);
auto gpu_name = std::string(gpu.getProperties().deviceName);
MIRRAGE_INFO("Detected GPU: " << gpu_name);
if(!_settings->gpu_preference.empty() && _settings->gpu_preference == gpu_name) {
score = std::numeric_limits<int>::max();
}
if(score > top_score) {
top_score = score;
top_gpu = gpu;
......@@ -487,6 +510,8 @@ namespace mirrage::graphic {
MIRRAGE_FAIL("Couldn't find a GPU that supports vulkan and all required features.");
}
MIRRAGE_INFO("Selected GPU: " << top_gpu.getProperties().deviceName);
auto cfg = vk::DeviceCreateInfo{};
cfg.setEnabledLayerCount(gsl::narrow<uint32_t>(_enabled_layers.size()));
cfg.setPpEnabledLayerNames(_enabled_layers.data());
......@@ -495,9 +520,9 @@ namespace mirrage::graphic {
auto supported_extensions = top_gpu.enumerateDeviceExtensionProperties();
auto extension_supported = [&](const char* e) {
return supported_extensions.end()
!= std::find_if(supported_extensions.begin(), supported_extensions.end(), [&](auto& se) {
return !strcmp(se.extensionName, e);
});
!= std::find_if(supported_extensions.begin(),
supported_extensions.end(),
[&](auto& se) { return !strcmp(se.extensionName, e); });
};
auto dedicated_alloc_supported = false;
......@@ -554,7 +579,8 @@ namespace mirrage::graphic {
auto used_queues = std::vector<vk::DeviceQueueCreateInfo>{};
used_queues.reserve(queue_families.size());
for(auto& qf : queue_families) {
MIRRAGE_INVARIANT(std::get<1>(qf.second).size() == std::get<0>(qf.second), "Size mismatch");
MIRRAGE_INVARIANT(std::get<1>(qf.second).size() == std::get<0>(qf.second),
"Size mismatch");
used_queues.emplace_back(vk::DeviceQueueCreateFlags(),
qf.first,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment