/// <summary>Given free suballocation, it removes it from sorted list of <see cref="m_FreeSuballocationsBySize"/> if it's suitable.</summary>
        public void UnregisterFreeSuballocation(D3D12MA_List <D3D12MA_Suballocation> .iterator item)
        {
            D3D12MA_ASSERT((D3D12MA_DEBUG_LEVEL > 0) && (item.Get()->type == D3D12MA_SUBALLOCATION_TYPE_FREE));
            D3D12MA_ASSERT((D3D12MA_DEBUG_LEVEL > 0) && (item.Get()->size > 0));

            // You may want to enable this validation at the beginning or at the end of
            // this function, depending on what do you want to check.
            D3D12MA_HEAVY_ASSERT((D3D12MA_DEBUG_LEVEL > 1) && ValidateFreeSuballocationList());

            if (item.Get()->size >= MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
            {
                D3D12MA_List <D3D12MA_Suballocation> .iterator *it = BinaryFindFirstNotLess(
                    m_FreeSuballocationsBySize.data(),
                    m_FreeSuballocationsBySize.data() + m_FreeSuballocationsBySize.size(),
                    in item,
                    new D3D12MA_SuballocationItemSizeLess()
                    );

                for (nuint index = (nuint)(it - m_FreeSuballocationsBySize.data()); index < m_FreeSuballocationsBySize.size(); ++index)
                {
                    if (*m_FreeSuballocationsBySize[index] == item)
                    {
                        m_FreeSuballocationsBySize.remove(index);
                        return;
                    }

                    D3D12MA_ASSERT((D3D12MA_DEBUG_LEVEL > 0) && (m_FreeSuballocationsBySize[index]->Get()->size == item.Get()->size)); // "Not found!"
                }

                D3D12MA_ASSERT(false); // "Not found!"
            }

            // D3D12MA_HEAVY_ASSERT((D3D12MA_DEBUG_LEVEL > 1) && ValidateFreeSuballocationList());
        }
Beispiel #2
0
        // allocationCallbacks externally owned, must outlive this object.
        public static void _ctor(ref D3D12MA_List <T> pThis, [NativeTypeName("const D3D12MA_ALLOCATION_CALLBACKS&")] D3D12MA_ALLOCATION_CALLBACKS *allocationCallbacks)
        {
            pThis.m_AllocationCallbacks = allocationCallbacks;
            D3D12MA_PoolAllocator <Item> ._ctor(ref pThis.m_ItemAllocator, allocationCallbacks, 128);

            pThis.m_pFront = null;
            pThis.m_pBack  = null;
            pThis.m_Count  = 0;
        }
        /// <summary>Releases given suballocation, making it free. Merges it with adjacent free suballocations if applicable. Returns iterator to new free suballocation at this place.</summary>
        public D3D12MA_List <D3D12MA_Suballocation> .iterator FreeSuballocation(D3D12MA_List <D3D12MA_Suballocation> .iterator suballocItem)
        {
            // Change this suballocation to be marked as free.
            D3D12MA_Suballocation *suballoc = suballocItem.Get();

            suballoc->type     = D3D12MA_SUBALLOCATION_TYPE_FREE;
            suballoc->userData = null;

            // Update totals.
            ++m_FreeCount;
            m_SumFreeSize += suballoc->size;

            // Merge with previous and/or next suballocation if it's also free.
            bool mergeWithNext = false;
            bool mergeWithPrev = false;

            D3D12MA_List <D3D12MA_Suballocation> .iterator nextItem = suballocItem;
            nextItem = nextItem.MoveNext();

            if ((nextItem != m_Suballocations.end()) && (nextItem.Get()->type == D3D12MA_SUBALLOCATION_TYPE_FREE))
            {
                mergeWithNext = true;
            }

            D3D12MA_List <D3D12MA_Suballocation> .iterator prevItem = suballocItem;

            if (suballocItem != m_Suballocations.begin())
            {
                prevItem = prevItem.MoveBack();

                if (prevItem.Get()->type == D3D12MA_SUBALLOCATION_TYPE_FREE)
                {
                    mergeWithPrev = true;
                }
            }

            if (mergeWithNext)
            {
                UnregisterFreeSuballocation(nextItem);
                MergeFreeWithNext(suballocItem);
            }

            if (mergeWithPrev)
            {
                UnregisterFreeSuballocation(prevItem);
                MergeFreeWithNext(prevItem);
                RegisterFreeSuballocation(prevItem);
                return(prevItem);
            }
            else
            {
                RegisterFreeSuballocation(suballocItem);
                return(suballocItem);
            }
        }
        internal static void _ctor(ref D3D12MA_BlockMetadata_Generic pThis, [NativeTypeName("const D3D12MA_ALLOCATION_CALLBACKS&")] D3D12MA_ALLOCATION_CALLBACKS *allocationCallbacks, bool isVirtual)
        {
            pThis.Base        = new D3D12MA_BlockMetadata(allocationCallbacks, isVirtual);
            pThis.Base.lpVtbl = Vtbl;

            pThis.m_FreeCount   = 0;
            pThis.m_SumFreeSize = 0;
            D3D12MA_List <D3D12MA_Suballocation> ._ctor(ref pThis.m_Suballocations, allocationCallbacks);

            D3D12MA_Vector <D3D12MA_List <D3D12MA_Suballocation> .iterator> ._ctor(ref pThis.m_FreeSuballocationsBySize, allocationCallbacks);

            Unsafe.SkipInit(out pThis.m_ZeroInitializedRange);

            D3D12MA_ASSERT((D3D12MA_DEBUG_LEVEL > 0) && (allocationCallbacks != null));
        }
        /// <summary>Given free suballocation, it merges it with following one, which must also be free.</summary>
        public void MergeFreeWithNext(D3D12MA_List <D3D12MA_Suballocation> .iterator item)
        {
            D3D12MA_ASSERT((D3D12MA_DEBUG_LEVEL > 0) && (item != m_Suballocations.end()));
            D3D12MA_ASSERT((D3D12MA_DEBUG_LEVEL > 0) && (item.Get()->type == D3D12MA_SUBALLOCATION_TYPE_FREE));

            D3D12MA_List <D3D12MA_Suballocation> .iterator nextItem = item;
            nextItem = nextItem.MoveNext();

            D3D12MA_ASSERT((D3D12MA_DEBUG_LEVEL > 0) && (nextItem != m_Suballocations.end()));
            D3D12MA_ASSERT((D3D12MA_DEBUG_LEVEL > 0) && (nextItem.Get()->type == D3D12MA_SUBALLOCATION_TYPE_FREE));

            item.Get()->size += nextItem.Get()->size;
            --m_FreeCount;

            m_Suballocations.erase(nextItem);
        }
        public readonly bool ValidateFreeSuballocationList()
        {
            ulong lastSize = 0;

            for (nuint i = 0, count = m_FreeSuballocationsBySize.size(); i < count; ++i)
            {
                D3D12MA_List <D3D12MA_Suballocation> .iterator it = *m_FreeSuballocationsBySize[i];

                _ = D3D12MA_VALIDATE(it.Get()->type == D3D12MA_SUBALLOCATION_TYPE_FREE);
                _ = D3D12MA_VALIDATE(it.Get()->size >= MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER);
                _ = D3D12MA_VALIDATE(it.Get()->size >= lastSize);

                lastSize = it.Get()->size;
            }

            return(true);
        }
        public static void Init(ref D3D12MA_BlockMetadata_Generic pThis, [NativeTypeName("UINT64")] ulong size)
        {
            D3D12MA_BlockMetadata.Init(ref pThis.Base, size);
            pThis.m_ZeroInitializedRange.Reset(size);

            pThis.m_FreeCount   = 1;
            pThis.m_SumFreeSize = size;

            D3D12MA_Suballocation suballoc = default;

            suballoc.offset   = 0;
            suballoc.size     = size;
            suballoc.type     = D3D12MA_SUBALLOCATION_TYPE_FREE;
            suballoc.userData = null;

            D3D12MA_ASSERT((D3D12MA_DEBUG_LEVEL > 0) && (size > MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER));
            pThis.m_Suballocations.push_back(in suballoc);

            D3D12MA_List <D3D12MA_Suballocation> .iterator suballocItem = pThis.m_Suballocations.end();
            suballocItem = suballocItem.MoveBack();

            pThis.m_FreeSuballocationsBySize.push_back(in suballocItem);
        }
        /// <summary>Given free suballocation, it inserts it into sorted list of <see cref="m_FreeSuballocationsBySize"/> if it's suitable.</summary>
        public void RegisterFreeSuballocation(D3D12MA_List <D3D12MA_Suballocation> .iterator item)
        {
            D3D12MA_ASSERT((D3D12MA_DEBUG_LEVEL > 0) && (item.Get()->type == D3D12MA_SUBALLOCATION_TYPE_FREE));
            D3D12MA_ASSERT((D3D12MA_DEBUG_LEVEL > 0) && (item.Get()->size > 0));

            // You may want to enable this validation at the beginning or at the end of
            // this function, depending on what do you want to check.
            D3D12MA_HEAVY_ASSERT((D3D12MA_DEBUG_LEVEL > 1) && ValidateFreeSuballocationList());

            if (item.Get()->size >= MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
            {
                if (m_FreeSuballocationsBySize.empty())
                {
                    m_FreeSuballocationsBySize.push_back(in item);
                }
                else
                {
                    _ = m_FreeSuballocationsBySize.InsertSorted(in item, new D3D12MA_SuballocationItemSizeLess());
                }
            }

            // D3D12MA_HEAVY_ASSERT((D3D12MA_DEBUG_LEVEL > 1) && ValidateFreeSuballocatioNList());
        }
        /// <summary>Checks if requested suballocation with given parameters can be placed in given pFreeSuballocItem. If yes, fills pOffset and returns true. If no, returns false.</summary>
        public readonly bool CheckAllocation([NativeTypeName("UINT64")] ulong allocSize, [NativeTypeName("UINT64")] ulong allocAlignment, D3D12MA_List <D3D12MA_Suballocation> .iterator suballocItem, [NativeTypeName("UINT64*")] ulong *pOffset, [NativeTypeName("UINT64*")] ulong *pSumFreeSize, [NativeTypeName("UINT64*")] ulong *pSumItemSize, [NativeTypeName("BOOL")] int *pZeroInitialized)
        {
            D3D12MA_ASSERT((D3D12MA_DEBUG_LEVEL > 0) && (allocSize > 0));
            D3D12MA_ASSERT((D3D12MA_DEBUG_LEVEL > 0) && (suballocItem != m_Suballocations.end()));
            D3D12MA_ASSERT((D3D12MA_DEBUG_LEVEL > 0) && (pOffset != null) && (pZeroInitialized != null));

            *pSumFreeSize     = 0;
            *pSumItemSize     = 0;
            *pZeroInitialized = FALSE;

            D3D12MA_Suballocation *suballoc = suballocItem.Get();

            D3D12MA_ASSERT((D3D12MA_DEBUG_LEVEL > 0) && (suballoc->type == D3D12MA_SUBALLOCATION_TYPE_FREE));

            *pSumFreeSize = suballoc->size;

            // Size of this suballocation is too small for this request: Early return.
            if (suballoc->size < allocSize)
            {
                return(false);
            }

            // Start from offset equal to beginning of this suballocation.
            *pOffset = suballoc->offset;

            // Apply D3D12MA_DEBUG_MARGIN at the beginning.
            if (D3D12MA_DEBUG_MARGIN > 0)
            {
                *pOffset += D3D12MA_DEBUG_MARGIN;
            }

            // Apply alignment.
            *pOffset = AlignUp(*pOffset, allocAlignment);

            // Calculate padding at the beginning based on current offset.
            ulong paddingBegin = *pOffset - suballoc->offset;

            // Calculate required margin at the end.
            ulong requiredEndMargin = D3D12MA_DEBUG_MARGIN;

            // Fail if requested size plus margin before and after is bigger than size of this suballocation.
            if (paddingBegin + allocSize + requiredEndMargin > suballoc->size)
            {
                return(false);
            }

            // All tests passed: Success. pOffset is already filled.
            *pZeroInitialized = m_ZeroInitializedRange.IsRangeZeroInitialized(*pOffset, *pOffset + allocSize);
            return(true);
        }