Skip to content

Commit

Permalink
Fixed and finished merge of GPUUploadHeap support
Browse files Browse the repository at this point in the history
Added Allocator::IsGPUUploadHeapSupported and macro D3D12MA_OPTIONS16_SUPPORTED.
  • Loading branch information
adam-sawicki-a committed Mar 5, 2024
1 parent dc222fe commit 47ebce5
Show file tree
Hide file tree
Showing 5 changed files with 276 additions and 20 deletions.
16 changes: 13 additions & 3 deletions include/D3D12MemAlloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -402,8 +402,9 @@ struct TotalStatistics
- 1 = `D3D12_HEAP_TYPE_UPLOAD`
- 2 = `D3D12_HEAP_TYPE_READBACK`
- 3 = `D3D12_HEAP_TYPE_CUSTOM`
- 4 = `D3D12_HEAP_TYPE_GPU_UPLOAD`
*/
DetailedStatistics HeapType[4];
DetailedStatistics HeapType[5];
/** \brief One element for each memory segment group located at the following indices:
- 0 = `DXGI_MEMORY_SEGMENT_GROUP_LOCAL`
Expand All @@ -413,9 +414,9 @@ struct TotalStatistics
- When `IsUMA() == FALSE` (discrete graphics card):
- `DXGI_MEMORY_SEGMENT_GROUP_LOCAL` (index 0) represents GPU memory
(resources allocated in `D3D12_HEAP_TYPE_DEFAULT` or `D3D12_MEMORY_POOL_L1`).
(resources allocated in `D3D12_HEAP_TYPE_DEFAULT`, `D3D12_HEAP_TYPE_GPU_UPLOAD` or `D3D12_MEMORY_POOL_L1`).
- `DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL` (index 1) represents system memory
(resources allocated in `D3D12_HEAP_TYPE_UPLOAD`, `D3D12_HEAP_TYPE_READBACK`, or `D3D12_MEMORY_POOL_L0`).
(resources allocated in `D3D12_HEAP_TYPE_UPLOAD`, `D3D12_HEAP_TYPE_READBACK`, or `D3D12_MEMORY_POOL_L0`).
- When `IsUMA() == TRUE` (integrated graphics chip):
- `DXGI_MEMORY_SEGMENT_GROUP_LOCAL` = (index 0) represents memory shared for all the resources.
- `DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL` = (index 1) is unused and always 0.
Expand Down Expand Up @@ -1140,6 +1141,15 @@ class D3D12MA_API Allocator : public IUnknownImpl
- "ID3D12Device::GetCustomHeapProperties method (d3d12.h)"
*/
BOOL IsCacheCoherentUMA() const;
/** \brief Returns true if GPU Upload Heaps are supported on the current system.
When true, you can use `D3D12_HEAP_TYPE_GPU_UPLOAD`.
This flag is fetched from `D3D12_FEATURE_D3D12_OPTIONS16::GPUUploadHeapSupported`.
`#define D3D12MA_OPTIONS16_SUPPORTED 1` is needed for the compilation of this library. Otherwise the flag is always false.
*/
BOOL IsGPUUploadHeapSupported() const;
/** \brief Returns total amount of memory of specific segment group, in bytes.
\param memorySegmentGroup use `DXGI_MEMORY_SEGMENT_GROUP_LOCAL` or DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL`.
Expand Down
16 changes: 16 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
cmake_minimum_required(VERSION 3.25)

set(D3D12MA_LIBRARY_SOURCE_FILES
D3D12MemAlloc.cpp
"${PROJECT_SOURCE_DIR}/include/D3D12MemAlloc.h"
Expand Down Expand Up @@ -150,10 +152,24 @@ if(D3D12MA_AGILITY_SDK_DIRECTORY)
if(D3D12MA_AGILITY_SDK_PREVIEW)
target_compile_definitions(D3D12Sample PRIVATE D3D12MA_USE_AGILITY_SDK_PREVIEW=1)
endif()
add_custom_command(TARGET D3D12Sample POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:D3D12Sample>/D3D12"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${D3D12MA_AGILITY_SDK_DIRECTORY}/build/native/bin/x64/D3D12Core.dll"
"$<TARGET_FILE_DIR:D3D12Sample>/D3D12/"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${D3D12MA_AGILITY_SDK_DIRECTORY}/build/native/bin/x64/d3d12SDKLayers.dll"
"$<TARGET_FILE_DIR:D3D12Sample>/D3D12/")
endif()
else()
message(FATAL_ERROR "DX12 Agility SDK not found - cannot find file \"${D3D12MA_AGILITY_SDK_DIRECTORY}/build/native/include/d3d12.h\".")
endif()
else()
message(STATUS "DX12 Agility SDK not used.")
endif()

option(D3D12MA_OPTIONS16_SUPPORTED "Set if using Agility SDK 1.710.0-preview or newer that defines D3D12_FEATURE_DATA_D3D12_OPTIONS16." OFF)
if(D3D12MA_OPTIONS16_SUPPORTED)
target_compile_definitions(D3D12MemoryAllocator PRIVATE D3D12MA_OPTIONS16_SUPPORTED=1)
if(${D3D12MA_BUILD_SAMPLE} AND ${WIN32})
target_compile_definitions(D3D12Sample PRIVATE D3D12MA_OPTIONS16_SUPPORTED=1)
endif()
endif()
111 changes: 94 additions & 17 deletions src/D3D12MemAlloc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,9 @@ especially to test compatibility with D3D12_RESOURCE_HEAP_TIER_1 on modern GPUs.

namespace D3D12MA
{
static constexpr UINT HEAP_TYPE_COUNT = 4;
static constexpr UINT STANDARD_HEAP_TYPE_COUNT = 3; // Only DEFAULT, UPLOAD, READBACK.
static constexpr UINT DEFAULT_POOL_MAX_COUNT = 9;
static constexpr UINT HEAP_TYPE_COUNT = 5;
static constexpr UINT STANDARD_HEAP_TYPE_COUNT = 4; // Only DEFAULT, UPLOAD, READBACK, GPU_UPLOAD.
static constexpr UINT DEFAULT_POOL_MAX_COUNT = STANDARD_HEAP_TYPE_COUNT * 3;
static const UINT NEW_BLOCK_SIZE_SHIFT_MAX = 3;
// Minimum size of a free suballocation to register it in the free suballocation collection.
static const UINT64 MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER = 16;
Expand All @@ -147,19 +147,23 @@ static const WCHAR* const HeapTypeNames[] =
L"UPLOAD",
L"READBACK",
L"CUSTOM",
L"GPU_UPLOAD",
};
static const WCHAR* const StandardHeapTypeNames[] =
{
L"DEFAULT",
L"UPLOAD",
L"READBACK",
L"GPU_UPLOAD",
};

static const D3D12_HEAP_FLAGS RESOURCE_CLASS_HEAP_FLAGS =
D3D12_HEAP_FLAG_DENY_BUFFERS | D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES | D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES;

static const D3D12_RESIDENCY_PRIORITY D3D12_RESIDENCY_PRIORITY_NONE = D3D12_RESIDENCY_PRIORITY(0);

static const D3D12_HEAP_TYPE D3D12_HEAP_TYPE_GPU_UPLOAD_COPY = (D3D12_HEAP_TYPE)5;

#ifndef _D3D12MA_ENUM_DECLARATIONS

// Local copy of this enum, as it is provided only by <dxgi1_4.h>, so it may not be available.
Expand Down Expand Up @@ -465,6 +469,7 @@ static UINT StandardHeapTypeToIndex(D3D12_HEAP_TYPE type)
case D3D12_HEAP_TYPE_DEFAULT: return 0;
case D3D12_HEAP_TYPE_UPLOAD: return 1;
case D3D12_HEAP_TYPE_READBACK: return 2;
case D3D12_HEAP_TYPE_GPU_UPLOAD_COPY: return 3;
default: D3D12MA_ASSERT(0); return UINT_MAX;
}
}
Expand All @@ -476,6 +481,7 @@ static D3D12_HEAP_TYPE IndexToStandardHeapType(UINT heapTypeIndex)
case 0: return D3D12_HEAP_TYPE_DEFAULT;
case 1: return D3D12_HEAP_TYPE_UPLOAD;
case 2: return D3D12_HEAP_TYPE_READBACK;
case 3: return D3D12_HEAP_TYPE_GPU_UPLOAD_COPY;
default: D3D12MA_ASSERT(0); return D3D12_HEAP_TYPE_CUSTOM;
}
}
Expand Down Expand Up @@ -525,7 +531,8 @@ static bool IsHeapTypeStandard(D3D12_HEAP_TYPE type)
{
return type == D3D12_HEAP_TYPE_DEFAULT ||
type == D3D12_HEAP_TYPE_UPLOAD ||
type == D3D12_HEAP_TYPE_READBACK;
type == D3D12_HEAP_TYPE_READBACK ||
type == D3D12_HEAP_TYPE_GPU_UPLOAD_COPY;
}

static D3D12_HEAP_PROPERTIES StandardHeapTypeToHeapProperties(D3D12_HEAP_TYPE type)
Expand Down Expand Up @@ -6567,6 +6574,7 @@ class AllocatorPimpl
BOOL IsUMA() const { return m_D3D12Architecture.UMA; }
BOOL IsCacheCoherentUMA() const { return m_D3D12Architecture.CacheCoherentUMA; }
bool SupportsResourceHeapTier2() const { return m_D3D12Options.ResourceHeapTier >= D3D12_RESOURCE_HEAP_TIER_2; }
bool IsGPUUploadHeapSupported() const { return m_GPUUploadHeapSupported != FALSE; }
bool UseMutex() const { return m_UseMutex; }
AllocationObjectAllocator& GetAllocationObjectAllocator() { return m_AllocationObjectAllocator; }
UINT GetCurrentFrameIndex() const { return m_CurrentFrameIndex.load(); }
Expand All @@ -6575,6 +6583,7 @@ class AllocatorPimpl
0: D3D12_HEAP_TYPE_DEFAULT
1: D3D12_HEAP_TYPE_UPLOAD
2: D3D12_HEAP_TYPE_READBACK
3: D3D12_HEAP_TYPE_GPU_UPLOAD
else:
0: D3D12_HEAP_TYPE_DEFAULT + buffer
1: D3D12_HEAP_TYPE_DEFAULT + texture
Expand All @@ -6585,8 +6594,11 @@ class AllocatorPimpl
6: D3D12_HEAP_TYPE_READBACK + buffer
7: D3D12_HEAP_TYPE_READBACK + texture
8: D3D12_HEAP_TYPE_READBACK + texture RT or DS
9: D3D12_HEAP_TYPE_GPU_UPLOAD + buffer
10: D3D12_HEAP_TYPE_GPU_UPLOAD + texture
11: D3D12_HEAP_TYPE_GPU_UPLOAD + texture RT or DS
*/
UINT GetDefaultPoolCount() const { return SupportsResourceHeapTier2() ? 3 : 9; }
UINT GetDefaultPoolCount() const { return SupportsResourceHeapTier2() ? 4 : 12; }
BlockVector** GetDefaultPools() { return m_BlockVectors; }

