Files
fn_registry/dev/issues/completed/0049c-graph-renderer-tier1.md

4.8 KiB
Raw Permalink Blame History

id, title, status, type, domain, scope, priority, depends, blocks, related, created, updated, tags
id title status type domain scope priority depends blocks related created updated tags
0049c `graph_renderer` Tier 1: RGBA8, orphan buffers, frustum cull, auto-pause completado feature
multi-app alta
2026-05-17 2026-05-17

0049c — graph_renderer Tier 1: RGBA8, orphan buffers, frustum cull, auto-pause

Metadata

Campo Valor
ID 0049c
Estado pendiente
Prioridad alta
Tipo mejora rendimiento — parte de #0049

Dependencias

Bloqueada por: 0049b (recomendado pero no estricto — cambios funcionan en 3.3 tambien). Desbloquea: 0049d, demos perf-realistas para issues posteriores.


Objetivo

Optimizaciones baratas y de gran impacto sobre graph_renderer.cpp y graph_force_layout para subir de ~5k nodos a ~20k nodos a 60fps en GPU integrada sin cambiar la API publica.

Contexto

Hoy el renderer:

  • Empaqueta colores como 4 floats × N (16 bytes/nodo) en el instance buffer.
  • Llama glBufferData cada frame → driver realloca el VBO.
  • Sube todas las aristas siempre, aunque esten fuera del viewport.
  • Force layout corre cada frame aunque la energia sea minima (estado convergido).

Arquitectura

cpp/functions/viz/
├── graph_renderer.{h,cpp}                 # MOD
├── graph_renderer.md                       # MOD: bump version (1.x)
├── graph_force_layout.{h,cpp}             # MOD: helper auto_pause
└── graph_force_layout.md                   # MOD

Sin cambios en la API publica — son optimizaciones internas.

Tareas

Fase 1 — Color packing RGBA8

  • 1.1 En el instance buffer, cambiar layout de (x, y, size, r, g, b, a) floats a (x, y, size, color_rgba8) donde color_rgba8 es uint32 packed.
  • 1.2 Ajustar shader vertex de nodos: layout(location=3) in uint a_color; vec4 col = unpackUnorm4x8(a_color);.
  • 1.3 Ajustar el packing en CPU: helper pack_rgba8(r,g,b,a) = (a<<24)|(b<<16)|(g<<8)|r.
  • 1.4 Idem para el buffer de aristas (color por vertex → uint32 por vertex).

Fase 2 — Orphan buffer pattern

  • 2.1 Reemplazar glBufferData(GL_ARRAY_BUFFER, sz, data, GL_DYNAMIC_DRAW) por:
    glBufferData(GL_ARRAY_BUFFER, capacity_bytes, nullptr, GL_STREAM_DRAW);  // orphan
    glBufferSubData(GL_ARRAY_BUFFER, 0, used_bytes, data);
    
  • 2.2 Mantener capacity_bytes interno en el GraphRenderer y crecer al doble si used_bytes > capacity.

Fase 3 — Frustum cull aristas

  • 3.1 Calcular AABB visible en world coords:
    float wx0 = cam_x - (width/2)/zoom;  float wx1 = cam_x + (width/2)/zoom;
    float wy0 = cam_y - (height/2)/zoom; float wy1 = cam_y + (height/2)/zoom;
    
  • 3.2 En el bucle de aristas, skip si AABB de la arista (segmento source→target con margen) no intersecta el viewport AABB.
  • 3.3 Nodos: similar — skip nodos cuyo AABB (centro ± size) cae fuera. Como son draws instanced, el cull se hace empaquetando solo los visibles en el instance buffer (mantener un counter visible_count).

Fase 4 — Auto-pause force layout

  • 4.1 En graph_force_layout.h, anadir helper:
    // Devuelve true si la energia ha caido bajo el umbral durante N frames consecutivos.
    bool graph_force_layout_should_pause(float energy, float threshold, int min_consecutive);
    
  • 4.2 Documentar uso en el .md. El consumer guarda un contador interno; el helper es puro.
  • 4.3 Migrar demos_graph.cpp para usarlo y para no invocar _step cuando paused == true. Boton "Resume" ya existe.

Fase 5 — Tests + benchmark

  • 5.1 Test Catch2 sobre pack_rgba8/unpack_rgba8: roundtrip exacto.
  • 5.2 Test Catch2 sobre graph_force_layout_should_pause: secuencias artificiales.
  • 5.3 Benchmark manual en demos_graph con N=20000: anotar fps antes/despues en el .md de la funcion (notes:).

Fase 6 — Cleanup

  • Bump version del .md de graph_renderer a 1.1.0 y de graph_force_layout a 1.1.0.
  • fn index y verificar.
  • Commit perf(viz): graph_renderer Tier 1 (RGBA8, orphan, cull) + force_layout auto-pause.

Criterio de done

  • demos_graph con 20k nodos a 60fps en GPU integrada de pruebas.
  • Tests verdes.
  • nvidia-smi o radeontop muestran que la CPU baja respecto al baseline (perfilar con Tracy si TRACY_ENABLE).

Riesgos

Riesgo Mitigacion
unpackUnorm4x8 no esta en GL 3.3 sin extension Esta en core 4.0+; con bump 0049b ya disponible. Si 0049b no se mergea antes, fallback a (color>>0)&0xff)/255.0 manual
Frustum cull provoca pop-in en bordes Anadir margen del 10% del viewport AABB
Crecimiento de capacity buffer en streaming Crecer al doble; documentar capacity inicial razonable (4096 nodos)