fix: properly set systemMemoryForced flag for secondary command buffers

Due to this flag was not properly handled on Windows, command buffer
allocations were never reused in immediate command lists in case of
host secondary buffers. This lead to huge host memory consumption
and performance degradation

Related-To: NEO-8072

Signed-off-by: Igor Venevtsev <igor.venevtsev@intel.com>
This commit is contained in:
Igor Venevtsev
2023-07-05 16:01:51 +00:00
committed by Compute-Runtime-Automation
parent 3242d3f8eb
commit eba306c099
3 changed files with 47 additions and 2 deletions

View File

@@ -482,7 +482,12 @@ GraphicsAllocation *CommandContainer::allocateCommandBuffer(bool forceHostMemory
device->getDeviceBitfield()};
properties.flags.forceSystemMemory = forceHostMemory && this->useSecondaryCommandStream;
return device->getMemoryManager()->allocateGraphicsMemoryWithProperties(properties);
auto commandBufferAllocation = device->getMemoryManager()->allocateGraphicsMemoryWithProperties(properties);
if (commandBufferAllocation) {
commandBufferAllocation->storageInfo.systemMemoryForced = properties.flags.forceSystemMemory;
}
return commandBufferAllocation;
}
void CommandContainer::fillReusableAllocationLists() {

View File

@@ -150,7 +150,7 @@ class CommandContainer : public NonCopyableOrMovableClass {
GraphicsAllocation *reuseExistingCmdBuffer();
GraphicsAllocation *reuseExistingCmdBuffer(bool forceHostMemory);
GraphicsAllocation *allocateCommandBuffer();
GraphicsAllocation *allocateCommandBuffer(bool forceHostMemory);
MOCKABLE_VIRTUAL GraphicsAllocation *allocateCommandBuffer(bool forceHostMemory);
void setCmdBuffer(GraphicsAllocation *cmdBuffer);
void addCurrentCommandBufferToReusableAllocationList();

View File

@@ -37,6 +37,13 @@ class MyMockCommandContainer : public CommandContainer {
using CommandContainer::getAlignedCmdBufferSize;
using CommandContainer::immediateReusableAllocationList;
using CommandContainer::secondaryCommandStreamForImmediateCmdList;
GraphicsAllocation *allocateCommandBuffer(bool forceHostMemory) override {
allocateCommandBufferCalled[!!forceHostMemory]++;
return CommandContainer::allocateCommandBuffer(forceHostMemory);
}
uint32_t allocateCommandBufferCalled[2] = {0, 0};
};
struct CommandContainerHeapStateTests : public ::testing::Test {
@@ -1432,6 +1439,39 @@ TEST_F(CommandContainerTest, givenCreateSecondaryCmdBufferInHostMemWhenFillReusa
allocList.freeAllGraphicsAllocations(pDevice);
}
TEST_F(CommandContainerTest, givenSecondCmdContainerCreatedAfterFirstCmdContainerDestroyedAndReusableAllocationsListUsedThenCommandBuffersAllocationsAreReused) {
auto cmdContainer = std::make_unique<MyMockCommandContainer>();
AllocationsList allocList;
cmdContainer->initialize(pDevice, &allocList, HeapSize::defaultHeapSize, true, true);
EXPECT_EQ(1u, cmdContainer->allocateCommandBufferCalled[0]); // forceHostMemory = 0
EXPECT_EQ(1u, cmdContainer->allocateCommandBufferCalled[1]); // forceHostMemory = 1
EXPECT_TRUE(allocList.peekIsEmpty());
cmdContainer.reset();
EXPECT_FALSE(allocList.peekIsEmpty());
cmdContainer = std::make_unique<MyMockCommandContainer>();
cmdContainer->initialize(pDevice, &allocList, HeapSize::defaultHeapSize, true, true);
EXPECT_EQ(0u, cmdContainer->allocateCommandBufferCalled[0]); // forceHostMemory = 0
EXPECT_EQ(0u, cmdContainer->allocateCommandBufferCalled[1]); // forceHostMemory = 1
cmdContainer.reset();
allocList.freeAllGraphicsAllocations(pDevice);
}
TEST_F(CommandContainerTest, givenAllocateCommandBufferInHostMemoryCalledThenForceSystemMemoryFlagSetInAllocationStorageInfo) {
auto cmdContainer = std::make_unique<MyMockCommandContainer>();
cmdContainer->initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, true);
auto commandBufferAllocation = cmdContainer->allocateCommandBuffer(true /*forceHostMemory*/);
EXPECT_TRUE(commandBufferAllocation->storageInfo.systemMemoryForced);
pDevice->getMemoryManager()->freeGraphicsMemory(commandBufferAllocation);
cmdContainer.reset();
}
TEST_F(CommandContainerTest, givenCmdContainerWhenFillReusableAllocationListsWithSharedHeapsEnabledThenOnlyOneHeapFilled) {
DebugManagerStateRestore dbgRestore;
DebugManager.flags.SetAmountOfReusableAllocations.set(1);