mirror of
https://github.com/optiscaler/OptiScaler.git
synced 2026-08-24 07:06:33 +00:00
WIP: Common Low Latency inputs
This commit is contained in:
@@ -328,6 +328,7 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y
|
||||
<ClInclude Include="hooks\Hook_Utils.h" />
|
||||
<ClInclude Include="hooks\LibraryLoad_Hooks.h" />
|
||||
<ClInclude Include="hooks\CommandBuffer_StateTracker.h" />
|
||||
<ClInclude Include="low_latency\input\input_common.h" />
|
||||
<ClInclude Include="low_latency\input\input_reflex.h" />
|
||||
<ClInclude Include="low_latency\input\input_xell.h" />
|
||||
<ClInclude Include="low_latency\input\input_antilag2.h" />
|
||||
@@ -592,6 +593,7 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y
|
||||
<ClCompile Include="hooks\LibraryLoad_Hooks.cpp" />
|
||||
<ClCompile Include="hooks\VulkanwDx12_Hooks.cpp" />
|
||||
<ClCompile Include="hooks\Xell_Hooks.cpp" />
|
||||
<ClCompile Include="low_latency\input\input_common.cpp" />
|
||||
<ClCompile Include="low_latency\input\input_reflex.cpp" />
|
||||
<ClCompile Include="low_latency\input\input_xell.cpp" />
|
||||
<ClCompile Include="low_latency\input\input_antilag2.cpp" />
|
||||
|
||||
@@ -872,6 +872,9 @@
|
||||
<ClInclude Include="shaders\rcas\shaders\RCAS_Shader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="low_latency\input\input_common.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Config.cpp">
|
||||
@@ -1355,6 +1358,9 @@
|
||||
<ClCompile Include="low_latency\input\input_reflex.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="low_latency\input\input_common.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="OptiScaler.rc" />
|
||||
|
||||
@@ -0,0 +1,353 @@
|
||||
#include "pch.h"
|
||||
#include "input_common.h"
|
||||
#include <low_latency/low_latency_tech/ll_xell.h>
|
||||
|
||||
bool InputCommon::update_low_latency_tech(IUnknown* pDevice, std::optional<LowLatencyMode> mode)
|
||||
{
|
||||
LowLatencyMode desiredMode = LowLatencyMode::None;
|
||||
|
||||
if (!pDevice)
|
||||
{
|
||||
// Some outputs might call sleep with nullptr
|
||||
if (activeOutput != LowLatencyMode::None && !mode.has_value())
|
||||
return true; // Allow it if we already have an output and not trying to set manually
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mode.has_value())
|
||||
desiredMode = mode.value();
|
||||
|
||||
if (desiredMode != LowLatencyMode::None && desiredMode == activeOutput)
|
||||
{
|
||||
// No need to do anything
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: init correct currently_active_tech, desiredMode == None -> Auto
|
||||
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
{
|
||||
activeOutput = current_tech->get_mode();
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG_ERROR("No Low Latency Tech selected");
|
||||
return false;
|
||||
}
|
||||
|
||||
void InputCommon::add_marker_to_report(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];
|
||||
|
||||
if (current_report->frameID != marker_params->frame_id)
|
||||
{
|
||||
*current_report = FrameReport {};
|
||||
}
|
||||
|
||||
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;
|
||||
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 (marker_params->marker_type)
|
||||
{
|
||||
case MarkerType::SIMULATION_START:
|
||||
_2nd_last_sim_start = last_sim_start;
|
||||
last_sim_start = get_timestamp() / 1000;
|
||||
current_report->simStartTime = last_sim_start;
|
||||
break;
|
||||
case MarkerType::SIMULATION_END:
|
||||
current_report->simEndTime = get_timestamp() / 1000;
|
||||
break;
|
||||
case MarkerType::RENDERSUBMIT_START:
|
||||
current_report->renderSubmitStartTime = get_timestamp() / 1000;
|
||||
break;
|
||||
case MarkerType::RENDERSUBMIT_END:
|
||||
current_report->renderSubmitEndTime = get_timestamp() / 1000;
|
||||
break;
|
||||
case MarkerType::PRESENT_START:
|
||||
current_report->presentStartTime = get_timestamp() / 1000;
|
||||
break;
|
||||
case MarkerType::PRESENT_END:
|
||||
current_report->presentEndTime = get_timestamp() / 1000;
|
||||
break;
|
||||
case MarkerType::INPUT_SAMPLE:
|
||||
current_report->inputSampleTime = get_timestamp() / 1000;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
InputResult InputCommon::set_low_latency_tech(IUnknown* pDevice, LowLatencyMode mode)
|
||||
{
|
||||
if (!update_low_latency_tech(pDevice, mode))
|
||||
return InputResult::LowLatencyUpdateFail;
|
||||
|
||||
return InputResult::Ok;
|
||||
}
|
||||
|
||||
InputResult InputCommon::sleep(IUnknown* pDevice, const InputContext& inputContext, std::optional<uint32_t> frame_id)
|
||||
{
|
||||
if (!update_low_latency_tech(pDevice))
|
||||
return InputResult::LowLatencyUpdateFail;
|
||||
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
current_tech->sleep(frame_id);
|
||||
else
|
||||
return InputResult::GenericError;
|
||||
|
||||
return InputResult::Ok;
|
||||
}
|
||||
|
||||
InputResult InputCommon::set_marker(const InputContext& inputContext, IUnknown* pDevice, MarkerParams* marker_params)
|
||||
{
|
||||
if (!update_low_latency_tech(pDevice))
|
||||
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::PRESENT_START)
|
||||
{
|
||||
return InputResult::InputNotSupported;
|
||||
}
|
||||
|
||||
// update_effective_fg_state();
|
||||
|
||||
// update_enabled_override();
|
||||
|
||||
add_marker_to_report(marker_params);
|
||||
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
current_tech->set_marker(pDevice, marker_params);
|
||||
else
|
||||
return InputResult::GenericError;
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return InputResult::InputNotSupported;
|
||||
}
|
||||
|
||||
// TODO: could consider adding async markers to the report but would require some rewriting
|
||||
// add_marker_to_report(marker_params);
|
||||
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
current_tech->set_async_marker(pCommandQueue, marker_params);
|
||||
else
|
||||
return InputResult::GenericError;
|
||||
|
||||
LOG_TRACE_LOWLATENCY("{}: {}", magic_enum::enum_name(marker_params->marker_type), marker_params->frame_id);
|
||||
|
||||
return InputResult::Ok;
|
||||
}
|
||||
|
||||
// TODO: impl
|
||||
InputResult InputCommon::set_sleep_mode(const InputContext& inputContext, IUnknown* pDevice, SleepMode* sleep_mode)
|
||||
{
|
||||
return InputResult::Ok;
|
||||
}
|
||||
|
||||
// TODO: impl
|
||||
InputResult InputCommon::get_sleep_status(const InputContext& inputContext, IUnknown* pDevice,
|
||||
SleepParams* sleep_params)
|
||||
{
|
||||
return InputResult::Ok;
|
||||
}
|
||||
|
||||
InputResult InputCommon::get_latency(const InputContext& inputContext, IUnknown* pDev, void* latency_params)
|
||||
{
|
||||
if (!latency_params)
|
||||
return InputResult::InvalidParameter;
|
||||
|
||||
if (inputContext.caller == LowLatencyInput::Reflex)
|
||||
{
|
||||
if (activeOutput == LowLatencyMode::Reflex)
|
||||
{
|
||||
// TODO: passthrough call, if success return InputResult::Ok;
|
||||
// return InputResult::Ok;
|
||||
}
|
||||
|
||||
NV_LATENCY_RESULT_PARAMS* reports = (NV_LATENCY_RESULT_PARAMS*) latency_params;
|
||||
|
||||
if (reports->version != NV_LATENCY_RESULT_PARAMS_VER1)
|
||||
{
|
||||
LOG_ERROR("Unsupported version {}", reports->version);
|
||||
return InputResult::InvalidParameter;
|
||||
}
|
||||
|
||||
// Assume no frame reports collected yet, report all zeros
|
||||
if (frame_reports[FRAME_REPORTS_BUFFER_SIZE - 1].frameID == 0)
|
||||
{
|
||||
std::memset(reports->frameReport, 0, sizeof(reports->frameReport));
|
||||
// spdlog::warn("GetLatency: Not enough data to report");
|
||||
return InputResult::GenericError;
|
||||
}
|
||||
|
||||
// Sort frame reports, find the oldest
|
||||
size_t minIdx = 0;
|
||||
uint64_t minID = frame_reports[0].frameID;
|
||||
for (size_t i = 1; i < FRAME_REPORTS_BUFFER_SIZE; i++)
|
||||
{
|
||||
if (frame_reports[i].frameID < minID)
|
||||
{
|
||||
minID = frame_reports[i].frameID;
|
||||
minIdx = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy starting from older before wrapping around
|
||||
size_t firstChunk = std::min<uint64_t>(NVAPI_BUFFER_SIZE, FRAME_REPORTS_BUFFER_SIZE - minIdx);
|
||||
std::memcpy(reports->frameReport, frame_reports + minIdx, firstChunk * sizeof(FrameReport));
|
||||
|
||||
// Copy the rest after wrapping around
|
||||
if (firstChunk < NVAPI_BUFFER_SIZE)
|
||||
{
|
||||
std::memcpy(reports->frameReport + firstChunk, frame_reports,
|
||||
(NVAPI_BUFFER_SIZE - firstChunk) * sizeof(FrameReport));
|
||||
}
|
||||
|
||||
return InputResult::Ok;
|
||||
}
|
||||
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
|
||||
|
||||
// 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++)
|
||||
{
|
||||
auto& reportOut = reports[i];
|
||||
auto& reportIn = frame_reports[i];
|
||||
|
||||
reportOut.m_frame_id = reportIn.frameID & 0xFFFFFFFF;
|
||||
reportOut.m_sim_start_ts = reportIn.simStartTime;
|
||||
reportOut.m_sim_end_ts = reportIn.simEndTime;
|
||||
reportOut.m_render_submit_start_ts = reportIn.renderSubmitStartTime;
|
||||
reportOut.m_render_submit_end_ts = reportIn.renderSubmitEndTime;
|
||||
reportOut.m_present_start_ts = reportIn.presentStartTime;
|
||||
reportOut.m_present_end_ts = reportIn.presentEndTime;
|
||||
}
|
||||
|
||||
return InputResult::Ok;
|
||||
}
|
||||
else
|
||||
{
|
||||
return InputResult::InputNotSupported;
|
||||
}
|
||||
}
|
||||
|
||||
xell_result_t InputCommon::pass_xellD3D12SetAppQueue(const InputContext& inputContext, void* appQueue)
|
||||
{
|
||||
if (inputContext.caller == LowLatencyInput::XeLL && activeInput == LowLatencyInput::XeLL &&
|
||||
activeOutput == LowLatencyMode::XeLL)
|
||||
{
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
{
|
||||
auto xell_tech = std::static_pointer_cast<XeLL>(current_tech);
|
||||
return xell_tech->xellD3D12SetAppQueue(appQueue);
|
||||
}
|
||||
}
|
||||
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
xell_result_t InputCommon::pass_xellSetDisplayInfo(const InputContext& inputContext, void* displayInfo)
|
||||
{
|
||||
if (inputContext.caller == LowLatencyInput::XeLL && activeInput == LowLatencyInput::XeLL &&
|
||||
activeOutput == LowLatencyMode::XeLL)
|
||||
{
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
{
|
||||
auto xell_tech = std::static_pointer_cast<XeLL>(current_tech);
|
||||
return xell_tech->xellSetDisplayInfo(displayInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
xell_result_t InputCommon::pass_xellSetFgEnabled(const InputContext& inputContext, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
if (inputContext.caller == LowLatencyInput::XeLL && activeInput == LowLatencyInput::XeLL &&
|
||||
activeOutput == LowLatencyMode::XeLL)
|
||||
{
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
{
|
||||
auto xell_tech = std::static_pointer_cast<XeLL>(current_tech);
|
||||
return xell_tech->xellSetFgEnabled(param1, param2);
|
||||
}
|
||||
}
|
||||
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
xell_result_t InputCommon::pass_xellSetGeneratedFramesCount(const InputContext& inputContext, uint32_t param1,
|
||||
uint32_t framesCount)
|
||||
{
|
||||
if (inputContext.caller == LowLatencyInput::XeLL && activeInput == LowLatencyInput::XeLL &&
|
||||
activeOutput == LowLatencyMode::XeLL)
|
||||
{
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
{
|
||||
auto xell_tech = std::static_pointer_cast<XeLL>(current_tech);
|
||||
return xell_tech->xellSetGeneratedFramesCount(param1, framesCount);
|
||||
}
|
||||
}
|
||||
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
xell_result_t InputCommon::pass_xellGetLastPresentStartFrameId(const InputContext& inputContext, uint32_t* p_frame_id)
|
||||
{
|
||||
if (inputContext.caller == LowLatencyInput::XeLL && activeInput == LowLatencyInput::XeLL &&
|
||||
activeOutput == LowLatencyMode::XeLL)
|
||||
{
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
{
|
||||
auto xell_tech = std::static_pointer_cast<XeLL>(current_tech);
|
||||
return xell_tech->xellGetLastPresentStartFrameId(p_frame_id);
|
||||
}
|
||||
}
|
||||
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
#pragma once
|
||||
#include <low_latency/low_latency_tech/low_latency_tech.h>
|
||||
#include <xell.h>
|
||||
|
||||
enum class LowLatencyInput
|
||||
{
|
||||
None,
|
||||
AntiLag2,
|
||||
Reflex,
|
||||
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,
|
||||
};
|
||||
|
||||
struct InputContext
|
||||
{
|
||||
LowLatencyInput caller;
|
||||
// bool sleepWithFrameId;
|
||||
bool noFrameId;
|
||||
InputMarkerMode markerMode;
|
||||
};
|
||||
|
||||
enum class InputResult : uint32_t
|
||||
{
|
||||
Ok,
|
||||
InputNotSupported,
|
||||
InvalidParameter,
|
||||
LowLatencyUpdateFail,
|
||||
GenericError,
|
||||
};
|
||||
|
||||
class InputCommon
|
||||
{
|
||||
inline static std::atomic<std::shared_ptr<LowLatencyTech>> currently_active_tech;
|
||||
inline static FrameReport frame_reports[FRAME_REPORTS_BUFFER_SIZE] {};
|
||||
|
||||
inline static LowLatencyInput activeInput = LowLatencyInput::None;
|
||||
inline static LowLatencyMode activeOutput = LowLatencyMode::None;
|
||||
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);
|
||||
|
||||
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,
|
||||
std::optional<uint32_t> frame_id = std::nullopt);
|
||||
static InputResult set_marker(const InputContext& inputContext, IUnknown* pDevice, MarkerParams* marker_params);
|
||||
static InputResult set_async_marker(const InputContext& inputContext, ID3D12CommandQueue* pCommandQueue,
|
||||
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
|
||||
get_latency(const InputContext& inputContext, IUnknown* pDev,
|
||||
void* latency_params); // NV_LATENCY_RESULT_PARAMS* for reflex, xell_frame_report_t* for xell,
|
||||
// passthrough when possible, fillout with local frame_reports if not
|
||||
|
||||
// XeLL-specific calls for passthrough, TODO: only allow when caller == activeOutput == activeInput == XeLL
|
||||
static xell_result_t pass_xellD3D12SetAppQueue(
|
||||
const InputContext& inputContext,
|
||||
void* appQueue); // if it's ID3D12CommandQueue* then some translation with async markers can be made
|
||||
static xell_result_t pass_xellSetDisplayInfo(const InputContext& inputContext, void* displayInfo);
|
||||
static xell_result_t pass_xellSetFgEnabled(const InputContext& inputContext, uint32_t param1, uint32_t param2);
|
||||
static xell_result_t pass_xellSetGeneratedFramesCount(const InputContext& inputContext, uint32_t param1,
|
||||
uint32_t framesCount);
|
||||
static xell_result_t pass_xellGetLastPresentStartFrameId(const InputContext& inputContext,
|
||||
uint32_t* p_frame_id); // Maybe not needed
|
||||
};
|
||||
@@ -22,7 +22,8 @@ enum class LowLatencyMode
|
||||
LatencyFlex,
|
||||
AntiLag2,
|
||||
XeLL,
|
||||
AntiLagVk
|
||||
AntiLagVk,
|
||||
Reflex
|
||||
};
|
||||
|
||||
void tonvss(NvAPI_ShortString nvss, std::string str);
|
||||
|
||||
@@ -185,7 +185,7 @@ void AntiLag2::set_sleep_mode(SleepMode* sleep_mode)
|
||||
sleep_mode->minimum_interval_us; // don't convert to fps due to fg fps limit fallback using intervals
|
||||
}
|
||||
|
||||
void AntiLag2::sleep()
|
||||
void AntiLag2::sleep(std::optional<uint32_t> frame_id)
|
||||
{
|
||||
last_sleep_framecount = simulation_framecount;
|
||||
|
||||
@@ -219,7 +219,7 @@ void AntiLag2::set_marker(IUnknown* pDevice, MarkerParams* marker_params)
|
||||
}
|
||||
}
|
||||
|
||||
void AntiLag2::set_async_marker(MarkerParams* marker_params)
|
||||
void AntiLag2::set_async_marker(IUnknown* pCommandQueue, MarkerParams* marker_params)
|
||||
{
|
||||
if (marker_params->marker_type == MarkerType::OUT_OF_BAND_PRESENT_START)
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <ffx_antilag2_dx12.h>
|
||||
#include <ffx_antilag2_dx11.h>
|
||||
|
||||
class AntiLag2 : public virtual LowLatencyTech
|
||||
class AntiLag2 : public LowLatencyTech
|
||||
{
|
||||
private:
|
||||
AMD::AntiLag2DX12::Context dx12_ctx = {};
|
||||
@@ -47,7 +47,7 @@ class AntiLag2 : public virtual LowLatencyTech
|
||||
|
||||
void get_sleep_status(SleepParams* sleep_params) override;
|
||||
void set_sleep_mode(SleepMode* sleep_mode) override;
|
||||
void sleep() override;
|
||||
void sleep(std::optional<uint32_t> frame_id) override;
|
||||
void set_marker(IUnknown* pDevice, MarkerParams* marker_params) override;
|
||||
void set_async_marker(MarkerParams* marker_params) override;
|
||||
void set_async_marker(IUnknown* pCommandQueue, MarkerParams* marker_params) override;
|
||||
};
|
||||
@@ -32,7 +32,7 @@ void AntiLagVk::set_sleep_mode(SleepMode* sleep_mode)
|
||||
sleep_mode->minimum_interval_us > 0 ? (uint32_t) std::round(1000000.0f / sleep_mode->minimum_interval_us) : 0;
|
||||
}
|
||||
|
||||
void AntiLagVk::sleep()
|
||||
void AntiLagVk::sleep(std::optional<uint32_t> frame_id)
|
||||
{
|
||||
// This can be supported but prefer using markers with frame ids instead
|
||||
return;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "low_latency_tech.h"
|
||||
|
||||
class AntiLagVk : public virtual LowLatencyTech
|
||||
class AntiLagVk : public LowLatencyTech
|
||||
{
|
||||
private:
|
||||
uint32_t max_fps = 0;
|
||||
@@ -32,7 +32,7 @@ class AntiLagVk : public virtual LowLatencyTech
|
||||
|
||||
void get_sleep_status(SleepParams* sleep_params) override;
|
||||
void set_sleep_mode(SleepMode* sleep_mode) override;
|
||||
void sleep() override;
|
||||
void sleep(std::optional<uint32_t> frame_id) override;
|
||||
void set_marker(IUnknown* pDevice, MarkerParams* marker_params) override;
|
||||
void set_async_marker(MarkerParams* marker_params) override {}; // Not used by AntiLag VK
|
||||
void set_async_marker(IUnknown* pCommandQueue, MarkerParams* marker_params) override {}; // Not used by AntiLag VK
|
||||
};
|
||||
@@ -152,14 +152,19 @@ void LatencyFlex::set_sleep_mode(SleepMode* sleep_mode)
|
||||
minimum_interval_us = sleep_mode->minimum_interval_us;
|
||||
};
|
||||
|
||||
void LatencyFlex::sleep()
|
||||
void LatencyFlex::sleep(std::optional<uint32_t> frame_id)
|
||||
{
|
||||
if ((LFXMode) Config::Instance()->FN_LatencyFlexMode.value_or_default() != LFXMode::ReflexIDs)
|
||||
{
|
||||
last_sleep_framecount = simulation_framecount;
|
||||
|
||||
if (current_call_spot == CallSpot::SleepCall)
|
||||
lfx_sleep(INVALID_ID);
|
||||
{
|
||||
if (frame_id.has_value())
|
||||
lfx_sleep(frame_id.value());
|
||||
else
|
||||
lfx_sleep(INVALID_ID);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "low_latency_tech.h"
|
||||
#include <latencyflex.h>
|
||||
|
||||
class LatencyFlex : public virtual LowLatencyTech
|
||||
class LatencyFlex : public LowLatencyTech
|
||||
{
|
||||
private:
|
||||
lfx::LatencyFleX* ctx = nullptr;
|
||||
@@ -51,7 +51,7 @@ class LatencyFlex : public virtual LowLatencyTech
|
||||
|
||||
void get_sleep_status(SleepParams* sleep_params) override;
|
||||
void set_sleep_mode(SleepMode* sleep_mode) override;
|
||||
void sleep() override;
|
||||
void sleep(std::optional<uint32_t> frame_id) override;
|
||||
void set_marker(IUnknown* pDevice, MarkerParams* marker_params) override;
|
||||
void set_async_marker(MarkerParams* marker_params) override {}; // Not used by LFX
|
||||
void set_async_marker(IUnknown* pCommandQueue, MarkerParams* marker_params) override {}; // Not used by LFX
|
||||
};
|
||||
@@ -183,10 +183,55 @@ void XeLL::set_marker(IUnknown* pDevice, MarkerParams* marker_params)
|
||||
}
|
||||
}
|
||||
|
||||
void XeLL::sleep()
|
||||
void XeLL::sleep(std::optional<uint32_t> frame_id)
|
||||
{
|
||||
// This can either be better than sleeping in XELL_SIMULATION_START
|
||||
// or be a total mess if +1 is not correct
|
||||
sleep_last_id = simulation_start_last_id + 1;
|
||||
xell_sleep((uint32_t) sleep_last_id);
|
||||
if (frame_id.has_value())
|
||||
xell_sleep(frame_id.value());
|
||||
else
|
||||
{
|
||||
// This can either be better than sleeping in XELL_SIMULATION_START
|
||||
// or be a total mess if +1 is not correct
|
||||
sleep_last_id = simulation_start_last_id + 1;
|
||||
xell_sleep((uint32_t) sleep_last_id);
|
||||
}
|
||||
}
|
||||
|
||||
xell_result_t XeLL::xellD3D12SetAppQueue(void* appQueue) const
|
||||
{
|
||||
if (!o_xellD3D12SetAppQueue)
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
|
||||
return o_xellD3D12SetAppQueue(XeLLProxy::Context(), appQueue);
|
||||
}
|
||||
|
||||
xell_result_t XeLL::xellSetDisplayInfo(void* displayInfo) const
|
||||
{
|
||||
if (!o_xellSetDisplayInfo)
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
|
||||
return o_xellSetDisplayInfo(XeLLProxy::Context(), displayInfo);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
xell_result_t XeLL::xellSetGeneratedFramesCount(uint32_t param1, uint32_t framesCount) const
|
||||
{
|
||||
if (!o_xellSetGeneratedFramesCount)
|
||||
return XELL_RESULT_ERROR_UNKNOWN;
|
||||
|
||||
return o_xellSetGeneratedFramesCount(XeLLProxy::Context(), param1, framesCount);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -3,13 +3,21 @@
|
||||
#include "low_latency_tech.h"
|
||||
|
||||
#include <xell_d3d12.h>
|
||||
#include "low_latency/input/input_xell.h"
|
||||
|
||||
class XeLL : public virtual LowLatencyTech
|
||||
class XeLL : public LowLatencyTech
|
||||
{
|
||||
bool sent_sleep_frame_ids[64] {};
|
||||
uint64_t simulation_start_last_id {};
|
||||
uint64_t sleep_last_id {};
|
||||
|
||||
// TODO: set those
|
||||
decltype(&xellD3D12SetAppQueue) o_xellD3D12SetAppQueue = nullptr;
|
||||
decltype(&xellSetDisplayInfo) o_xellSetDisplayInfo = nullptr;
|
||||
decltype(&xellSetFgEnabled) o_xellSetFgEnabled = nullptr;
|
||||
decltype(&xellSetGeneratedFramesCount) o_xellSetGeneratedFramesCount = nullptr;
|
||||
decltype(&xellGetLastPresentStartFrameId) o_xellGetLastPresentStartFrameId = nullptr; // Maybe not needed
|
||||
|
||||
void xell_sleep(uint32_t frame_id);
|
||||
void add_marker(uint32_t frame_id, xell_latency_marker_type_t marker);
|
||||
|
||||
@@ -38,7 +46,14 @@ class XeLL : public virtual LowLatencyTech
|
||||
|
||||
void get_sleep_status(SleepParams* sleep_params) override;
|
||||
void set_sleep_mode(SleepMode* sleep_mode) override;
|
||||
void sleep() override;
|
||||
void sleep(std::optional<uint32_t> frame_id) override;
|
||||
void set_marker(IUnknown* pDevice, MarkerParams* marker_params) override;
|
||||
void set_async_marker(MarkerParams* marker_params) override {}; // Not used by XeLL
|
||||
void set_async_marker(IUnknown* pCommandQueue, MarkerParams* marker_params) override {}; // Not used by XeLL
|
||||
|
||||
// For passthrough
|
||||
xell_result_t xellD3D12SetAppQueue(void* appQueue) const;
|
||||
xell_result_t xellSetDisplayInfo(void* displayInfo) const;
|
||||
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;
|
||||
};
|
||||
@@ -84,7 +84,7 @@ class LowLatencyTech
|
||||
|
||||
virtual void get_sleep_status(SleepParams* sleep_params) = 0;
|
||||
virtual void set_sleep_mode(SleepMode* sleep_mode) = 0;
|
||||
virtual void sleep() = 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(MarkerParams* marker_params) = 0;
|
||||
virtual void set_async_marker(IUnknown* pCommandQueue, MarkerParams* marker_params) = 0;
|
||||
};
|
||||
@@ -325,7 +325,7 @@ NvAPI_Status LowLatency::SetAsyncFrameMarker(ID3D12CommandQueue* pCommandQueue,
|
||||
}
|
||||
|
||||
if (auto current_tech = currently_active_tech.load())
|
||||
current_tech->set_async_marker(&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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user