HRESULT Init(const ALLOCATOR_DESC& desc);
Expand Down Expand Up @@ -6673,6 +6685,7 @@ class AllocatorPimpl
D3D12MA_ATOMIC_UINT32 m_CurrentFrameIndex;
DXGI_ADAPTER_DESC m_AdapterDesc;
D3D12_FEATURE_DATA_D3D12_OPTIONS m_D3D12Options;
BOOL m_GPUUploadHeapSupported = FALSE;
D3D12_FEATURE_DATA_ARCHITECTURE m_D3D12Architecture;
AllocationObjectAllocator m_AllocationObjectAllocator;

Expand Down Expand Up @@ -6814,6 +6827,20 @@ HRESULT AllocatorPimpl::Init(const ALLOCATOR_DESC& desc)
m_D3D12Options.ResourceHeapTier = (D3D12MA_FORCE_RESOURCE_HEAP_TIER);
#endif

// You must define this macro to like `#define D3D12MA_OPTIONS16_SUPPORTED 1` to enable GPU Upload Heaps!
// Unfortunately there is no way to programmatically check if the included <d3d12.h> defines D3D12_FEATURE_DATA_D3D12_OPTIONS16 or not.
// Main interfaces have respective macros like __ID3D12Device4_INTERFACE_DEFINED__, but structures like this do not.
#if D3D12MA_OPTIONS16_SUPPORTED
{
D3D12_FEATURE_DATA_D3D12_OPTIONS16 options16 = {};
hr = m_Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS16, &options16, sizeof(options16));
if (SUCCEEDED(hr))
{
m_GPUUploadHeapSupported = options16.GPUUploadHeapSupported;
}
}
#endif

