/// <summary> /// Copy block of bits from source to destination. /// </summary> /// <param name="dstPos">Destination position in bit array.</param> /// <param name="srcBitArray">Source bit array from which bits will be copied.</param> /// <param name="srcPos">Source position in bit array.</param> /// <param name="numBits">Number of bits to copy.</param> public void Copy(int dstPos, ref UnsafeBitArray srcBitArray, int srcPos, int numBits) { if (numBits == 0) { return; } CheckArgsCopy(ref this, dstPos, ref srcBitArray, srcPos, numBits); if (numBits <= 64) // 1x CopyUlong { CopyUlong(dstPos, ref srcBitArray, srcPos, numBits); } else if (numBits <= 128) // 2x CopyUlong { CopyUlong(dstPos, ref srcBitArray, srcPos, 64); numBits -= 64; if (numBits > 0) { CopyUlong(dstPos + 64, ref srcBitArray, srcPos + 64, numBits); } } else if ((dstPos & 7) == (srcPos & 7)) // aligned copy { var dstPosInBytes = CollectionHelper.Align(dstPos, 8) >> 3; var srcPosInBytes = CollectionHelper.Align(srcPos, 8) >> 3; var numPreBits = dstPosInBytes * 8 - dstPos; if (numPreBits > 0) { CopyUlong(dstPos, ref srcBitArray, srcPos, numPreBits); } var numBitsLeft = numBits - numPreBits; var numBytes = numBitsLeft / 8; if (numBytes > 0) { unsafe { UnsafeUtility.MemMove((byte *)Ptr + dstPosInBytes, (byte *)srcBitArray.Ptr + srcPosInBytes, numBytes); } } var numPostBits = numBitsLeft & 7; if (numPostBits > 0) { CopyUlong((dstPosInBytes + numBytes) * 8, ref srcBitArray, (srcPosInBytes + numBytes) * 8, numPostBits); } } else // unaligned copy { var dstPosAligned = CollectionHelper.Align(dstPos, 64); var numPreBits = dstPosAligned - dstPos; if (numPreBits > 0) { CopyUlong(dstPos, ref srcBitArray, srcPos, numPreBits); numBits -= numPreBits; dstPos += numPreBits; srcPos += numPreBits; } for (; numBits >= 64; numBits -= 64, dstPos += 64, srcPos += 64) { Ptr[dstPos >> 6] = srcBitArray.GetBits(srcPos, 64); } if (numBits > 0) { CopyUlong(dstPos, ref srcBitArray, srcPos, numBits); } } }
/// <summary> /// Creates a new list with the specified initial capacity and type of memory allocation. /// </summary> /// <param name="sizeOf">Size of element.</param> /// <param name="alignOf">Alignment of element.</param> /// <param name="initialCapacity">The initial capacity of the list. If the list grows larger than its capacity, /// the internal array is copied to a new, larger array.</param> /// <param name="allocator">A member of the /// [Unity.Collections.Allocator](https://docs.unity3d.com/ScriptReference/Unity.Collections.Allocator.html) enumeration.</param> /// <param name="options">Memory should be cleared on allocation or left uninitialized.</param> public static UnsafeList *Create(int sizeOf, int alignOf, int initialCapacity, Allocator allocator, NativeArrayOptions options = NativeArrayOptions.UninitializedMemory) { UnsafeList *listData = (UnsafeList *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <UnsafeList>(), UnsafeUtility.AlignOf <UnsafeList>(), allocator); UnsafeUtility.MemClear(listData, UnsafeUtility.SizeOf <UnsafeList>()); listData->Allocator = allocator; if (initialCapacity != 0) { listData->SetCapacity(sizeOf, alignOf, initialCapacity); } if (options == NativeArrayOptions.ClearMemory && listData->Ptr != null) { UnsafeUtility.MemClear(listData->Ptr, listData->Capacity * sizeOf); } return(listData); }
/// <summary> /// Clear all bits to 0. /// </summary> public void Clear() { var sizeInBytes = Length / 8; UnsafeUtility.MemClear(Ptr, sizeInBytes); }
public static unsafe void MemCpy(void *destination, void *source, long size) => UnsafeUtility_Collections.MemCpy(destination, source, size);
/// <summary> /// Adds value to counter. /// </summary> /// <param name="value">Value to add to counter.</param> /// <returns></returns> public long Add(long value) { return Interlocked.Add(ref UnsafeUtility.AsRef<long>(Counter), value) - value; }
public static int GetFieldOffset(FieldInfo field) => UnsafeUtility_Collections.GetFieldOffset(field);
public static unsafe void Free(void *memory, Allocator allocator) => UnsafeUtility_Collections.Free(memory, allocator);
public void RemoveRangeSwapBack <T>(int begin, int end) where T : struct { RemoveRangeSwapBack(UnsafeUtility.SizeOf <T>(), begin, end); }
public void RemoveAtSwapBack <T>(int index, T t) where T : struct, IEquatable <T> { Assert.IsTrue(index >= 0 && index < m_size); Assert.IsTrue(UnsafeUtility.ReadArrayElement <T>(m_pointer, index).Equals(t)); RemoveAtSwapBack <T>(index); }
public static bool IsBlittable <T>() where T : struct { return(UnsafeUtility.IsBlittable(typeof(T))); }
public void Execute(int index) { UnityUnsafeUtility.MemCpy(destPtr + index * sourceLength, sourcePtr, sourceLength * UnityUnsafeUtility.SizeOf <T>()); }
internal static bool IsFieldOfType <T>(string fieldName, Type expectedFieldType) where T : struct { return(UnsafeUtility.IsFieldOfType(typeof(T), fieldName, expectedFieldType)); }
public static void SetFieldStruct <T>(object target, FieldInfo field, ref T value) where T : struct { UnsafeUtility.SetFieldStructInternal(target, field, UnsafeUtility.AddressOf <T>(ref value), Marshal.SizeOf(typeof(T))); }
/// <summary> /// Adds value to counter. /// </summary> /// <param name="value">Value to add to counter.</param> /// <returns></returns> public int Add(int value) { return Interlocked.Add(ref UnsafeUtility.AsRef<int>(Counter), value) - value; }
/// <summary> /// Attempts to copy the data of the current <see cref="Mesh"/> to another one, as fast as possible, /// with minimal allocations (a few tens of bytes in scenarios with very large meshes). /// </summary> public static void CopyTo(this Mesh inMesh, ref Mesh outMesh) { if (inMesh == null) { return; } if (outMesh == null) { outMesh = new Mesh(); } else { outMesh.Clear(); } outMesh.name = inMesh.name; outMesh.bounds = inMesh.bounds; using (var readArray = Mesh.AcquireReadOnlyMeshData(inMesh)) { //------------------------------------------------------------- // INPUT INFO //------------------------------------------------------------- var readData = readArray[0]; // Formats var vertexFormat = inMesh.GetVertexAttributes(); var indexFormat = inMesh.indexFormat; var isIndexShort = indexFormat == IndexFormat.UInt16; // Counts var vertexCount = readData.vertexCount; var indexCount = isIndexShort ? readData.GetIndexData <ushort>().Length : readData.GetIndexData <uint>().Length; // Element Size in bytes var indexSize = isIndexShort ? SHORT_SIZE : INT_SIZE; var vertexSize = 0; for (var i = 0; i < vertexFormat.Length; i++) { // 4 bytes per component by default var size = FLOAT_SIZE; switch (vertexFormat[i].format) { case VertexAttributeFormat.Float16: case VertexAttributeFormat.UNorm16: case VertexAttributeFormat.SNorm16: case VertexAttributeFormat.UInt16: case VertexAttributeFormat.SInt16: size = 2; break; case VertexAttributeFormat.UNorm8: case VertexAttributeFormat.SNorm8: case VertexAttributeFormat.UInt8: case VertexAttributeFormat.SInt8: size = 1; break; } vertexSize += vertexFormat[i].dimension * size; } //------------------------------------------------------------- // OUTPUT SETUP //------------------------------------------------------------- var writeArray = Mesh.AllocateWritableMeshData(1); var writeData = writeArray[0]; writeData.SetVertexBufferParams(vertexCount, vertexFormat); writeData.SetIndexBufferParams(indexCount, indexFormat); //------------------------------------------------------------- // MEMORY COPYING //------------------------------------------------------------- NativeArray <byte> inData; NativeArray <byte> outData; // Vertices inData = readData.GetVertexData <byte>(); outData = writeData.GetVertexData <byte>(); #if USE_UNSAFE unsafe { UnityUnsafeUtility.MemCpy(outData.GetUnsafePtr(), inData.GetUnsafeReadOnlyPtr(), vertexCount * vertexSize); } #else inData.CopyTo(outData); #endif // Indices inData = readData.GetIndexData <byte>(); outData = writeData.GetIndexData <byte>(); #if USE_UNSAFE unsafe { UnityUnsafeUtility.MemCpy(outData.GetUnsafePtr(), inData.GetUnsafeReadOnlyPtr(), indexCount * indexSize); } #else inData.CopyTo(outData); #endif //------------------------------------------------------------- // FINALIZATION //------------------------------------------------------------- writeData.subMeshCount = inMesh.subMeshCount; // Set all sub-meshes for (var i = 0; i < inMesh.subMeshCount; i++) { writeData.SetSubMesh(i, new SubMeshDescriptor((int)inMesh.GetIndexStart(i), (int)inMesh.GetIndexCount(i))); } Mesh.ApplyAndDisposeWritableMeshData(writeArray, outMesh); } }
public void Append <T>(UnsafeList src) where T : struct { Append(UnsafeUtility.SizeOf <T>(), src); }
public static unsafe void *AddressOf <T>(ref T output) where T : struct => UnsafeUtility_Collections.AddressOf(ref output);
public ref UnsafeList GetUnsafeList() { return(ref *(UnsafeList *)UnsafeUtility.AddressOf(ref this)); }
public static unsafe void MemClear(void *destination, long size) => UnsafeUtility_Collections.MemClear(destination, size);
public void SetCapacity <T>(int targetCapacity, Allocator allocator = Allocator.Persistent) where T : struct { SetCapacity(UnsafeUtility.SizeOf <T>(), UnsafeUtility.AlignOf <T>(), targetCapacity, allocator); }
public static unsafe void *Malloc(long size, int alignment, Allocator allocator) => UnsafeUtility_Collections.Malloc(size, alignment, allocator);
public void Add <T>(T t, Allocator allocator = Allocator.Persistent) where T : struct { Resize <T>(m_size + 1, allocator); UnsafeUtility.WriteArrayElement(m_pointer, m_size - 1, t); }
public static int SizeOf <T>() where T : struct => UnsafeUtility_Collections.SizeOf <T>();
public void *Allocate <T>(int count = 1) where T : struct { return(Allocate(UnsafeUtility.SizeOf <T>() * count, UnsafeUtility.AlignOf <T>())); }