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
4 changes: 0 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,6 @@ endif()

if(GPGMM_ENABLE_ALLOCATOR_LEAK_CHECKS)
target_compile_definitions(gpgmm_common_config INTERFACE "GPGMM_ENABLE_ALLOCATOR_LEAK_CHECKS")
else()
target_compile_definitions(gpgmm_common_config INTERFACE
$<$<CONFIG:Debug>:GPGMM_ENABLE_ALLOCATOR_LEAK_CHECKS>
)
endif()

if(GPGMM_DISABLE_SIZE_CACHE)
Expand Down
2 changes: 1 addition & 1 deletion build_overrides/gpgmm_features.gni
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ declare_args() {

# Enables checking of allocator leaks.
# Sets -dGPGMM_ENABLE_ALLOCATOR_LEAK_CHECKS
gpgmm_enable_allocator_leak_checks = is_debug
gpgmm_enable_allocator_leak_checks = false

# Enables ASSERT on severity functionality.
# Sets -dGPGMM_ENABLE_ASSERT_ON_WARNING
Expand Down
2 changes: 2 additions & 0 deletions src/gpgmm/common/MemoryAllocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,15 @@ namespace gpgmm {
}

MemoryAllocator::~MemoryAllocator() {
#if defined(GPGMM_ENABLE_ALLOCATOR_LEAK_CHECKS)
// If memory cannot be reused by a (parent) allocator, ensure no used memory leaked.
if (GetParent() == nullptr) {
ASSERT(mInfo.UsedBlockUsage == 0u);
ASSERT(mInfo.UsedBlockCount == 0u);
ASSERT(mInfo.UsedMemoryCount == 0u);
ASSERT(mInfo.UsedMemoryUsage == 0u);
}
#endif
}

std::unique_ptr<MemoryAllocation> MemoryAllocator::TryAllocateMemory(
Expand Down
15 changes: 8 additions & 7 deletions src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,9 +482,9 @@ namespace gpgmm::d3d12 {
mIsCustomHeapsDisabled(descriptor.Flags & ALLOCATOR_FLAG_DISABLE_CUSTOM_HEAPS) {
GPGMM_TRACE_EVENT_OBJECT_NEW(this);

#if defined(GPGMM_ENABLE_ALLOCATOR_LEAK_CHECKS)
mDebugAllocator = std::make_unique<DebugResourceAllocator>();
#endif
if (descriptor.Flags & ALLOCATOR_FLAG_NEVER_LEAK_MEMORY) {
mDebugAllocator = std::make_unique<DebugResourceAllocator>();
}

const bool isUMA =
(IsResidencyEnabled()) ? mResidencyManager->IsUMA() : mCaps->IsAdapterUMA();
Expand Down Expand Up @@ -686,6 +686,11 @@ namespace gpgmm::d3d12 {
ResourceAllocator::~ResourceAllocator() {
GPGMM_TRACE_EVENT_OBJECT_DESTROY(this);

// Give the debug allocator the first chance to report leaks.
if (mDebugAllocator) {
mDebugAllocator->ReportLiveAllocations();
}

// Destroy allocators in the reverse order they were created so we can record delete events
// before event tracer shutdown.
mSmallBufferAllocatorOfType = {};
Expand All @@ -696,10 +701,6 @@ namespace gpgmm::d3d12 {
mResourceAllocatorOfType = {};
mResourceHeapAllocatorOfType = {};

#if defined(GPGMM_ENABLE_ALLOCATOR_LEAK_CHECKS)
mDebugAllocator->ReportLiveAllocations();
#endif

#if defined(GPGMM_ENABLE_DEVICE_LEAK_CHECKS)
ReportLiveDeviceObjects(mDevice);
#endif
Expand Down
7 changes: 7 additions & 0 deletions src/gpgmm/d3d12/ResourceAllocatorD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ namespace gpgmm::d3d12 {
the corresponding heap type.
*/
ALLOCATOR_FLAG_DISABLE_CUSTOM_HEAPS = 0x10,

/** \brief Report leaks of resource allocations.

Used to track outstanding allocations made with this allocator. When the allocator is about
to be released, it will report details on any leaked allocations as log messages.
*/
ALLOCATOR_FLAG_NEVER_LEAK_MEMORY = 0x20,
};

DEFINE_ENUM_FLAG_OPERATORS(ALLOCATOR_FLAGS)
Expand Down
3 changes: 3 additions & 0 deletions src/tests/D3D12Test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ namespace gpgmm::d3d12 {
desc.Flags |= ALLOCATOR_FLAG_DISABLE_MEMORY_PREFETCH;
}

// Make sure leak detection is always enabled.
desc.Flags |= gpgmm::d3d12::ALLOCATOR_FLAG_NEVER_LEAK_MEMORY;

desc.MinLogLevel = GetMessageSeverity(GetLogLevel());

if (IsDumpAllEventsEnabled()) {
Expand Down
14 changes: 14 additions & 0 deletions src/tests/end2end/D3D12ResourceAllocatorTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,20 @@ TEST_F(D3D12ResourceAllocatorTests, CreateBuffer) {
}
}

TEST_F(D3D12ResourceAllocatorTests, CreateBufferLeaked) {
ComPtr<ResourceAllocator> resourceAllocator;
ASSERT_SUCCEEDED(
ResourceAllocator::CreateAllocator(CreateBasicAllocatorDesc(), &resourceAllocator));
ASSERT_NE(resourceAllocator, nullptr);

ComPtr<ResourceAllocation> allocation;
ASSERT_SUCCEEDED(
resourceAllocator->CreateResource({}, CreateBasicBufferDesc(kDefaultBufferSize),
D3D12_RESOURCE_STATE_COMMON, nullptr, &allocation));

allocation.Detach(); // leaked!
}

// Verifies there are no attribution of heaps when UMA + no read-back.
TEST_F(D3D12ResourceAllocatorTests, CreateBufferUMA) {
GPGMM_SKIP_TEST_IF(!mIsUMA);
Expand Down