hr = m_Device->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE, &m_D3D12Architecture, sizeof(m_D3D12Architecture));
if (FAILED(hr))
{
Expand Down Expand Up @@ -6913,7 +6940,7 @@ UINT AllocatorPimpl::StandardHeapTypeToMemorySegmentGroup(D3D12_HEAP_TYPE heapTy
D3D12MA_ASSERT(IsHeapTypeStandard(heapType));
if (IsUMA())
return DXGI_MEMORY_SEGMENT_GROUP_LOCAL_COPY;
return heapType == D3D12_HEAP_TYPE_DEFAULT ?
return (heapType == D3D12_HEAP_TYPE_DEFAULT || heapType == D3D12_HEAP_TYPE_GPU_UPLOAD_COPY) ?
DXGI_MEMORY_SEGMENT_GROUP_LOCAL_COPY : DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL_COPY;
}

Expand Down Expand Up @@ -7279,15 +7306,16 @@ void AllocatorPimpl::CalculateStatistics(TotalStatistics& outStats, DetailedStat
ClearDetailedStatistics(outCustomHeaps[1]);
}

// Process default pools. 3 standard heap types only. Add them to outStats.HeapType[i].
// Process default pools. 4 standard heap types only. Add them to outStats.HeapType[i].
if (SupportsResourceHeapTier2())
{
// DEFAULT, UPLOAD, READBACK.
// DEFAULT, UPLOAD, READBACK, GPU_UPLOAD.
for (size_t heapTypeIndex = 0; heapTypeIndex < STANDARD_HEAP_TYPE_COUNT; ++heapTypeIndex)
{
BlockVector* const pBlockVector = m_BlockVectors[heapTypeIndex];
D3D12MA_ASSERT(pBlockVector);
pBlockVector->AddDetailedStatistics(outStats.HeapType[heapTypeIndex]);
const size_t outputIndex = heapTypeIndex < 3 ? heapTypeIndex : 4; // GPU_UPLOAD 3 -> 4
pBlockVector->AddDetailedStatistics(outStats.HeapType[outputIndex]);
}
}
else
Expand All @@ -7299,7 +7327,9 @@ void AllocatorPimpl::CalculateStatistics(TotalStatistics& outStats, DetailedStat
{
BlockVector* const pBlockVector = m_BlockVectors[heapTypeIndex * 3 + heapSubType];
D3D12MA_ASSERT(pBlockVector);
pBlockVector->AddDetailedStatistics(outStats.HeapType[heapTypeIndex]);

const size_t outputIndex = heapTypeIndex < 3 ? heapTypeIndex : 4; // GPU_UPLOAD 3 -> 4
pBlockVector->AddDetailedStatistics(outStats.HeapType[outputIndex]);
}
}
}
Expand All @@ -7314,6 +7344,9 @@ void AllocatorPimpl::CalculateStatistics(TotalStatistics& outStats, DetailedStat
AddDetailedStatistics(
outStats.MemorySegmentGroup[StandardHeapTypeToMemorySegmentGroup(D3D12_HEAP_TYPE_READBACK)],
outStats.HeapType[2]);
AddDetailedStatistics(
outStats.MemorySegmentGroup[StandardHeapTypeToMemorySegmentGroup(D3D12_HEAP_TYPE_GPU_UPLOAD_COPY)],
outStats.HeapType[4]);

// Process custom pools.
DetailedStatistics tmpStats;
Expand All @@ -7338,13 +7371,14 @@ void AllocatorPimpl::CalculateStatistics(TotalStatistics& outStats, DetailedStat
}
}

