Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 72 additions & 51 deletions .github/workflows/.patches/dawn.diff

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -864,7 +864,7 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.

INPUT = src/gpgmm
INPUT = src

# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
Expand Down
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,31 +33,32 @@ allocatorDesc.Adapter = Adapter;
// Use CheckFeatureSupport
allocatorDesc.ResourceHeapTier = D3D12_RESOURCE_HEAP_TIER_1;

ComPtr<gpgmm::d3d12::ResidencyManager> residency; // Optional
ComPtr<gpgmm::d3d12::ResourceAllocator> allocator;
gpgmm::d3d12::ResourceAllocator::CreateResourceAllocator(desc, &allocator, &residency);
ComPtr<gpgmm::d3d12::IResidencyManager> residency; // Optional
ComPtr<gpgmm::d3d12::IResourceAllocator> allocator;
gpgmm::d3d12::CreateResourceAllocator(desc, &allocator, &residency);
```

```cpp
D3D12_RESOURCE_DESC& resourceDesc = {};
D3D12_RESOURCE_STATES initialState = {}
gpgmm::d3d12::ALLOCATION_DESC allocationDesc = {};

ComPtr<gpgmm::d3d12::ResourceAllocation> allocation;
ComPtr<gpgmm::d3d12::IResourceAllocation> allocation;
allocator->CreateResource(allocationDesc, resourceDesc, initialState, nullptr, &allocation);
```

GPUs do not support page-faulting, so it's up the GPU application to avoid using too much
physical GPU memory. GPGMM integrates residency into the resource allocators to simplify and optimize allocation:

```cpp
gpgmm::d3d12::ResidencyList list;
list.Add(allocation->GetMemory());
ComPtr<gpgmm::d3d12::IResidencyList> list;
CreateResidencyList(&list);
list->Add(allocation->GetMemory());

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

