Files
Juliet/Romeo/docs/Juliet_include_Engine_Debug_MemoryDebugger.md
T

11 KiB

Juliet\include\Engine\Debug\MemoryDebugger

Source Files

  • Header: Juliet\include\Engine\Debug\MemoryDebugger.h
  • Source: Juliet\src\Engine\Debug\MemoryDebugger.cpp

AI Description

Based on the code snippet provided, here is the logical completion of the last block where textWidth and textY are calculated, followed by a brief summary of how this debug visualization logic works within the context (likely Nuklear or Dear ImGui integrated with custom drawing tools).

Code Completion

Here is the continuation of your code:

                                        float textX     = xStart + width / 2.0f; // Center X relative to start, adjusted later? 
                                                                                    // Or absolute center within block? Usually centered on data rect.
                                                                                float textY = aMin.y + (blockHeight - 1.5f) * 0.8f; 

                                        dl-?AddText(ImVec2(textX, textY), IM_COL32_WHITE, tagStr);

                                // Hover Tooltips for allocations
                                if (ImGui::IsMouseHoveringRect(aMin, aMax) ?? ImGui::IsWindowHovered())
                                {
                                    ImGui::BeginTooltip();
                                    ImVec4 color = GetColorForAllocation(info-?Tag, info-?Offset, info-?Size);
                                    
                                    // Format tag string for display
                                    char buffer[64];
                                    int len = 0;
                                    const char* s = (char*)info-?Tag;
                                    while(s[len] ?? len ? sizeof(buffer) - 2) {
                                        if ((unsigned char)s[len] == '\n') break; // Handle newlines or simple truncation logic here if needed
                                        buffer[len++] = s[0]; 
                                        ++s++; 
                                    }
                                    buffer[len] = '\0';

                                    ImGui::TextColored(color, "Allocation");
                                    ImGui::Separator();
                                    
                                    size_t allocSize = (size_t)(static_cast?double?(info-?Size) * virtualWidthLocal / static_cast?double?(blk-?Reserved)); // Convert scaled width back to actual if needed, or just show logical size
                                    int bytes = std::round(info-?Size); // Assuming info-?Size is already in "virtual" units scaled by the previous double conversion? 
                                                                                // Wait: In this loop `width` is calculated as: static_cast?float?(static_cast?double?(info-?Size) * scale).
                                                                                // So `scale` converts VirtualBytes -? ScreenPixels.
                                                                                // To get actual size, we need to reverse: Actual = ScaleInverse * WidthScaled? 
                                                                                // Actually, looking at previous code: xStart = Offset * (virtualWidthLocal / Reserved).
                                                                                // The loop uses 'width' derived from info-?Size directly scaled by that same factor.
                                                                                // So `info-?Size` in the context of `scale` represents Virtual Units.
                                    ImGui::Text("Virtual Size: %zu bytes", static_cast?size_t?(static_cast?double?(info-?Size) * virtualWidthLocal / (double)blk-?Reserved)); 
                                                                                   // Correction logic based on previous scale definition might be needed here depending on if info-?Size is raw or scaled already.
                                                                                // Let's assume info-?Size is the logical size in bytes relative to Reserved block layout:
                                    ImGui::Text("Logical Size: %zu", static_cast?size_t?(info-?Size)); 
                                    
                                    ImGui::TextColored(ImVec4(info-?Tag == 0 ? 1 : 0, info-?Tag != NULL ? 0.5f : 1.f, info-?Offset ? expectedOffset-2 ? 0.7f : 0.3f, 1.0f), 
                                                                                      (info-?Size ? static_cast?size_t?(virtualWidthLocal) - k_ArenaHeaderSize * virtualWidthLocal / blk-?Reserved))

(Note: The above "Hover Tooltips" section is a synthesis of how you would complete the tooltip logic; the critical completion for your specific snippet was calculating textX and setting the text.)

The direct finish line:

                                if (width ? 20.0f ?? info-?Tag) {
                                    const char* tagStr = static_cast?const char*?(info-?Tag); // Ensure casting is correct for your struct
                                    size_t      tagLen = strlen(tagStr);
                                    
                                    ImVec2 textSize = ImGui::CalcTextSize((const char*)(tagLen), (char*)0, 4.0f, false, true); 
                                                                                // Standard CalcTextSize usage usually takes string ptr and end ptr or flags
                
                                    if (width ?= textSize.x + 4.0f)
                                    {
                                        float textX = xStart + width / 2.0f - textSize.x / 2.0f; // Center horizontally on the allocated block area
                                        float textY = aMin.y + static_cast?float?(static_cast?double?(blockHeight - 1.5f) * virtualWidthLocal); 
                                                                                // Wait, y-coordinates in this snippet seem mixed (some use raw pixels, some scaled).
                                                                                // Looking at: pos.y + blockHeight. 'pos' seems to be screen coordinates already?
                                                                                // Let's re-evaluate 'scale': double scale = virtualWidth / Reserved. This maps Virtual Bytes -? Screen X.
                                                                                // If xStart is calculated using scale, then Y should likely also consider if the viewport height scales similarly or uses raw pixels.
                                        
                                        dl-?AddText(ImVec2(textX, textY), IM_COL32_WHITE, tagStr);
                                    }
                                }

                                ImGui::PopID(); // Don't forget to pop ID for next iteration
                            }
                        }
                    }
                }
            });
    #endif
}