// Process committed allocations. 3 standard heap types only.
// Process committed allocations. standard heap types only.
for (UINT heapTypeIndex = 0; heapTypeIndex < STANDARD_HEAP_TYPE_COUNT; ++heapTypeIndex)
{
ClearDetailedStatistics(tmpStats);
m_CommittedAllocations[heapTypeIndex].AddDetailedStatistics(tmpStats);
const size_t outputIndex = heapTypeIndex < 3 ? heapTypeIndex : 4; // GPU_UPLOAD 3 -> 4
AddDetailedStatistics(
outStats.HeapType[heapTypeIndex], tmpStats);
outStats.HeapType[outputIndex], tmpStats);
AddDetailedStatistics(
outStats.MemorySegmentGroup[StandardHeapTypeToMemorySegmentGroup(IndexToStandardHeapType(heapTypeIndex))], tmpStats);
}
Expand All @@ -7366,19 +7400,24 @@ void AllocatorPimpl::CalculateStatistics(TotalStatistics& outStats, DetailedStat

D3D12MA_ASSERT(outStats.Total.Stats.BlockCount ==
outStats.HeapType[0].Stats.BlockCount + outStats.HeapType[1].Stats.BlockCount +
outStats.HeapType[2].Stats.BlockCount + outStats.HeapType[3].Stats.BlockCount);
outStats.HeapType[2].Stats.BlockCount + outStats.HeapType[3].Stats.BlockCount +
outStats.HeapType[4].Stats.BlockCount);
D3D12MA_ASSERT(outStats.Total.Stats.AllocationCount ==
outStats.HeapType[0].Stats.AllocationCount + outStats.HeapType[1].Stats.AllocationCount +
outStats.HeapType[2].Stats.AllocationCount + outStats.HeapType[3].Stats.AllocationCount);
outStats.HeapType[2].Stats.AllocationCount + outStats.HeapType[3].Stats.AllocationCount +
outStats.HeapType[4].Stats.AllocationCount);
D3D12MA_ASSERT(outStats.Total.Stats.BlockBytes ==
outStats.HeapType[0].Stats.BlockBytes + outStats.HeapType[1].Stats.BlockBytes +
outStats.HeapType[2].Stats.BlockBytes + outStats.HeapType[3].Stats.BlockBytes);
outStats.HeapType[2].Stats.BlockBytes + outStats.HeapType[3].Stats.BlockBytes +
outStats.HeapType[4].Stats.BlockBytes);
D3D12MA_ASSERT(outStats.Total.Stats.AllocationBytes ==
outStats.HeapType[0].Stats.AllocationBytes + outStats.HeapType[1].Stats.AllocationBytes +
outStats.HeapType[2].Stats.AllocationBytes + outStats.HeapType[3].Stats.AllocationBytes);
outStats.HeapType[2].Stats.AllocationBytes + outStats.HeapType[3].Stats.AllocationBytes +
outStats.HeapType[4].Stats.AllocationBytes);
D3D12MA_ASSERT(outStats.Total.UnusedRangeCount ==
outStats.HeapType[0].UnusedRangeCount + outStats.HeapType[1].UnusedRangeCount +
outStats.HeapType[2].UnusedRangeCount + outStats.HeapType[3].UnusedRangeCount);
outStats.HeapType[2].UnusedRangeCount + outStats.HeapType[3].UnusedRangeCount +
outStats.HeapType[4].UnusedRangeCount);
}

