Separate out vulkan from low latency

This commit is contained in:
FakeMichau
2025-06-13 01:31:35 +02:00
parent 84d606de70
commit 3bc4e9887f
5 changed files with 283 additions and 262 deletions
@@ -0,0 +1,87 @@
#include "low_latency.h"
// private
void LowLatency::update_effective_fg_state() {
if (!currently_active_tech)
return;
if (forced_fg.has_value())
currently_active_tech->set_effective_fg_state(forced_fg.value());
else
currently_active_tech->set_effective_fg_state(fg);
}
void LowLatency::update_enabled_override() {
if (!currently_active_tech)
return;
currently_active_tech->set_low_latency_override(Config::get().get_force_reflex());
}
std::string LowLatency::marker_to_name(uint32_t marker) {
switch (marker) {
case SIMULATION_START:
return "SIMULATION_START";
break;
case SIMULATION_END:
return "SIMULATION_END";
break;
case RENDERSUBMIT_START:
return "RENDERSUBMIT_START";
break;
case RENDERSUBMIT_END:
return "RENDERSUBMIT_END";
break;
case PRESENT_START:
return "PRESENT_START";
break;
case PRESENT_END:
return "PRESENT_END";
break;
case INPUT_SAMPLE:
return "INPUT_SAMPLE";
break;
case TRIGGER_FLASH:
return "TRIGGER_FLASH";
break;
case PC_LATENCY_PING:
return "PC_LATENCY_PING";
break;
case OUT_OF_BAND_RENDERSUBMIT_START:
return "OUT_OF_BAND_RENDERSUBMIT_START";
break;
case OUT_OF_BAND_RENDERSUBMIT_END:
return "OUT_OF_BAND_RENDERSUBMIT_END";
break;
case OUT_OF_BAND_PRESENT_START:
return "OUT_OF_BAND_PRESENT_START";
break;
case OUT_OF_BAND_PRESENT_END:
return "OUT_OF_BAND_PRESENT_END";
break;
}
return "Unknown";
}
// public
bool LowLatency::deinit_current_tech() {
if (currently_active_tech) {
currently_active_tech->deinit();
delete currently_active_tech;
currently_active_tech = nullptr;
return true;
}
return false;
}
void LowLatency::get_low_latency_context(void** low_latency_context, Mode* low_latency_tech) {
if (!currently_active_tech || !low_latency_context)
return;
*low_latency_context = currently_active_tech->get_tech_context();
*low_latency_tech = currently_active_tech->get_mode();
}
+13 -8
View File
@@ -38,14 +38,20 @@ private:
FrameReport frame_reports[64]{};
std::optional<bool> forced_fg;
bool fg;
bool update_low_latency_tech(IUnknown* pDevice);
void update_effective_fg_state();
void update_enabled_override();
std::string marker_to_name(uint32_t marker);
// D3D
bool update_low_latency_tech(IUnknown* pDevice);
void get_latency_result(NV_LATENCY_RESULT_PARAMS* pGetLatencyParams);
void add_marker_to_report(NV_LATENCY_MARKER_PARAMS *pSetLatencyMarkerParams);
// Vulkan
bool update_low_latency_tech(HANDLE vkDevice);
void get_latency_result(NV_VULKAN_LATENCY_RESULT_PARAMS *pGetLatencyParams);
void add_marker_to_report(NV_VULKAN_LATENCY_MARKER_PARAMS *pSetLatencyMarkerParams);
inline std::string marker_to_name(uint32_t marker);
public:
LowLatency() = default;
@@ -56,19 +62,18 @@ public:
void set_fg_type(bool interpolated, uint64_t frame_id) { currently_active_tech->set_fg_type(interpolated, frame_id); }
void get_low_latency_context(void** low_latency_context, Mode* low_latency_tech);
NvAPI_Status GetSleepStatus(IUnknown* pDevice, NV_GET_SLEEP_STATUS_PARAMS* pGetSleepStatusParams);
NvAPI_Status SetSleepMode(IUnknown* pDevice, NV_SET_SLEEP_MODE_PARAMS* pSetSleepModeParams);
// D3D
NvAPI_Status Sleep(IUnknown* pDevice);
NvAPI_Status SetSleepMode(IUnknown* pDevice, NV_SET_SLEEP_MODE_PARAMS* pSetSleepModeParams);
NvAPI_Status GetSleepStatus(IUnknown* pDevice, NV_GET_SLEEP_STATUS_PARAMS* pGetSleepStatusParams);
NvAPI_Status SetLatencyMarker(IUnknown *pDev, NV_LATENCY_MARKER_PARAMS *pSetLatencyMarkerParams);
NvAPI_Status SetAsyncFrameMarker(ID3D12CommandQueue *pCommandQueue, NV_ASYNC_FRAME_MARKER_PARAMS *pSetAsyncFrameMarkerParams);
NvAPI_Status GetLatency(IUnknown* pDev, NV_LATENCY_RESULT_PARAMS* pGetLatencyParams);
// Vulkan
bool update_low_latency_tech(HANDLE vkDevice);
void get_latency_result(NV_VULKAN_LATENCY_RESULT_PARAMS *pGetLatencyParams);
NvAPI_Status SetLatencyMarker(HANDLE vkDevice, NV_VULKAN_LATENCY_MARKER_PARAMS *pSetLatencyMarkerParams);
NvAPI_Status Sleep(HANDLE vkDevice);
NvAPI_Status SetSleepMode(HANDLE vkDevice, NV_VULKAN_SET_SLEEP_MODE_PARAMS* pSetSleepModeParams);
NvAPI_Status GetSleepStatus(HANDLE vkDevice, NV_VULKAN_GET_SLEEP_STATUS_PARAMS* pGetSleepStatusParams);
NvAPI_Status SetLatencyMarker(HANDLE vkDevice, NV_VULKAN_LATENCY_MARKER_PARAMS *pSetLatencyMarkerParams);
NvAPI_Status GetLatency(HANDLE vkDevice, NV_VULKAN_LATENCY_RESULT_PARAMS* pGetLatencyParams);
};
+15 -254
View File
@@ -1,25 +1,13 @@
#include "low_latency.h"
#include "low_latency_tech/ll_antilag2.h"
#include "low_latency_tech/ll_antilag_vk.h"
#include "low_latency_tech/ll_latencyflex.h"
#include "low_latency_tech/ll_xell.h"
#include "log.h"
#include "config.h"
bool LowLatency::deinit_current_tech() {
if (currently_active_tech) {
currently_active_tech->deinit();
delete currently_active_tech;
currently_active_tech = nullptr;
return true;
}
return false;
}
// private
bool LowLatency::update_low_latency_tech(IUnknown* pDevice) {
if (!currently_active_tech) {
if (!Config::get().get_force_latencyflex()) {
@@ -64,57 +52,10 @@ bool LowLatency::update_low_latency_tech(IUnknown* pDevice) {
return true;
}
bool LowLatency::update_low_latency_tech(HANDLE vkDevice) {
if (!currently_active_tech) {
if (!Config::get().get_force_latencyflex()) {
currently_active_tech = new AntiLagVk();
if (currently_active_tech->init(nullptr)) {
spdlog::info("LowLatency algo: AntiLag Vulkan");
return true;
}
delete currently_active_tech;
}
currently_active_tech = new LatencyFlex();
if (currently_active_tech->init(nullptr)) {
spdlog::info("LowLatency algo: LatencyFlex");
return true;
}
void LowLatency::get_latency_result(NV_LATENCY_RESULT_PARAMS* pGetLatencyParams) {
for (auto i = 0; i < 64; i++) {
memcpy(&pGetLatencyParams->frameReport[i], &frame_reports[i], sizeof(frame_reports[i]));
}
static bool last_force_latencyflex = Config::get().get_force_latencyflex();
bool force_latencyflex = Config::get().get_force_latencyflex();
bool change_detected = last_force_latencyflex != force_latencyflex;
last_force_latencyflex = force_latencyflex;
if (change_detected) {
if (deinit_current_tech()) {
return update_low_latency_tech((HANDLE) nullptr); // call back to reinit
} else {
spdlog::error("Couldn't deinitialize low latency tech");
return false;
}
}
return true;
}
void LowLatency::update_effective_fg_state() {
if (!currently_active_tech)
return;
if (forced_fg.has_value())
currently_active_tech->set_effective_fg_state(forced_fg.value());
else
currently_active_tech->set_effective_fg_state(fg);
}
void LowLatency::update_enabled_override() {
if (!currently_active_tech)
return;
currently_active_tech->set_low_latency_override(Config::get().get_force_reflex());
}
void LowLatency::add_marker_to_report(NV_LATENCY_MARKER_PARAMS* pSetLatencyMarkerParams) {
@@ -160,142 +101,12 @@ void LowLatency::add_marker_to_report(NV_LATENCY_MARKER_PARAMS* pSetLatencyMarke
}
}
void LowLatency::add_marker_to_report(NV_VULKAN_LATENCY_MARKER_PARAMS* pSetLatencyMarkerParams) {
auto current_timestamp = get_timestamp() / 1000;
static auto last_sim_start = current_timestamp;
static auto _2nd_last_sim_start = current_timestamp;
auto current_report = &frame_reports[pSetLatencyMarkerParams->frameID % 64];
current_report->frameID = pSetLatencyMarkerParams->frameID;
current_report->gpuFrameTimeUs = (uint32_t)(last_sim_start - _2nd_last_sim_start);
current_report->gpuActiveRenderTimeUs = 100;
current_report->driverStartTime = current_timestamp;
current_report->driverEndTime = current_timestamp + 100;
current_report->gpuRenderStartTime = current_timestamp;
current_report->gpuRenderEndTime = current_timestamp + 100;
current_report->osRenderQueueStartTime = current_timestamp;
current_report->osRenderQueueEndTime = current_timestamp + 100;
switch (pSetLatencyMarkerParams->markerType) {
case VULKAN_SIMULATION_START:
_2nd_last_sim_start = last_sim_start;
last_sim_start = get_timestamp() / 1000;
current_report->simStartTime = last_sim_start;
break;
case VULKAN_SIMULATION_END:
current_report->simEndTime = get_timestamp() / 1000;
break;
case VULKAN_RENDERSUBMIT_START:
current_report->renderSubmitStartTime = get_timestamp() / 1000;
break;
case VULKAN_RENDERSUBMIT_END:
current_report->renderSubmitEndTime = get_timestamp() / 1000;
break;
case VULKAN_PRESENT_START:
current_report->presentStartTime = get_timestamp() / 1000;
break;
case VULKAN_PRESENT_END:
current_report->presentEndTime = get_timestamp() / 1000;
break;
case VULKAN_INPUT_SAMPLE:
current_report->inputSampleTime = get_timestamp() / 1000;
break;
default:
break;
}
}
void LowLatency::get_latency_result(NV_LATENCY_RESULT_PARAMS* pGetLatencyParams) {
for (auto i = 0; i < 64; i++) {
memcpy(&pGetLatencyParams->frameReport[i], &frame_reports[i], sizeof(frame_reports[i]));
}
}
void LowLatency::get_latency_result(NV_VULKAN_LATENCY_RESULT_PARAMS* pGetLatencyParams) {
for (auto i = 0; i < 64; i++) {
// some data is sent into rsvd
memcpy(&pGetLatencyParams->frameReport[i], &frame_reports[i], sizeof(frame_reports[i]));
}
}
void LowLatency::get_low_latency_context(void** low_latency_context, Mode* low_latency_tech) {
if (!currently_active_tech || !low_latency_context)
return;
*low_latency_context = currently_active_tech->get_tech_context();
*low_latency_tech = currently_active_tech->get_mode();
}
std::string LowLatency::marker_to_name(uint32_t marker) {
switch (marker) {
case SIMULATION_START:
return "SIMULATION_START";
break;
case SIMULATION_END:
return "SIMULATION_END";
break;
case RENDERSUBMIT_START:
return "RENDERSUBMIT_START";
break;
case RENDERSUBMIT_END:
return "RENDERSUBMIT_END";
break;
case PRESENT_START:
return "PRESENT_START";
break;
case PRESENT_END:
return "PRESENT_END";
break;
case INPUT_SAMPLE:
return "INPUT_SAMPLE";
break;
case TRIGGER_FLASH:
return "TRIGGER_FLASH";
break;
case PC_LATENCY_PING:
return "PC_LATENCY_PING";
break;
case OUT_OF_BAND_RENDERSUBMIT_START:
return "OUT_OF_BAND_RENDERSUBMIT_START";
break;
case OUT_OF_BAND_RENDERSUBMIT_END:
return "OUT_OF_BAND_RENDERSUBMIT_END";
break;
case OUT_OF_BAND_PRESENT_START:
return "OUT_OF_BAND_PRESENT_START";
break;
case OUT_OF_BAND_PRESENT_END:
return "OUT_OF_BAND_PRESENT_END";
break;
}
return "Unknown";
}
NvAPI_Status LowLatency::GetSleepStatus(IUnknown *pDevice, NV_GET_SLEEP_STATUS_PARAMS *pGetSleepStatusParams)
{
// public
NvAPI_Status LowLatency::Sleep(IUnknown* pDevice) {
if (!update_low_latency_tech(pDevice))
return ERROR();
SleepParams sleep_params{};
currently_active_tech->get_sleep_status(&sleep_params);
pGetSleepStatusParams->bLowLatencyMode = sleep_params.low_latency_enabled;
pGetSleepStatusParams->bFsVrr = sleep_params.fullscreen_vrr;
pGetSleepStatusParams->bCplVsyncOn = sleep_params.control_panel_vsync_override;
return OK();
}
NvAPI_Status LowLatency::GetSleepStatus(HANDLE vkDevice, NV_VULKAN_GET_SLEEP_STATUS_PARAMS* pGetSleepStatusParams)
{
if (!update_low_latency_tech(vkDevice))
return ERROR();
SleepParams sleep_params{};
currently_active_tech->get_sleep_status(&sleep_params);
pGetSleepStatusParams->bLowLatencyMode = sleep_params.low_latency_enabled;
currently_active_tech->sleep();
return OK();
}
@@ -316,36 +127,18 @@ NvAPI_Status LowLatency::SetSleepMode(IUnknown* pDevice, NV_SET_SLEEP_MODE_PARAM
return OK();
}
NvAPI_Status LowLatency::SetSleepMode(HANDLE vkDevice, NV_VULKAN_SET_SLEEP_MODE_PARAMS* pSetSleepModeParams) {
if (!update_low_latency_tech(vkDevice))
return ERROR();
SleepMode sleep_mode{};
sleep_mode.low_latency_enabled = pSetSleepModeParams->bLowLatencyMode;
sleep_mode.low_latency_boost = pSetSleepModeParams->bLowLatencyBoost;
sleep_mode.minimum_interval_us = pSetSleepModeParams->minimumIntervalUs;
sleep_mode.use_markers_to_optimize = true;
currently_active_tech->set_sleep_mode(&sleep_mode);
return OK();
}
NvAPI_Status LowLatency::Sleep(IUnknown* pDevice) {
NvAPI_Status LowLatency::GetSleepStatus(IUnknown *pDevice, NV_GET_SLEEP_STATUS_PARAMS *pGetSleepStatusParams)
{
if (!update_low_latency_tech(pDevice))
return ERROR();
currently_active_tech->sleep();
SleepParams sleep_params{};
return OK();
}
currently_active_tech->get_sleep_status(&sleep_params);
NvAPI_Status LowLatency::Sleep(HANDLE vkDevice) {
if (!update_low_latency_tech(vkDevice))
return ERROR();
currently_active_tech->sleep();
pGetSleepStatusParams->bLowLatencyMode = sleep_params.low_latency_enabled;
pGetSleepStatusParams->bFsVrr = sleep_params.fullscreen_vrr;
pGetSleepStatusParams->bCplVsyncOn = sleep_params.control_panel_vsync_override;
return OK();
}
@@ -372,29 +165,6 @@ NvAPI_Status LowLatency::SetLatencyMarker(IUnknown* pDev, NV_LATENCY_MARKER_PARA
return NVAPI_OK;
}
NvAPI_Status LowLatency::SetLatencyMarker(HANDLE vkDevice, NV_VULKAN_LATENCY_MARKER_PARAMS* pSetLatencyMarkerParams) {
if (!update_low_latency_tech(vkDevice))
return ERROR();
update_effective_fg_state();
update_enabled_override();
add_marker_to_report(pSetLatencyMarkerParams);
MarkerParams marker_params{};
marker_params.frame_id = pSetLatencyMarkerParams->frameID;
marker_params.marker_type = (MarkerType) pSetLatencyMarkerParams->markerType; // requires enums to match
// This cast is not ideal as it needs to be cast to VkDevice while knowing it's vulkan
currently_active_tech->set_marker((IUnknown*)vkDevice, &marker_params);
spdlog::trace("{}: {}", marker_to_name(pSetLatencyMarkerParams->markerType), pSetLatencyMarkerParams->frameID);
return NVAPI_OK;
}
NvAPI_Status LowLatency::SetAsyncFrameMarker(ID3D12CommandQueue* pCommandQueue, NV_ASYNC_FRAME_MARKER_PARAMS* pSetAsyncFrameMarkerParams) {
if (!currently_active_tech) // can't init using ID3D12CommandQueue, can only check if available
return ERROR();
@@ -442,12 +212,3 @@ NvAPI_Status LowLatency::GetLatency(IUnknown* pDev, NV_LATENCY_RESULT_PARAMS* pG
return OK();
}
NvAPI_Status LowLatency::GetLatency(HANDLE vkDevice, NV_VULKAN_LATENCY_RESULT_PARAMS* pGetLatencyParams) {
if (!update_low_latency_tech(vkDevice))
return ERROR();
get_latency_result(pGetLatencyParams);
return OK();
}
@@ -0,0 +1,166 @@
#include "low_latency.h"
#include "low_latency_tech/ll_antilag_vk.h"
#include "low_latency_tech/ll_latencyflex.h"
#include "log.h"
#include "config.h"
// private
bool LowLatency::update_low_latency_tech(HANDLE vkDevice) {
if (!currently_active_tech) {
if (!Config::get().get_force_latencyflex()) {
currently_active_tech = new AntiLagVk();
if (currently_active_tech->init(nullptr)) {
spdlog::info("LowLatency algo: AntiLag Vulkan");
return true;
}
delete currently_active_tech;
}
currently_active_tech = new LatencyFlex();
if (currently_active_tech->init(nullptr)) {
spdlog::info("LowLatency algo: LatencyFlex");
return true;
}
}
static bool last_force_latencyflex = Config::get().get_force_latencyflex();
bool force_latencyflex = Config::get().get_force_latencyflex();
bool change_detected = last_force_latencyflex != force_latencyflex;
last_force_latencyflex = force_latencyflex;
if (change_detected) {
if (deinit_current_tech()) {
return update_low_latency_tech((HANDLE) nullptr); // call back to reinit
} else {
spdlog::error("Couldn't deinitialize low latency tech");
return false;
}
}
return true;
}
void LowLatency::get_latency_result(NV_VULKAN_LATENCY_RESULT_PARAMS* pGetLatencyParams) {
for (auto i = 0; i < 64; i++) {
// some data is sent into rsvd
memcpy(&pGetLatencyParams->frameReport[i], &frame_reports[i], sizeof(frame_reports[i]));
}
}
void LowLatency::add_marker_to_report(NV_VULKAN_LATENCY_MARKER_PARAMS* pSetLatencyMarkerParams) {
auto current_timestamp = get_timestamp() / 1000;
static auto last_sim_start = current_timestamp;
static auto _2nd_last_sim_start = current_timestamp;
auto current_report = &frame_reports[pSetLatencyMarkerParams->frameID % 64];
current_report->frameID = pSetLatencyMarkerParams->frameID;
current_report->gpuFrameTimeUs = (uint32_t)(last_sim_start - _2nd_last_sim_start);
current_report->gpuActiveRenderTimeUs = 100;
current_report->driverStartTime = current_timestamp;
current_report->driverEndTime = current_timestamp + 100;
current_report->gpuRenderStartTime = current_timestamp;
current_report->gpuRenderEndTime = current_timestamp + 100;
current_report->osRenderQueueStartTime = current_timestamp;
current_report->osRenderQueueEndTime = current_timestamp + 100;
switch (pSetLatencyMarkerParams->markerType) {
case VULKAN_SIMULATION_START:
_2nd_last_sim_start = last_sim_start;
last_sim_start = get_timestamp() / 1000;
current_report->simStartTime = last_sim_start;
break;
case VULKAN_SIMULATION_END:
current_report->simEndTime = get_timestamp() / 1000;
break;
case VULKAN_RENDERSUBMIT_START:
current_report->renderSubmitStartTime = get_timestamp() / 1000;
break;
case VULKAN_RENDERSUBMIT_END:
current_report->renderSubmitEndTime = get_timestamp() / 1000;
break;
case VULKAN_PRESENT_START:
current_report->presentStartTime = get_timestamp() / 1000;
break;
case VULKAN_PRESENT_END:
current_report->presentEndTime = get_timestamp() / 1000;
break;
case VULKAN_INPUT_SAMPLE:
current_report->inputSampleTime = get_timestamp() / 1000;
break;
default:
break;
}
}
// public
NvAPI_Status LowLatency::Sleep(HANDLE vkDevice) {
if (!update_low_latency_tech(vkDevice))
return ERROR();
currently_active_tech->sleep();
return OK();
}
NvAPI_Status LowLatency::SetSleepMode(HANDLE vkDevice, NV_VULKAN_SET_SLEEP_MODE_PARAMS* pSetSleepModeParams) {
if (!update_low_latency_tech(vkDevice))
return ERROR();
SleepMode sleep_mode{};
sleep_mode.low_latency_enabled = pSetSleepModeParams->bLowLatencyMode;
sleep_mode.low_latency_boost = pSetSleepModeParams->bLowLatencyBoost;
sleep_mode.minimum_interval_us = pSetSleepModeParams->minimumIntervalUs;
sleep_mode.use_markers_to_optimize = true;
currently_active_tech->set_sleep_mode(&sleep_mode);
return OK();
}
NvAPI_Status LowLatency::GetSleepStatus(HANDLE vkDevice, NV_VULKAN_GET_SLEEP_STATUS_PARAMS* pGetSleepStatusParams)
{
if (!update_low_latency_tech(vkDevice))
return ERROR();
SleepParams sleep_params{};
currently_active_tech->get_sleep_status(&sleep_params);
pGetSleepStatusParams->bLowLatencyMode = sleep_params.low_latency_enabled;
return OK();
}
NvAPI_Status LowLatency::SetLatencyMarker(HANDLE vkDevice, NV_VULKAN_LATENCY_MARKER_PARAMS* pSetLatencyMarkerParams) {
if (!update_low_latency_tech(vkDevice))
return ERROR();
update_effective_fg_state();
update_enabled_override();
add_marker_to_report(pSetLatencyMarkerParams);
MarkerParams marker_params{};
marker_params.frame_id = pSetLatencyMarkerParams->frameID;
marker_params.marker_type = (MarkerType) pSetLatencyMarkerParams->markerType; // requires enums to match
// This cast is not ideal as it needs to be cast to VkDevice while knowing it's vulkan
currently_active_tech->set_marker((IUnknown*)vkDevice, &marker_params);
spdlog::trace("{}: {}", marker_to_name(pSetLatencyMarkerParams->markerType), pSetLatencyMarkerParams->frameID);
return NVAPI_OK;
}
NvAPI_Status LowLatency::GetLatency(HANDLE vkDevice, NV_VULKAN_LATENCY_RESULT_PARAMS* pGetLatencyParams) {
if (!update_low_latency_tech(vkDevice))
return ERROR();
get_latency_result(pGetLatencyParams);
return OK();
}
+2
View File
@@ -2,6 +2,8 @@ src = files([
'main.cpp',
'fakenvapi.cpp',
'low_latency.cpp',
'low_latency_d3d.cpp',
'low_latency_vk.cpp',
'low_latency_tech/ll_antilag2.cpp',
'low_latency_tech/ll_antilag_vk.cpp',
'low_latency_tech/ll_xell.cpp',