Files
AC6_recomp/src/ac6recomp_app.h
T
Dipshet 9603fb84d0 Added F3 debug overlay: FPS counters, frametime graphs
FPS/frametime counters (avg 0.5s), two fixed-time-interval frametime graphs (fps-independent, spikes preserved), present-wait metric (rex/ui/present_stats.h). Guest stats provider wired in OnCreateDialogs. Removed the old inline F3-only build watermark (moves to a standalone always-on drawer in a later commit).
2026-07-14 20:12:39 +02:00

99 lines
3.3 KiB
C++

#pragma once
#include <memory>
#include <string>
#include <rex/cvar.h>
#include <rex/logging.h>
#include <rex/rex_app.h>
#if REX_HAS_D3D12
#include <rex/graphics/d3d12/graphics_system.h>
#endif
#if REX_HAS_VULKAN
#include <rex/graphics/vulkan/graphics_system.h>
#endif
#include "ac6_native_graphics.h"
#include "ac6_native_graphics_overlay.h"
#include "render_hooks.h"
#include "generated/ac6recomp_config.h"
REXCVAR_DECLARE(std::string, ac6_graphics_backend);
class Ac6recompApp : public rex::ReXApp {
public:
using rex::ReXApp::ReXApp;
Ac6recompApp(rex::ui::WindowedAppContext& ctx, std::string_view name, rex::PPCImageInfo ppc_info)
: rex::ReXApp(ctx, name, ppc_info) {
REXLOG_INFO("Ac6recompApp constructor");
}
static std::unique_ptr<rex::ui::WindowedApp> Create(
rex::ui::WindowedAppContext& ctx) {
REXLOG_INFO("Ac6recompApp::Create");
return std::unique_ptr<Ac6recompApp>(new Ac6recompApp(ctx, "ac6recomp", PPCImageConfig));
}
protected:
void OnPreSetup(rex::RuntimeConfig& config) override {
REXLOG_INFO("Ac6recompApp::OnPreSetup");
rex::ReXApp::OnPreSetup(config);
const std::string requested_backend = REXCVAR_GET(ac6_graphics_backend);
#if REX_HAS_VULKAN
if (requested_backend == "vulkan" || requested_backend == "auto") {
config.graphics =
REX_GRAPHICS_BACKEND(rex::graphics::vulkan::VulkanGraphicsSystem);
REXLOG_INFO("Ac6recompApp: selected Vulkan graphics backend");
return;
}
#endif
#if REX_HAS_D3D12
if (requested_backend == "d3d12" || requested_backend == "auto") {
config.graphics =
REX_GRAPHICS_BACKEND(rex::graphics::d3d12::D3D12GraphicsSystem);
REXLOG_INFO("Ac6recompApp: selected D3D12 graphics backend");
return;
}
#endif
REXLOG_WARN("Ac6recompApp: requested graphics backend '{}' is not available in this build",
requested_backend);
}
void OnPostSetup() override {
REXLOG_INFO("Ac6recompApp::OnPostSetup");
rex::ReXApp::OnPostSetup();
auto* graphics_sys = runtime()->graphics_system();
if (graphics_sys) {
graphics_sys->SetFrameBoundaryCallback([](rex::memory::Memory* memory) {
::ac6::graphics::OnFrameBoundary(memory);
});
REXLOG_INFO("Ac6recompApp: Native frame boundary callback registered");
}
}
void OnCreateDialogs(rex::ui::ImGuiDrawer* drawer) override {
REXLOG_INFO("Ac6recompApp::OnCreateDialogs");
native_graphics_status_dialog_ =
std::make_unique<ac6::graphics::NativeGraphicsStatusDialog>(drawer);
native_graphics_status_dialog_->Show();
// Feed the F3 debug overlay the game's own frame stats so its guest
// frametime graph and counter reflect the real sim cadence (SDK cannot
// reach into the AC6 app layer, so it takes them through this callback).
// Must be here, not OnPostSetup: the debug overlay is created just before
// OnCreateDialogs, but OnPostSetup runs BEFORE the overlay exists, so a
// provider set there is silently dropped.
SetGuestFrameStats([]() -> rex::ui::FrameStats {
const ::ac6::FrameStats s = ::ac6::GetFrameStats();
return rex::ui::FrameStats{s.frame_time_ms, s.fps, s.frame_count};
});
}
private:
std::unique_ptr<ac6::graphics::NativeGraphicsStatusDialog> native_graphics_status_dialog_;
};