Skip to content

Commit

Permalink
Remove Usage of std::set in ResidencySet
Browse files Browse the repository at this point in the history
Removes usage of std::set in ResidencySet and replaces it with a vector.
This does allow duplicat heaps to be inserted into the ResidencySet,
however insertion will be O(1) instead of O(log(n)) and instead we can
easily identify duplicate heaps by checking their last used fence value
when when they are iterated.
  • Loading branch information
bjjones committed Aug 1, 2022
1 parent 82f472d commit 4c85289
Show file tree
Hide file tree
Showing 15 changed files with 182 additions and 53 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ GPUs do not support page-faulting, so it's up the GPU application to avoid using
physical GPU memory. GPGMM integrates residency into the resource allocators to simplify and optimize allocation:

```cpp
gpgmm::d3d12::ResidencySet set;
gpgmm::d3d12::ResidencyList list;
set.Insert(allocation->GetMemory());

residency->ExecuteCommandList(&queue, &commandList, &set, 1);
residency->ExecuteCommandList(&queue, &commandList, &list, 1);

// Prepare for next frame.
set.Reset();
Expand Down
4 changes: 2 additions & 2 deletions src/gpgmm/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,10 @@ source_set("gpgmm_sources") {
"d3d12/IUnknownImplD3D12.h",
"d3d12/JSONSerializerD3D12.cpp",
"d3d12/JSONSerializerD3D12.h",
"d3d12/ResidencyListD3D12.cpp",
"d3d12/ResidencyListD3D12.h",
"d3d12/ResidencyManagerD3D12.cpp",
"d3d12/ResidencyManagerD3D12.h",
"d3d12/ResidencySetD3D12.cpp",
"d3d12/ResidencySetD3D12.h",
"d3d12/ResourceAllocationD3D12.cpp",
"d3d12/ResourceAllocationD3D12.h",
"d3d12/ResourceAllocatorD3D12.cpp",
Expand Down
4 changes: 2 additions & 2 deletions src/gpgmm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ if (GPGMM_ENABLE_D3D12)
"d3d12/IUnknownImplD3D12.h"
"d3d12/JSONSerializerD3D12.cpp"
"d3d12/JSONSerializerD3D12.h"
"d3d12/ResidencyListD3D12.cpp"
"d3d12/ResidencyListD3D12.h"
"d3d12/ResidencyManagerD3D12.cpp"
"d3d12/ResidencyManagerD3D12.h"
"d3d12/ResidencySetD3D12.cpp"
"d3d12/ResidencySetD3D12.h"
"d3d12/ResourceAllocationD3D12.cpp"
"d3d12/ResourceAllocationD3D12.h"
"d3d12/ResourceAllocatorD3D12.cpp"
Expand Down
2 changes: 1 addition & 1 deletion src/gpgmm/d3d12/HeapD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

namespace gpgmm::d3d12 {

class ResidencySet;
class ResidencyList;
class ResidencyManager;
class ResourceAllocator;

Expand Down
16 changes: 8 additions & 8 deletions src/gpgmm/d3d12/JSONSerializerD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

#include "gpgmm/common/TraceEvent.h"
#include "gpgmm/d3d12/HeapD3D12.h"
#include "gpgmm/d3d12/ResidencyListD3D12.h"
#include "gpgmm/d3d12/ResidencyManagerD3D12.h"
#include "gpgmm/d3d12/ResidencySetD3D12.h"
#include "gpgmm/d3d12/ResourceAllocationD3D12.h"
#include "gpgmm/d3d12/ResourceAllocatorD3D12.h"
#include "gpgmm/d3d12/UtilsD3D12.h"
Expand Down Expand Up @@ -230,22 +230,22 @@ namespace gpgmm::d3d12 {
// static
JSONDict JSONSerializer::Serialize(const EXECUTE_COMMAND_LISTS_DESC& desc) {
JSONDict dict;
JSONArray residencySets;
JSONArray residencyLists;
for (uint64_t i = 0; i < desc.Count; i++) {
JSONDict residencySetDict;
JSONDict residencyListDict;
JSONArray heapArray;
for (const auto& heap : *desc.ResidencySets[i]) {
for (const auto& heap : *desc.ResidencyLists[i]) {
heapArray.AddItem(gpgmm::JSONSerializer::Serialize(heap));
}
if (!heapArray.IsEmpty()) {
residencySetDict.AddItem("Heaps", heapArray);
residencyListDict.AddItem("Heaps", heapArray);
}

residencySets.AddItem(residencySetDict);
residencyLists.AddItem(residencyListDict);
}

if (!residencySets.IsEmpty()) {
dict.AddItem("ResidencySets", residencySets);
if (!residencyLists.IsEmpty()) {
dict.AddItem("ResidencyLists", residencyLists);
}

return dict;
Expand Down
4 changes: 2 additions & 2 deletions src/gpgmm/d3d12/JSONSerializerD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace gpgmm::d3d12 {
struct HEAP_INFO;
struct RESOURCE_ALLOCATION_DESC;
struct RESOURCE_ALLOCATION_INFO;
class ResidencySet;
class ResidencyList;
struct RESIDENCY_DESC;

// Declare backend aliases.
Expand All @@ -47,7 +47,7 @@ namespace gpgmm::d3d12 {
};

struct EXECUTE_COMMAND_LISTS_DESC {
ResidencySet* const* ResidencySets;
ResidencyList* const* ResidencyLists;
uint32_t Count;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,46 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include "gpgmm/d3d12/ResidencySetD3D12.h"
#include "gpgmm/d3d12/ResidencyListD3D12.h"

#include "gpgmm/common/TraceEvent.h"

namespace gpgmm::d3d12 {

ResidencyList::ResidencyList() {
GPGMM_TRACE_EVENT_OBJECT_NEW(this);
}

ResidencyList::~ResidencyList() {
GPGMM_TRACE_EVENT_OBJECT_DESTROY(this);
}

HRESULT ResidencyList::Add(Heap* pHeap) {
if (pHeap == nullptr) {
return E_INVALIDARG;
}

mList.push_back(pHeap);
return S_OK;
}

HRESULT ResidencyList::Reset() {
mList.clear();
return S_OK;
}

ResidencyList::UnderlyingType::const_iterator ResidencyList::begin() const {
return mList.begin();
}

ResidencyList::UnderlyingType::const_iterator ResidencyList::end() const {
return mList.end();
}

const char* ResidencyList::GetTypename() const {
return "ResidencyList";
}

ResidencySet::ResidencySet() {
GPGMM_TRACE_EVENT_OBJECT_NEW(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,66 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef GPGMM_D3D12_RESIDENCYSETD3D12_H_
#define GPGMM_D3D12_RESIDENCYSETD3D12_H_
#ifndef GPGMM_D3D12_RESIDENCYLISTD3D12_H_
#define GPGMM_D3D12_RESIDENCYLISTD3D12_H_

#include "gpgmm/d3d12/d3d12_platform.h"
#include "include/gpgmm_export.h"

#include <set>
#include <vector>

namespace gpgmm::d3d12 {

class Heap;

/** \brief Represents a list of heaps which will be "made resident" when executing a
command-list.
A residency set helps track heaps for residency which will be referenced together by a
command-list. The application uses a ResidencyList by inserting heaps, by calling
ResourceAllocation::GetMemory, into the list. Once ResidencyManager::ExecuteCommandLists is
called, the list can be reset or cleared for the next frame.
Without a ResidencyList, the application would need to manually ResidencyManager::LockHeap and
ResidencyManager::UnlockHeap each heap before and after ResidencyManager::ExecuteCommandLists,
respectively.
*/
class GPGMM_EXPORT ResidencyList final {
public:
/** \brief Create a residency list or collection of heaps to manage together for residency.
*/
ResidencyList();
~ResidencyList();

ResidencyList(const ResidencyList&) = default;
ResidencyList& operator=(const ResidencyList&) = default;

/** \brief Adds a heap to the residency list.
@param pHeap A pointer to Heap about to be added.
\return S_OK if heap was added, else error.
*/
HRESULT Add(Heap* pHeap);

/** \brief Reset this residency set.
Removes all heaps from the set so the set can be re-used.
*/
HRESULT Reset();

using UnderlyingType = std::vector<Heap*>;

UnderlyingType::const_iterator begin() const;
UnderlyingType::const_iterator end() const;

private:
const char* GetTypename() const;

UnderlyingType mList;
};

/** \brief Represents a set of heaps which will be "made resident" when executing a
command-list.
Expand All @@ -35,6 +83,8 @@ namespace gpgmm::d3d12 {
Without a ResidencySet, the application would need to manually ResidencyManager::LockHeap and
ResidencyManager::UnlockHeap each heap before and after ResidencyManager::ExecuteCommandLists,
respectively.
\deprecated Use ResidencyList instead of ResidencySet.
*/
class GPGMM_EXPORT ResidencySet final {
public:
Expand Down
40 changes: 35 additions & 5 deletions src/gpgmm/d3d12/ResidencyManagerD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#include "gpgmm/d3d12/FenceD3D12.h"
#include "gpgmm/d3d12/HeapD3D12.h"
#include "gpgmm/d3d12/JSONSerializerD3D12.h"
#include "gpgmm/d3d12/ResidencySetD3D12.h"
#include "gpgmm/d3d12/ResidencyListD3D12.h"
#include "gpgmm/d3d12/UtilsD3D12.h"
#include "gpgmm/utils/Math.h"

Expand Down Expand Up @@ -565,12 +565,36 @@ namespace gpgmm::d3d12 {
return S_OK;
}

/** \brief Execute command lists using residency managed heaps.
*
/deprecated use ResidencyList instead of ResidencySet
*/
HRESULT ResidencyManager::ExecuteCommandLists(ID3D12CommandQueue* pQueue,
ID3D12CommandList* const* ppCommandLists,
ResidencySet* const* ppResidencySets,
uint32_t count) {
ResidencyList residencyList;

// TODO: support multiple command lists.
if (count > 1) {
return E_NOTIMPL;
}

for (Heap* heap : *ppResidencySets[0]) {
residencyList.Add(heap);
}

ResidencyList* residencyListPtr = &residencyList;

return ExecuteCommandLists(pQueue, ppCommandLists, &residencyListPtr, count);
}

// Given a list of heaps that are pending usage, this function will estimate memory needed,
// evict resources until enough space is available, then make resident any heaps scheduled for
// usage.
HRESULT ResidencyManager::ExecuteCommandLists(ID3D12CommandQueue* pQueue,
ID3D12CommandList* const* ppCommandLists,
ResidencySet* const* ppResidencySets,
ResidencyList* const* ppResidencyLists,
uint32_t count) {
TRACE_EVENT0(TraceEventCategory::Default, "ResidencyManager.ExecuteCommandLists");

Expand All @@ -585,19 +609,25 @@ namespace gpgmm::d3d12 {
return E_NOTIMPL;
}

ResidencySet* residencySet = ppResidencySets[0];
ResidencyList* residencyList = ppResidencyLists[0];

std::vector<ID3D12Pageable*> localHeapsToMakeResident;
std::vector<ID3D12Pageable*> nonLocalHeapsToMakeResident;
uint64_t localSizeToMakeResident = 0;
uint64_t nonLocalSizeToMakeResident = 0;

for (Heap* heap : *residencySet) {
for (Heap* heap : *residencyList) {
// Heaps that are locked resident are not tracked in the LRU cache.
if (heap->IsResidencyLocked()) {
continue;
}

// ResidencyList can contain duplicates. We can skip them by checking if the heap's last
// used fence is the same as the current one.
if (heap->GetLastUsedFenceValue() == mFence->GetCurrentFence()) {
continue;
}

if (heap->IsInResidencyLRUCache()) {
// If the heap is already in the LRU, we must remove it and append again below to
// update its position in the LRU.
Expand Down Expand Up @@ -657,7 +687,7 @@ namespace gpgmm::d3d12 {
}

GPGMM_TRACE_EVENT_OBJECT_CALL("ResidencyManager.ExecuteCommandLists",
(EXECUTE_COMMAND_LISTS_DESC{ppResidencySets, count}));
(EXECUTE_COMMAND_LISTS_DESC{ppResidencyLists, count}));

return S_OK;
}
Expand Down
21 changes: 19 additions & 2 deletions src/gpgmm/d3d12/ResidencyManagerD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ namespace gpgmm::d3d12 {

class Fence;
class Heap;
class ResidencyList;
class ResidencySet;
class ResourceAllocator;

Expand Down Expand Up @@ -140,7 +141,7 @@ namespace gpgmm::d3d12 {
A Heap is considered "resident" when it is accessible by the GPU. A Heap can be made explicitly
resident by calling ResidencyManager::LockHeap or implicitly resident by using the Heap with a
ResidencySet upon calling ResidencyManager::ExecuteCommandLists or through a
ResidencyList upon calling ResidencyManager::ExecuteCommandLists or through a
operation that always requires the Heap to be resident (eg. Map, Unmap).
Internally, the ResidencyManager keeps the application in-budget by calling ID3D12Device::Evict
Expand Down Expand Up @@ -180,12 +181,28 @@ namespace gpgmm::d3d12 {

/** \brief Execute command lists using residency managed heaps.
Submits an array of command lists and residency lists for the specified command queue.
@param pQueue The command queue to submit to.
@param ppCommandLists The array of ID3D12CommandList command lists to be executed.
@param ppResidencyLists The array of ResidencyList residency lists to make resident.
@param count The size of commandLists and residencyLists arrays.
*/
HRESULT ExecuteCommandLists(ID3D12CommandQueue* pQueue,
ID3D12CommandList* const* ppCommandLists,
ResidencyList* const* ppResidencyLists,
uint32_t count);

/** \brief Execute command lists using residency managed heaps.
Submits an array of command lists and residency sets for the specified command queue.
@param pQueue The command queue to submit to.
@param ppCommandLists The array of ID3D12CommandList command lists to be executed.
@param ppResidencySets The array of ResidencySet residency sets to make resident.
@param count The size of commandLists and residencySets arrays.
@param count The size of commandLists and residencyLists arrays.
/deprecated Use ResidencyList instead of ResidencySet.
*/
HRESULT ExecuteCommandLists(ID3D12CommandQueue* pQueue,
ID3D12CommandList* const* ppCommandLists,
Expand Down
2 changes: 1 addition & 1 deletion src/gpgmm/d3d12/ResourceAllocationD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
#include "gpgmm/d3d12/ErrorD3D12.h"
#include "gpgmm/d3d12/HeapD3D12.h"
#include "gpgmm/d3d12/JSONSerializerD3D12.h"
#include "gpgmm/d3d12/ResidencyListD3D12.h"
#include "gpgmm/d3d12/ResidencyManagerD3D12.h"
#include "gpgmm/d3d12/ResidencySetD3D12.h"
#include "gpgmm/d3d12/UtilsD3D12.h"

#include <utility>
Expand Down
2 changes: 1 addition & 1 deletion src/gpgmm/d3d12/ResourceAllocationD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace gpgmm::d3d12 {
class DebugResourceAllocator;
class Heap;
class ResidencyManager;
class ResidencySet;
class ResidencyList;

/** \struct RESOURCE_ALLOCATION_DESC
Describes a resource allocation.
Expand Down
2 changes: 1 addition & 1 deletion src/include/gpgmm_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
// clang-format off

#include "gpgmm/d3d12/HeapD3D12.h"
#include "gpgmm/d3d12/ResidencySetD3D12.h"
#include "gpgmm/d3d12/ResidencyListD3D12.h"
#include "gpgmm/d3d12/ResidencyManagerD3D12.h"
#include "gpgmm/d3d12/ResourceAllocationD3D12.h"
#include "gpgmm/d3d12/ResourceAllocatorD3D12.h"
Expand Down
Loading

0 comments on commit 4c85289

Please sign in to comment.