Merge pull request #2 from FakeMichau/antilag2

AntiLag 2 and LatencyFlex
This commit is contained in:
Michał Lewandowski
2024-09-13 01:01:31 +02:00
committed by GitHub
10 changed files with 401 additions and 139 deletions
+128 -30
View File
@@ -1,24 +1,24 @@
#include "nvapi.h"
#include "fakenvapi.h"
#include <string>
namespace nvd {
NvAPI_Status __cdecl NvAPI_Initialize() {
IDXGIFactory1* pFactory = nullptr;
if (FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory))) {
log("Failed to create DXGI Factory");
spdlog::error("Failed to create DXGI Factory");
return Error();
}
IDXGIAdapter1* pAdapter = nullptr;
if (FAILED(pFactory->EnumAdapters1(0, &pAdapter))) {
log("Failed to enumerate adapters");
spdlog::error("Failed to enumerate adapters");
pFactory->Release();
return Error();
}
DXGI_ADAPTER_DESC1 adapterDesc;
if (FAILED(pAdapter->GetDesc1(&adapterDesc))) {
log("Failed to get adapter description");
spdlog::error("Failed to get adapter description");
pAdapter->Release();
pFactory->Release();
return Error();
@@ -33,6 +33,8 @@ namespace nvd {
pAdapter->Release();
pFactory->Release();
lowlatency_ctx.init_lfx();
return Ok();
}
@@ -57,7 +59,7 @@ namespace nvd {
if (displayId == 0) {
return Ok();
}
return Error(NVAPI_NVIDIA_DISPLAY_NOT_FOUND);
return Error(NVAPI_END_ENUMERATION);
}
NvAPI_Status __cdecl NvAPI_GetLogicalGPUFromPhysicalGPU(NvPhysicalGpuHandle physicalHandle, NvLogicalGpuHandle* logicalHandle) {
@@ -85,7 +87,7 @@ namespace nvd {
NvAPI_Status __cdecl NvAPI_GetErrorMessage(NvAPI_Status status, NvAPI_ShortString szMsg) {
std::string error = fromErrorNr(status);
log(std::format("NvAPI_GetErrorMessage gave this error: {}", error));
spdlog::error("NvAPI_GetErrorMessage gave this error: {}", error);
tonvss(szMsg, error);
return Ok();
}
@@ -105,12 +107,12 @@ namespace nvd {
}
NvAPI_Status __cdecl NvAPI_GPU_GetArchInfo(NvPhysicalGpuHandle handle, NV_GPU_ARCH_INFO* archInfo) {
archInfo->architecture = spoof::arch;
archInfo->architecture_id = spoof::arch;
archInfo->implementation = spoof::implementation;
archInfo->implementation_id = spoof::implementation;
archInfo->revision = spoof::revision;
archInfo->revision_id = spoof::revision;
archInfo->architecture = NV_GPU_ARCHITECTURE_AD100;
archInfo->architecture_id = NV_GPU_ARCHITECTURE_AD100;
archInfo->implementation = NV_GPU_ARCH_IMPLEMENTATION_AD102;
archInfo->implementation_id = NV_GPU_ARCH_IMPLEMENTATION_AD102;
archInfo->revision = NV_GPU_CHIP_REV_UNKNOWN;
archInfo->revision_id = NV_GPU_CHIP_REV_UNKNOWN;
return Ok();
}
@@ -131,7 +133,7 @@ namespace nvd {
}
NvAPI_Status __cdecl NvAPI_GPU_GetFullName(NvPhysicalGpuHandle hPhysicalGpu, NvAPI_ShortString szName) {
tonvss(szName, spoof::fullGPUName);
tonvss(szName, "NVIDIA GeForce RTX 4090");
return Ok();
}
@@ -262,15 +264,19 @@ namespace nvd {
}
NvAPI_Status __cdecl NvAPI_SYS_GetDisplayDriverInfo(NV_DISPLAY_DRIVER_INFO* driverInfo) {
spoof::driverInfo(driverInfo);
driverInfo->driverVersion = 99999;
tonvss(driverInfo->szBuildBranch, "buildBranch");
driverInfo->bIsDCHDriver = 1;
driverInfo->bIsNVIDIAStudioPackage = 1;
driverInfo->bIsNVIDIARTXProductionBranchPackage = 1;
driverInfo->bIsNVIDIARTXNewFeatureBranchPackage = 1;
if (driverInfo->version == 2)
tonvss(driverInfo->szBuildBaseBranch, "buildBaseBranch");
return Ok();
}
NvAPI_Status __cdecl NvAPI_SYS_GetDriverAndBranchVersion(NvU32* pDriverVersion, NvAPI_ShortString szBuildBranchString) {
memset(pDriverVersion, 0, sizeof(NvU32));
memcpy(pDriverVersion, &spoof::driverVersion, sizeof(NvU32));
// *pDriverVersion = spoof::driverVersion;
tonvss(szBuildBranchString, spoof::buildBranch);
tonvss(szBuildBranchString, "buildBranch");
return Ok();
}
@@ -295,6 +301,9 @@ namespace nvd {
}
NvAPI_Status __cdecl NvAPI_D3D_GetSleepStatus(IUnknown* pDevice, NV_GET_SLEEP_STATUS_PARAMS* pGetSleepStatusParams) {
pGetSleepStatusParams->bLowLatencyMode = lowlatency_ctx.active;
pGetSleepStatusParams->bFsVrr = true;
pGetSleepStatusParams->bCplVsyncOn = true;
return Ok();
}
@@ -303,14 +312,46 @@ namespace nvd {
}
NvAPI_Status __cdecl NvAPI_D3D_SetSleepMode(IUnknown* pDevice, NV_SET_SLEEP_MODE_PARAMS* pSetSleepModeParams) {
lowlatency_ctx.active = pSetSleepModeParams->bLowLatencyMode;
#ifdef TESTING
lowlatency_ctx.force_lfx = pSetSleepModeParams->bLowLatencyBoost;
#endif
lowlatency_ctx.set_min_interval_us(pSetSleepModeParams->minimumIntervalUs);
return Ok();
}
NvAPI_Status __cdecl NvAPI_D3D_SetLatencyMarker(IUnknown* pDev, NV_LATENCY_MARKER_PARAMS* pSetLatencyMarkerParams) {
if (!pDev)
return Error();
spdlog::debug("markerType: {}, frame id: {}", (unsigned int)pSetLatencyMarkerParams->markerType, (unsigned long long)pSetLatencyMarkerParams->frameID);
lowlatency_ctx.init_al2(pDev);
switch (pSetLatencyMarkerParams->markerType) {
case SIMULATION_START:
if (lowlatency_ctx.call_spot != SimulationStart) break;
spdlog::debug("LowLatency update called on simulation start with result: {}", lowlatency_ctx.update());
break;
case INPUT_SAMPLE:
if (lowlatency_ctx.call_spot == SleepCall) break;
lowlatency_ctx.call_spot = InputSample;
spdlog::debug("LowLatency update called on input sample with result: {}", lowlatency_ctx.update());
break;
case PRESENT_START:
if (lowlatency_ctx.fg) lowlatency_ctx.mark_end_of_rendering();
break;
}
return Ok();
}
NvAPI_Status __cdecl NvAPI_D3D_Sleep(IUnknown* pDevice) {
if (!pDevice)
return Error();
lowlatency_ctx.init_al2(pDevice);
lowlatency_ctx.call_spot = SleepCall;
spdlog::debug("LowLatency update called on sleep with result: {}", lowlatency_ctx.update());
return Ok();
}
NvAPI_Status __cdecl NvAPI_D3D_SetReflexSync(IUnknown* pDev, NV_SET_REFLEX_SYNC_PARAMS* pSetReflexSyncParams) {
return Ok();
}
@@ -390,6 +431,7 @@ namespace nvd {
return Ok();
}
// Taken directly from dxvk-nvapi
static bool ConvertBuildRaytracingAccelerationStructureInputs(const NVAPI_D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS_EX* nvDesc, std::vector<D3D12_RAYTRACING_GEOMETRY_DESC>& geometryDescs, D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS* d3dDesc) {
d3dDesc->Type = nvDesc->type;
// assume that OMM via VK_EXT_opacity_micromap and DMM via VK_NV_displacement_micromap are not supported, allow only standard flags to be passed
@@ -426,13 +468,13 @@ namespace nvd {
d3dGeoDesc.AABBs = nvGeoDesc.aabbs;
break;
case NVAPI_D3D12_RAYTRACING_GEOMETRY_TYPE_OMM_TRIANGLES_EX: // GetRaytracingCaps reports no OMM caps, we shouldn't reach this
log("Triangles with OMM attachment passed to acceleration structure build when OMM is not supported");
spdlog::error("Triangles with OMM attachment passed to acceleration structure build when OMM is not supported");
return false;
case NVAPI_D3D12_RAYTRACING_GEOMETRY_TYPE_DMM_TRIANGLES_EX: // GetRaytracingCaps reports no DMM caps, we shouldn't reach this
log("Triangles with DMM attachment passed to acceleration structure build when DMM is not supported");
spdlog::error("Triangles with DMM attachment passed to acceleration structure build when DMM is not supported");
return false;
default:
log("Unknown NVAPI_D3D12_RAYTRACING_GEOMETRY_TYPE_EX");
spdlog::error("Unknown NVAPI_D3D12_RAYTRACING_GEOMETRY_TYPE_EX");
return false;
}
}
@@ -468,7 +510,12 @@ namespace nvd {
return Error(NVAPI_INVALID_ARGUMENT);
pCommandList->BuildRaytracingAccelerationStructure(&desc, pParams->numPostbuildInfoDescs, pParams->pPostbuildInfoDescs);
return Ok();
static bool logged = false;
if (!logged) {
logged = true;
return Ok();
}
else return NVAPI_OK; //return without logging
}
NvAPI_Status __cdecl NvAPI_D3D12_NotifyOutOfBandCommandQueue(ID3D12CommandQueue* pCommandQueue, NV_OUT_OF_BAND_CQ_TYPE cqType) {
@@ -476,6 +523,30 @@ namespace nvd {
}
NvAPI_Status __cdecl NvAPI_D3D12_SetAsyncFrameMarker(ID3D12CommandQueue* pCommandQueue, NV_ASYNC_FRAME_MARKER_PARAMS* pSetAsyncFrameMarkerParams) {
if (pSetAsyncFrameMarkerParams->markerType == OUT_OF_BAND_PRESENT_START) {
constexpr unsigned int history_size = 10;
static NvU64 counter = 0;
static NvU64 previous_frame_ids[history_size] = {};
static NvU64 previous_frame_id = 0;
NvU64 current_frame_id = pSetAsyncFrameMarkerParams->frameID;
previous_frame_ids[counter%history_size] = current_frame_id;
counter++;
std::unordered_set<NvU64> seen;
unsigned int repeat_count = 0;
for (const NvU64& frame_id : previous_frame_ids) {
if (seen.contains(frame_id)) repeat_count++;
else seen.insert(frame_id);
}
if (lowlatency_ctx.fg && repeat_count == 0) lowlatency_ctx.fg = false;
else if (!lowlatency_ctx.fg && repeat_count >= history_size / 2) lowlatency_ctx.fg = true;
if (lowlatency_ctx.fg) lowlatency_ctx.set_fg_type(previous_frame_id == current_frame_id);
previous_frame_id = current_frame_id;
}
spdlog::debug("Async markerType: {}, frame id: {}", (unsigned int)pSetAsyncFrameMarkerParams->markerType, (unsigned long long)pSetAsyncFrameMarkerParams->frameID);
return Ok();
}
@@ -488,30 +559,57 @@ namespace nvd {
return Ok();
}
NvAPI_Status __cdecl NvAPI_DRS_SaveSettings(NvDRSSessionHandle session) {
return Ok();
}
NvAPI_Status __cdecl NvAPI_DRS_GetBaseProfile(NvDRSSessionHandle session, NvDRSProfileHandle* profile) {
*profile = drsProfile;
return Ok();
}
NvAPI_Status __cdecl NvAPI_DRS_GetSetting(NvDRSSessionHandle hSession, NvDRSProfileHandle hProfile, NvU32 settingId, NVDRS_SETTING* pSetting) {
log(std::format("Missing setting: {}", settingId));
return Error(NVAPI_SETTING_NOT_FOUND);
spdlog::debug("Missing get setting: {}", settingId);
return Ok();
}
NvAPI_Status __cdecl NvAPI_DRS_SetSetting(NvDRSSessionHandle hSession, NvDRSProfileHandle hProfile, NVDRS_SETTING *pSetting) {
spdlog::debug("Missing set setting: {}", pSetting->settingId);
return Ok();
}
NvAPI_Status __cdecl NvAPI_DRS_DestroySession(NvDRSSessionHandle session) {
return Ok();
}
NvAPI_Status __cdecl NvAPI_Unload() {
return Ok();
}
NvAPI_Status __cdecl MISC_unknown(IUnknown* unknown, uint32_t* pMiscUnk) {
NvAPI_Status __cdecl NvAPI_Unknown_1(IUnknown* unknown, uint32_t* pMiscUnk) {
std::fill(pMiscUnk, pMiscUnk + 4, 0x1);
return Ok();
}
NvAPI_Status __cdecl MISC_vulkan(IUnknown* unknown) {
NvAPI_Status __cdecl NvAPI_Vulkan_1(IUnknown* unknown) {
return Ok();
}
NvAPI_Status __cdecl NvAPI_Unload() {
lowlatency_ctx.unload();
return Ok();
}
NvAPI_Status __cdecl Dummy_GetLatency(uint64_t* call_spot, uint64_t* target, uint64_t* latency, uint64_t* frame_time) {
#if _MSC_VER && _WIN64
if (!call_spot || !target || !latency || !frame_time) return Error(NVAPI_INVALID_POINTER);
if (lowlatency_ctx.get_mode() != LatencyFlex) return Error(NVAPI_DATA_NOT_FOUND);
*call_spot = (uint64_t)lowlatency_ctx.call_spot;
*target = lowlatency_ctx.lfx_stats.target;
*latency = lowlatency_ctx.lfx_stats.latency;
*frame_time = lowlatency_ctx.lfx_stats.frame_time;
return Ok();
#else
return Error(NVAPI_DATA_NOT_FOUND);
#endif
}
}
+12 -4
View File
@@ -1,6 +1,8 @@
#pragma once
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <numeric>
#include <format>
#include <dxgi.h>
@@ -11,8 +13,9 @@
#endif
#include <vector>
#include "lowlatency.h"
#include "util.h"
#include "spoofInfo.h"
#include "log.h"
namespace nvd {
@@ -20,13 +23,14 @@ namespace nvd {
static auto drsSession = reinterpret_cast<NvDRSSessionHandle>(&drs);
static auto drsProfile = reinterpret_cast<NvDRSProfileHandle>(&drs);
static LUID luid;
static UINT deviceId;
static UINT vendorId;
static UINT subSysId;
static UINT revisionId;
static LowLatency lowlatency_ctx;
NvAPI_Status __cdecl NvAPI_Initialize();
NvAPI_Status __cdecl NvAPI_GetInterfaceVersionString(NvAPI_ShortString desc);
NvAPI_Status __cdecl NvAPI_EnumPhysicalGPUs(NvPhysicalGpuHandle handles[NVAPI_MAX_PHYSICAL_GPUS], NvU32* count);
@@ -63,6 +67,7 @@ namespace nvd {
NvAPI_Status __cdecl NvAPI_D3D_SetSleepMode(IUnknown* pDevice, NV_SET_SLEEP_MODE_PARAMS* pSetSleepModeParams);
NvAPI_Status __cdecl NvAPI_D3D_SetLatencyMarker(IUnknown* pDev, NV_LATENCY_MARKER_PARAMS* pSetLatencyMarkerParams);
NvAPI_Status __cdecl NvAPI_D3D_Sleep(IUnknown* pDevice);
NvAPI_Status __cdecl NvAPI_D3D_SetReflexSync(IUnknown* pDev, NV_SET_REFLEX_SYNC_PARAMS* pSetReflexSyncParams);
NvAPI_Status __cdecl NvAPI_D3D11_IsNvShaderExtnOpCodeSupported(IUnknown* invalid, NvU32 opCode, bool* pSupported);
NvAPI_Status __cdecl NvAPI_D3D11_BeginUAVOverlap(IUnknown* pDeviceOrContext);
NvAPI_Status __cdecl NvAPI_D3D11_EndUAVOverlap(IUnknown* pDeviceOrContext);
@@ -76,10 +81,13 @@ namespace nvd {
NvAPI_Status __cdecl NvAPI_D3D12_SetAsyncFrameMarker(ID3D12CommandQueue* pCommandQueue, NV_ASYNC_FRAME_MARKER_PARAMS* pSetAsyncFrameMarkerParams);
NvAPI_Status __cdecl NvAPI_DRS_CreateSession(NvDRSSessionHandle* session);
NvAPI_Status __cdecl NvAPI_DRS_LoadSettings(NvDRSSessionHandle session);
NvAPI_Status __cdecl NvAPI_DRS_SaveSettings(NvDRSSessionHandle session);
NvAPI_Status __cdecl NvAPI_DRS_GetBaseProfile(NvDRSSessionHandle session, NvDRSProfileHandle* profile);
NvAPI_Status __cdecl NvAPI_DRS_GetSetting(NvDRSSessionHandle hSession, NvDRSProfileHandle hProfile, NvU32 settingId, NVDRS_SETTING* pSetting);
NvAPI_Status __cdecl NvAPI_DRS_SetSetting(NvDRSSessionHandle hSession, NvDRSProfileHandle hProfile, NVDRS_SETTING *pSetting);
NvAPI_Status __cdecl NvAPI_DRS_DestroySession(NvDRSSessionHandle session);
NvAPI_Status __cdecl NvAPI_Unknown_1(IUnknown* unknown, uint32_t* pMiscUnk);
NvAPI_Status __cdecl NvAPI_Vulkan_1(IUnknown* unknown);
NvAPI_Status __cdecl NvAPI_Unload();
NvAPI_Status __cdecl MISC_unknown(IUnknown* unknown, uint32_t* pMiscUnk);
NvAPI_Status __cdecl MISC_vulkan(IUnknown* unknown);
NvAPI_Status __cdecl Dummy_GetLatency(uint64_t* call_spot, uint64_t* waitTarget, uint64_t* latency, uint64_t* frameTime);
}
+42 -51
View File
@@ -1,52 +1,43 @@
#include "log.h"
std::ostream null(nullptr);
std::ostream* logStream = &null;
std::ofstream fileStream;
std::string getCurrentTimeFormatted() {
auto now = std::chrono::system_clock::now();
auto now_t = std::chrono::system_clock::to_time_t(now);
auto now_tm = *std::localtime(&now_t);
auto now_duration = now - std::chrono::system_clock::from_time_t(std::mktime(&now_tm));
auto now_us = std::chrono::duration_cast<std::chrono::microseconds>(now_duration);
std::ostringstream oss;
oss << std::setfill('0') << std::setw(2) << now_tm.tm_hour << ":"
<< std::setfill('0') << std::setw(2) << now_tm.tm_min << ":"
<< std::setfill('0') << std::setw(2) << now_tm.tm_sec << "."
<< std::setfill('0') << std::setw(6) << now_us.count();
return oss.str();
}
void log(const std::string& log) {
*logStream << "[" << getCurrentTimeFormatted() << "] " << log << std::endl;
}
NvAPI_Status Ok(const std::source_location& location) {
log(std::format("{}: {}", location.function_name(), "OK"));
return NVAPI_OK;
}
NvAPI_Status Error(NvAPI_Status status, const std::source_location& location) {
log(std::format("{}: {}", location.function_name(), fromErrorNr(status)));
return status;
}
void prepareLogging(std::optional<std::string> fileName) {
if (fileName.has_value()) {
fileStream.open(fileName.value(), std::ios_base::out | std::ios_base::app);
if (fileStream.is_open()) {
logStream = &fileStream;
return;
}
else {
std::cerr << "Failed to open log file: " << fileName.value() << std::endl;
}
}
// logStream = &std::cout;
}
void closeLogging() {
fileStream.close();
#include "log.h"
inline std::string extractFunctionName(const std::string& signature) {
size_t start = signature.find("nvd::");
if (start == std::string::npos) return {};
start += 5;
size_t end = signature.find('(', start);
if (end == std::string::npos) return {};
return signature.substr(start, end - start);
}
NvAPI_Status Ok(const std::source_location& location) {
spdlog::trace("{}: {}", extractFunctionName(location.function_name()), "OK");
return NVAPI_OK;
}
NvAPI_Status Error(NvAPI_Status status, const std::source_location& location) {
spdlog::trace("{}: {}", extractFunctionName(location.function_name()), fromErrorNr(status));
return status;
}
void prepareLogging(spdlog::level::level_enum level) {
try {
if (level != spdlog::level::off) {
auto logger = spdlog::basic_logger_mt("basic_logger", "fakenvapi.log");
spdlog::set_default_logger(logger);
if (level == spdlog::level::trace)
spdlog::set_pattern("[%H:%M:%S.%f] [%L] [thread %t] %v");
else
spdlog::set_pattern("[%H:%M:%S.%f] [%L] %v");
spdlog::set_level(level);
spdlog::flush_on(level);
}
} catch (const spdlog::spdlog_ex &ex) {
std::cout << "Log init failed: " << ex.what() << std::endl;
}
}
void closeLogging() {
spdlog::default_logger()->flush();
spdlog::shutdown();
}
Regular → Executable
+4 -4
View File
@@ -7,11 +7,11 @@
#include <format>
#include <source_location>
#include "util.h"
#include "../include/nvapi.h"
#include "../external/nvapi.h"
#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"
std::string getCurrentTimeFormatted();
void log(const std::string& log);
NvAPI_Status Ok(const std::source_location &location = std::source_location::current());
NvAPI_Status Error(NvAPI_Status status = NVAPI_ERROR, const std::source_location &location = std::source_location::current());
void prepareLogging(std::optional<std::string> fileName);
void prepareLogging(spdlog::level::level_enum level);
void closeLogging();
+186
View File
@@ -0,0 +1,186 @@
#pragma once
#include <chrono>
#include <dxgi.h>
#if defined __MINGW64__ || defined __MINGW32__
#include "../external/d3d12.h"
#else
#include <d3d12.h>
#endif
#if _MSC_VER && _WIN64
#include "../external/ffx_antilag2_dx12.h"
#include "../external/ffx_antilag2_dx11.h"
#endif
#include "../external/latencyflex.h"
#include "log.h"
enum Mode {
AntiLag2,
LatencyFlex,
};
enum CallSpot {
SleepCall = 0,
InputSample = 1,
SimulationStart = 2
};
struct LFXStats {
uint64_t latency = 0;
uint64_t frame_time = 1;
uint64_t target = 0;
uint64_t frame_id = 0;
bool needs_reset = false;
};
class LowLatency {
#if _MSC_VER && _WIN64
AMD::AntiLag2DX12::Context context_dx12 = {};
AMD::AntiLag2DX11::Context context_dx11 = {};
Mode mode = AntiLag2;
#else
Mode mode = LatencyFlex;
#endif
lfx::LatencyFleX *lf;
unsigned long min_interval_us = 0;
bool al_available = false;
static inline uint64_t GetTimestamp() {
LARGE_INTEGER frequency;
LARGE_INTEGER counter;
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&counter);
return static_cast<uint64_t>(counter.QuadPart) * UINT64_C(1000000000) / static_cast<uint64_t>(frequency.QuadPart);
}
public:
CallSpot call_spot = SimulationStart;
LFXStats lfx_stats = {};
bool fg = false;
bool active = true;
bool force_lfx = false;
inline HRESULT init_al2(IUnknown *pDevice) {
#if _MSC_VER && _WIN64
if (mode == AntiLag2 && !context_dx12.m_pAntiLagAPI && !context_dx11.m_pAntiLagAPI) {
ID3D12Device* device = nullptr;
HRESULT hr = pDevice->QueryInterface(__uuidof(ID3D12Device), reinterpret_cast<void**>(&device));
HRESULT init_return = S_FALSE;
if (hr == S_OK) {
init_return = AMD::AntiLag2DX12::Initialize(&context_dx12, device);
} else {
init_return = AMD::AntiLag2DX11::Initialize(&context_dx11);
}
al_available = init_return == S_OK;
}
#else
al_available = false;
#endif
return 0x2137;
}
void init_lfx() {
lf = new lfx::LatencyFleX();
}
inline HRESULT update() {
if (!active) return S_FALSE;
if (al_available && !force_lfx && (min_interval_us == 0 || !fg))
mode = AntiLag2;
else
mode = LatencyFlex;
spdlog::debug("LowLatency algo: {}", mode == AntiLag2 ? "AntiLag 2" : "LatencyFlex");
spdlog::debug("FG status: {}", fg ? "enabled" : "disabled");
if (mode == AntiLag2) {
#if _MSC_VER && _WIN64
if (lfx_stats.frame_id != 1) lfx_stats.needs_reset = true;
int max_fps = min_interval_us > 0 ? 1000000 / min_interval_us : 0;
if (context_dx12.m_pAntiLagAPI)
return AMD::AntiLag2DX12::Update(&context_dx12, true, max_fps);
else if (context_dx11.m_pAntiLagAPI)
return AMD::AntiLag2DX11::Update(&context_dx11, true, max_fps);
#endif
} else if (mode == LatencyFlex) {
if (lfx_stats.needs_reset) {
spdlog::info("LFX Reset");
lfx_stats.frame_id = 1;
lfx_stats.needs_reset = false;
lf->Reset();
}
uint64_t current_timestamp = GetTimestamp();
uint64_t timestamp;
// Set FPS Limiter
lf->target_frame_time = 1000 * min_interval_us;
lf->EndFrame(lfx_stats.frame_id, current_timestamp, &lfx_stats.latency, &lfx_stats.frame_time);
spdlog::debug("LFX latency: {}, frame_time: {}, current_timestamp: {}", lfx_stats.latency, lfx_stats.frame_time, current_timestamp);
lfx_stats.frame_id++;
lfx_stats.target = lf->GetWaitTarget(lfx_stats.frame_id);
if (lfx_stats.target > current_timestamp) {
uint64_t extra_delay = 0;
// uint64_t extra_delay = (lfx_stats.target - current_timestamp) * 0.15;
static uint64_t timeout_events = 0;
uint64_t timeout_timestamp = current_timestamp + 50000000ULL;
if (lfx_stats.target > timeout_timestamp) {
timestamp = timeout_timestamp;
timeout_events++;
lfx_stats.needs_reset = timeout_events > 5;
} else {
timestamp = lfx_stats.target + extra_delay;
timeout_events = 0;
}
std::this_thread::sleep_for(std::chrono::nanoseconds(lfx_stats.target + extra_delay - current_timestamp));
} else {
timestamp = current_timestamp;
}
lf->BeginFrame(lfx_stats.frame_id, lfx_stats.target, timestamp);
return S_OK;
}
return S_FALSE;
}
inline HRESULT set_fg_type(bool interpolated) {
#if _MSC_VER && _WIN64
if (mode == AntiLag2)
return AMD::AntiLag2DX12::SetFrameGenFrameType(&context_dx12, interpolated);
#endif
return S_FALSE;
}
inline HRESULT mark_end_of_rendering() {
#if _MSC_VER && _WIN64
if (mode == AntiLag2)
return AMD::AntiLag2DX12::MarkEndOfFrameRendering(&context_dx12);
#endif
return S_FALSE;
}
inline void unload() {
#if _MSC_VER && _WIN64
if (context_dx12.m_pAntiLagAPI) AMD::AntiLag2DX12::DeInitialize(&context_dx12);
if (context_dx11.m_pAntiLagAPI) AMD::AntiLag2DX11::DeInitialize(&context_dx11);
#endif
}
void set_min_interval_us(unsigned long interval_us) {
if (min_interval_us != interval_us) {
min_interval_us = interval_us;
spdlog::info("Changed max fps: {}", interval_us > 0 ? 1000000 / interval_us : 0);
}
}
Mode get_mode() {
return mode;
}
};
+26 -15
View File
@@ -4,26 +4,31 @@
#include <dxgi.h>
#include <d3d11.h>
#include "../include/nvapi_interface.h"
#include "../external/nvapi_interface.h"
#if defined __MINGW64__ || defined __MINGW32__
#include "../include/d3d12.h"
#else
#include <d3d12.h>
#endif
#include "../include/nvapi.h"
#include "nvapi.h"
#include "../external/nvapi.h"
#include "fakenvapi.h"
#include "log.h"
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
auto logEnv = std::getenv("NVAPI_LOG");
auto logEnv = std::getenv("FAKENVAPI_LOG");
#ifdef TESTING
bool force_log = true;
#else
bool force_log = false;
#endif
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
if (logEnv && *logEnv == '1')
prepareLogging("nvapi-dummy.log");
if ((logEnv && *logEnv == '1') || force_log)
prepareLogging(spdlog::level::trace);
else
prepareLogging(std::nullopt);
log("--------------");
prepareLogging(spdlog::level::off);
spdlog::critical("----------------");
break;
case DLL_PROCESS_DETACH:
closeLogging();
@@ -36,15 +41,17 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
NVAPI_INTERFACE_TABLE additional_interface_table[] = {
{ "NvAPI_Diag_ReportCallStart", 0x33c7358c },
{ "NvAPI_Diag_ReportCallReturn", 0x593e8644 },
{ "MISC_unknown", 0xe9b009b9 },
{ "MISC_vulkan", 0x17d13d6 }
{ "NvAPI_Unknown_1", 0xe9b009b9 },
{ "NvAPI_Vulkan_1", 0x17d13d6 },
{ "Dummy_GetLatency", 0x21372137 }
};
namespace nvd {
extern "C" {
NvAPI_Status __cdecl placeholder() {
// return Ok();
return Error(NVAPI_NO_IMPLEMENTATION);
// return Error(NVAPI_NO_IMPLEMENTATION);
return NVAPI_NO_IMPLEMENTATION; // no logging
}
static std::unordered_map<NvU32, void*> registry;
@@ -67,7 +74,7 @@ namespace nvd {
[id](const auto& item) { return item.id == id; });
if (it == std::end(extended_interface_table)) {
log(std::format("NvAPI_QueryInterface (0x{:x}): Unknown interface ID", id));
spdlog::debug("NvAPI_QueryInterface (0x{:x}): Unknown interface ID", id);
return registry.insert({ id, nullptr }).first->second;
}
@@ -107,6 +114,7 @@ namespace nvd {
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D_SetSleepMode)
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D_SetLatencyMarker)
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D_Sleep)
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D_SetReflexSync)
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D11_IsNvShaderExtnOpCodeSupported)
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D11_BeginUAVOverlap)
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D11_EndUAVOverlap)
@@ -120,14 +128,17 @@ namespace nvd {
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D12_SetAsyncFrameMarker)
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_DRS_CreateSession)
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_DRS_LoadSettings)
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_DRS_SaveSettings)
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_DRS_GetBaseProfile)
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_DRS_GetSetting)
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_DRS_SetSetting)
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_DRS_DestroySession)
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_Unknown_1)
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_Vulkan_1)
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_Unload)
INSERT_AND_RETURN_WHEN_EQUALS(MISC_unknown)
INSERT_AND_RETURN_WHEN_EQUALS(MISC_vulkan)
INSERT_AND_RETURN_WHEN_EQUALS(Dummy_GetLatency)
log(std::format("{}: not implemented, placeholder given", it->func));
spdlog::debug("{}: not implemented, placeholder given", it->func);
return registry.insert({ id, (void*)placeholder }).first->second;
// return registry.insert({ id, nullptr }).first->second;
}
+2 -1
View File
@@ -1,7 +1,8 @@
dll = shared_library(
'nvapi'+target_suffix,
['main.cpp', 'nvapi.cpp', 'spoofInfo.cpp', 'util.cpp', 'log.cpp'],
['main.cpp', 'fakenvapi.cpp', 'util.cpp', 'log.cpp'],
name_prefix : '',
dependencies : [ lib_dxgi ],
include_directories: [ spdlog_headers ],
install: true
)
-14
View File
@@ -1,14 +0,0 @@
#include "spoofInfo.h"
namespace spoof {
void driverInfo(NV_DISPLAY_DRIVER_INFO* driverInfo) {
driverInfo->driverVersion = driverVersion;
tonvss(driverInfo->szBuildBranch, buildBranch);
driverInfo->bIsDCHDriver = isDCHDriver;
driverInfo->bIsNVIDIAStudioPackage = isNVIDIAStudioPackage;
driverInfo->bIsNVIDIARTXProductionBranchPackage = isNVIDIARTXProductionBranchPackage;
driverInfo->bIsNVIDIARTXNewFeatureBranchPackage = isNVIDIARTXNewFeatureBranchPackage;
if (driverInfo->version == 2)
tonvss(driverInfo->szBuildBaseBranch, buildBaseBranch);
}
}
-19
View File
@@ -1,19 +0,0 @@
#pragma once
#include "util.h"
namespace spoof {
constexpr NvU32 driverVersion = 99999;
constexpr auto buildBranch = "buildBranch";
constexpr NvU32 isDCHDriver = 1;
constexpr NvU32 isNVIDIAStudioPackage = 1;
constexpr NvU32 isNVIDIARTXProductionBranchPackage = 1;
constexpr NvU32 isNVIDIARTXNewFeatureBranchPackage = 1;
constexpr auto buildBaseBranch = "buildBaseBranch";
constexpr auto fullGPUName = "NVIDIA GeForce RTX 4090";
constexpr NV_GPU_ARCHITECTURE_ID arch = NV_GPU_ARCHITECTURE_AD100;
constexpr NV_GPU_ARCH_IMPLEMENTATION_ID implementation = NV_GPU_ARCH_IMPLEMENTATION_AD102;
constexpr NV_GPU_CHIP_REVISION revision = NV_GPU_CHIP_REV_UNKNOWN;
void driverInfo(NV_DISPLAY_DRIVER_INFO* driverInfo);
}
+1 -1
View File
@@ -1,5 +1,5 @@
#pragma once
#include "../include/nvapi.h"
#include "../external/nvapi.h"
#include <string>
#include <string.h>
#include <map>