ShaderMemoryAtlas diagram
ShaderMemoryAtlas — architecture & feature overview
Unreal Engine Plugin

Shader Memory Atlas

GPU memory profiler and heatmap visualizer for Unreal Engine 4.27 – 5.x+. Identify, measure, and eliminate VRAM bottlenecks without leaving the editor.

UE 4.27 – 5.x+ Editor Plugin Win64 / Mac / Linux Zero Runtime Overhead Blueprint API CSV Export

Introduction

Shader Memory Atlas gives Unreal Engine developers a clear, actionable view of GPU memory consumption during level authoring. When building levels it is difficult to know which assets are consuming the most VRAM, or to find which actors are responsible for memory spikes. This plugin addresses that problem directly.

The plugin scans every loaded texture, material, shader, and static mesh, ranks each asset by memory footprint, and presents the results in a dockable editor panel. A live color-coded heatmap overlays all level actors so expensive objects are visible in the viewport at a glance — no console commands required.

Shader Memory Atlas is an Editor-only module. It is excluded from all packaged builds by the Unreal Build Tool and adds zero runtime overhead to your shipped game.

Features

📊
VRAM Tracking

Scans all loaded textures, materials, shaders, and static meshes. Queries the RHI driver for accurate total and used GPU memory figures.

🌡
Heatmap Overlay

Color-codes every actor in the level from green (cheap) to red (expensive). Applied and removed in under 100 ms. Original materials restored without side-effects.

🗔
Dockable Editor Panel

Four sortable asset lists with a live VRAM dashboard. Double-click any row to focus the asset directly in the Content Browser.

📄
CSV Export

One-click export to Saved/MemoryAtlasReport.csv. Open in any spreadsheet application for detailed before/after comparison.

🧩
Blueprint API

All heatmap functions are BlueprintCallable. Use in Editor Utility Widgets, custom tools, or Play-in-Editor sessions.

Per-Actor Breakdown

Query memory cost per actor or per level programmatically. Integrate into custom pipeline tools and automated budgeting checks.

Specifications

Plugin TypeEditor (excluded from game targets)
Engine CompatibilityUnreal Engine 4.27 – 5.x+
Editor PlatformsWindows (Win64), macOS, Linux
Loading PhaseDefault
Runtime CostNone — compiles out of packaged builds
Blueprint ExposureFull (heatmap actor API)
C++ StandardC++17 (Unreal Engine default)

Memory Calculation Methods

Asset TypeFormula
UTexture2DWidth × Height × BytesPerPixel(Format) × MipCount
UMaterial10,240 bytes base + (InstructionCount × 100 bytes)
UMaterialInstanceParent material cost + parameter overhead
UStaticMeshVertex buffers + index buffers across all LODs
RHI Total / UsedFTextureMemoryStats via RHIGetTextureMemoryStats()

Pixel format coverage: DXT1 (0.5 bpp), DXT5 (1 bpp), BC7 (1 bpp), RGBA8 (4 bpp), half-float (8 bpp), float (16 bpp). Values are estimates; exact GPU allocation varies by driver, hardware, and streaming state.

Installation

1

Copy the plugin folder

Place the ShaderMemoryAtlas folder inside <YourProject>/Plugins/. Create the Plugins directory if it does not yet exist.

2

Regenerate project files

Right-click <YourProject>.uproject and select Generate Visual Studio project files.

3

Build the project

Open the solution in Visual Studio and build with Ctrl+Shift+B. On macOS / Linux, build from the terminal using RunUAT.sh BuildPlugin.

4

Enable in the Unreal Editor

Open Edit → Plugins, search for Shader Memory Atlas, check Enabled, and click Restart Now.

To make the plugin available across all projects, copy it to <EngineRoot>/Engine/Plugins/ShaderMemoryAtlas/ instead.

Quick Start

1 — Open the panel

Window  →  Shader Memory Atlas

2 — Scan memory

Click Refresh. The plugin iterates all loaded assets and populates the four lists with per-asset memory estimates. A full scan typically completes in 1–5 seconds depending on level size.

3 — Read the results

The dashboard at the top of the panel displays total GPU memory and current driver-reported usage. The four lists below show the highest-cost assets in each category. Double-click any row to select and focus that asset in the Content Browser.

