perf: benchmark CPU-only sin ventana visible durante medición

- Crear ventana con SDL_WINDOW_HIDDEN para que no aparezca hasta que
  el benchmark termine
- runPerformanceBenchmark() elimina todas las llamadas a render() y
  SDL_HideWindow/ShowWindow; mide solo update() (física pura)
- SDL_ShowWindow() se llama en initialize() tras el benchmark y warmup
- Imprimir resultados por consola con formato [Benchmark CPU]

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-21 01:25:33 +01:00
parent 9ae851d5b6
commit e13905567d

View File

@@ -102,7 +102,7 @@ bool Engine::initialize(int width, int height, int zoom, bool fullscreen, AppMod
// Crear ventana principal (fullscreen si se especifica) // Crear ventana principal (fullscreen si se especifica)
// SDL_WINDOW_HIGH_PIXEL_DENSITY removido — DPI detectado con SDL_GetWindowSizeInPixels() // SDL_WINDOW_HIGH_PIXEL_DENSITY removido — DPI detectado con SDL_GetWindowSizeInPixels()
// SDL_WINDOW_OPENGL eliminado — SDL_GPU usa Metal/Vulkan/D3D12 directamente // SDL_WINDOW_OPENGL eliminado — SDL_GPU usa Metal/Vulkan/D3D12 directamente
Uint32 window_flags = 0; Uint32 window_flags = SDL_WINDOW_HIDDEN; // Oculta hasta que el benchmark termine
if (fullscreen) { if (fullscreen) {
window_flags |= SDL_WINDOW_FULLSCREEN; window_flags |= SDL_WINDOW_FULLSCREEN;
} }
@@ -367,6 +367,9 @@ bool Engine::initialize(int width, int height, int zoom, bool fullscreen, AppMod
delete[] tmp; delete[] tmp;
} }
// Mostrar ventana ahora que el benchmark terminó
SDL_ShowWindow(window_);
} }
return success; return success;
@@ -1410,17 +1413,13 @@ void Engine::runPerformanceBenchmark() {
SDL_free(displays); SDL_free(displays);
} }
SDL_HideWindow(window_); // Benchmark CPU-only: sin render(), sin GPU, ventana permanece oculta
if (gpu_ctx_) gpu_ctx_->setVSync(false); // Disable VSync for benchmark
const int BENCH_DURATION_MS = 600; const int BENCH_DURATION_MS = 600;
const int WARMUP_FRAMES = 5; const int WARMUP_ITERS = 10;
SimulationMode original_mode = current_mode_; SimulationMode original_mode = current_mode_;
auto restore = [&]() { auto restore = [&]() {
if (gpu_ctx_) gpu_ctx_->setVSync(vsync_enabled_);
SDL_ShowWindow(window_);
current_mode_ = original_mode; current_mode_ = original_mode;
if (shape_manager_->isShapeModeActive()) { if (shape_manager_->isShapeModeActive()) {
shape_manager_->toggleShapeMode(false); shape_manager_->toggleShapeMode(false);
@@ -1434,23 +1433,21 @@ void Engine::runPerformanceBenchmark() {
scene_manager_->changeScenario(CUSTOM_SCENARIO_IDX, SimulationMode::SHAPE); scene_manager_->changeScenario(CUSTOM_SCENARIO_IDX, SimulationMode::SHAPE);
activateShapeInternal(ShapeType::SPHERE); activateShapeInternal(ShapeType::SPHERE);
last_frame_time_ = 0; last_frame_time_ = 0;
for (int w = 0; w < WARMUP_FRAMES; ++w) { for (int w = 0; w < WARMUP_ITERS; ++w) {
calculateDeltaTime(); calculateDeltaTime();
SDL_Event e; while (SDL_PollEvent(&e)) {}
update(); update();
render();
} }
int frame_count = 0; int frame_count = 0;
Uint64 start = SDL_GetTicks(); Uint64 start = SDL_GetTicks();
while (SDL_GetTicks() - start < static_cast<Uint64>(BENCH_DURATION_MS)) { while (SDL_GetTicks() - start < static_cast<Uint64>(BENCH_DURATION_MS)) {
calculateDeltaTime(); calculateDeltaTime();
SDL_Event e; while (SDL_PollEvent(&e)) {}
update(); update();
render();
++frame_count; ++frame_count;
} }
float fps = static_cast<float>(frame_count) / (BENCH_DURATION_MS / 1000.0f); float ups = static_cast<float>(frame_count) / (BENCH_DURATION_MS / 1000.0f);
custom_auto_available_ = (fps >= monitor_hz); custom_auto_available_ = (ups >= monitor_hz);
std::cout << "[Benchmark CPU] Custom (" << custom_scenario_balls_ << " bolas): "
<< ups << " ups → " << (custom_auto_available_ ? "OK" : "insuficiente") << "\n";
} }
for (int idx = DEMO_AUTO_MAX_SCENARIO; idx >= DEMO_AUTO_MIN_SCENARIO; --idx) { for (int idx = DEMO_AUTO_MAX_SCENARIO; idx >= DEMO_AUTO_MIN_SCENARIO; --idx) {
@@ -1458,32 +1455,36 @@ void Engine::runPerformanceBenchmark() {
activateShapeInternal(ShapeType::SPHERE); activateShapeInternal(ShapeType::SPHERE);
last_frame_time_ = 0; last_frame_time_ = 0;
for (int w = 0; w < WARMUP_FRAMES; ++w) { for (int w = 0; w < WARMUP_ITERS; ++w) {
calculateDeltaTime(); calculateDeltaTime();
SDL_Event e; while (SDL_PollEvent(&e)) {}
update(); update();
render();
} }
int frame_count = 0; int frame_count = 0;
Uint64 start = SDL_GetTicks(); Uint64 start = SDL_GetTicks();
while (SDL_GetTicks() - start < static_cast<Uint64>(BENCH_DURATION_MS)) { while (SDL_GetTicks() - start < static_cast<Uint64>(BENCH_DURATION_MS)) {
calculateDeltaTime(); calculateDeltaTime();
SDL_Event e;
while (SDL_PollEvent(&e)) {}
update(); update();
render();
++frame_count; ++frame_count;
} }
float measured_fps = static_cast<float>(frame_count) / (BENCH_DURATION_MS / 1000.0f); float measured_ups = static_cast<float>(frame_count) / (BENCH_DURATION_MS / 1000.0f);
if (measured_fps >= monitor_hz) { int ball_count = BALL_COUNT_SCENARIOS[idx];
if (measured_ups >= monitor_hz) {
std::cout << "[Benchmark CPU] Escenario " << idx << " (" << ball_count << " bolas): "
<< measured_ups << " ups → OK\n";
std::cout << "[Benchmark CPU] Resultado: max escenario auto = " << idx
<< " (" << ball_count << " bolas)\n";
max_auto_scenario_ = idx; max_auto_scenario_ = idx;
restore(); restore();
return; return;
} }
std::cout << "[Benchmark CPU] Escenario " << idx << " (" << ball_count << " bolas): "
<< measured_ups << " ups → insuficiente\n";
} }
std::cout << "[Benchmark CPU] Resultado: max escenario auto = " << DEMO_AUTO_MIN_SCENARIO
<< " (" << BALL_COUNT_SCENARIOS[DEMO_AUTO_MIN_SCENARIO] << " bolas)\n";
max_auto_scenario_ = DEMO_AUTO_MIN_SCENARIO; max_auto_scenario_ = DEMO_AUTO_MIN_SCENARIO;
restore(); restore();
} }