refactor render code, add sections

This commit is contained in:
silverweed 2024-07-25 12:25:05 +02:00
parent bf3fe17393
commit d00db42d7a
3 changed files with 149 additions and 130 deletions

View file

@ -1,3 +1,19 @@
internal
std::optional<Byte_Range> get_section_range(const App_State &app, Section_Id sec)
{
switch (sec) {
default: return {};
case Sec_TFile_Header: return Byte_Range { 0, app.tfile_data.root_file_header_size };
case Sec_TFile_Object: return app.tfile_data.rng_root_file_obj;
case Sec_TFile_Info: return app.tfile_data.rng_root_file_info;
case Sec_TFile_FreeList: return app.tfile_data.rng_root_file_free;
case Sec_TKey_List: return app.rndata.rng_tkeys_list;
case Sec_RNTuple_Anchor: return app.rndata.rng_anchor;
case Sec_RNTuple_Header: return app.rndata.rng_header;
case Sec_RNTuple_Footer: return app.rndata.rng_footer;
}
}
internal internal
void accum_dt_ms(Delta_Time_Accum &accum, f32 dt) void accum_dt_ms(Delta_Time_Accum &accum, f32 dt)
{ {
@ -31,72 +47,62 @@ String8 to_pretty_size(Arena *arena, u64 bytes)
} }
internal internal
u32 mem_edit_bg_color_fn(const u8 *, u64 off, void *user_data) Section find_section(App_State &app, u64 off)
{ {
App_State *app = reinterpret_cast<App_State *>(user_data); const RNTuple_Data &rdata = app.rndata;
const RNTuple_Data &rdata = app->rndata; const TFile_Data &tdata = app.tfile_data;
const TFile_Data &tdata = app->tfile_data;
u64 rblob_sz = rdata.rblob_header_size; // @Incomplete u64 rblob_sz = rdata.rblob_header_size; // @Incomplete
i64 hilite_cluster = app->viewer.highlight_cluster ? app->viewer.highlighted_cluster : -1; i64 hilite_cluster = app.viewer.highlight_cluster ? app.viewer.highlighted_cluster : -1;
b8 hilite = false;
off += app->viewer.base_display_addr;
#define COL(c) (ImColor((c)[0], (c)[1], (c)[2]))
// TFile start // TFile start
if (off <= tdata.root_file_header_size) return COL(app->viewer.col_tfile_header); if (off <= tdata.root_file_header_size) return { Sec_TFile_Header, { 0, tdata.root_file_header_size }, 0, hilite };
if (tdata.rng_root_file_obj.start <= off && off < tdata.rng_root_file_obj.end()) return COL(app->viewer.col_tfile_obj); if (tdata.rng_root_file_obj.start <= off && off < tdata.rng_root_file_obj.end()) return { Sec_TFile_Object, tdata.rng_root_file_obj, 0, hilite };
if (tdata.rng_root_file_info.start <= off && off < tdata.rng_root_file_info.end()) return COL(app->viewer.col_tfile_info); if (tdata.rng_root_file_info.start <= off && off < tdata.rng_root_file_info.end()) return { Sec_TFile_Info, tdata.rng_root_file_info, 0, hilite };
if (tdata.rng_root_file_free.start <= off && off < tdata.rng_root_file_free.end()) return COL(app->viewer.col_tfile_free); if (tdata.rng_root_file_free.start <= off && off < tdata.rng_root_file_free.end()) return { Sec_TFile_FreeList, tdata.rng_root_file_free, 0, hilite };
// Handle pages /// Handle pages
// fast case: `off` is in the same page info as previous `off`. {
if (app->last_pinfo->range.start < off && off < app->last_pinfo->range.end()) { // fast case: `off` is in the same page info as previous `off`.
if (hilite_cluster >= 0 && app->last_pinfo->cluster_id == (u64)hilite_cluster) if (app.last_pinfo->range.start < off && off < app.last_pinfo->range.end()) {
return COL(app->viewer.col_highlight); hilite = hilite_cluster >= 0 && app.last_pinfo->cluster_id == (u64)hilite_cluster;
if (off >= app->last_pinfo->range.end() - app->last_pinfo->checksum_size()) return { Sec_Page, app.last_pinfo->range, app.last_pinfo->checksum_size(), hilite };
return COL(app->viewer.col_checksum); }
return COL(app->viewer.col_page);
// still fast case: `off is in the next page info as the previous.
if (app.last_pinfo->next) // don't check if it's checksum, since it's the first byte of the page
app.last_pinfo = app.last_pinfo->next;
if (app.last_pinfo && app.last_pinfo->range.start <= off && off < app.last_pinfo->range.end()) {
hilite = hilite_cluster >= 0 && app.last_pinfo->cluster_id == (u64)hilite_cluster;
return { Sec_Page, app.last_pinfo->range, app.last_pinfo->checksum_size(), hilite };
}
} }
// still fast case: `off is in the next page info as the previous. if (rdata.rng_anchor_key.start <= off && off < rdata.rng_anchor.end())
if (app->last_pinfo->next) // don't check if it's checksum, since it's the first byte of the page return { Sec_RNTuple_Anchor, rdata.rng_anchor, 8, hilite };
app->last_pinfo = app->last_pinfo->next;
if (app->last_pinfo && app->last_pinfo->range.start <= off && off < app->last_pinfo->range.end()) { if (rdata.rng_header.start - rblob_sz <= off && off < rdata.rng_header.end())
if (hilite_cluster >= 0 && app->last_pinfo->cluster_id == (u64)hilite_cluster) return { Sec_RNTuple_Header, rdata.rng_header, 8, hilite };
return COL(app->viewer.col_highlight);
if (off == app->last_pinfo->range.start)
return COL(app->viewer.col_page_start);
if (off >= app->last_pinfo->range.end() - app->last_pinfo->checksum_size())
return COL(app->viewer.col_checksum);
return COL(app->viewer.col_page);
}
if (rdata.rng_anchor_key.start <= off && off < rdata.rng_anchor_key.end()) return COL(app->viewer.col_key); if (rdata.rng_footer.start - rblob_sz <= off && off < rdata.rng_footer.end())
if (rdata.rng_anchor.start <= off && off < rdata.rng_anchor.end() - 8) return COL(app->viewer.col_anchor); return { Sec_RNTuple_Footer, rdata.rng_footer, 8, hilite };
if (rdata.rng_anchor.end() - 8 <= off && off < rdata.rng_anchor.end()) return COL(app->viewer.col_checksum);
if (rdata.rng_header.start - rblob_sz <= off && off < rdata.rng_header.start) return COL(app->viewer.col_key); if (rdata.rng_tkeys_list.start <= off && off < rdata.rng_tkeys_list.end())
if (rdata.rng_header.start <= off && off < rdata.rng_header.end() - 8) return COL(app->viewer.col_header); return { Sec_TKey_List, rdata.rng_tkeys_list, 0, hilite };
if (rdata.rng_header.end() - 8 <= off && off < rdata.rng_header.end()) return COL(app->viewer.col_checksum);
if (rdata.rng_footer.start - rblob_sz <= off && off < rdata.rng_footer.start) return COL(app->viewer.col_key);
if (rdata.rng_footer.start <= off && off < rdata.rng_footer.end() - 8) return COL(app->viewer.col_footer);
if (rdata.rng_footer.end() - 8 <= off && off < rdata.rng_footer.end()) return COL(app->viewer.col_checksum);
if (rdata.rng_tkeys_list.start <= off && off < rdata.rng_tkeys_list.end()) return COL(app->viewer.col_tkeys_list);
// @Speed // @Speed
for (u64 cg_idx = 0; cg_idx < rdata.n_cluster_groups; ++cg_idx) { for (u64 cg_idx = 0; cg_idx < rdata.n_cluster_groups; ++cg_idx) {
Cluster_Group_Info &cg_info = rdata.cluster_groups[cg_idx]; Cluster_Group_Info &cg_info = rdata.cluster_groups[cg_idx];
if (cg_info.rng_page_list.start -rblob_sz <= off && off < cg_info.rng_page_list.start) return COL(app->viewer.col_page_list); if (cg_info.rng_page_list.start - rblob_sz <= off && off < cg_info.rng_page_list.end())
if (cg_info.rng_page_list.start <= off && off < cg_info.rng_page_list.end() - 8) return COL(app->viewer.col_page_list); return { Sec_Page_List, cg_info.rng_page_list, 8, hilite };
if (cg_info.rng_page_list.end() - 8 <= off && off < cg_info.rng_page_list.end()) return COL(app->viewer.col_checksum);
} }
// Slow page group lookup, ideally only done once per render when last_pinfo is invalid. // Slow page group lookup, ideally only done once per render when last_pinfo is invalid.
for (Page_Info_Chunk *chunk = rdata.page_chunks; chunk; chunk = chunk->next) { for (Page_Info_Chunk *chunk = rdata.page_chunks; chunk; chunk = chunk->next) {
if (chunk->range.start - rblob_sz <= off && off < chunk->range.start) return COL(app->viewer.col_key); // If we're at the start of a chunk, return a fake Sec_Page used to highlight the RBlob header bytes.
if (chunk->range.start - rblob_sz <= off && off < chunk->range.start)
return { Sec_Page, { chunk->range.start, 0 }, 0, hilite };
if (chunk->range.start <= off && off < chunk->range.end()) { if (chunk->range.start <= off && off < chunk->range.end()) {
for (u64 group_idx = chunk->first_group; group_idx < rdata.n_page_groups; ++group_idx) { for (u64 group_idx = chunk->first_group; group_idx < rdata.n_page_groups; ++group_idx) {
const Page_Info_Group &group = rdata.page_groups[group_idx]; const Page_Info_Group &group = rdata.page_groups[group_idx];
@ -105,11 +111,9 @@ u32 mem_edit_bg_color_fn(const u8 *, u64 off, void *user_data)
for (Page_Info_Node *pinfo = group.first; pinfo; pinfo = pinfo->next) { for (Page_Info_Node *pinfo = group.first; pinfo; pinfo = pinfo->next) {
if (pinfo->range.start <= off && off < pinfo->range.end()) { if (pinfo->range.start <= off && off < pinfo->range.end()) {
app->last_pinfo = pinfo; app.last_pinfo = pinfo;
if (hilite_cluster >= 0 && pinfo->cluster_id == (u64)hilite_cluster) return COL(app->viewer.col_highlight); hilite = hilite_cluster >= 0 && pinfo->cluster_id == (u64)hilite_cluster;
if (pinfo->range.start == off) return COL(app->viewer.col_page_start); return { Sec_Page, pinfo->range, pinfo->checksum_size(), hilite };
if (off >= pinfo->range.end() - pinfo->checksum_size()) return COL(app->viewer.col_checksum);
return COL(app->viewer.col_page);
} }
} }
} }
@ -119,9 +123,25 @@ u32 mem_edit_bg_color_fn(const u8 *, u64 off, void *user_data)
assert(false); assert(false);
} }
} }
#undef COL
return IM_COL32(0, 0, 0, 0); return {};
}
internal
u32 mem_edit_bg_color_fn(const u8 *, u64 off, void *user_data)
{
App_State *app = reinterpret_cast<App_State *>(user_data);
off += app->viewer.base_display_addr;
Section section = find_section(*app, off);
#define COL(c) (ImColor((c)[0], (c)[1], (c)[2]))
if (section.highlighted) return COL(app->viewer.col_highlight);
if (section.id == Sec_Page && off == section.range.start) return COL(app->viewer.col_page_start);
if (off < section.range.start) return COL(app->viewer.col_key);
if (section.range.end() - section.post_size <= off && off < section.range.end()) return COL(app->viewer.col_checksum);
return COL(app->viewer.col_section[section.id]);
#undef COL
} }
internal internal
@ -152,21 +172,23 @@ void make_viewer(App_State &app)
viewer.mem_edit = make_memory_editor(app); viewer.mem_edit = make_memory_editor(app);
#define COL(c, r, g, b) viewer.c[0] = r/255.0, viewer.c[1] = g/255.0, viewer.c[2] = b/255.0 #define COL(c, r, g, b) viewer.c[0] = r/255.0, viewer.c[1] = g/255.0, viewer.c[2] = b/255.0
COL(col_anchor, 150, 150, 0);
COL(col_header, 150, 0, 50);
COL(col_footer, 50, 0, 150);
COL(col_key, 0, 100, 50); COL(col_key, 0, 100, 50);
COL(col_tfile_header, 90, 90, 90);
COL(col_tfile_obj, 120, 120, 120);
COL(col_tfile_info, 95, 76, 76);
COL(col_tfile_free, 60, 60, 90);
COL(col_page, 125, 0, 125);
COL(col_page_start, 200, 0, 200); COL(col_page_start, 200, 0, 200);
COL(col_checksum, 134, 65, 25); COL(col_checksum, 134, 65, 25);
COL(col_page_list, 60, 110, 120);
COL(col_tkeys_list, 100, 140, 100);
COL(col_highlight, 190, 190, 190); COL(col_highlight, 190, 190, 190);
#define COL_S(c, r, g, b) viewer.col_section[c][0] = r/255.0, viewer.col_section[c][1] = g/255.0, viewer.col_section[c][2] = b/255.0
COL_S(Sec_RNTuple_Anchor, 150, 150, 0);
COL_S(Sec_RNTuple_Header, 150, 0, 50);
COL_S(Sec_RNTuple_Footer, 50, 0, 150);
COL_S(Sec_TFile_Header, 90, 90, 90);
COL_S(Sec_TFile_Object, 120, 120, 120);
COL_S(Sec_TFile_Info, 95, 76, 76);
COL_S(Sec_TFile_FreeList, 60, 60, 90);
COL_S(Sec_Page, 125, 0, 125);
COL_S(Sec_Page_List, 60, 110, 120);
COL_S(Sec_TKey_List, 100, 140, 100);
#undef COL #undef COL
#undef COL_S
app.viewer = viewer; app.viewer = viewer;
} }
@ -282,65 +304,31 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms)
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiColorEditFlags flags = ImGuiColorEditFlags_NoInputs|ImGuiColorEditFlags_NoLabel; ImGuiColorEditFlags flags = ImGuiColorEditFlags_NoInputs|ImGuiColorEditFlags_NoLabel;
ImGui::ColorEdit3("_TFile Header", app.viewer.col_tfile_header, flags); // Unique sections: just display a button that jumps to the start of it and show their size
ImGui::SameLine(); for (u32 i = 0; i < Sec_COUNT; ++i) {
if (ImGui::Button("TFile Header")) viewer_jump_to(app.viewer, 0); std::optional<Byte_Range> range = get_section_range(app, static_cast<Section_Id>(i));
ImGui::SameLine(); if (!range) continue;
ImGui::Text("%s", to_pretty_size(scratch.arena, app.tfile_data.root_file_header_size).c());
ImGui::ColorEdit3("_TFile Object", app.viewer.col_tfile_obj, flags); String8 sec_name = section_names[i];
ImGui::SameLine(); String8 col_label = push_str8f(scratch.arena, "_%s", sec_name.c());
if (ImGui::Button("TFile Object")) viewer_jump_to(app.viewer, app.tfile_data.rng_root_file_obj.start); ImGui::ColorEdit3(col_label.c(), app.viewer.col_section[i], flags);
ImGui::SameLine(); ImGui::SameLine();
ImGui::Text("%s", to_pretty_size(scratch.arena, app.tfile_data.rng_root_file_obj.len).c()); if (ImGui::Button(sec_name.c()))
viewer_jump_to(app.viewer, range->start);
ImGui::ColorEdit3("_TFile Info", app.viewer.col_tfile_info, flags); ImGui::SameLine();
ImGui::SameLine(); ImGui::Text("%s", to_pretty_size(scratch.arena, range->len).c());
if (ImGui::Button("TFile Info")) viewer_jump_to(app.viewer, app.tfile_data.rng_root_file_info.start); }
ImGui::SameLine();
ImGui::Text("%s", to_pretty_size(scratch.arena, app.tfile_data.rng_root_file_info.len).c());
ImGui::ColorEdit3("_TFile FreeList", app.viewer.col_tfile_free, flags);
ImGui::SameLine();
if (ImGui::Button("TFile FreeList")) viewer_jump_to(app.viewer, app.tfile_data.rng_root_file_free.start);
ImGui::SameLine();
ImGui::Text("%s", to_pretty_size(scratch.arena, app.tfile_data.rng_root_file_free.len).c());
ImGui::ColorEdit3("_TKey List", app.viewer.col_tkeys_list, flags);
ImGui::SameLine();
if (ImGui::Button("TKey List")) viewer_jump_to(app.viewer, app.rndata.rng_tkeys_list.start);
ImGui::SameLine();
ImGui::Text("%s", to_pretty_size(scratch.arena, app.rndata.rng_tkeys_list.len).c());
ImGui::ColorEdit3("_RNTuple Anchor", app.viewer.col_anchor, flags);
ImGui::SameLine();
if (ImGui::Button("RNTuple Anchor")) viewer_jump_to(app.viewer, app.rndata.rng_anchor.start);
ImGui::SameLine();
ImGui::Text("%s", to_pretty_size(scratch.arena, app.rndata.rng_anchor.len).c());
ImGui::ColorEdit3("_RNTuple Header", app.viewer.col_header, flags);
ImGui::SameLine();
if (ImGui::Button("RNTuple Header")) viewer_jump_to(app.viewer, app.rndata.rng_header.start);
ImGui::SameLine();
ImGui::Text("%s", to_pretty_size(scratch.arena, app.rndata.rng_header.len).c());
ImGui::ColorEdit3("_RNTuple Footer", app.viewer.col_footer, flags);
ImGui::SameLine();
if (ImGui::Button("RNTuple Footer")) viewer_jump_to(app.viewer, app.rndata.rng_footer.start);
ImGui::SameLine();
ImGui::Text("%s", to_pretty_size(scratch.arena, app.rndata.rng_footer.len).c());
ImGui::ColorEdit3("_TKey Header", app.viewer.col_key, flags);
ImGui::SameLine();
if (ImGui::Button("TKey Header")) {} // TODO jump to next key
// Repeated sections: allow jumping to the N-th
ImGui::ColorEdit3("_Page Start", app.viewer.col_page_start, flags); ImGui::ColorEdit3("_Page Start", app.viewer.col_page_start, flags);
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Page Start")) viewer_jump_to_page(app, 0); if (ImGui::Button("Page Start"))
viewer_jump_to_page(app, 0);
ImGui::ColorEdit3("_Page", app.viewer.col_page, flags); ImGui::ColorEdit3("_Page", app.viewer.col_section[Sec_Page], flags);
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Page")) viewer_jump_to_page(app, app.viewer.latest_page_gone_to); if (ImGui::Button("Page"))
viewer_jump_to_page(app, app.viewer.latest_page_gone_to);
ImGui::SameLine(); ImGui::SameLine();
{ {
const i64 step_fast_i64 = app.rndata.n_pages / 100; const i64 step_fast_i64 = app.rndata.n_pages / 100;
@ -357,7 +345,7 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms)
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Checksum")) {} // TODO jump to next checksum if (ImGui::Button("Checksum")) {} // TODO jump to next checksum
ImGui::ColorEdit3("_Page List", app.viewer.col_page_list, flags); ImGui::ColorEdit3("_Page List", app.viewer.col_section[Sec_Page_List], flags);
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Page List")) viewer_jump_to_page_list(app, app.viewer.latest_page_list_gone_to); if (ImGui::Button("Page List")) viewer_jump_to_page_list(app, app.viewer.latest_page_list_gone_to);
ImGui::SameLine(); ImGui::SameLine();
@ -387,6 +375,7 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms)
i64 cluster_to_highlight = app.viewer.highlighted_cluster; i64 cluster_to_highlight = app.viewer.highlighted_cluster;
ImGui::PushItemWidth(100.f); ImGui::PushItemWidth(100.f);
if (ImGui::InputScalar("##highlighted_cluster", ImGuiDataType_S64, &cluster_to_highlight, &step_i64, &step_fast_i64, "%u")) { if (ImGui::InputScalar("##highlighted_cluster", ImGuiDataType_S64, &cluster_to_highlight, &step_i64, &step_fast_i64, "%u")) {
app.viewer.highlight_cluster = true;
viewer_jump_to_cluster(app, cluster_to_highlight); viewer_jump_to_cluster(app, cluster_to_highlight);
} }
ImGui::PopItemWidth(); ImGui::PopItemWidth();

