memory reports
This commit is contained in:
8
Makefile
8
Makefile
@@ -22,7 +22,8 @@ src/collision.cpp \
|
||||
src/bvh.cpp \
|
||||
src/cutscene.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=pcdrv → PCdrv backend (default, emulator + SIO1)
|
||||
@@ -32,5 +33,10 @@ else
|
||||
CPPFLAGS += -DPCDRV_SUPPORT=1
|
||||
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/psyqo.mk
|
||||
|
||||
96
src/memoverlay.cpp
Normal file
96
src/memoverlay.cpp
Normal 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
47
src/memoverlay.hh
Normal 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
|
||||
@@ -17,6 +17,9 @@
|
||||
|
||||
#include "gtemath.hh"
|
||||
#include "uisystem.hh"
|
||||
#ifdef PSXSPLASH_MEMOVERLAY
|
||||
#include "memoverlay.hh"
|
||||
#endif
|
||||
|
||||
using namespace psyqo::fixed_point_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);
|
||||
}
|
||||
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.chain(clear); m_gpu.chain(ot);
|
||||
if (m_uiSystem) m_uiSystem->renderText(m_gpu);
|
||||
#ifdef PSXSPLASH_MEMOVERLAY
|
||||
if (m_memOverlay) m_memOverlay->renderText(m_gpu);
|
||||
#endif
|
||||
m_frameCount++;
|
||||
}
|
||||
|
||||
@@ -311,9 +320,15 @@ void psxsplash::Renderer::RenderWithBVH(eastl::vector<GameObject*>& objects, con
|
||||
processTriangle(obj->polygons[ref.triangleIndex], fogFarSZ, 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.chain(clear); m_gpu.chain(ot);
|
||||
if (m_uiSystem) m_uiSystem->renderText(m_gpu);
|
||||
#ifdef PSXSPLASH_MEMOVERLAY
|
||||
if (m_memOverlay) m_memOverlay->renderText(m_gpu);
|
||||
#endif
|
||||
m_frameCount++;
|
||||
}
|
||||
|
||||
@@ -756,9 +771,15 @@ void psxsplash::Renderer::RenderWithRooms(eastl::vector<GameObject*>& objects,
|
||||
#endif
|
||||
|
||||
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.chain(clear); m_gpu.chain(ot);
|
||||
if (m_uiSystem) m_uiSystem->renderText(m_gpu);
|
||||
#ifdef PSXSPLASH_MEMOVERLAY
|
||||
if (m_memOverlay) m_memOverlay->renderText(m_gpu);
|
||||
#endif
|
||||
m_frameCount++;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
namespace psxsplash {
|
||||
|
||||
class UISystem; // Forward declaration
|
||||
#ifdef PSXSPLASH_MEMOVERLAY
|
||||
class MemOverlay; // Forward declaration
|
||||
#endif
|
||||
|
||||
struct FogConfig {
|
||||
bool enabled = false;
|
||||
@@ -58,6 +61,9 @@ class Renderer final {
|
||||
int16_t width, int16_t height);
|
||||
|
||||
void SetUISystem(UISystem* ui) { m_uiSystem = ui; }
|
||||
#ifdef PSXSPLASH_MEMOVERLAY
|
||||
void SetMemOverlay(MemOverlay* overlay) { m_memOverlay = overlay; }
|
||||
#endif
|
||||
psyqo::GPU& getGPU() { return m_gpu; }
|
||||
|
||||
static Renderer& GetInstance() {
|
||||
@@ -84,6 +90,9 @@ class Renderer final {
|
||||
psyqo::Color m_clearcolor = {.r = 0, .g = 0, .b = 0};
|
||||
|
||||
UISystem* m_uiSystem = nullptr;
|
||||
#ifdef PSXSPLASH_MEMOVERLAY
|
||||
MemOverlay* m_memOverlay = nullptr;
|
||||
#endif
|
||||
|
||||
TriangleRef m_visibleRefs[MAX_VISIBLE_TRIANGLES];
|
||||
int m_frameCount = 0;
|
||||
|
||||
@@ -148,6 +148,13 @@ void psxsplash::SceneManager::InitializeScene(uint8_t* splashpackData, LoadingSc
|
||||
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;
|
||||
|
||||
playerRotationX = 0.0_pi;
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
#include "fileloader.hh"
|
||||
#include "cutscene.hh"
|
||||
#include "uisystem.hh"
|
||||
#ifdef PSXSPLASH_MEMOVERLAY
|
||||
#include "memoverlay.hh"
|
||||
#endif
|
||||
|
||||
namespace psxsplash {
|
||||
|
||||
@@ -138,6 +141,9 @@ class SceneManager {
|
||||
|
||||
// UI system (v13+)
|
||||
UISystem m_uiSystem;
|
||||
#ifdef PSXSPLASH_MEMOVERLAY
|
||||
MemOverlay m_memOverlay;
|
||||
#endif
|
||||
|
||||
psxsplash::Controls m_controls;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user