Gfx partition with 64KB and 2MB heap granularities

Related-To: NEO-5507

Signed-off-by: Milczarek, Slawomir <slawomir.milczarek@intel.com>
This commit is contained in:
Milczarek, Slawomir 2021-03-24 11:37:13 +00:00 committed by Compute-Runtime-Automation
parent 2258836b86
commit 75f3b416ae
5 changed files with 50 additions and 30 deletions

View File

@ -80,17 +80,18 @@ void testGfxPartition(MockGfxPartition &gfxPartition, uint64_t gfxBase, uint64_t
gfxBase += sizeHeap32;
}
uint32_t numStandardHeaps = static_cast<uint32_t>(HeapIndex::HEAP_STANDARD2MB) - static_cast<uint32_t>(HeapIndex::HEAP_STANDARD) + 1;
uint64_t sizeStandard = alignDown((gfxTop - gfxBase) / numStandardHeaps, GfxPartition::heapGranularity);
constexpr uint32_t numStandardHeaps = static_cast<uint32_t>(HeapIndex::HEAP_STANDARD2MB) - static_cast<uint32_t>(HeapIndex::HEAP_STANDARD) + 1;
constexpr uint64_t maxStandardHeapGranularity = std::max(GfxPartition::heapGranularity, GfxPartition::heapGranularity2MB);
uint64_t maxStandardHeapSize = alignDown((gfxTop - gfxBase) / numStandardHeaps, maxStandardHeapGranularity);
EXPECT_TRUE(gfxPartition.heapInitialized(HeapIndex::HEAP_STANDARD));
auto heapStandardBase = gfxPartition.getHeapBase(HeapIndex::HEAP_STANDARD);
auto heapStandardSize = gfxPartition.getHeapSize(HeapIndex::HEAP_STANDARD);
EXPECT_TRUE(isAligned<GfxPartition::heapGranularity>(heapStandardBase));
EXPECT_EQ(heapStandardBase, gfxBase);
EXPECT_EQ(heapStandardSize, sizeStandard);
EXPECT_EQ(heapStandardSize, maxStandardHeapSize);
gfxBase += sizeStandard;
gfxBase += maxStandardHeapSize;
EXPECT_TRUE(gfxPartition.heapInitialized(HeapIndex::HEAP_STANDARD64KB));
auto heapStandard64KbBase = gfxPartition.getHeapBase(HeapIndex::HEAP_STANDARD64KB);
auto heapStandard64KbSize = gfxPartition.getHeapSize(HeapIndex::HEAP_STANDARD64KB);
@ -98,7 +99,7 @@ void testGfxPartition(MockGfxPartition &gfxPartition, uint64_t gfxBase, uint64_t
EXPECT_EQ(heapStandard64KbBase, heapStandardBase + heapStandardSize);
EXPECT_EQ(heapStandard64KbSize, heapStandardSize);
gfxBase += sizeStandard;
gfxBase += maxStandardHeapSize;
EXPECT_TRUE(gfxPartition.heapInitialized(HeapIndex::HEAP_STANDARD2MB));
auto heapStandard2MbBase = gfxPartition.getHeapBase(HeapIndex::HEAP_STANDARD2MB);
auto heapStandard2MbSize = gfxPartition.getHeapSize(HeapIndex::HEAP_STANDARD2MB);
@ -107,7 +108,7 @@ void testGfxPartition(MockGfxPartition &gfxPartition, uint64_t gfxBase, uint64_t
EXPECT_EQ(heapStandard2MbSize, heapStandard64KbSize);
EXPECT_LE(heapStandard2MbBase + heapStandard2MbSize, gfxTop);
EXPECT_LE(gfxBase + sizeStandard, gfxTop);
EXPECT_LE(gfxBase + maxStandardHeapSize, gfxTop);
EXPECT_EQ(gfxPartition.getHeapMinimalAddress(HeapIndex::HEAP_INTERNAL_FRONT_WINDOW), gfxPartition.getHeapBase(HeapIndex::HEAP_INTERNAL_FRONT_WINDOW));
EXPECT_EQ(gfxPartition.getHeapMinimalAddress(HeapIndex::HEAP_INTERNAL_DEVICE_FRONT_WINDOW), gfxPartition.getHeapBase(HeapIndex::HEAP_INTERNAL_DEVICE_FRONT_WINDOW));
@ -121,6 +122,7 @@ void testGfxPartition(MockGfxPartition &gfxPartition, uint64_t gfxBase, uint64_t
}
const bool isInternalHeapType = heap == HeapIndex::HEAP_INTERNAL || heap == HeapIndex::HEAP_INTERNAL_DEVICE_MEMORY;
const auto heapGranularity = (heap == HeapIndex::HEAP_STANDARD2MB) ? GfxPartition::heapGranularity2MB : GfxPartition::heapGranularity;
if (heap == HeapIndex::HEAP_SVM) {
EXPECT_EQ(gfxPartition.getHeapMinimalAddress(heap), gfxPartition.getHeapBase(heap));
@ -128,7 +130,7 @@ void testGfxPartition(MockGfxPartition &gfxPartition, uint64_t gfxBase, uint64_t
EXPECT_EQ(gfxPartition.getHeapMinimalAddress(heap), gfxPartition.getHeapBase(heap) + GfxPartition::internalFrontWindowPoolSize);
} else {
EXPECT_GT(gfxPartition.getHeapMinimalAddress(heap), gfxPartition.getHeapBase(heap));
EXPECT_EQ(gfxPartition.getHeapMinimalAddress(heap), gfxPartition.getHeapBase(heap) + GfxPartition::heapGranularity);
EXPECT_EQ(gfxPartition.getHeapMinimalAddress(heap), gfxPartition.getHeapBase(heap) + heapGranularity);
}
auto ptrBig = gfxPartition.heapAllocate(heap, sizeBig);
@ -137,7 +139,7 @@ void testGfxPartition(MockGfxPartition &gfxPartition, uint64_t gfxBase, uint64_t
if (isInternalHeapType) {
EXPECT_EQ(ptrBig, gfxPartition.getHeapBase(heap) + GfxPartition::internalFrontWindowPoolSize);
} else {
EXPECT_EQ(ptrBig, gfxPartition.getHeapBase(heap) + GfxPartition::heapGranularity);
EXPECT_EQ(ptrBig, gfxPartition.getHeapBase(heap) + heapGranularity);
}
gfxPartition.heapFree(heap, ptrBig, sizeBig);
@ -146,7 +148,7 @@ void testGfxPartition(MockGfxPartition &gfxPartition, uint64_t gfxBase, uint64_t
EXPECT_LT(gfxPartition.getHeapBase(heap), ptrSmall);
EXPECT_GT(gfxPartition.getHeapLimit(heap), ptrSmall);
EXPECT_EQ(ptrSmall, gfxPartition.getHeapBase(heap) + gfxPartition.getHeapSize(heap) - GfxPartition::heapGranularity - sizeSmall);
EXPECT_EQ(ptrSmall, gfxPartition.getHeapBase(heap) + gfxPartition.getHeapSize(heap) - heapGranularity - sizeSmall);
gfxPartition.heapFree(heap, ptrSmall, sizeSmall);
}
@ -213,12 +215,13 @@ TEST(GfxPartitionTest, GivenFullRange48BitSvmHeap64KbSplitWhenTestingGfxPartitio
uint64_t gfxBase = is32bit ? MemoryConstants::maxSvmAddress + 1 : maxNBitValue(48 - 1) + 1;
uint64_t gfxTop = maxNBitValue(48) + 1;
auto numStandardHeaps = static_cast<uint32_t>(HeapIndex::HEAP_STANDARD2MB) - static_cast<uint32_t>(HeapIndex::HEAP_STANDARD) + 1;
auto heapStandardSize = alignDown((gfxTop - gfxBase - 4 * sizeHeap32) / numStandardHeaps, GfxPartition::heapGranularity);
auto heapStandard64KBSize = alignDown(heapStandardSize / numRootDevices, GfxPartition::heapGranularity);
constexpr auto numStandardHeaps = static_cast<uint32_t>(HeapIndex::HEAP_STANDARD2MB) - static_cast<uint32_t>(HeapIndex::HEAP_STANDARD) + 1;
constexpr auto maxStandardHeapGranularity = std::max(GfxPartition::heapGranularity, GfxPartition::heapGranularity2MB);
auto maxStandardHeapSize = alignDown((gfxTop - gfxBase - 4 * sizeHeap32) / numStandardHeaps, maxStandardHeapGranularity);
auto heapStandard64KBSize = alignDown(maxStandardHeapSize / numRootDevices, GfxPartition::heapGranularity);
EXPECT_EQ(heapStandard64KBSize, gfxPartition.getHeapSize(HeapIndex::HEAP_STANDARD64KB));
EXPECT_EQ(gfxBase + 4 * sizeHeap32 + heapStandardSize + rootDeviceIndex * heapStandard64KBSize, gfxPartition.getHeapBase(HeapIndex::HEAP_STANDARD64KB));
EXPECT_EQ(gfxBase + 4 * sizeHeap32 + maxStandardHeapSize + rootDeviceIndex * heapStandard64KBSize, gfxPartition.getHeapBase(HeapIndex::HEAP_STANDARD64KB));
}
TEST(GfxPartitionTest, GivenFullRange47BitSvmHeap64KbSplitWhenTestingGfxPartitionThenAllExpectationsAreMet) {
@ -231,12 +234,13 @@ TEST(GfxPartitionTest, GivenFullRange47BitSvmHeap64KbSplitWhenTestingGfxPartitio
uint64_t gfxBase = is32bit ? MemoryConstants::maxSvmAddress + 1 : (uint64_t)gfxPartition.getReservedCpuAddressRange();
uint64_t gfxTop = is32bit ? maxNBitValue(47) + 1 : gfxBase + gfxPartition.getReservedCpuAddressRangeSize();
auto numStandardHeaps = static_cast<uint32_t>(HeapIndex::HEAP_STANDARD2MB) - static_cast<uint32_t>(HeapIndex::HEAP_STANDARD) + 1;
auto heapStandardSize = alignDown((gfxTop - gfxBase - 4 * sizeHeap32) / numStandardHeaps, GfxPartition::heapGranularity);
auto heapStandard64KBSize = alignDown(heapStandardSize / numRootDevices, GfxPartition::heapGranularity);
constexpr auto numStandardHeaps = static_cast<uint32_t>(HeapIndex::HEAP_STANDARD2MB) - static_cast<uint32_t>(HeapIndex::HEAP_STANDARD) + 1;
constexpr auto maxStandardHeapGranularity = std::max(GfxPartition::heapGranularity, GfxPartition::heapGranularity2MB);
auto maxStandardHeapSize = alignDown((gfxTop - gfxBase - 4 * sizeHeap32) / numStandardHeaps, maxStandardHeapGranularity);
auto heapStandard64KBSize = alignDown(maxStandardHeapSize / numRootDevices, GfxPartition::heapGranularity);
EXPECT_EQ(heapStandard64KBSize, gfxPartition.getHeapSize(HeapIndex::HEAP_STANDARD64KB));
EXPECT_EQ(gfxBase + 4 * sizeHeap32 + heapStandardSize + rootDeviceIndex * heapStandard64KBSize, gfxPartition.getHeapBase(HeapIndex::HEAP_STANDARD64KB));
EXPECT_EQ(gfxBase + 4 * sizeHeap32 + maxStandardHeapSize + rootDeviceIndex * heapStandard64KBSize, gfxPartition.getHeapBase(HeapIndex::HEAP_STANDARD64KB));
}
class MockOsMemory : public OSMemory {

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2020 Intel Corporation
* Copyright (C) 2019-2021 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@ -16,4 +16,5 @@ std::array<HeapIndex, static_cast<uint32_t>(HeapIndex::TOTAL_HEAPS)>
HeapIndex::HEAP_EXTERNAL,
HeapIndex::HEAP_STANDARD,
HeapIndex::HEAP_STANDARD64KB,
HeapIndex::HEAP_STANDARD2MB,
HeapIndex::HEAP_SVM}};

View File

@ -1103,7 +1103,7 @@ TEST_F(WddmGfxPartitionTest, WhenInitializingGfxPartitionThenAllHeapsAreInitiali
for (auto heap : MockGfxPartition::allHeapNames) {
if (!gfxPartition.heapInitialized(heap)) {
EXPECT_TRUE(heap == HeapIndex::HEAP_SVM || heap == HeapIndex::HEAP_EXTENDED);
EXPECT_TRUE(heap == HeapIndex::HEAP_SVM || heap == HeapIndex::HEAP_STANDARD2MB || heap == HeapIndex::HEAP_EXTENDED);
} else {
EXPECT_TRUE(gfxPartition.heapInitialized(heap));
}

View File

@ -38,12 +38,17 @@ void GfxPartition::Heap::init(uint64_t base, uint64_t size, size_t allocationAli
this->base = base;
this->size = size;
// Exclude very first and very last 64K from GPU address range allocation
if (size > 2 * GfxPartition::heapGranularity) {
size -= 2 * GfxPartition::heapGranularity;
auto heapGranularity = GfxPartition::heapGranularity;
if (allocationAlignment > heapGranularity) {
heapGranularity = GfxPartition::heapGranularity2MB;
}
alloc = std::make_unique<HeapAllocator>(base + GfxPartition::heapGranularity, size, allocationAlignment);
// Exclude very first and very last 64K from GPU address range allocation
if (size > 2 * heapGranularity) {
size -= 2 * heapGranularity;
}
alloc = std::make_unique<HeapAllocator>(base + heapGranularity, size, allocationAlignment);
}
void GfxPartition::Heap::initExternalWithFrontWindow(uint64_t base, uint64_t size) {
@ -184,20 +189,27 @@ bool GfxPartition::init(uint64_t gpuAddressSpace, size_t cpuAddressRangeSizeToRe
gfxBase += gfxHeap32Size;
}
uint32_t numStandardHeaps = static_cast<uint32_t>(HeapIndex::HEAP_STANDARD2MB) - static_cast<uint32_t>(HeapIndex::HEAP_STANDARD) + 1;
uint64_t gfxStandardSize = alignDown((gfxTop - gfxBase) / numStandardHeaps, heapGranularity);
constexpr uint32_t numStandardHeaps = static_cast<uint32_t>(HeapIndex::HEAP_STANDARD2MB) - static_cast<uint32_t>(HeapIndex::HEAP_STANDARD) + 1;
constexpr uint64_t maxStandardHeapGranularity = std::max(GfxPartition::heapGranularity, GfxPartition::heapGranularity2MB);
uint64_t maxStandardHeapSize = alignDown((gfxTop - gfxBase) / numStandardHeaps, maxStandardHeapGranularity);
auto gfxStandardSize = maxStandardHeapSize;
heapInit(HeapIndex::HEAP_STANDARD, gfxBase, gfxStandardSize);
gfxBase += gfxStandardSize;
DEBUG_BREAK_IF(!isAligned<GfxPartition::heapGranularity>(getHeapBase(HeapIndex::HEAP_STANDARD)));
gfxBase += maxStandardHeapSize;
// Split HEAP_STANDARD64K among root devices
auto gfxStandard64KBSize = alignDown(gfxStandardSize / numRootDevices, GfxPartition::heapGranularity);
auto gfxStandard64KBSize = alignDown(maxStandardHeapSize / numRootDevices, GfxPartition::heapGranularity);
heapInitWithAllocationAlignment(HeapIndex::HEAP_STANDARD64KB, gfxBase + rootDeviceIndex * gfxStandard64KBSize, gfxStandard64KBSize, MemoryConstants::pageSize64k);
gfxBase += gfxStandardSize;
DEBUG_BREAK_IF(!isAligned<GfxPartition::heapGranularity>(getHeapBase(HeapIndex::HEAP_STANDARD64KB)));
gfxBase += maxStandardHeapSize;
// Split HEAP_STANDARD2MB among root devices
auto gfxStandard2MBSize = alignDown(gfxStandardSize / numRootDevices, GfxPartition::heapGranularity);
auto gfxStandard2MBSize = alignDown(maxStandardHeapSize / numRootDevices, GfxPartition::heapGranularity2MB);
heapInitWithAllocationAlignment(HeapIndex::HEAP_STANDARD2MB, gfxBase + rootDeviceIndex * gfxStandard2MBSize, gfxStandard2MBSize, 2 * MemoryConstants::megaByte);
DEBUG_BREAK_IF(!isAligned<GfxPartition::heapGranularity2MB>(getHeapBase(HeapIndex::HEAP_STANDARD2MB)));
return true;
}

View File

@ -98,6 +98,8 @@ class GfxPartition {
} else if (heapIndex == HeapIndex::HEAP_INTERNAL ||
heapIndex == HeapIndex::HEAP_INTERNAL_DEVICE_MEMORY) {
return getHeapBase(heapIndex) + GfxPartition::internalFrontWindowPoolSize;
} else if (heapIndex == HeapIndex::HEAP_STANDARD2MB) {
return getHeapBase(heapIndex) + GfxPartition::heapGranularity2MB;
}
return getHeapBase(heapIndex) + GfxPartition::heapGranularity;
}
@ -105,7 +107,8 @@ class GfxPartition {
bool isLimitedRange() { return getHeap(HeapIndex::HEAP_SVM).getSize() == 0ull; }
static const uint64_t heapGranularity = 2 * MemoryConstants::megaByte;
static constexpr uint64_t heapGranularity = MemoryConstants::pageSize64k;
static constexpr uint64_t heapGranularity2MB = 2 * MemoryConstants::megaByte;
static constexpr size_t externalFrontWindowPoolSize = 16 * MemoryConstants::megaByte;
static constexpr size_t internalFrontWindowPoolSize = 1 * MemoryConstants::megaByte;