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
10 changes: 10 additions & 0 deletions include/gpgmm_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@ namespace gpgmm::d3d12 {
cannot be determined.
*/
RESIDENCY_HEAP_FLAG_CREATE_RESIDENT = 0x2,

/** \brief Creates a residency heap that is locked.

A locked heap cannot be evicted once made resident.

This flag is equivalent to calling LockHeap immediately after creation.
*/
RESIDENCY_HEAP_FLAG_CREATE_LOCKED = 0x4,
};

DEFINE_ENUM_FLAG_OPERATORS(RESIDENCY_HEAP_FLAGS)
Expand Down Expand Up @@ -572,6 +580,8 @@ namespace gpgmm::d3d12 {
Unlocking a heap allows the residency manager will evict it when over budget.

@param pHeap A pointer to the heap being unlocked.

\return S_OK if unlocking was successful or S_FALSE if a lock remains.
*/
virtual HRESULT UnlockHeap(IResidencyHeap * pHeap) = 0;

Expand Down
5 changes: 5 additions & 0 deletions src/gpgmm/d3d12/ErrorD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@
#define GPGMM_ASSERT_FAILED(hr) ASSERT(SUCCEEDED(hr));
#define GPGMM_ASSERT_SUCCEEDED(hr) ASSERT(FAILED(hr));

// Same as FAILED but also returns true if S_FALSE.
// S_FALSE is used to denote a result where the operation didn't do anything.
// For example, passing NULL to create an object without returning it will destroy it.
#define GPGMM_UNSUCCESSFUL(hr) (FAILED(hr) || (hr == S_FALSE))

namespace gpgmm::d3d12 {

HRESULT GetErrorResult(ErrorCode error);
Expand Down
49 changes: 40 additions & 9 deletions src/gpgmm/d3d12/ResidencyHeapD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ namespace gpgmm::d3d12 {
}

std::unique_ptr<ResidencyHeap> heap(
new ResidencyHeap(pPageable, newDescriptor, isResidencyDisabled));
new ResidencyHeap(pResidencyManager, pPageable, newDescriptor, isResidencyDisabled));

if (!isResidencyDisabled) {
// Check if the underlying memory was implicitly made resident.
Expand Down Expand Up @@ -191,19 +191,30 @@ namespace gpgmm::d3d12 {
GetDevice(pPageable));
} else {
if (newDescriptor.Flags & RESIDENCY_HEAP_FLAG_CREATE_RESIDENT) {
GPGMM_RETURN_IF_FAILED(residencyManager->LockHeap(heap.get()),
GetDevice(pPageable));
GPGMM_RETURN_IF_FAILED(residencyManager->UnlockHeap(heap.get()),
GetDevice(pPageable));
GPGMM_RETURN_IF_FAILED(heap->Lock(), GetDevice(pPageable));
GPGMM_RETURN_IF_FAILED(heap->Unlock(), GetDevice(pPageable));
ASSERT(heap->GetInfo().Status == RESIDENCY_HEAP_STATUS_RESIDENT);
}
}

if (descriptor.Flags & RESIDENCY_HEAP_FLAG_CREATE_LOCKED) {
GPGMM_RETURN_IF_FAILED(heap->Lock(), GetDevice(pPageable));
}

} else {
if (descriptor.Flags & RESIDENCY_HEAP_FLAG_CREATE_RESIDENT) {
WarnLog(MessageId::kPerformanceWarning, heap.get())
<< "RESIDENCY_HEAP_FLAG_CREATE_RESIDENT was specified but had no effect "
"becauase residency management is not being used.";
}

// Heap created not resident requires no budget to be created.
if (descriptor.Flags & RESIDENCY_HEAP_FLAG_CREATE_LOCKED) {
ErrorLog(ErrorCode::kInvalidArgument, heap.get())
<< "RESIDENCY_HEAP_FLAG_CREATE_LOCKED cannot be specified without a residency "
"manager.";
return E_INVALIDARG;
}
}

GPGMM_RETURN_IF_FAILED(heap->SetDebugName(newDescriptor.DebugName), GetDevice(pPageable));
Expand Down Expand Up @@ -278,26 +289,32 @@ namespace gpgmm::d3d12 {
ppResidencyHeapOut);
}

