No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ShaderBitArray.cs 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. using System;
  2. namespace UnityEngine.Rendering.Universal
  3. {
  4. // A dynamic array of bits backed by a managed array of floats,
  5. // since that's what Unity Shader constant API offers.
  6. //
  7. // Example:
  8. // ShaderBitArray bits;
  9. // bits.Resize(8);
  10. // bits[0] = true;
  11. // cmd.SetGlobalFloatArray("_BitArray", bits.data);
  12. // bits.Clear();
  13. internal struct ShaderBitArray
  14. {
  15. const int k_BitsPerElement = 32;
  16. const int k_ElementShift = 5;
  17. const int k_ElementMask = (1 << k_ElementShift) - 1;
  18. private float[] m_Data;
  19. public int elemLength => m_Data == null ? 0 : m_Data.Length;
  20. public int bitCapacity => elemLength * k_BitsPerElement;
  21. public float[] data => m_Data;
  22. public void Resize(int bitCount)
  23. {
  24. if (bitCapacity > bitCount)
  25. return;
  26. int newElemCount = ((bitCount + (k_BitsPerElement - 1)) / k_BitsPerElement);
  27. if (newElemCount == m_Data?.Length)
  28. return;
  29. var newData = new float[newElemCount];
  30. if (m_Data != null)
  31. {
  32. for (int i = 0; i < m_Data.Length; i++)
  33. newData[i] = m_Data[i];
  34. }
  35. m_Data = newData;
  36. }
  37. public void Clear()
  38. {
  39. for (int i = 0; i < m_Data.Length; i++)
  40. m_Data[i] = 0;
  41. }
  42. private void GetElementIndexAndBitOffset(int index, out int elemIndex, out int bitOffset)
  43. {
  44. elemIndex = index >> k_ElementShift;
  45. bitOffset = index & k_ElementMask;
  46. }
  47. public bool this[int index]
  48. {
  49. get
  50. {
  51. GetElementIndexAndBitOffset(index, out var elemIndex, out var bitOffset);
  52. unsafe
  53. {
  54. fixed (float* floatData = m_Data)
  55. {
  56. uint* uintElem = (uint*)&floatData[elemIndex];
  57. bool val = ((*uintElem) & (1u << bitOffset)) != 0u;
  58. return val;
  59. }
  60. }
  61. }
  62. set
  63. {
  64. GetElementIndexAndBitOffset(index, out var elemIndex, out var bitOffset);
  65. unsafe
  66. {
  67. fixed (float* floatData = m_Data)
  68. {
  69. uint* uintElem = (uint*)&floatData[elemIndex];
  70. if (value == true)
  71. *uintElem = (*uintElem) | (1u << bitOffset);
  72. else
  73. *uintElem = (*uintElem) & ~(1u << bitOffset);
  74. }
  75. }
  76. }
  77. }
  78. public override string ToString()
  79. {
  80. unsafe
  81. {
  82. Debug.Assert(bitCapacity < 4096, "Bit string too long! It was truncated!");
  83. int len = Math.Min(bitCapacity, 4096);
  84. byte* buf = stackalloc byte[len];
  85. for (int i = 0; i < len; i++)
  86. {
  87. buf[i] = (byte)(this[i] ? '1' : '0');
  88. }
  89. return new string((sbyte*)buf, 0, len, System.Text.Encoding.UTF8);
  90. }
  91. }
  92. }
  93. }