XeHPC Implicit scaling: put command/ring/semaphore buffer to first memory bank

In direct submission scenario command/ring/semaphore buffer allocations
are placed in the same memory bank to ensure that their memory is updated in
correct order

Related-To: NEO-6698
Signed-off-by: Mateusz Jablonski <mateusz.jablonski@intel.com>
This commit is contained in:
Mateusz Jablonski 2022-03-16 18:41:29 +00:00 committed by Compute-Runtime-Automation
parent aa7ba69746
commit 3792481d33
7 changed files with 337 additions and 5 deletions

View File

@ -401,4 +401,5 @@ UseTileMemoryBankInVirtualMemoryCreation = -1
DisableScratchPages = 0
ForceAllResourcesUncached = 0
ForcePreParserEnabledForMiArbCheck = -1
BatchBufferStartPrepatchingWaEnabled = -1
BatchBufferStartPrepatchingWaEnabled = -1
DirectSubmissionForceLocalMemoryStorageMode = -1

View File

@ -282,6 +282,7 @@ DECLARE_DEBUG_VARIABLE(int32_t, DirectSubmissionNewResourceTlbFlush, -1, "-1: dr
DECLARE_DEBUG_VARIABLE(int32_t, DirectSubmissionDisableMonitorFence, -1, "Disable dispatching monitor fence commands")
DECLARE_DEBUG_VARIABLE(int32_t, EnableDirectSubmissionController, -1, "Enable direct submission terminating after given timeout, -1: default, 0: disabled, 1: enabled")
DECLARE_DEBUG_VARIABLE(int32_t, DirectSubmissionControllerTimeout, -1, "Set direct submission controller timeout, -1: default 5 ms, >=0: timeout in ms")
DECLARE_DEBUG_VARIABLE(int32_t, DirectSubmissionForceLocalMemoryStorageMode, -1, "Force first memory bank storage for command/ring/semaphore buffer, -1: default - for multiOsContextCapable engine, 0: disabled, 1: for multiOsContextCapable engine, 2: for all engines")
/* IMPLICIT SCALING */
DECLARE_DEBUG_VARIABLE(int32_t, EnableWalkerPartition, -1, "-1: default, 0: disable, 1: enable, Enables Walker Partitioning via WPARID.")

View File

@ -66,7 +66,7 @@ bool DirectSubmissionHw<GfxFamily, Dispatcher>::allocateResources() {
const AllocationProperties commandStreamAllocationProperties{device.getRootDeviceIndex(),
true, allocationSize,
AllocationType::RING_BUFFER,
isMultiOsContextCapable, osContext.getDeviceBitfield()};
isMultiOsContextCapable, false, osContext.getDeviceBitfield()};
ringBuffer = memoryManager->allocateGraphicsMemoryWithProperties(commandStreamAllocationProperties);
UNRECOVERABLE_IF(ringBuffer == nullptr);
allocations.push_back(ringBuffer);
@ -78,7 +78,7 @@ bool DirectSubmissionHw<GfxFamily, Dispatcher>::allocateResources() {
const AllocationProperties semaphoreAllocationProperties{device.getRootDeviceIndex(),
true, MemoryConstants::pageSize,
AllocationType::SEMAPHORE_BUFFER,
isMultiOsContextCapable, osContext.getDeviceBitfield()};
isMultiOsContextCapable, false, osContext.getDeviceBitfield()};
semaphores = memoryManager->allocateGraphicsMemoryWithProperties(semaphoreAllocationProperties);
UNRECOVERABLE_IF(semaphores == nullptr);
allocations.push_back(semaphores);

View File

@ -153,6 +153,34 @@ StorageInfo MemoryManager::createStorageInfoFromProperties(const AllocationPrope
default:
break;
}
bool forceLocalMemoryForDirectSubmission = properties.flags.multiOsContextCapable;
switch (DebugManager.flags.DirectSubmissionForceLocalMemoryStorageMode.get()) {
case 0:
forceLocalMemoryForDirectSubmission = false;
break;
case 2:
forceLocalMemoryForDirectSubmission = true;
break;
default:
break;
}
if (forceLocalMemoryForDirectSubmission) {
if (properties.allocationType == AllocationType::COMMAND_BUFFER ||
properties.allocationType == AllocationType::RING_BUFFER ||
properties.allocationType == AllocationType::SEMAPHORE_BUFFER) {
storageInfo.memoryBanks = {};
for (auto bank = 0u; bank < deviceCount; bank++) {
if (allTilesValue.test(bank)) {
storageInfo.memoryBanks.set(bank);
break;
}
}
UNRECOVERABLE_IF(storageInfo.memoryBanks.none());
}
}
return storageInfo;
}
uint32_t StorageInfo::getNumBanks() const {

View File

@ -239,6 +239,28 @@ void HwHelperHw<Family>::setExtraAllocationData(AllocationData &allocationData,
allocationData.flags.useSystemMemory = false;
}
bool forceLocalMemoryForDirectSubmission = properties.flags.multiOsContextCapable;
switch (DebugManager.flags.DirectSubmissionForceLocalMemoryStorageMode.get()) {
case 0:
forceLocalMemoryForDirectSubmission = false;
break;
case 2:
forceLocalMemoryForDirectSubmission = true;
break;
default:
break;
}
if (forceLocalMemoryForDirectSubmission) {
if (properties.allocationType == AllocationType::COMMAND_BUFFER ||
properties.allocationType == AllocationType::RING_BUFFER ||
properties.allocationType == AllocationType::SEMAPHORE_BUFFER) {
allocationData.flags.useSystemMemory = false;
allocationData.flags.requiresCpuAccess = true;
allocationData.flags.resource48Bit = true;
}
}
allocationData.cacheRegion = properties.cacheRegion;
if (allocationData.flags.requiresCpuAccess && !allocationData.flags.useSystemMemory &&

View File

@ -628,3 +628,125 @@ TEST(MemoryManagerTest, givenExternalAllocationTypeWhenIsAllocatedInDevicePoolTh
EXPECT_EQ(0u, memoryManager.externalLocalMemoryUsageBankSelector[mockRootDeviceIndex]->getOccupiedMemorySizeForBank(0));
EXPECT_EQ(0u, memoryManager.internalLocalMemoryUsageBankSelector[mockRootDeviceIndex]->getOccupiedMemorySizeForBank(0));
}
struct MemoryManagerDirectSubmissionImplicitScalingTest : public ::testing::Test {
void SetUp() override {
DebugManager.flags.CreateMultipleSubDevices.set(numSubDevices);
executionEnvironment = std::make_unique<MockExecutionEnvironment>(defaultHwInfo.get());
auto allTilesMask = executionEnvironment->rootDeviceEnvironments[mockRootDeviceIndex]->deviceAffinityMask.getGenericSubDevicesMask();
allocationProperties = std::make_unique<AllocationProperties>(mockRootDeviceIndex, MemoryConstants::pageSize, AllocationType::UNKNOWN, allTilesMask);
allocationProperties->flags.multiOsContextCapable = true;
constexpr auto enableLocalMemory = true;
memoryManager = std::make_unique<MockMemoryManager>(false, enableLocalMemory, *executionEnvironment);
memoryManager->internalLocalMemoryUsageBankSelector[mockRootDeviceIndex]->reserveOnBanks(1u, MemoryConstants::pageSize2Mb);
EXPECT_NE(0u, memoryManager->internalLocalMemoryUsageBankSelector[mockRootDeviceIndex]->getLeastOccupiedBank(allTilesMask));
}
DebugManagerStateRestore restorer{};
constexpr static DeviceBitfield firstTileMask{1u};
constexpr static auto numSubDevices = 2u;
std::unique_ptr<MockExecutionEnvironment> executionEnvironment{};
std::unique_ptr<AllocationProperties> allocationProperties{};
std::unique_ptr<MockMemoryManager> memoryManager{};
};
HWTEST2_F(MemoryManagerDirectSubmissionImplicitScalingTest, givenCommandBufferTypeWhenIsAllocatedForMultiOsContextThenMemoryIsPlacedOnFirstAvailableMemoryBankInLocalMemory, IsXeHpcCore) {
allocationProperties->allocationType = AllocationType::COMMAND_BUFFER;
auto allocation = memoryManager->allocateGraphicsMemoryInPreferredPool(*allocationProperties, nullptr);
EXPECT_NE(nullptr, allocation);
EXPECT_EQ(MemoryPool::LocalMemory, allocation->getMemoryPool());
EXPECT_EQ(firstTileMask, allocation->storageInfo.getMemoryBanks());
memoryManager->freeGraphicsMemory(allocation);
}
HWTEST2_F(MemoryManagerDirectSubmissionImplicitScalingTest, givenRingBufferTypeWhenIsAllocatedForMultiOsContextThenMemoryIsPlacedOnFirstAvailableMemoryBankInLocalMemory, IsXeHpcCore) {
allocationProperties->allocationType = AllocationType::RING_BUFFER;
auto allocation = memoryManager->allocateGraphicsMemoryInPreferredPool(*allocationProperties, nullptr);
EXPECT_NE(nullptr, allocation);
EXPECT_EQ(MemoryPool::LocalMemory, allocation->getMemoryPool());
EXPECT_EQ(firstTileMask, allocation->storageInfo.getMemoryBanks());
memoryManager->freeGraphicsMemory(allocation);
}
HWTEST2_F(MemoryManagerDirectSubmissionImplicitScalingTest, givenSemaphoreBufferTypeWhenIsAllocatedForMultiOsContextThenMemoryIsPlacedOnFirstAvailableMemoryBankInLocalMemory, IsXeHpcCore) {
allocationProperties->allocationType = AllocationType::SEMAPHORE_BUFFER;
auto allocation = memoryManager->allocateGraphicsMemoryInPreferredPool(*allocationProperties, nullptr);
EXPECT_NE(nullptr, allocation);
EXPECT_EQ(MemoryPool::LocalMemory, allocation->getMemoryPool());
EXPECT_EQ(firstTileMask, allocation->storageInfo.getMemoryBanks());
memoryManager->freeGraphicsMemory(allocation);
}
HWTEST2_F(MemoryManagerDirectSubmissionImplicitScalingTest, givenDirectSubmissionForceLocalMemoryStorageDisabledWhenAllocatingMemoryForRingOrSemaphoreBufferThenAllocateInSystemMemory, IsXeHpcCore) {
DebugManager.flags.DirectSubmissionForceLocalMemoryStorageMode.set(0);
for (auto &multiTile : ::testing::Bool()) {
for (auto &allocationType : {AllocationType::RING_BUFFER, AllocationType::SEMAPHORE_BUFFER}) {
allocationProperties->allocationType = allocationType;
allocationProperties->flags.multiOsContextCapable = multiTile;
auto allocation = memoryManager->allocateGraphicsMemoryInPreferredPool(*allocationProperties, nullptr);
EXPECT_NE(nullptr, allocation);
EXPECT_NE(MemoryPool::LocalMemory, allocation->getMemoryPool());
EXPECT_NE(firstTileMask, allocation->storageInfo.getMemoryBanks());
memoryManager->freeGraphicsMemory(allocation);
}
}
}
HWTEST2_F(MemoryManagerDirectSubmissionImplicitScalingTest, givenDirectSubmissionForceLocalMemoryStorageEnabledForMultiTileEsWhenAllocatingMemoryForCommandOrRingOrSemaphoreBufferThenFirstBankIsSelectedOnlyForMultiTileEngines, IsXeHpcCore) {
DebugManager.flags.DirectSubmissionForceLocalMemoryStorageMode.set(1);
for (auto &multiTile : ::testing::Bool()) {
for (auto &allocationType : {AllocationType::COMMAND_BUFFER, AllocationType::RING_BUFFER, AllocationType::SEMAPHORE_BUFFER}) {
allocationProperties->allocationType = allocationType;
allocationProperties->flags.multiOsContextCapable = multiTile;
auto allocation = memoryManager->allocateGraphicsMemoryInPreferredPool(*allocationProperties, nullptr);
EXPECT_NE(nullptr, allocation);
if (multiTile) {
EXPECT_EQ(MemoryPool::LocalMemory, allocation->getMemoryPool());
EXPECT_EQ(firstTileMask, allocation->storageInfo.getMemoryBanks());
} else {
if (allocationType != AllocationType::COMMAND_BUFFER) {
EXPECT_NE(firstTileMask, allocation->storageInfo.getMemoryBanks());
EXPECT_NE(firstTileMask, allocation->storageInfo.getMemoryBanks());
}
}
memoryManager->freeGraphicsMemory(allocation);
}
}
}
HWTEST2_F(MemoryManagerDirectSubmissionImplicitScalingTest, givenDirectSubmissionForceLocalMemoryStorageEnabledForAllEnginesWhenAllocatingMemoryForCommandOrRingOrSemaphoreBufferThenFirstBankIsSelected, IsXeHpcCore) {
DebugManager.flags.DirectSubmissionForceLocalMemoryStorageMode.set(2);
for (auto &multiTile : ::testing::Bool()) {
for (auto &allocationType : {AllocationType::COMMAND_BUFFER, AllocationType::RING_BUFFER, AllocationType::SEMAPHORE_BUFFER}) {
allocationProperties->allocationType = allocationType;
allocationProperties->flags.multiOsContextCapable = multiTile;
auto allocation = memoryManager->allocateGraphicsMemoryInPreferredPool(*allocationProperties, nullptr);
EXPECT_NE(nullptr, allocation);
EXPECT_EQ(MemoryPool::LocalMemory, allocation->getMemoryPool());
EXPECT_EQ(firstTileMask, allocation->storageInfo.getMemoryBanks());
memoryManager->freeGraphicsMemory(allocation);
}
}
}

View File

@ -160,11 +160,12 @@ TEST_F(MultiDeviceStorageInfoTest, givenSingleTileCsrWhenCreatingStorageInfoForL
EXPECT_FALSE(storageInfo.tileInstanced);
}
TEST_F(MultiDeviceStorageInfoTest, givenMultiTileCsrWhenCreatingStorageInfoForCommandBufferThenSingleMemoryBankIsOnAndPageTableClonningIsRequired) {
TEST_F(MultiDeviceStorageInfoTest, givenMultiTileCsrWhenCreatingStorageInfoForCommandBufferThenFirstAvailableMemoryBankIsOnAndPageTableClonningIsRequired) {
const DeviceBitfield firstTileMask{static_cast<uint32_t>(1u)};
AllocationProperties properties{mockRootDeviceIndex, false, 0u, AllocationType::COMMAND_BUFFER, true, false, singleTileMask};
auto storageInfo = memoryManager->createStorageInfoFromProperties(properties);
EXPECT_TRUE(storageInfo.cloningOfPageTables);
EXPECT_EQ(singleTileMask, storageInfo.memoryBanks);
EXPECT_EQ(firstTileMask, storageInfo.memoryBanks);
EXPECT_EQ(allTilesMask, storageInfo.pageTablesVisibility);
}
@ -462,3 +463,160 @@ TEST_F(MultiDeviceStorageInfoTest,
EXPECT_FALSE(storageInfo.tileInstanced);
EXPECT_EQ(allTilesMask, storageInfo.pageTablesVisibility);
}
TEST_F(MultiDeviceStorageInfoTest, givenSingleTileWhenCreatingStorageInfoForSemaphoreBufferThenProvidedMemoryBankIsSelected) {
AllocationProperties properties{mockRootDeviceIndex, false, numDevices * MemoryConstants::pageSize64k, AllocationType::SEMAPHORE_BUFFER, false, singleTileMask};
properties.flags.multiOsContextCapable = false;
auto storageInfo = memoryManager->createStorageInfoFromProperties(properties);
EXPECT_EQ(singleTileMask, storageInfo.memoryBanks);
}
TEST_F(MultiDeviceStorageInfoTest, givenSingleTileWhenCreatingStorageInfoForCommandBufferThenProvidedMemoryBankIsSelected) {
AllocationProperties properties{mockRootDeviceIndex, false, numDevices * MemoryConstants::pageSize64k, AllocationType::COMMAND_BUFFER, false, singleTileMask};
properties.flags.multiOsContextCapable = false;
auto storageInfo = memoryManager->createStorageInfoFromProperties(properties);
EXPECT_EQ(singleTileMask, storageInfo.memoryBanks);
}
TEST_F(MultiDeviceStorageInfoTest, givenSingleTileWhenCreatingStorageInfoForRingBufferThenProvidedMemoryBankIsSelected) {
AllocationProperties properties{mockRootDeviceIndex, false, numDevices * MemoryConstants::pageSize64k, AllocationType::RING_BUFFER, false, singleTileMask};
properties.flags.multiOsContextCapable = false;
auto storageInfo = memoryManager->createStorageInfoFromProperties(properties);
EXPECT_EQ(singleTileMask, storageInfo.memoryBanks);
}
TEST_F(MultiDeviceStorageInfoTest, givenMultiTileWhenCreatingStorageInfoForSemaphoreBufferThenFirstBankIsSelectedEvenIfOtherTileIsLessOccupied) {
constexpr uint32_t firstAvailableTileMask = 2u;
memoryManager->internalLocalMemoryUsageBankSelector[mockRootDeviceIndex]->reserveOnBanks(firstAvailableTileMask, MemoryConstants::pageSize2Mb);
EXPECT_NE(1u, memoryManager->internalLocalMemoryUsageBankSelector[mockRootDeviceIndex]->getLeastOccupiedBank(allTilesMask));
AffinityMaskHelper affinityMaskHelper{false};
affinityMaskHelper.enableGenericSubDevice(1);
affinityMaskHelper.enableGenericSubDevice(2);
affinityMaskHelper.enableGenericSubDevice(3);
memoryManager->peekExecutionEnvironment().rootDeviceEnvironments[mockRootDeviceIndex]->deviceAffinityMask = affinityMaskHelper;
AllocationProperties properties{mockRootDeviceIndex, false, numDevices * MemoryConstants::pageSize64k, AllocationType::SEMAPHORE_BUFFER, false, affinityMaskHelper.getGenericSubDevicesMask()};
properties.flags.multiOsContextCapable = true;
auto storageInfo = memoryManager->createStorageInfoFromProperties(properties);
EXPECT_EQ(DeviceBitfield{firstAvailableTileMask}, storageInfo.memoryBanks);
}
TEST_F(MultiDeviceStorageInfoTest, givenMultiTileWhenCreatingStorageInfoForCommandBufferThenFirstBankIsSelectedEvenIfOtherTileIsLessOccupied) {
constexpr uint32_t firstAvailableTileMask = 2u;
memoryManager->internalLocalMemoryUsageBankSelector[mockRootDeviceIndex]->reserveOnBanks(firstAvailableTileMask, MemoryConstants::pageSize2Mb);
EXPECT_NE(1u, memoryManager->internalLocalMemoryUsageBankSelector[mockRootDeviceIndex]->getLeastOccupiedBank(allTilesMask));
AffinityMaskHelper affinityMaskHelper{false};
affinityMaskHelper.enableGenericSubDevice(1);
affinityMaskHelper.enableGenericSubDevice(2);
affinityMaskHelper.enableGenericSubDevice(3);
memoryManager->peekExecutionEnvironment().rootDeviceEnvironments[mockRootDeviceIndex]->deviceAffinityMask = affinityMaskHelper;
AllocationProperties properties{mockRootDeviceIndex, false, numDevices * MemoryConstants::pageSize64k, AllocationType::COMMAND_BUFFER, false, affinityMaskHelper.getGenericSubDevicesMask()};
properties.flags.multiOsContextCapable = true;
auto storageInfo = memoryManager->createStorageInfoFromProperties(properties);
EXPECT_EQ(DeviceBitfield{firstAvailableTileMask}, storageInfo.memoryBanks);
}
TEST_F(MultiDeviceStorageInfoTest, givenMultiTileWhenCreatingStorageInfoForRingBufferThenFirstBankIsSelectedEvenIfOtherTileIsLessOccupied) {
constexpr uint32_t firstAvailableTileMask = 2u;
memoryManager->internalLocalMemoryUsageBankSelector[mockRootDeviceIndex]->reserveOnBanks(firstAvailableTileMask, MemoryConstants::pageSize2Mb);
EXPECT_NE(1u, memoryManager->internalLocalMemoryUsageBankSelector[mockRootDeviceIndex]->getLeastOccupiedBank(allTilesMask));
AffinityMaskHelper affinityMaskHelper{false};
affinityMaskHelper.enableGenericSubDevice(1);
affinityMaskHelper.enableGenericSubDevice(2);
affinityMaskHelper.enableGenericSubDevice(3);
memoryManager->peekExecutionEnvironment().rootDeviceEnvironments[mockRootDeviceIndex]->deviceAffinityMask = affinityMaskHelper;
AllocationProperties properties{mockRootDeviceIndex, false, numDevices * MemoryConstants::pageSize64k, AllocationType::RING_BUFFER, false, affinityMaskHelper.getGenericSubDevicesMask()};
properties.flags.multiOsContextCapable = true;
auto storageInfo = memoryManager->createStorageInfoFromProperties(properties);
EXPECT_EQ(DeviceBitfield{firstAvailableTileMask}, storageInfo.memoryBanks);
}
TEST_F(MultiDeviceStorageInfoTest, givenDirectSubmissionForceLocalMemoryStorageDisabledWhenCreatingStorageInfoForCommandRingOrSemaphoreBufferThenPreferredBankIsSelected) {
DebugManagerStateRestore restorer;
DebugManager.flags.DirectSubmissionForceLocalMemoryStorageMode.set(0);
constexpr uint32_t firstAvailableTileMask = 2u;
memoryManager->internalLocalMemoryUsageBankSelector[mockRootDeviceIndex]->reserveOnBanks(firstAvailableTileMask, MemoryConstants::pageSize2Mb);
EXPECT_NE(1u, memoryManager->internalLocalMemoryUsageBankSelector[mockRootDeviceIndex]->getLeastOccupiedBank(allTilesMask));
AffinityMaskHelper affinityMaskHelper{false};
affinityMaskHelper.enableGenericSubDevice(1);
affinityMaskHelper.enableGenericSubDevice(2);
affinityMaskHelper.enableGenericSubDevice(3);
memoryManager->peekExecutionEnvironment().rootDeviceEnvironments[mockRootDeviceIndex]->deviceAffinityMask = affinityMaskHelper;
for (auto &multiTile : ::testing::Bool()) {
for (auto &allocationType : {AllocationType::COMMAND_BUFFER, AllocationType::RING_BUFFER, AllocationType::SEMAPHORE_BUFFER}) {
AllocationProperties properties{mockRootDeviceIndex, false, numDevices * MemoryConstants::pageSize64k, allocationType, false, affinityMaskHelper.getGenericSubDevicesMask()};
properties.flags.multiOsContextCapable = multiTile;
auto storageInfo = memoryManager->createStorageInfoFromProperties(properties);
EXPECT_NE(DeviceBitfield{firstAvailableTileMask}, storageInfo.memoryBanks);
}
}
}
TEST_F(MultiDeviceStorageInfoTest, givenDirectSubmissionForceLocalMemoryStorageEnabledForMultiTileEnginesWhenCreatingStorageInfoForCommandRingOrSemaphoreBufferThenFirstBankIsSelectedOnlyForMultiTileEngines) {
DebugManagerStateRestore restorer;
DebugManager.flags.DirectSubmissionForceLocalMemoryStorageMode.set(1);
constexpr uint32_t firstAvailableTileMask = 2u;
memoryManager->internalLocalMemoryUsageBankSelector[mockRootDeviceIndex]->reserveOnBanks(firstAvailableTileMask, MemoryConstants::pageSize2Mb);
EXPECT_NE(1u, memoryManager->internalLocalMemoryUsageBankSelector[mockRootDeviceIndex]->getLeastOccupiedBank(allTilesMask));
AffinityMaskHelper affinityMaskHelper{false};
affinityMaskHelper.enableGenericSubDevice(1);
affinityMaskHelper.enableGenericSubDevice(2);
affinityMaskHelper.enableGenericSubDevice(3);
memoryManager->peekExecutionEnvironment().rootDeviceEnvironments[mockRootDeviceIndex]->deviceAffinityMask = affinityMaskHelper;
for (auto &multiTile : ::testing::Bool()) {
for (auto &allocationType : {AllocationType::COMMAND_BUFFER, AllocationType::RING_BUFFER, AllocationType::SEMAPHORE_BUFFER}) {
AllocationProperties properties{mockRootDeviceIndex, false, numDevices * MemoryConstants::pageSize64k, allocationType, false, affinityMaskHelper.getGenericSubDevicesMask()};
properties.flags.multiOsContextCapable = multiTile;
auto storageInfo = memoryManager->createStorageInfoFromProperties(properties);
if (multiTile) {
EXPECT_EQ(DeviceBitfield{firstAvailableTileMask}, storageInfo.memoryBanks);
} else {
EXPECT_NE(DeviceBitfield{firstAvailableTileMask}, storageInfo.memoryBanks);
}
}
}
}
TEST_F(MultiDeviceStorageInfoTest, givenDirectSubmissionForceLocalMemoryStorageEnabledForAllEnginesWhenCreatingStorageInfoForCommandRingOrSemaphoreBufferThenFirstBankIsSelected) {
DebugManagerStateRestore restorer;
DebugManager.flags.DirectSubmissionForceLocalMemoryStorageMode.set(2);
constexpr uint32_t firstAvailableTileMask = 2u;
memoryManager->internalLocalMemoryUsageBankSelector[mockRootDeviceIndex]->reserveOnBanks(firstAvailableTileMask, MemoryConstants::pageSize2Mb);
EXPECT_NE(1u, memoryManager->internalLocalMemoryUsageBankSelector[mockRootDeviceIndex]->getLeastOccupiedBank(allTilesMask));
AffinityMaskHelper affinityMaskHelper{false};
affinityMaskHelper.enableGenericSubDevice(1);
affinityMaskHelper.enableGenericSubDevice(2);
affinityMaskHelper.enableGenericSubDevice(3);
memoryManager->peekExecutionEnvironment().rootDeviceEnvironments[mockRootDeviceIndex]->deviceAffinityMask = affinityMaskHelper;
for (auto &multiTile : ::testing::Bool()) {
for (auto &allocationType : {AllocationType::COMMAND_BUFFER, AllocationType::RING_BUFFER, AllocationType::SEMAPHORE_BUFFER}) {
AllocationProperties properties{mockRootDeviceIndex, false, numDevices * MemoryConstants::pageSize64k, allocationType, false, affinityMaskHelper.getGenericSubDevicesMask()};
properties.flags.multiOsContextCapable = multiTile;
auto storageInfo = memoryManager->createStorageInfoFromProperties(properties);
EXPECT_EQ(DeviceBitfield{firstAvailableTileMask}, storageInfo.memoryBanks);
}
}
}