GPU selection: prefer the discrete GPU + settings device picker
This commit is contained in:
parent
96de5455f2
commit
ef55119407
8 changed files with 209 additions and 25 deletions
|
|
@ -25,7 +25,7 @@
|
||||||
#include <d3d12.h>
|
#include <d3d12.h>
|
||||||
#include <d3d12sdklayers.h>
|
#include <d3d12sdklayers.h>
|
||||||
#include <d3dcompiler.h>
|
#include <d3dcompiler.h>
|
||||||
#include <dxgi1_5.h>
|
#include <dxgi1_6.h>
|
||||||
#include <dxgidebug.h>
|
#include <dxgidebug.h>
|
||||||
// For Microsoft::WRL::ComPtr.
|
// For Microsoft::WRL::ComPtr.
|
||||||
#include <wrl/client.h>
|
#include <wrl/client.h>
|
||||||
|
|
|
||||||
28
include/rex/ui/graphics_device_list.h
Normal file
28
include/rex/ui/graphics_device_list.h
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
/**
|
||||||
|
* @file rex/ui/graphics_device_list.h
|
||||||
|
*
|
||||||
|
* @brief Registry of the graphics devices the active backend enumerated.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace rex::ui {
|
||||||
|
|
||||||
|
// Devices the active graphics backend enumerated during initialization, in
|
||||||
|
// cvar index order: element i is selected by setting the backend's device
|
||||||
|
// cvar to i, and -1 selects automatically. Published by the provider so UI
|
||||||
|
// like the settings overlay can offer a device picker without linking against
|
||||||
|
// a specific backend.
|
||||||
|
struct GraphicsDeviceList {
|
||||||
|
// Init-only int32 cvar that selects a device by index ("d3d12_adapter" or
|
||||||
|
// "vulkan_device"); empty when no backend has published a list.
|
||||||
|
std::string cvar_name;
|
||||||
|
std::vector<std::string> device_names;
|
||||||
|
};
|
||||||
|
|
||||||
|
void SetGraphicsDeviceList(GraphicsDeviceList list);
|
||||||
|
GraphicsDeviceList GetGraphicsDeviceList();
|
||||||
|
|
||||||
|
} // namespace rex::ui
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <rex/ui/graphics_device_list.h>
|
||||||
#include <rex/ui/imgui_dialog.h>
|
#include <rex/ui/imgui_dialog.h>
|
||||||
|
|
||||||
namespace rex::ui {
|
namespace rex::ui {
|
||||||
|
|
@ -66,6 +67,8 @@ class SimpleSettingsDialog final : public ImGuiDialog {
|
||||||
RestartGameCallback restart_game_;
|
RestartGameCallback restart_game_;
|
||||||
SimpleProfileState profiles_;
|
SimpleProfileState profiles_;
|
||||||
bool visible_ = false;
|
bool visible_ = false;
|
||||||
|
GraphicsDeviceList device_list_;
|
||||||
|
int device_index_ = 0;
|
||||||
int resolution_scale_index_ = 0;
|
int resolution_scale_index_ = 0;
|
||||||
int frame_cap_index_ = 0;
|
int frame_cap_index_ = 0;
|
||||||
int aspect_ratio_index_ = 0;
|
int aspect_ratio_index_ = 0;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
# Core UI sources
|
# Core UI sources
|
||||||
set(REXUI_CORE_SOURCES
|
set(REXUI_CORE_SOURCES
|
||||||
|
graphics_device_list.cpp
|
||||||
graphics_upload_buffer_pool.cpp
|
graphics_upload_buffer_pool.cpp
|
||||||
graphics_util.cpp
|
graphics_util.cpp
|
||||||
imgui_dialog.cpp
|
imgui_dialog.cpp
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
#include <rex/cvar.h>
|
#include <rex/cvar.h>
|
||||||
#include <rex/logging.h>
|
#include <rex/logging.h>
|
||||||
#include <rex/math.h>
|
#include <rex/math.h>
|
||||||
|
#include <rex/ui/graphics_device_list.h>
|
||||||
#include <rex/ui/d3d12/d3d12_immediate_drawer.h>
|
#include <rex/ui/d3d12/d3d12_immediate_drawer.h>
|
||||||
#include <rex/ui/d3d12/d3d12_presenter.h>
|
#include <rex/ui/d3d12/d3d12_presenter.h>
|
||||||
#include <rex/ui/d3d12/d3d12_provider.h>
|
#include <rex/ui/d3d12/d3d12_provider.h>
|
||||||
|
|
@ -250,10 +251,63 @@ bool D3D12Provider::Initialize() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Log all adapters so GPU-selection problems are diagnosable from user logs,
|
||||||
|
// and publish them for the settings UI device picker (indices match the
|
||||||
|
// 'd3d12_adapter' cvar).
|
||||||
|
{
|
||||||
|
GraphicsDeviceList device_list;
|
||||||
|
device_list.cvar_name = "d3d12_adapter";
|
||||||
|
IDXGIAdapter1* logged_adapter;
|
||||||
|
for (uint32_t i = 0; dxgi_factory->EnumAdapters1(i, &logged_adapter) == S_OK; ++i) {
|
||||||
|
std::string device_name = "Adapter " + std::to_string(i);
|
||||||
|
DXGI_ADAPTER_DESC1 logged_desc;
|
||||||
|
if (SUCCEEDED(logged_adapter->GetDesc1(&logged_desc))) {
|
||||||
|
char logged_name_mb[512] = {};
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, logged_desc.Description, -1, logged_name_mb,
|
||||||
|
sizeof(logged_name_mb) - 1, nullptr, nullptr);
|
||||||
|
if (logged_name_mb[0]) {
|
||||||
|
device_name = logged_name_mb;
|
||||||
|
}
|
||||||
|
REXGPU_INFO("DXGI adapter {}: {} (vendor 0x{:04X}, device 0x{:04X}){}", i, logged_name_mb,
|
||||||
|
logged_desc.VendorId, logged_desc.DeviceId,
|
||||||
|
(logged_desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) ? " [software]" : "");
|
||||||
|
}
|
||||||
|
device_list.device_names.push_back(std::move(device_name));
|
||||||
|
logged_adapter->Release();
|
||||||
|
}
|
||||||
|
SetGraphicsDeviceList(std::move(device_list));
|
||||||
|
}
|
||||||
|
|
||||||
// Choose the adapter.
|
// Choose the adapter.
|
||||||
uint32_t adapter_index = 0;
|
uint32_t adapter_index = 0;
|
||||||
IDXGIAdapter1* adapter = nullptr;
|
IDXGIAdapter1* adapter = nullptr;
|
||||||
while (dxgi_factory->EnumAdapters1(adapter_index, &adapter) == S_OK) {
|
// With no explicit adapter requested, ask DXGI for adapters sorted by GPU
|
||||||
|
// preference so hybrid-graphics systems (laptop Optimus / PowerXpress) pick
|
||||||
|
// the discrete GPU instead of whichever adapter enumerates first (usually
|
||||||
|
// the integrated one the display is wired to). IDXGIFactory6 requires
|
||||||
|
// Windows 10 1803+; fall back to plain enumeration order without it.
|
||||||
|
if (REXCVAR_GET(d3d12_adapter) == -1) {
|
||||||
|
IDXGIFactory6* dxgi_factory6 = nullptr;
|
||||||
|
if (SUCCEEDED(dxgi_factory->QueryInterface(IID_PPV_ARGS(&dxgi_factory6)))) {
|
||||||
|
while (dxgi_factory6->EnumAdapterByGpuPreference(adapter_index,
|
||||||
|
DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
|
||||||
|
IID_PPV_ARGS(&adapter)) == S_OK) {
|
||||||
|
DXGI_ADAPTER_DESC1 adapter_desc;
|
||||||
|
if (SUCCEEDED(adapter->GetDesc1(&adapter_desc)) &&
|
||||||
|
!(adapter_desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) &&
|
||||||
|
SUCCEEDED(pfn_d3d12_create_device_(adapter, D3D_FEATURE_LEVEL_11_0,
|
||||||
|
_uuidof(ID3D12Device), nullptr))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
adapter->Release();
|
||||||
|
adapter = nullptr;
|
||||||
|
++adapter_index;
|
||||||
|
}
|
||||||
|
dxgi_factory6->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
adapter_index = 0;
|
||||||
|
while (adapter == nullptr && dxgi_factory->EnumAdapters1(adapter_index, &adapter) == S_OK) {
|
||||||
DXGI_ADAPTER_DESC1 adapter_desc;
|
DXGI_ADAPTER_DESC1 adapter_desc;
|
||||||
if (SUCCEEDED(adapter->GetDesc1(&adapter_desc))) {
|
if (SUCCEEDED(adapter->GetDesc1(&adapter_desc))) {
|
||||||
if (SUCCEEDED(pfn_d3d12_create_device_(adapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device),
|
if (SUCCEEDED(pfn_d3d12_create_device_(adapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device),
|
||||||
|
|
|
||||||
29
src/ui/graphics_device_list.cpp
Normal file
29
src/ui/graphics_device_list.cpp
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
/**
|
||||||
|
* @file ui/graphics_device_list.cpp
|
||||||
|
*
|
||||||
|
* @brief Registry of the graphics devices the active backend enumerated.
|
||||||
|
*/
|
||||||
|
#include <rex/ui/graphics_device_list.h>
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace rex::ui {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::mutex g_graphics_device_list_mutex;
|
||||||
|
GraphicsDeviceList g_graphics_device_list;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void SetGraphicsDeviceList(GraphicsDeviceList list) {
|
||||||
|
std::lock_guard<std::mutex> lock(g_graphics_device_list_mutex);
|
||||||
|
g_graphics_device_list = std::move(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsDeviceList GetGraphicsDeviceList() {
|
||||||
|
std::lock_guard<std::mutex> lock(g_graphics_device_list_mutex);
|
||||||
|
return g_graphics_device_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace rex::ui
|
||||||
|
|
@ -41,8 +41,16 @@ bool HasCvar(std::string_view name) {
|
||||||
|
|
||||||
std::vector<std::string_view> GetSimpleSettingsCvars() {
|
std::vector<std::string_view> GetSimpleSettingsCvars() {
|
||||||
std::vector<std::string_view> cvars;
|
std::vector<std::string_view> cvars;
|
||||||
cvars.reserve(14);
|
cvars.reserve(15);
|
||||||
cvars.insert(cvars.end(), kCoreSimpleSettingsCvars.begin(), kCoreSimpleSettingsCvars.end());
|
cvars.insert(cvars.end(), kCoreSimpleSettingsCvars.begin(), kCoreSimpleSettingsCvars.end());
|
||||||
|
// Literal names rather than the registry's string to keep the string_views
|
||||||
|
// pointing at static storage.
|
||||||
|
const std::string device_cvar = GetGraphicsDeviceList().cvar_name;
|
||||||
|
if (device_cvar == "d3d12_adapter" && HasCvar("d3d12_adapter")) {
|
||||||
|
cvars.push_back("d3d12_adapter");
|
||||||
|
} else if (device_cvar == "vulkan_device" && HasCvar("vulkan_device")) {
|
||||||
|
cvars.push_back("vulkan_device");
|
||||||
|
}
|
||||||
if (HasCvar("skate3_ultrawide")) {
|
if (HasCvar("skate3_ultrawide")) {
|
||||||
cvars.push_back("skate3_ultrawide");
|
cvars.push_back("skate3_ultrawide");
|
||||||
}
|
}
|
||||||
|
|
@ -70,6 +78,18 @@ std::vector<std::string_view> GetSimpleSettingsCvars() {
|
||||||
return cvars;
|
return cvars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 0 = automatic selection (cvar -1); i+1 = the list's device i.
|
||||||
|
int DeviceIndexFromCvar(const GraphicsDeviceList& device_list) {
|
||||||
|
if (device_list.device_names.empty() || !HasCvar(device_list.cvar_name)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int32_t current = rex::cvar::Query<int32_t>(device_list.cvar_name);
|
||||||
|
if (current >= 0 && current < static_cast<int32_t>(device_list.device_names.size())) {
|
||||||
|
return current + 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int ResolutionIndexFromCvar() {
|
int ResolutionIndexFromCvar() {
|
||||||
int32_t current = rex::cvar::Query<int32_t>("resolution_scale");
|
int32_t current = rex::cvar::Query<int32_t>("resolution_scale");
|
||||||
int best = 0;
|
int best = 0;
|
||||||
|
|
@ -233,6 +253,8 @@ void SimpleSettingsDialog::Show() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleSettingsDialog::LoadSettingsFromCvars() {
|
void SimpleSettingsDialog::LoadSettingsFromCvars() {
|
||||||
|
device_list_ = GetGraphicsDeviceList();
|
||||||
|
device_index_ = DeviceIndexFromCvar(device_list_);
|
||||||
resolution_scale_index_ = ResolutionIndexFromCvar();
|
resolution_scale_index_ = ResolutionIndexFromCvar();
|
||||||
frame_cap_index_ = FrameCapIndexFromCvar();
|
frame_cap_index_ = FrameCapIndexFromCvar();
|
||||||
aspect_ratio_index_ =
|
aspect_ratio_index_ =
|
||||||
|
|
@ -246,7 +268,8 @@ void SimpleSettingsDialog::LoadSettingsFromCvars() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SimpleSettingsDialog::HasSettingsChanges() const {
|
bool SimpleSettingsDialog::HasSettingsChanges() const {
|
||||||
return resolution_scale_index_ != ResolutionIndexFromCvar() ||
|
return device_index_ != DeviceIndexFromCvar(device_list_) ||
|
||||||
|
resolution_scale_index_ != ResolutionIndexFromCvar() ||
|
||||||
frame_cap_index_ != FrameCapIndexFromCvar() ||
|
frame_cap_index_ != FrameCapIndexFromCvar() ||
|
||||||
(HasCvar("skate3_ultrawide") &&
|
(HasCvar("skate3_ultrawide") &&
|
||||||
(aspect_ratio_index_ != 0) != rex::cvar::Query<bool>("skate3_ultrawide")) ||
|
(aspect_ratio_index_ != 0) != rex::cvar::Query<bool>("skate3_ultrawide")) ||
|
||||||
|
|
@ -297,6 +320,12 @@ void SimpleSettingsDialog::SaveVideo() {
|
||||||
aspect_ratio_index_ =
|
aspect_ratio_index_ =
|
||||||
std::clamp(aspect_ratio_index_, 0, static_cast<int>(kAspectRatioLabels.size()) - 1);
|
std::clamp(aspect_ratio_index_, 0, static_cast<int>(kAspectRatioLabels.size()) - 1);
|
||||||
field_of_view_ = std::clamp(field_of_view_, 40.0f, 120.0f);
|
field_of_view_ = std::clamp(field_of_view_, 40.0f, 120.0f);
|
||||||
|
if (!device_list_.device_names.empty() && HasCvar(device_list_.cvar_name)) {
|
||||||
|
device_index_ =
|
||||||
|
std::clamp(device_index_, 0, static_cast<int>(device_list_.device_names.size()));
|
||||||
|
rex::cvar::SetFlagByName(device_list_.cvar_name,
|
||||||
|
device_index_ == 0 ? "-1" : std::to_string(device_index_ - 1));
|
||||||
|
}
|
||||||
const auto scale = std::to_string(kResolutionScales[resolution_scale_index_]);
|
const auto scale = std::to_string(kResolutionScales[resolution_scale_index_]);
|
||||||
rex::cvar::SetFlagByName("resolution_scale", scale);
|
rex::cvar::SetFlagByName("resolution_scale", scale);
|
||||||
rex::cvar::SetFlagByName("draw_resolution_scale_x", scale);
|
rex::cvar::SetFlagByName("draw_resolution_scale_x", scale);
|
||||||
|
|
@ -430,6 +459,27 @@ void SimpleSettingsDialog::OnDraw(ImGuiIO& io) {
|
||||||
if (selected_tab_ == 0) {
|
if (selected_tab_ == 0) {
|
||||||
SectionTitle("Video");
|
SectionTitle("Video");
|
||||||
|
|
||||||
|
if (!device_list_.device_names.empty() && HasCvar(device_list_.cvar_name)) {
|
||||||
|
BeginFieldRow("Graphics Device");
|
||||||
|
// Index-prefixed labels: virtual display drivers (Parsec etc.) make the
|
||||||
|
// same physical GPU enumerate several times, and the index is what the
|
||||||
|
// device cvar and the startup log speak in.
|
||||||
|
std::vector<std::string> device_label_storage;
|
||||||
|
device_label_storage.reserve(device_list_.device_names.size());
|
||||||
|
for (size_t i = 0; i < device_list_.device_names.size(); ++i) {
|
||||||
|
device_label_storage.push_back(std::to_string(i) + ": " + device_list_.device_names[i]);
|
||||||
|
}
|
||||||
|
std::vector<const char*> device_labels;
|
||||||
|
device_labels.reserve(device_label_storage.size() + 1);
|
||||||
|
device_labels.push_back("Auto (recommended)");
|
||||||
|
for (const auto& label : device_label_storage) {
|
||||||
|
device_labels.push_back(label.c_str());
|
||||||
|
}
|
||||||
|
ImGui::Combo("##graphics_device", &device_index_, device_labels.data(),
|
||||||
|
static_cast<int>(device_labels.size()));
|
||||||
|
EndFieldRow();
|
||||||
|
}
|
||||||
|
|
||||||
BeginFieldRow("Resolution Scale");
|
BeginFieldRow("Resolution Scale");
|
||||||
ImGui::Combo("##resolution_scale", &resolution_scale_index_, kResolutionLabels.data(),
|
ImGui::Combo("##resolution_scale", &resolution_scale_index_, kResolutionLabels.data(),
|
||||||
static_cast<int>(kResolutionLabels.size()));
|
static_cast<int>(kResolutionLabels.size()));
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include <rex/cvar.h>
|
#include <rex/cvar.h>
|
||||||
#include <rex/logging.h>
|
#include <rex/logging.h>
|
||||||
|
#include <rex/ui/graphics_device_list.h>
|
||||||
#include <rex/ui/vulkan/immediate_drawer.h>
|
#include <rex/ui/vulkan/immediate_drawer.h>
|
||||||
#include <rex/ui/vulkan/presenter.h>
|
#include <rex/ui/vulkan/presenter.h>
|
||||||
#include <rex/ui/vulkan/provider.h>
|
#include <rex/ui/vulkan/provider.h>
|
||||||
|
|
@ -67,12 +68,18 @@ std::unique_ptr<VulkanProvider> VulkanProvider::Create(const bool with_gpu_emula
|
||||||
REXLOG_WARN(
|
REXLOG_WARN(
|
||||||
"Available Vulkan physical devices (use the 'vulkan_device' "
|
"Available Vulkan physical devices (use the 'vulkan_device' "
|
||||||
"configuration variable to force a specific device):");
|
"configuration variable to force a specific device):");
|
||||||
for (size_t physical_device_index = 0; physical_device_index < physical_devices.size();
|
{
|
||||||
++physical_device_index) {
|
GraphicsDeviceList device_list;
|
||||||
VkPhysicalDeviceProperties physical_device_properties;
|
device_list.cvar_name = "vulkan_device";
|
||||||
ifn.vkGetPhysicalDeviceProperties(physical_devices[physical_device_index],
|
for (size_t physical_device_index = 0; physical_device_index < physical_devices.size();
|
||||||
&physical_device_properties);
|
++physical_device_index) {
|
||||||
REXLOG_WARN("* {}: {}", physical_device_index, physical_device_properties.deviceName);
|
VkPhysicalDeviceProperties physical_device_properties;
|
||||||
|
ifn.vkGetPhysicalDeviceProperties(physical_devices[physical_device_index],
|
||||||
|
&physical_device_properties);
|
||||||
|
REXLOG_WARN("* {}: {}", physical_device_index, physical_device_properties.deviceName);
|
||||||
|
device_list.device_names.push_back(physical_device_properties.deviceName);
|
||||||
|
}
|
||||||
|
SetGraphicsDeviceList(std::move(device_list));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (REXCVAR_GET(vulkan_device) >= 0 &&
|
if (REXCVAR_GET(vulkan_device) >= 0 &&
|
||||||
|
|
@ -88,9 +95,7 @@ std::unique_ptr<VulkanProvider> VulkanProvider::Create(const bool with_gpu_emula
|
||||||
bool prefer_fragment_stores = REXCVAR_GET(vulkan_prefer_fragment_stores_and_atomics);
|
bool prefer_fragment_stores = REXCVAR_GET(vulkan_prefer_fragment_stores_and_atomics);
|
||||||
bool prefer_vertex_stores = REXCVAR_GET(vulkan_prefer_vertex_pipeline_stores_and_atomics);
|
bool prefer_vertex_stores = REXCVAR_GET(vulkan_prefer_vertex_pipeline_stores_and_atomics);
|
||||||
bool prefer_fill_mode_non_solid = REXCVAR_GET(vulkan_prefer_fill_mode_non_solid);
|
bool prefer_fill_mode_non_solid = REXCVAR_GET(vulkan_prefer_fill_mode_non_solid);
|
||||||
if (with_gpu_emulation && physical_devices.size() > 1 &&
|
if (physical_devices.size() > 1) {
|
||||||
(prefer_geometry_shader || prefer_fragment_stores || prefer_vertex_stores ||
|
|
||||||
prefer_fill_mode_non_solid)) {
|
|
||||||
struct PhysicalDeviceScore {
|
struct PhysicalDeviceScore {
|
||||||
VkPhysicalDevice physical_device;
|
VkPhysicalDevice physical_device;
|
||||||
uint32_t score;
|
uint32_t score;
|
||||||
|
|
@ -98,20 +103,34 @@ std::unique_ptr<VulkanProvider> VulkanProvider::Create(const bool with_gpu_emula
|
||||||
std::vector<PhysicalDeviceScore> scored_devices;
|
std::vector<PhysicalDeviceScore> scored_devices;
|
||||||
scored_devices.reserve(physical_devices.size());
|
scored_devices.reserve(physical_devices.size());
|
||||||
for (const VkPhysicalDevice physical_device : physical_devices) {
|
for (const VkPhysicalDevice physical_device : physical_devices) {
|
||||||
VkPhysicalDeviceFeatures supported_features = {};
|
|
||||||
ifn.vkGetPhysicalDeviceFeatures(physical_device, &supported_features);
|
|
||||||
uint32_t score = 0;
|
uint32_t score = 0;
|
||||||
if (prefer_geometry_shader && supported_features.geometryShader) {
|
if (with_gpu_emulation) {
|
||||||
++score;
|
VkPhysicalDeviceFeatures supported_features = {};
|
||||||
|
ifn.vkGetPhysicalDeviceFeatures(physical_device, &supported_features);
|
||||||
|
if (prefer_geometry_shader && supported_features.geometryShader) {
|
||||||
|
score += 4;
|
||||||
|
}
|
||||||
|
if (prefer_fragment_stores && supported_features.fragmentStoresAndAtomics) {
|
||||||
|
score += 4;
|
||||||
|
}
|
||||||
|
if (prefer_vertex_stores && supported_features.vertexPipelineStoresAndAtomics) {
|
||||||
|
score += 4;
|
||||||
|
}
|
||||||
|
if (prefer_fill_mode_non_solid && supported_features.fillModeNonSolid) {
|
||||||
|
score += 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (prefer_fragment_stores && supported_features.fragmentStoresAndAtomics) {
|
// Prefer the discrete GPU on hybrid-graphics systems. Weighted below
|
||||||
++score;
|
// the emulation feature bits so feature support still wins, but it
|
||||||
}
|
// breaks the tie that previously left device choice to enumeration
|
||||||
if (prefer_vertex_stores && supported_features.vertexPipelineStoresAndAtomics) {
|
// order (typically the integrated GPU first on laptops).
|
||||||
++score;
|
VkPhysicalDeviceProperties physical_device_properties;
|
||||||
}
|
ifn.vkGetPhysicalDeviceProperties(physical_device, &physical_device_properties);
|
||||||
if (prefer_fill_mode_non_solid && supported_features.fillModeNonSolid) {
|
if (physical_device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
|
||||||
++score;
|
score += 2;
|
||||||
|
} else if (physical_device_properties.deviceType ==
|
||||||
|
VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
|
||||||
|
score += 1;
|
||||||
}
|
}
|
||||||
scored_devices.push_back({physical_device, score});
|
scored_devices.push_back({physical_device, score});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue