diff --git a/src/dxvk/dxvk_device_filter.cpp b/src/dxvk/dxvk_device_filter.cpp new file mode 100644 index 00000000..251cabfd --- /dev/null +++ b/src/dxvk/dxvk_device_filter.cpp @@ -0,0 +1,30 @@ +#include "dxvk_device_filter.h" + +namespace dxvk { + + DxvkDeviceFilter::DxvkDeviceFilter() { + m_matchDeviceName = env::getEnvVar(L"DXVK_FILTER_DEVICE_NAME"); + + if (m_matchDeviceName.size() != 0) + m_flags.set(DxvkDeviceFilterFlag::MatchDeviceName); + } + + + DxvkDeviceFilter::~DxvkDeviceFilter() { + + } + + + bool DxvkDeviceFilter::testAdapter( + const Rc& adapter) const { + const auto& deviceProps = adapter->deviceProperties(); + + if (m_flags.test(DxvkDeviceFilterFlag::MatchDeviceName)) { + if (deviceProps.deviceName != m_matchDeviceName) + return false; + } + + return true; + } + +} diff --git a/src/dxvk/dxvk_device_filter.h b/src/dxvk/dxvk_device_filter.h new file mode 100644 index 00000000..b22da7e8 --- /dev/null +++ b/src/dxvk/dxvk_device_filter.h @@ -0,0 +1,53 @@ +#pragma once + +#include "dxvk_adapter.h" + +namespace dxvk { + + /** + * \brief Device filter flags + * + * The device filter flags specify which device + * properties are considered when testing adapters. + * If no flags are set, all devices pass the test. + */ + enum class DxvkDeviceFilterFlag { + MatchDeviceName = 0, + }; + + using DxvkDeviceFilterFlags = Flags; + + + /** + * \brief DXVK device filter + * + * Used to select specific Vulkan devices to use + * with DXVK. This may be useful for games which + * do not offer an option to select the correct + * device. + */ + class DxvkDeviceFilter { + + public: + + DxvkDeviceFilter(); + ~DxvkDeviceFilter(); + + /** + * \brief Tests an adapter + * + * \param [in] adapter Adapter handle + * \returns \c true if the test passes + */ + bool testAdapter( + const Rc& adapter) const; + + private: + + DxvkDeviceFilterFlags m_flags; + + std::string m_matchDeviceName; + + }; + +} \ No newline at end of file diff --git a/src/dxvk/dxvk_instance.cpp b/src/dxvk/dxvk_instance.cpp index 692829e3..f588f7d7 100644 --- a/src/dxvk/dxvk_instance.cpp +++ b/src/dxvk/dxvk_instance.cpp @@ -88,6 +88,8 @@ namespace dxvk { std::vector> DxvkInstance::queryAdapters() { + DxvkDeviceFilter filter; + uint32_t numAdapters = 0; if (m_vki->vkEnumeratePhysicalDevices(m_vki->instance(), &numAdapters, nullptr) != VK_SUCCESS) throw DxvkError("DxvkInstance::enumAdapters: Failed to enumerate adapters"); @@ -97,8 +99,12 @@ namespace dxvk { throw DxvkError("DxvkInstance::enumAdapters: Failed to enumerate adapters"); std::vector> result; - for (uint32_t i = 0; i < numAdapters; i++) - result.push_back(new DxvkAdapter(this, adapters[i])); + for (uint32_t i = 0; i < numAdapters; i++) { + Rc adapter = new DxvkAdapter(this, adapters[i]); + + if (filter.testAdapter(adapter)) + result.push_back(adapter); + } std::sort(result.begin(), result.end(), [this] (const Rc& a, const Rc& b) -> bool { @@ -106,6 +112,11 @@ namespace dxvk { && b->deviceProperties().deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU; }); + if (result.size() == 0) { + Logger::warn("DXVK: No adapters found. Please check your " + "device filter settings and Vulkan setup."); + } + return result; } diff --git a/src/dxvk/dxvk_instance.h b/src/dxvk/dxvk_instance.h index d2b32426..1c84aa44 100644 --- a/src/dxvk/dxvk_instance.h +++ b/src/dxvk/dxvk_instance.h @@ -4,6 +4,7 @@ #include "dxvk_adapter.h" #include "dxvk_device.h" +#include "dxvk_device_filter.h" #include "dxvk_openvr.h" namespace dxvk { diff --git a/src/dxvk/meson.build b/src/dxvk/meson.build index 5eef2f1b..8edb1179 100644 --- a/src/dxvk/meson.build +++ b/src/dxvk/meson.build @@ -41,6 +41,7 @@ dxvk_src = files([ 'dxvk_data.cpp', 'dxvk_descriptor.cpp', 'dxvk_device.cpp', + 'dxvk_device_filter.cpp', 'dxvk_extensions.cpp', 'dxvk_event.cpp', 'dxvk_event_tracker.cpp',