public void TestAlignUlong_ZeroAlignment() { for (ulong value = 0; value < 512ul; ++value) { Assert.AreEqual(value, CollectionHelper.Align(value, 0ul)); } }
public unsafe static void AllocateQueue <T>(Allocator label, out NativeQueueData *outBuf) where T : struct { var queueDataSize = CollectionHelper.Align(UnsafeUtility.SizeOf <NativeQueueData>(), JobsUtility.CacheLineSize); var data = (NativeQueueData *)Memory.Unmanaged.Allocate( queueDataSize + JobsUtility.CacheLineSize * JobsUtility.MaxJobThreadCount , JobsUtility.CacheLineSize , label ); data->m_CurrentWriteBlockTLS = (((byte *)data) + queueDataSize); data->m_FirstBlock = IntPtr.Zero; data->m_LastBlock = IntPtr.Zero; data->m_MaxItems = (NativeQueueBlockPoolData.m_BlockSize - UnsafeUtility.SizeOf <NativeQueueBlockHeader>()) / UnsafeUtility.SizeOf <T>(); data->m_CurrentRead = 0; for (int threadIndex = 0; threadIndex < JobsUtility.MaxJobThreadCount; ++threadIndex) { data->SetCurrentWriteBlockTLS(threadIndex, null); } outBuf = data; }
public void TestAlignUp_ZeroAlignment() { for (int value = 0; value < 512; ++value) { Assert.AreEqual(value, CollectionHelper.Align(value, 0)); } }
public void TestAlignUp_Align63ToPow2() { Assert.AreEqual(63, CollectionHelper.Align(63, 1)); Assert.AreEqual(64, CollectionHelper.Align(63, 2)); Assert.AreEqual(64, CollectionHelper.Align(63, 4)); Assert.AreEqual(64, CollectionHelper.Align(63, 8)); Assert.AreEqual(64, CollectionHelper.Align(63, 16)); Assert.AreEqual(64, CollectionHelper.Align(63, 32)); Assert.AreEqual(64, CollectionHelper.Align(63, 64)); Assert.AreEqual(128, CollectionHelper.Align(63, 128)); }
public void TestAlignUp_Align15ToPow2() { Assert.AreEqual(15, CollectionHelper.Align(15, 1)); Assert.AreEqual(16, CollectionHelper.Align(15, 2)); Assert.AreEqual(16, CollectionHelper.Align(15, 4)); Assert.AreEqual(16, CollectionHelper.Align(15, 8)); Assert.AreEqual(16, CollectionHelper.Align(15, 16)); Assert.AreEqual(32, CollectionHelper.Align(15, 32)); Assert.AreEqual(64, CollectionHelper.Align(15, 64)); Assert.AreEqual(128, CollectionHelper.Align(15, 128)); }
public void TestAlignUp_Align1ToPow2() { Assert.AreEqual(1, CollectionHelper.Align(1, 1)); Assert.AreEqual(2, CollectionHelper.Align(1, 2)); Assert.AreEqual(4, CollectionHelper.Align(1, 4)); Assert.AreEqual(8, CollectionHelper.Align(1, 8)); Assert.AreEqual(16, CollectionHelper.Align(1, 16)); Assert.AreEqual(32, CollectionHelper.Align(1, 32)); Assert.AreEqual(64, CollectionHelper.Align(1, 64)); Assert.AreEqual(128, CollectionHelper.Align(1, 128)); }
public void TestAlignUp_AlignMultipleOfAlignment() { Assert.AreEqual(2, CollectionHelper.Align(2, 1)); Assert.AreEqual(4, CollectionHelper.Align(4, 2)); Assert.AreEqual(8, CollectionHelper.Align(8, 4)); Assert.AreEqual(16, CollectionHelper.Align(16, 8)); Assert.AreEqual(32, CollectionHelper.Align(32, 16)); Assert.AreEqual(64, CollectionHelper.Align(64, 32)); Assert.AreEqual(128, CollectionHelper.Align(128, 64)); Assert.AreEqual(256, CollectionHelper.Align(256, 128)); }
public void TestAlignUp_Align0ToPow2() { Assert.AreEqual(0, CollectionHelper.Align(0, 1)); Assert.AreEqual(0, CollectionHelper.Align(0, 2)); Assert.AreEqual(0, CollectionHelper.Align(0, 4)); Assert.AreEqual(0, CollectionHelper.Align(0, 8)); Assert.AreEqual(0, CollectionHelper.Align(0, 16)); Assert.AreEqual(0, CollectionHelper.Align(0, 32)); Assert.AreEqual(0, CollectionHelper.Align(0, 64)); Assert.AreEqual(0, CollectionHelper.Align(0, 128)); }
public void TestAlignUlong_Align63ToPow2() { Assert.AreEqual(63ul, CollectionHelper.Align(63ul, 1ul)); Assert.AreEqual(64ul, CollectionHelper.Align(63ul, 2ul)); Assert.AreEqual(64ul, CollectionHelper.Align(63ul, 4ul)); Assert.AreEqual(64ul, CollectionHelper.Align(63ul, 8ul)); Assert.AreEqual(64ul, CollectionHelper.Align(63ul, 16ul)); Assert.AreEqual(64ul, CollectionHelper.Align(63ul, 32ul)); Assert.AreEqual(64ul, CollectionHelper.Align(63ul, 64ul)); Assert.AreEqual(128ul, CollectionHelper.Align(63ul, 128ul)); }
public void TestAlignUlong_AlignMultipleOfAlignment() { Assert.AreEqual(2ul, CollectionHelper.Align(2ul, 1ul)); Assert.AreEqual(4ul, CollectionHelper.Align(4ul, 2ul)); Assert.AreEqual(8ul, CollectionHelper.Align(8ul, 4ul)); Assert.AreEqual(16ul, CollectionHelper.Align(16ul, 8ul)); Assert.AreEqual(32ul, CollectionHelper.Align(32ul, 16ul)); Assert.AreEqual(64ul, CollectionHelper.Align(64ul, 32ul)); Assert.AreEqual(128ul, CollectionHelper.Align(128ul, 64ul)); Assert.AreEqual(256ul, CollectionHelper.Align(256ul, 128ul)); }
/// <summary> /// Allocates memory out of a block. /// </summary> /// <remarks> /// Not all allocation sizes and alignment combinations are valid. The maximum value bytesToAllocate can be is /// (ms_BlockSize - (alignment - 1)). /// </remarks> /// <param name="bytesToAllocate">Bytes to allocate.</param> /// <param name="alignment">Alignment in bytes for the allocation.</param> /// <returns>Pointer to allocation.</returns> public byte *Allocate(int bytesToAllocate, int alignment) { CheckAllocationTooLarge(bytesToAllocate, alignment); var nextAligned = CollectionHelper.Align(m_nextPtr, (ulong)alignment); var nextAllocationEnd = nextAligned + (ulong)bytesToAllocate; // If we haven't allocated a block or the next allocation end is past the end of the current block, then allocate a new block. if (m_currentBlockIndex < 0 || nextAllocationEnd > (ulong)m_bufferAllocator[m_currentBlockIndex] + ms_BlockSize) { CheckExceededBudget(); // Allocate a fresh block of memory int index = m_bufferAllocator.Allocate(); m_allocations.Ptr[index] = 0; m_currentBlockIndex = index; nextAligned = CollectionHelper.Align((ulong)m_bufferAllocator[m_currentBlockIndex], (ulong)alignment); nextAllocationEnd = nextAligned + (ulong)bytesToAllocate; } var pointer = (byte *)nextAligned; m_nextPtr = nextAllocationEnd; m_allocations.Ptr[m_currentBlockIndex]++; return(pointer); }
/// <summary> /// Completes construction of the blob asset and returns a reference to the asset in unmanaged memory. /// </summary> /// <remarks>Use the <see cref="BlobAssetReference{T}"/> to access the blob asset. When the asset is no longer /// needed, call<see cref="BlobAssetReference{T}.Dispose()"/> to destroy the blob asset and free its allocated /// memory.</remarks> /// <param name="allocator">The type of memory to allocate. Unless the asset has a very short life span, use /// <see cref="Allocator.Persistent"/>.</param> /// <typeparam name="T">The data type of the struct used to construct the asset's root. Use the same struct type /// that you used when calling <see cref="ConstructRoot{T}"/>.</typeparam> /// <returns></returns> public BlobAssetReference <T> CreateBlobAssetReference <T>(Allocator allocator) where T : struct { var offsets = new NativeArray <int>(m_allocations.Length + 1, Allocator.Temp); var sortedAllocs = new NativeArray <SortedIndex>(m_allocations.Length, Allocator.Temp); offsets[0] = 0; for (int i = 0; i < m_allocations.Length; ++i) { offsets[i + 1] = offsets[i] + m_allocations[i].size; sortedAllocs[i] = new SortedIndex { p = m_allocations[i].p, index = i }; } int dataSize = offsets[m_allocations.Length]; sortedAllocs.Sort(); var sortedPatches = new NativeArray <SortedIndex>(m_patches.Length, Allocator.Temp); for (int i = 0; i < m_patches.Length; ++i) { sortedPatches[i] = new SortedIndex { p = (byte *)m_patches[i].offsetPtr, index = i } } ; sortedPatches.Sort(); byte *buffer = (byte *)Memory.Unmanaged.Allocate(sizeof(BlobAssetHeader) + dataSize, 16, allocator); byte *data = buffer + sizeof(BlobAssetHeader); for (int i = 0; i < m_allocations.Length; ++i) { UnsafeUtility.MemCpy(data + offsets[i], m_allocations[i].p, m_allocations[i].size); } int iAlloc = 0; var allocStart = m_allocations[sortedAllocs[0].index].p; var allocEnd = allocStart + m_allocations[sortedAllocs[0].index].size; for (int i = 0; i < m_patches.Length; ++i) { int patchIndex = sortedPatches[i].index; int *offsetPtr = (int *)sortedPatches[i].p; while (offsetPtr > allocEnd) { ++iAlloc; allocStart = m_allocations[sortedAllocs[iAlloc].index].p; allocEnd = allocStart + m_allocations[sortedAllocs[iAlloc].index].size; } var patch = m_patches[patchIndex]; int offsetPtrInData = offsets[sortedAllocs[iAlloc].index] + (int)((byte *)offsetPtr - allocStart); int targetPtrInData = offsets[patch.target.allocIndex] + patch.target.offset; *(int *)(data + offsetPtrInData) = targetPtrInData - offsetPtrInData; if (patch.length != 0) { *(int *)(data + offsetPtrInData + 4) = patch.length; } } sortedPatches.Dispose(); sortedAllocs.Dispose(); offsets.Dispose(); BlobAssetHeader *header = (BlobAssetHeader *)buffer; *header = new BlobAssetHeader(); header->Length = (int)dataSize; header->Allocator = allocator; // @TODO use 64bit hash header->Hash = math.hash(buffer + sizeof(BlobAssetHeader), dataSize); BlobAssetReference <T> blobAssetReference; blobAssetReference.m_data.m_Align8Union = 0; header->ValidationPtr = blobAssetReference.m_data.m_Ptr = buffer + sizeof(BlobAssetHeader); return(blobAssetReference); } void *AllocationToPointer(BlobDataRef blobDataRef) { return(m_allocations[blobDataRef.allocIndex].p + blobDataRef.offset); } BlobAllocation EnsureEnoughRoomInChunk(int size, int alignment) { if (m_currentChunkIndex == -1) { return(AllocateNewChunk()); } var alloc = m_allocations[m_currentChunkIndex]; int startOffset = CollectionHelper.Align(alloc.size, alignment); if (startOffset + size > m_chunkSize) { return(AllocateNewChunk()); } UnsafeUtility.MemClear(alloc.p + alloc.size, startOffset - alloc.size); alloc.size = startOffset; return(alloc); } BlobDataRef Allocate(int size, int alignment) { if (size > m_chunkSize) { size = CollectionHelper.Align(size, 16); var allocIndex = m_allocations.Length; var mem = (byte *)Memory.Unmanaged.Allocate(size, alignment, m_allocator); UnsafeUtility.MemClear(mem, size); m_allocations.Add(new BlobAllocation { p = mem, size = size }); return(new BlobDataRef { allocIndex = allocIndex, offset = 0 }); } BlobAllocation alloc = EnsureEnoughRoomInChunk(size, alignment); var offset = alloc.size; UnsafeUtility.MemClear(alloc.p + alloc.size, size); alloc.size += size; m_allocations[m_currentChunkIndex] = alloc; return(new BlobDataRef { allocIndex = m_currentChunkIndex, offset = offset }); } BlobAllocation AllocateNewChunk() { // align size of last chunk to 16 bytes so chunks can be concatenated without breaking alignment if (m_currentChunkIndex != -1) { var currentAlloc = m_allocations[m_currentChunkIndex]; currentAlloc.size = CollectionHelper.Align(currentAlloc.size, 16); m_allocations[m_currentChunkIndex] = currentAlloc; } m_currentChunkIndex = m_allocations.Length; var alloc = new BlobAllocation { p = (byte *)Memory.Unmanaged.Allocate(m_chunkSize, 16, m_allocator), size = 0 }; m_allocations.Add(alloc); return(alloc); }
/// <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); } } }