Add documentation chapter "Virtual allocator"
diff --git a/src/D3D12MemAlloc.h b/src/D3D12MemAlloc.h
index a40aa4f..84a1fbb 100644
--- a/src/D3D12MemAlloc.h
+++ b/src/D3D12MemAlloc.h
@@ -24,7 +24,7 @@
 

 /** \mainpage D3D12 Memory Allocator

 

-<b>Version 2.0.0-development</b> (2020-06-15)

+<b>Version 2.0.0-development</b> (2020-07-16)

 

 Copyright (c) 2019-2020 Advanced Micro Devices, Inc. All rights reserved. \n

 License: MIT

@@ -39,6 +39,7 @@
         - [Creating resources](@ref quick_start_creating_resources)

         - [Mapping memory](@ref quick_start_mapping_memory)

     - \subpage reserving_memory

+    - \subpage virtual_allocator

 - \subpage configuration

   - [Custom CPU memory allocator](@ref custom_memory_allocator)

 - \subpage general_considerations

@@ -273,6 +274,158 @@
   Only placed resources are considered.

 

 

+\page virtual_allocator Virtual allocator

+

+As an extra feature, the core allocation algorithm of the library is exposed through a simple and convenient API of "virtual allocator".

+It doesn't allocate any real GPU memory. It just keeps track of used and free regions of a "virtual block".

+You can use it to allocate your own memory or other objects, even completely unrelated to D3D12.

+A common use case is sub-allocation of pieces of one large GPU buffer.

+

+\section virtual_allocator_creating_virtual_block Creating virtual block

+

+To use this functionality, there is no main "allocator" object.

+You don't need to have D3D12MA::Allocator object created.

+All you need to do is to create a separate D3D12MA::VirtualBlock object for each block of memory you want to be managed by the allocator:

+

+-# Fill in D3D12MA::ALLOCATOR_DESC structure.

+-# Call D3D12MA::CreateVirtualBlock. Get new D3D12MA::VirtualBlock object.

+

+Example:

+

+\code

+D3D12MA::VIRTUAL_BLOCK_DESC blockDesc = {};

+blockDesc.Size = 1048576; // 1 MB

+

+D3D12MA::VirtualBlock *block;

+HRESULT hr = CreateVirtualBlock(&blockDesc, &block);

+\endcode

+

+\section virtual_allocator_making_virtual_allocations Making virtual allocations

+

+D3D12MA::VirtualBlock object contains internal data structure that keeps track of free and occupied regions

+using the same code as the main D3D12 memory allocator.

+However, there is no "virtual allocation" object.

+When you request a new allocation, a `UINT64` number is returned.

+It is an offset inside the block where the allocation has been placed, but it also uniquely identifies the allocation within this block.

+

+In order to make an allocation:

+

+-# Fill in D3D12MA::VIRTUAL_ALLOCATION_DESC structure.

+-# Call D3D12MA::VirtualBlock::Allocate. Get new `UINT64 offset` that identifies the allocation.

+

+Example:

+

+\code

+D3D12MA::VIRTUAL_ALLOCATION_DESC allocDesc = {};

+allocDesc.Size = 4096; // 4 KB

+

+UINT64 allocOffset;

+hr = block->Allocate(&allocDesc, &allocOffset);

+if(SUCCEEDED(hr))

+{

+    // Use the 4 KB of your memory starting at allocOffset.

+}

+else

+{

+    // Allocation failed - no space for it could be found. Handle this error!

+}

+\endcode

+

+\section virtual_allocator_deallocation Deallocation

+

+When no longer needed, an allocation can be freed by calling D3D12MA::VirtualBlock::FreeAllocation.

+You can only pass to this function the exact offset that was previously returned by D3D12MA::VirtualBlock::Allocate

+and not any other location within the memory.

+

+When whole block is no longer needed, the block object can be released by calling D3D12MA::VirtualBlock::Release.

+All allocations must be freed before the block is destroyed, which is checked internally by an assert.

+However, if you don't want to call `block->FreeAllocation` for each allocation, you can use D3D12MA::VirtualBlock::Clear to free them all at once -

+a feature not available in normal D3D12 memory allocator. Example:

+

+\code

+block->FreeAllocation(allocOffset);

+block->Release();

+\endcode

+

+\section virtual_allocator_allocation_parameters Allocation parameters

+

+You can attach a custom pointer to each allocation by using D3D12MA::VirtualBlock::SetAllocationUserData.

+Its default value is `NULL`.

+It can be used to store any data that needs to be associated with that allocation - e.g. an index, a handle, or a pointer to some

+larger data structure containing more information. Example:

+

+\code

+struct CustomAllocData

+{

+    std::string m_AllocName;

+};

+CustomAllocData* allocData = new CustomAllocData();

+allocData->m_AllocName = "My allocation 1";

+block->SetAllocationUserData(allocOffset, allocData);

+\endcode

+

+The pointer can later be fetched, along with allocation size, by passing the allocation offset to function

+D3D12MA::VirtualBlock::GetAllocationInfo and inspecting returned structure D3D12MA::VIRTUAL_ALLOCATION_INFO.

+If you allocated a new object to be used as the custom pointer, don't forget to delete that object before freeing the allocation!

+Example:

+

+\code

+VIRTUAL_ALLOCATION_INFO allocInfo;

+block->GetAllocationInfo(allocOffset, &allocInfo);

+delete (CustomAllocData*)allocInfo.pUserData;

+

+block->FreeAllocation(allocOffset);

+\endcode

+

+\section virtual_allocator_alignment_and_units Alignment and units

+

+It feels natural to express sizes and offsets in bytes.

+If an offset of an allocation needs to be aligned to a multiply of some number (e.g. 4 bytes), you can fill optional member

+D3D12MA::VIRTUAL_ALLOCATION_DESC::Alignment to request it. Example:

+

+\code

+D3D12MA::VIRTUAL_ALLOCATION_DESC allocDesc = {};

+allocDesc.Size = 4096; // 4 KB

+allocDesc.Alignment = 4; // Returned offset must be a multiply of 4 B

+

+UINT64 allocOffset;

+hr = block->Allocate(&allocDesc, &allocOffset);

+\endcode

+

+Alignments of different allocations made from one block may vary.

+However, if all alignments and sizes are always multiply of some size e.g. 4 B or `sizeof(MyDataStruct)`,

+you can express all sizes, alignments, and offsets in multiples of that size instead of individual bytes.

+It might be more convenient, but you need to make sure to use this new unit consistently in all the places:

+

+- D3D12MA::VIRTUAL_BLOCK_DESC::Size

+- D3D12MA::VIRTUAL_ALLOCATION_DESC::Size and D3D12MA::VIRTUAL_ALLOCATION_DESC::Alignment

+- Using offset returned by D3D12MA::VirtualBlock::Allocate

+

+\section virtual_allocator_statistics Statistics

+

+You can obtain statistics of a virtual block using D3D12MA::VirtualBlock::CalculateStats.

+The function fills structure D3D12MA::StatInfo - same as used by the normal D3D12 memory allocator.

+Example:

+

+\code

+D3D12MA::StatInfo statInfo;

+block->CalculateStats(&statInfo);

+printf("My virtual block has %llu bytes used by %u virtual allocations\n",

+    statInfo.UsedBytes, statInfo.AllocationCount);

+\endcode

+

+You can also request a full list of allocations and free regions as a string in JSON format by calling

+D3D12MA::VirtualBlock::BuildStatsString.

+Returned string must be later freed using D3D12MA::VirtualBlock::FreeStatsString.

+The format of this string may differ from the one returned by the main D3D12 allocator, but it is similar.

+

+\section virtual_allocator_additional_considerations Additional considerations

+

+Note that the "virtual allocator" functionality is implemented on a level of individual memory blocks.

+Keeping track of a whole collection of blocks, allocating new ones when out of free space,

+deleting empty ones, and deciding which one to try first for a new allocation must be implemented by the user.

+

+

 \page configuration Configuration

 

 Please check file `D3D12MemAlloc.cpp` lines between "Configuration Begin" and