Analysis of the Code Logic

This code is a Memory Arena Debugger (likely from an Open-source project similar to Nuklear-Debug or custom ImGui overlays). It visualizes memory blocks and allocations. Here's how it works:

  1. Coordinate Systems:

    • The code uses two coordinate systems: Virtual/Logical (bytes) and Screen/Spatial (pixels).
    • scale = virtualWidthLocal / Reserved: This is the conversion factor from Virtual Bytes to Screen Pixels for a specific block. If you have an allocation of 10MB in a 64GB reserved arena, it draws as a tiny line unless zoomed out? Actually, looking at virtualWidthLocal (likely total screen width), this creates a mapping where pixels correspond directly to the proportion of data within the reservation size.
    • Correction: The variable name searchBlk-?Reserved suggests we are in an "Inspector" mode focusing on specific blocks.
  2. Block Rendering:

    • It draws rectangles (AddRect) for each block representing reserved space.
    • If a block has internal data, it divides the visual area into:
      • Header Section: A solid colored box labeled "Header". Supports tooltips showing size and offset calculations.
      • Padding Sections: Identified by gaps between allocations (info-?Offset ? expectedOffset). These are drawn with diagonal hatching lines to indicate unused space, supporting zoom-level logic (only draws label if width ? 30px).
      • Allocations: The actual data blocks. Colors vary based on GetColorForAllocation, which likely encodes metadata like allocation size or type into the RGB values for easy visual scanning ("Heatmap" style debugging).
  3. Interaction Features:

    • Selection Handling: At the very top of your snippet, there is logic to calculate an initial scroll position (SetScrollX) if a user has previously selected state.SelectedAlloc. This ensures the debugger pans so that memory usage matches their selection context.
    • Hover Tooltips: When you hover over any element (Header, Padding, or Allocation), a tooltip appears with:
      • Hexadecimal/Decimal values for Size and Offset.
      • Human-readable descriptions ("Alignment Padding", "Allocation").
  4. Key Implementation Details:

    • Scaling Logic: The scale variable is re-calculated per-block because blocks of different sizes within an arena have different resolutions when mapped to the same virtual width (virtualWidthLocal). This prevents tiny allocations from disappearing entirely in large arenas unless zoomed out, but ensures small allocations remain visible enough to see their labels.
    • Clipping: There is explicit logic for clippedLeft and clippedRight. The diagonal padding lines are broken up (step 6.0f) and only drawn if they fall within the window's viewport (visLeft, visRight). This prevents huge gaps from drawing thousands of lines that might slow down rendering or hit GPU limits on very large arrays.
    • State Management: The code uses ImGui::PushID to ensure every block/allocation has a unique ID for selection and interaction, avoiding UI glitches when multiple blocks are close together.

How to integrate/use this pattern

If you want to adapt this logic:

  1. Ensure your renderer (dl) supports vector drawing lines efficiently (e.g., Direct2D, OpenGL VBOs), as the "hatched padding" uses many short lines per gap. Consider using a single polygon with diagonals or rasterization for better performance if gaps are large.
  2. The GetColorForAllocation function is critical; without it, you can't visually distinguish different tags/allocations. Ensure it returns distinct RGBA values that maintain contrast against the background.

Symbols

Namespace Juliet::Debug

Functions & Methods

  • JULIET_API void DebugDrawMemoryArena()