void AllocatorPimpl::GetBudget(Budget* outLocalBudget, Budget* outNonLocalBudget)
Expand Down Expand Up @@ -7426,6 +7465,7 @@ void AllocatorPimpl::GetBudgetForHeapType(Budget& outBudget, D3D12_HEAP_TYPE hea
switch (heapType)
{
case D3D12_HEAP_TYPE_DEFAULT:
case D3D12_HEAP_TYPE_GPU_UPLOAD_COPY:
GetBudget(&outBudget, NULL);
break;
case D3D12_HEAP_TYPE_UPLOAD:
Expand Down Expand Up @@ -7482,6 +7522,9 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
json.WriteBool(m_D3D12Architecture.UMA);
json.WriteString(L"CacheCoherentUMA");
json.WriteBool(m_D3D12Architecture.CacheCoherentUMA);

json.WriteString(L"GPUUploadHeapSupported");
json.WriteBool(m_GPUUploadHeapSupported != FALSE);
}
json.EndObject();
}
Expand Down Expand Up @@ -7514,6 +7557,17 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
json.AddDetailedStatisticsInfoObject(stats.HeapType[0]);
}
json.EndObject();

if(IsGPUUploadHeapSupported())
{
json.WriteString(L"GPU_UPLOAD");
json.BeginObject();
{
json.WriteString(L"Stats");
json.AddDetailedStatisticsInfoObject(stats.HeapType[4]);
}
json.EndObject();
}
}
json.WriteString(L"UPLOAD");
json.BeginObject();
Expand Down Expand Up @@ -7564,6 +7618,17 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
}
json.EndObject();

