Sincronización y FPS para Source Main 5.2 Pegasus/Mudream - Source Mu - Mu Server Files
 

Sincronización y FPS para Source Main 5.2 Pegasus/Mudream

Publicado por Dakosmu, Nov 19, 2025, 04:03 PM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

Dakosmu

Guía: Optimización del Límite de FPS (Frames por Segundo) y Latencia

Introducción

Esta guía cubre un método avanzado para gestionar la frecuencia de cuadros (FPS) de renderizado en un entorno específico, incluyendo mecanismos para anular (override) la configuración de FPS y reducir la latencia mediante técnicas de Sleep Spin.



---

Paso 1: Entendiendo el Código Base

El fragmento de código que vamos a analizar y potencialmente modificar se encarga de calcular el tiempo que debe transcurrir entre cuadros (ms_per_frame) y forzar una espera si el cuadro se renderizó demasiado rápido. Esto es crucial para la estabilidad y el consumo de recursos.

  • ms_per_frame: El tiempo objetivo en milisegundos para cada cuadro (inverso del FPS deseado).
  • elapsed_ms: El tiempo real transcurrido desde el último cuadro.
  • rest_ms: El tiempo que queda por esperar para alcanzar el ms_per_frame objetivo.

---

Paso 2: Análisis del Bloque de Control de FPS

El código utiliza una estructura condicional principal. Si el tiempo transcurrido (elapsed_ms) es menor que el tiempo objetivo (ms_per_frame), se ejecuta el bloque de espera (Sleep/Spin).

El código utiliza la variable g_FPSOverrideActive para permitir una anulación de FPS externa:
if (ms_per_frame > 0.0)
{
    if (g_FPSOverrideActive == 1 && g_FPSOverrideMs > 0.0)
    {
        ms_per_frame = g_FPSOverrideMs;
    }
// ...
}

---

Paso 3: Mecanismos de Espera (Sleep vs. Sleep Spin)

El fragmento de código distingue entre la "Tubería Original de 150 FPS" (g_UseOriginal150FPSPipeline) que usa la simple función Sleep() y un enfoque más moderno y de menor latencia llamado Sleep Spin.

  • Tubería Original (Sleep): Simplemente llama a Sleep((DWORD)rest_ms);, lo que cede completamente el control al sistema operativo por el tiempo restante. Esto puede ser menos preciso.
  • Nuevo Enfoque (Sleep Spin): Combina un sleep_for más largo con un bucle de espera activa (while(true)) que usa std::this_thread::yield() para consumir el tiempo restante con alta precisión, reduciendo la latencia de entrada.

El código C++ completo de esta lógica es:

if (ms_per_frame > 0.0)
{
    if (g_FPSOverrideActive == 1 && g_FPSOverrideMs > 0.0)
    {
        ms_per_frame = g_FPSOverrideMs;
    }

    const double now_ms = g_pTimer->GetAbsTime();
    const double elapsed_ms = now_ms - last_render_tick_count;
   
    if (elapsed_ms < ms_per_frame)
    {
        double rest_ms = ms_per_frame - elapsed_ms;
       
        if (g_UseOriginal150FPSPipeline)
        {
            // ORIGINAL PIPELINE FIX
            if (rest_ms > 1.0)
            {
                Sleep((DWORD)rest_ms);
            }
        }
        else
        {
            // SLEEP SPIN FOR RECHECK
            // CPU AT TIMING
            constexpr float min_spin_ms = 1.0f;
            constexpr float spin_yield_threshold_ms = 0.5f;
            constexpr float sleep_threshold_ms = 5.0f;
           
            const auto sleep_ms = rest_ms - min_spin_ms;
           
            const auto start_sleep = g_pTimer->GetTimeElapsed();
            if (sleep_ms > sleep_threshold_ms)
            {
                std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<long>(sleep_ms)));
            }
           
            const auto actual_sleep_ms = g_pTimer->GetTimeElapsed() - start_sleep;
            const auto start_spin = g_pTimer->GetTimeElapsed();
            const auto spin_ms = rest_ms - actual_sleep_ms;
           
            // ROT + FRAME COUNT TIMIBNGS
            while (true)
            {
                const auto current = g_pTimer->GetTimeElapsed();
                const auto spinned_ms = current - start_spin;
                if (spinned_ms >= spin_ms) break;
                if (spin_ms - spinned_ms > spin_yield_threshold_ms)
                {
                    std::this_thread::yield();
                }
            }
        }
        current_tick_count += static_cast<int>(rest_ms);
    }
}

---

Conclusión

Este mecanismo garantiza que el motor de renderizado respete los límites de FPS establecidos, utilizando el método de espera más adecuado para balancear el consumo de CPU y la precisión del temporizador/latencia. Para juegos o aplicaciones sensibles a la latencia, el enfoque Sleep Spin es generalmente el preferido.
Bon Dia

🡱 🡳
Real Time Web Analytics