コード例 #1
0
 public void TestAlignUlong_ZeroAlignment()
 {
     for (ulong value = 0; value < 512ul; ++value)
     {
         Assert.AreEqual(value, CollectionHelper.Align(value, 0ul));
     }
 }
コード例 #2
0
        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;
        }
コード例 #3
0
 public void TestAlignUp_ZeroAlignment()
 {
     for (int value = 0; value < 512; ++value)
     {
         Assert.AreEqual(value, CollectionHelper.Align(value, 0));
     }
 }
コード例 #4
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));
 }
コード例 #5
0
 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));
 }
コード例 #6
0
 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));
 }
コード例 #7
0
 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));
 }
コード例 #8
0
 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));
 }
コード例 #9
0
 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));
 }
コード例 #10
0
 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));
 }
コード例 #11
0
        /// <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);
        }
コード例 #12
0
        /// <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);
        }
コード例 #13
0
        /// <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);
                }
            }
        }