fix: match the A740 UBWC hint on driver 512.676.76

Co-authored-by: Vabian124 <82999916+Vabian124@users.noreply.github.com>
This commit is contained in:
Kurt HimebauchandVabian124 committed 2026-10-23 13:54:01 -04:00
1 parent fc768a3c45
commit dccd5a7c69
4 files changed
+30 -6

No files matched your search

@@ -238,7 +238,7 @@ static int ensure_ring(uint32_t w, uint32_t h, VkFormat fmt, uint32_t n) {
}
g_ring_w = w; g_ring_h = h; g_ring_fmt = fmt;
LOGD("framegen: generation ring %ux%u x%u", w, h, n);
return 1;
return 2;
}
@@ -350,6 +350,7 @@ int vkp_framegen_run(VkCommandBuffer cmd, VkImage scene, VkImageView scene_view,
fge_configure((uint32_t)mult, (uint32_t)atomic_load(&g_target), flow, hz,
atomic_load(&g_model), atomic_load(&g_preset));
}
const int size_changed = g_built_w != (uint32_t)w || g_built_h != (uint32_t)h || g_built_fmt != fmt;
if (!fge_prepare((uint32_t)w, (uint32_t)h, fmt)) {
if (fmt != VK_FORMAT_R8G8B8A8_UNORM && fge_unavailable()) {
refuse_format(fmt, kind, w, h, "build its chain");
@@ -361,17 +362,25 @@ int vkp_framegen_run(VkCommandBuffer cmd, VkImage scene, VkImageView scene_view,
}
return 0;
}
if (g_built_w != (uint32_t)w || g_built_h != (uint32_t)h || g_built_fmt != fmt) {
if (size_changed) {
g_built_w = (uint32_t)w; g_built_h = (uint32_t)h; g_built_fmt = fmt;
g_generating_logged = 0;
}
uint32_t want = (uint32_t)(mult - 1);
if (!ensure_ring((uint32_t)w, (uint32_t)h, fmt, want)) {
const int ring = ensure_ring((uint32_t)w, (uint32_t)h, fmt, want);
if (!ring) {
if (fmt != VK_FORMAT_R8G8B8A8_UNORM) { refuse_format(fmt, kind, w, h, "make its generation ring"); return 0; }
FGLOG("no memory for the generation ring (%dx%d x%u); frame generation stays off", w, h, want);
mark_failed(kind);
return 0;
}
/* The ring and the engine's images are new on this frame. Dispatching into them now
* null-dereferenced Turnip (vkp_framegen_run, first Steam frame, 2560x1440 to the panel).
* Show this frame as it is; generation starts once the size has settled. */
if (size_changed || ring == 2) {
FGLOG("frame generation catches up at %dx%d; this frame is shown as it is", w, h);
return 0;
}
/* The pacer's source rate must be the game's, not this loop's: a loop slowed by its own
* generations would otherwise read as a slower game and justify even more generations. */
@@ -1626,6 +1626,10 @@ static int render_impl(int scene_w, int scene_h, const struct vkp_draw *draws, i
VkImageLayout result_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
if (fx) {
int mapped_w = (int)(scene_w * g_map.kx + 0.5f), mapped_h = (int)(scene_h * g_map.ky + 0.5f);
/* Frame generation samples every output pixel. Upscaling first made it interpolate
* the whole panel (3200x1440 on a 1440p phone) and rebuild on Steam's first frame.
* Grade at the game's size instead; the screen blit still scales to the panel. */
if (fg) { mapped_w = scene_w; mapped_h = scene_h; }
vkp_effects_set_formats(scene_fmt, scene_fmt);
result = vkp_effects_run(cmd, scene_img, scene_w, scene_h, mapped_w, mapped_h, &rw, &rh);
result_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
@@ -14,7 +14,7 @@ object TpUbwcHint {
private set
// On Adreno 740, TPL1_DBG_ECO_CNTL1.TP_UBWC_FLAG_HINT is shared by every driver on the GPU and must
// match the system driver: blob v6xx leaves it off, newer blobs set it. A mismatch corrupts Android UI.
// match the system driver. A mismatch corrupts Android UI.
// Samsung's One UI firmware sets it whatever blob version it reports.
internal fun features(model: Int, systemDriverVersion: String?, samsung: Boolean = false,
mode: String = SessionPrefs.TP_UBWC_AUTO): String? {
@@ -22,8 +22,11 @@ object TpUbwcHint {
if (mode == SessionPrefs.TP_UBWC_ON) return "enable_tp_ubwc_flag_hint=1"
if (mode == SessionPrefs.TP_UBWC_OFF) return "enable_tp_ubwc_flag_hint=0"
if (samsung) return "enable_tp_ubwc_flag_hint=1"
val blob = systemDriverVersion?.split('.')?.getOrNull(1)?.toIntOrNull() ?: return null
return "enable_tp_ubwc_flag_hint=" + if (blob >= 700) "1" else "0"
val parts = systemDriverVersion?.split('.') ?: return null
val blob = parts.getOrNull(1)?.toIntOrNull() ?: return null
val patch = parts.getOrNull(2)?.toIntOrNull() ?: 0
val on = blob >= 700 || (blob == 676 && patch >= 76)
return "enable_tp_ubwc_flag_hint=" + if (on) "1" else "0"
}
@Synchronized
@@ -8,6 +8,14 @@ import com.droiddeck.launcher.session.SessionPrefs
class TpUbwcHintTest {
@Test fun a740OnABlobV6xxTurnsTheHintOff() {
assertEquals("enable_tp_ubwc_flag_hint=0", TpUbwcHint.features(740, "512.676.53"))
assertEquals("enable_tp_ubwc_flag_hint=0", TpUbwcHint.features(740, "512.676.75"))
assertEquals("enable_tp_ubwc_flag_hint=0", TpUbwcHint.features(740, "512.676"))
assertEquals("enable_tp_ubwc_flag_hint=0", TpUbwcHint.features(740, "512.699.10"))
}
@Test fun a740OnThePocoBlobTurnsTheHintOn() {
assertEquals("enable_tp_ubwc_flag_hint=1", TpUbwcHint.features(740, "512.676.76"))
assertEquals("enable_tp_ubwc_flag_hint=1", TpUbwcHint.features(740, "512.676.80"))
}
@Test fun a740OnANewerBlobTurnsTheHintOn() {