4 — Enable the heatmap

Click Enable Heatmap. Actors are immediately color-coded:

Green — Low 0–50% of peak actor cost. No action needed.
Yellow — Medium 50–75% of peak. Worth reviewing.
Red — High 75–100% of peak. Optimize these first.

Drag the Intensity slider if colors are hard to read in bright scenes. Click Disable Heatmap to restore all original materials instantly.

5 — Export a report

Click Export CSV. Open <Project>/Saved/MemoryAtlasReport.csv in a spreadsheet application and sort by size to find the largest optimization targets.

FVRAMTracker API

FVRAMTracker is a stateless static class. No instance is required. All functions are safe to call from any editor context.

Full scene scan

C++
FVRAMTracker::FMemoryStats Stats = FVRAMTracker::ScanMemoryUsage();

// Stats.TotalVRAM     — driver-reported total GPU memory (bytes)
// Stats.UsedVRAM      — driver-reported used GPU memory (bytes)
// Stats.TextureMemory — aggregate of all texture entries
// Stats.TopTextures   — TArray<FMemoryEntry> sorted by SizeBytes desc

Individual asset queries

C++
int64 TexSize  = FVRAMTracker::GetTextureMemorySize(MyTexture);
int64 MatSize  = FVRAMTracker::GetMaterialMemorySize(MyMaterial);
int64 InstSize = FVRAMTracker::GetMaterialInstanceMemorySize(MyInstance);
int64 MshSize  = FVRAMTracker::GetStaticMeshMemorySize(MyMesh);

Per-actor and per-level breakdown

C++
TArray<FVRAMTracker::FMemoryEntry> Entries =
    FVRAMTracker::GetActorMemoryUsage(MyActor);

TArray<FVRAMTracker::FMemoryEntry> LevelEntries =
    FVRAMTracker::GetLevelMemoryUsage(MyLevel);

RHI driver query and formatting

C++
int64 Total, Used;
FVRAMTracker::GetRHIMemoryStats(Total, Used);

FString Human = FVRAMTracker::FormatBytes(Bytes); // e.g. "512.00 MB"

Data structures

C++ — FMemoryEntry / FMemoryStats
struct FMemoryEntry
{
    FString   Name;        // Asset display name
    FString   Type;        // "Texture" | "Material" | "Shader" | "Mesh"
    int64     SizeBytes;   // Estimated memory in bytes
    UObject*  Object;      // Raw pointer to the asset
    FString   AssetPath;   // Content Browser path
};

struct FMemoryStats
{
    int64 TotalVRAM, UsedVRAM;
    int64 TextureMemory, MaterialMemory, ShaderMemory, MeshMemory;

    TArray<FMemoryEntry> TopTextures;
    TArray<FMemoryEntry> TopMaterials;
    TArray<FMemoryEntry> TopShaders;
    TArray<FMemoryEntry> TopMeshes;
};

AMemoryHeatmap API

AMemoryHeatmap is a spawnable actor. All four functions are BlueprintCallable or BlueprintPure and accessible from both C++ and Blueprint graphs.

C++ — spawn and control
AMemoryHeatmap* Heatmap = World->SpawnActor<AMemoryHeatmap>();

// Apply the heatmap overlay
Heatmap->SetHeatmapEnabled(true);

// Adjust emissive brightness — range 0.1 to 10.0, default 1.0
Heatmap->SetIntensity(2.0f);

// Re-scan the level and reapply colors
Heatmap->RefreshHeatmap();

// Restore all original materials
Heatmap->SetHeatmapEnabled(false);

// Static pure helper — compute the heatmap color for any cost / max pair
FLinearColor Color = AMemoryHeatmap::GetHeatmapColor(ActorCost, MaxCost);

Blueprint function reference

FunctionTypeDescription
SetHeatmapEnabled(bool)BlueprintCallableApplies or removes the heatmap overlay
RefreshHeatmap()BlueprintCallableRe-scans the level and reapplies all colors
SetIntensity(float)BlueprintCallableSets the emissive brightness multiplier (0.1–10.0)
GetHeatmapColor(int64, int64)BlueprintPureReturns FLinearColor for a given cost / max pair

Color encoding algorithm

ratio = ActorCost / MaxCost

ratio 0.00 – 0.50  →  lerp  Green  (0, 1, 0)  →  Yellow  (1, 1, 0)
ratio 0.50 – 1.00  →  lerp  Yellow (1, 1, 0)  →  Red     (1, 0, 0)

final_emissive = color * IntensityMultiplier
Original materials are stored in a TMap<UPrimitiveComponent*, TArray<UMaterialInterface*>> before any dynamic instances are applied. Calling SetHeatmapEnabled(false) iterates this map and restores every slot exactly, leaving no persistent side-effects on the level.

Editor Panel

SShaderMemoryAtlasWidget is a Slate SCompoundWidget rendered inside a registered dockable tab. Open it from Window → Shader Memory Atlas.

┌─ Toolbar ────────────────────────────────────────────┐
│  [ Refresh ]   [ Export CSV ]                            │
├─ Memory Overview ────────────────────────────────────────┬
│  Total VRAM: 8.00 GB          Used: 3.21 GB              │
├─ Textures ───────────────┼─ Materials ───────────────┘
│  T_Rock_Diffuse   128.00 MB  │  M_Rock          45.00 KB  │
│  T_Sky_HDRI        64.00 MB  │  M_Foliage_Base  38.00 KB  │
├─ Shaders ───────────────┼─ Meshes ───────────────────┘
│  SH_Foliage        22.00 KB  │  SM_Building     3.20 MB   │
│  SH_Water          18.00 KB  │  SM_Tree_Hero    1.80 MB   │
├─ Heatmap Controls ──────────────────────────────────┘
│  [ Enable Heatmap ]    Intensity: ──────⬤──────  2.0    │
└───────────────────────────────────────────────────────────└

Control reference

ControlBehavior
RefreshCalls FVRAMTracker::ScanMemoryUsage() and repopulates all four lists
Export CSVSerializes FMemoryStats to <Project>/Saved/MemoryAtlasReport.csv
Enable / Disable HeatmapSpawns or toggles AMemoryHeatmap in the editor world
Intensity sliderCalls AMemoryHeatmap::SetIntensity() on every value change
Double-click asset rowCalls GEditor->SyncBrowserToObjects() with the selected asset

System Design

FShaderMemoryAtlasModule (IModuleInterface) ├── Registers dockable tab spawner ├── Adds "Shader Memory Atlas" entry under Window menu └── Manages plugin lifecycle (startup / shutdown) SShaderMemoryAtlasWidget (SCompoundWidget — Slate) ├── Memory overview dashboard (TotalVRAM, UsedVRAM) ├── Four SListView<FMemoryEntry> (Textures / Materials / Shaders / Meshes) ├── Heatmap enable toggle + intensity slider ├── Toolbar (Refresh, Export CSV) └── Double-click → GEditor SyncBrowserToObjects() FVRAMTracker (static utility class) ├── ScanMemoryUsage() — full scene scan, returns FMemoryStats ├── Asset-level queries — texture / material / mesh individual sizes ├── RHI query — driver-level total / used VRAM └── FormatBytes() — bytes to KB / MB / GB AMemoryHeatmap (AActor) ├── ScanLevel() — builds per-actor FActorHeatmapData array ├── ApplyHeatmapVisualization — creates UMaterialInstanceDynamic per component ├── RestoreOriginalMaterials — reinstates from TMap on disable └── Blueprint-callable API

Build Configuration

The module type is Editor with loading phase Default. The PlatformAllowList restricts compilation to Win64, Mac, and Linux — the module never compiles against game targets or any mobile platform.

C# — ShaderMemoryAtlas.Build.cs
PublicDependencyModuleNames.AddRange(new string[]
{
    "Core", "CoreUObject", "Engine",
    "RenderCore", "RHI", "Renderer", "ShaderCore"
});

PrivateDependencyModuleNames.AddRange(new string[]
{
    "UnrealEd", "Slate", "SlateCore",
    "MaterialEditor", "AssetRegistry",
    "LevelEditor", "PropertyEditor",
    "Json", "JsonUtilities"
});

