Skip to content

Debug Tables

Vicious Squid edited this page Oct 1, 2026 · 4 revisions

Debug Tables (Dense Numerical Instrument) is real-time developer tool for inspecting the dense data used by the renderer.

Intended to make the RenderTable/EntityTable rendering pipeline visible rather than treating it as a black box.

Open it from:

Debug → Debug Tables

The Debug menu also contains Project Overview… and Validate All Connections…, providing map-level, I/O-level and dense-rendering diagnostics in one place.

Purpose

Fio's renderer does not normally need to reconstruct authored objects in order to render the world. The runtime publishes dense numerical state through:

  • RenderTable — dense brush/render-projection state
  • EntityTable — dense entity state
  • visible integer slot arrays — the rows selected for the current view

Debug Tables exposes those structures directly.

The window is read-only. It does not create a second world representation and does not modify the rendering pipeline.

The tool reads the published render-state snapshot used by the live editor/runtime.

Pipeline

The Pipeline tab shows the current dense execution path:

World / LogicThread
        ↓
RenderTable + EntityTable
        ↓
visible integer slots
        ↓
renderer key generation / sorting
        ↓
contiguous runs
        ↓
instanced GL submission

It also reports:

  • live RenderTable row count
  • RenderTable allocated capacity
  • live EntityTable row count
  • EntityTable allocated capacity
  • NumPy memory used by each table
  • total dense numerical storage
  • published render-state frame age
  • renderer draw-call count
  • batched draw count
  • visible triangle count

The tool deliberately does not invent CPU stage timings. It reports only measurements that are actually available from the published state and renderer statistics.

RenderTable

The RENDERTABLE tab provides direct read-only access to the NumPy arrays held by the live RenderTable.

Select any available array from the ARRAY selector to inspect its rows and values.

Each array view reports its:

  • shape
  • dtype
  • allocated byte size
  • live row values

The table contains dense render information such as transforms, classification flags, texture identifiers, UV state, colours, geometry identifiers and special-material state.

This is the actual numerical representation consumed by the renderer; the Debug Tables window does not translate it back into Brush objects for display.

EntityTable

The ENTITYTABLE tab performs the same inspection for the live EntityTable.

This exposes the dense numerical representation of renderable entities, including fields used to classify and submit models, sprites and Effects.

This makes it possible to inspect the data that reaches the renderer without relying on the original authored Thing representation.

Key Microscope

The KEY MICROSCOPE shows the logical render-key stream generated from the visible RenderTable rows.

For the cube-brush path, the logical key layout is:

[ texture-name-id: 32 bits | cube-face: 3 bits ]

The tool:

  1. Starts from the current visible RenderTable slots.
  2. Filters out non-cube geometry.
  3. Examines the six texture slots for each visible cube brush.
  4. Removes faces marked as non-drawable.
  5. Packs each drawable face into an integer render key.
  6. Sorts those keys into contiguous runs.
  7. Reports the resulting runs and key distribution.

The display includes:

  • visible cube rows
  • drawable faces
  • number of contiguous runs
  • run start/end positions
  • run lengths
  • packed hexadecimal keys
  • texture-name IDs
  • cube-face IDs
  • key frequency distribution

For example:

RENDER-KEY MICROSCOPE

Logical key layout: [ texture-name-id:32 | cube-face:3 ]

visible cube rows   1,024
drawable faces      5,781
contiguous runs        47

RUNS
  000  rows     0-  143  n=144  key=0x0000000123  tex=  36 face=3
  001  rows   144-  287  n=144  key=0x0000000243  tex=  72 face=3
  ...

This makes batching behaviour directly inspectable instead of relying on a single draw-call count.

Logical key vs final renderer key

The microscope displays the logical brush key.

The logical key uses texture-name-id so the numerical projection remains independent of OpenGL resource handles.

At the renderer boundary, the texture-name ID is resolved to the corresponding GL texture ID, which is used by the renderer's final brush key.

Therefore the microscope intentionally shows the key one step before the GL-resource resolution boundary.

Follow Selection

Enable FOLLOW SELECTION to trace the currently selected object through the dense representation.

When the selected object has an ID, Debug Tables resolves that ID against the live tables and can show:

authored ID
    ↓
RenderTable row
    ↓
logical render key
    ↓
render run

For entity rows it can also show:

authored ID
    ↓
EntityTable row
    ↓
sprite-key

This allows a specific object selected in the editor to be followed into the numerical rendering pipeline.

If an ID cannot be found, the tool reports:

ID NOT PRESENT IN RENDERTABLE OR ENTITYTABLE

This is useful for diagnosing stale projections, missing rows, selection mismatches and unexpected classification.

Memory

The MEMORY tab lists every NumPy array in both tables.

For each field it reports:

TABLE / FIELD
SHAPE
DTYPE
BYTES

Both live row count and allocated capacity matter here.

Fio's dense tables retain allocated storage beyond the current live row count, so the displayed byte count represents the actual NumPy allocation rather than an estimate based only on populated rows.

Live Updates

Debug Tables refreshes automatically while open.

The raw array views expose the currently published tables. The window therefore follows the runtime's published render-state boundary rather than independently rebuilding scene state.

The window can also be manually refreshed with Refresh.

Export

Use Export to save a complete numerical debug snapshot as a ZIP archive.

The exported format is:

fio-debug-tables-v1

The archive can contain:

manifest.json
pipeline.json
pipeline.txt

RenderTable/
EntityTable/

visible_brush_slots.npy

KeyMicroscope/
key_microscope.json
key_microscope.txt

memory.json
memory.txt
follow_selection.txt

The RenderTable and EntityTable arrays are exported as NumPy .npy files.

The arrays are exported at their full allocated capacity rather than being truncated. The live row count and live shape are recorded separately in the memory metadata.

This makes the export useful for offline analysis as well as immediate debugging.

What Debug Tables is for

Debug Tables is particularly useful when investigating:

  • unexpected RenderTable contents
  • missing or duplicated dense rows
  • entity classification problems
  • sprite/model/Effect projection errors
  • incorrect render keys
  • excessive render runs
  • poor batching
  • stale selection mappings
  • live entity or brush insertion
  • dense-table capacity growth
  • render-state publication problems
  • discrepancies between dense state and visible rendering

It is also useful when developing the renderer itself: the numerical data can be inspected before changing the rendering code, making it possible to determine whether a problem originates in projection, classification, key generation, batching or GL submission.

Design principle

Debug Tables is deliberately built around the same dense representation used by the renderer.

It does not maintain a parallel debug scene, duplicate the world model or convert the tables back into collections of authored objects.

The purpose is simple:

What the renderer sees should be inspectable.

That makes the dense rendering pipeline observable all the way from an authored object's identity through table rows and packed keys to the renderer's submission statistics.

Clone this wiki locally