mirror of
https://github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator.git
synced 2024-11-21 19:50:05 +00:00
Internal optimization in traversal of BlockMetadata_Generic::m_Suballocations
This commit is contained in:
parent
4488fa2a73
commit
8188312fe7
@ -40,7 +40,7 @@ Additional features:
|
||||
|
||||
# Prerequisites
|
||||
|
||||
- Self-contained C++ library in single pair of H + CPP files. No external dependencies other than standard C, C++ library and Windows SDK. Some features of C++11 used. STL containers, C++ exceptions, and RTTI are not used.
|
||||
- Self-contained C++ library in single pair of H + CPP files. No external dependencies other than standard C, C++ library and Windows SDK. Some features of C++14 used. STL containers, C++ exceptions, and RTTI are not used.
|
||||
- Object-oriented interface in a convention similar to D3D12.
|
||||
- Error handling implemented by returning `HRESULT` error codes - same way as in D3D12.
|
||||
- Interface documented using Doxygen-style comments.
|
||||
|
@ -1561,6 +1561,7 @@ public:
|
||||
|
||||
void Remove(Item* pItem);
|
||||
|
||||
class reverse_iterator;
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
@ -1570,6 +1571,12 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
iterator(const reverse_iterator& src) :
|
||||
m_pList(src.m_pList),
|
||||
m_pItem(src.m_pItem)
|
||||
{
|
||||
}
|
||||
|
||||
T& operator*() const
|
||||
{
|
||||
D3D12MA_HEAVY_ASSERT(m_pItem != NULL);
|
||||
@ -1636,6 +1643,91 @@ public:
|
||||
}
|
||||
|
||||
friend class List<T>;
|
||||
friend class const_iterator;
|
||||
};
|
||||
|
||||
class reverse_iterator
|
||||
{
|
||||
public:
|
||||
reverse_iterator() :
|
||||
m_pList(NULL),
|
||||
m_pItem(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
reverse_iterator(const iterator& src) :
|
||||
m_pList(src.m_pList),
|
||||
m_pItem(src.m_pItem)
|
||||
{
|
||||
}
|
||||
|
||||
T& operator*() const
|
||||
{
|
||||
D3D12MA_HEAVY_ASSERT(m_pItem != NULL);
|
||||
return m_pItem->Value;
|
||||
}
|
||||
T* operator->() const
|
||||
{
|
||||
D3D12MA_HEAVY_ASSERT(m_pItem != NULL);
|
||||
return &m_pItem->Value;
|
||||
}
|
||||
|
||||
reverse_iterator& operator++()
|
||||
{
|
||||
D3D12MA_HEAVY_ASSERT(m_pItem != NULL);
|
||||
m_pItem = m_pItem->pPrev;
|
||||
return *this;
|
||||
}
|
||||
reverse_iterator& operator--()
|
||||
{
|
||||
if(m_pItem != NULL)
|
||||
{
|
||||
m_pItem = m_pItem->pNext;
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D12MA_HEAVY_ASSERT(!m_pList->IsEmpty());
|
||||
m_pItem = m_pList->Front();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
reverse_iterator operator++(int)
|
||||
{
|
||||
reverse_iterator result = *this;
|
||||
++*this;
|
||||
return result;
|
||||
}
|
||||
reverse_iterator operator--(int)
|
||||
{
|
||||
reverse_iterator result = *this;
|
||||
--*this;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool operator==(const reverse_iterator& rhs) const
|
||||
{
|
||||
D3D12MA_HEAVY_ASSERT(m_pList == rhs.m_pList);
|
||||
return m_pItem == rhs.m_pItem;
|
||||
}
|
||||
bool operator!=(const reverse_iterator& rhs) const
|
||||
{
|
||||
D3D12MA_HEAVY_ASSERT(m_pList == rhs.m_pList);
|
||||
return m_pItem != rhs.m_pItem;
|
||||
}
|
||||
|
||||
private:
|
||||
List<T>* m_pList;
|
||||
Item* m_pItem;
|
||||
|
||||
reverse_iterator(List<T>* pList, Item* pItem) :
|
||||
m_pList(pList),
|
||||
m_pItem(pItem)
|
||||
{
|
||||
}
|
||||
|
||||
friend class List<T>;
|
||||
friend class const_reverse_iterator;
|
||||
};
|
||||
|
||||
class const_iterator
|
||||
@ -1653,6 +1745,23 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator(const reverse_iterator& src) :
|
||||
m_pList(src.m_pList),
|
||||
m_pItem(src.m_pItem)
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator(const const_reverse_iterator& src) :
|
||||
m_pList(src.m_pList),
|
||||
m_pItem(src.m_pItem)
|
||||
{
|
||||
}
|
||||
|
||||
iterator dropConst() const
|
||||
{
|
||||
return iterator(const_cast<List<T>*>(m_pList), const_cast<Item*>(m_pItem));
|
||||
}
|
||||
|
||||
const T& operator*() const
|
||||
{
|
||||
D3D12MA_HEAVY_ASSERT(m_pItem != NULL);
|
||||
@ -1721,6 +1830,106 @@ public:
|
||||
friend class List<T>;
|
||||
};
|
||||
|
||||
class const_reverse_iterator
|
||||
{
|
||||
public:
|
||||
const_reverse_iterator() :
|
||||
m_pList(NULL),
|
||||
m_pItem(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
const_reverse_iterator(const iterator& src) :
|
||||
m_pList(src.m_pList),
|
||||
m_pItem(src.m_pItem)
|
||||
{
|
||||
}
|
||||
|
||||
const_reverse_iterator(const reverse_iterator& src) :
|
||||
m_pList(src.m_pList),
|
||||
m_pItem(src.m_pItem)
|
||||
{
|
||||
}
|
||||
|
||||
const_reverse_iterator(const const_iterator& src) :
|
||||
m_pList(src.m_pList),
|
||||
m_pItem(src.m_pItem)
|
||||
{
|
||||
}
|
||||
|
||||
reverse_iterator dropConst() const
|
||||
{
|
||||
return reverse_iterator(const_cast<List<T>*>(m_pList), const_cast<Item*>(m_pItem));
|
||||
}
|
||||
|
||||
const T& operator*() const
|
||||
{
|
||||
D3D12MA_HEAVY_ASSERT(m_pItem != NULL);
|
||||
return m_pItem->Value;
|
||||
}
|
||||
const T* operator->() const
|
||||
{
|
||||
D3D12MA_HEAVY_ASSERT(m_pItem != NULL);
|
||||
return &m_pItem->Value;
|
||||
}
|
||||
|
||||
const_reverse_iterator& operator++()
|
||||
{
|
||||
D3D12MA_HEAVY_ASSERT(m_pItem != NULL);
|
||||
m_pItem = m_pItem->pPrev;
|
||||
return *this;
|
||||
}
|
||||
const_reverse_iterator& operator--()
|
||||
{
|
||||
if(m_pItem != NULL)
|
||||
{
|
||||
m_pItem = m_pItem->pNext;
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D12MA_HEAVY_ASSERT(!m_pList->IsEmpty());
|
||||
m_pItem = m_pList->Front();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_reverse_iterator operator++(int)
|
||||
{
|
||||
const_reverse_iterator result = *this;
|
||||
++*this;
|
||||
return result;
|
||||
}
|
||||
const_reverse_iterator operator--(int)
|
||||
{
|
||||
const_reverse_iterator result = *this;
|
||||
--*this;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool operator==(const const_reverse_iterator& rhs) const
|
||||
{
|
||||
D3D12MA_HEAVY_ASSERT(m_pList == rhs.m_pList);
|
||||
return m_pItem == rhs.m_pItem;
|
||||
}
|
||||
bool operator!=(const const_reverse_iterator& rhs) const
|
||||
{
|
||||
D3D12MA_HEAVY_ASSERT(m_pList == rhs.m_pList);
|
||||
return m_pItem != rhs.m_pItem;
|
||||
}
|
||||
|
||||
private:
|
||||
const_reverse_iterator(const List<T>* pList, const Item* pItem) :
|
||||
m_pList(pList),
|
||||
m_pItem(pItem)
|
||||
{
|
||||
}
|
||||
|
||||
const List<T>* m_pList;
|
||||
const Item* m_pItem;
|
||||
|
||||
friend class List<T>;
|
||||
};
|
||||
|
||||
bool empty() const { return IsEmpty(); }
|
||||
size_t size() const { return GetCount(); }
|
||||
|
||||
@ -1733,6 +1942,15 @@ public:
|
||||
const_iterator begin() const { return cbegin(); }
|
||||
const_iterator end() const { return cend(); }
|
||||
|
||||
reverse_iterator rbegin() { return reverse_iterator(this, Back()); }
|
||||
reverse_iterator rend() { return reverse_iterator(this, NULL); }
|
||||
|
||||
const_reverse_iterator crbegin() const { return const_reverse_iterator(this, Back()); }
|
||||
const_reverse_iterator crend() const { return const_reverse_iterator(this, NULL); }
|
||||
|
||||
const_reverse_iterator rbegin() const { return crbegin(); }
|
||||
const_reverse_iterator rend() const { return crend(); }
|
||||
|
||||
void clear() { Clear(); }
|
||||
void push_back(const T& value) { PushBack(value); }
|
||||
void erase(iterator it) { Remove(it.m_pItem); }
|
||||
@ -2420,6 +2638,7 @@ private:
|
||||
Vector<SuballocationList::iterator> m_FreeSuballocationsBySize;
|
||||
ZeroInitializedRange m_ZeroInitializedRange;
|
||||
|
||||
SuballocationList::const_iterator FindAtOffset(UINT64 offset) const;
|
||||
bool ValidateFreeSuballocationList() const;
|
||||
|
||||
// Checks if requested suballocation with given parameters can be placed in given pFreeSuballocItem.
|
||||
@ -3194,16 +3413,9 @@ bool BlockMetadata_Generic::IsEmpty() const
|
||||
|
||||
void BlockMetadata_Generic::GetAllocationInfo(UINT64 offset, VIRTUAL_ALLOCATION_INFO& outInfo) const
|
||||
{
|
||||
for(const auto& suballoc : m_Suballocations)
|
||||
{
|
||||
if(suballoc.offset == offset)
|
||||
{
|
||||
Suballocation& suballoc = *FindAtOffset(offset).dropConst();
|
||||
outInfo.size = suballoc.size;
|
||||
outInfo.pUserData = suballoc.userData;
|
||||
return;
|
||||
}
|
||||
}
|
||||
D3D12MA_ASSERT(0 && "Not found!");
|
||||
}
|
||||
|
||||
bool BlockMetadata_Generic::CreateAllocationRequest(
|
||||
@ -3319,18 +3531,7 @@ void BlockMetadata_Generic::Alloc(
|
||||
|
||||
void BlockMetadata_Generic::FreeAtOffset(UINT64 offset)
|
||||
{
|
||||
for(SuballocationList::iterator suballocItem = m_Suballocations.begin();
|
||||
suballocItem != m_Suballocations.end();
|
||||
++suballocItem)
|
||||
{
|
||||
Suballocation& suballoc = *suballocItem;
|
||||
if(suballoc.offset == offset)
|
||||
{
|
||||
FreeSuballocation(suballocItem);
|
||||
return;
|
||||
}
|
||||
}
|
||||
D3D12MA_ASSERT(0 && "Not found!");
|
||||
FreeSuballocation(FindAtOffset(offset).dropConst());
|
||||
}
|
||||
|
||||
void BlockMetadata_Generic::Clear()
|
||||
@ -3349,6 +3550,38 @@ void BlockMetadata_Generic::Clear()
|
||||
m_FreeSuballocationsBySize.push_back(m_Suballocations.begin());
|
||||
}
|
||||
|
||||
SuballocationList::const_iterator BlockMetadata_Generic::FindAtOffset(UINT64 offset) const
|
||||
{
|
||||
const UINT64 last = m_Suballocations.crbegin()->offset;
|
||||
if (last == offset)
|
||||
return m_Suballocations.crbegin();
|
||||
const UINT64 first = m_Suballocations.cbegin()->offset;
|
||||
if (first == offset)
|
||||
return m_Suballocations.cbegin();
|
||||
|
||||
const size_t suballocCount = m_Suballocations.size();
|
||||
const UINT64 step = (last - first + m_Suballocations.cbegin()->size) / suballocCount;
|
||||
auto findSuballocation = [&](auto begin, auto end) -> SuballocationList::const_iterator
|
||||
{
|
||||
for (auto suballocItem = begin;
|
||||
suballocItem != end;
|
||||
++suballocItem)
|
||||
{
|
||||
const Suballocation& suballoc = *suballocItem;
|
||||
if (suballoc.offset == offset)
|
||||
return suballocItem;
|
||||
}
|
||||
D3D12MA_ASSERT(false && "Not found!");
|
||||
return m_Suballocations.end();
|
||||
};
|
||||
// If requested offset is closer to the end of range, search from the end
|
||||
if ((offset - first) > suballocCount * step / 2)
|
||||
{
|
||||
return findSuballocation(m_Suballocations.crbegin(), m_Suballocations.crend());
|
||||
}
|
||||
return findSuballocation(m_Suballocations.cbegin(), m_Suballocations.cend());
|
||||
}
|
||||
|
||||
bool BlockMetadata_Generic::ValidateFreeSuballocationList() const
|
||||
{
|
||||
UINT64 lastSize = 0;
|
||||
@ -3548,15 +3781,8 @@ void BlockMetadata_Generic::UnregisterFreeSuballocation(SuballocationList::itera
|
||||
|
||||
void BlockMetadata_Generic::SetAllocationUserData(UINT64 offset, void* userData)
|
||||
{
|
||||
for(auto& suballoc : m_Suballocations)
|
||||
{
|
||||
if(suballoc.offset == offset)
|
||||
{
|
||||
Suballocation& suballoc = *FindAtOffset(offset).dropConst();
|
||||
suballoc.userData = userData;
|
||||
return;
|
||||
}
|
||||
}
|
||||
D3D12MA_ASSERT(0 && "Not found!");
|
||||
}
|
||||
|
||||
void BlockMetadata_Generic::CalcAllocationStatInfo(StatInfo& outInfo) const
|
||||
|
Loading…
Reference in New Issue
Block a user