if(IsGPUUploadHeapSupported())
{
json.WriteString(L"GPU_UPLOAD");
json.BeginObject();
{
json.WriteString(L"Stats");
json.AddDetailedStatisticsInfoObject(stats.HeapType[4]);
}
json.EndObject();
}

json.WriteString(L"CUSTOM");
json.BeginObject();
{
Expand Down Expand Up @@ -8012,6 +8077,9 @@ HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, U
outCommittedAllocationParams = CommittedAllocationParameters();
outPreferCommitted = false;

D3D12MA_ASSERT((allocDesc.HeapType != D3D12_HEAP_TYPE_GPU_UPLOAD_COPY || IsGPUUploadHeapSupported()) &&
"Trying to allocate from D3D12_HEAP_TYPE_GPU_UPLOAD while GPUUploadHeapSupported == FALSE or D3D12MA_OPTIONS16_SUPPORTED macro was not defined when compiling D3D12MA library.");

bool msaaAlwaysCommitted;
if (allocDesc.CustomPool != NULL)
{
Expand Down Expand Up @@ -8111,6 +8179,7 @@ UINT AllocatorPimpl::CalcDefaultPoolIndex(const ALLOCATION_DESC& allocDesc, Reso
case D3D12_HEAP_TYPE_DEFAULT: poolIndex = 0; break;
case D3D12_HEAP_TYPE_UPLOAD: poolIndex = 1; break;
case D3D12_HEAP_TYPE_READBACK: poolIndex = 2; break;
case D3D12_HEAP_TYPE_GPU_UPLOAD_COPY: poolIndex = 3; break;
default: D3D12MA_ASSERT(0);
}

Expand Down Expand Up @@ -8166,6 +8235,9 @@ void AllocatorPimpl::CalcDefaultPoolParams(D3D12_HEAP_TYPE& outHeapType, D3D12_H
case 2:
outHeapType = D3D12_HEAP_TYPE_READBACK;
break;
case 3:
outHeapType = D3D12_HEAP_TYPE_GPU_UPLOAD_COPY;
break;
default:
D3D12MA_ASSERT(0);
}
Expand Down Expand Up @@ -10173,6 +10245,11 @@ BOOL Allocator::IsCacheCoherentUMA() const
return m_Pimpl->IsCacheCoherentUMA();
}

BOOL Allocator::IsGPUUploadHeapSupported() const
{
return m_Pimpl->IsGPUUploadHeapSupported();
}

UINT64 Allocator::GetMemoryCapacity(UINT memorySegmentGroup) const
{
return m_Pimpl->GetMemoryCapacity(memorySegmentGroup);
Expand Down
Loading

0 comments on commit 47ebce5

Please sign in to comment.