Performance Characteristics

OperationTypical DurationPer-Frame Cost
Full level scan 1–5 seconds (one-time) None
Heatmap apply / remove < 100 ms ~1 ms (when active)
Widget UI refresh < 50 ms None
CSV export < 500 ms None
Plugin idle (no scan) None

All heavy work runs on the game thread during the explicit scan phase triggered by clicking Refresh. No background threads or per-frame queries are active when the heatmap is disabled.

Optimization Guide

Recommended workflow

1

Establish a baseline

Load your level, open the panel, click Refresh, and export a CSV. This is your before snapshot.

2

Identify hotspots

Enable the heatmap. Red actors are the highest-priority targets. Cross-reference with the asset lists to confirm which assets are responsible.

3

Optimize textures first

Textures are typically 60–80% of VRAM. Apply DXT1/DXT5/BC7 compression, reduce resolution on rarely-seen surfaces, and enable mip maps.

4

Simplify materials

Share base UMaterial assets with UMaterialInstance for variation. Reduce shader instruction count. Use static switches to strip unused feature branches.

5

Add LODs to meshes

Background geometry rarely needs more than 20% of the hero triangle count. Use Hierarchical Instanced Static Meshes for repeated props.

6

Measure and record

Click Refresh and compare totals to the baseline. Export a second CSV and diff the two files to document your progress.

Texture guidelines

  • Prefer DXT1 for opaque surfaces and DXT5 / BC7 for surfaces with alpha
  • Enable mip maps on all textures — the engine streams lower mips for distant geometry
  • Reducing resolution from 4K to 2K is often unnoticeable and halves texture memory
  • Enable texture streaming for large open-world levels
  • Avoid uncompressed RGBA8 except for render targets that require full precision

Material guidelines

  • Share a single base UMaterial; use UMaterialInstance for per-object parameter variation
  • Fewer shader nodes means a smaller compiled permutation cache
  • Use static switches to compile out unused feature branches
  • Avoid creating a unique base material for every prop in the level

Mesh guidelines

  • Add LOD levels — background geometry at 100 m rarely needs more than 500 triangles
  • Remove unused UV channels; each adds per-vertex data across all LODs
  • Use Hierarchical Instanced Static Meshes (HISMs) for foliage and repeated props
  • Decimate high-polygon background objects using the built-in mesh reduction tool

VRAM Budgets

Reference budgets for common target platforms. Values are recommendations, not hard limits.

Android
TierDevice VRAMTarget
Low-end512 MB – 1 GB300 MB
Mid-range1 – 2 GB800 MB
High-end2 – 4 GB1.5 GB
Windows PC
PresetDevice VRAMTarget
Minimum2 GB1.5 GB
Recommended4 – 6 GB3 GB
High / Ultra8 GB+6 GB

Troubleshooting

SymptomSolution
Lists empty after Refresh Open the Content Browser first so assets load into memory, then click Refresh.
Heatmap shows no colors Ensure actors have materials assigned (not default grey). Raise the intensity slider to 2.0 or higher.
Export button has no effect Confirm <Project>/Saved/ exists. Close the CSV file if it is open in another application.
Memory values appear unexpectedly low Values are metadata estimates. Exact GPU allocation varies by driver and streaming state — use them for relative comparison.
Plugin does not appear in the Plugins list Confirm the ShaderMemoryAtlas folder is in <Project>/Plugins/ and that the project was rebuilt after copying.

Diagnostic commands

Check Window → Developer Tools → Output Log and filter by Shader Memory Atlas for detailed per-operation logging.

stat memory          — system and GPU memory overview
stat rhi             — RHI-level GPU statistics
stat gpu             — per-pass GPU timing
stat scenerendering  — scene rendering statistics

Changelog

1.0 — Initial Release

  • VRAM tracking for textures, materials, shaders, and static meshes
  • Per-actor and per-level memory breakdown API
  • Color-coded heatmap overlay with adjustable intensity
  • Dockable Slate editor panel with four sortable asset lists
  • Double-click to Content Browser focus
  • One-click CSV export
  • Full Blueprint-callable heatmap API
  • RHI driver query for accurate total and used VRAM