gfx/drivers: clamp menu pipeline 'time' uniform to avoid fp32 drift

The menu pipeline draw paths in gl2, gl3, vulkan, d3d9hlsl and d3d9cg
each maintain a 'static float t = 0.0f' accumulator, incremented by
0.01 each draw call and pushed to the menu shader 'time' uniform that
drives the XMB ribbon, snow, snowflake and bokeh effects.

Because the accumulator was never wrapped, fp32 precision degraded as
t grew: at t around 10^5 (~46h cumulative menu time at 60 Hz) the
0.01 increment starts being silently rounded, and at t = 2^24 the
counter freezes entirely. Since t is static and persists for the
lifetime of the RetroArch process, long-running frontends (arcade
cabs, kiosks, set-tops) accumulate drift across sessions.

Wrap t once per 2*pi*100 period via a single compare and subtract.
Subtracting a full trig period leaves sin(t)/cos(t) phase intact, so
shader output is bit-identical away from the wrap frame. No fmodf,
no libm dependency, no extra math when not wrapping; the per-frame
cost is one float compare predicted not-taken.

vulkan already had a fmodf-based variant of this fix; rework it to
match the other four drivers for consistency and to drop the libm
call from the hot path.
This commit is contained in:
LibretroAdmin authored and U-DESKTOP-SPFP6AQ\twistedtechre committed 2026-05-17 03:16:23 +02:00
1 parent ff2ba6796a
commit aebd062503
5 files changed
+29 -8

No files matched your search

+6
View File
@@ -713,6 +713,12 @@ static void gfx_display_d3d9_cg_draw(gfx_display_ctx_draw_t *draw,
static float t = 0.0f;
CGparameter param;
t += 0.01f;
/* Wrap once per period (2*pi*100) to keep fp32 increments
* precise over long sessions. Subtracting a full trig period
* is invisible to sin(t)/cos(t) animations in the menu
* pipeline shaders. */
if (t > 628.318530f)
t -= 628.318530f;
param = cgGetNamedParameter(
(CGprogram)_chain->pipeline_vprg[idx], "time");
+6 -1
View File
@@ -1256,8 +1256,13 @@ static void gfx_display_d3d9_hlsl_draw_pipeline(
return;
}
/* Update time uniform - mirrors d3d10 ubo_values.time increment */
/* Update time uniform - mirrors d3d10 ubo_values.time increment.
* Wrap once per period (2*pi*100) to keep fp32 increments precise
* over long sessions. Subtracting a full trig period is invisible
* to sin(t)/cos(t) animations in the menu pipeline shaders. */
t += 0.01f;
if (t > 628.318530f)
t -= 628.318530f;
{
hlsl_renderchain_t *_chain = (hlsl_renderchain_t*)d3d->renderchain_data;
+6 -1
View File
@@ -689,7 +689,12 @@ static void gfx_display_gl2_draw_pipeline(
gl->shader->use(gl, gl->shader_data, draw->pipeline_id,
true);
t += 0.01;
t += 0.01f;
/* Wrap once per period (2*pi*100) to keep fp32 increments precise
* over long sessions. Subtracting a full trig period is invisible
* to sin(t)/cos(t) animations in the menu pipeline shaders. */
if (t > 628.318530f)
t -= 628.318530f;
uniform_param.type = UNIFORM_1F;
uniform_param.enabled = true;
+6 -1
View File
@@ -654,7 +654,12 @@ static void gfx_display_gl3_draw_pipeline(
}
#endif
t += 0.01;
t += 0.01f;
/* Wrap once per period (2*pi*100) to keep fp32 increments precise
* over long sessions. Subtracting a full trig period is invisible
* to sin(t)/cos(t) animations in the menu pipeline shaders. */
if (t > 628.318530f)
t -= 628.318530f;
#endif
}
+5 -5
View File
@@ -1868,11 +1868,11 @@ static void gfx_display_vk_draw_pipeline(
}
t += 0.01f;
/* Wrap to maintain float precision over long sessions.
* Period of 2*pi*100 ensures trig-based shader animations
* (sin(t), cos(t)) cycle seamlessly. */
if (t > 628.0f)
t = fmodf(t, 628.318530f);
/* Wrap once per period (2*pi*100) to keep fp32 increments precise
* over long sessions. Subtracting a full trig period is invisible
* to sin(t)/cos(t) animations in the menu pipeline shaders. */
if (t > 628.318530f)
t -= 628.318530f;
}
#endif