reflex: Use standard Vulkan types for present ID/latency and synchronize swapchain access with present lock

This commit is contained in:
Tears of the SteelTemple committed 2026-11-04 12:22:45 +02:00
1 parent d6c41d25a5
commit 318acd83e6
2 files changed
+43 -62

No files matched your search

+41 -55
View File
@@ -252,35 +252,9 @@ static void window_settings_live(void) {
static const char *g_present_got = ""; // the TOTK_VK_PRESENT value of the mode the swapchain got; "" before one
// ---- NVIDIA Reflex Low Latency (VK_NV_low_latency2)
typedef struct {
VkStructureType sType;
const void *pNext;
VkBool32 lowLatencyMode;
VkBool32 lowLatencyBoost;
uint32_t minimumIntervalUs;
} ReflexModeInfoNV;
typedef struct {
VkStructureType sType;
const void *pNext;
VkSemaphore sleepSemaphore;
uint64_t value;
} ReflexSleepInfoNV;
typedef struct {
VkStructureType sType;
const void *pNext;
uint64_t presentID;
int marker;
} ReflexMarkerInfoNV;
typedef VkResult(VKAPI_PTR *ReflexSetModeFn)(VkDevice, VkSwapchainKHR, const ReflexModeInfoNV *);
typedef VkResult(VKAPI_PTR *ReflexSleepFn)(VkDevice, VkSwapchainKHR, const ReflexSleepInfoNV *);
typedef void(VKAPI_PTR *ReflexMarkerFn)(VkDevice, VkSwapchainKHR, const ReflexMarkerInfoNV *);
static ReflexSetModeFn g_reflex_set_mode;
static ReflexSleepFn g_reflex_sleep;
static ReflexMarkerFn g_reflex_marker;
static PFN_vkSetLatencySleepModeNV g_reflex_set_mode;
static PFN_vkLatencySleepNV g_reflex_sleep;
static PFN_vkSetLatencyMarkerNV g_reflex_marker;
static VkSemaphore g_reflex_sem;
static uint64_t g_reflex_val;
static uint64_t g_reflex_present_id = 1;
@@ -291,9 +265,9 @@ static void reflex_apply_locked(void) {
VkCtx *c = vk_ctx();
if (!c || !c->has_nv_reflex || !g_sc) return;
if (!g_reflex_set_mode) {
g_reflex_set_mode = (ReflexSetModeFn)vkGetDeviceProcAddr(c->device, "vkSetLatencySleepModeNV");
g_reflex_sleep = (ReflexSleepFn)vkGetDeviceProcAddr(c->device, "vkLatencySleepNV");
g_reflex_marker = (ReflexMarkerFn)vkGetDeviceProcAddr(c->device, "vkSetLatencyMarkerNV");
g_reflex_set_mode = (PFN_vkSetLatencySleepModeNV)vkGetDeviceProcAddr(c->device, "vkSetLatencySleepModeNV");
g_reflex_sleep = (PFN_vkLatencySleepNV)vkGetDeviceProcAddr(c->device, "vkLatencySleepNV");
g_reflex_marker = (PFN_vkSetLatencyMarkerNV)vkGetDeviceProcAddr(c->device, "vkSetLatencyMarkerNV");
}
if (!g_reflex_set_mode) return;
if (!g_reflex_sem) {
@@ -310,8 +284,12 @@ static void reflex_apply_locked(void) {
if (mode == g_reflex_mode && min_us == g_reflex_min_us) return;
g_reflex_mode = mode;
g_reflex_min_us = min_us;
ReflexModeInfoNV mi = {.sType = (VkStructureType)1000505000, .lowLatencyMode = mode > 0 ? VK_TRUE : VK_FALSE,
.lowLatencyBoost = mode == 2 ? VK_TRUE : VK_FALSE, .minimumIntervalUs = min_us};
VkLatencySleepModeInfoNV mi = {
.sType = VK_STRUCTURE_TYPE_LATENCY_SLEEP_MODE_INFO_NV,
.lowLatencyMode = mode > 0 ? VK_TRUE : VK_FALSE,
.lowLatencyBoost = mode == 2 ? VK_TRUE : VK_FALSE,
.minimumIntervalUs = min_us
};
VkResult r = g_reflex_set_mode(c->device, g_sc, &mi);
rt_log("REFLEX: NVIDIA Reflex Low Latency -> %s (minInterval=%u us, VK_NV_low_latency2=%s)",
mode == 2 ? "ON + BOOST" : mode == 1 ? "ON" : "OFF", min_us, r == VK_SUCCESS ? "OK" : "ERR");
@@ -329,17 +307,36 @@ uint64_t vk_reflex_current_present_id(void) {
void vk_reflex_marker(int marker) {
VkCtx *c = vk_ctx();
if (!c || !c->has_nv_reflex || !g_reflex_marker || g_reflex_mode <= 0 || !g_sc) return;
uint64_t pid = __atomic_load_n(&g_reflex_present_id, __ATOMIC_RELAXED);
ReflexMarkerInfoNV mi = {.sType = (VkStructureType)1000505002, .presentID = pid, .marker = marker};
g_reflex_marker(c->device, g_sc, &mi);
plat_rmutex_lock(&g_pl);
if (g_sc && g_reflex_marker) {
uint64_t pid = __atomic_load_n(&g_reflex_present_id, __ATOMIC_RELAXED);
VkSetLatencyMarkerInfoNV mi = {
.sType = VK_STRUCTURE_TYPE_SET_LATENCY_MARKER_INFO_NV,
.presentID = pid,
.marker = (VkLatencyMarkerNV)marker
};
g_reflex_marker(c->device, g_sc, &mi);
}
plat_rmutex_unlock(&g_pl);
}
void vk_reflex_sleep(void) {
VkCtx *c = vk_ctx();
if (!c || !c->has_nv_reflex || !g_reflex_sleep || !g_reflex_sem || g_reflex_mode <= 0 || !g_sc) return;
uint64_t val = __atomic_add_fetch(&g_reflex_val, 1, __ATOMIC_RELAXED);
ReflexSleepInfoNV si = {.sType = (VkStructureType)1000505001, .sleepSemaphore = g_reflex_sem, .value = val};
if (g_reflex_sleep(c->device, g_sc, &si) == VK_SUCCESS) {
VkLatencySleepInfoNV si = {
.sType = VK_STRUCTURE_TYPE_LATENCY_SLEEP_INFO_NV,
.signalSemaphore = g_reflex_sem,
.value = val
};
VkResult r = VK_ERROR_INITIALIZATION_FAILED;
plat_rmutex_lock(&g_pl);
if (g_sc && g_reflex_sleep) {
r = g_reflex_sleep(c->device, g_sc, &si);
}
plat_rmutex_unlock(&g_pl);
if (r == VK_SUCCESS) {
VkSemaphoreWaitInfo wi = {.sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, .semaphoreCount = 1,
.pSemaphores = &g_reflex_sem, .pValues = &val};
vkWaitSemaphores(c->device, &wi, 50000000ull);
@@ -377,14 +374,8 @@ static void flip_locked(void) {
if (!g_sc) return;
vk_reflex_marker(4); // VK_LATENCY_MARKER_PRESENT_START_NV
uint64_t cur_pid = __atomic_load_n(&g_reflex_present_id, __ATOMIC_RELAXED);
typedef struct {
VkStructureType sType;
const void *pNext;
uint32_t swapchainCount;
const uint64_t *pPresentIds;
} PresentIdKHR;
PresentIdKHR pid_khr = {
.sType = (VkStructureType)1000085001,
VkPresentIdKHR pid_khr = {
.sType = VK_STRUCTURE_TYPE_PRESENT_ID_KHR,
.pNext = NULL,
.swapchainCount = 1,
.pPresentIds = &cur_pid
@@ -444,15 +435,10 @@ static int create_swapchain(void) {
vk_queue_lock();
vkDeviceWaitIdle(c->device);
VkSwapchainKHR old = g_sc;
typedef struct {
VkStructureType sType;
const void *pNext;
VkBool32 latencyMode;
} SwapchainLatencyCreateInfoNV;
SwapchainLatencyCreateInfoNV slc = {
.sType = (VkStructureType)1000505004,
VkSwapchainLatencyCreateInfoNV slc = {
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_LATENCY_CREATE_INFO_NV,
.pNext = NULL,
.latencyMode = VK_TRUE
.latencyModeEnable = VK_TRUE
};
VkSwapchainCreateInfoKHR ci = {
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
+2 -7
View File
@@ -434,13 +434,8 @@ uint64_t vk_sync_submit(const uint64_t *handles, int n) {
{.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO, .commandBuffer = s->cb}};
VkSemaphoreSubmitInfo sig = {.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, .semaphore = c->timeline,
.value = fence, .stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT};
typedef struct {
VkStructureType sType;
const void *pNext;
uint64_t presentID;
} LatencySubmissionPresentIdNV;
LatencySubmissionPresentIdNV lsid = {
.sType = (VkStructureType)1000505005,
VkLatencySubmissionPresentIdNV lsid = {
.sType = VK_STRUCTURE_TYPE_LATENCY_SUBMISSION_PRESENT_ID_NV,
.pNext = NULL,
.presentID = vk_reflex_current_present_id()
};