memory reports

This commit is contained in:
Jan Racek
2026-03-27 19:30:01 +01:00
parent 4ff7ecdd57
commit 85eb7e59d9
7 changed files with 193 additions and 1 deletions

View File

@@ -22,7 +22,8 @@ src/collision.cpp \
src/bvh.cpp \ src/bvh.cpp \
src/cutscene.cpp \ src/cutscene.cpp \
src/uisystem.cpp \ src/uisystem.cpp \
src/loadingscreen.cpp src/loadingscreen.cpp \
src/memoverlay.cpp
# LOADER=cdrom → CD-ROM backend (for ISO builds on real hardware) # LOADER=cdrom → CD-ROM backend (for ISO builds on real hardware)
# LOADER=pcdrv → PCdrv backend (default, emulator + SIO1) # LOADER=pcdrv → PCdrv backend (default, emulator + SIO1)
@@ -32,5 +33,10 @@ else
CPPFLAGS += -DPCDRV_SUPPORT=1 CPPFLAGS += -DPCDRV_SUPPORT=1
endif endif
# MEMOVERLAY=1 → Enable runtime heap/RAM usage overlay
ifeq ($(MEMOVERLAY),1)
CPPFLAGS += -DPSXSPLASH_MEMOVERLAY
endif
include third_party/nugget/psyqo-lua/psyqo-lua.mk include third_party/nugget/psyqo-lua/psyqo-lua.mk
include third_party/nugget/psyqo/psyqo.mk include third_party/nugget/psyqo/psyqo.mk

96
src/memoverlay.cpp Normal file
View File

@@ -0,0 +1,96 @@
#ifdef PSXSPLASH_MEMOVERLAY
#include "memoverlay.hh"
#include <psyqo/alloc.h>
#include <psyqo/primitives/rectangles.hh>
#include "vram_config.h"
// Linker symbols
extern "C" {
extern char __heap_start;
extern char __stack_start;
}
namespace psxsplash {
void MemOverlay::init(psyqo::Font<>* font) {
m_font = font;
m_heapBase = reinterpret_cast<uintptr_t>(&__heap_start);
m_stackTop = reinterpret_cast<uintptr_t>(&__stack_start);
m_totalAvail = (uint32_t)(m_stackTop - m_heapBase);
}
void MemOverlay::renderOT(psyqo::OrderingTable<Renderer::ORDERING_TABLE_SIZE>& ot,
psyqo::BumpAllocator<Renderer::BUMP_ALLOCATOR_SIZE>& balloc) {
if (!m_font || m_totalAvail == 0) return;
// Measure current heap usage
void* heapEnd = psyqo_heap_end();
uint32_t heapUsed = 0;
if (heapEnd != nullptr) {
heapUsed = (uint32_t)(reinterpret_cast<uintptr_t>(heapEnd) - m_heapBase);
}
m_lastPct = (heapUsed * 100) / m_totalAvail;
if (m_lastPct > 100) m_lastPct = 100;
m_lastUsedKB = heapUsed / 1024;
m_lastTotalKB = m_totalAvail / 1024;
// Bar dimensions - top-right corner
static constexpr int16_t BAR_W = 80;
static constexpr int16_t BAR_H = 6;
static constexpr int16_t BAR_X = VRAM_RES_WIDTH - BAR_W - 4;
static constexpr int16_t BAR_Y = 4;
// Need room for two rectangles
size_t needed = sizeof(psyqo::Fragments::SimpleFragment<psyqo::Prim::Rectangle>) * 2 + 32;
if (balloc.remaining() < needed) return;
// Fill bar first (OT is LIFO, so first insert renders last / on top)
int16_t fillW = (int16_t)((uint32_t)BAR_W * m_lastPct / 100);
if (fillW > 0) {
uint8_t r, g;
if (m_lastPct < 50) {
r = (uint8_t)(m_lastPct * 5);
g = 200;
} else {
r = 250;
g = (uint8_t)((100 - m_lastPct) * 4);
}
auto& fillFrag = balloc.allocateFragment<psyqo::Prim::Rectangle>();
fillFrag.primitive.setColor(psyqo::Color{.r = r, .g = g, .b = 20});
fillFrag.primitive.position = {.x = BAR_X, .y = BAR_Y};
fillFrag.primitive.size = {.x = fillW, .y = BAR_H};
fillFrag.primitive.setOpaque();
ot.insert(fillFrag, 0);
}
// Background bar (inserted second, so renders first / behind fill)
auto& bgFrag = balloc.allocateFragment<psyqo::Prim::Rectangle>();
bgFrag.primitive.setColor(psyqo::Color{.r = 40, .g = 40, .b = 40});
bgFrag.primitive.position = {.x = BAR_X, .y = BAR_Y};
bgFrag.primitive.size = {.x = BAR_W, .y = BAR_H};
bgFrag.primitive.setOpaque();
ot.insert(bgFrag, 0);
}
void MemOverlay::renderText(psyqo::GPU& gpu) {
if (!m_font || m_totalAvail == 0) return;
static constexpr int16_t BAR_H = 6;
static constexpr int16_t BAR_X = VRAM_RES_WIDTH - 80 - 4;
static constexpr int16_t BAR_Y = 4;
static constexpr int16_t TEXT_Y = BAR_Y + BAR_H + 2;
m_font->chainprintf(gpu,
{{.x = BAR_X - 20, .y = TEXT_Y}},
{{.r = 0xcc, .g = 0xcc, .b = 0xcc}},
"%luK/%luK", m_lastUsedKB, m_lastTotalKB);
}
} // namespace psxsplash
#endif // PSXSPLASH_MEMOVERLAY

