mirror of
https://github.com/valentderah/totk-pc-recomp.git
synced 2026-11-13 02:41:02 +00:00
reflex: Use standard Vulkan types for present ID/latency and synchronize swapchain access with present lock
This commit is contained in:
1 parent
d6c41d25a5
commit
318acd83e6
2 files changed
+43
-62
No files matched your search
+41
-55
@@ -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
@@ -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()
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user