aboutsummaryrefslogtreecommitdiff
path: root/src/layer.cc
diff options
context:
space:
mode:
authorNicolas James <nj3ahxac@gmail.com>2026-03-24 11:00:30 +1100
committerNicolas James <nj3ahxac@gmail.com>2026-03-24 11:00:30 +1100
commite270ee282a776956d666230dc924941c50b1ac65 (patch)
tree25381ddebf43bf80d9288d872dc77a248449b0a0 /src/layer.cc
parent09f27da54e12343b8c639186b6b2c61253f2a99a (diff)
Add nvidia spoofing for GetPhysicalDeviceSurfaceCapabilities2KHR, don't advertise AntiLag when doing so
Diffstat (limited to 'src/layer.cc')
-rw-r--r--src/layer.cc78
1 files changed, 74 insertions, 4 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{