Skip to content

Commit

Permalink
Use explicit API casting function. (#973)
Browse files Browse the repository at this point in the history
  • Loading branch information
bbernhar authored Jan 10, 2024
1 parent 23eedf2 commit 286967c
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 50 deletions.
16 changes: 16 additions & 0 deletions src/gpgmm/common/Backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,22 @@ namespace gpgmm {
common);
}

template <typename InterfaceType>
struct APIObjectTraits;

template <typename InterfaceType>
typename APIObjectTraits<InterfaceType>::DerivedType* FromAPI(InterfaceType* basePtr) {
return static_cast<typename APIObjectTraits<InterfaceType>::DerivedType*>(basePtr);
}

template <typename APIObjectType>
struct APIInterfaceTraits;

template <typename APIObjectType>
typename APIInterfaceTraits<APIObjectType>::InterfaceType* ToAPI(APIObjectType* objectPtr) {
return static_cast<typename APIInterfaceTraits<APIObjectType>::InterfaceType*>(objectPtr);
}

} // namespace gpgmm

#endif // SRC_GPGMM_COMMON_BACKEND_H_
49 changes: 48 additions & 1 deletion src/gpgmm/d3d12/BackendD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,58 @@

#include "gpgmm/common/Backend.h"

namespace gpgmm::d3d12 {
#include <gpgmm_d3d12.h>

namespace gpgmm::d3d12 {
class ResidencyHeap;
class ResourceAllocation;
class ResourceAllocator;
class ResidencyManager;
} // namespace gpgmm::d3d12

// Compile-time mappings to/from API object/interface to down or up casts with only permitted API
// types. For example, `FromAPI(interface)` instead of `static_cast<Object*>(interface)`.
template <>
struct gpgmm::APIObjectTraits<gpgmm::d3d12::IResidencyHeap> {
using DerivedType = gpgmm::d3d12::ResidencyHeap;
};

template <>
struct gpgmm::APIInterfaceTraits<gpgmm::d3d12::ResidencyHeap> {
using InterfaceType = gpgmm::d3d12::IResidencyHeap;
};

template <>
struct gpgmm::APIObjectTraits<gpgmm::d3d12::IResourceAllocator> {
using DerivedType = gpgmm::d3d12::ResourceAllocator;
};

template <>
struct gpgmm::APIInterfaceTraits<gpgmm::d3d12::ResourceAllocator> {
using InterfaceType = gpgmm::d3d12::IResourceAllocator;
};

template <>
struct gpgmm::APIObjectTraits<gpgmm::d3d12::IResidencyManager> {
using DerivedType = gpgmm::d3d12::ResidencyManager;
};

template <>
struct gpgmm::APIInterfaceTraits<gpgmm::d3d12::ResidencyManager> {
using InterfaceType = gpgmm::d3d12::IResidencyManager;
};

namespace gpgmm::d3d12 {

template <typename InterfaceType>
auto FromAPI(InterfaceType&& basePtr) -> decltype(gpgmm::FromAPI(basePtr)) {
return gpgmm::FromAPI(basePtr);
}

template <typename APIObjectType>
auto ToAPI(APIObjectType&& objectPtr) -> decltype(gpgmm::ToAPI(objectPtr)) {
return gpgmm::ToAPI(objectPtr);
}

struct BackendTraits {
using AllocationType = ResourceAllocation;
Expand Down
2 changes: 1 addition & 1 deletion src/gpgmm/d3d12/JSONSerializerD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ namespace gpgmm::d3d12 {
JSONDict residencyListDict;
JSONArray heapArray;
ResidencyList* residencyList = static_cast<ResidencyList*>(params.ResidencyLists[i]);
for (ResidencyHeap* heap : *residencyList) {
for (IResidencyHeap* heap : *residencyList) {
heapArray.AddItem(gpgmm::JSONSerializer::Serialize(heap));
}
if (!heapArray.IsEmpty()) {
Expand Down
5 changes: 3 additions & 2 deletions src/gpgmm/d3d12/ResidencyHeapD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "gpgmm/common/SizeClass.h"
#include "gpgmm/common/TraceEvent.h"
#include "gpgmm/d3d12/BackendD3D12.h"
#include "gpgmm/d3d12/ErrorD3D12.h"
#include "gpgmm/d3d12/JSONSerializerD3D12.h"
#include "gpgmm/d3d12/LogD3D12.h"
Expand Down Expand Up @@ -150,7 +151,7 @@ namespace gpgmm::d3d12 {
return E_INVALIDARG;
}

ResidencyManager* residencyManager = static_cast<ResidencyManager*>(pResidencyManager);
ResidencyManager* residencyManager = FromAPI(pResidencyManager);

std::unique_ptr<ResidencyHeap> heap(
new ResidencyHeap(residencyManager, pPageable, newDescriptor));
Expand Down Expand Up @@ -250,7 +251,7 @@ namespace gpgmm::d3d12 {
// Ensure enough budget exists before creating the heap to avoid an out-of-memory error.
if (pResidencyManager != nullptr &&
descriptor.Flags & RESIDENCY_HEAP_FLAG_CREATE_IN_BUDGET) {
ResidencyManager* residencyManager = static_cast<ResidencyManager*>(pResidencyManager);
ResidencyManager* residencyManager = FromAPI(pResidencyManager);

uint64_t bytesEvicted = descriptor.SizeInBytes;
GPGMM_RETURN_IF_FAILED(residencyManager->EvictInternal(
Expand Down
2 changes: 1 addition & 1 deletion src/gpgmm/d3d12/ResidencyListD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ namespace gpgmm::d3d12 {
return E_INVALIDARG;
}

mList.push_back(static_cast<ResidencyHeap*>(pHeap));
mList.push_back(pHeap);
return S_OK;
}

Expand Down
4 changes: 1 addition & 3 deletions src/gpgmm/d3d12/ResidencyListD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,8 @@

namespace gpgmm::d3d12 {

class ResidencyHeap;

class ResidencyList final : public IResidencyList, public Unknown {
using UnderlyingType = std::vector<ResidencyHeap*>;
using UnderlyingType = std::vector<IResidencyHeap*>;

public:
ResidencyList();
Expand Down
47 changes: 22 additions & 25 deletions src/gpgmm/d3d12/ResidencyManagerD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "gpgmm/common/EventMessage.h"
#include "gpgmm/common/SizeClass.h"
#include "gpgmm/d3d12/BackendD3D12.h"
#include "gpgmm/d3d12/BudgetUpdateD3D12.h"
#include "gpgmm/d3d12/CapsD3D12.h"
#include "gpgmm/d3d12/ErrorD3D12.h"
Expand Down Expand Up @@ -194,14 +195,10 @@ namespace gpgmm::d3d12 {
}

// Increments number of locks on a heap to ensure the heap remains resident.
HRESULT ResidencyManager::LockHeap(ResidencyHeap* pHeap) {
GPGMM_RETURN_IF_NULL(pHeap);
HRESULT ResidencyManager::LockHeap(ResidencyHeap* heap) {
GPGMM_RETURN_IF_NULL(heap);

std::lock_guard<std::mutex> lock(mMutex);

ResidencyHeap* heap = static_cast<ResidencyHeap*>(pHeap);
ASSERT(heap != nullptr);

if (!heap->IsInList() && !heap->IsResidencyLocked()) {
ComPtr<ID3D12Pageable> pageable;
GPGMM_RETURN_IF_FAILED(heap->QueryInterface(IID_PPV_ARGS(&pageable)), mDevice);
Expand Down Expand Up @@ -234,12 +231,10 @@ namespace gpgmm::d3d12 {

// Decrements number of locks on a heap. When the number of locks becomes zero, the heap is
// inserted into the LRU cache and becomes eligible for eviction.
HRESULT ResidencyManager::UnlockHeap(ResidencyHeap* pHeap) {
GPGMM_RETURN_IF_NULL(pHeap);
HRESULT ResidencyManager::UnlockHeap(ResidencyHeap* heap) {
GPGMM_RETURN_IF_NULL(heap);

std::lock_guard<std::mutex> lock(mMutex);
ResidencyHeap* heap = static_cast<ResidencyHeap*>(pHeap);
ASSERT(heap != nullptr);

// If the heap was never locked, nothing further should be done.
if (!heap->IsResidencyLocked()) {
Expand Down Expand Up @@ -629,31 +624,33 @@ namespace gpgmm::d3d12 {
uint64_t nonLocalSizeToMakeResident = 0;

std::vector<ResidencyHeap*> heapsToMakeResident;
for (ResidencyHeap* heap : *residencyList) {
for (IResidencyHeap* heap : *residencyList) {
ResidencyHeap* backendHeap = FromAPI(heap);

// Heaps that are locked resident are not tracked in the LRU cache.
if (heap->IsResidencyLocked()) {
if (backendHeap->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() == mResidencyFence->GetCurrentFence()) {
if (backendHeap->GetLastUsedFenceValue() == mResidencyFence->GetCurrentFence()) {
continue;
}

if (heap->IsInList()) {
if (backendHeap->IsInList()) {
// If the heap is already in the LRU, we must remove it and append again below to
// update its position in the LRU.
heap->RemoveFromList();
backendHeap->RemoveFromList();
} else {
ComPtr<ID3D12Pageable> pageable;
GPGMM_RETURN_IF_FAILED(heap->QueryInterface(IID_PPV_ARGS(&pageable)));
GPGMM_RETURN_IF_FAILED(backendHeap->QueryInterface(IID_PPV_ARGS(&pageable)));

if (heap->GetMemorySegment() == DXGI_MEMORY_SEGMENT_GROUP_LOCAL) {
localSizeToMakeResident += heap->GetSize();
if (backendHeap->GetMemorySegment() == DXGI_MEMORY_SEGMENT_GROUP_LOCAL) {
localSizeToMakeResident += backendHeap->GetSize();
localHeapsToMakeResident.push_back(pageable.Get());
} else {
nonLocalSizeToMakeResident += heap->GetSize();
nonLocalSizeToMakeResident += backendHeap->GetSize();
nonLocalHeapsToMakeResident.push_back(pageable.Get());
}
}
Expand All @@ -662,21 +659,21 @@ namespace gpgmm::d3d12 {
// command list stay resident at least until that command list has finished execution.
// Setting this serial unnecessarily can leave the LRU in a state where nothing is
// eligible for eviction, even though some evictions may be possible.
heap->SetLastUsedFenceValue(mResidencyFence->GetCurrentFence());
backendHeap->SetLastUsedFenceValue(mResidencyFence->GetCurrentFence());

// Insert the heap into the appropriate LRU.
InsertHeapInternal(heap);
InsertHeapInternal(backendHeap);

// Temporarily track which heaps will be made resident. Once MakeResident() is called
// on them will we transition them all together.
heapsToMakeResident.push_back(heap);
heapsToMakeResident.push_back(backendHeap);

// If the heap should be already resident, calling MakeResident again will be redundant.
// Tell the developer the heap wasn't properly tracked by the residency manager.
if (heap->GetInfo().Status == RESIDENCY_HEAP_STATUS_UNKNOWN) {
if (backendHeap->GetInfo().Status == RESIDENCY_HEAP_STATUS_UNKNOWN) {
WarnLog(MessageId::kPerformanceWarning, this)
<< "Residency state could not be determined for the heap (Heap="
<< ToHexStr(heap)
<< ToHexStr(backendHeap)
<< "). This likely means the developer was attempting to make a "
"non-resource heap resident without calling lock/unlock first.";
}
Expand Down Expand Up @@ -881,7 +878,7 @@ namespace gpgmm::d3d12 {
const RESIDENCY_HEAP_STATUS& newStatus) {
GPGMM_RETURN_IF_NULL(pHeap);

ResidencyHeap* heap = static_cast<ResidencyHeap*>(pHeap);
ResidencyHeap* heap = FromAPI(pHeap);
if (heap->GetInfo().IsLocked) {
ErrorLog(ErrorCode::kBadOperation, this)
<< "Heap residency cannot be updated because it was locked. "
Expand Down
10 changes: 5 additions & 5 deletions src/gpgmm/d3d12/ResourceAllocationD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ namespace gpgmm::d3d12 {

// If the developer forgots to unlock the heap, do so now so the heap can be made eligable
// for eviction.
ResidencyHeap* residencyHeap = static_cast<ResidencyHeap*>(GetMemory());
ResidencyHeap* residencyHeap = FromAPI(GetMemory());
if (SUCCEEDED(residencyHeap->GetResidencyManager(nullptr)) &&
GPGMM_UNSUCCESSFUL(residencyHeap->Unlock())) {
WarnLog(MessageId::kPerformanceWarning, this)
Expand Down Expand Up @@ -133,7 +133,7 @@ namespace gpgmm::d3d12 {
return GetErrorResult(ErrorCode::kBadOperation);
}

ResidencyHeap* residencyHeap = static_cast<ResidencyHeap*>(GetMemory());
ResidencyHeap* residencyHeap = FromAPI(GetMemory());
if (SUCCEEDED(residencyHeap->GetResidencyManager(nullptr))) {
GPGMM_RETURN_IF_FAILED(residencyHeap->Lock());
}
Expand Down Expand Up @@ -173,7 +173,7 @@ namespace gpgmm::d3d12 {
}

// Underlying heap cannot be evicted until the last Unmap.
ResidencyHeap* residencyHeap = static_cast<ResidencyHeap*>(GetMemory());
ResidencyHeap* residencyHeap = FromAPI(GetMemory());
if (mMappedCount.Unref() && SUCCEEDED(residencyHeap->GetResidencyManager(nullptr))) {
residencyHeap->Unlock();
}
Expand Down Expand Up @@ -204,7 +204,7 @@ namespace gpgmm::d3d12 {
}

IResidencyHeap* ResourceAllocation::GetMemory() const {
return static_cast<ResidencyHeap*>(MemoryAllocationBase::GetMemory());
return ToBackend(MemoryAllocationBase::GetMemory());
}

HRESULT ResourceAllocation::SetDebugNameImpl(LPCWSTR name) {
Expand All @@ -226,7 +226,7 @@ namespace gpgmm::d3d12 {
}

HRESULT STDMETHODCALLTYPE ResourceAllocation::QueryInterface(REFIID riid, void** ppvObject) {
ResidencyHeap* residencyHeap = static_cast<ResidencyHeap*>(GetMemory());
ResidencyHeap* residencyHeap = FromAPI(GetMemory());

// Only committed resources can be exported. Committed resources are created
// without explicit heaps.
Expand Down
18 changes: 8 additions & 10 deletions src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ namespace gpgmm::d3d12 {
HRESULT CreateResourceAllocator(const RESOURCE_ALLOCATOR_DESC& allocatorDescriptor,
IResourceAllocator* pResourceAllocator,
IResourceAllocator** ppResourceAllocatorOut) {
ResourceAllocator* resourceAllocator = static_cast<ResourceAllocator*>(pResourceAllocator);
ResourceAllocator* resourceAllocator = FromAPI(pResourceAllocator);
return ResourceAllocator::CreateResourceAllocator(
allocatorDescriptor, resourceAllocator->GetDevice(), resourceAllocator->GetAdapter(),
resourceAllocator->GetResidencyManager(), pResourceAllocator, ppResourceAllocatorOut);
Expand Down Expand Up @@ -586,12 +586,10 @@ namespace gpgmm::d3d12 {
std::unique_ptr<ResourceAllocator> resourceAllocator;
if (pResourceAllocator == nullptr) {
resourceAllocator = std::unique_ptr<ResourceAllocator>(new ResourceAllocator(
newDescriptor, pDevice, pAdapter, static_cast<ResidencyManager*>(pResidencyManager),
std::move(caps)));
newDescriptor, pDevice, pAdapter, FromAPI(pResidencyManager), std::move(caps)));
} else {
resourceAllocator = std::unique_ptr<ResourceAllocator>(new ResourceAllocator(
newDescriptor, static_cast<ResourceAllocator*>(pResourceAllocator),
std::move(caps)));
resourceAllocator = std::unique_ptr<ResourceAllocator>(
new ResourceAllocator(newDescriptor, FromAPI(pResourceAllocator), std::move(caps)));
}

GPGMM_TRACE_EVENT_OBJECT_SNAPSHOT(resourceAllocator.get(), newDescriptor);
Expand Down Expand Up @@ -1600,9 +1598,9 @@ namespace gpgmm::d3d12 {
allocationDesc.SizeInBytes = allocationSize;
allocationDesc.Type = RESOURCE_ALLOCATION_TYPE_STANDALONE;

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

return S_OK;
}
Expand Down Expand Up @@ -1670,7 +1668,7 @@ namespace gpgmm::d3d12 {
GPGMM_RETURN_IF_FAILED(resourceHeap->SetDebugName(L"Resource heap (committed)"));

if (resourceHeapOut != nullptr) {
*resourceHeapOut = static_cast<ResidencyHeap*>(resourceHeap.Detach());
*resourceHeapOut = FromAPI(resourceHeap.Detach());
}

return S_OK;
Expand Down
4 changes: 2 additions & 2 deletions src/gpgmm/d3d12/ResourceHeapAllocatorD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ namespace gpgmm::d3d12 {
mStats.UsedMemoryUsage += resourceHeapDesc.SizeInBytes;
mStats.UsedMemoryCount++;

return std::make_unique<MemoryAllocationBase>(
this, static_cast<ResidencyHeap*>(resourceHeap.Detach()), request.SizeInBytes);
return std::make_unique<MemoryAllocationBase>(this, FromAPI(resourceHeap.Detach()),
request.SizeInBytes);
}

void ResourceHeapAllocator::DeallocateMemory(std::unique_ptr<MemoryAllocationBase> allocation) {
Expand Down

0 comments on commit 286967c

Please sign in to comment.