/// <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());
        }
Example #2
0
        public int SetMinBytes([NativeTypeName("UINT64")] ulong minBytes)
        {
            using var @lock = new D3D12MA_MutexLockWrite(ref m_Mutex, m_hAllocator->UseMutex());

            if (minBytes == m_MinBytes)
            {
                return(S_OK);
            }

            HRESULT hr           = S_OK;
            ulong   sumBlockSize = CalcSumBlockSize();
            nuint   blockCount   = m_Blocks.size();

            // New minBytes is smaller - may be able to free some blocks.
            if (minBytes < m_MinBytes)
            {
                m_HasEmptyBlock = false; // Will recalculate this value from scratch.

                for (nuint blockIndex = blockCount; unchecked (blockIndex-- != 0);)
                {
                    D3D12MA_NormalBlock *block = m_Blocks[blockIndex]->Value;

                    ulong size    = block->m_pMetadata->GetSize();
                    bool  isEmpty = block->m_pMetadata->IsEmpty();

                    if (isEmpty && ((sumBlockSize - size) >= minBytes) && ((blockCount - 1) >= m_MinBlockCount))
                    {
                        D3D12MA_DELETE(m_hAllocator->GetAllocs(), block);
                        m_Blocks.remove(blockIndex);

                        sumBlockSize -= size;
                        --blockCount;
                    }
                    else
                    {
                        if (isEmpty)
                        {
                            m_HasEmptyBlock = true;
                        }
                    }
                }
            }
            else
            {
                // New minBytes is larger - may need to allocate some blocks.
                ulong minBlockSize = m_PreferredBlockSize >> (int)NEW_BLOCK_SIZE_SHIFT_MAX;

                while (SUCCEEDED(hr) && sumBlockSize < minBytes)
                {
                    if (blockCount < m_MaxBlockCount)
                    {
                        ulong newBlockSize = m_PreferredBlockSize;

                        if (!m_ExplicitBlockSize)
                        {
                            if (sumBlockSize + newBlockSize > minBytes)
                            {
                                newBlockSize = minBytes - sumBlockSize;
                            }
                            else if (((blockCount + 1) < m_MaxBlockCount) && ((sumBlockSize + newBlockSize + minBlockSize) > minBytes))
                            {
                                // Next one would be the last block to create and its size would be smaller than
                                // the smallest block size we want to use here, so make this one smaller.

                                newBlockSize -= minBlockSize + sumBlockSize + m_PreferredBlockSize - minBytes;
                            }
                        }

                        hr = CreateBlock(newBlockSize, null);

                        if (SUCCEEDED(hr))
                        {
                            m_HasEmptyBlock = true;
                            sumBlockSize   += newBlockSize;
                            ++blockCount;
                        }
                    }
                    else
                    {
                        hr = E_INVALIDARG;
                    }
                }
            }

            m_MinBytes = minBytes;
            return(hr);
        }