Add globalDsh and ssh for scratch in bindlessHeapHelper

Change-Id: Ieab07271425a2898d79854a3d0b3ade25bc37c51
Signed-off-by: Maciej Plewka <maciej.plewka@intel.com>
This commit is contained in:
Maciej Plewka
2020-11-03 11:42:35 +01:00
committed by sys_ocldev
parent f4158e10ff
commit 4745b7d20b
3 changed files with 116 additions and 64 deletions

View File

@@ -14,19 +14,18 @@
namespace NEO {
constexpr size_t globalSshAllocationSize = 4 * MemoryConstants::pageSize64k;
using BindlesHeapType = BindlessHeapsHelper::BindlesHeapType;
BindlessHeapsHelper::BindlessHeapsHelper(MemoryManager *memManager, bool isMultiOsContextCapable, const uint32_t rootDeviceIndex) : memManager(memManager), isMultiOsContextCapable(isMultiOsContextCapable), rootDeviceIndex(rootDeviceIndex) {
auto specialHeapAllocation = getHeapAllocation(MemoryConstants::pageSize64k, MemoryConstants::pageSize64k);
UNRECOVERABLE_IF(specialHeapAllocation == nullptr);
ssHeapsAllocations.push_back(specialHeapAllocation);
specialSsh = std::make_unique<IndirectHeap>(specialHeapAllocation, false);
for (auto heapType = 0; heapType < BindlesHeapType::NUM_HEAP_TYPES; heapType++) {
auto allocInFrontWindow = heapType != BindlesHeapType::GLOBAL_DSH;
auto heapAllocation = getHeapAllocation(MemoryConstants::pageSize64k, MemoryConstants::pageSize64k, allocInFrontWindow);
UNRECOVERABLE_IF(heapAllocation == nullptr);
ssHeapsAllocations.push_back(heapAllocation);
surfaceStateHeaps[heapType] = std::make_unique<IndirectHeap>(heapAllocation, false);
}
auto globalSshAllocation = getHeapAllocation(globalSshAllocationSize, MemoryConstants::pageSize64k);
UNRECOVERABLE_IF(globalSshAllocation == nullptr);
ssHeapsAllocations.push_back(globalSshAllocation);
globalSsh = std::make_unique<IndirectHeap>(globalSshAllocation, false);
borderColorStates = getHeapAllocation(MemoryConstants::pageSize, MemoryConstants::pageSize);
borderColorStates = getHeapAllocation(MemoryConstants::pageSize, MemoryConstants::pageSize, true);
UNRECOVERABLE_IF(borderColorStates == nullptr);
float borderColorDefault[4] = {0, 0, 0, 0};
memcpy_s(borderColorStates->getUnderlyingBuffer(), sizeof(borderColorDefault), borderColorDefault, sizeof(borderColorDefault));
@@ -42,38 +41,46 @@ BindlessHeapsHelper::~BindlessHeapsHelper() {
ssHeapsAllocations.clear();
}
GraphicsAllocation *BindlessHeapsHelper::getHeapAllocation(size_t heapSize, size_t alignment) {
GraphicsAllocation *BindlessHeapsHelper::getHeapAllocation(size_t heapSize, size_t alignment, bool allocInFrontWindow) {
auto allocationType = GraphicsAllocation::AllocationType::LINEAR_STREAM;
NEO::AllocationProperties properties{rootDeviceIndex, true, heapSize, allocationType, isMultiOsContextCapable, false};
properties.flags.use32BitFrontWindow = true;
properties.flags.use32BitFrontWindow = allocInFrontWindow;
properties.alignment = alignment;
return this->memManager->allocateGraphicsMemoryWithProperties(properties);
}
SurfaceStateInHeapInfo *BindlessHeapsHelper::allocateSSInHeap(size_t ssSize, void *ssPtr, GraphicsAllocation *surfaceAllocation) {
auto ssAllocatedInfo = surfaceStateInHeapAllocationMap.find(surfaceAllocation);
if (ssAllocatedInfo != surfaceStateInHeapAllocationMap.end()) {
return ssAllocatedInfo->second.get();
SurfaceStateInHeapInfo BindlessHeapsHelper::allocateSSInHeap(size_t ssSize, GraphicsAllocation *surfaceAllocation, BindlesHeapType heapType) {
auto heap = surfaceStateHeaps[heapType].get();
if (heapType == BindlesHeapType::GLOBAL_SSH) {
auto ssAllocatedInfo = surfaceStateInHeapAllocationMap.find(surfaceAllocation);
if (ssAllocatedInfo != surfaceStateInHeapAllocationMap.end()) {
return *ssAllocatedInfo->second.get();
}
}
void *ptrInHeap = getSpaceInHeap(ssSize, heapType);
auto bindlessOffset = heap->getGraphicsAllocation()->getGpuAddress() - heap->getGraphicsAllocation()->getGpuBaseAddress() + heap->getUsed() - ssSize;
SurfaceStateInHeapInfo bindlesInfo;
if (heapType == BindlesHeapType::GLOBAL_SSH) {
std::pair<GraphicsAllocation *, std::unique_ptr<SurfaceStateInHeapInfo>> pair(surfaceAllocation, std::make_unique<SurfaceStateInHeapInfo>(SurfaceStateInHeapInfo{heap->getGraphicsAllocation(), bindlessOffset, ptrInHeap}));
bindlesInfo = *pair.second;
surfaceStateInHeapAllocationMap.insert(std::move(pair));
} else {
bindlesInfo = SurfaceStateInHeapInfo{heap->getGraphicsAllocation(), bindlessOffset, ptrInHeap};
}
void *ptrInHeap = getSpaceInSsh(ssSize);
memcpy_s(ptrInHeap, ssSize, ssPtr, ssSize);
auto bindlessOffset = globalSsh->getGraphicsAllocation()->getGpuAddress() - globalSsh->getGraphicsAllocation()->getGpuBaseAddress() + globalSsh->getUsed() - ssSize;
std::pair<GraphicsAllocation *, std::unique_ptr<SurfaceStateInHeapInfo>> pair(surfaceAllocation, std::make_unique<SurfaceStateInHeapInfo>(SurfaceStateInHeapInfo{globalSsh->getGraphicsAllocation(), bindlessOffset}));
auto bindlesInfo = pair.second.get();
surfaceStateInHeapAllocationMap.insert(std::move(pair));
return bindlesInfo;
}
void *BindlessHeapsHelper::getSpaceInSsh(size_t ssSize) {
if (globalSsh->getAvailableSpace() < ssSize) {
growGlobalSSh();
void *BindlessHeapsHelper::getSpaceInHeap(size_t ssSize, BindlesHeapType heapType) {
auto heap = surfaceStateHeaps[heapType].get();
if (heap->getAvailableSpace() < ssSize) {
growHeap(heapType);
}
return globalSsh->getSpace(ssSize);
return heap->getSpace(ssSize);
}
uint64_t BindlessHeapsHelper::getGlobalSshBase() {
return globalSsh->getGraphicsAllocation()->getGpuBaseAddress();
uint64_t BindlessHeapsHelper::getGlobalHeapsBase() {
return surfaceStateHeaps[BindlesHeapType::GLOBAL_SSH]->getGraphicsAllocation()->getGpuBaseAddress();
}
uint32_t BindlessHeapsHelper::getDefaultBorderColorOffset() {
@@ -83,13 +90,15 @@ uint32_t BindlessHeapsHelper::getAlphaBorderColorOffset() {
return getDefaultBorderColorOffset() + 4 * sizeof(float);
}
void BindlessHeapsHelper::growGlobalSSh() {
auto newAlloc = getHeapAllocation(globalSshAllocationSize, MemoryConstants::pageSize64k);
void BindlessHeapsHelper::growHeap(BindlesHeapType heapType) {
auto heap = surfaceStateHeaps[heapType].get();
auto allocInFrontWindow = heapType != BindlesHeapType::GLOBAL_DSH;
auto newAlloc = getHeapAllocation(globalSshAllocationSize, MemoryConstants::pageSize64k, allocInFrontWindow);
UNRECOVERABLE_IF(newAlloc == nullptr);
ssHeapsAllocations.push_back(newAlloc);
globalSsh->replaceGraphicsAllocation(newAlloc);
globalSsh->replaceBuffer(newAlloc->getUnderlyingBuffer(),
newAlloc->getUnderlyingBufferSize());
heap->replaceGraphicsAllocation(newAlloc);
heap->replaceBuffer(newAlloc->getUnderlyingBuffer(),
newAlloc->getUnderlyingBufferSize());
}
} // namespace NEO

View File

@@ -24,27 +24,34 @@ class GraphicsAllocation;
struct SurfaceStateInHeapInfo {
GraphicsAllocation *heapAllocation;
uint64_t surfaceStateOffset;
void *ssPtr;
};
class BindlessHeapsHelper {
public:
enum BindlesHeapType {
SPECIAL_SSH = 0,
GLOBAL_SSH,
GLOBAL_DSH,
SCRATCH_SSH,
NUM_HEAP_TYPES
};
BindlessHeapsHelper(MemoryManager *memManager, bool isMultiOsContextCapable, const uint32_t rootDeviceIndex);
~BindlessHeapsHelper();
GraphicsAllocation *getHeapAllocation(size_t heapSize, size_t alignment);
GraphicsAllocation *getHeapAllocation(size_t heapSize, size_t alignment, bool allocInFrontWindow);
SurfaceStateInHeapInfo *allocateSSInHeap(size_t ssSize, void *ssPtr, GraphicsAllocation *surfaceAllocation);
uint64_t getGlobalSshBase();
void *getSpaceInSsh(size_t ssSize);
SurfaceStateInHeapInfo allocateSSInHeap(size_t ssSize, GraphicsAllocation *surfaceAllocation, BindlesHeapType heapType);
uint64_t getGlobalHeapsBase();
void *getSpaceInHeap(size_t ssSize, BindlesHeapType heapType);
uint32_t getDefaultBorderColorOffset();
uint32_t getAlphaBorderColorOffset();
protected:
void growGlobalSSh();
void growHeap(BindlesHeapType heapType);
MemoryManager *memManager = nullptr;
bool isMultiOsContextCapable = false;
const uint32_t rootDeviceIndex;
std::unique_ptr<IndirectHeap> specialSsh;
std::unique_ptr<IndirectHeap> globalSsh;
std::unique_ptr<IndirectHeap> surfaceStateHeaps[BindlesHeapType::NUM_HEAP_TYPES];
GraphicsAllocation *borderColorStates;
std::vector<GraphicsAllocation *> ssHeapsAllocations;
std::unordered_map<GraphicsAllocation *, std::unique_ptr<SurfaceStateInHeapInfo>> surfaceStateInHeapAllocationMap;

View File

@@ -19,16 +19,25 @@ using namespace NEO;
class MockBindlesHeapsHelper : public BindlessHeapsHelper {
public:
using BaseClass = BindlessHeapsHelper;
MockBindlesHeapsHelper(MemoryManager *memManager, bool isMultiOsContextCapable, const uint32_t rootDeviceIndex) : BaseClass(memManager, isMultiOsContextCapable, rootDeviceIndex) {}
MockBindlesHeapsHelper(MemoryManager *memManager, bool isMultiOsContextCapable, const uint32_t rootDeviceIndex) : BaseClass(memManager, isMultiOsContextCapable, rootDeviceIndex) {
globalSsh = surfaceStateHeaps[BindlesHeapType::GLOBAL_SSH].get();
specialSsh = surfaceStateHeaps[BindlesHeapType::SPECIAL_SSH].get();
scratchSsh = surfaceStateHeaps[BindlesHeapType::SPECIAL_SSH].get();
globalDsh = surfaceStateHeaps[BindlesHeapType::SPECIAL_SSH].get();
}
using BindlesHeapType = BindlessHeapsHelper::BindlesHeapType;
using BaseClass::borderColorStates;
using BaseClass::globalSsh;
using BaseClass::growGlobalSSh;
using BaseClass::growHeap;
using BaseClass::isMultiOsContextCapable;
using BaseClass::memManager;
using BaseClass::rootDeviceIndex;
using BaseClass::specialSsh;
using BaseClass::ssHeapsAllocations;
using BaseClass::surfaceStateInHeapAllocationMap;
IndirectHeap *specialSsh;
IndirectHeap *globalSsh;
IndirectHeap *scratchSsh;
IndirectHeap *globalDsh;
};
TEST(BindlessHeapsHelper, givenBindlessModeFlagEnabledWhenCreatingRootDevicesThenBindlesHeapHelperCreated) {
@@ -59,9 +68,7 @@ TEST_F(BindlessHeapsHelperTests, givenBindlessHepaHelperWhenAllocatSsInHeapThenH
MockGraphicsAllocation alloc;
size_t size = 0x40;
auto ss = std::make_unique<uint8_t[]>(size);
memset(ss.get(), 35, size);
bindlessHeapHelper->allocateSSInHeap(size, ss.get(), &alloc);
bindlessHeapHelper->allocateSSInHeap(size, &alloc, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
auto usedAfter = bindlessHeapHelper->globalSsh->getUsed();
EXPECT_GT(usedAfter, usedBefore);
}
@@ -71,12 +78,10 @@ TEST_F(BindlessHeapsHelperTests, givenBindlessHepaHelperWhenAllocateSsInHeapThen
MockGraphicsAllocation alloc;
size_t size = 0x40;
auto ss = std::make_unique<uint8_t[]>(size);
memset(ss.get(), 35, size);
bindlessHeapHelper->allocateSSInHeap(size, ss.get(), &alloc);
auto ssInHeapInfo = bindlessHeapHelper->allocateSSInHeap(size, &alloc, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
auto allocInHeapPtr = bindlessHeapHelper->globalSsh->getGraphicsAllocation()->getUnderlyingBuffer();
EXPECT_EQ(memcmp(ss.get(), allocInHeapPtr, size), 0);
EXPECT_EQ(ssInHeapInfo.ssPtr, allocInHeapPtr);
}
TEST_F(BindlessHeapsHelperTests, givenBindlessHepaHelperWhenAllocateSsInHeapTwiceForTheSameAllocationThenTheSameOffsetReturned) {
@@ -84,12 +89,10 @@ TEST_F(BindlessHeapsHelperTests, givenBindlessHepaHelperWhenAllocateSsInHeapTwic
MockGraphicsAllocation alloc;
size_t size = 0x40;
auto ss = std::make_unique<uint8_t[]>(size);
memset(ss.get(), 35, size);
auto ssInHeapInfo1 = bindlessHeapHelper->allocateSSInHeap(size, ss.get(), &alloc);
auto ssInHeapInfo2 = bindlessHeapHelper->allocateSSInHeap(size, ss.get(), &alloc);
auto ssInHeapInfo1 = bindlessHeapHelper->allocateSSInHeap(size, &alloc, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
auto ssInHeapInfo2 = bindlessHeapHelper->allocateSSInHeap(size, &alloc, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
EXPECT_EQ(ssInHeapInfo1->surfaceStateOffset, ssInHeapInfo2->surfaceStateOffset);
EXPECT_EQ(ssInHeapInfo1.surfaceStateOffset, ssInHeapInfo2.surfaceStateOffset);
}
TEST_F(BindlessHeapsHelperTests, givenBindlessHepaHelperWhenAllocateSsInHeapTwiceForDifferentAllocationThenDifferentOffsetsReturned) {
@@ -100,10 +103,10 @@ TEST_F(BindlessHeapsHelperTests, givenBindlessHepaHelperWhenAllocateSsInHeapTwic
size_t size = 0x40;
auto ss = std::make_unique<uint8_t[]>(size);
memset(ss.get(), 35, size);
auto ssInHeapInfo1 = bindlessHeapHelper->allocateSSInHeap(size, ss.get(), &alloc1);
auto ssInHeapInfo2 = bindlessHeapHelper->allocateSSInHeap(size, ss.get(), &alloc2);
auto ssInHeapInfo1 = bindlessHeapHelper->allocateSSInHeap(size, &alloc1, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
auto ssInHeapInfo2 = bindlessHeapHelper->allocateSSInHeap(size, &alloc2, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
EXPECT_NE(ssInHeapInfo1->surfaceStateOffset, ssInHeapInfo2->surfaceStateOffset);
EXPECT_NE(ssInHeapInfo1.surfaceStateOffset, ssInHeapInfo2.surfaceStateOffset);
}
TEST_F(BindlessHeapsHelperTests, givenBindlessHepaHelperWhenAllocateMoreSsThanNewHeapAllocationCreated) {
@@ -112,13 +115,11 @@ TEST_F(BindlessHeapsHelperTests, givenBindlessHepaHelperWhenAllocateMoreSsThanNe
auto ssCount = bindlessHeapHelper->globalSsh->getAvailableSpace() / ssSize;
auto graphicsAllocations = std::make_unique<MockGraphicsAllocation[]>(ssCount);
auto ssAllocationBefore = bindlessHeapHelper->globalSsh->getGraphicsAllocation();
auto ss = std::make_unique<uint8_t[]>(ssSize);
memset(ss.get(), 35, ssSize);
for (uint32_t i = 0; i < ssCount; i++) {
bindlessHeapHelper->allocateSSInHeap(ssSize, ss.get(), &graphicsAllocations[i]);
bindlessHeapHelper->allocateSSInHeap(ssSize, &graphicsAllocations[i], BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
}
MockGraphicsAllocation alloc;
bindlessHeapHelper->allocateSSInHeap(ssSize, ss.get(), &alloc);
bindlessHeapHelper->allocateSSInHeap(ssSize, &alloc, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
auto ssAllocationAfter = bindlessHeapHelper->globalSsh->getGraphicsAllocation();
@@ -128,7 +129,7 @@ TEST_F(BindlessHeapsHelperTests, givenBindlessHepaHelperWhenAllocateMoreSsThanNe
TEST_F(BindlessHeapsHelperTests, givenBindlessHepaHelperWhenCreatedThenAllocationsHaveTheSameBaseAddress) {
auto bindlessHeapHelper = std::make_unique<MockBindlesHeapsHelper>(pDevice->getMemoryManager(), pDevice->getNumAvailableDevices() > 1, pDevice->getRootDeviceIndex());
for (auto allocation : bindlessHeapHelper->ssHeapsAllocations) {
EXPECT_EQ(allocation->getGpuBaseAddress(), bindlessHeapHelper->getGlobalSshBase());
EXPECT_EQ(allocation->getGpuBaseAddress(), bindlessHeapHelper->getGlobalHeapsBase());
}
}
@@ -142,4 +143,39 @@ TEST_F(BindlessHeapsHelperTests, givenBindlessHepaHelperWhenGetAlphaBorderColorO
auto bindlessHeapHelper = std::make_unique<MockBindlesHeapsHelper>(pDevice->getMemoryManager(), pDevice->getNumAvailableDevices() > 1, pDevice->getRootDeviceIndex());
auto expectedOffset = bindlessHeapHelper->borderColorStates->getGpuAddress() - bindlessHeapHelper->borderColorStates->getGpuBaseAddress() + 4 * sizeof(float);
EXPECT_EQ(bindlessHeapHelper->getAlphaBorderColorOffset(), expectedOffset);
}
TEST_F(BindlessHeapsHelperTests, givenBindlessHepaHelperWhenAllocatSsInSpecialHeapThenOffsetLessThanFrontWindowSize) {
auto bindlessHeapHelper = std::make_unique<MockBindlesHeapsHelper>(pDevice->getMemoryManager(), pDevice->getNumAvailableDevices() > 1, pDevice->getRootDeviceIndex());
MockGraphicsAllocation alloc;
size_t size = 0x40;
auto ssInHeapInfo = bindlessHeapHelper->allocateSSInHeap(size, &alloc, BindlessHeapsHelper::BindlesHeapType::SPECIAL_SSH);
auto frontWindowSize = GfxPartition::externalFrontWindowPoolSize;
EXPECT_LT(ssInHeapInfo.surfaceStateOffset, frontWindowSize);
}
TEST_F(BindlessHeapsHelperTests, givenBindlessHepaHelperWhenAllocatSsInGlobalHeapThenOffsetLessThanFrontWindowSize) {
auto bindlessHeapHelper = std::make_unique<MockBindlesHeapsHelper>(pDevice->getMemoryManager(), pDevice->getNumAvailableDevices() > 1, pDevice->getRootDeviceIndex());
MockGraphicsAllocation alloc;
size_t size = 0x40;
auto ssInHeapInfo = bindlessHeapHelper->allocateSSInHeap(size, &alloc, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
auto frontWindowSize = GfxPartition::externalFrontWindowPoolSize;
EXPECT_LT(ssInHeapInfo.surfaceStateOffset, frontWindowSize);
}
TEST_F(BindlessHeapsHelperTests, givenBindlessHepaHelperWhenAllocatSsInScratchHeapThenOffsetLessThanFrontWindowSize) {
auto bindlessHeapHelper = std::make_unique<MockBindlesHeapsHelper>(pDevice->getMemoryManager(), pDevice->getNumAvailableDevices() > 1, pDevice->getRootDeviceIndex());
MockGraphicsAllocation alloc;
size_t size = 0x40;
auto ssInHeapInfo = bindlessHeapHelper->allocateSSInHeap(size, &alloc, BindlessHeapsHelper::BindlesHeapType::SCRATCH_SSH);
auto frontWindowSize = GfxPartition::externalFrontWindowPoolSize;
EXPECT_LT(ssInHeapInfo.surfaceStateOffset, frontWindowSize);
}
TEST_F(BindlessHeapsHelperTests, givenBindlessHepaHelperWhenAllocatSsInGlobalDshThenOffsetGreaterOrEqualFrontWindowSize) {
auto bindlessHeapHelper = std::make_unique<MockBindlesHeapsHelper>(pDevice->getMemoryManager(), pDevice->getNumAvailableDevices() > 1, pDevice->getRootDeviceIndex());
MockGraphicsAllocation alloc;
size_t size = 0x40;
auto ssInHeapInfo = bindlessHeapHelper->allocateSSInHeap(size, &alloc, BindlessHeapsHelper::BindlesHeapType::GLOBAL_DSH);
auto frontWindowSize = GfxPartition::externalFrontWindowPoolSize;
EXPECT_GE(ssInHeapInfo.surfaceStateOffset, frontWindowSize);
}