Tables: sharing transient buffers between tables, reducing memory footprints. (#3740)

This commit is contained in:
ocornut
2021-05-07 18:00:12 +02:00
parent cbcd89152b
commit 32c453ae53
3 changed files with 72 additions and 43 deletions

View File

@ -130,10 +130,11 @@ struct ImGuiTabBar; // Storage for a tab bar
struct ImGuiTabItem; // Storage for a tab item (within a tab bar)
struct ImGuiTable; // Storage for a table
struct ImGuiTableColumn; // Storage for one column of a table
struct ImGuiTableTempData; // Temporary storage for one table (one per table in the stack), shared between tables.
struct ImGuiTableSettings; // Storage for a table .ini settings
struct ImGuiTableColumnsSettings; // Storage for a column .ini settings
struct ImGuiWindow; // Storage for one window
struct ImGuiWindowTempData; // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame)
struct ImGuiWindowTempData; // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame, in practice we currently keep it for each window)
struct ImGuiWindowSettings; // Storage for a window .ini settings (we keep one of those even if the actual window wasn't instanced during this session)
// Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists.
@ -1516,8 +1517,9 @@ struct ImGuiContext
// Table
ImGuiTable* CurrentTable;
int CurrentTableStackIdx;
ImPool<ImGuiTable> Tables;
ImVector<ImGuiPtrOrIndex> CurrentTableStack;
ImVector<ImGuiTableTempData> TablesTempDataStack;
ImVector<float> TablesLastTimeActive; // Last used timestamp of each tables (SOA, for efficient GC)
ImVector<ImDrawChannel> DrawChannelsTempMergeBuffer;
@ -1694,6 +1696,7 @@ struct ImGuiContext
memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal));
CurrentTable = NULL;
CurrentTableStackIdx = -1;
CurrentTabBar = NULL;
LastValidMousePos = ImVec2(0.0f, 0.0f);
@ -2089,12 +2092,13 @@ struct ImGuiTableCellData
ImGuiTableColumnIdx Column; // Column number
};
// FIXME-TABLE: transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData
// FIXME-TABLE: more transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData
struct ImGuiTable
{
ImGuiID ID;
ImGuiTableFlags Flags;
void* RawData; // Single allocation to hold Columns[], DisplayOrderToIndex[] and RowCellData[]
ImGuiTableTempData* TempData; // Transient data while table is active. Point within g.CurrentTableStack[]
ImSpan<ImGuiTableColumn> Columns; // Point within RawData[]
ImSpan<ImGuiTableColumnIdx> DisplayOrderToIndex; // Point within RawData[]. Store display order of columns (when not reordered, the values are 0...Count-1)
ImSpan<ImGuiTableCellData> RowCellData; // Point within RawData[]. Store cells background requests for current row.
@ -2146,22 +2150,13 @@ struct ImGuiTable
ImRect Bg0ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG0/1 channel. This tends to be == OuterWindow->ClipRect at BeginTable() because output in BG0/BG1 is cpu-clipped
ImRect Bg2ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG2 channel. This tends to be a correct, tight-fit, because output to BG2 are done by widgets relying on regular ClipRect.
ImRect HostClipRect; // This is used to check if we can eventually merge our columns draw calls into the current draw call of the current window.
ImRect HostBackupWorkRect; // Backup of InnerWindow->WorkRect at the end of BeginTable()
ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable()
ImRect HostBackupInnerClipRect; // Backup of InnerWindow->ClipRect during PushTableBackground()/PopTableBackground()
ImVec2 HostBackupPrevLineSize; // Backup of InnerWindow->DC.PrevLineSize at the end of BeginTable()
ImVec2 HostBackupCurrLineSize; // Backup of InnerWindow->DC.CurrLineSize at the end of BeginTable()
ImVec2 HostBackupCursorMaxPos; // Backup of InnerWindow->DC.CursorMaxPos at the end of BeginTable()
ImVec2 UserOuterSize; // outer_size.x passed to BeginTable()
ImVec1 HostBackupColumnsOffset; // Backup of OuterWindow->DC.ColumnsOffset at the end of BeginTable()
float HostBackupItemWidth; // Backup of OuterWindow->DC.ItemWidth at the end of BeginTable()
int HostBackupItemWidthStackSize;// Backup of OuterWindow->DC.ItemWidthStack.Size at the end of BeginTable()
ImGuiWindow* OuterWindow; // Parent window for the table
ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window)
ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names
ImDrawListSplitter DrawSplitter; // We carry our own ImDrawList splitter to allow recursion (FIXME: could be stored outside, worst case we need 1 splitter per recursing table)
ImDrawListSplitter DrawSplitter; // We carry our own ImDrawList splitter to allow recursion (should move to ImGuiTableTempDataB)
ImGuiTableColumnSortSpecs SortSpecsSingle;
ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would work be good.
ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would be good.
ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs()
ImGuiTableColumnIdx SortSpecsCount;
ImGuiTableColumnIdx ColumnsEnabledCount; // Number of enabled columns (<= ColumnsCount)
@ -2208,6 +2203,26 @@ struct ImGuiTable
IMGUI_API ~ImGuiTable() { IM_FREE(RawData); }
};
// Transient data that are only needed between BeginTable() and EndTable(), those buffers are shared.
// Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure.
// FIXME-TABLE: more transient data could be stored here: DrawSplitter (!), SortSpecs? incoming RowData?
struct ImGuiTableTempData
{
int TableIndex; // Index in g.Tables.Buf[] pool
ImVec2 UserOuterSize; // outer_size.x passed to BeginTable()
ImRect HostBackupWorkRect; // Backup of InnerWindow->WorkRect at the end of BeginTable()
ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable()
ImVec2 HostBackupPrevLineSize; // Backup of InnerWindow->DC.PrevLineSize at the end of BeginTable()
ImVec2 HostBackupCurrLineSize; // Backup of InnerWindow->DC.CurrLineSize at the end of BeginTable()
ImVec2 HostBackupCursorMaxPos; // Backup of InnerWindow->DC.CursorMaxPos at the end of BeginTable()
ImVec1 HostBackupColumnsOffset; // Backup of OuterWindow->DC.ColumnsOffset at the end of BeginTable()
float HostBackupItemWidth; // Backup of OuterWindow->DC.ItemWidth at the end of BeginTable()
int HostBackupItemWidthStackSize;//Backup of OuterWindow->DC.ItemWidthStack.Size at the end of BeginTable()
IMGUI_API ImGuiTableTempData() { memset(this, 0, sizeof(*this)); LastTimeActive = -1.0f; }
};
// sizeof() ~ 12
struct ImGuiTableColumnSettings
{