Skip to content

Instantly share code, notes, and snippets.

@ruccho
Created October 14, 2025 04:48
Show Gist options
  • Save ruccho/bc630d1d3b0792d6c1c1858c1dc2068e to your computer and use it in GitHub Desktop.
Save ruccho/bc630d1d3b0792d6c1c1858c1dc2068e to your computer and use it in GitHub Desktop.
BatchRendererGroup data layouting helper
using System;
using System.Runtime.CompilerServices;
using Unity.Collections;
using UnityEngine;
using UnityEngine.Rendering;
public struct InstanceDataLayouter
{
private int _offset;
private int _metadataIndex;
public int NumMetadata => _metadataIndex;
public InstanceDataInfo<T> Alloc<T>(int nameId, int count, ref NativeArray<T>? array) where T : unmanaged
{
var stride = Unsafe.SizeOf<T>();
_offset = AlignTo(_offset, stride);
if (array is not { } arrayValue || arrayValue.Length != count)
{
array?.Dispose();
array = new NativeArray<T>(count, Allocator.Persistent);
}
var result =
new InstanceDataInfo<T>(nameId, _offset / stride, _offset, _metadataIndex++, array.Value, false);
_offset += count * stride;
return result;
}
public InstanceDataInfo<T> AllocStatic<T>(int nameId, ref NativeArray<T>? array) where T : unmanaged
{
var stride = Unsafe.SizeOf<T>();
_offset = AlignTo(_offset, stride);
if (array is not { } arrayValue || arrayValue.Length != 1)
{
array?.Dispose();
array = new NativeArray<T>(1, Allocator.Persistent);
}
var result =
new InstanceDataInfo<T>(nameId, _offset / stride, _offset, _metadataIndex++, array.Value, true);
_offset += stride;
return result;
}
public void AllocZero<T>(int count) where T : unmanaged
{
var stride = Unsafe.SizeOf<T>();
_offset = AlignTo(_offset, stride);
_offset += count * stride;
}
static int AlignTo(int offset, int stride) => (offset + stride - 1) / stride * stride;
public int GetSize(int alignment)
{
return AlignTo(_offset, alignment);
}
}
public struct InstanceDataInfo<T> where T : unmanaged
{
private readonly int? _nameId;
private readonly int _graphicsBufferStartIndex;
private readonly int _offset;
private readonly int _metadataIndex;
private readonly bool _isStatic;
public NativeArray<T> Array;
public InstanceDataInfo(int? nameId, int graphicsBufferStartIndex, int offset, int metadataIndex,
NativeArray<T> array, bool isStatic)
{
_nameId = nameId;
_graphicsBufferStartIndex = graphicsBufferStartIndex;
_offset = offset;
_metadataIndex = metadataIndex;
_isStatic = isStatic;
Array = array;
}
public void ApplyMetadata(Span<MetadataValue> metadata)
{
if (_nameId is { } nameId)
{
metadata[_metadataIndex] = new MetadataValue()
{
NameID = nameId,
Value = (uint)_offset | (_isStatic ? 0 : 0x80000000)
};
}
}
public void ApplyValue(GraphicsBuffer buffer)
{
buffer.SetData(Array, 0, _graphicsBufferStartIndex, Array.Length);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment