WIP: Improve low latency output switching

This commit is contained in:
FakeMichau
2026-06-27 21:43:13 +02:00
parent c5206f6339
commit 0d490baab5
4 changed files with 95 additions and 56 deletions
+66 -49
View File
@@ -30,6 +30,60 @@ bool InputCommon::deinit_current_tech()
return false;
}
bool InputCommon::init_tech(IUnknown* pDevice, LowLatencyMode desiredMode)
{
if (!currently_active_tech.load() && delay_deinit == 0)
{
auto try_init = [&](auto low_latency_tech, const char* name) -> bool
{
if (low_latency_tech->init(pDevice))
{
LOG_INFO("LowLatency algo: {}", name);
currently_active_tech.store(std::move(low_latency_tech));
return true;
}
return false;
};
bool isInitialized = false;
switch (desiredMode)
{
case LowLatencyMode::XeLL:
isInitialized = try_init(std::make_shared<XeLL>(), "XeLL");
break;
case LowLatencyMode::AntiLag2:
isInitialized = try_init(std::make_shared<AntiLag2>(), "AntiLag2");
break;
case LowLatencyMode::Reflex:
// isInitialized = try_init(std::make_shared<Reflex>(), "Reflex");
break;
case LowLatencyMode::LatencyFlex:
isInitialized = try_init(std::make_shared<LatencyFlex>(), "LatencyFlex");
break;
default:
break;
}
if (!isInitialized && desiredMode != LowLatencyMode::LatencyFlex)
{
isInitialized = try_init(std::make_shared<LatencyFlex>(), "LatencyFlex (Fallback)");
if (isInitialized)
{
Config::Instance()->LowLatencyOutput.set_volatile_value(LowLatencyMode::LatencyFlex);
}
}
if (auto current_tech = currently_active_tech.load(); current_tech && isInitialized)
{
activeOutput = current_tech->get_mode();
current_tech->set_sleep_mode(&get_sleep_copy(activeInput)); // Restore any potential sleep mode
return true;
}
}
return false;
}
bool InputCommon::update_low_latency_tech(IUnknown* pDevice, std::optional<LowLatencyMode> mode)
{
if (avaliableInputs.count() == 0)
@@ -143,54 +197,17 @@ bool InputCommon::update_low_latency_tech(IUnknown* pDevice, std::optional<LowLa
desiredMode = LowLatencyMode::XeLL;
if (activeOutput == desiredMode)
{
delay_deinit = 0;
return true;
}
// Beyond this point activeOutput needs changing
if (!currently_active_tech.load() && delay_deinit == 0)
{
auto try_init = [&](auto low_latency_tech, const char* name) -> bool
{
if (low_latency_tech->init(pDevice))
{
LOG_INFO("LowLatency algo: {}", name);
currently_active_tech.store(std::move(low_latency_tech));
return true;
}
return false;
};
std::scoped_lock lock(create_tech_mutex);
bool isInitialized = false;
switch (desiredMode)
{
case LowLatencyMode::XeLL:
isInitialized = try_init(std::make_shared<XeLL>(), "XeLL");
break;
case LowLatencyMode::AntiLag2:
isInitialized = try_init(std::make_shared<AntiLag2>(), "AntiLag2");
break;
case LowLatencyMode::Reflex:
// isInitialized = try_init(std::make_shared<Reflex>(), "Reflex");
break;
case LowLatencyMode::LatencyFlex:
isInitialized = try_init(std::make_shared<LatencyFlex>(), "LatencyFlex");
break;
default:
break;
}
if (!isInitialized && desiredMode != LowLatencyMode::LatencyFlex)
{
isInitialized = try_init(std::make_shared<LatencyFlex>(), "LatencyFlex (Fallback)");
}
if (auto current_tech = currently_active_tech.load(); current_tech && isInitialized)
{
activeOutput = current_tech->get_mode();
current_tech->set_sleep_mode(&get_sleep_copy(activeInput)); // Restore any potential sleep mode
return true;
}
}
if (init_tech(pDevice, desiredMode))
return true;
auto try_reinit = [&]() -> bool
{
@@ -200,7 +217,7 @@ bool InputCommon::update_low_latency_tech(IUnknown* pDevice, std::optional<LowLa
return false;
}
return update_low_latency_tech(pDevice, desiredMode);
return init_tech(pDevice, desiredMode);
};
// WAR: FSR FG might still be using AntiLag 2, give Opti time to set AL2 context to null
@@ -306,7 +323,7 @@ InputResult InputCommon::sleep(const InputContext& inputContext, IUnknown* pDevi
if (auto current_tech = currently_active_tech.load())
current_tech->sleep(frame_id);
else
return InputResult::GenericError;
return InputResult::NoReadyOutput;
return InputResult::Ok;
}
@@ -348,7 +365,7 @@ InputResult InputCommon::set_marker(const InputContext& inputContext, IUnknown*
if (auto current_tech = currently_active_tech.load())
current_tech->set_marker(pDevice, marker_params);
else
return InputResult::GenericError;
return InputResult::NoReadyOutput;
LOG_TRACE_LOWLATENCY("{}: {}", magic_enum::enum_name(marker_params.marker_type), marker_params.frame_id);
@@ -383,7 +400,7 @@ InputResult InputCommon::set_async_marker(const InputContext& inputContext, ID3D
if (auto current_tech = currently_active_tech.load())
current_tech->set_async_marker(pCommandQueue, marker_params);
else
return InputResult::GenericError;
return InputResult::NoReadyOutput;
LOG_TRACE_LOWLATENCY("{}: {}", magic_enum::enum_name(marker_params.marker_type), marker_params.frame_id);
@@ -407,7 +424,7 @@ InputResult InputCommon::set_sleep_mode(const InputContext& inputContext, IUnkno
if (auto current_tech = currently_active_tech.load())
current_tech->set_sleep_mode(sleep_mode);
else
return InputResult::GenericError;
return InputResult::NoReadyOutput;
return InputResult::Ok;
}
@@ -429,7 +446,7 @@ InputResult InputCommon::get_sleep_status(const InputContext& inputContext, IUnk
if (auto current_tech = currently_active_tech.load())
current_tech->get_sleep_status(sleep_params);
else
return InputResult::GenericError;
return InputResult::NoReadyOutput;
return InputResult::Ok;
}
@@ -29,6 +29,7 @@ enum class InputResult : uint32_t
InvalidParameter,
LowLatencyUpdateFail,
NotEnoughReports,
NoReadyOutput,
GenericError,
};
@@ -46,6 +47,8 @@ struct TimingData
class InputCommon
{
inline static std::atomic<std::shared_ptr<LowLatencyTech>> currently_active_tech;
inline static std::mutex create_tech_mutex {};
inline static FrameReport frame_reports[FRAME_REPORTS_BUFFER_SIZE] {};
inline static std::atomic_uint64_t last_present_start_frame_id = 0;
inline static std::atomic_uint32_t delay_deinit = 0;
@@ -57,6 +60,7 @@ class InputCommon
inline static bool enabled = false;
static bool deinit_current_tech();
static bool init_tech(IUnknown* pDevice, LowLatencyMode desiredMode);
static bool update_low_latency_tech(IUnknown* pDevice, std::optional<LowLatencyMode> mode = std::nullopt);
static void add_marker_to_report(const MarkerParams& marker_params);
static void set_input_avaliable(LowLatencyInput input) { avaliableInputs.set(input); };
+24 -6
View File
@@ -20,7 +20,10 @@ NvAPI_Status InputReflex::D3D_SetSleepMode(IUnknown* pDev, NV_SET_SLEEP_MODE_PAR
else
LOG_ERROR("set_sleep_mode result: {}", magic_enum::enum_name(result));
return NVAPI_ERROR;
if (result == InputResult::NoReadyOutput)
return NVAPI_OK;
else
return NVAPI_ERROR;
}
NvAPI_Status InputReflex::D3D_GetSleepStatus(IUnknown* pDevice, NV_GET_SLEEP_STATUS_PARAMS* pGetSleepStatusParams)
@@ -49,7 +52,10 @@ NvAPI_Status InputReflex::D3D_GetSleepStatus(IUnknown* pDevice, NV_GET_SLEEP_STA
LOG_ERROR("get_sleep_status result: {}", magic_enum::enum_name(result));
}
return NVAPI_ERROR;
if (result == InputResult::NoReadyOutput)
return NVAPI_OK;
else
return NVAPI_ERROR;
}
NvAPI_Status InputReflex::D3D_Sleep(IUnknown* pDev)
@@ -64,7 +70,10 @@ NvAPI_Status InputReflex::D3D_Sleep(IUnknown* pDev)
else
LOG_ERROR("sleep result: {}", magic_enum::enum_name(result));
return NVAPI_ERROR;
if (result == InputResult::NoReadyOutput)
return NVAPI_OK;
else
return NVAPI_ERROR;
}
NvAPI_Status InputReflex::D3D_GetLatency(IUnknown* pDev, NV_LATENCY_RESULT_PARAMS* pGetLatencyParams)
@@ -81,7 +90,10 @@ NvAPI_Status InputReflex::D3D_GetLatency(IUnknown* pDev, NV_LATENCY_RESULT_PARAM
else
LOG_ERROR("get_latency result: {}", magic_enum::enum_name(result));
return NVAPI_ERROR;
if (result == InputResult::NoReadyOutput)
return NVAPI_OK;
else
return NVAPI_ERROR;
}
NvAPI_Status InputReflex::D3D_SetLatencyMarker(IUnknown* pDev, NV_LATENCY_MARKER_PARAMS* pSetLatencyMarkerParams)
@@ -101,7 +113,10 @@ NvAPI_Status InputReflex::D3D_SetLatencyMarker(IUnknown* pDev, NV_LATENCY_MARKER
else
LOG_ERROR("set_marker result: {}", magic_enum::enum_name(result));
return NVAPI_ERROR;
if (result == InputResult::NoReadyOutput)
return NVAPI_OK;
else
return NVAPI_ERROR;
}
NvAPI_Status InputReflex::D3D12_SetAsyncFrameMarker(ID3D12CommandQueue* pCommandQueue,
@@ -122,5 +137,8 @@ NvAPI_Status InputReflex::D3D12_SetAsyncFrameMarker(ID3D12CommandQueue* pCommand
else
LOG_ERROR("set_async_marker result: {}", magic_enum::enum_name(result));
return NVAPI_ERROR;
if (result == InputResult::NoReadyOutput)
return NVAPI_OK;
else
return NVAPI_ERROR;
}
@@ -61,7 +61,7 @@ bool XeLL::init(IUnknown* pDevice)
auto xellInputContext = (InputXeLL::xell_input_handle_t) XellHooks::getOurContext();
if (!xellInputContext)
return false;
return true;
auto resendResult = XELL_RESULT_SUCCESS;