// Prepare for next frame.
list.Reset();
list->Reset();
```

Residency also works for non-resources too:
Expand All @@ -67,8 +68,8 @@ gpgmm::d3d12::HEAP_DESC shaderVisibleHeap = {};
shaderVisibleHeap.SizeInBytes = kHeapSize;
shaderVisibleHeap.MemorySegmentGroup = DXGI_MEMORY_SEGMENT_GROUP_LOCAL;

ComPtr<gpgmm::d3d12::Heap> descriptorHeap;
gpgmm::d3d12::Heap::CreateHeap(shaderVisibleHeap, residencyManager,
ComPtr<gpgmm::d3d12::IHeap> descriptorHeap;
gpgmm::d3d12::CreateHeap(shaderVisibleHeap, residencyManager,
[&](ID3D12Pageable** ppPageableOut) -> HRESULT {
ComPtr<ID3D12DescriptorHeap> heap;
mDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&heap));
Expand Down
2 changes: 2 additions & 0 deletions src/fuzzers/D3D12Fuzzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

#include <gpgmm_d3d12.h>

using Microsoft::WRL::ComPtr;

uint64_t UInt8ToUInt64(const uint8_t* src);

HRESULT CreateResourceAllocatorDesc(gpgmm::d3d12::ALLOCATOR_DESC* allocatorDesc);
Expand Down
19 changes: 9 additions & 10 deletions src/fuzzers/D3D12ResidencyManagerFuzzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@

namespace {

ComPtr<gpgmm::d3d12::ResourceAllocator> gResourceAllocator;
ComPtr<gpgmm::d3d12::ResidencyManager> gResidencyManager;
std::vector<ComPtr<gpgmm::d3d12::ResourceAllocation>> gAllocationsBelowBudget = {};
ComPtr<gpgmm::d3d12::IResourceAllocator> gResourceAllocator;
ComPtr<gpgmm::d3d12::IResidencyManager> gResidencyManager;
std::vector<ComPtr<gpgmm::d3d12::IResourceAllocation>> gAllocationsBelowBudget = {};

uint64_t GetBudgetLeft(gpgmm::d3d12::ResidencyManager* const residencyManager,
uint64_t GetBudgetLeft(gpgmm::d3d12::IResidencyManager* const residencyManager,
const DXGI_MEMORY_SEGMENT_GROUP& memorySegmentGroup) {
if (residencyManager == nullptr) {
return 0;
Expand Down Expand Up @@ -67,13 +67,12 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {

residencyDesc.IsUMA = arch.UMA;

if (FAILED(gpgmm::d3d12::ResidencyManager::CreateResidencyManager(residencyDesc,
&gResidencyManager))) {
if (FAILED(gpgmm::d3d12::CreateResidencyManager(residencyDesc, &gResidencyManager))) {
return 0;
}

if (FAILED(gpgmm::d3d12::ResourceAllocator::CreateResourceAllocator(
allocatorDesc, gResidencyManager.Get(), &gResourceAllocator))) {
if (FAILED(gpgmm::d3d12::CreateResourceAllocator(allocatorDesc, gResidencyManager.Get(),
&gResourceAllocator))) {
return 0;
}

Expand All @@ -92,7 +91,7 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
// Keep allocating until we reach the budget.
uint64_t memoryUnderBudget = GetBudgetLeft(gResidencyManager.Get(), bufferMemorySegment);
while (gResourceAllocator->GetInfo().UsedMemoryUsage + kBufferMemorySize < memoryUnderBudget) {
ComPtr<gpgmm::d3d12::ResourceAllocation> allocation;
ComPtr<gpgmm::d3d12::IResourceAllocation> allocation;
if (FAILED(gResourceAllocator->CreateResource({}, bufferDesc, D3D12_RESOURCE_STATE_COMMON,
nullptr, &allocation))) {
return 0;
Expand All @@ -112,7 +111,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
gpgmm::d3d12::ALLOCATION_DESC allocationDesc = {};
allocationDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;

ComPtr<gpgmm::d3d12::ResourceAllocation> allocationOverBudget;
ComPtr<gpgmm::d3d12::IResourceAllocation> allocationOverBudget;
gResourceAllocator->CreateResource(allocationDesc, CreateBufferDesc(UInt8ToUInt64(data)),
D3D12_RESOURCE_STATE_COMMON, nullptr, &allocationOverBudget);
return 0;
Expand Down
8 changes: 4 additions & 4 deletions src/fuzzers/D3D12ResourceAllocatorFuzzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

namespace {

ComPtr<gpgmm::d3d12::ResourceAllocator> gResourceAllocator;
ComPtr<gpgmm::d3d12::IResourceAllocator> gResourceAllocator;

} // namespace

Expand All @@ -30,8 +30,8 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
return 0;
}

if (FAILED(gpgmm::d3d12::ResourceAllocator::CreateResourceAllocator(allocatorDesc,
&gResourceAllocator))) {
if (FAILED(
gpgmm::d3d12::CreateResourceAllocator(allocatorDesc, &gResourceAllocator, nullptr))) {
return 0;
}

Expand All @@ -46,7 +46,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
gpgmm::d3d12::ALLOCATION_DESC allocationDesc = {};
allocationDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;

ComPtr<gpgmm::d3d12::ResourceAllocation> allocation;
ComPtr<gpgmm::d3d12::IResourceAllocation> allocation;
gResourceAllocator->CreateResource(allocationDesc, CreateBufferDesc(UInt8ToUInt64(data)),
D3D12_RESOURCE_STATE_COMMON, nullptr, &allocation);
return 0;
Expand Down
7 changes: 0 additions & 7 deletions src/gpgmm/common/Backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,12 @@
namespace gpgmm {

// Forward declare common types.
class MemoryBase;
class MemoryAllocation;

template <typename CommonType, typename BackendTrait>
struct CommonTrait;

// Define common types.

template <typename BackendTrait>
struct CommonTrait<MemoryBase, BackendTrait> {
using CommonType = typename BackendTrait::MemoryType;
};

template <typename BackendTrait>
struct CommonTrait<MemoryAllocation, BackendTrait> {
using CommonType = typename BackendTrait::AllocationType;
Expand Down
6 changes: 3 additions & 3 deletions src/gpgmm/common/BuddyMemoryAllocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ namespace gpgmm {
GPGMM_TRY_ASSIGN(TrySubAllocateMemory(
&mBuddyBlockAllocator, allocationSize, request.Alignment,
request.NeverAllocate,
[&](const auto& block) -> MemoryBase* {
[&](const auto& block) -> IMemoryObject* {
const uint64_t memoryIndex = GetMemoryIndex(block->Offset);
MemoryAllocation memoryAllocation =
mUsedPool.AcquireFromPool(memoryIndex);
Expand All @@ -78,7 +78,7 @@ namespace gpgmm {
memoryAllocation = *memoryAllocationPtr;
}

MemoryBase* memory = memoryAllocation.GetMemory();
IMemoryObject* memory = memoryAllocation.GetMemory();
mUsedPool.ReturnToPool(memoryAllocation, memoryIndex);

return memory;
Expand Down Expand Up @@ -113,7 +113,7 @@ namespace gpgmm {

MemoryAllocation memoryAllocation = mUsedPool.AcquireFromPool(memoryIndex);

MemoryBase* memory = memoryAllocation.GetMemory();
IMemoryObject* memory = memoryAllocation.GetMemory();
ASSERT(memory != nullptr);

if (memory->RemoveSubAllocationRef()) {
Expand Down
4 changes: 2 additions & 2 deletions src/gpgmm/common/Memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ namespace gpgmm {
return mAlignment;
}

MemoryPool* MemoryBase::GetPool() const {
IMemoryPool* MemoryBase::GetPool() const {
return mPool;
}

void MemoryBase::SetPool(MemoryPool* pool) {
void MemoryBase::SetPool(IMemoryPool* pool) {
ASSERT(pool != nullptr);
mPool = pool;
}
Expand Down
41 changes: 4 additions & 37 deletions src/gpgmm/common/Memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,55 +17,22 @@

#include "gpgmm/common/Object.h"
#include "gpgmm/utils/RefCount.h"
#include "include/gpgmm.h"

namespace gpgmm {

class MemoryPool;

/** \brief Represents a memory object.

When memory is sub-allocated, it will have a non-zero refcount.
*/
class MemoryBase : public ObjectBase {
public:
/** \brief Constructs a memory object of the specified size and alignment.

@param size Size, in bytes, of the memory object.
@param alignment Alignment, in bytes, of the memory object.
*/
explicit MemoryBase(uint64_t size, uint64_t alignment);
virtual ~MemoryBase() override;

/** \brief Return the size of the memory object.

\return Size, in bytes, of the memory object.
*/
uint64_t GetSize() const;

/** \brief Return the alignment of the memory object.

\return Alignment, in bytes, of the memory object.
*/
uint64_t GetAlignment() const;

/** \brief Get the memory pool managing the object.

\return A pointer to MemoryPool managing this memory object.
*/
MemoryPool* GetPool() const;

/** \brief Set the memory pool to manage this object.
IMemoryPool* GetPool() const;
void SetPool(IMemoryPool* pool);

@param pool A pointer to MemoryPool used to manage this object.
*/
void SetPool(MemoryPool* pool);

/** \brief Increments the sub-allocation reference count on the heap.
*/
void AddSubAllocationRef();

/** \brief Decrements the sub-allocation reference count on the heap.
*/
bool RemoveSubAllocationRef();

private:
Expand All @@ -76,7 +43,7 @@ namespace gpgmm {
const uint64_t mSize;
const uint64_t mAlignment;

MemoryPool* mPool = nullptr; // nullptr means no pool is assigned.
IMemoryPool* mPool = nullptr; // nullptr means no pool is assigned.
};

} // namespace gpgmm
Expand Down
6 changes: 3 additions & 3 deletions src/gpgmm/common/MemoryAllocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace gpgmm {
}

MemoryAllocation::MemoryAllocation(MemoryAllocator* allocator,
MemoryBase* memory,
IMemoryObject* memory,
uint64_t offset,
AllocationMethod method,
MemoryBlock* block,
Expand All @@ -49,7 +49,7 @@ namespace gpgmm {
}

MemoryAllocation::MemoryAllocation(MemoryAllocator* allocator,
MemoryBase* memory,
IMemoryObject* memory,
uint64_t requestSize,
uint8_t* mappedPointer)
: mAllocator(allocator),
Expand All @@ -76,7 +76,7 @@ namespace gpgmm {
return {GetSize(), GetAlignment()};
}

MemoryBase* MemoryAllocation::GetMemory() const {
IMemoryObject* MemoryAllocation::GetMemory() const {
return mMemory;
}

Expand Down
40 changes: 5 additions & 35 deletions src/gpgmm/common/MemoryAllocation.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,42 +17,12 @@
#define GPGMM_COMMON_MEMORYALLOCATION_H_

#include "gpgmm/utils/Limits.h"
#include "include/gpgmm.h"
#include "include/gpgmm_export.h"

namespace gpgmm {

/** \enum AllocationMethod
Represents how memory was allocated.
*/
enum class AllocationMethod {

/** \brief Not yet allocated or invalid.

This is an invalid state that assigned temporary before the actual method is known.
*/
kUndefined = 0,

/** \brief Not sub-divided.

One and only one allocation exists for the memory.
*/
kStandalone = 1,

/** \brief Sub-divided using one or more allocations.

Underlying memory will be broken up into one or more memory allocations.
*/
kSubAllocated = 2,

/** \brief Sub-divided within a single memory allocation.

A single memory allocation will be broken into one or more sub-allocations.
*/
kSubAllocatedWithin = 3,
};

struct MemoryBlock;
class MemoryBase;
class MemoryAllocator;

/** \struct MemoryAllocationInfo
Expand Down Expand Up @@ -98,7 +68,7 @@ namespace gpgmm {
@param mappedPointer A pointer to uint8_t which is mapped by the allocation.
*/
MemoryAllocation(MemoryAllocator* allocator,
MemoryBase* memory,
IMemoryObject* memory,
uint64_t offset,
AllocationMethod method,
MemoryBlock* block,
Expand All @@ -116,7 +86,7 @@ namespace gpgmm {
@param mappedPointer A pointer to uint8_t which is mapped by the allocation.
*/
MemoryAllocation(MemoryAllocator* allocator,
MemoryBase* memory,
IMemoryObject* memory,
uint64_t requestSize,
uint8_t* mappedPointer = nullptr);

Expand All @@ -137,7 +107,7 @@ namespace gpgmm {

\return A pointer to the MemoryBase used by this allocation.
*/
MemoryBase* GetMemory() const;
IMemoryObject* GetMemory() const;

/** \brief Get the byte addressable pointer mapped by this allocation.

Expand Down Expand Up @@ -195,7 +165,7 @@ namespace gpgmm {
MemoryAllocator* mAllocator;

private:
MemoryBase* mMemory;
IMemoryObject* mMemory;
uint64_t mOffset; // Offset always local to the memory.
AllocationMethod mMethod;
MemoryBlock* mBlock;
Expand Down
Loading