View file

@ -1,20 +1,11 @@
struct Viewer { struct Viewer {
MemoryEditor mem_edit; MemoryEditor mem_edit;
f32 col_anchor[3]; f32 col_section[Sec_COUNT][3];
f32 col_header[3];
f32 col_footer[3];
f32 col_key[3]; f32 col_key[3];
f32 col_tfile_header[3];
f32 col_tfile_obj[3];
f32 col_tfile_info[3];
f32 col_tfile_free[3];
f32 col_page[3];
f32 col_page_start[3];
f32 col_checksum[3]; f32 col_checksum[3];
f32 col_page_list[3];
f32 col_tkeys_list[3];
f32 col_highlight[3]; f32 col_highlight[3];
f32 col_page_start[3];
u64 base_display_addr; u64 base_display_addr;

View file

@ -84,3 +84,42 @@ struct RNTuple_Data {
Page_Info_Chunk *page_chunks; Page_Info_Chunk *page_chunks;
u64 n_page_chunks; u64 n_page_chunks;
}; };
// A Section represents an interesting sequence of bytes in the file.
// It is associated to stuff such as a color, some metadata, etc.
enum Section_Id {
Sec_None,
Sec_TFile_Header,
Sec_TFile_Object,
Sec_TFile_Info,
Sec_TFile_FreeList,
Sec_TKey_List,
Sec_RNTuple_Anchor,
Sec_RNTuple_Header,
Sec_RNTuple_Footer,
Sec_Page,
Sec_Page_List,
Sec_COUNT
};
struct Section {
Section_Id id;
Byte_Range range;
u64 post_size; // usually the checksum, included in `range`
b8 highlighted;
};
inline const String8 section_names[Sec_COUNT] = {
str8("None"),
str8("TFile Header"),
str8("TFile Object"),
str8("TFile Info"),
str8("TFile FreeList"),
str8("TKey List"),
str8("RNTuple Anchor"),
str8("RNTuple Header"),
str8("RNTuple Footer"),
str8("Page"),
str8("Page List"),
};