UnityGame/Library/PackageCache/com.unity.render-pipelines.universal/Runtime/ShaderBitArray.cs

106 lines
3.2 KiB
C#
Raw Normal View History

2024-10-27 10:53:47 +03:00
using System;
namespace UnityEngine.Rendering.Universal
{
// A dynamic array of bits backed by a managed array of floats,
// since that's what Unity Shader constant API offers.
//
// Example:
// ShaderBitArray bits;
// bits.Resize(8);
// bits[0] = true;
// cmd.SetGlobalFloatArray("_BitArray", bits.data);
// bits.Clear();
internal struct ShaderBitArray
{
const int k_BitsPerElement = 32;
const int k_ElementShift = 5;
const int k_ElementMask = (1 << k_ElementShift) - 1;
private float[] m_Data;
public int elemLength => m_Data == null ? 0 : m_Data.Length;
public int bitCapacity => elemLength * k_BitsPerElement;
public float[] data => m_Data;
public void Resize(int bitCount)
{
if (bitCapacity > bitCount)
return;
int newElemCount = ((bitCount + (k_BitsPerElement - 1)) / k_BitsPerElement);
if (newElemCount == m_Data?.Length)
return;
var newData = new float[newElemCount];
if (m_Data != null)
{
for (int i = 0; i < m_Data.Length; i++)
newData[i] = m_Data[i];
}
m_Data = newData;
}
public void Clear()
{
for (int i = 0; i < m_Data.Length; i++)
m_Data[i] = 0;
}
private void GetElementIndexAndBitOffset(int index, out int elemIndex, out int bitOffset)
{
elemIndex = index >> k_ElementShift;
bitOffset = index & k_ElementMask;
}
public bool this[int index]
{
get
{
GetElementIndexAndBitOffset(index, out var elemIndex, out var bitOffset);
unsafe
{
fixed (float* floatData = m_Data)
{
uint* uintElem = (uint*)&floatData[elemIndex];
bool val = ((*uintElem) & (1u << bitOffset)) != 0u;
return val;
}
}
}
set
{
GetElementIndexAndBitOffset(index, out var elemIndex, out var bitOffset);
unsafe
{
fixed (float* floatData = m_Data)
{
uint* uintElem = (uint*)&floatData[elemIndex];
if (value == true)
*uintElem = (*uintElem) | (1u << bitOffset);
else
*uintElem = (*uintElem) & ~(1u << bitOffset);
}
}
}
}
public override string ToString()
{
unsafe
{
Debug.Assert(bitCapacity < 4096, "Bit string too long! It was truncated!");
int len = Math.Min(bitCapacity, 4096);
byte* buf = stackalloc byte[len];
for (int i = 0; i < len; i++)
{
buf[i] = (byte)(this[i] ? '1' : '0');
}
return new string((sbyte*)buf, 0, len, System.Text.Encoding.UTF8);
}
}
}
}