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.
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.
Features
Scans all loaded textures, materials, shaders, and static meshes. Queries the RHI driver for accurate total and used GPU memory figures.
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.
Four sortable asset lists with a live VRAM dashboard. Double-click any row to focus the asset directly in the Content Browser.
One-click export to Saved/MemoryAtlasReport.csv. Open in any spreadsheet
application for detailed before/after comparison.
All heatmap functions are BlueprintCallable. Use in Editor Utility
Widgets, custom tools, or Play-in-Editor sessions.
Query memory cost per actor or per level programmatically. Integrate into custom pipeline tools and automated budgeting checks.
Specifications
| Plugin Type | Editor (excluded from game targets) |
| Engine Compatibility | Unreal Engine 4.27 – 5.x+ |
| Editor Platforms | Windows (Win64), macOS, Linux |
| Loading Phase | Default |
| Runtime Cost | None — compiles out of packaged builds |
| Blueprint Exposure | Full (heatmap actor API) |
| C++ Standard | C++17 (Unreal Engine default) |
Memory Calculation Methods
| Asset Type | Formula |
|---|---|
| UTexture2D | Width × Height × BytesPerPixel(Format) × MipCount |
| UMaterial | 10,240 bytes base + (InstructionCount × 100 bytes) |
| UMaterialInstance | Parent material cost + parameter overhead |
| UStaticMesh | Vertex buffers + index buffers across all LODs |
| RHI Total / Used | FTextureMemoryStats 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
Copy the plugin folder
Place the ShaderMemoryAtlas folder inside <YourProject>/Plugins/. Create the Plugins directory if it does not yet exist.
Regenerate project files
Right-click <YourProject>.uproject and select Generate Visual Studio project files.
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.
Enable in the Unreal Editor
Open Edit → Plugins, search for Shader Memory Atlas, check Enabled, and click Restart Now.
<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:
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
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
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
TArray<FVRAMTracker::FMemoryEntry> Entries =
FVRAMTracker::GetActorMemoryUsage(MyActor);
TArray<FVRAMTracker::FMemoryEntry> LevelEntries =
FVRAMTracker::GetLevelMemoryUsage(MyLevel);
RHI driver query and formatting
int64 Total, Used;
FVRAMTracker::GetRHIMemoryStats(Total, Used);
FString Human = FVRAMTracker::FormatBytes(Bytes); // e.g. "512.00 MB"
Data structures
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.
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
| Function | Type | Description |
|---|---|---|
SetHeatmapEnabled(bool) | BlueprintCallable | Applies or removes the heatmap overlay |
RefreshHeatmap() | BlueprintCallable | Re-scans the level and reapplies all colors |
SetIntensity(float) | BlueprintCallable | Sets the emissive brightness multiplier (0.1–10.0) |
GetHeatmapColor(int64, int64) | BlueprintPure | Returns 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
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
| Control | Behavior |
|---|---|
| Refresh | Calls FVRAMTracker::ScanMemoryUsage() and repopulates all four lists |
| Export CSV | Serializes FMemoryStats to <Project>/Saved/MemoryAtlasReport.csv |
| Enable / Disable Heatmap | Spawns or toggles AMemoryHeatmap in the editor world |
| Intensity slider | Calls AMemoryHeatmap::SetIntensity() on every value change |
| Double-click asset row | Calls GEditor->SyncBrowserToObjects() with the selected asset |
System Design
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.
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
| Operation | Typical Duration | Per-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
Establish a baseline
Load your level, open the panel, click Refresh, and export a CSV. This is your before snapshot.
Identify hotspots
Enable the heatmap. Red actors are the highest-priority targets. Cross-reference with the asset lists to confirm which assets are responsible.
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.
Simplify materials
Share base UMaterial assets with UMaterialInstance for variation. Reduce shader instruction count. Use static switches to strip unused feature branches.
Add LODs to meshes
Background geometry rarely needs more than 20% of the hero triangle count. Use Hierarchical Instanced Static Meshes for repeated props.
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.
| Tier | Device VRAM | Target |
|---|---|---|
| Low-end | 512 MB – 1 GB | 300 MB |
| Mid-range | 1 – 2 GB | 800 MB |
| High-end | 2 – 4 GB | 1.5 GB |
| Preset | Device VRAM | Target |
|---|---|---|
| Minimum | 2 GB | 1.5 GB |
| Recommended | 4 – 6 GB | 3 GB |
| High / Ultra | 8 GB+ | 6 GB |
Troubleshooting
| Symptom | Solution |
|---|---|
| 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
