mirror of
https://github.com/optiscaler/OptiScaler.git
synced 2026-08-25 07:36:45 +00:00
WIP: XeLL inputs cont.
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
#include "input_common.h"
|
||||
#include <low_latency/low_latency_tech/ll_xell.h>
|
||||
|
||||
// private
|
||||
bool InputCommon::update_low_latency_tech(IUnknown* pDevice, std::optional<LowLatencyMode> mode)
|
||||
{
|
||||
LowLatencyMode desiredMode = LowLatencyMode::None;
|
||||
@@ -24,7 +25,18 @@ bool InputCommon::update_low_latency_tech(IUnknown* pDevice, std::optional<LowLa
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Add system for selecting input
|
||||
if (activeInput == LowLatencyInput::XeLL)
|
||||
return true;
|
||||
activeInput = LowLatencyInput::XeLL;
|
||||
|
||||
// TODO: init correct currently_active_tech, desiredMode == None -> Auto
|
||||
auto new_tech_xell = std::make_shared<XeLL>();
|
||||
if (new_tech_xell->init(pDevice))
|
||||
{
|
||||
LOG_INFO("LowLatency algo: XeLL");
|
||||
currently_active_tech.store(std::move(new_tech_xell));
|
||||
}
|
||||
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
{
|
||||
@@ -36,19 +48,19 @@ bool InputCommon::update_low_latency_tech(IUnknown* pDevice, std::optional<LowLa
|
||||
return false;
|
||||
}
|
||||
|
||||
void InputCommon::add_marker_to_report(MarkerParams* marker_params)
|
||||
void InputCommon::add_marker_to_report(const MarkerParams& marker_params)
|
||||
{
|
||||
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[marker_params->frame_id % FRAME_REPORTS_BUFFER_SIZE];
|
||||
auto current_report = &frame_reports[marker_params.frame_id % FRAME_REPORTS_BUFFER_SIZE];
|
||||
|
||||
if (current_report->frameID != marker_params->frame_id)
|
||||
if (current_report->frameID != marker_params.frame_id)
|
||||
{
|
||||
*current_report = FrameReport {};
|
||||
}
|
||||
|
||||
current_report->frameID = marker_params->frame_id;
|
||||
current_report->frameID = marker_params.frame_id;
|
||||
current_report->gpuFrameTimeUs = (uint32_t) (last_sim_start - _2nd_last_sim_start);
|
||||
current_report->gpuActiveRenderTimeUs = 100;
|
||||
current_report->driverStartTime = current_timestamp;
|
||||
@@ -57,7 +69,7 @@ void InputCommon::add_marker_to_report(MarkerParams* marker_params)
|
||||
current_report->gpuRenderEndTime = current_timestamp + 100;
|
||||
current_report->osRenderQueueStartTime = current_timestamp;
|
||||
current_report->osRenderQueueEndTime = current_timestamp + 100;
|
||||
switch (marker_params->marker_type)
|
||||
switch (marker_params.marker_type)
|
||||
{
|
||||
case MarkerType::SIMULATION_START:
|
||||
_2nd_last_sim_start = last_sim_start;
|
||||
@@ -87,6 +99,7 @@ void InputCommon::add_marker_to_report(MarkerParams* marker_params)
|
||||
}
|
||||
}
|
||||
|
||||
// public
|
||||
InputResult InputCommon::set_low_latency_tech(IUnknown* pDevice, LowLatencyMode mode)
|
||||
{
|
||||
if (!update_low_latency_tech(pDevice, mode))
|
||||
@@ -95,11 +108,14 @@ InputResult InputCommon::set_low_latency_tech(IUnknown* pDevice, LowLatencyMode
|
||||
return InputResult::Ok;
|
||||
}
|
||||
|
||||
InputResult InputCommon::sleep(IUnknown* pDevice, const InputContext& inputContext, std::optional<uint32_t> frame_id)
|
||||
InputResult InputCommon::sleep(const InputContext& inputContext, IUnknown* pDevice, std::optional<uint32_t> frame_id)
|
||||
{
|
||||
if (!update_low_latency_tech(pDevice))
|
||||
return InputResult::LowLatencyUpdateFail;
|
||||
|
||||
if (inputContext.caller != activeInput)
|
||||
return InputResult::UsingDifferentInput;
|
||||
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
current_tech->sleep(frame_id);
|
||||
else
|
||||
@@ -108,20 +124,21 @@ InputResult InputCommon::sleep(IUnknown* pDevice, const InputContext& inputConte
|
||||
return InputResult::Ok;
|
||||
}
|
||||
|
||||
InputResult InputCommon::set_marker(const InputContext& inputContext, IUnknown* pDevice, MarkerParams* marker_params)
|
||||
InputResult InputCommon::set_marker(const InputContext& inputContext, IUnknown* pDevice,
|
||||
const MarkerParams& marker_params)
|
||||
{
|
||||
if (!update_low_latency_tech(pDevice))
|
||||
return InputResult::LowLatencyUpdateFail;
|
||||
|
||||
if (!marker_params)
|
||||
return InputResult::InvalidParameter;
|
||||
if (inputContext.caller != activeInput)
|
||||
return InputResult::UsingDifferentInput;
|
||||
|
||||
if (inputContext.markerMode == InputMarkerMode::NoMarkers)
|
||||
{
|
||||
return InputResult::InputNotSupported;
|
||||
}
|
||||
else if (inputContext.markerMode == InputMarkerMode::PresentStartOnly &&
|
||||
marker_params->marker_type != MarkerType::PRESENT_START)
|
||||
marker_params.marker_type != MarkerType::PRESENT_START)
|
||||
{
|
||||
return InputResult::InputNotSupported;
|
||||
}
|
||||
@@ -137,26 +154,26 @@ InputResult InputCommon::set_marker(const InputContext& inputContext, IUnknown*
|
||||
else
|
||||
return InputResult::GenericError;
|
||||
|
||||
LOG_TRACE_LOWLATENCY("{}: {}", magic_enum::enum_name(marker_params->marker_type), marker_params->frame_id);
|
||||
LOG_TRACE_LOWLATENCY("{}: {}", magic_enum::enum_name(marker_params.marker_type), marker_params.frame_id);
|
||||
|
||||
return InputResult::Ok;
|
||||
}
|
||||
|
||||
InputResult InputCommon::set_async_marker(const InputContext& inputContext, ID3D12CommandQueue* pCommandQueue,
|
||||
MarkerParams* marker_params)
|
||||
const MarkerParams& marker_params)
|
||||
{
|
||||
if (inputContext.caller != activeInput)
|
||||
return InputResult::UsingDifferentInput;
|
||||
|
||||
if (!currently_active_tech.load()) // can't init using ID3D12CommandQueue, can only check if available
|
||||
return InputResult::LowLatencyUpdateFail;
|
||||
|
||||
if (!marker_params)
|
||||
return InputResult::InvalidParameter;
|
||||
|
||||
if (inputContext.markerMode == InputMarkerMode::NoMarkers)
|
||||
{
|
||||
return InputResult::InputNotSupported;
|
||||
}
|
||||
else if (inputContext.markerMode == InputMarkerMode::PresentStartOnly &&
|
||||
marker_params->marker_type != MarkerType::OUT_OF_BAND_PRESENT_START)
|
||||
marker_params.marker_type != MarkerType::OUT_OF_BAND_PRESENT_START)
|
||||
{
|
||||
return InputResult::InputNotSupported;
|
||||
}
|
||||
@@ -169,7 +186,7 @@ InputResult InputCommon::set_async_marker(const InputContext& inputContext, ID3D
|
||||
else
|
||||
return InputResult::GenericError;
|
||||
|
||||
LOG_TRACE_LOWLATENCY("{}: {}", magic_enum::enum_name(marker_params->marker_type), marker_params->frame_id);
|
||||
LOG_TRACE_LOWLATENCY("{}: {}", magic_enum::enum_name(marker_params.marker_type), marker_params.frame_id);
|
||||
|
||||
return InputResult::Ok;
|
||||
}
|
||||
@@ -177,6 +194,17 @@ InputResult InputCommon::set_async_marker(const InputContext& inputContext, ID3D
|
||||
// TODO: impl
|
||||
InputResult InputCommon::set_sleep_mode(const InputContext& inputContext, IUnknown* pDevice, SleepMode* sleep_mode)
|
||||
{
|
||||
if (!update_low_latency_tech(pDevice))
|
||||
return InputResult::LowLatencyUpdateFail;
|
||||
|
||||
if (inputContext.caller != activeInput)
|
||||
return InputResult::UsingDifferentInput;
|
||||
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
current_tech->set_sleep_mode(sleep_mode);
|
||||
else
|
||||
return InputResult::GenericError;
|
||||
|
||||
return InputResult::Ok;
|
||||
}
|
||||
|
||||
@@ -184,11 +212,28 @@ InputResult InputCommon::set_sleep_mode(const InputContext& inputContext, IUnkno
|
||||
InputResult InputCommon::get_sleep_status(const InputContext& inputContext, IUnknown* pDevice,
|
||||
SleepParams* sleep_params)
|
||||
{
|
||||
if (!update_low_latency_tech(pDevice))
|
||||
return InputResult::LowLatencyUpdateFail;
|
||||
|
||||
if (inputContext.caller != activeInput)
|
||||
return InputResult::UsingDifferentInput;
|
||||
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
current_tech->get_sleep_status(sleep_params);
|
||||
else
|
||||
return InputResult::GenericError;
|
||||
|
||||
return InputResult::Ok;
|
||||
}
|
||||
|
||||
InputResult InputCommon::get_latency(const InputContext& inputContext, IUnknown* pDev, void* latency_params)
|
||||
{
|
||||
if (inputContext.caller != activeInput)
|
||||
return InputResult::UsingDifferentInput;
|
||||
|
||||
if (!update_low_latency_tech(pDev))
|
||||
return InputResult::LowLatencyUpdateFail;
|
||||
|
||||
if (!latency_params)
|
||||
return InputResult::InvalidParameter;
|
||||
|
||||
@@ -243,15 +288,21 @@ InputResult InputCommon::get_latency(const InputContext& inputContext, IUnknown*
|
||||
}
|
||||
else if (inputContext.caller == LowLatencyInput::XeLL)
|
||||
{
|
||||
if (activeOutput == LowLatencyMode::XeLL)
|
||||
{
|
||||
// TODO: passthrough call, if success return InputResult::Ok;
|
||||
// return InputResult::Ok;
|
||||
}
|
||||
|
||||
xell_frame_report_t* reports = (xell_frame_report_t*) latency_params;
|
||||
constexpr size_t reportCount = 64; // 64 reports, if the app allocated less then it's on them
|
||||
|
||||
if (activeOutput == LowLatencyMode::XeLL)
|
||||
{
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
{
|
||||
auto xell_tech = std::static_pointer_cast<XeLL>(current_tech);
|
||||
auto result = xell_tech->xellGetFramesReports(reports);
|
||||
|
||||
if (result == XELL_RESULT_SUCCESS)
|
||||
return InputResult::Ok;
|
||||
}
|
||||
}
|
||||
|
||||
// Hopefully not too slow
|
||||
// XeLL doesn't seem to make any guarantees about ordering so no sort needed
|
||||
for (auto i = 0; i < reportCount; i++)
|
||||
|
||||
@@ -10,38 +10,11 @@ enum class LowLatencyInput
|
||||
XeLL
|
||||
};
|
||||
|
||||
#define FRAME_REPORTS_BUFFER_SIZE 70
|
||||
#define NVAPI_BUFFER_SIZE 64
|
||||
|
||||
struct FrameReport
|
||||
{
|
||||
uint64_t frameID;
|
||||
uint64_t inputSampleTime;
|
||||
uint64_t simStartTime;
|
||||
uint64_t simEndTime;
|
||||
uint64_t renderSubmitStartTime;
|
||||
uint64_t renderSubmitEndTime;
|
||||
uint64_t presentStartTime;
|
||||
uint64_t presentEndTime;
|
||||
uint64_t driverStartTime;
|
||||
uint64_t driverEndTime;
|
||||
uint64_t osRenderQueueStartTime;
|
||||
uint64_t osRenderQueueEndTime;
|
||||
uint64_t gpuRenderStartTime;
|
||||
uint64_t gpuRenderEndTime;
|
||||
uint32_t gpuActiveRenderTimeUs;
|
||||
uint32_t gpuFrameTimeUs;
|
||||
uint64_t cameraConstructedTime;
|
||||
uint32_t crossAdapterCopyTimeUs;
|
||||
uint32_t aiFrameTimeUs;
|
||||
uint8_t rsvd[104];
|
||||
};
|
||||
|
||||
enum class InputMarkerMode
|
||||
{
|
||||
NoMarkers,
|
||||
PresentStartOnly,
|
||||
FullMarkers,
|
||||
FullMarkers, // TODO: add something about xell's partial async markers
|
||||
};
|
||||
|
||||
struct InputContext
|
||||
@@ -55,6 +28,7 @@ struct InputContext
|
||||
enum class InputResult : uint32_t
|
||||
{
|
||||
Ok,
|
||||
UsingDifferentInput,
|
||||
InputNotSupported,
|
||||
InvalidParameter,
|
||||
LowLatencyUpdateFail,
|
||||
@@ -71,17 +45,18 @@ class InputCommon
|
||||
inline static bool enabled = false;
|
||||
|
||||
static bool update_low_latency_tech(IUnknown* pDevice, std::optional<LowLatencyMode> mode = std::nullopt);
|
||||
static void add_marker_to_report(MarkerParams* marker_params);
|
||||
static void add_marker_to_report(const MarkerParams& marker_params);
|
||||
|
||||
public:
|
||||
static InputResult set_low_latency_tech(IUnknown* pDevice, LowLatencyMode mode);
|
||||
|
||||
// TODO: Ignore all calls that are not coming for the activeInput
|
||||
static InputResult sleep(IUnknown* pDevice, const InputContext& inputContext,
|
||||
static InputResult sleep(const InputContext& inputContext, IUnknown* pDevice,
|
||||
std::optional<uint32_t> frame_id = std::nullopt);
|
||||
static InputResult set_marker(const InputContext& inputContext, IUnknown* pDevice, MarkerParams* marker_params);
|
||||
static InputResult set_marker(const InputContext& inputContext, IUnknown* pDevice,
|
||||
const MarkerParams& marker_params);
|
||||
static InputResult set_async_marker(const InputContext& inputContext, ID3D12CommandQueue* pCommandQueue,
|
||||
MarkerParams* marker_params);
|
||||
const MarkerParams& marker_params);
|
||||
static InputResult set_sleep_mode(const InputContext& inputContext, IUnknown* pDevice, SleepMode* sleep_mode);
|
||||
static InputResult get_sleep_status(const InputContext& inputContext, IUnknown* pDevice, SleepParams* sleep_params);
|
||||
static InputResult
|
||||
|
||||
@@ -14,32 +14,125 @@ xell_result_t InputXeLL::DestroyContext(xell_input_handle_t context)
|
||||
}
|
||||
xell_result_t InputXeLL::SetSleepMode(xell_input_handle_t context, const xell_sleep_params_t* param)
|
||||
{
|
||||
// TODO: impl
|
||||
return XELL_RESULT_SUCCESS;
|
||||
if (!context)
|
||||
return XELL_RESULT_ERROR_INVALID_CONTEXT;
|
||||
|
||||
if (!param)
|
||||
return XELL_RESULT_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
SleepMode sleepMode {};
|
||||
sleepMode.low_latency_enabled = param->bLowLatencyMode;
|
||||
sleepMode.low_latency_boost = param->bLowLatencyBoost;
|
||||
sleepMode.minimum_interval_us = param->minimumIntervalUs;
|
||||
|
||||
// TODO: not fully filled out
|
||||
|
||||
auto result = InputCommon::set_sleep_mode(inputContext, context->device, &sleepMode);
|
||||
|
||||
if (result == InputResult::Ok)
|
||||
return XELL_RESULT_SUCCESS;
|
||||
else
|
||||
LOG_ERROR("set_sleep_mode result: {}", magic_enum::enum_name(result));
|
||||
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
}
|
||||
xell_result_t InputXeLL::GetSleepMode(xell_input_handle_t context, xell_sleep_params_t* param)
|
||||
{
|
||||
// TODO: impl
|
||||
if (!context)
|
||||
return XELL_RESULT_ERROR_INVALID_CONTEXT;
|
||||
|
||||
param->bLowLatencyMode = true;
|
||||
if (!param)
|
||||
return XELL_RESULT_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
return XELL_RESULT_SUCCESS;
|
||||
if (!context->device)
|
||||
return XELL_RESULT_ERROR_DEVICE;
|
||||
|
||||
SleepParams sleepParams {};
|
||||
|
||||
auto result = InputCommon::get_sleep_status(inputContext, context->device, &sleepParams);
|
||||
|
||||
if (result == InputResult::Ok)
|
||||
{
|
||||
param->bLowLatencyMode = sleepParams.low_latency_enabled;
|
||||
param->bLowLatencyBoost = sleepParams.low_latency_boost;
|
||||
param->minimumIntervalUs = sleepParams.minimum_interval_us;
|
||||
|
||||
// TODO: not fully filled out
|
||||
|
||||
return XELL_RESULT_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("get_sleep_status result: {}", magic_enum::enum_name(result));
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
xell_result_t InputXeLL::Sleep(xell_input_handle_t context, uint32_t frame_id)
|
||||
{
|
||||
// TODO: impl
|
||||
return XELL_RESULT_SUCCESS;
|
||||
if (!context)
|
||||
return XELL_RESULT_ERROR_INVALID_CONTEXT;
|
||||
|
||||
if (!context->device)
|
||||
return XELL_RESULT_ERROR_DEVICE;
|
||||
|
||||
auto result = InputCommon::sleep(inputContext, context->device, frame_id);
|
||||
|
||||
if (result == InputResult::Ok)
|
||||
return XELL_RESULT_SUCCESS;
|
||||
else
|
||||
LOG_ERROR("sleep result: {}", magic_enum::enum_name(result));
|
||||
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
}
|
||||
xell_result_t InputXeLL::AddMarkerData(xell_input_handle_t context, uint32_t frame_id,
|
||||
xell_latency_marker_type_t marker)
|
||||
{
|
||||
// TODO: impl
|
||||
return XELL_RESULT_SUCCESS;
|
||||
if (!context)
|
||||
return XELL_RESULT_ERROR_INVALID_CONTEXT;
|
||||
|
||||
if (marker >= XELL_MARKER_COUNT)
|
||||
{
|
||||
// TODO: call async, probably, need to understand the high markers
|
||||
MarkerParams markerParams {};
|
||||
markerParams.frame_id = frame_id;
|
||||
|
||||
if (marker == 80860000)
|
||||
markerParams.marker_type = MarkerType::OUT_OF_BAND_RENDERSUBMIT_START;
|
||||
else if (marker == 80860001)
|
||||
markerParams.marker_type = MarkerType::OUT_OF_BAND_RENDERSUBMIT_END;
|
||||
else
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
|
||||
auto result = InputCommon::set_async_marker(inputContext, context->d3d12AppQueue, markerParams);
|
||||
|
||||
if (result == InputResult::Ok)
|
||||
return XELL_RESULT_SUCCESS;
|
||||
else
|
||||
LOG_ERROR("sleep result: {}", magic_enum::enum_name(result));
|
||||
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
MarkerParams markerParams {};
|
||||
markerParams.frame_id = frame_id;
|
||||
markerParams.marker_type = (MarkerType) marker; // Those should match 1:1
|
||||
|
||||
if (marker == XELL_PRESENT_START)
|
||||
context->lastPresentStartFrameId = frame_id;
|
||||
|
||||
auto result = InputCommon::set_marker(inputContext, context->device, markerParams);
|
||||
|
||||
if (result == InputResult::Ok)
|
||||
return XELL_RESULT_SUCCESS;
|
||||
else
|
||||
LOG_ERROR("set_marker result: {}", magic_enum::enum_name(result));
|
||||
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
}
|
||||
xell_result_t InputXeLL::GetVersion(xell_version_t* pVersion)
|
||||
{
|
||||
if (!pVersion)
|
||||
return XELL_RESULT_ERROR_INVALID_CONTEXT;
|
||||
return XELL_RESULT_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
// TODO: make this mimic the version of loaded xefg dll so that both are seen as compatible
|
||||
pVersion->major = 1;
|
||||
@@ -66,10 +159,14 @@ xell_result_t InputXeLL::GetFramesReports(xell_input_handle_t context, xell_fram
|
||||
if (!outdata)
|
||||
return XELL_RESULT_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
// outdata should have 64 reports, hopefully the app allocated that much
|
||||
// TODO: fillout
|
||||
auto result = InputCommon::get_latency(inputContext, context->device, outdata);
|
||||
|
||||
return XELL_RESULT_SUCCESS;
|
||||
if (result == InputResult::Ok)
|
||||
return XELL_RESULT_SUCCESS;
|
||||
else
|
||||
LOG_ERROR("get_latency result: {}", magic_enum::enum_name(result));
|
||||
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
// D3D12
|
||||
@@ -109,7 +206,7 @@ xell_result_t InputXeLL::D3D12SetAppQueue(xell_input_handle_t context, ID3D12Com
|
||||
|
||||
context->d3d12AppQueue = appQueue;
|
||||
|
||||
return XELL_RESULT_SUCCESS;
|
||||
return InputCommon::pass_xellD3D12SetAppQueue(inputContext, appQueue);
|
||||
}
|
||||
xell_result_t InputXeLL::GetContextParameterP(xell_input_handle_t context, uint32_t param1, uint64_t param2)
|
||||
{
|
||||
@@ -200,18 +297,20 @@ xell_result_t InputXeLL::SetDisplayInfo(xell_input_handle_t context, void* displ
|
||||
|
||||
context->displayInfo = displayInfo;
|
||||
|
||||
return XELL_RESULT_SUCCESS;
|
||||
return InputCommon::pass_xellSetDisplayInfo(inputContext, displayInfo);
|
||||
}
|
||||
xell_result_t InputXeLL::SetFgEnabled(xell_input_handle_t context, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
// TODO: figure out params and impl
|
||||
return XELL_RESULT_SUCCESS;
|
||||
// This might need to take Opti's FG into account, unsure
|
||||
return InputCommon::pass_xellSetFgEnabled(inputContext, param1, param2);
|
||||
}
|
||||
|
||||
xell_result_t InputXeLL::SetGeneratedFramesCount(xell_input_handle_t context, uint32_t param1, uint32_t framesCount)
|
||||
{
|
||||
// TODO: figure out params and impl
|
||||
return XELL_RESULT_SUCCESS;
|
||||
// TODO: store framesCount for the SleepParams::fg_multiplier
|
||||
return InputCommon::pass_xellSetGeneratedFramesCount(inputContext, param1, framesCount);
|
||||
}
|
||||
|
||||
#ifdef LOW_LATENCY_INPUTS
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <xell.h>
|
||||
#include <xell_d3d12.h>
|
||||
#include "input_common.h"
|
||||
|
||||
class InputXeLL
|
||||
{
|
||||
@@ -15,6 +16,10 @@ class InputXeLL
|
||||
void* displayInfo;
|
||||
};
|
||||
|
||||
const static inline InputContext inputContext { .caller = LowLatencyInput::XeLL,
|
||||
.noFrameId = false,
|
||||
.markerMode = InputMarkerMode::FullMarkers };
|
||||
|
||||
public:
|
||||
typedef struct _xell_input_handle_t* xell_input_handle_t;
|
||||
|
||||
|
||||
@@ -26,6 +26,33 @@ enum class LowLatencyMode
|
||||
Reflex
|
||||
};
|
||||
|
||||
#define FRAME_REPORTS_BUFFER_SIZE 70
|
||||
#define NVAPI_BUFFER_SIZE 64
|
||||
|
||||
struct FrameReport
|
||||
{
|
||||
uint64_t frameID;
|
||||
uint64_t inputSampleTime;
|
||||
uint64_t simStartTime;
|
||||
uint64_t simEndTime;
|
||||
uint64_t renderSubmitStartTime;
|
||||
uint64_t renderSubmitEndTime;
|
||||
uint64_t presentStartTime;
|
||||
uint64_t presentEndTime;
|
||||
uint64_t driverStartTime;
|
||||
uint64_t driverEndTime;
|
||||
uint64_t osRenderQueueStartTime;
|
||||
uint64_t osRenderQueueEndTime;
|
||||
uint64_t gpuRenderStartTime;
|
||||
uint64_t gpuRenderEndTime;
|
||||
uint32_t gpuActiveRenderTimeUs;
|
||||
uint32_t gpuFrameTimeUs;
|
||||
uint64_t cameraConstructedTime;
|
||||
uint32_t crossAdapterCopyTimeUs;
|
||||
uint32_t aiFrameTimeUs;
|
||||
uint8_t rsvd[104];
|
||||
};
|
||||
|
||||
void tonvss(NvAPI_ShortString nvss, std::string str);
|
||||
|
||||
#define INSERT_AND_RETURN_WHEN_EQUALS(method) \
|
||||
|
||||
@@ -193,9 +193,9 @@ void AntiLag2::sleep(std::optional<uint32_t> frame_id)
|
||||
al2_sleep();
|
||||
}
|
||||
|
||||
void AntiLag2::set_marker(IUnknown* pDevice, MarkerParams* marker_params)
|
||||
void AntiLag2::set_marker(IUnknown* pDevice, const MarkerParams& marker_params)
|
||||
{
|
||||
switch (marker_params->marker_type)
|
||||
switch (marker_params.marker_type)
|
||||
{
|
||||
case MarkerType::SIMULATION_START:
|
||||
simulation_framecount++;
|
||||
@@ -219,12 +219,12 @@ void AntiLag2::set_marker(IUnknown* pDevice, MarkerParams* marker_params)
|
||||
}
|
||||
}
|
||||
|
||||
void AntiLag2::set_async_marker(IUnknown* pCommandQueue, MarkerParams* marker_params)
|
||||
void AntiLag2::set_async_marker(IUnknown* pCommandQueue, const MarkerParams& marker_params)
|
||||
{
|
||||
if (marker_params->marker_type == MarkerType::OUT_OF_BAND_PRESENT_START)
|
||||
if (marker_params.marker_type == MarkerType::OUT_OF_BAND_PRESENT_START)
|
||||
{
|
||||
static uint64_t previous_frame_id = marker_params->frame_id;
|
||||
set_fg_type(previous_frame_id == marker_params->frame_id, marker_params->frame_id);
|
||||
previous_frame_id = marker_params->frame_id;
|
||||
static uint64_t previous_frame_id = marker_params.frame_id;
|
||||
set_fg_type(previous_frame_id == marker_params.frame_id, marker_params.frame_id);
|
||||
previous_frame_id = marker_params.frame_id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,6 @@ class AntiLag2 : public LowLatencyTech
|
||||
void get_sleep_status(SleepParams* sleep_params) override;
|
||||
void set_sleep_mode(SleepMode* sleep_mode) override;
|
||||
void sleep(std::optional<uint32_t> frame_id) override;
|
||||
void set_marker(IUnknown* pDevice, MarkerParams* marker_params) override;
|
||||
void set_async_marker(IUnknown* pCommandQueue, MarkerParams* marker_params) override;
|
||||
void set_marker(IUnknown* pDevice, const MarkerParams& marker_params) override;
|
||||
void set_async_marker(IUnknown* pCommandQueue, const MarkerParams& marker_params) override;
|
||||
};
|
||||
@@ -38,9 +38,9 @@ void AntiLagVk::sleep(std::optional<uint32_t> frame_id)
|
||||
return;
|
||||
}
|
||||
|
||||
void AntiLagVk::set_marker(IUnknown* pDevice, MarkerParams* marker_params)
|
||||
void AntiLagVk::set_marker(IUnknown* pDevice, const MarkerParams& marker_params)
|
||||
{
|
||||
if (!pDevice || !marker_params)
|
||||
if (!pDevice)
|
||||
{
|
||||
LOG_ERROR("Invalid pointer");
|
||||
return;
|
||||
@@ -55,7 +55,7 @@ void AntiLagVk::set_marker(IUnknown* pDevice, MarkerParams* marker_params)
|
||||
|
||||
call_count++;
|
||||
|
||||
if (marker_params->marker_type == MarkerType::OUT_OF_BAND_PRESENT_START)
|
||||
if (marker_params.marker_type == MarkerType::OUT_OF_BAND_PRESENT_START)
|
||||
{
|
||||
last_oob_present = call_count;
|
||||
if (!using_oob_present)
|
||||
@@ -65,13 +65,13 @@ void AntiLagVk::set_marker(IUnknown* pDevice, MarkerParams* marker_params)
|
||||
if (using_oob_present && call_count - last_oob_present > allowed_gap)
|
||||
using_oob_present = false;
|
||||
|
||||
if (marker_params->marker_type == MarkerType::SIMULATION_START)
|
||||
if (marker_params.marker_type == MarkerType::SIMULATION_START)
|
||||
{
|
||||
// Before processing user input
|
||||
VkAntiLagPresentationInfoAMD inputInfo = {};
|
||||
inputInfo.sType = VK_STRUCTURE_TYPE_ANTI_LAG_PRESENTATION_INFO_AMD;
|
||||
inputInfo.stage = VK_ANTI_LAG_STAGE_INPUT_AMD;
|
||||
inputInfo.frameIndex = marker_params->frame_id;
|
||||
inputInfo.frameIndex = marker_params.frame_id;
|
||||
|
||||
VkAntiLagDataAMD antiLagDataInput = {};
|
||||
antiLagDataInput.sType = VK_STRUCTURE_TYPE_ANTI_LAG_DATA_AMD;
|
||||
@@ -81,20 +81,21 @@ void AntiLagVk::set_marker(IUnknown* pDevice, MarkerParams* marker_params)
|
||||
|
||||
if (VulkanHooks::o_vkAntiLagUpdateAMD)
|
||||
{
|
||||
LOG_TRACE_LOWLATENCY("AntiLag Input: {}, status: {}", marker_params->frame_id, is_enabled());
|
||||
LOG_TRACE_LOWLATENCY("AntiLag Input: {}, status: {}", marker_params.frame_id, is_enabled());
|
||||
|
||||
// TODO: somehow confirm that pDevice is actually VkDevice
|
||||
VulkanHooks::o_vkAntiLagUpdateAMD((VkDevice) pDevice, &antiLagDataInput);
|
||||
}
|
||||
}
|
||||
|
||||
if ((marker_params->marker_type == MarkerType::PRESENT_START && !using_oob_present) ||
|
||||
marker_params->marker_type == MarkerType::OUT_OF_BAND_PRESENT_START)
|
||||
if ((marker_params.marker_type == MarkerType::PRESENT_START && !using_oob_present) ||
|
||||
marker_params.marker_type == MarkerType::OUT_OF_BAND_PRESENT_START)
|
||||
{
|
||||
// Before calling vkQueuePresentKHR
|
||||
VkAntiLagPresentationInfoAMD presentInfo = {};
|
||||
presentInfo.sType = VK_STRUCTURE_TYPE_ANTI_LAG_PRESENTATION_INFO_AMD;
|
||||
presentInfo.stage = VK_ANTI_LAG_STAGE_PRESENT_AMD;
|
||||
presentInfo.frameIndex = marker_params->frame_id;
|
||||
presentInfo.frameIndex = marker_params.frame_id;
|
||||
|
||||
VkAntiLagDataAMD antiLagDataPresent = {};
|
||||
antiLagDataPresent.sType = VK_STRUCTURE_TYPE_ANTI_LAG_DATA_AMD;
|
||||
@@ -104,7 +105,7 @@ void AntiLagVk::set_marker(IUnknown* pDevice, MarkerParams* marker_params)
|
||||
|
||||
if (VulkanHooks::o_vkAntiLagUpdateAMD)
|
||||
{
|
||||
LOG_TRACE_LOWLATENCY("AntiLag Present: {}, status: {}", marker_params->frame_id, is_enabled());
|
||||
LOG_TRACE_LOWLATENCY("AntiLag Present: {}, status: {}", marker_params.frame_id, is_enabled());
|
||||
|
||||
VulkanHooks::o_vkAntiLagUpdateAMD((VkDevice) pDevice, &antiLagDataPresent);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ class AntiLagVk : public LowLatencyTech
|
||||
void get_sleep_status(SleepParams* sleep_params) override;
|
||||
void set_sleep_mode(SleepMode* sleep_mode) override;
|
||||
void sleep(std::optional<uint32_t> frame_id) override;
|
||||
void set_marker(IUnknown* pDevice, MarkerParams* marker_params) override;
|
||||
void set_async_marker(IUnknown* pCommandQueue, MarkerParams* marker_params) override {}; // Not used by AntiLag VK
|
||||
void set_marker(IUnknown* pDevice, const MarkerParams& marker_params) override;
|
||||
void set_async_marker(IUnknown* pCommandQueue, const MarkerParams& marker_params) override {
|
||||
}; // Not used by AntiLag VK
|
||||
};
|
||||
@@ -168,9 +168,9 @@ void LatencyFlex::sleep(std::optional<uint32_t> frame_id)
|
||||
}
|
||||
};
|
||||
|
||||
void LatencyFlex::set_marker(IUnknown* pDevice, MarkerParams* marker_params)
|
||||
void LatencyFlex::set_marker(IUnknown* pDevice, const MarkerParams& marker_params)
|
||||
{
|
||||
switch (marker_params->marker_type)
|
||||
switch (marker_params.marker_type)
|
||||
{
|
||||
case MarkerType::SIMULATION_START:
|
||||
simulation_framecount++;
|
||||
@@ -181,12 +181,12 @@ void LatencyFlex::set_marker(IUnknown* pDevice, MarkerParams* marker_params)
|
||||
current_call_spot = CallSpot::SleepCall;
|
||||
|
||||
if (current_call_spot == CallSpot::SimulationStart)
|
||||
lfx_sleep(marker_params->frame_id);
|
||||
lfx_sleep(marker_params.frame_id);
|
||||
break;
|
||||
|
||||
case MarkerType::RENDERSUBMIT_END:
|
||||
if ((LFXMode) Config::Instance()->FN_LatencyFlexMode.value_or_default() != LFXMode::Conservative)
|
||||
lfx_end_frame(marker_params->frame_id);
|
||||
lfx_end_frame(marker_params.frame_id);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -52,6 +52,6 @@ class LatencyFlex : public LowLatencyTech
|
||||
void get_sleep_status(SleepParams* sleep_params) override;
|
||||
void set_sleep_mode(SleepMode* sleep_mode) override;
|
||||
void sleep(std::optional<uint32_t> frame_id) override;
|
||||
void set_marker(IUnknown* pDevice, MarkerParams* marker_params) override;
|
||||
void set_async_marker(IUnknown* pCommandQueue, MarkerParams* marker_params) override {}; // Not used by LFX
|
||||
void set_marker(IUnknown* pDevice, const MarkerParams& marker_params) override;
|
||||
void set_async_marker(IUnknown* pCommandQueue, const MarkerParams& marker_params) override {}; // Not used by LFX
|
||||
};
|
||||
@@ -13,7 +13,7 @@ void XeLL::xell_sleep(uint32_t frame_id)
|
||||
if (!inited_using_context || is_enabled())
|
||||
{
|
||||
LOG_TRACE_LOWLATENCY("Sleeping with frame_id: {}", frame_id);
|
||||
XeLLProxy::Sleep()(XeLLProxy::Context(), frame_id);
|
||||
o_xellSleep(xell_context, frame_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ void XeLL::add_marker(uint32_t frame_id, xell_latency_marker_type_t marker)
|
||||
}
|
||||
|
||||
if (!inited_using_context || is_enabled())
|
||||
XeLLProxy::AddMarkerData()(XeLLProxy::Context(), frame_id, marker);
|
||||
o_xellAddMarkerData(xell_context, frame_id, marker);
|
||||
}
|
||||
|
||||
bool XeLL::init(IUnknown* pDevice)
|
||||
@@ -43,7 +43,7 @@ bool XeLL::init(IUnknown* pDevice)
|
||||
if (hr != S_OK)
|
||||
return false;
|
||||
|
||||
auto result = XeLLProxy::CreateContext(dx12_pDevice);
|
||||
auto result = o_xellD3D12CreateContext(dx12_pDevice, &xell_context) == XELL_RESULT_SUCCESS;
|
||||
|
||||
if (result)
|
||||
XellHooks::blockExternalContexts(true);
|
||||
@@ -59,16 +59,22 @@ bool XeLL::init_using_ctx(void* context)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!XeLLProxy::Context())
|
||||
if (!context)
|
||||
{
|
||||
LOG_ERROR("XeLL handed over to fakenvapi but the context is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (xell_context)
|
||||
{
|
||||
o_xellDestroyContext(xell_context);
|
||||
xell_context = (xell_context_handle_t) context;
|
||||
}
|
||||
|
||||
// Context is handled and held inside XeLLProxy
|
||||
inited_using_context = true;
|
||||
XellHooks::blockExternalContexts(true);
|
||||
LOG_INFO("XeLL initialized using existing context: {:X}", (uint64_t) XeLLProxy::Context());
|
||||
LOG_INFO("XeLL initialized using existing context: {:X}", (uint64_t) xell_context);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -85,17 +91,17 @@ void XeLL::deinit()
|
||||
}
|
||||
else
|
||||
{
|
||||
XeLLProxy::DestroyXeLLContext();
|
||||
o_xellDestroyContext(xell_context);
|
||||
LOG_INFO("XeLL deinitialized");
|
||||
}
|
||||
}
|
||||
|
||||
void* XeLL::get_tech_context() { return XeLLProxy::Context(); }
|
||||
void* XeLL::get_tech_context() { return xell_context; }
|
||||
|
||||
void XeLL::get_sleep_status(SleepParams* sleep_params)
|
||||
{
|
||||
xell_sleep_params_t xell_sleep_params {};
|
||||
auto result = XeLLProxy::GetSleepMode()(XeLLProxy::Context(), &xell_sleep_params);
|
||||
auto result = o_xellGetSleepMode(xell_context, &xell_sleep_params) == XELL_RESULT_SUCCESS;
|
||||
|
||||
sleep_params->low_latency_enabled = xell_sleep_params.bLowLatencyMode;
|
||||
sleep_params->fullscreen_vrr = true;
|
||||
@@ -130,7 +136,7 @@ void XeLL::set_sleep_mode(SleepMode* sleep_mode)
|
||||
xell_sleep_params.minimumIntervalUs != last_minimumIntervalUs ||
|
||||
xell_sleep_params.bLowLatencyBoost != last_bLowLatencyBoost)
|
||||
{
|
||||
auto result = XeLLProxy::SetSleepMode()(XeLLProxy::Context(), &xell_sleep_params);
|
||||
auto result = o_xellSetSleepMode(xell_context, &xell_sleep_params) == XELL_RESULT_SUCCESS;
|
||||
|
||||
last_bLowLatencyMode = xell_sleep_params.bLowLatencyMode;
|
||||
last_minimumIntervalUs = xell_sleep_params.minimumIntervalUs;
|
||||
@@ -138,21 +144,21 @@ void XeLL::set_sleep_mode(SleepMode* sleep_mode)
|
||||
}
|
||||
}
|
||||
|
||||
void XeLL::set_marker(IUnknown* pDevice, MarkerParams* marker_params)
|
||||
void XeLL::set_marker(IUnknown* pDevice, const MarkerParams& marker_params)
|
||||
{
|
||||
if (!pDevice || !marker_params)
|
||||
if (!pDevice)
|
||||
{
|
||||
LOG_ERROR("Invalid pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
// XeLL frame ids are uint64_t
|
||||
auto frame_id = (uint32_t) marker_params->frame_id;
|
||||
auto frame_id = (uint32_t) marker_params.frame_id;
|
||||
|
||||
switch (marker_params->marker_type)
|
||||
switch (marker_params.marker_type)
|
||||
{
|
||||
case MarkerType::SIMULATION_START:
|
||||
simulation_start_last_id = marker_params->frame_id;
|
||||
simulation_start_last_id = marker_params.frame_id;
|
||||
|
||||
// Call sleep just before simulation start if sleep isn't getting called
|
||||
if (sleep_last_id + 10 < simulation_start_last_id)
|
||||
@@ -176,13 +182,37 @@ void XeLL::set_marker(IUnknown* pDevice, MarkerParams* marker_params)
|
||||
add_marker(frame_id, XELL_PRESENT_END);
|
||||
break;
|
||||
// case MarkerType::INPUT_SAMPLE:
|
||||
// add_marker(marker_params->frame_id, XELL_INPUT_SAMPLE);
|
||||
// add_marker(marker_params.frame_id, XELL_INPUT_SAMPLE);
|
||||
// break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void XeLL::set_async_marker(IUnknown* pCommandQueue, const MarkerParams& marker_params)
|
||||
{
|
||||
if (!pCommandQueue)
|
||||
{
|
||||
LOG_ERROR("Invalid pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
// XeLL frame ids are uint64_t
|
||||
auto frame_id = (uint32_t) marker_params.frame_id;
|
||||
|
||||
switch (marker_params.marker_type)
|
||||
{
|
||||
case MarkerType::OUT_OF_BAND_RENDERSUBMIT_START:
|
||||
add_marker(frame_id, (xell_latency_marker_type_t) 80860000);
|
||||
break;
|
||||
case MarkerType::OUT_OF_BAND_RENDERSUBMIT_END:
|
||||
add_marker(frame_id, (xell_latency_marker_type_t) 80860001);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void XeLL::sleep(std::optional<uint32_t> frame_id)
|
||||
{
|
||||
if (frame_id.has_value())
|
||||
@@ -201,7 +231,7 @@ xell_result_t XeLL::xellD3D12SetAppQueue(ID3D12CommandQueue* appQueue) const
|
||||
if (!o_xellD3D12SetAppQueue)
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
|
||||
return o_xellD3D12SetAppQueue(XeLLProxy::Context(), appQueue);
|
||||
return o_xellD3D12SetAppQueue(xell_context, appQueue);
|
||||
}
|
||||
|
||||
xell_result_t XeLL::xellSetDisplayInfo(void* displayInfo) const
|
||||
@@ -209,7 +239,7 @@ xell_result_t XeLL::xellSetDisplayInfo(void* displayInfo) const
|
||||
if (!o_xellSetDisplayInfo)
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
|
||||
return o_xellSetDisplayInfo(XeLLProxy::Context(), displayInfo);
|
||||
return o_xellSetDisplayInfo(xell_context, displayInfo);
|
||||
}
|
||||
|
||||
xell_result_t XeLL::xellSetFgEnabled(uint32_t param1, uint32_t param2) const
|
||||
@@ -217,7 +247,7 @@ xell_result_t XeLL::xellSetFgEnabled(uint32_t param1, uint32_t param2) const
|
||||
if (!o_xellSetFgEnabled)
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
|
||||
return o_xellSetFgEnabled(XeLLProxy::Context(), param1, param2);
|
||||
return o_xellSetFgEnabled(xell_context, param1, param2);
|
||||
}
|
||||
|
||||
xell_result_t XeLL::xellSetGeneratedFramesCount(uint32_t param1, uint32_t framesCount) const
|
||||
@@ -225,7 +255,7 @@ xell_result_t XeLL::xellSetGeneratedFramesCount(uint32_t param1, uint32_t frames
|
||||
if (!o_xellSetGeneratedFramesCount)
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
|
||||
return o_xellSetGeneratedFramesCount(XeLLProxy::Context(), param1, framesCount);
|
||||
return o_xellSetGeneratedFramesCount(xell_context, param1, framesCount);
|
||||
}
|
||||
|
||||
xell_result_t XeLL::xellGetLastPresentStartFrameId(uint32_t* p_frame_id) const
|
||||
@@ -233,5 +263,13 @@ xell_result_t XeLL::xellGetLastPresentStartFrameId(uint32_t* p_frame_id) const
|
||||
if (!o_xellGetLastPresentStartFrameId)
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
|
||||
return o_xellGetLastPresentStartFrameId(XeLLProxy::Context(), p_frame_id);
|
||||
}
|
||||
return o_xellGetLastPresentStartFrameId(xell_context, p_frame_id);
|
||||
}
|
||||
|
||||
xell_result_t XeLL::xellGetFramesReports(xell_frame_report_t* outdata) const
|
||||
{
|
||||
if (!o_xellGetFramesReports)
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
|
||||
return o_xellGetFramesReports(xell_context, outdata);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <xell_d3d12.h>
|
||||
#include "low_latency/input/input_xell.h"
|
||||
#include <proxies/XeLL_Proxy.h>
|
||||
|
||||
class XeLL : public LowLatencyTech
|
||||
{
|
||||
@@ -11,7 +12,18 @@ class XeLL : public LowLatencyTech
|
||||
uint64_t simulation_start_last_id {};
|
||||
uint64_t sleep_last_id {};
|
||||
|
||||
// TODO: set those
|
||||
xell_context_handle_t xell_context {};
|
||||
|
||||
decltype(&xellDestroyContext) o_xellDestroyContext = nullptr;
|
||||
decltype(&xellSetSleepMode) o_xellSetSleepMode = nullptr;
|
||||
decltype(&xellGetSleepMode) o_xellGetSleepMode = nullptr;
|
||||
decltype(&xellSleep) o_xellSleep = nullptr;
|
||||
decltype(&xellAddMarkerData) o_xellAddMarkerData = nullptr;
|
||||
decltype(&xellGetVersion) o_xellGetVersion = nullptr;
|
||||
decltype(&xellSetLoggingCallback) o_xellSetLoggingCallback = nullptr;
|
||||
decltype(&xellGetFramesReports) o_xellGetFramesReports = nullptr;
|
||||
decltype(&xellD3D12CreateContext) o_xellD3D12CreateContext = nullptr;
|
||||
|
||||
decltype(&xellD3D12SetAppQueue) o_xellD3D12SetAppQueue = nullptr;
|
||||
decltype(&xellSetDisplayInfo) o_xellSetDisplayInfo = nullptr;
|
||||
decltype(&xellSetFgEnabled) o_xellSetFgEnabled = nullptr;
|
||||
@@ -22,11 +34,43 @@ class XeLL : public LowLatencyTech
|
||||
void add_marker(uint32_t frame_id, xell_latency_marker_type_t marker);
|
||||
|
||||
public:
|
||||
XeLL() : LowLatencyTech() {}
|
||||
XeLL() : LowLatencyTech()
|
||||
{
|
||||
if (XeLLProxy::InitXeLL())
|
||||
{
|
||||
#ifdef LOW_LATENCY_INPUTS
|
||||
o_xellDestroyContext = XeLLProxy::RealDestroyContext();
|
||||
o_xellSetSleepMode = XeLLProxy::RealSetSleepMode();
|
||||
o_xellGetSleepMode = XeLLProxy::RealGetSleepMode();
|
||||
o_xellSleep = XeLLProxy::RealSleep();
|
||||
o_xellAddMarkerData = XeLLProxy::RealAddMarkerData();
|
||||
o_xellGetVersion = XeLLProxy::RealGetVersion();
|
||||
o_xellSetLoggingCallback = XeLLProxy::RealSetLoggingCallback();
|
||||
o_xellGetFramesReports = XeLLProxy::RealGetFramesReports();
|
||||
o_xellD3D12CreateContext = XeLLProxy::RealD3D12CreateContext();
|
||||
|
||||
o_xellD3D12SetAppQueue = XeLLProxy::RealD3D12SetAppQueue();
|
||||
o_xellSetDisplayInfo = XeLLProxy::RealSetDisplayInfo();
|
||||
o_xellSetFgEnabled = XeLLProxy::RealSetFgEnabled();
|
||||
o_xellSetGeneratedFramesCount = XeLLProxy::RealSetGeneratedFramesCount();
|
||||
o_xellGetLastPresentStartFrameId = XeLLProxy::RealGetLastPresentStartFrameId(); // Maybe not needed
|
||||
#else
|
||||
o_xellDestroyContext = XeLLProxy::DestroyContext();
|
||||
o_xellSetSleepMode = XeLLProxy::SetSleepMode();
|
||||
o_xellGetSleepMode = XeLLProxy::GetSleepMode();
|
||||
o_xellSleep = XeLLProxy::Sleep();
|
||||
o_xellAddMarkerData = XeLLProxy::AddMarkerData();
|
||||
o_xellGetVersion = XeLLProxy::GetVersion();
|
||||
o_xellSetLoggingCallback = XeLLProxy::SetLoggingCallback();
|
||||
o_xellGetFramesReports = XeLLProxy::GetFramesReports();
|
||||
o_xellD3D12CreateContext = XeLLProxy::D3D12CreateContext();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// From LowLatencyTech
|
||||
bool init(IUnknown* pDevice) override;
|
||||
bool init_using_ctx(void* context) override; // Context is always held by XeLLProxy
|
||||
bool init_using_ctx(void* context) override;
|
||||
void deinit() override;
|
||||
|
||||
LowLatencyMode get_mode() override { return LowLatencyMode::XeLL; };
|
||||
@@ -47,8 +91,8 @@ class XeLL : public LowLatencyTech
|
||||
void get_sleep_status(SleepParams* sleep_params) override;
|
||||
void set_sleep_mode(SleepMode* sleep_mode) override;
|
||||
void sleep(std::optional<uint32_t> frame_id) override;
|
||||
void set_marker(IUnknown* pDevice, MarkerParams* marker_params) override;
|
||||
void set_async_marker(IUnknown* pCommandQueue, MarkerParams* marker_params) override {}; // Not used by XeLL
|
||||
void set_marker(IUnknown* pDevice, const MarkerParams& marker_params) override;
|
||||
void set_async_marker(IUnknown* pCommandQueue, const MarkerParams& marker_params) override;
|
||||
|
||||
// For passthrough
|
||||
xell_result_t xellD3D12SetAppQueue(ID3D12CommandQueue* appQueue) const;
|
||||
@@ -56,4 +100,5 @@ class XeLL : public LowLatencyTech
|
||||
xell_result_t xellSetFgEnabled(uint32_t param1, uint32_t param2) const;
|
||||
xell_result_t xellSetGeneratedFramesCount(uint32_t param1, uint32_t framesCount) const;
|
||||
xell_result_t xellGetLastPresentStartFrameId(uint32_t* p_frame_id) const;
|
||||
xell_result_t xellGetFramesReports(xell_frame_report_t* outdata) const;
|
||||
};
|
||||
@@ -18,8 +18,13 @@ enum class CallSpot
|
||||
struct SleepParams
|
||||
{
|
||||
bool low_latency_enabled;
|
||||
bool low_latency_boost;
|
||||
uint32_t minimum_interval_us; // 0 -> no fps limit
|
||||
bool fullscreen_vrr;
|
||||
bool control_panel_vsync_override;
|
||||
bool use_game_sleep;
|
||||
bool fullscreen_i_flip;
|
||||
uint8_t fg_multiplier;
|
||||
};
|
||||
|
||||
struct SleepMode
|
||||
@@ -28,6 +33,7 @@ struct SleepMode
|
||||
bool low_latency_boost;
|
||||
uint32_t minimum_interval_us; // 0 -> no fps limit
|
||||
bool use_markers_to_optimize; // TODO: log this if false
|
||||
bool use_min_queue_time;
|
||||
};
|
||||
|
||||
enum class MarkerType
|
||||
@@ -85,6 +91,6 @@ class LowLatencyTech
|
||||
virtual void get_sleep_status(SleepParams* sleep_params) = 0;
|
||||
virtual void set_sleep_mode(SleepMode* sleep_mode) = 0;
|
||||
virtual void sleep(std::optional<uint32_t> frame_id = std::nullopt) = 0;
|
||||
virtual void set_marker(IUnknown* pDevice, MarkerParams* marker_params) = 0;
|
||||
virtual void set_async_marker(IUnknown* pCommandQueue, MarkerParams* marker_params) = 0;
|
||||
virtual void set_marker(IUnknown* pDevice, const MarkerParams& marker_params) = 0;
|
||||
virtual void set_async_marker(IUnknown* pCommandQueue, const MarkerParams& marker_params) = 0;
|
||||
};
|
||||
@@ -59,7 +59,7 @@ void UeLowLatency::tickStart(int64_t frameId, float DeltaSeconds, bool bIdleMode
|
||||
MarkerParams marker {};
|
||||
marker.marker_type = MarkerType::SIMULATION_START;
|
||||
marker.frame_id = frameId;
|
||||
lowLatencyFeature->set_marker(State::Instance().currentD3D12Device, &marker);
|
||||
lowLatencyFeature->set_marker(State::Instance().currentD3D12Device, marker);
|
||||
}
|
||||
|
||||
void UeLowLatency::tickEnd(int64_t frameId, float DeltaSeconds, bool bIdleMode)
|
||||
@@ -69,5 +69,5 @@ void UeLowLatency::tickEnd(int64_t frameId, float DeltaSeconds, bool bIdleMode)
|
||||
MarkerParams marker {};
|
||||
marker.marker_type = MarkerType::SIMULATION_END;
|
||||
marker.frame_id = frameId;
|
||||
lowLatencyFeature->set_marker(State::Instance().currentD3D12Device, &marker);
|
||||
lowLatencyFeature->set_marker(State::Instance().currentD3D12Device, marker);
|
||||
}
|
||||
|
||||
@@ -8,30 +8,6 @@
|
||||
#include "low_latency/ll_util.h"
|
||||
#include <optional>
|
||||
|
||||
#define FRAME_REPORTS_BUFFER_SIZE 70
|
||||
#define NVAPI_BUFFER_SIZE 64
|
||||
|
||||
struct FrameReport
|
||||
{
|
||||
uint64_t frameID;
|
||||
uint64_t inputSampleTime;
|
||||
uint64_t simStartTime;
|
||||
uint64_t simEndTime;
|
||||
uint64_t renderSubmitStartTime;
|
||||
uint64_t renderSubmitEndTime;
|
||||
uint64_t presentStartTime;
|
||||
uint64_t presentEndTime;
|
||||
uint64_t driverStartTime;
|
||||
uint64_t driverEndTime;
|
||||
uint64_t osRenderQueueStartTime;
|
||||
uint64_t osRenderQueueEndTime;
|
||||
uint64_t gpuRenderStartTime;
|
||||
uint64_t gpuRenderEndTime;
|
||||
uint32_t gpuActiveRenderTimeUs;
|
||||
uint32_t gpuFrameTimeUs;
|
||||
uint8_t rsvd[120];
|
||||
};
|
||||
|
||||
class LowLatency
|
||||
{
|
||||
private:
|
||||
|
||||
@@ -278,7 +278,7 @@ NvAPI_Status LowLatency::SetLatencyMarker(IUnknown* pDev, NV_LATENCY_MARKER_PARA
|
||||
marker_params.marker_type = (MarkerType) pSetLatencyMarkerParams->markerType; // requires enums to match
|
||||
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
current_tech->set_marker(pDev, &marker_params);
|
||||
current_tech->set_marker(pDev, marker_params);
|
||||
|
||||
LOG_TRACE_FAKENVAPI("{}: {}", magic_enum::enum_name(marker_params.marker_type), marker_params.frame_id);
|
||||
|
||||
@@ -325,7 +325,7 @@ NvAPI_Status LowLatency::SetAsyncFrameMarker(ID3D12CommandQueue* pCommandQueue,
|
||||
}
|
||||
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
current_tech->set_async_marker(pCommandQueue, &marker_params);
|
||||
current_tech->set_async_marker(pCommandQueue, marker_params);
|
||||
|
||||
LOG_TRACE_FAKENVAPI("Async {}: {}", magic_enum::enum_name(marker_params.marker_type), marker_params.frame_id);
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ NvAPI_Status LowLatency::SetLatencyMarker(HANDLE vkDevice, NV_VULKAN_LATENCY_MAR
|
||||
|
||||
// This cast is not ideal as it needs to be cast to VkDevice while knowing it's vulkan
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
current_tech->set_marker((IUnknown*) vkDevice, &marker_params);
|
||||
current_tech->set_marker((IUnknown*) vkDevice, marker_params);
|
||||
|
||||
LOG_TRACE_FAKENVAPI("{}: {}", magic_enum::enum_name(marker_params.marker_type), marker_params.frame_id);
|
||||
|
||||
|
||||
+107
-19
@@ -30,6 +30,13 @@ typedef decltype(&xellGetFramesReports) PFN_xellGetFramesReports;
|
||||
// Dx12
|
||||
typedef decltype(&xellD3D12CreateContext) PFN_xellD3D12CreateContext;
|
||||
|
||||
// Extra
|
||||
typedef decltype(&xellD3D12SetAppQueue) PFN_xellD3D12SetAppQueue;
|
||||
typedef decltype(&xellSetDisplayInfo) PFN_xellSetDisplayInfo;
|
||||
typedef decltype(&xellSetFgEnabled) PFN_xellSetFgEnabled;
|
||||
typedef decltype(&xellSetGeneratedFramesCount) PFN_xellSetGeneratedFramesCount;
|
||||
typedef decltype(&xellGetLastPresentStartFrameId) PFN_xellGetLastPresentStartFrameId;
|
||||
|
||||
// This callback runs once for every function exported by the Old DLL
|
||||
static int ExportCallback(PVOID hNewDll, ULONG nOrdinal, LPCSTR pszName, PVOID pOldFunction)
|
||||
{
|
||||
@@ -68,6 +75,7 @@ class XeLLProxy
|
||||
{
|
||||
private:
|
||||
inline static HMODULE _dll = nullptr;
|
||||
inline static HMODULE _memoryDll = nullptr;
|
||||
inline static std::wstring _dllPath;
|
||||
|
||||
inline static xell_version_t _xellVersion {};
|
||||
@@ -109,6 +117,13 @@ class XeLLProxy
|
||||
// Dx12
|
||||
inline static PFN_xellD3D12CreateContext _xellD3D12CreateContext = nullptr;
|
||||
|
||||
// Extra
|
||||
inline static PFN_xellD3D12SetAppQueue _xellD3D12SetAppQueue = nullptr;
|
||||
inline static PFN_xellSetDisplayInfo _xellSetDisplayInfo = nullptr;
|
||||
inline static PFN_xellSetFgEnabled _xellSetFgEnabled = nullptr;
|
||||
inline static PFN_xellSetGeneratedFramesCount _xellSetGeneratedFramesCount = nullptr;
|
||||
inline static PFN_xellGetLastPresentStartFrameId _xellGetLastPresentStartFrameId = nullptr;
|
||||
|
||||
inline static xell_version_t GetDLLVersion(std::wstring dllPath)
|
||||
{
|
||||
xell_version_t xellVersion {};
|
||||
@@ -141,11 +156,7 @@ class XeLLProxy
|
||||
return dll;
|
||||
}
|
||||
|
||||
public:
|
||||
static HMODULE Module() { return _dll; }
|
||||
static std::wstring Module_Path() { return _dllPath; }
|
||||
|
||||
static bool InitXeLL()
|
||||
static bool InitXeLLProper()
|
||||
{
|
||||
if (_dll != nullptr)
|
||||
return true;
|
||||
@@ -154,7 +165,7 @@ class XeLLProxy
|
||||
|
||||
std::vector<std::wstring> dllNames = { L"libxell.dll" };
|
||||
|
||||
auto optiPath = Config::Instance()->MainDllPath.value();
|
||||
auto& optiPath = Config::Instance()->MainDllPath.value();
|
||||
|
||||
for (size_t i = 0; i < dllNames.size(); i++)
|
||||
{
|
||||
@@ -162,21 +173,16 @@ class XeLLProxy
|
||||
|
||||
auto overridePath = Config::Instance()->XeLLLibrary.value_or(L"");
|
||||
|
||||
HMODULE memModule = nullptr;
|
||||
|
||||
#ifdef LOW_LATENCY_INPUTS
|
||||
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||
(LPCSTR) InputXeLL::D3D12CreateContext, &mainModule);
|
||||
#else
|
||||
Util::LoadProxyLibrary(dllNames[i], optiPath, overridePath, &memModule, &mainModule);
|
||||
#endif
|
||||
Util::LoadProxyLibrary(dllNames[i], optiPath, overridePath, &_memoryDll, &mainModule);
|
||||
|
||||
if (mainModule != nullptr)
|
||||
{
|
||||
// We don't control which XeLL dll XeFG will pick
|
||||
// Detouring GetModuleHandleExA seemingly isn't enough
|
||||
if (memModule && mainModule != memModule)
|
||||
RedirectAllExports(memModule, mainModule);
|
||||
#ifndef LOW_LATENCY_INPUTS
|
||||
if (_memoryDll && mainModule != _memoryDll)
|
||||
RedirectAllExports(_memoryDll, mainModule);
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -195,6 +201,44 @@ class XeLLProxy
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool InitXeLLInput()
|
||||
{
|
||||
#ifndef LOW_LATENCY_INPUTS
|
||||
return true;
|
||||
#endif
|
||||
|
||||
HMODULE mainModule = nullptr;
|
||||
|
||||
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||
(LPCSTR) InputXeLL::D3D12CreateContext, &mainModule);
|
||||
|
||||
if (_dll != nullptr)
|
||||
{
|
||||
// If our xell and the one in memory aren't the same then
|
||||
// hook the in-memory functions with our xell inputs ones
|
||||
if (_memoryDll && _dll != _memoryDll)
|
||||
RedirectAllExports(_memoryDll, dllModule);
|
||||
}
|
||||
|
||||
if (mainModule != nullptr)
|
||||
{
|
||||
wchar_t modulePath[MAX_PATH];
|
||||
DWORD len = GetModuleFileNameW(mainModule, modulePath, MAX_PATH);
|
||||
_dllPath = std::wstring(modulePath);
|
||||
|
||||
LOG_INFO("Loaded from {}", wstring_to_string(_dllPath));
|
||||
return HookXeLL(mainModule);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
static HMODULE Module() { return _dll; }
|
||||
static std::wstring Module_Path() { return _dllPath; }
|
||||
|
||||
static bool InitXeLL() { return InitXeLLProper() && InitXeLLInput(); }
|
||||
|
||||
static bool HookXeLL(HMODULE libxellModule)
|
||||
{
|
||||
// if dll already loaded
|
||||
@@ -228,6 +272,17 @@ class XeLLProxy
|
||||
|
||||
_xellD3D12CreateContext =
|
||||
(PFN_xellD3D12CreateContext) KernelBaseProxy::GetProcAddress_()(_dll, "xellD3D12CreateContext");
|
||||
|
||||
_xellD3D12SetAppQueue =
|
||||
(PFN_xellD3D12SetAppQueue) KernelBaseProxy::GetProcAddress_()(_dll, "xellD3D12SetAppQueue");
|
||||
_xellSetDisplayInfo =
|
||||
(PFN_xellSetDisplayInfo) KernelBaseProxy::GetProcAddress_()(_dll, "xellSetDisplayInfo");
|
||||
_xellSetFgEnabled = (PFN_xellSetFgEnabled) KernelBaseProxy::GetProcAddress_()(_dll, "xellSetFgEnabled");
|
||||
_xellSetGeneratedFramesCount = (PFN_xellSetGeneratedFramesCount) KernelBaseProxy::GetProcAddress_()(
|
||||
_dll, "xellSetGeneratedFramesCount");
|
||||
_xellGetLastPresentStartFrameId =
|
||||
(PFN_xellGetLastPresentStartFrameId) KernelBaseProxy::GetProcAddress_()(
|
||||
_dll, "xellGetLastPresentStartFrameId");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,6 +315,37 @@ class XeLLProxy
|
||||
return _xellVersion;
|
||||
}
|
||||
|
||||
#ifdef LOW_LATENCY_INPUTS
|
||||
// We export / implement those functions
|
||||
static PFN_xellDestroyContext DestroyContext() { return xellDestroyContext; }
|
||||
static PFN_xellSetSleepMode SetSleepMode() { return xellSetSleepMode; }
|
||||
static PFN_xellGetSleepMode GetSleepMode() { return xellGetSleepMode; }
|
||||
static PFN_xellSleep Sleep() { return xellSleep; }
|
||||
static PFN_xellAddMarkerData AddMarkerData() { return xellAddMarkerData; }
|
||||
static PFN_xellGetVersion GetVersion() { return xellGetVersion; }
|
||||
static PFN_xellSetLoggingCallback SetLoggingCallback() { return xellSetLoggingCallback; }
|
||||
static PFN_xellGetFramesReports GetFramesReports() { return xellGetFramesReports; }
|
||||
static PFN_xellD3D12CreateContext D3D12CreateContext() { return xellD3D12CreateContext; }
|
||||
|
||||
// Pointing to the actual DLL
|
||||
static PFN_xellDestroyContext RealDestroyContext() { return _xellDestroyContext; }
|
||||
static PFN_xellSetSleepMode RealSetSleepMode() { return _xellSetSleepMode; }
|
||||
static PFN_xellGetSleepMode RealGetSleepMode() { return _xellGetSleepMode; }
|
||||
static PFN_xellSleep RealSleep() { return _xellSleep; }
|
||||
static PFN_xellAddMarkerData RealAddMarkerData() { return _xellAddMarkerData; }
|
||||
static PFN_xellGetVersion RealGetVersion() { return _xellGetVersion; }
|
||||
static PFN_xellSetLoggingCallback RealSetLoggingCallback() { return _xellSetLoggingCallback; }
|
||||
static PFN_xellGetFramesReports RealGetFramesReports() { return _xellGetFramesReports; }
|
||||
static PFN_xellD3D12CreateContext RealD3D12CreateContext() { return _xellD3D12CreateContext; }
|
||||
static PFN_xellD3D12SetAppQueue RealD3D12SetAppQueue() { return _xellD3D12SetAppQueue; }
|
||||
static PFN_xellSetDisplayInfo RealSetDisplayInfo() { return _xellSetDisplayInfo; }
|
||||
static PFN_xellSetFgEnabled RealSetFgEnabled() { return _xellSetFgEnabled; }
|
||||
static PFN_xellSetGeneratedFramesCount RealSetGeneratedFramesCount() { return _xellSetGeneratedFramesCount; }
|
||||
static PFN_xellGetLastPresentStartFrameId RealGetLastPresentStartFrameId()
|
||||
{
|
||||
return _xellGetLastPresentStartFrameId;
|
||||
}
|
||||
#else
|
||||
static PFN_xellDestroyContext DestroyContext() { return _xellDestroyContext; }
|
||||
static PFN_xellSetSleepMode SetSleepMode() { return _xellSetSleepMode; }
|
||||
static PFN_xellGetSleepMode GetSleepMode() { return _xellGetSleepMode; }
|
||||
@@ -268,8 +354,8 @@ class XeLLProxy
|
||||
static PFN_xellGetVersion GetVersion() { return _xellGetVersion; }
|
||||
static PFN_xellSetLoggingCallback SetLoggingCallback() { return _xellSetLoggingCallback; }
|
||||
static PFN_xellGetFramesReports GetFramesReports() { return _xellGetFramesReports; }
|
||||
|
||||
static PFN_xellD3D12CreateContext D3D12CreateContext() { return _xellD3D12CreateContext; }
|
||||
#endif
|
||||
|
||||
static bool DestroyXeLLContext()
|
||||
{
|
||||
@@ -279,7 +365,7 @@ class XeLLProxy
|
||||
{
|
||||
auto context = _xellContext;
|
||||
_xellContext = nullptr;
|
||||
auto xellResult = _xellDestroyContext(context);
|
||||
auto xellResult = DestroyContext()(context);
|
||||
|
||||
LOG_INFO("XeLL DestroyContext result: {} ({})", magic_enum::enum_name(xellResult), (UINT) xellResult);
|
||||
|
||||
@@ -299,11 +385,13 @@ class XeLLProxy
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef LOW_LATENCY_INPUTS
|
||||
if (!XellHooks::Hook())
|
||||
{
|
||||
LOG_ERROR("Couldn't detour XeLL");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_xellContext != nullptr)
|
||||
DestroyXeLLContext();
|
||||
@@ -311,7 +399,7 @@ class XeLLProxy
|
||||
xell_result_t xellResult;
|
||||
{
|
||||
ScopedSkipSpoofing skipSpoofing {};
|
||||
xellResult = _xellD3D12CreateContext(device, &_xellContext);
|
||||
xellResult = D3D12CreateContext()(device, &_xellContext);
|
||||
}
|
||||
|
||||
if (xellResult != XELL_RESULT_SUCCESS)
|
||||
|
||||
Reference in New Issue
Block a user