ResidencyHeap::ResidencyHeap(ComPtr<ID3D12Pageable> pageable,
ResidencyHeap::ResidencyHeap(ComPtr<IResidencyManager> residencyManager,
ComPtr<ID3D12Pageable> pageable,
const RESIDENCY_HEAP_DESC& descriptor,
bool isResidencyDisabled)
: MemoryBase(descriptor.SizeInBytes, descriptor.Alignment),
mResidencyManager(std::move(residencyManager)),
mPageable(std::move(pageable)),
mHeapSegment(descriptor.HeapSegment),
mResidencyLock(0),
mIsResidencyDisabled(isResidencyDisabled),
mState(RESIDENCY_HEAP_STATUS_UNKNOWN) {
ASSERT(mPageable != nullptr);
if (!mIsResidencyDisabled) {
if (residencyManager != nullptr) {
GPGMM_TRACE_EVENT_OBJECT_NEW(this);
}
}

ResidencyHeap::~ResidencyHeap() {
if (mIsResidencyDisabled) {
if (mResidencyManager == nullptr) {
return;
}

if (IsResidencyLocked() && GPGMM_UNSUCCESSFUL(Unlock())) {
DebugLog(MessageId::kUnknown, this)
<< "Heap was locked for residency while being destroyed.";
}

// When a heap is destroyed, it no longer resides in resident memory, so we must evict
// it from the residency cache. If this heap is not manually removed from the residency
// cache, the ResidencyManager will attempt to use it after it has been deallocated.
Expand Down Expand Up @@ -364,4 +381,18 @@ namespace gpgmm::d3d12 {
return DebugObject::SetDebugName(Name);
}

HRESULT ResidencyHeap::Lock() {
ASSERT(mResidencyManager != nullptr);
return mResidencyManager->LockHeap(this);
}

HRESULT ResidencyHeap::Unlock() {
ASSERT(mResidencyManager != nullptr);
return mResidencyManager->UnlockHeap(this);
}

IResidencyManager* ResidencyHeap::GetResidencyManager() const {
return mResidencyManager.Get();
}

} // namespace gpgmm::d3d12
10 changes: 8 additions & 2 deletions src/gpgmm/d3d12/ResidencyHeapD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,16 @@ namespace gpgmm::d3d12 {
LPCWSTR GetDebugName() const override;
HRESULT SetDebugName(LPCWSTR Name) override;

IResidencyManager* GetResidencyManager() const;

HRESULT Lock();
HRESULT Unlock();

private:
friend ResidencyManager;

ResidencyHeap(ComPtr<ID3D12Pageable> pageable,
ResidencyHeap(ComPtr<IResidencyManager> residencyManager,
ComPtr<ID3D12Pageable> pageable,
const RESIDENCY_HEAP_DESC& descriptor,
bool isResidencyDisabled);

Expand All @@ -87,13 +93,13 @@ namespace gpgmm::d3d12 {
void AddResidencyLockRef();
void ReleaseResidencyLock();

ComPtr<IResidencyManager> mResidencyManager;
ComPtr<ID3D12Pageable> mPageable;

// mLastUsedFenceValue denotes the last time this pageable was submitted to the GPU.
uint64_t mLastUsedFenceValue = 0;
DXGI_MEMORY_SEGMENT_GROUP mHeapSegment;
RefCounted mResidencyLock;
bool mIsResidencyDisabled;
RESIDENCY_HEAP_STATUS mState;
};
} // namespace gpgmm::d3d12
Expand Down
4 changes: 2 additions & 2 deletions src/gpgmm/d3d12/ResidencyManagerD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ namespace gpgmm::d3d12 {

// If the heap was never locked, nothing further should be done.
if (!heap->IsResidencyLocked()) {
return S_OK;
return S_FALSE;
}

if (heap->IsInList()) {
Expand All @@ -256,7 +256,7 @@ namespace gpgmm::d3d12 {

// If another lock still exists on the heap, nothing further should be done.
if (heap->IsResidencyLocked()) {
return S_OK;
return S_FALSE;
}

// When all locks have been removed, the resource remains resident and becomes tracked in
Expand Down
26 changes: 13 additions & 13 deletions src/gpgmm/d3d12/ResourceAllocationD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ namespace gpgmm::d3d12 {
} // namespace

ResourceAllocation::ResourceAllocation(const RESOURCE_RESOURCE_ALLOCATION_DESC& desc,
ResidencyManager* residencyManager,
MemoryAllocatorBase* allocator,
ResidencyHeap* resourceHeap,
MemoryBlock* block,
Expand All @@ -54,7 +53,6 @@ namespace gpgmm::d3d12 {
static_cast<AllocationMethod>(desc.Type),
block,
desc.SizeInBytes),
mResidencyManager(residencyManager),
mResource(std::move(resource)),
mOffsetFromResource(desc.OffsetFromResource) {
ASSERT(resourceHeap != nullptr);
Expand All @@ -63,6 +61,9 @@ namespace gpgmm::d3d12 {

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

void ResourceAllocation::DeleteThis() {
if (mMappedCount.GetRefCount() > 0) {
WarnLog(MessageId::kPerformanceWarning, this)
<< "Destroying a mapped resource allocation is allowed but discouraged. Please "
Expand All @@ -72,17 +73,15 @@ namespace gpgmm::d3d12 {

// If the developer forgots to unlock the heap, do so now so the heap can be made eligable
// for eviction.
if (mResidencyManager != nullptr) {
mResidencyManager->UnlockHeap(GetMemory());
ResidencyHeap* residencyHeap = static_cast<ResidencyHeap*>(GetMemory());
if (residencyHeap->GetResidencyManager() != nullptr) {
residencyHeap->Unlock();
WarnLog(MessageId::kPerformanceWarning, this)
<< "Destroying a locked resource allocation is allowed but discouraged. Please "
"call UnlockHeap the same number of times as LockHeap before releasing the "
"resource "
"allocation.";
"resource allocation.";
}
}

void ResourceAllocation::DeleteThis() {
GetAllocator()->DeallocateMemory(std::unique_ptr<MemoryAllocationBase>(this));
}

Expand All @@ -102,9 +101,9 @@ namespace gpgmm::d3d12 {
return GetErrorResult(ErrorCode::kBadOperation);
}

if (mResidencyManager != nullptr) {
GPGMM_RETURN_IF_FAILED(mResidencyManager->LockHeap(GetMemory()),
GetDevice(mResource.Get()));
ResidencyHeap* residencyHeap = static_cast<ResidencyHeap*>(GetMemory());
if (residencyHeap->GetResidencyManager() != nullptr) {
GPGMM_RETURN_IF_FAILED(residencyHeap->Lock(), GetDevice(mResource.Get()));
}

// Range coordinates are always subresource-relative so the range should only be
Expand Down Expand Up @@ -142,8 +141,9 @@ namespace gpgmm::d3d12 {
}

// Underlying heap cannot be evicted until the last Unmap.
if (mResidencyManager != nullptr && mMappedCount.Unref()) {
mResidencyManager->UnlockHeap(GetMemory());
ResidencyHeap* residencyHeap = static_cast<ResidencyHeap*>(GetMemory());
if (residencyHeap->GetResidencyManager() != nullptr && mMappedCount.Unref()) {
residencyHeap->Unlock();
}

D3D12_RANGE newWrittenRange{};
Expand Down
2 changes: 0 additions & 2 deletions src/gpgmm/d3d12/ResourceAllocationD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ namespace gpgmm::d3d12 {
friend ResourceAllocator;

ResourceAllocation(const RESOURCE_RESOURCE_ALLOCATION_DESC& desc,
ResidencyManager* residencyManager,
MemoryAllocatorBase* allocator,
ResidencyHeap* resourceHeap,
MemoryBlock* block,
Expand All @@ -78,7 +77,6 @@ namespace gpgmm::d3d12 {
// ObjectBase interface
DEFINE_OBJECT_BASE_OVERRIDES(IResourceAllocation)

ResidencyManager* const mResidencyManager;
ComPtr<ID3D12Resource> mResource;

const uint64_t mOffsetFromResource;
Expand Down
19 changes: 9 additions & 10 deletions src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1332,8 +1332,8 @@ namespace gpgmm::d3d12 {
allocationDesc.DebugName = allocationDescriptor.DebugName;

*ppResourceAllocationOut = new ResourceAllocation(
allocationDesc, mResidencyManager.Get(), subAllocation.GetAllocator(),
resourceHeap, subAllocation.GetBlock(), std::move(committedResource));
allocationDesc, subAllocation.GetAllocator(), resourceHeap,
subAllocation.GetBlock(), std::move(committedResource));

return S_OK;
}));
Expand Down Expand Up @@ -1373,8 +1373,8 @@ namespace gpgmm::d3d12 {
allocationDesc.DebugName = allocationDescriptor.DebugName;

*ppResourceAllocationOut = new ResourceAllocation(
allocationDesc, mResidencyManager.Get(), subAllocation.GetAllocator(),
resourceHeap, subAllocation.GetBlock(), std::move(placedResource));
allocationDesc, subAllocation.GetAllocator(), resourceHeap,
subAllocation.GetBlock(), std::move(placedResource));

return S_OK;
}));
Expand Down Expand Up @@ -1417,8 +1417,8 @@ namespace gpgmm::d3d12 {
allocationDesc.DebugName = allocationDescriptor.DebugName;

*ppResourceAllocationOut = new ResourceAllocation(
allocationDesc, mResidencyManager.Get(), allocation.GetAllocator(),
resourceHeap, allocation.GetBlock(), std::move(placedResource));
allocationDesc, allocation.GetAllocator(), resourceHeap,
allocation.GetBlock(), std::move(placedResource));

return S_OK;
}));
Expand Down Expand Up @@ -1478,8 +1478,7 @@ namespace gpgmm::d3d12 {

if (ppResourceAllocationOut != nullptr) {
*ppResourceAllocationOut = new ResourceAllocation(
allocationDesc, mResidencyManager.Get(), this, resourceHeap.Detach(), nullptr,
std::move(committedResource));
allocationDesc, this, resourceHeap.Detach(), nullptr, std::move(committedResource));
}

return ErrorCode::kNone;
Expand Down Expand Up @@ -1567,8 +1566,8 @@ namespace gpgmm::d3d12 {
allocationDesc.Type = RESOURCE_ALLOCATION_TYPE_STANDALONE;

*ppResourceAllocationOut = new ResourceAllocation(
allocationDesc, nullptr, this, static_cast<ResidencyHeap*>(resourceHeap.Detach()),
nullptr, pCommittedResource);
allocationDesc, this, static_cast<ResidencyHeap*>(resourceHeap.Detach()), nullptr,
pCommittedResource);

return S_OK;
}
Expand Down
Loading