mirror of
https://github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator.git
synced 2024-11-21 19:50:05 +00:00
Removed Allocation::WasZeroInitialized
It wasn't fully implemented anyway.
This commit is contained in:
parent
c29f274ea1
commit
514c67b84d
@ -543,26 +543,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
LPCWSTR GetName() const { return m_Name; }
|
LPCWSTR GetName() const { return m_Name; }
|
||||||
|
|
||||||
/** \brief Returns `TRUE` if the memory of the allocation was filled with zeros when the allocation was created.
|
|
||||||
|
|
||||||
Returns `TRUE` only if the allocator is sure that the entire memory where the
|
|
||||||
allocation was created was filled with zeros at the moment the allocation was made.
|
|
||||||
|
|
||||||
Returns `FALSE` if the memory could potentially contain garbage data.
|
|
||||||
If it's a render-target or depth-stencil texture, it then needs proper
|
|
||||||
initialization with `ClearRenderTargetView`, `ClearDepthStencilView`, `DiscardResource`,
|
|
||||||
or a copy operation, as described on page
|
|
||||||
"ID3D12Device::CreatePlacedResource method - Notes on the required resource initialization" in Microsoft documentation.
|
|
||||||
Please note that rendering a fullscreen triangle or quad to the texture as
|
|
||||||
a render target is not a proper way of initialization!
|
|
||||||
|
|
||||||
See also articles:
|
|
||||||
|
|
||||||
- "Coming to DirectX 12: More control over memory allocation" on DirectX Developer Blog
|
|
||||||
- ["Initializing DX12 Textures After Allocation and Aliasing"](https://asawicki.info/news_1724_initializing_dx12_textures_after_allocation_and_aliasing).
|
|
||||||
*/
|
|
||||||
BOOL WasZeroInitialized() const { return m_PackedData.WasZeroInitialized(); }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void ReleaseThis() override;
|
void ReleaseThis() override;
|
||||||
|
|
||||||
@ -621,29 +601,26 @@ private:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PackedData() :
|
PackedData() :
|
||||||
m_Type(0), m_ResourceDimension(0), m_ResourceFlags(0), m_TextureLayout(0), m_WasZeroInitialized(0) { }
|
m_Type(0), m_ResourceDimension(0), m_ResourceFlags(0), m_TextureLayout(0) { }
|
||||||
|
|
||||||
Type GetType() const { return (Type)m_Type; }
|
Type GetType() const { return (Type)m_Type; }
|
||||||
D3D12_RESOURCE_DIMENSION GetResourceDimension() const { return (D3D12_RESOURCE_DIMENSION)m_ResourceDimension; }
|
D3D12_RESOURCE_DIMENSION GetResourceDimension() const { return (D3D12_RESOURCE_DIMENSION)m_ResourceDimension; }
|
||||||
D3D12_RESOURCE_FLAGS GetResourceFlags() const { return (D3D12_RESOURCE_FLAGS)m_ResourceFlags; }
|
D3D12_RESOURCE_FLAGS GetResourceFlags() const { return (D3D12_RESOURCE_FLAGS)m_ResourceFlags; }
|
||||||
D3D12_TEXTURE_LAYOUT GetTextureLayout() const { return (D3D12_TEXTURE_LAYOUT)m_TextureLayout; }
|
D3D12_TEXTURE_LAYOUT GetTextureLayout() const { return (D3D12_TEXTURE_LAYOUT)m_TextureLayout; }
|
||||||
BOOL WasZeroInitialized() const { return (BOOL)m_WasZeroInitialized; }
|
|
||||||
|
|
||||||
void SetType(Type type);
|
void SetType(Type type);
|
||||||
void SetResourceDimension(D3D12_RESOURCE_DIMENSION resourceDimension);
|
void SetResourceDimension(D3D12_RESOURCE_DIMENSION resourceDimension);
|
||||||
void SetResourceFlags(D3D12_RESOURCE_FLAGS resourceFlags);
|
void SetResourceFlags(D3D12_RESOURCE_FLAGS resourceFlags);
|
||||||
void SetTextureLayout(D3D12_TEXTURE_LAYOUT textureLayout);
|
void SetTextureLayout(D3D12_TEXTURE_LAYOUT textureLayout);
|
||||||
void SetWasZeroInitialized(BOOL wasZeroInitialized) { m_WasZeroInitialized = wasZeroInitialized ? 1 : 0; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UINT m_Type : 2; // enum Type
|
UINT m_Type : 2; // enum Type
|
||||||
UINT m_ResourceDimension : 3; // enum D3D12_RESOURCE_DIMENSION
|
UINT m_ResourceDimension : 3; // enum D3D12_RESOURCE_DIMENSION
|
||||||
UINT m_ResourceFlags : 24; // flags D3D12_RESOURCE_FLAGS
|
UINT m_ResourceFlags : 24; // flags D3D12_RESOURCE_FLAGS
|
||||||
UINT m_TextureLayout : 9; // enum D3D12_TEXTURE_LAYOUT
|
UINT m_TextureLayout : 9; // enum D3D12_TEXTURE_LAYOUT
|
||||||
UINT m_WasZeroInitialized : 1; // BOOL
|
|
||||||
} m_PackedData;
|
} m_PackedData;
|
||||||
|
|
||||||
Allocation(AllocatorPimpl* allocator, UINT64 size, UINT64 alignment, BOOL wasZeroInitialized);
|
Allocation(AllocatorPimpl* allocator, UINT64 size, UINT64 alignment);
|
||||||
// Nothing here, everything already done in Release.
|
// Nothing here, everything already done in Release.
|
||||||
virtual ~Allocation() = default;
|
virtual ~Allocation() = default;
|
||||||
|
|
||||||
|
@ -2874,75 +2874,9 @@ struct AllocationRequest
|
|||||||
UINT64 sumFreeSize; // Sum size of free items that overlap with proposed allocation.
|
UINT64 sumFreeSize; // Sum size of free items that overlap with proposed allocation.
|
||||||
UINT64 sumItemSize; // Sum size of items to make lost that overlap with proposed allocation.
|
UINT64 sumItemSize; // Sum size of items to make lost that overlap with proposed allocation.
|
||||||
SuballocationList::iterator item;
|
SuballocationList::iterator item;
|
||||||
BOOL zeroInitialized = FALSE; // TODO Implement proper handling in TLSF and Linear, using ZeroInitializedRange class.
|
|
||||||
};
|
};
|
||||||
#endif // _D3D12MA_ALLOCATION_REQUEST
|
#endif // _D3D12MA_ALLOCATION_REQUEST
|
||||||
|
|
||||||
#ifndef _D3D12MA_ZERO_INITIALIZED_RANGE
|
|
||||||
/*
|
|
||||||
Keeps track of the range of bytes that are surely initialized with zeros.
|
|
||||||
Everything outside of it is considered uninitialized memory that may contain
|
|
||||||
garbage data.
|
|
||||||
|
|
||||||
The range is left-inclusive.
|
|
||||||
*/
|
|
||||||
class ZeroInitializedRange
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Reset(UINT64 size);
|
|
||||||
BOOL IsRangeZeroInitialized(UINT64 beg, UINT64 end) const;
|
|
||||||
void MarkRangeAsUsed(UINT64 usedBeg, UINT64 usedEnd);
|
|
||||||
|
|
||||||
private:
|
|
||||||
UINT64 m_ZeroBeg = 0, m_ZeroEnd = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef _D3D12MA_ZERO_INITIALIZED_RANGE_FUNCTIONS
|
|
||||||
void ZeroInitializedRange::Reset(UINT64 size)
|
|
||||||
{
|
|
||||||
D3D12MA_ASSERT(size > 0);
|
|
||||||
m_ZeroBeg = 0;
|
|
||||||
m_ZeroEnd = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL ZeroInitializedRange::IsRangeZeroInitialized(UINT64 beg, UINT64 end) const
|
|
||||||
{
|
|
||||||
D3D12MA_ASSERT(beg < end);
|
|
||||||
return m_ZeroBeg <= beg && end <= m_ZeroEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZeroInitializedRange::MarkRangeAsUsed(UINT64 usedBeg, UINT64 usedEnd)
|
|
||||||
{
|
|
||||||
D3D12MA_ASSERT(usedBeg < usedEnd);
|
|
||||||
// No new bytes marked.
|
|
||||||
if (usedEnd <= m_ZeroBeg || m_ZeroEnd <= usedBeg)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// All bytes marked.
|
|
||||||
if (usedBeg <= m_ZeroBeg && m_ZeroEnd <= usedEnd)
|
|
||||||
{
|
|
||||||
m_ZeroBeg = m_ZeroEnd = 0;
|
|
||||||
}
|
|
||||||
// Some bytes marked.
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const UINT64 remainingZeroBefore = usedBeg > m_ZeroBeg ? usedBeg - m_ZeroBeg : 0;
|
|
||||||
const UINT64 remainingZeroAfter = usedEnd < m_ZeroEnd ? m_ZeroEnd - usedEnd : 0;
|
|
||||||
D3D12MA_ASSERT(remainingZeroBefore > 0 || remainingZeroAfter > 0);
|
|
||||||
if (remainingZeroBefore > remainingZeroAfter)
|
|
||||||
{
|
|
||||||
m_ZeroEnd = usedBeg;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_ZeroBeg = usedEnd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // _D3D12MA_ZERO_INITIALIZED_RANGE_FUNCTIONS
|
|
||||||
#endif // _D3D12MA_ZERO_INITIALIZED_RANGE
|
|
||||||
|
|
||||||
#ifndef _D3D12MA_BLOCK_METADATA
|
#ifndef _D3D12MA_BLOCK_METADATA
|
||||||
/*
|
/*
|
||||||
Data structure used for bookkeeping of allocations and unused ranges of memory
|
Data structure used for bookkeeping of allocations and unused ranges of memory
|
||||||
@ -3121,610 +3055,6 @@ void BlockMetadata::PrintDetailedMap_End(JsonWriter& json) const
|
|||||||
#endif // _D3D12MA_BLOCK_METADATA_FUNCTIONS
|
#endif // _D3D12MA_BLOCK_METADATA_FUNCTIONS
|
||||||
#endif // _D3D12MA_BLOCK_METADATA
|
#endif // _D3D12MA_BLOCK_METADATA
|
||||||
|
|
||||||
#if 0
|
|
||||||
#ifndef _D3D12MA_BLOCK_METADATA_GENERIC
|
|
||||||
class BlockMetadata_Generic : public BlockMetadata
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BlockMetadata_Generic(const ALLOCATION_CALLBACKS* allocationCallbacks, bool isVirtual);
|
|
||||||
virtual ~BlockMetadata_Generic() = default;
|
|
||||||
|
|
||||||
size_t GetAllocationCount() const override { return m_Suballocations.size() - m_FreeCount; }
|
|
||||||
UINT64 GetSumFreeSize() const override { return m_SumFreeSize; }
|
|
||||||
UINT64 GetAllocationOffset(AllocHandle allocHandle) const override { return (UINT64)allocHandle - 1; }
|
|
||||||
|
|
||||||
void Init(UINT64 size) override;
|
|
||||||
bool Validate() const override;
|
|
||||||
bool IsEmpty() const override;
|
|
||||||
void GetAllocationInfo(AllocHandle allocHandle, VIRTUAL_ALLOCATION_INFO& outInfo) const override;
|
|
||||||
|
|
||||||
bool CreateAllocationRequest(
|
|
||||||
UINT64 allocSize,
|
|
||||||
UINT64 allocAlignment,
|
|
||||||
bool upperAddress,
|
|
||||||
AllocationRequest* pAllocationRequest) override;
|
|
||||||
|
|
||||||
void Alloc(
|
|
||||||
const AllocationRequest& request,
|
|
||||||
UINT64 allocSize,
|
|
||||||
void* privateData) override;
|
|
||||||
|
|
||||||
void Free(AllocHandle allocHandle) override;
|
|
||||||
void Clear() override;
|
|
||||||
|
|
||||||
void SetAllocationPrivateData(AllocHandle allocHandle, void* privateData) override;
|
|
||||||
|
|
||||||
void AddStatistics(Statistics& inoutStats) const override;
|
|
||||||
void AddDetailedStatistics(DetailedStatistics& inoutStats) const override;
|
|
||||||
void WriteAllocationInfoToJson(JsonWriter& json) const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
UINT m_FreeCount;
|
|
||||||
UINT64 m_SumFreeSize;
|
|
||||||
SuballocationList m_Suballocations;
|
|
||||||
// Suballocations that are free and have size greater than certain threshold.
|
|
||||||
// Sorted by size, ascending.
|
|
||||||
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.
|
|
||||||
// If yes, fills pOffset and returns true. If no, returns false.
|
|
||||||
bool CheckAllocation(
|
|
||||||
UINT64 allocSize,
|
|
||||||
UINT64 allocAlignment,
|
|
||||||
SuballocationList::const_iterator suballocItem,
|
|
||||||
AllocHandle* pAllocHandle,
|
|
||||||
UINT64* pSumFreeSize,
|
|
||||||
UINT64* pSumItemSize,
|
|
||||||
BOOL *pZeroInitialized) const;
|
|
||||||
// Given free suballocation, it merges it with following one, which must also be free.
|
|
||||||
void MergeFreeWithNext(SuballocationList::iterator item);
|
|
||||||
// Releases given suballocation, making it free.
|
|
||||||
// Merges it with adjacent free suballocations if applicable.
|
|
||||||
// Returns iterator to new free suballocation at this place.
|
|
||||||
SuballocationList::iterator FreeSuballocation(SuballocationList::iterator suballocItem);
|
|
||||||
// Given free suballocation, it inserts it into sorted list of
|
|
||||||
// m_FreeSuballocationsBySize if it's suitable.
|
|
||||||
void RegisterFreeSuballocation(SuballocationList::iterator item);
|
|
||||||
// Given free suballocation, it removes it from sorted list of
|
|
||||||
// m_FreeSuballocationsBySize if it's suitable.
|
|
||||||
void UnregisterFreeSuballocation(SuballocationList::iterator item);
|
|
||||||
|
|
||||||
D3D12MA_CLASS_NO_COPY(BlockMetadata_Generic)
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef _D3D12MA_BLOCK_METADATA_GENERIC_FUNCTIONS
|
|
||||||
BlockMetadata_Generic::BlockMetadata_Generic(const ALLOCATION_CALLBACKS* allocationCallbacks, bool isVirtual)
|
|
||||||
: BlockMetadata(allocationCallbacks, isVirtual),
|
|
||||||
m_FreeCount(0),
|
|
||||||
m_SumFreeSize(0),
|
|
||||||
m_Suballocations(*allocationCallbacks),
|
|
||||||
m_FreeSuballocationsBySize(*allocationCallbacks)
|
|
||||||
{
|
|
||||||
D3D12MA_ASSERT(allocationCallbacks);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockMetadata_Generic::Init(UINT64 size)
|
|
||||||
{
|
|
||||||
BlockMetadata::Init(size);
|
|
||||||
m_ZeroInitializedRange.Reset(size);
|
|
||||||
|
|
||||||
m_FreeCount = 1;
|
|
||||||
m_SumFreeSize = size;
|
|
||||||
|
|
||||||
Suballocation suballoc = {};
|
|
||||||
suballoc.offset = 0;
|
|
||||||
suballoc.size = size;
|
|
||||||
suballoc.type = SUBALLOCATION_TYPE_FREE;
|
|
||||||
suballoc.privateData = NULL;
|
|
||||||
|
|
||||||
D3D12MA_ASSERT(size > MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER);
|
|
||||||
m_Suballocations.push_back(suballoc);
|
|
||||||
SuballocationList::iterator suballocItem = m_Suballocations.end();
|
|
||||||
--suballocItem;
|
|
||||||
m_FreeSuballocationsBySize.push_back(suballocItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BlockMetadata_Generic::Validate() const
|
|
||||||
{
|
|
||||||
D3D12MA_VALIDATE(!m_Suballocations.empty());
|
|
||||||
|
|
||||||
// Expected offset of new suballocation as calculated from previous ones.
|
|
||||||
UINT64 calculatedOffset = 0;
|
|
||||||
// Expected number of free suballocations as calculated from traversing their list.
|
|
||||||
UINT calculatedFreeCount = 0;
|
|
||||||
// Expected sum size of free suballocations as calculated from traversing their list.
|
|
||||||
UINT64 calculatedSumFreeSize = 0;
|
|
||||||
// Expected number of free suballocations that should be registered in
|
|
||||||
// m_FreeSuballocationsBySize calculated from traversing their list.
|
|
||||||
size_t freeSuballocationsToRegister = 0;
|
|
||||||
// True if previous visited suballocation was free.
|
|
||||||
bool prevFree = false;
|
|
||||||
|
|
||||||
for (const auto& subAlloc : m_Suballocations)
|
|
||||||
{
|
|
||||||
// Actual offset of this suballocation doesn't match expected one.
|
|
||||||
D3D12MA_VALIDATE(subAlloc.offset == calculatedOffset);
|
|
||||||
|
|
||||||
const bool currFree = (subAlloc.type == SUBALLOCATION_TYPE_FREE);
|
|
||||||
// Two adjacent free suballocations are invalid. They should be merged.
|
|
||||||
D3D12MA_VALIDATE(!prevFree || !currFree);
|
|
||||||
|
|
||||||
const Allocation* const alloc = (Allocation*)subAlloc.privateData;
|
|
||||||
if (!IsVirtual())
|
|
||||||
{
|
|
||||||
D3D12MA_VALIDATE(currFree == (alloc == NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currFree)
|
|
||||||
{
|
|
||||||
calculatedSumFreeSize += subAlloc.size;
|
|
||||||
++calculatedFreeCount;
|
|
||||||
if (subAlloc.size >= MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
|
|
||||||
{
|
|
||||||
++freeSuballocationsToRegister;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Margin required between allocations - every free space must be at least that large.
|
|
||||||
D3D12MA_VALIDATE(subAlloc.size >= GetDebugMargin());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!IsVirtual())
|
|
||||||
{
|
|
||||||
D3D12MA_VALIDATE(alloc->GetOffset() == subAlloc.offset);
|
|
||||||
D3D12MA_VALIDATE(alloc->GetSize() == subAlloc.size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Margin required between allocations - previous allocation must be free.
|
|
||||||
D3D12MA_VALIDATE(GetDebugMargin() == 0 || prevFree);
|
|
||||||
}
|
|
||||||
|
|
||||||
calculatedOffset += subAlloc.size;
|
|
||||||
prevFree = currFree;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Number of free suballocations registered in m_FreeSuballocationsBySize doesn't
|
|
||||||
// match expected one.
|
|
||||||
D3D12MA_VALIDATE(m_FreeSuballocationsBySize.size() == freeSuballocationsToRegister);
|
|
||||||
|
|
||||||
UINT64 lastSize = 0;
|
|
||||||
for (size_t i = 0; i < m_FreeSuballocationsBySize.size(); ++i)
|
|
||||||
{
|
|
||||||
SuballocationList::iterator suballocItem = m_FreeSuballocationsBySize[i];
|
|
||||||
|
|
||||||
// Only free suballocations can be registered in m_FreeSuballocationsBySize.
|
|
||||||
D3D12MA_VALIDATE(suballocItem->type == SUBALLOCATION_TYPE_FREE);
|
|
||||||
// They must be sorted by size ascending.
|
|
||||||
D3D12MA_VALIDATE(suballocItem->size >= lastSize);
|
|
||||||
|
|
||||||
lastSize = suballocItem->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if totals match calculacted values.
|
|
||||||
D3D12MA_VALIDATE(ValidateFreeSuballocationList());
|
|
||||||
D3D12MA_VALIDATE(calculatedOffset == GetSize());
|
|
||||||
D3D12MA_VALIDATE(calculatedSumFreeSize == m_SumFreeSize);
|
|
||||||
D3D12MA_VALIDATE(calculatedFreeCount == m_FreeCount);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BlockMetadata_Generic::IsEmpty() const
|
|
||||||
{
|
|
||||||
return (m_Suballocations.size() == 1) && (m_FreeCount == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockMetadata_Generic::GetAllocationInfo(AllocHandle allocHandle, VIRTUAL_ALLOCATION_INFO& outInfo) const
|
|
||||||
{
|
|
||||||
Suballocation& suballoc = *FindAtOffset((UINT64)allocHandle - 1).dropConst();
|
|
||||||
outInfo.Offset = suballoc.offset;
|
|
||||||
outInfo.Size = suballoc.size;
|
|
||||||
outInfo.pPrivateData = suballoc.privateData;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BlockMetadata_Generic::CreateAllocationRequest(
|
|
||||||
UINT64 allocSize,
|
|
||||||
UINT64 allocAlignment,
|
|
||||||
bool upperAddress,
|
|
||||||
AllocationRequest* pAllocationRequest)
|
|
||||||
{
|
|
||||||
D3D12MA_ASSERT(allocSize > 0);
|
|
||||||
D3D12MA_ASSERT(!upperAddress && "ALLOCATION_FLAG_UPPER_ADDRESS can be used only with linear algorithm.");
|
|
||||||
D3D12MA_ASSERT(pAllocationRequest != NULL);
|
|
||||||
D3D12MA_HEAVY_ASSERT(Validate());
|
|
||||||
|
|
||||||
// There is not enough total free space in this block to fullfill the request: Early return.
|
|
||||||
if (m_SumFreeSize < allocSize + GetDebugMargin())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// New algorithm, efficiently searching freeSuballocationsBySize.
|
|
||||||
const size_t freeSuballocCount = m_FreeSuballocationsBySize.size();
|
|
||||||
if (freeSuballocCount > 0)
|
|
||||||
{
|
|
||||||
// Find first free suballocation with size not less than allocSize + GetDebugMargin().
|
|
||||||
SuballocationList::iterator* const it = BinaryFindFirstNotLess(
|
|
||||||
m_FreeSuballocationsBySize.data(),
|
|
||||||
m_FreeSuballocationsBySize.data() + freeSuballocCount,
|
|
||||||
allocSize + GetDebugMargin(),
|
|
||||||
SuballocationItemSizeLess());
|
|
||||||
size_t index = it - m_FreeSuballocationsBySize.data();
|
|
||||||
for (; index < freeSuballocCount; ++index)
|
|
||||||
{
|
|
||||||
if (CheckAllocation(
|
|
||||||
allocSize,
|
|
||||||
allocAlignment,
|
|
||||||
m_FreeSuballocationsBySize[index],
|
|
||||||
&pAllocationRequest->allocHandle,
|
|
||||||
&pAllocationRequest->sumFreeSize,
|
|
||||||
&pAllocationRequest->sumItemSize,
|
|
||||||
&pAllocationRequest->zeroInitialized))
|
|
||||||
{
|
|
||||||
pAllocationRequest->item = m_FreeSuballocationsBySize[index];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockMetadata_Generic::Alloc(
|
|
||||||
const AllocationRequest& request,
|
|
||||||
UINT64 allocSize,
|
|
||||||
void* privateData)
|
|
||||||
{
|
|
||||||
D3D12MA_ASSERT(request.item != m_Suballocations.end());
|
|
||||||
Suballocation& suballoc = *request.item;
|
|
||||||
// Given suballocation is a free block.
|
|
||||||
D3D12MA_ASSERT(suballoc.type == SUBALLOCATION_TYPE_FREE);
|
|
||||||
// Given offset is inside this suballocation.
|
|
||||||
UINT64 offset = (UINT64)request.allocHandle - 1;
|
|
||||||
D3D12MA_ASSERT(offset >= suballoc.offset);
|
|
||||||
const UINT64 paddingBegin = offset - suballoc.offset;
|
|
||||||
D3D12MA_ASSERT(suballoc.size >= paddingBegin + allocSize);
|
|
||||||
const UINT64 paddingEnd = suballoc.size - paddingBegin - allocSize;
|
|
||||||
|
|
||||||
// Unregister this free suballocation from m_FreeSuballocationsBySize and update
|
|
||||||
// it to become used.
|
|
||||||
UnregisterFreeSuballocation(request.item);
|
|
||||||
|
|
||||||
suballoc.offset = offset;
|
|
||||||
suballoc.size = allocSize;
|
|
||||||
suballoc.type = SUBALLOCATION_TYPE_ALLOCATION;
|
|
||||||
suballoc.privateData = privateData;
|
|
||||||
|
|
||||||
// If there are any free bytes remaining at the end, insert new free suballocation after current one.
|
|
||||||
if (paddingEnd)
|
|
||||||
{
|
|
||||||
Suballocation paddingSuballoc = {};
|
|
||||||
paddingSuballoc.offset = offset + allocSize;
|
|
||||||
paddingSuballoc.size = paddingEnd;
|
|
||||||
paddingSuballoc.type = SUBALLOCATION_TYPE_FREE;
|
|
||||||
SuballocationList::iterator next = request.item;
|
|
||||||
++next;
|
|
||||||
const SuballocationList::iterator paddingEndItem =
|
|
||||||
m_Suballocations.insert(next, paddingSuballoc);
|
|
||||||
RegisterFreeSuballocation(paddingEndItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there are any free bytes remaining at the beginning, insert new free suballocation before current one.
|
|
||||||
if (paddingBegin)
|
|
||||||
{
|
|
||||||
Suballocation paddingSuballoc = {};
|
|
||||||
paddingSuballoc.offset = offset - paddingBegin;
|
|
||||||
paddingSuballoc.size = paddingBegin;
|
|
||||||
paddingSuballoc.type = SUBALLOCATION_TYPE_FREE;
|
|
||||||
const SuballocationList::iterator paddingBeginItem =
|
|
||||||
m_Suballocations.insert(request.item, paddingSuballoc);
|
|
||||||
RegisterFreeSuballocation(paddingBeginItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update totals.
|
|
||||||
m_FreeCount = m_FreeCount - 1;
|
|
||||||
if (paddingBegin > 0)
|
|
||||||
{
|
|
||||||
++m_FreeCount;
|
|
||||||
}
|
|
||||||
if (paddingEnd > 0)
|
|
||||||
{
|
|
||||||
++m_FreeCount;
|
|
||||||
}
|
|
||||||
m_SumFreeSize -= allocSize;
|
|
||||||
|
|
||||||
m_ZeroInitializedRange.MarkRangeAsUsed(offset, offset + allocSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockMetadata_Generic::Free(AllocHandle allocHandle)
|
|
||||||
{
|
|
||||||
FreeSuballocation(FindAtOffset((UINT64)allocHandle - 1).dropConst());
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockMetadata_Generic::Clear()
|
|
||||||
{
|
|
||||||
m_FreeCount = 1;
|
|
||||||
m_SumFreeSize = GetSize();
|
|
||||||
|
|
||||||
m_Suballocations.clear();
|
|
||||||
Suballocation suballoc = {};
|
|
||||||
suballoc.offset = 0;
|
|
||||||
suballoc.size = GetSize();
|
|
||||||
suballoc.type = SUBALLOCATION_TYPE_FREE;
|
|
||||||
m_Suballocations.push_back(suballoc);
|
|
||||||
|
|
||||||
m_FreeSuballocationsBySize.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;
|
|
||||||
for (size_t i = 0, count = m_FreeSuballocationsBySize.size(); i < count; ++i)
|
|
||||||
{
|
|
||||||
const SuballocationList::iterator it = m_FreeSuballocationsBySize[i];
|
|
||||||
|
|
||||||
D3D12MA_VALIDATE(it->type == SUBALLOCATION_TYPE_FREE);
|
|
||||||
D3D12MA_VALIDATE(it->size >= MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER);
|
|
||||||
D3D12MA_VALIDATE(it->size >= lastSize);
|
|
||||||
lastSize = it->size;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BlockMetadata_Generic::CheckAllocation(
|
|
||||||
UINT64 allocSize,
|
|
||||||
UINT64 allocAlignment,
|
|
||||||
SuballocationList::const_iterator suballocItem,
|
|
||||||
AllocHandle* pAllocHandle,
|
|
||||||
UINT64* pSumFreeSize,
|
|
||||||
UINT64* pSumItemSize,
|
|
||||||
BOOL* pZeroInitialized) const
|
|
||||||
{
|
|
||||||
D3D12MA_ASSERT(allocSize > 0);
|
|
||||||
D3D12MA_ASSERT(suballocItem != m_Suballocations.cend());
|
|
||||||
D3D12MA_ASSERT(pAllocHandle != NULL && pZeroInitialized != NULL);
|
|
||||||
|
|
||||||
*pSumFreeSize = 0;
|
|
||||||
*pSumItemSize = 0;
|
|
||||||
*pZeroInitialized = FALSE;
|
|
||||||
|
|
||||||
const Suballocation& suballoc = *suballocItem;
|
|
||||||
D3D12MA_ASSERT(suballoc.type == 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 and debug margin of previous allocation if present.
|
|
||||||
UINT64 offset = suballoc.offset + (suballocItem == m_Suballocations.cbegin() ? 0 : GetDebugMargin());
|
|
||||||
|
|
||||||
// Apply alignment.
|
|
||||||
offset = AlignUp(offset, allocAlignment);
|
|
||||||
|
|
||||||
// Calculate padding at the beginning based on current offset.
|
|
||||||
const UINT64 paddingBegin = offset - suballoc.offset;
|
|
||||||
|
|
||||||
// Fail if requested size plus margin after is bigger than size of this suballocation.
|
|
||||||
if (paddingBegin + allocSize + GetDebugMargin() > suballoc.size)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// All tests passed: Success. Offset is already filled.
|
|
||||||
*pZeroInitialized = m_ZeroInitializedRange.IsRangeZeroInitialized(offset, offset + allocSize);
|
|
||||||
*pAllocHandle = (AllocHandle)(offset + 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockMetadata_Generic::MergeFreeWithNext(SuballocationList::iterator item)
|
|
||||||
{
|
|
||||||
D3D12MA_ASSERT(item != m_Suballocations.end());
|
|
||||||
D3D12MA_ASSERT(item->type == SUBALLOCATION_TYPE_FREE);
|
|
||||||
|
|
||||||
SuballocationList::iterator nextItem = item;
|
|
||||||
++nextItem;
|
|
||||||
D3D12MA_ASSERT(nextItem != m_Suballocations.end());
|
|
||||||
D3D12MA_ASSERT(nextItem->type == SUBALLOCATION_TYPE_FREE);
|
|
||||||
|
|
||||||
item->size += nextItem->size;
|
|
||||||
--m_FreeCount;
|
|
||||||
m_Suballocations.erase(nextItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
SuballocationList::iterator BlockMetadata_Generic::FreeSuballocation(SuballocationList::iterator suballocItem)
|
|
||||||
{
|
|
||||||
// Change this suballocation to be marked as free.
|
|
||||||
Suballocation& suballoc = *suballocItem;
|
|
||||||
suballoc.type = SUBALLOCATION_TYPE_FREE;
|
|
||||||
suballoc.privateData = 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;
|
|
||||||
|
|
||||||
SuballocationList::iterator nextItem = suballocItem;
|
|
||||||
++nextItem;
|
|
||||||
if ((nextItem != m_Suballocations.end()) && (nextItem->type == SUBALLOCATION_TYPE_FREE))
|
|
||||||
{
|
|
||||||
mergeWithNext = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
SuballocationList::iterator prevItem = suballocItem;
|
|
||||||
if (suballocItem != m_Suballocations.begin())
|
|
||||||
{
|
|
||||||
--prevItem;
|
|
||||||
if (prevItem->type == 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockMetadata_Generic::RegisterFreeSuballocation(SuballocationList::iterator item)
|
|
||||||
{
|
|
||||||
D3D12MA_ASSERT(item->type == SUBALLOCATION_TYPE_FREE);
|
|
||||||
D3D12MA_ASSERT(item->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(ValidateFreeSuballocationList());
|
|
||||||
|
|
||||||
if (item->size >= MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
|
|
||||||
{
|
|
||||||
if (m_FreeSuballocationsBySize.empty())
|
|
||||||
{
|
|
||||||
m_FreeSuballocationsBySize.push_back(item);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_FreeSuballocationsBySize.InsertSorted(item, SuballocationItemSizeLess());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//D3D12MA_HEAVY_ASSERT(ValidateFreeSuballocationList());
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockMetadata_Generic::UnregisterFreeSuballocation(SuballocationList::iterator item)
|
|
||||||
{
|
|
||||||
D3D12MA_ASSERT(item->type == SUBALLOCATION_TYPE_FREE);
|
|
||||||
D3D12MA_ASSERT(item->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(ValidateFreeSuballocationList());
|
|
||||||
|
|
||||||
if (item->size >= MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
|
|
||||||
{
|
|
||||||
SuballocationList::iterator* const it = BinaryFindFirstNotLess(
|
|
||||||
m_FreeSuballocationsBySize.data(),
|
|
||||||
m_FreeSuballocationsBySize.data() + m_FreeSuballocationsBySize.size(),
|
|
||||||
item,
|
|
||||||
SuballocationItemSizeLess());
|
|
||||||
for (size_t index = it - m_FreeSuballocationsBySize.data();
|
|
||||||
index < m_FreeSuballocationsBySize.size();
|
|
||||||
++index)
|
|
||||||
{
|
|
||||||
if (m_FreeSuballocationsBySize[index] == item)
|
|
||||||
{
|
|
||||||
m_FreeSuballocationsBySize.remove(index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
D3D12MA_ASSERT((m_FreeSuballocationsBySize[index]->size == item->size) && "Not found.");
|
|
||||||
}
|
|
||||||
D3D12MA_ASSERT(0 && "Not found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
//D3D12MA_HEAVY_ASSERT(ValidateFreeSuballocationList());
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockMetadata_Generic::SetAllocationPrivateData(AllocHandle allocHandle, void* privateData)
|
|
||||||
{
|
|
||||||
Suballocation& suballoc = *FindAtOffset((UINT64)allocHandle - 1).dropConst();
|
|
||||||
suballoc.privateData = privateData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockMetadata_Generic::AddStatistics(Statistics& inoutStats) const
|
|
||||||
{
|
|
||||||
inoutStats.BlockCount++;
|
|
||||||
inoutStats.AllocationCount += (UINT)m_Suballocations.size() - m_FreeCount;
|
|
||||||
inoutStats.BlockBytes += GetSize();
|
|
||||||
inoutStats.AllocationBytes += GetSize() - m_SumFreeSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockMetadata_Generic::AddDetailedStatistics(DetailedStatistics& inoutStats) const
|
|
||||||
{
|
|
||||||
inoutStats.Stats.BlockCount++;
|
|
||||||
inoutStats.Stats.BlockBytes += GetSize();
|
|
||||||
|
|
||||||
for (const auto& suballoc : m_Suballocations)
|
|
||||||
{
|
|
||||||
if (suballoc.type == SUBALLOCATION_TYPE_FREE)
|
|
||||||
AddDetailedStatisticsUnusedRange(inoutStats, suballoc.size);
|
|
||||||
else
|
|
||||||
AddDetailedStatisticsAllocation(inoutStats, suballoc.size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockMetadata_Generic::WriteAllocationInfoToJson(JsonWriter& json) const
|
|
||||||
{
|
|
||||||
PrintDetailedMap_Begin(json, GetSumFreeSize(), GetAllocationCount(), m_FreeCount);
|
|
||||||
for (const auto& suballoc : m_Suballocations)
|
|
||||||
{
|
|
||||||
if (suballoc.type == SUBALLOCATION_TYPE_FREE)
|
|
||||||
PrintDetailedMap_UnusedRange(json, suballoc.offset, suballoc.size);
|
|
||||||
else
|
|
||||||
PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.size, suballoc.privateData);
|
|
||||||
}
|
|
||||||
PrintDetailedMap_End(json);
|
|
||||||
}
|
|
||||||
#endif // _D3D12MA_BLOCK_METADATA_GENERIC_FUNCTIONS
|
|
||||||
#endif // _D3D12MA_BLOCK_METADATA_GENERIC
|
|
||||||
#endif // #if 0
|
|
||||||
|
|
||||||
#ifndef _D3D12MA_BLOCK_METADATA_LINEAR
|
#ifndef _D3D12MA_BLOCK_METADATA_LINEAR
|
||||||
class BlockMetadata_Linear : public BlockMetadata
|
class BlockMetadata_Linear : public BlockMetadata
|
||||||
{
|
{
|
||||||
@ -7983,16 +7313,8 @@ HRESULT AllocatorPimpl::AllocateCommittedResource(
|
|||||||
}
|
}
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
BOOL wasZeroInitialized = TRUE;
|
|
||||||
#if D3D12MA_CREATE_NOT_ZEROED_AVAILABLE
|
|
||||||
if((committedAllocParams.m_HeapFlags & D3D12_HEAP_FLAG_CREATE_NOT_ZEROED) != 0)
|
|
||||||
{
|
|
||||||
wasZeroInitialized = FALSE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Allocation* alloc = m_AllocationObjectAllocator.Allocate(
|
Allocation* alloc = m_AllocationObjectAllocator.Allocate(
|
||||||
this, resourceSize, createParams.GetBaseResourceDesc()->Alignment, wasZeroInitialized);
|
this, resourceSize, createParams.GetBaseResourceDesc()->Alignment);
|
||||||
alloc->InitCommitted(committedAllocParams.m_List);
|
alloc->InitCommitted(committedAllocParams.m_List);
|
||||||
alloc->SetResourcePointer(res, createParams.GetBaseResourceDesc());
|
alloc->SetResourcePointer(res, createParams.GetBaseResourceDesc());
|
||||||
alloc->SetPrivateData(pPrivateData);
|
alloc->SetPrivateData(pPrivateData);
|
||||||
@ -8051,16 +7373,7 @@ HRESULT AllocatorPimpl::AllocateHeap(
|
|||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
SetResidencyPriority(heap, committedAllocParams.m_ResidencyPriority);
|
SetResidencyPriority(heap, committedAllocParams.m_ResidencyPriority);
|
||||||
|
(*ppAllocation) = m_AllocationObjectAllocator.Allocate(this, allocInfo.SizeInBytes, allocInfo.Alignment);
|
||||||
BOOL wasZeroInitialized = TRUE;
|
|
||||||
#if D3D12MA_CREATE_NOT_ZEROED_AVAILABLE
|
|
||||||
if((heapDesc.Flags & D3D12_HEAP_FLAG_CREATE_NOT_ZEROED) != 0)
|
|
||||||
{
|
|
||||||
wasZeroInitialized = FALSE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
(*ppAllocation) = m_AllocationObjectAllocator.Allocate(this, allocInfo.SizeInBytes, allocInfo.Alignment, wasZeroInitialized);
|
|
||||||
(*ppAllocation)->InitHeap(committedAllocParams.m_List, heap);
|
(*ppAllocation)->InitHeap(committedAllocParams.m_List, heap);
|
||||||
(*ppAllocation)->SetPrivateData(pPrivateData);
|
(*ppAllocation)->SetPrivateData(pPrivateData);
|
||||||
committedAllocParams.m_List->Register(*ppAllocation);
|
committedAllocParams.m_List->Register(*ppAllocation);
|
||||||
@ -9085,7 +8398,7 @@ HRESULT BlockVector::CommitAllocationRequest(
|
|||||||
if (pBlock->m_pMetadata->IsEmpty())
|
if (pBlock->m_pMetadata->IsEmpty())
|
||||||
m_HasEmptyBlock = false;
|
m_HasEmptyBlock = false;
|
||||||
|
|
||||||
*pAllocation = m_hAllocator->GetAllocationObjectAllocator().Allocate(m_hAllocator, size, alignment, allocRequest.zeroInitialized);
|
*pAllocation = m_hAllocator->GetAllocationObjectAllocator().Allocate(m_hAllocator, size, alignment);
|
||||||
pBlock->m_pMetadata->Alloc(allocRequest, size, *pAllocation);
|
pBlock->m_pMetadata->Alloc(allocRequest, size, *pAllocation);
|
||||||
|
|
||||||
(*pAllocation)->InitPlaced(allocRequest.allocHandle, pBlock);
|
(*pAllocation)->InitPlaced(allocRequest.allocHandle, pBlock);
|
||||||
@ -10023,7 +9336,7 @@ void Allocation::ReleaseThis()
|
|||||||
m_Allocator->GetAllocationObjectAllocator().Free(this);
|
m_Allocator->GetAllocationObjectAllocator().Free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Allocation::Allocation(AllocatorPimpl* allocator, UINT64 size, UINT64 alignment, BOOL wasZeroInitialized)
|
Allocation::Allocation(AllocatorPimpl* allocator, UINT64 size, UINT64 alignment)
|
||||||
: m_Allocator{ allocator },
|
: m_Allocator{ allocator },
|
||||||
m_Size{ size },
|
m_Size{ size },
|
||||||
m_Alignment{ alignment },
|
m_Alignment{ alignment },
|
||||||
@ -10037,7 +9350,6 @@ Allocation::Allocation(AllocatorPimpl* allocator, UINT64 size, UINT64 alignment,
|
|||||||
m_PackedData.SetResourceDimension(D3D12_RESOURCE_DIMENSION_UNKNOWN);
|
m_PackedData.SetResourceDimension(D3D12_RESOURCE_DIMENSION_UNKNOWN);
|
||||||
m_PackedData.SetResourceFlags(D3D12_RESOURCE_FLAG_NONE);
|
m_PackedData.SetResourceFlags(D3D12_RESOURCE_FLAG_NONE);
|
||||||
m_PackedData.SetTextureLayout(D3D12_TEXTURE_LAYOUT_UNKNOWN);
|
m_PackedData.SetTextureLayout(D3D12_TEXTURE_LAYOUT_UNKNOWN);
|
||||||
m_PackedData.SetWasZeroInitialized(wasZeroInitialized);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Allocation::InitCommitted(CommittedAllocationList* list)
|
void Allocation::InitCommitted(CommittedAllocationList* list)
|
||||||
@ -10071,7 +9383,6 @@ void Allocation::SwapBlockAllocation(Allocation* allocation)
|
|||||||
D3D12MA_ASSERT(allocation->m_PackedData.GetType() == TYPE_PLACED);
|
D3D12MA_ASSERT(allocation->m_PackedData.GetType() == TYPE_PLACED);
|
||||||
|
|
||||||
D3D12MA_SWAP(m_Resource, allocation->m_Resource);
|
D3D12MA_SWAP(m_Resource, allocation->m_Resource);
|
||||||
m_PackedData.SetWasZeroInitialized(allocation->m_PackedData.WasZeroInitialized());
|
|
||||||
m_Placed.block->m_pMetadata->SetAllocationPrivateData(m_Placed.allocHandle, allocation);
|
m_Placed.block->m_pMetadata->SetAllocationPrivateData(m_Placed.allocHandle, allocation);
|
||||||
D3D12MA_SWAP(m_Placed, allocation->m_Placed);
|
D3D12MA_SWAP(m_Placed, allocation->m_Placed);
|
||||||
m_Placed.block->m_pMetadata->SetAllocationPrivateData(m_Placed.allocHandle, this);
|
m_Placed.block->m_pMetadata->SetAllocationPrivateData(m_Placed.allocHandle, this);
|
||||||
|
140
src/Tests.cpp
140
src/Tests.cpp
@ -1834,145 +1834,6 @@ static void TestTransfer(const TestContext& ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TestZeroInitialized(const TestContext& ctx)
|
|
||||||
{
|
|
||||||
wprintf(L"Test zero initialized\n");
|
|
||||||
|
|
||||||
const UINT64 bufSize = 128ull * 1024;
|
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC resourceDesc;
|
|
||||||
FillResourceDescForBuffer(resourceDesc, bufSize);
|
|
||||||
|
|
||||||
// # Create upload buffer and fill it with data.
|
|
||||||
|
|
||||||
D3D12MA::ALLOCATION_DESC allocDescUpload = {};
|
|
||||||
allocDescUpload.HeapType = D3D12_HEAP_TYPE_UPLOAD;
|
|
||||||
|
|
||||||
ResourceWithAllocation bufUpload;
|
|
||||||
CHECK_HR( ctx.allocator->CreateResource(
|
|
||||||
&allocDescUpload,
|
|
||||||
&resourceDesc,
|
|
||||||
D3D12_RESOURCE_STATE_GENERIC_READ,
|
|
||||||
NULL,
|
|
||||||
&bufUpload.allocation,
|
|
||||||
IID_PPV_ARGS(&bufUpload.resource)) );
|
|
||||||
|
|
||||||
{
|
|
||||||
void* mappedPtr = nullptr;
|
|
||||||
CHECK_HR( bufUpload.resource->Map(0, &EMPTY_RANGE, &mappedPtr) );
|
|
||||||
FillData(mappedPtr, bufSize, 5236245);
|
|
||||||
bufUpload.resource->Unmap(0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// # Create readback buffer
|
|
||||||
|
|
||||||
D3D12MA::ALLOCATION_DESC allocDescReadback = {};
|
|
||||||
allocDescReadback.HeapType = D3D12_HEAP_TYPE_READBACK;
|
|
||||||
|
|
||||||
ResourceWithAllocation bufReadback;
|
|
||||||
CHECK_HR( ctx.allocator->CreateResource(
|
|
||||||
&allocDescReadback,
|
|
||||||
&resourceDesc,
|
|
||||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
|
||||||
NULL,
|
|
||||||
&bufReadback.allocation,
|
|
||||||
IID_PPV_ARGS(&bufReadback.resource)) );
|
|
||||||
|
|
||||||
auto CheckBufferData = [&](const ResourceWithAllocation& buf)
|
|
||||||
{
|
|
||||||
const bool shouldBeZero = buf.allocation->WasZeroInitialized() != FALSE;
|
|
||||||
|
|
||||||
{
|
|
||||||
ID3D12GraphicsCommandList* cmdList = BeginCommandList();
|
|
||||||
cmdList->CopyBufferRegion(bufReadback.resource.Get(), 0, buf.resource.Get(), 0, bufSize);
|
|
||||||
EndCommandList(cmdList);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isZero = false;
|
|
||||||
{
|
|
||||||
const D3D12_RANGE readRange{0, bufSize}; // I could pass pReadRange = NULL but it generates D3D Debug layer warning: EXECUTION WARNING #930: MAP_INVALID_NULLRANGE
|
|
||||||
void* mappedPtr = nullptr;
|
|
||||||
CHECK_HR( bufReadback.resource->Map(0, &readRange, &mappedPtr) );
|
|
||||||
isZero = ValidateDataZero(mappedPtr, bufSize);
|
|
||||||
bufReadback.resource->Unmap(0, &EMPTY_RANGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
wprintf(L"Should be zero: %u, is zero: %u\n", shouldBeZero ? 1 : 0, isZero ? 1 : 0);
|
|
||||||
|
|
||||||
if(shouldBeZero)
|
|
||||||
{
|
|
||||||
CHECK_BOOL(isZero);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// # Test 1: Committed resource. Should always be zero initialized.
|
|
||||||
|
|
||||||
{
|
|
||||||
D3D12MA::ALLOCATION_DESC allocDescDefault = {};
|
|
||||||
allocDescDefault.HeapType = D3D12_HEAP_TYPE_DEFAULT;
|
|
||||||
allocDescDefault.Flags = D3D12MA::ALLOCATION_FLAG_COMMITTED;
|
|
||||||
|
|
||||||
ResourceWithAllocation bufDefault;
|
|
||||||
CHECK_HR( ctx.allocator->CreateResource(
|
|
||||||
&allocDescDefault,
|
|
||||||
&resourceDesc,
|
|
||||||
D3D12_RESOURCE_STATE_COPY_SOURCE,
|
|
||||||
NULL,
|
|
||||||
&bufDefault.allocation,
|
|
||||||
IID_PPV_ARGS(&bufDefault.resource)) );
|
|
||||||
|
|
||||||
wprintf(L" Committed: ");
|
|
||||||
CheckBufferData(bufDefault);
|
|
||||||
CHECK_BOOL( bufDefault.allocation->WasZeroInitialized() );
|
|
||||||
}
|
|
||||||
|
|
||||||
// # Test 2: (Probably) placed resource.
|
|
||||||
|
|
||||||
ResourceWithAllocation bufDefault;
|
|
||||||
for(uint32_t i = 0; i < 2; ++i)
|
|
||||||
{
|
|
||||||
// 1. Create buffer
|
|
||||||
|
|
||||||
D3D12MA::ALLOCATION_DESC allocDescDefault = {};
|
|
||||||
allocDescDefault.HeapType = D3D12_HEAP_TYPE_DEFAULT;
|
|
||||||
|
|
||||||
CHECK_HR( ctx.allocator->CreateResource(
|
|
||||||
&allocDescDefault,
|
|
||||||
&resourceDesc,
|
|
||||||
D3D12_RESOURCE_STATE_COPY_SOURCE,
|
|
||||||
NULL,
|
|
||||||
&bufDefault.allocation,
|
|
||||||
IID_PPV_ARGS(&bufDefault.resource)) );
|
|
||||||
|
|
||||||
// 2. Check it
|
|
||||||
|
|
||||||
wprintf(L" Normal #%u: ", i);
|
|
||||||
CheckBufferData(bufDefault);
|
|
||||||
|
|
||||||
// 3. Upload some data to it
|
|
||||||
|
|
||||||
{
|
|
||||||
ID3D12GraphicsCommandList* cmdList = BeginCommandList();
|
|
||||||
|
|
||||||
D3D12_RESOURCE_BARRIER barrier = {};
|
|
||||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
|
||||||
barrier.Transition.pResource = bufDefault.resource.Get();
|
|
||||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
|
||||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
|
|
||||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
|
||||||
cmdList->ResourceBarrier(1, &barrier);
|
|
||||||
|
|
||||||
cmdList->CopyBufferRegion(bufDefault.resource.Get(), 0, bufUpload.resource.Get(), 0, bufSize);
|
|
||||||
|
|
||||||
EndCommandList(cmdList);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Delete it
|
|
||||||
|
|
||||||
bufDefault.Reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TestMultithreading(const TestContext& ctx)
|
static void TestMultithreading(const TestContext& ctx)
|
||||||
{
|
{
|
||||||
wprintf(L"Test multithreading\n");
|
wprintf(L"Test multithreading\n");
|
||||||
@ -4381,7 +4242,6 @@ static void TestGroupBasics(const TestContext& ctx)
|
|||||||
TestMapping(ctx);
|
TestMapping(ctx);
|
||||||
TestStats(ctx);
|
TestStats(ctx);
|
||||||
TestTransfer(ctx);
|
TestTransfer(ctx);
|
||||||
TestZeroInitialized(ctx);
|
|
||||||
TestMultithreading(ctx);
|
TestMultithreading(ctx);
|
||||||
TestLinearAllocator(ctx);
|
TestLinearAllocator(ctx);
|
||||||
TestLinearAllocatorMultiBlock(ctx);
|
TestLinearAllocatorMultiBlock(ctx);
|
||||||
|
Loading…
Reference in New Issue
Block a user