vulkan: prefer MAILBOX for tear-free presentation

Let the frontend remain the sole frame pacer by requesting MAILBOX for tear-free delivery, with FIFO retained as the required fallback.

Co-authored-by: Martin Penkava <mpenkava1337@gmail.com>
This commit is contained in:
Matthew Stanley
2026-07-14 10:17:08 -07:00
parent af9de64951
commit f5498f796c
4 changed files with 46 additions and 7 deletions
@@ -0,0 +1,23 @@
# Martin Penkava PR #16: Vulkan MAILBOX tear-free policy
Last evaluated: 2026-07-14
| Item | Value |
| --- | --- |
| Head repository/branch | `shaneomac1337/psxrecomp`, `smackdown2-fixes` (submitted as `mstan/psxrecomp` PR #16) |
| Source commit | `d05d14bb11caafad2963abe824f249249a80cb11` |
| Source author | Martin Penkava `<mpenkava1337@gmail.com>` |
| Local base | `7085721afe338a03cb114321a3576cdff420b732` (`origin/master`) |
| Local branch | `perf/pr16-vulkan-mailbox-tear-free-mpenkava` |
## Included scope
The tear-free Vulkan policy prefers MAILBOX because PSXRecomp's frontend already paces frames. If MAILBOX is unavailable, Vulkan's required FIFO mode remains the fallback; the explicit tearing policy still requests IMMEDIATE.
## Deliberate exclusions
- Source-commit benchmark comments naming a particular game are omitted; the policy itself is title-independent.
- Command-buffer batching and staging reuse are isolated on separate branches.
- Timing diagnostics, CRT presentation, and game-specific data are excluded.
The source commit has no secondary co-author trailer; only Martin Penkava is credited in the local commit trailer.
+3 -3
View File
@@ -45,9 +45,9 @@ void vk_renderer_present_blank(void);
* server, 24-bit present). No-op when the Vulkan path is inactive. */
void vk_renderer_sync_cpu(void);
/* Set the present mode: 1=FIFO (vsync), 0=IMMEDIATE (lowest latency, may tear),
* -1=MAILBOX (low-latency, tear-free). Applied on the next swapchain (re)build;
* unsupported modes fall back to FIFO (always available). */
/* Set the present policy: 1=tear-free, 0=IMMEDIATE (lowest latency, may tear),
* -1=MAILBOX. Tear-free prefers MAILBOX because the frontend already paces
* frames; unsupported modes fall back to FIFO (always available). */
void vk_renderer_set_present_mode(int mode);
#ifdef __cplusplus
+6 -4
View File
@@ -226,7 +226,7 @@ static VkFormat s_sc_format;
static VkExtent2D s_sc_extent;
static uint32_t s_sc_count;
static VkImage s_sc_images[8];
static int s_present_mode_req = 1; /* 1 FIFO, 0 IMMEDIATE, -1 MAILBOX */
static int s_present_mode_req = 1; /* 1 tear-free, 0 IMMEDIATE, -1 MAILBOX */
/* Per-frame sync (double-buffered command recording). */
#define VK_FRAMES 2
@@ -778,9 +778,11 @@ static VkPresentModeKHR choose_present_mode(void) {
if (n > 8) n = 8;
VkPresentModeKHR modes[8];
p_vkGetPhysicalDeviceSurfacePresentModesKHR(s_phys, s_surface, &n, modes);
VkPresentModeKHR want = (s_present_mode_req == 0) ? VK_PRESENT_MODE_IMMEDIATE_KHR
: (s_present_mode_req < 0) ? VK_PRESENT_MODE_MAILBOX_KHR
: VK_PRESENT_MODE_FIFO_KHR;
/* The frontend already owns frame cadence. Prefer MAILBOX for tear-free
* delivery so FIFO does not introduce a second blocking pacer. */
VkPresentModeKHR want = (s_present_mode_req == 0)
? VK_PRESENT_MODE_IMMEDIATE_KHR
: VK_PRESENT_MODE_MAILBOX_KHR;
for (uint32_t i = 0; i < n; i++) if (modes[i] == want) return want;
return VK_PRESENT_MODE_FIFO_KHR; /* always supported */
}
+14
View File
@@ -0,0 +1,14 @@
#!/usr/bin/env python3
from pathlib import Path
import re
source = (Path(__file__).parents[1] / "src" / "gpu_vk_renderer.c").read_text()
choose = re.search(r"static VkPresentModeKHR choose_present_mode\(.*?\n\}", source, re.DOTALL)
assert choose
body = choose.group(0)
assert "s_present_mode_req == 0" in body
assert "VK_PRESENT_MODE_IMMEDIATE_KHR" in body
assert "VK_PRESENT_MODE_MAILBOX_KHR" in body
assert "return VK_PRESENT_MODE_FIFO_KHR" in body
assert "s_present_mode_req < 0" not in body
print("Vulkan MAILBOX present-policy test passed")