diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/layer.cc | 78 | ||||
| -rw-r--r-- | src/layer_context.cc | 11 | ||||
| -rw-r--r-- | src/layer_context.hh | 6 |
3 files changed, 87 insertions, 8 deletions
diff --git a/src/layer.cc b/src/layer.cc index 5ddae67..91d6a23 100644 --- a/src/layer.cc +++ b/src/layer.cc @@ -115,6 +115,7 @@ CreateInstance(const VkInstanceCreateInfo* pCreateInfo, INSTANCE_VTABLE_LOAD(EnumerateDeviceExtensionProperties); INSTANCE_VTABLE_LOAD(GetPhysicalDeviceQueueFamilyProperties2); INSTANCE_VTABLE_LOAD(GetPhysicalDeviceFeatures2); + INSTANCE_VTABLE_LOAD(GetPhysicalDeviceSurfaceCapabilities2KHR); #undef INSTANCE_VTABLE_LOAD const auto lock = std::scoped_lock{layer_context.mutex}; @@ -207,7 +208,8 @@ static VKAPI_ATTR VkResult VKAPI_CALL CreateDevice( // explicitly ask for the extension when it creates the device. const auto was_antilag_requested = - requested.contains(VK_AMD_ANTI_LAG_EXTENSION_NAME); + requested.contains(VK_AMD_ANTI_LAG_EXTENSION_NAME) || + requested.contains(VK_NV_LOW_LATENCY_2_EXTENSION_NAME); const auto context = layer_context.get_context(physical_device); if (!context->supports_required_extensions && was_antilag_requested) { @@ -575,10 +577,19 @@ static VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties( return VK_INCOMPLETE; // They gave us zero space to work with. } - pProperties[0] = - VkExtensionProperties{.extensionName = VK_AMD_ANTI_LAG_EXTENSION_NAME, - .specVersion = VK_AMD_ANTI_LAG_SPEC_VERSION}; + // If we're spoofing nvidia we want to provide their extension instead. + const auto extension_properties = [&]() -> VkExtensionProperties { + if (context->instance.layer.should_spoof_nvidia) { + return {.extensionName = VK_NV_LOW_LATENCY_2_EXTENSION_NAME, + .specVersion = VK_NV_LOW_LATENCY_2_SPEC_VERSION}; + } + return {.extensionName = VK_AMD_ANTI_LAG_EXTENSION_NAME, + .specVersion = VK_AMD_ANTI_LAG_SPEC_VERSION}; + }(); + + pProperties[0] = extension_properties; count = 1; + return VK_SUCCESS; } @@ -590,6 +601,13 @@ static VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceFeatures2( vtable.GetPhysicalDeviceFeatures2(physical_device, pFeatures); + // Don't provide AntiLag if we're trying to spoof nvidia. + // Nvidia uses VkSurfaceCapabilities2KHR to determine if a surface + // is capable of reflex instead of AMD's physical device switch found here. + if (context->instance.layer.should_spoof_nvidia) { + return; + } + const auto feature = find_next<VkPhysicalDeviceAntiLagFeaturesAMD>( pFeatures, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ANTI_LAG_FEATURES_AMD); @@ -603,6 +621,55 @@ static VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceFeatures2KHR( return low_latency::GetPhysicalDeviceFeatures2(physical_device, pFeatures); } +static VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceSurfaceCapabilities2KHR( + VkPhysicalDevice physical_device, + const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, + VkSurfaceCapabilities2KHR* pSurfaceCapabilities) { + + const auto context = layer_context.get_context(physical_device); + const auto& vtable = context->instance.vtable; + + vtable.GetPhysicalDeviceSurfaceCapabilities2KHR( + physical_device, pSurfaceInfo, pSurfaceCapabilities); + + // Don't do this unless we're spoofing nvidia. + if (!context->instance.layer.should_spoof_nvidia) { + return; + } + + const auto lsc = find_next<VkLatencySurfaceCapabilitiesNV>( + pSurfaceCapabilities, + VK_STRUCTURE_TYPE_LATENCY_SURFACE_CAPABILITIES_NV); + + if (!lsc) { + return; + } + + // I kind of eyeballed these! + const auto supported_modes = std::vector<VkPresentModeKHR>{ + VK_PRESENT_MODE_IMMEDIATE_KHR, + VK_PRESENT_MODE_MAILBOX_KHR, + VK_PRESENT_MODE_FIFO_KHR, + }; + const auto num_supported_modes = + static_cast<std::uint32_t>(std::size(supported_modes)); + + // They're asking how many we want to return. + if (!lsc->pPresentModes) { + lsc->presentModeCount = static_cast<std::uint32_t>(num_supported_modes); + return; + } + + // Finally we can write what surfaces are capable. + const auto num_to_write = + std::min(lsc->presentModeCount, num_supported_modes); + + std::ranges::copy_n(std::begin(supported_modes), num_to_write, + lsc->pPresentModes); + + lsc->presentModeCount = num_to_write; +} + static VKAPI_ATTR void VKAPI_CALL AntiLagUpdateAMD(VkDevice device, const VkAntiLagDataAMD* pData) { const auto context = layer_context.get_context(device); @@ -665,6 +732,9 @@ static const auto instance_functions = func_map_t{ low_latency::GetPhysicalDeviceFeatures2), HOOK_ENTRY("vkGetPhysicalDeviceFeatures2KHR", low_latency::GetPhysicalDeviceFeatures2KHR), + + HOOK_ENTRY("vkGetPhysicalDeviceSurfaceCapabilities2KHR", + low_latency::GetPhysicalDeviceSurfaceCapabilities2KHR), }; static const auto device_functions = func_map_t{ diff --git a/src/layer_context.cc b/src/layer_context.cc index 28a94b5..4699202 100644 --- a/src/layer_context.cc +++ b/src/layer_context.cc @@ -4,12 +4,15 @@ #include <string_view> namespace low_latency { - + LayerContext::LayerContext() { - this->is_antilag_1_enabled = []() -> auto { - const auto env = std::getenv(LayerContext::SLEEP_AFTER_PRESENT_ENV); + const auto parse_bool_env = [](const auto& name) -> bool { + const auto env = std::getenv(name); return env && std::string_view{env} == "1"; - }(); + }; + + this->is_antilag_1_enabled = parse_bool_env(SLEEP_AFTER_PRESENT_ENV); + this->should_spoof_nvidia = parse_bool_env(SPOOF_NVIDIA_ENV); } LayerContext::~LayerContext() {} diff --git a/src/layer_context.hh b/src/layer_context.hh index 316d540..da13dc6 100644 --- a/src/layer_context.hh +++ b/src/layer_context.hh @@ -53,11 +53,17 @@ class LayerContext final : public Context { static constexpr auto SLEEP_AFTER_PRESENT_ENV = "LOW_LATENCY_LAYER_SLEEP_AFTER_PRESENT"; + // If this is not null and set to exactly "1", then VK_NV_LOW_LATENCY2 + // should be provided instead of VK_AMD_anti_lag. + static constexpr auto SPOOF_NVIDIA_ENV = + "LOW_LATENCY_LAYER_SPOOF_NV_LOWLATENCY2"; + public: std::mutex mutex; std::unordered_map<void*, std::shared_ptr<Context>> contexts; bool is_antilag_1_enabled = false; + bool should_spoof_nvidia = false; public: LayerContext(); |