47
src/memoverlay.hh Normal file
View File

@@ -0,0 +1,47 @@
#pragma once
// Runtime memory overlay - shows heap/RAM usage as a progress bar + text.
// Compiled only when PSXSPLASH_MEMOVERLAY is defined (set from SplashEdit build flag).
#ifdef PSXSPLASH_MEMOVERLAY
#include <psyqo/font.hh>
#include <psyqo/gpu.hh>
#include <psyqo/bump-allocator.hh>
#include <psyqo/ordering-table.hh>
#include "renderer.hh"
namespace psxsplash {
class MemOverlay {
public:
/// Call once at startup to cache linker symbol addresses.
void init(psyqo::Font<>* font);
/// Phase 1: Insert progress bar rectangles into the OT.
/// Call BEFORE gpu.chain(ot).
void renderOT(psyqo::OrderingTable<Renderer::ORDERING_TABLE_SIZE>& ot,
psyqo::BumpAllocator<Renderer::BUMP_ALLOCATOR_SIZE>& balloc);
/// Phase 2: Emit text via chainprintf.
/// Call AFTER gpu.chain(ot).
void renderText(psyqo::GPU& gpu);
private:
psyqo::Font<>* m_font = nullptr;
// Cached addresses from linker symbols
uintptr_t m_heapBase = 0;
uintptr_t m_stackTop = 0;
uint32_t m_totalAvail = 0;
// Cached each frame for text phase
uint32_t m_lastUsedKB = 0;
uint32_t m_lastTotalKB = 0;
uint32_t m_lastPct = 0;
};
} // namespace psxsplash
#endif // PSXSPLASH_MEMOVERLAY

View File

@@ -17,6 +17,9 @@
#include "gtemath.hh" #include "gtemath.hh"
#include "uisystem.hh" #include "uisystem.hh"
#ifdef PSXSPLASH_MEMOVERLAY
#include "memoverlay.hh"
#endif
using namespace psyqo::fixed_point_literals; using namespace psyqo::fixed_point_literals;
using namespace psyqo::trig_literals; using namespace psyqo::trig_literals;
@@ -277,9 +280,15 @@ void psxsplash::Renderer::Render(eastl::vector<GameObject*>& objects) {
processTriangle(obj->polygons[i], fogFarSZ, ot, balloc); processTriangle(obj->polygons[i], fogFarSZ, ot, balloc);
} }
if (m_uiSystem) m_uiSystem->renderOT(m_gpu, ot, balloc); if (m_uiSystem) m_uiSystem->renderOT(m_gpu, ot, balloc);
#ifdef PSXSPLASH_MEMOVERLAY
if (m_memOverlay) m_memOverlay->renderOT(ot, balloc);
#endif
m_gpu.getNextClear(clear.primitive, m_clearcolor); m_gpu.getNextClear(clear.primitive, m_clearcolor);
m_gpu.chain(clear); m_gpu.chain(ot); m_gpu.chain(clear); m_gpu.chain(ot);
if (m_uiSystem) m_uiSystem->renderText(m_gpu); if (m_uiSystem) m_uiSystem->renderText(m_gpu);
#ifdef PSXSPLASH_MEMOVERLAY
if (m_memOverlay) m_memOverlay->renderText(m_gpu);
#endif
m_frameCount++; m_frameCount++;
} }
@@ -311,9 +320,15 @@ void psxsplash::Renderer::RenderWithBVH(eastl::vector<GameObject*>& objects, con
processTriangle(obj->polygons[ref.triangleIndex], fogFarSZ, ot, balloc); processTriangle(obj->polygons[ref.triangleIndex], fogFarSZ, ot, balloc);
} }
if (m_uiSystem) m_uiSystem->renderOT(m_gpu, ot, balloc); if (m_uiSystem) m_uiSystem->renderOT(m_gpu, ot, balloc);
#ifdef PSXSPLASH_MEMOVERLAY
if (m_memOverlay) m_memOverlay->renderOT(ot, balloc);
#endif
m_gpu.getNextClear(clear.primitive, m_clearcolor); m_gpu.getNextClear(clear.primitive, m_clearcolor);
m_gpu.chain(clear); m_gpu.chain(ot); m_gpu.chain(clear); m_gpu.chain(ot);
if (m_uiSystem) m_uiSystem->renderText(m_gpu); if (m_uiSystem) m_uiSystem->renderText(m_gpu);
#ifdef PSXSPLASH_MEMOVERLAY
if (m_memOverlay) m_memOverlay->renderText(m_gpu);
#endif
m_frameCount++; m_frameCount++;
} }
@@ -756,9 +771,15 @@ void psxsplash::Renderer::RenderWithRooms(eastl::vector<GameObject*>& objects,
#endif #endif
if (m_uiSystem) m_uiSystem->renderOT(m_gpu, ot, balloc); if (m_uiSystem) m_uiSystem->renderOT(m_gpu, ot, balloc);
#ifdef PSXSPLASH_MEMOVERLAY
if (m_memOverlay) m_memOverlay->renderOT(ot, balloc);
#endif
m_gpu.getNextClear(clear.primitive, m_clearcolor); m_gpu.getNextClear(clear.primitive, m_clearcolor);
m_gpu.chain(clear); m_gpu.chain(ot); m_gpu.chain(clear); m_gpu.chain(ot);
if (m_uiSystem) m_uiSystem->renderText(m_gpu); if (m_uiSystem) m_uiSystem->renderText(m_gpu);
#ifdef PSXSPLASH_MEMOVERLAY
if (m_memOverlay) m_memOverlay->renderText(m_gpu);
#endif
m_frameCount++; m_frameCount++;
} }

