feature: bindless addressing allocator - reuse of bindless slots
- introduce 2 reuse pools to bindlessHeapHelper - one pool stores slots for reuse, second pool stores released slots - stateCacheDirty flags keep track of state cache - when pools are switched - flags are set indicating flushing caches is needed after old slots have been reused for new allocations Related-To: NEO-7063 Signed-off-by: Mateusz Hoppe <mateusz.hoppe@intel.com>
This commit is contained in:
parent
edd5523f82
commit
00de13939d
|
@ -14,6 +14,7 @@
|
|||
#include "shared/source/indirect_heap/indirect_heap.h"
|
||||
#include "shared/source/memory_manager/allocation_properties.h"
|
||||
#include "shared/source/memory_manager/memory_manager.h"
|
||||
#include "shared/source/os_interface/os_context.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
|
@ -61,20 +62,59 @@ GraphicsAllocation *BindlessHeapsHelper::getHeapAllocation(size_t heapSize, size
|
|||
return this->memManager->allocateGraphicsMemoryWithProperties(properties);
|
||||
}
|
||||
|
||||
void BindlessHeapsHelper::clearStateDirtyForContext(uint32_t osContextId) {
|
||||
std::lock_guard<std::mutex> autolock(this->mtx);
|
||||
|
||||
stateCacheDirtyForContext.reset(osContextId);
|
||||
}
|
||||
|
||||
bool BindlessHeapsHelper::getStateDirtyForContext(uint32_t osContextId) {
|
||||
std::lock_guard<std::mutex> autolock(this->mtx);
|
||||
|
||||
return stateCacheDirtyForContext.test(osContextId);
|
||||
}
|
||||
|
||||
SurfaceStateInHeapInfo BindlessHeapsHelper::allocateSSInHeap(size_t ssSize, GraphicsAllocation *surfaceAllocation, BindlesHeapType heapType) {
|
||||
auto heap = surfaceStateHeaps[heapType].get();
|
||||
|
||||
std::lock_guard<std::mutex> autolock(this->mtx);
|
||||
if (heapType == BindlesHeapType::GLOBAL_SSH) {
|
||||
|
||||
int index = getReusedSshVectorIndex(ssSize);
|
||||
if (!allocateFromReusePool) {
|
||||
if ((surfaceStateInHeapVectorReuse[releasePoolIndex][0].size() + surfaceStateInHeapVectorReuse[releasePoolIndex][1].size()) > reuseSlotCountThreshold) {
|
||||
|
||||
if (surfaceStateInHeapVectorReuse[index].size()) {
|
||||
SurfaceStateInHeapInfo surfaceStateFromVector = surfaceStateInHeapVectorReuse[index].back();
|
||||
surfaceStateInHeapVectorReuse[index].pop_back();
|
||||
return surfaceStateFromVector;
|
||||
// invalidate all contexts
|
||||
stateCacheDirtyForContext.set();
|
||||
allocateFromReusePool = true;
|
||||
allocatePoolIndex = releasePoolIndex;
|
||||
releasePoolIndex = allocatePoolIndex == 0 ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (allocateFromReusePool) {
|
||||
int index = getReusedSshVectorIndex(ssSize);
|
||||
|
||||
if (surfaceStateInHeapVectorReuse[allocatePoolIndex][index].size()) {
|
||||
SurfaceStateInHeapInfo surfaceStateFromVector = surfaceStateInHeapVectorReuse[allocatePoolIndex][index].back();
|
||||
surfaceStateInHeapVectorReuse[allocatePoolIndex][index].pop_back();
|
||||
|
||||
if (surfaceStateInHeapVectorReuse[allocatePoolIndex][index].empty()) {
|
||||
allocateFromReusePool = false;
|
||||
|
||||
// copy remaining slots from allocate pool to release pool
|
||||
int otherSizeIndex = index == 0 ? 1 : 0;
|
||||
surfaceStateInHeapVectorReuse[releasePoolIndex][otherSizeIndex].insert(surfaceStateInHeapVectorReuse[releasePoolIndex][otherSizeIndex].end(),
|
||||
surfaceStateInHeapVectorReuse[allocatePoolIndex][otherSizeIndex].begin(),
|
||||
surfaceStateInHeapVectorReuse[allocatePoolIndex][otherSizeIndex].end());
|
||||
|
||||
surfaceStateInHeapVectorReuse[allocatePoolIndex][otherSizeIndex].clear();
|
||||
}
|
||||
|
||||
return surfaceStateFromVector;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *ptrInHeap = getSpaceInHeap(ssSize, heapType);
|
||||
SurfaceStateInHeapInfo bindlesInfo = {nullptr, 0, nullptr};
|
||||
|
||||
|
@ -128,14 +168,13 @@ bool BindlessHeapsHelper::growHeap(BindlesHeapType heapType) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void BindlessHeapsHelper::placeSSAllocationInReuseVectorOnFreeMemory(GraphicsAllocation *gfxAllocation) {
|
||||
auto ssAllocatedInfo = gfxAllocation->getBindlessInfo();
|
||||
|
||||
if (ssAllocatedInfo.heapAllocation != nullptr) {
|
||||
void BindlessHeapsHelper::releaseSSToReusePool(const SurfaceStateInHeapInfo &surfStateInfo) {
|
||||
if (surfStateInfo.heapAllocation != nullptr) {
|
||||
std::lock_guard<std::mutex> autolock(this->mtx);
|
||||
int index = getReusedSshVectorIndex(ssAllocatedInfo.ssSize);
|
||||
surfaceStateInHeapVectorReuse[index].push_back(std::move(ssAllocatedInfo));
|
||||
int index = getReusedSshVectorIndex(surfStateInfo.ssSize);
|
||||
surfaceStateInHeapVectorReuse[releasePoolIndex][index].push_back(std::move(surfStateInfo));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "shared/source/helpers/heap_helper.h"
|
||||
#include "shared/source/memory_manager/graphics_allocation.h"
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
@ -18,7 +19,6 @@
|
|||
namespace NEO {
|
||||
|
||||
class IndirectHeap;
|
||||
|
||||
class BindlessHeapsHelper {
|
||||
public:
|
||||
enum BindlesHeapType {
|
||||
|
@ -41,7 +41,7 @@ class BindlessHeapsHelper {
|
|||
uint32_t getDefaultBorderColorOffset();
|
||||
uint32_t getAlphaBorderColorOffset();
|
||||
IndirectHeap *getHeap(BindlesHeapType heapType);
|
||||
void placeSSAllocationInReuseVectorOnFreeMemory(GraphicsAllocation *gfxAllocation);
|
||||
void releaseSSToReusePool(const SurfaceStateInHeapInfo &surfStateInfo);
|
||||
bool isGlobalDshSupported() {
|
||||
return globalBindlessDsh;
|
||||
}
|
||||
|
@ -55,6 +55,8 @@ class BindlessHeapsHelper {
|
|||
}
|
||||
return index;
|
||||
}
|
||||
bool getStateDirtyForContext(uint32_t osContextId);
|
||||
void clearStateDirtyForContext(uint32_t osContextId);
|
||||
|
||||
protected:
|
||||
const size_t surfaceStateSize;
|
||||
|
@ -65,7 +67,14 @@ class BindlessHeapsHelper {
|
|||
std::unique_ptr<IndirectHeap> surfaceStateHeaps[BindlesHeapType::NUM_HEAP_TYPES];
|
||||
GraphicsAllocation *borderColorStates;
|
||||
std::vector<GraphicsAllocation *> ssHeapsAllocations;
|
||||
std::vector<SurfaceStateInHeapInfo> surfaceStateInHeapVectorReuse[2];
|
||||
|
||||
size_t reuseSlotCountThreshold = 512;
|
||||
uint32_t allocatePoolIndex = 0;
|
||||
uint32_t releasePoolIndex = 0;
|
||||
bool allocateFromReusePool = false;
|
||||
std::array<std::vector<SurfaceStateInHeapInfo>, 2> surfaceStateInHeapVectorReuse[2];
|
||||
std::bitset<64> stateCacheDirtyForContext;
|
||||
|
||||
std::mutex mtx;
|
||||
DeviceBitfield deviceBitfield;
|
||||
bool globalBindlessDsh = false;
|
||||
|
|
|
@ -245,7 +245,7 @@ void MemoryManager::freeGraphicsMemory(GraphicsAllocation *gfxAllocation, bool i
|
|||
return;
|
||||
}
|
||||
if (ApiSpecificConfig::getGlobalBindlessHeapConfiguration() && executionEnvironment.rootDeviceEnvironments[gfxAllocation->getRootDeviceIndex()]->getBindlessHeapsHelper() != nullptr) {
|
||||
executionEnvironment.rootDeviceEnvironments[gfxAllocation->getRootDeviceIndex()]->getBindlessHeapsHelper()->placeSSAllocationInReuseVectorOnFreeMemory(gfxAllocation);
|
||||
executionEnvironment.rootDeviceEnvironments[gfxAllocation->getRootDeviceIndex()]->getBindlessHeapsHelper()->releaseSSToReusePool(gfxAllocation->getBindlessInfo());
|
||||
}
|
||||
const bool hasFragments = gfxAllocation->fragmentsStorage.fragmentCount != 0;
|
||||
const bool isLocked = gfxAllocation->isLocked();
|
||||
|
|
|
@ -29,13 +29,18 @@ class MockBindlesHeapsHelper : public BindlessHeapsHelper {
|
|||
}
|
||||
|
||||
using BindlesHeapType = BindlessHeapsHelper::BindlesHeapType;
|
||||
using BaseClass::allocateFromReusePool;
|
||||
using BaseClass::allocatePoolIndex;
|
||||
using BaseClass::borderColorStates;
|
||||
using BaseClass::globalBindlessDsh;
|
||||
using BaseClass::growHeap;
|
||||
using BaseClass::isMultiOsContextCapable;
|
||||
using BaseClass::memManager;
|
||||
using BaseClass::releasePoolIndex;
|
||||
using BaseClass::reuseSlotCountThreshold;
|
||||
using BaseClass::rootDeviceIndex;
|
||||
using BaseClass::ssHeapsAllocations;
|
||||
using BaseClass::stateCacheDirtyForContext;
|
||||
using BaseClass::surfaceStateHeaps;
|
||||
using BaseClass::surfaceStateInHeapVectorReuse;
|
||||
using BaseClass::surfaceStateSize;
|
||||
|
|
|
@ -233,8 +233,11 @@ TEST_F(BindlessHeapsHelperTests, givenBindlessHeapHelperWhenFreeGraphicsMemoryIs
|
|||
auto ssInHeapInfo = alloc->getBindlessInfo();
|
||||
|
||||
memManager->freeGraphicsMemory(alloc);
|
||||
EXPECT_EQ(bindlessHeapHelperPtr->surfaceStateInHeapVectorReuse[0].size(), 1u);
|
||||
auto ssInHeapInfoFromReuseVector = bindlessHeapHelperPtr->surfaceStateInHeapVectorReuse[0].front();
|
||||
|
||||
auto freePoolIndex = bindlessHeapHelperPtr->releasePoolIndex;
|
||||
|
||||
EXPECT_EQ(bindlessHeapHelperPtr->surfaceStateInHeapVectorReuse[freePoolIndex][0].size(), 1u);
|
||||
auto ssInHeapInfoFromReuseVector = bindlessHeapHelperPtr->surfaceStateInHeapVectorReuse[freePoolIndex][0].front();
|
||||
EXPECT_EQ(ssInHeapInfoFromReuseVector.surfaceStateOffset, ssInHeapInfo.surfaceStateOffset);
|
||||
EXPECT_EQ(ssInHeapInfoFromReuseVector.ssPtr, ssInHeapInfo.ssPtr);
|
||||
|
||||
|
@ -245,8 +248,8 @@ TEST_F(BindlessHeapsHelperTests, givenBindlessHeapHelperWhenFreeGraphicsMemoryIs
|
|||
auto ssInHeapInfo2 = alloc2->getBindlessInfo();
|
||||
|
||||
memManager->freeGraphicsMemory(alloc2);
|
||||
EXPECT_EQ(bindlessHeapHelperPtr->surfaceStateInHeapVectorReuse[1].size(), 1u);
|
||||
ssInHeapInfoFromReuseVector = bindlessHeapHelperPtr->surfaceStateInHeapVectorReuse[1].front();
|
||||
EXPECT_EQ(bindlessHeapHelperPtr->surfaceStateInHeapVectorReuse[freePoolIndex][1].size(), 1u);
|
||||
ssInHeapInfoFromReuseVector = bindlessHeapHelperPtr->surfaceStateInHeapVectorReuse[freePoolIndex][1].front();
|
||||
EXPECT_EQ(ssInHeapInfoFromReuseVector.surfaceStateOffset, ssInHeapInfo2.surfaceStateOffset);
|
||||
EXPECT_EQ(ssInHeapInfoFromReuseVector.ssPtr, ssInHeapInfo2.ssPtr);
|
||||
}
|
||||
|
@ -268,7 +271,7 @@ TEST_F(BindlessHeapsHelperTests, givenBindlessHeapHelperWhenAllocatingBindlessSl
|
|||
memManager->freeGraphicsMemory(alloc);
|
||||
}
|
||||
|
||||
TEST_F(BindlessHeapsHelperTests, givenBindlessHeapHelperPreviousAllocationThenItShouldBeReused) {
|
||||
TEST_F(BindlessHeapsHelperTests, givenBindlessHeapHelperPreviousAllocationThenItShouldNotBeReusedIfThresholdNotReached) {
|
||||
DebugManagerStateRestore dbgRestorer;
|
||||
DebugManager.flags.UseBindlessMode.set(1);
|
||||
auto bindlessHeapHelper = std::make_unique<MockBindlesHeapsHelper>(getMemoryManager(), false, rootDeviceIndex, devBitfield);
|
||||
|
@ -279,17 +282,21 @@ TEST_F(BindlessHeapsHelperTests, givenBindlessHeapHelperPreviousAllocationThenIt
|
|||
|
||||
auto ssInHeapInfo = alloc->getBindlessInfo();
|
||||
memManager->freeGraphicsMemory(alloc);
|
||||
EXPECT_EQ(bindlessHeapHelperPtr->surfaceStateInHeapVectorReuse[0].size(), 1u);
|
||||
|
||||
auto freePoolIndex = bindlessHeapHelperPtr->releasePoolIndex;
|
||||
|
||||
EXPECT_EQ(bindlessHeapHelperPtr->surfaceStateInHeapVectorReuse[freePoolIndex][0].size(), 1u);
|
||||
MockGraphicsAllocation *alloc2 = new MockGraphicsAllocation;
|
||||
|
||||
memManager->allocateBindlessSlot(alloc2);
|
||||
auto reusedSSinHeapInfo = alloc2->getBindlessInfo();
|
||||
auto newSSinHeapInfo = alloc2->getBindlessInfo();
|
||||
|
||||
EXPECT_EQ(bindlessHeapHelperPtr->surfaceStateInHeapVectorReuse[0].size(), 0u);
|
||||
EXPECT_EQ(ssInHeapInfo.surfaceStateOffset, reusedSSinHeapInfo.surfaceStateOffset);
|
||||
EXPECT_EQ(ssInHeapInfo.ssPtr, reusedSSinHeapInfo.ssPtr);
|
||||
EXPECT_NE(bindlessHeapHelperPtr->surfaceStateInHeapVectorReuse[freePoolIndex][0].size(), 0u);
|
||||
EXPECT_NE(ssInHeapInfo.surfaceStateOffset, newSSinHeapInfo.surfaceStateOffset);
|
||||
EXPECT_NE(ssInHeapInfo.ssPtr, newSSinHeapInfo.ssPtr);
|
||||
memManager->freeGraphicsMemory(alloc2);
|
||||
}
|
||||
|
||||
TEST_F(BindlessHeapsHelperTests, givenDeviceWhenBindlessHeapHelperInitializedThenCorrectDeviceBitFieldIsUsed) {
|
||||
DebugManagerStateRestore dbgRestorer;
|
||||
DebugManager.flags.UseBindlessMode.set(1);
|
||||
|
@ -297,3 +304,228 @@ TEST_F(BindlessHeapsHelperTests, givenDeviceWhenBindlessHeapHelperInitializedThe
|
|||
auto bindlessHeapHelper = std::make_unique<MockBindlesHeapsHelper>(getMemoryManager(), false, rootDeviceIndex, deviceBitfield);
|
||||
EXPECT_EQ(reinterpret_cast<MockMemoryManager *>(getMemoryManager())->recentlyPassedDeviceBitfield, deviceBitfield);
|
||||
}
|
||||
|
||||
TEST_F(BindlessHeapsHelperTests, givenBindlessHeapHelperWhenCreatedThenAllocateAndReleasePoolIndicesAreInitializedToZero) {
|
||||
auto bindlessHeapHelper = std::make_unique<MockBindlesHeapsHelper>(getMemoryManager(), false, rootDeviceIndex, devBitfield);
|
||||
|
||||
EXPECT_FALSE(bindlessHeapHelper->allocateFromReusePool);
|
||||
EXPECT_EQ(0u, bindlessHeapHelper->allocatePoolIndex);
|
||||
EXPECT_EQ(0u, bindlessHeapHelper->releasePoolIndex);
|
||||
|
||||
EXPECT_EQ(0u, bindlessHeapHelper->stateCacheDirtyForContext.to_ulong());
|
||||
}
|
||||
|
||||
TEST_F(BindlessHeapsHelperTests, givenFreeSlotsExceedingThresholdInResuePoolWhenNewSlotsAllocatedThenSlotsAreAllocatedFromReusePool) {
|
||||
auto bindlessHeapHelper = std::make_unique<MockBindlesHeapsHelper>(getMemoryManager(), false, rootDeviceIndex, devBitfield);
|
||||
bindlessHeapHelper->reuseSlotCountThreshold = 4;
|
||||
|
||||
size_t size = bindlessHeapHelper->surfaceStateSize;
|
||||
|
||||
SurfaceStateInHeapInfo ssInHeapInfos[5];
|
||||
|
||||
ssInHeapInfos[0] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
ssInHeapInfos[1] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
// allocate double size for image
|
||||
ssInHeapInfos[2] = bindlessHeapHelper->allocateSSInHeap(2 * size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
ssInHeapInfos[3] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
ssInHeapInfos[4] = bindlessHeapHelper->allocateSSInHeap(2 * size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
|
||||
EXPECT_FALSE(bindlessHeapHelper->allocateFromReusePool);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
bindlessHeapHelper->releaseSSToReusePool(ssInHeapInfos[i]);
|
||||
ssInHeapInfos[i] = {0};
|
||||
}
|
||||
|
||||
ssInHeapInfos[4] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
EXPECT_TRUE(bindlessHeapHelper->allocateFromReusePool);
|
||||
|
||||
EXPECT_EQ(0u, bindlessHeapHelper->allocatePoolIndex);
|
||||
EXPECT_EQ(1u, bindlessHeapHelper->releasePoolIndex);
|
||||
|
||||
EXPECT_EQ(std::numeric_limits<uint64_t>::max(), bindlessHeapHelper->stateCacheDirtyForContext.to_ullong());
|
||||
}
|
||||
|
||||
TEST_F(BindlessHeapsHelperTests, givenReusePoolExhaustedWhenNewSlotsAllocatedThenSlotsAreNotResuedAndStateCacheDirtyFlagsAreNotSet) {
|
||||
auto bindlessHeapHelper = std::make_unique<MockBindlesHeapsHelper>(getMemoryManager(), false, rootDeviceIndex, devBitfield);
|
||||
bindlessHeapHelper->reuseSlotCountThreshold = 4;
|
||||
|
||||
size_t size = bindlessHeapHelper->surfaceStateSize;
|
||||
|
||||
SurfaceStateInHeapInfo ssInHeapInfos[5];
|
||||
|
||||
ssInHeapInfos[0] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
ssInHeapInfos[1] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
// allocate double size for image
|
||||
ssInHeapInfos[2] = bindlessHeapHelper->allocateSSInHeap(2 * size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
ssInHeapInfos[3] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
ssInHeapInfos[4] = bindlessHeapHelper->allocateSSInHeap(2 * size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
|
||||
EXPECT_FALSE(bindlessHeapHelper->allocateFromReusePool);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
bindlessHeapHelper->releaseSSToReusePool(ssInHeapInfos[i]);
|
||||
ssInHeapInfos[i] = {0};
|
||||
}
|
||||
EXPECT_FALSE(bindlessHeapHelper->allocateFromReusePool);
|
||||
EXPECT_EQ(0u, bindlessHeapHelper->allocatePoolIndex);
|
||||
EXPECT_EQ(0u, bindlessHeapHelper->releasePoolIndex);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ssInHeapInfos[i] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
}
|
||||
|
||||
EXPECT_EQ(0u, bindlessHeapHelper->allocatePoolIndex);
|
||||
EXPECT_EQ(1u, bindlessHeapHelper->releasePoolIndex);
|
||||
|
||||
auto allocatePoolIndex = bindlessHeapHelper->allocatePoolIndex;
|
||||
auto releasePoolIndex = bindlessHeapHelper->releasePoolIndex;
|
||||
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[allocatePoolIndex][0].size(), 0u);
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[releasePoolIndex][1].size(), 2u);
|
||||
|
||||
bindlessHeapHelper->stateCacheDirtyForContext.reset();
|
||||
|
||||
ssInHeapInfos[3] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
EXPECT_NE(0u, ssInHeapInfos[3].surfaceStateOffset);
|
||||
EXPECT_NE(nullptr, ssInHeapInfos[3].ssPtr);
|
||||
|
||||
EXPECT_FALSE(bindlessHeapHelper->allocateFromReusePool);
|
||||
EXPECT_EQ(0u, bindlessHeapHelper->stateCacheDirtyForContext.to_ullong());
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[allocatePoolIndex][0].size(), 0u);
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[allocatePoolIndex][1].size(), 0u);
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[releasePoolIndex][0].size(), 0u);
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[releasePoolIndex][1].size(), 2u);
|
||||
}
|
||||
|
||||
TEST_F(BindlessHeapsHelperTests, givenReleasedSlotsToSecondPoolWhenThresholdReachedThenPoolsAreSwitchedAndSlotsAllocatedFromReusePool) {
|
||||
auto bindlessHeapHelper = std::make_unique<MockBindlesHeapsHelper>(getMemoryManager(), false, rootDeviceIndex, devBitfield);
|
||||
bindlessHeapHelper->reuseSlotCountThreshold = 4;
|
||||
|
||||
size_t size = bindlessHeapHelper->surfaceStateSize;
|
||||
|
||||
SurfaceStateInHeapInfo ssInHeapInfos[5];
|
||||
|
||||
ssInHeapInfos[0] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
ssInHeapInfos[1] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
// allocate double size for image
|
||||
ssInHeapInfos[2] = bindlessHeapHelper->allocateSSInHeap(2 * size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
ssInHeapInfos[3] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
ssInHeapInfos[4] = bindlessHeapHelper->allocateSSInHeap(2 * size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
bindlessHeapHelper->releaseSSToReusePool(ssInHeapInfos[i]);
|
||||
ssInHeapInfos[i] = {0};
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ssInHeapInfos[i] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
}
|
||||
|
||||
EXPECT_EQ(0u, bindlessHeapHelper->allocatePoolIndex);
|
||||
EXPECT_EQ(1u, bindlessHeapHelper->releasePoolIndex);
|
||||
|
||||
auto allocatePoolIndex = bindlessHeapHelper->allocatePoolIndex;
|
||||
auto releasePoolIndex = bindlessHeapHelper->releasePoolIndex;
|
||||
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[allocatePoolIndex][0].size(), 0u);
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[releasePoolIndex][1].size(), 2u);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
bindlessHeapHelper->releaseSSToReusePool(ssInHeapInfos[i]);
|
||||
ssInHeapInfos[i] = {0};
|
||||
}
|
||||
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[releasePoolIndex][0].size(), 3u);
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[releasePoolIndex][1].size(), 2u);
|
||||
|
||||
ssInHeapInfos[3] = bindlessHeapHelper->allocateSSInHeap(2 * size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
|
||||
EXPECT_EQ(1u, bindlessHeapHelper->allocatePoolIndex);
|
||||
EXPECT_EQ(0u, bindlessHeapHelper->releasePoolIndex);
|
||||
|
||||
allocatePoolIndex = bindlessHeapHelper->allocatePoolIndex;
|
||||
releasePoolIndex = bindlessHeapHelper->releasePoolIndex;
|
||||
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[allocatePoolIndex][1].size(), 1u);
|
||||
|
||||
ssInHeapInfos[4] = bindlessHeapHelper->allocateSSInHeap(2 * size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[allocatePoolIndex][1].size(), 0u);
|
||||
EXPECT_FALSE(bindlessHeapHelper->allocateFromReusePool);
|
||||
|
||||
bindlessHeapHelper->releaseSSToReusePool(ssInHeapInfos[3]);
|
||||
bindlessHeapHelper->releaseSSToReusePool(ssInHeapInfos[4]);
|
||||
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[allocatePoolIndex][0].size(), 0u);
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[allocatePoolIndex][1].size(), 0u);
|
||||
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[releasePoolIndex][0].size(), 3u);
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[releasePoolIndex][1].size(), 2u);
|
||||
|
||||
bindlessHeapHelper->stateCacheDirtyForContext.reset();
|
||||
|
||||
ssInHeapInfos[0] = bindlessHeapHelper->allocateSSInHeap(2 * size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
|
||||
EXPECT_EQ(0u, bindlessHeapHelper->allocatePoolIndex);
|
||||
EXPECT_EQ(1u, bindlessHeapHelper->releasePoolIndex);
|
||||
EXPECT_EQ(std::numeric_limits<uint64_t>::max(), bindlessHeapHelper->stateCacheDirtyForContext.to_ullong());
|
||||
EXPECT_TRUE(bindlessHeapHelper->allocateFromReusePool);
|
||||
|
||||
allocatePoolIndex = bindlessHeapHelper->allocatePoolIndex;
|
||||
releasePoolIndex = bindlessHeapHelper->releasePoolIndex;
|
||||
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[allocatePoolIndex][0].size(), 3u);
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[allocatePoolIndex][1].size(), 1u);
|
||||
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[releasePoolIndex][0].size(), 0u);
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[releasePoolIndex][1].size(), 0u);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
}
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[allocatePoolIndex][0].size(), 0u);
|
||||
EXPECT_FALSE(bindlessHeapHelper->allocateFromReusePool);
|
||||
}
|
||||
|
||||
TEST_F(BindlessHeapsHelperTests, givenFreeSlotsInReusePoolForONeSizeWhenAllocatingDifferentSizeThenNewSlotFromHeapIsAllocated) {
|
||||
auto bindlessHeapHelper = std::make_unique<MockBindlesHeapsHelper>(getMemoryManager(), false, rootDeviceIndex, devBitfield);
|
||||
bindlessHeapHelper->reuseSlotCountThreshold = 4;
|
||||
|
||||
size_t size = bindlessHeapHelper->surfaceStateSize;
|
||||
|
||||
SurfaceStateInHeapInfo ssInHeapInfos[5];
|
||||
|
||||
ssInHeapInfos[0] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
ssInHeapInfos[1] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
ssInHeapInfos[2] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
ssInHeapInfos[3] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
ssInHeapInfos[4] = bindlessHeapHelper->allocateSSInHeap(size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
bindlessHeapHelper->releaseSSToReusePool(ssInHeapInfos[i]);
|
||||
ssInHeapInfos[i] = {0};
|
||||
}
|
||||
|
||||
ssInHeapInfos[0] = bindlessHeapHelper->allocateSSInHeap(2 * size, nullptr, BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH);
|
||||
|
||||
EXPECT_EQ(0u, bindlessHeapHelper->allocatePoolIndex);
|
||||
EXPECT_EQ(1u, bindlessHeapHelper->releasePoolIndex);
|
||||
|
||||
EXPECT_NE(0u, ssInHeapInfos[0].surfaceStateOffset);
|
||||
EXPECT_NE(nullptr, ssInHeapInfos[0].ssPtr);
|
||||
|
||||
auto allocatePoolIndex = bindlessHeapHelper->allocatePoolIndex;
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[allocatePoolIndex][0].size(), 5u);
|
||||
EXPECT_EQ(bindlessHeapHelper->surfaceStateInHeapVectorReuse[allocatePoolIndex][1].size(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(BindlessHeapsHelperTests, givenBindlessHelperWhenGettingAndClearingDirstyStateForContextThenCorrectFlagIsReturnedAdCleard) {
|
||||
auto bindlessHeapHelper = std::make_unique<MockBindlesHeapsHelper>(getMemoryManager(), false, rootDeviceIndex, devBitfield);
|
||||
|
||||
EXPECT_FALSE(bindlessHeapHelper->getStateDirtyForContext(1));
|
||||
bindlessHeapHelper->stateCacheDirtyForContext.set(3);
|
||||
EXPECT_TRUE(bindlessHeapHelper->getStateDirtyForContext(3));
|
||||
|
||||
bindlessHeapHelper->clearStateDirtyForContext(3);
|
||||
EXPECT_FALSE(bindlessHeapHelper->getStateDirtyForContext(3));
|
||||
}
|
Loading…
Reference in New Issue