gfx/drivers_shader/shader_gl_cg: mask IN.frame_count when no modulo declared

The Cg shader 'IN.frame_count' input is bound via cg_gl_set_param_1f,
which forces a (float) cast of an unsigned monotonic counter. fp32
integer precision dies at 2^24 = 16,777,216, so at 60 fps any Cg
shader that uses IN.frame_count for time-based animation freezes its
counter after roughly 77 hours of continuous play.

The frame_count_mod field on each shader pass is the documented
defense, but it is opt-in and most presets do not set it. Add a
default 24-bit mask when no modulo is declared, so the cast stays
bit-exact in perpetuity and existing Cg shaders that key animation
off IN.frame_count keep working in long sessions.

Presets that do declare frame_count_mod are unaffected.
This commit is contained in:
LibretroAdmin authored and U-DESKTOP-SPFP6AQ\twistedtechre committed 2026-05-17 03:16:26 +02:00
1 parent aebd062503
commit 9e5bd445a1
1 file changed
+7
+7
View File
@@ -455,6 +455,13 @@ static void gl_cg_set_params(void *dat, void *shader_data)
unsigned modulo = cg->shader->pass[cg->active_idx - 1].frame_count_mod;
if (modulo)
frame_count %= modulo;
else
/* fp32 mantissa is 23 bits; integers above 2^24 cannot be
* represented exactly. Mask to 24 bits when the shader pass
* has not declared its own modulo, so (float)frame_count stays
* bit-exact and time-based Cg shaders keep animating beyond
* ~77 h of continuous play. */
frame_count &= 0xFFFFFFu;
cg_gl_set_param_1f(cg->prg[cg->active_idx].frame_cnt_f, (float)frame_count);
cg_gl_set_param_1f(cg->prg[cg->active_idx].frame_cnt_v, (float)frame_count);