View File

@@ -21,6 +21,9 @@
namespace psxsplash { namespace psxsplash {
class UISystem; // Forward declaration class UISystem; // Forward declaration
#ifdef PSXSPLASH_MEMOVERLAY
class MemOverlay; // Forward declaration
#endif
struct FogConfig { struct FogConfig {
bool enabled = false; bool enabled = false;
@@ -58,6 +61,9 @@ class Renderer final {
int16_t width, int16_t height); int16_t width, int16_t height);
void SetUISystem(UISystem* ui) { m_uiSystem = ui; } void SetUISystem(UISystem* ui) { m_uiSystem = ui; }
#ifdef PSXSPLASH_MEMOVERLAY
void SetMemOverlay(MemOverlay* overlay) { m_memOverlay = overlay; }
#endif
psyqo::GPU& getGPU() { return m_gpu; } psyqo::GPU& getGPU() { return m_gpu; }
static Renderer& GetInstance() { static Renderer& GetInstance() {
@@ -84,6 +90,9 @@ class Renderer final {
psyqo::Color m_clearcolor = {.r = 0, .g = 0, .b = 0}; psyqo::Color m_clearcolor = {.r = 0, .g = 0, .b = 0};
UISystem* m_uiSystem = nullptr; UISystem* m_uiSystem = nullptr;
#ifdef PSXSPLASH_MEMOVERLAY
MemOverlay* m_memOverlay = nullptr;
#endif
TriangleRef m_visibleRefs[MAX_VISIBLE_TRIANGLES]; TriangleRef m_visibleRefs[MAX_VISIBLE_TRIANGLES];
int m_frameCount = 0; int m_frameCount = 0;

View File

@@ -148,6 +148,13 @@ void psxsplash::SceneManager::InitializeScene(uint8_t* splashpackData, LoadingSc
Renderer::GetInstance().SetUISystem(nullptr); Renderer::GetInstance().SetUISystem(nullptr);
} }
#ifdef PSXSPLASH_MEMOVERLAY
if (s_font != nullptr) {
m_memOverlay.init(s_font);
Renderer::GetInstance().SetMemOverlay(&m_memOverlay);
}
#endif
m_playerPosition = sceneSetup.playerStartPosition; m_playerPosition = sceneSetup.playerStartPosition;
playerRotationX = 0.0_pi; playerRotationX = 0.0_pi;

View File

@@ -21,6 +21,9 @@
#include "fileloader.hh" #include "fileloader.hh"
#include "cutscene.hh" #include "cutscene.hh"
#include "uisystem.hh" #include "uisystem.hh"
#ifdef PSXSPLASH_MEMOVERLAY
#include "memoverlay.hh"
#endif
namespace psxsplash { namespace psxsplash {
@@ -138,6 +141,9 @@ class SceneManager {
// UI system (v13+) // UI system (v13+)
UISystem m_uiSystem; UISystem m_uiSystem;
#ifdef PSXSPLASH_MEMOVERLAY
MemOverlay m_memOverlay;
#endif
psxsplash::Controls m_controls; psxsplash::Controls m_controls;