Skip to content

Instantly share code, notes, and snippets.

@d4rkc0d3r
Last active February 17, 2025 21:31
Show Gist options
  • Select an option

  • Save d4rkc0d3r/b975d64a37c64a73be221749614fd5fc to your computer and use it in GitHub Desktop.

Select an option

Save d4rkc0d3r/b975d64a37c64a73be221749614fd5fc to your computer and use it in GitHub Desktop.
#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEditor;
using System.Linq;
public class MeshVRAMSize : EditorWindow
{
Object selected;
private int ByteSize(VertexAttributeFormat format)
{
switch(format)
{
case VertexAttributeFormat.UNorm8:
case VertexAttributeFormat.SNorm8:
case VertexAttributeFormat.UInt8:
case VertexAttributeFormat.SInt8:
return 1;
case VertexAttributeFormat.Float16:
case VertexAttributeFormat.UNorm16:
case VertexAttributeFormat.SNorm16:
case VertexAttributeFormat.UInt16:
case VertexAttributeFormat.SInt16:
return 2;
case VertexAttributeFormat.Float32:
case VertexAttributeFormat.UInt32:
case VertexAttributeFormat.SInt32:
default:
return 4;
}
}
private (int vertexAttributes, int blendShapes) CalculateMeshVRAMSize(Mesh mesh)
{
var vertexAttributes = mesh.GetVertexAttributes();
int vertexAttributeVRAMSize = 0;
foreach (var vertexAttribute in vertexAttributes)
{
int skinnedMeshPositionNormalTangentMultiplier = 1;
// skinned meshes have 2x the amount of position, normal and tangent data since they store both the un-skinned and skinned data
// we check for the blend indices and blend weights attributes since they are required for skinned meshes
if (mesh.HasVertexAttribute(VertexAttribute.BlendIndices) && mesh.HasVertexAttribute(VertexAttribute.BlendWeight) &&
(vertexAttribute.attribute == VertexAttribute.Position || vertexAttribute.attribute == VertexAttribute.Normal || vertexAttribute.attribute == VertexAttribute.Tangent))
skinnedMeshPositionNormalTangentMultiplier = 2;
vertexAttributeVRAMSize += ByteSize(vertexAttribute.format) * vertexAttribute.dimension * skinnedMeshPositionNormalTangentMultiplier;
}
var deltaPositions = new Vector3[mesh.vertexCount];
var deltaNormals = new Vector3[mesh.vertexCount];
var deltaTangents = new Vector3[mesh.vertexCount];
int blendShapeVRAMSize = 0;
for (int i = 0; i < mesh.blendShapeCount; i++)
{
var blendShapeName = mesh.GetBlendShapeName(i);
var blendShapeFrameCount = mesh.GetBlendShapeFrameCount(i);
for (int j = 0; j < blendShapeFrameCount; j++)
{
mesh.GetBlendShapeFrameVertices(i, j, deltaPositions, deltaNormals, deltaTangents);
for (int k = 0; k < deltaPositions.Length; k++)
{
if (deltaPositions[k] != Vector3.zero || deltaNormals[k] != Vector3.zero || deltaTangents[k] != Vector3.zero)
{
// every affected vertex has 1 uint for the index, 3 floats for the position, 3 floats for the normal and 3 floats for the tangent
// this is true even if all normals or tangents in all blend shapes are zero
blendShapeVRAMSize += 40;
}
}
}
}
return (vertexAttributeVRAMSize * mesh.vertexCount, blendShapeVRAMSize);
}
int blendShapeVRAMSize = -1;
int vertexAttributeVRAMSize = -1;
void OnGUI()
{
EditorGUI.BeginChangeCheck();
selected = EditorGUILayout.ObjectField(selected, typeof(Object), true);
if (EditorGUI.EndChangeCheck())
{
blendShapeVRAMSize = -1;
vertexAttributeVRAMSize = -1;
}
var mesh = selected as Mesh;
if (mesh == null)
{
var skinnedMeshRenderer = selected as SkinnedMeshRenderer;
if (skinnedMeshRenderer != null)
mesh = skinnedMeshRenderer.sharedMesh;
var gameObject = selected as GameObject;
if (gameObject != null && gameObject.GetComponent<SkinnedMeshRenderer>() != null)
mesh = gameObject.GetComponent<SkinnedMeshRenderer>().sharedMesh;
if (gameObject != null && gameObject.GetComponent<MeshFilter>() != null)
mesh = gameObject.GetComponent<MeshFilter>().sharedMesh;
}
if (mesh == null)
{
selected = null;
return;
}
if (blendShapeVRAMSize == -1 || vertexAttributeVRAMSize == -1)
{
var vramSize = CalculateMeshVRAMSize(mesh);
vertexAttributeVRAMSize = vramSize.vertexAttributes;
blendShapeVRAMSize = vramSize.blendShapes;
}
EditorGUILayout.LabelField($"Vertex Count: {mesh.vertexCount}");
EditorGUILayout.LabelField($"Blend Shape Count: {mesh.blendShapeCount}");
EditorGUILayout.LabelField($"Vertex Attribute VRAM Size: {vertexAttributeVRAMSize / 1024f / 1024f:f2} MiB");
EditorGUILayout.LabelField($"Blend Shape VRAM Size: {blendShapeVRAMSize / 1024f / 1024f:f2} MiB");
EditorGUILayout.LabelField($"Total VRAM Size: {(vertexAttributeVRAMSize + blendShapeVRAMSize) / 1024f / 1024f:f2} MiB");
}
[MenuItem("Tools/d4rkpl4y3r/Mesh VRAM Size")]
public static void OpenWindow()
{
var window = GetWindow(typeof(MeshVRAMSize)) as MeshVRAMSize;
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment