Adding Vulkan support to the reflex markers graph

It behaves a bit differently than with D3D
This commit is contained in:
FakeMichau
2026-03-22 19:45:24 +01:00
parent 899cd37cb8
commit 099da43ade
2 changed files with 77 additions and 39 deletions
+74 -39
View File
@@ -221,6 +221,15 @@ NvAPI_Status ReflexHooks::hkNvAPI_Vulkan_SetSleepMode(HANDLE vkDevice,
return o_NvAPI_Vulkan_SetSleepMode(vkDevice, pSetSleepModeParams);
}
NvAPI_Status ReflexHooks::hkNvAPI_Vulkan_GetLatency(HANDLE vkDevice, NV_VULKAN_LATENCY_RESULT_PARAMS* pGetLatencyParams)
{
#ifdef LOG_REFLEX_CALLS
LOG_FUNC();
#endif
return o_NvAPI_Vulkan_GetLatency(vkDevice, pGetLatencyParams);
}
void ReflexHooks::hookReflex(PFN_NvApi_QueryInterface& queryInterface)
{
if (!_inited)
@@ -236,9 +245,11 @@ void ReflexHooks::hookReflex(PFN_NvApi_QueryInterface& queryInterface)
o_NvAPI_D3D12_SetAsyncFrameMarker = GET_INTERFACE(NvAPI_D3D12_SetAsyncFrameMarker, queryInterface);
o_NvAPI_Vulkan_SetLatencyMarker = GET_INTERFACE(NvAPI_Vulkan_SetLatencyMarker, queryInterface);
o_NvAPI_Vulkan_SetSleepMode = GET_INTERFACE(NvAPI_Vulkan_SetSleepMode, queryInterface);
o_NvAPI_Vulkan_GetLatency = GET_INTERFACE(NvAPI_Vulkan_GetLatency, queryInterface);
_inited = o_NvAPI_D3D_SetSleepMode && o_NvAPI_D3D_Sleep && o_NvAPI_D3D_GetLatency &&
o_NvAPI_D3D_SetLatencyMarker && o_NvAPI_D3D12_SetAsyncFrameMarker;
o_NvAPI_D3D_SetLatencyMarker && o_NvAPI_D3D12_SetAsyncFrameMarker &&
o_NvAPI_Vulkan_SetLatencyMarker && o_NvAPI_Vulkan_SetSleepMode && o_NvAPI_Vulkan_GetLatency;
if (_inited)
LOG_DEBUG("Inited Reflex hooks");
@@ -281,6 +292,10 @@ void* ReflexHooks::getHookedReflex(unsigned int InterfaceId)
{
return &hkNvAPI_Vulkan_SetSleepMode;
}
if (InterfaceId == GET_ID(NvAPI_Vulkan_GetLatency) && o_NvAPI_Vulkan_GetLatency)
{
return &hkNvAPI_Vulkan_GetLatency;
}
return nullptr;
}
@@ -301,52 +316,72 @@ bool ReflexHooks::updateTimingData()
{
bool canCall = ((State::Instance().activeFgOutput == FGOutput::XeFG && !fakenvapi::isUsingAsMainNvapi() &&
!Config::Instance()->XeFGWithoutXeLL.value_or_default()) ||
o_NvAPI_D3D_GetLatency);
o_NvAPI_D3D_GetLatency || o_NvAPI_Vulkan_GetLatency);
if (!canCall || !_lastSleepDev)
if (!canCall)
return false;
NV_LATENCY_RESULT_PARAMS results {};
results.version = NV_LATENCY_RESULT_PARAMS_VER;
if (auto result = hkNvAPI_D3D_GetLatency(_lastSleepDev, &results); result != NVAPI_OK)
return false;
// 64th element have the latest data
auto& frameReport = results.frameReport[63];
uint64_t start = UINT64_MAX;
uint64_t end = 0;
// Please don't look, just thought it would be least work
auto pTimes = (uint64_t*) &frameReport.simStartTime;
for (auto i = 0; i < 11; i++)
auto processFrameReport = [&](const auto& frameReport) -> bool
{
auto& time = pTimes[i];
if (time == 0)
continue;
uint64_t start = UINT64_MAX;
uint64_t end = 0;
if (time < start)
start = time;
// Please don't look, just thought it would be least work
auto pTimes = (const uint64_t*) &frameReport.simStartTime;
for (auto i = 0; i < 11; i++)
{
auto& time = pTimes[i];
if (time == 0)
continue;
if (time > end)
end = time;
if (time < start)
start = time;
if (time > end)
end = time;
}
if (end < start)
return false;
double rangeNs = static_cast<double>(end - start);
timingData[TimingType::TimeRange] = TimingEntry { .position = 0, .length = rangeNs };
UPDATE_TIMING_ENTRY(sim, Simulation)
UPDATE_TIMING_ENTRY(renderSubmit, RenderSubmit)
UPDATE_TIMING_ENTRY(present, Present)
UPDATE_TIMING_ENTRY(driver, Driver)
UPDATE_TIMING_ENTRY(osRenderQueue, OsRenderQueue)
UPDATE_TIMING_ENTRY(gpuRender, GpuRender)
return true;
};
if (_lastSleepDev && o_NvAPI_D3D_GetLatency)
{
// Not calling free on this but it's static so hopefully fine
static NV_LATENCY_RESULT_PARAMS* results = new NV_LATENCY_RESULT_PARAMS(NV_LATENCY_RESULT_PARAMS_VER);
if (auto result = hkNvAPI_D3D_GetLatency(_lastSleepDev, results); result != NVAPI_OK)
return false;
// 64th element has the latest data
return processFrameReport(results->frameReport[63]);
}
else if (_lastVkSleepDev && o_NvAPI_Vulkan_GetLatency)
{
// Not calling free on this but it's static so hopefully fine
static NV_VULKAN_LATENCY_RESULT_PARAMS* results =
new NV_VULKAN_LATENCY_RESULT_PARAMS(NV_VULKAN_LATENCY_RESULT_PARAMS_VER);
if (auto result = hkNvAPI_Vulkan_GetLatency(_lastVkSleepDev, results); result != NVAPI_OK)
return false;
// 64th element has the latest data
return processFrameReport(results->frameReport[63]);
}
if (end < start)
return false;
double rangeNs = static_cast<double>(end - start);
timingData[TimingType::TimeRange] = TimingEntry { .position = 0, .length = rangeNs };
UPDATE_TIMING_ENTRY(sim, Simulation)
UPDATE_TIMING_ENTRY(renderSubmit, RenderSubmit)
UPDATE_TIMING_ENTRY(present, Present)
UPDATE_TIMING_ENTRY(driver, Driver)
UPDATE_TIMING_ENTRY(osRenderQueue, OsRenderQueue)
UPDATE_TIMING_ENTRY(gpuRender, GpuRender)
return true;
return false;
}
// For updating information about Reflex hooks
+3
View File
@@ -56,11 +56,13 @@ class ReflexHooks
// Vulkan
inline static decltype(&NvAPI_Vulkan_SetLatencyMarker) o_NvAPI_Vulkan_SetLatencyMarker = nullptr;
inline static decltype(&NvAPI_Vulkan_SetSleepMode) o_NvAPI_Vulkan_SetSleepMode = nullptr;
inline static decltype(&NvAPI_Vulkan_GetLatency) o_NvAPI_Vulkan_GetLatency = nullptr;
static NvAPI_Status hkNvAPI_Vulkan_SetLatencyMarker(HANDLE vkDevice,
NV_VULKAN_LATENCY_MARKER_PARAMS* pSetLatencyMarkerParams);
static NvAPI_Status hkNvAPI_Vulkan_SetSleepMode(HANDLE vkDevice,
NV_VULKAN_SET_SLEEP_MODE_PARAMS* pSetSleepModeParams);
static NvAPI_Status hkNvAPI_Vulkan_GetLatency(HANDLE vkDevice, NV_VULKAN_LATENCY_RESULT_PARAMS* pGetLatencyParams);
VALIDATE_MEMBER_HOOK(hkNvAPI_D3D_SetSleepMode, decltype(&NvAPI_D3D_SetSleepMode))
VALIDATE_MEMBER_HOOK(hkNvAPI_D3D_Sleep, decltype(&NvAPI_D3D_Sleep))
@@ -69,6 +71,7 @@ class ReflexHooks
VALIDATE_MEMBER_HOOK(hkNvAPI_D3D12_SetAsyncFrameMarker, decltype(&NvAPI_D3D12_SetAsyncFrameMarker))
VALIDATE_MEMBER_HOOK(hkNvAPI_Vulkan_SetLatencyMarker, decltype(&NvAPI_Vulkan_SetLatencyMarker))
VALIDATE_MEMBER_HOOK(hkNvAPI_Vulkan_SetSleepMode, decltype(&NvAPI_Vulkan_SetSleepMode))
VALIDATE_MEMBER_HOOK(hkNvAPI_Vulkan_GetLatency, decltype(&NvAPI_Vulkan_GetLatency))
public:
static std::optional<TimingEntry> timingData[TimingType::TimingTypeCOUNT];