Add heap sharing to immediate command lists

This change is intended to be used in immediate command lists that are
using flush task functionality.
With this change all immediate command list using the same csr will consume
shared allocations for dsh and ssh heaps. This will decrease number of SBA
commands dispatched when multiple command lists coexists and dispatch kernels.
With this change new SBA command should be dispatched only when current heap
allocation is exhausted.
Functionality is currently disabled and available under debug key.
Functionality will be enabled by default for all immediate command lists
with flush task functionality enabled.

Related-To: NEO-7142

Signed-off-by: Zbigniew Zdanowicz <zbigniew.zdanowicz@intel.com>
This commit is contained in:
Zbigniew Zdanowicz
2022-09-26 22:28:10 +00:00
committed by Compute-Runtime-Automation
parent 71bef6094d
commit 3d92186362
35 changed files with 671 additions and 93 deletions

View File

@@ -18,26 +18,17 @@ using namespace NEO;
constexpr uint32_t defaultNumIddsPerBlock = 64;
class CommandContainerTest : public DeviceFixture,
public ::testing::Test {
using CommandContainerFixture = DeviceFixture;
using CommandContainerTest = Test<CommandContainerFixture>;
class MyMockCommandContainer : public CommandContainer {
public:
void SetUp() override {
::testing::Test::SetUp();
DeviceFixture::setUp();
}
void TearDown() override {
DeviceFixture::tearDown();
::testing::Test::TearDown();
}
using CommandContainer::allocationIndirectHeaps;
using CommandContainer::dirtyHeaps;
using CommandContainer::getTotalCmdBufferSize;
};
struct CommandContainerHeapStateTests : public ::testing::Test {
class MyMockCommandContainer : public CommandContainer {
public:
using CommandContainer::dirtyHeaps;
};
MyMockCommandContainer myCommandContainer;
};
@@ -795,23 +786,18 @@ TEST_F(CommandContainerTest, givenCmdContainerWhenContainerIsInitializedThenStre
TEST_F(CommandContainerTest, GivenCmdContainerAndDebugFlagWhenContainerIsInitializedThenStreamSizeEqualsAlignedTotalCmdBuffSizeDecreasedOfReservedSize) {
DebugManagerStateRestore restorer;
class MyCommandContainer : public CommandContainer {
public:
using CommandContainer::getTotalCmdBufferSize;
};
DebugManager.flags.OverrideCmdListCmdBufferSizeInKb.set(0);
MyCommandContainer cmdContainer;
MyMockCommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, true);
size_t alignedSize = alignUp<size_t>(cmdContainer.getTotalCmdBufferSize(), MemoryConstants::pageSize64k);
EXPECT_EQ(cmdContainer.getCommandStream()->getMaxAvailableSpace(), alignedSize - MyCommandContainer::cmdBufferReservedSize);
EXPECT_EQ(cmdContainer.getCommandStream()->getMaxAvailableSpace(), alignedSize - MyMockCommandContainer::cmdBufferReservedSize);
auto newSizeInKB = 512;
DebugManager.flags.OverrideCmdListCmdBufferSizeInKb.set(newSizeInKB);
MyCommandContainer cmdContainer2;
MyMockCommandContainer cmdContainer2;
cmdContainer2.initialize(pDevice, nullptr, true);
alignedSize = alignUp<size_t>(cmdContainer.getTotalCmdBufferSize(), MemoryConstants::pageSize64k);
EXPECT_EQ(cmdContainer2.getCommandStream()->getMaxAvailableSpace(), alignedSize - MyCommandContainer::cmdBufferReservedSize);
EXPECT_EQ(cmdContainer2.getCommandStream()->getMaxAvailableSpace(), alignedSize - MyMockCommandContainer::cmdBufferReservedSize);
}
TEST_F(CommandContainerTest, givenCmdContainerWhenAlocatingNextCmdBufferThenStreamSizeEqualAlignedTotalCmdBuffSizeDecreasedOfReservedSize) {
@@ -841,15 +827,68 @@ TEST_F(CommandContainerTest, givenCmdContainerWhenCloseAndAllocateNextCommandBuf
}
TEST_F(CommandContainerTest, GivenCmdContainerWhenContainerIsInitializedThenSurfaceStateIndirectHeapSizeIsCorrect) {
class MyCommandContainer : public CommandContainer {
public:
using CommandContainer::allocationIndirectHeaps;
};
MyCommandContainer cmdContainer;
MyMockCommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, true);
auto size = cmdContainer.allocationIndirectHeaps[IndirectHeap::Type::SURFACE_STATE]->getUnderlyingBufferSize();
constexpr size_t expectedHeapSize = MemoryConstants::pageSize64k;
EXPECT_EQ(expectedHeapSize, size);
}
TEST_F(CommandContainerTest, givenCmdContainerHasImmediateCsrWhenGettingHeapWithoutEnsuringSpaceThenExpectNullptrReturnedOrUnrecoverable) {
CommandContainer cmdContainer;
cmdContainer.setImmediateCmdListCsr(pDevice->getDefaultEngine().commandStreamReceiver);
cmdContainer.setNumIddPerBlock(1);
auto code = cmdContainer.initialize(pDevice, nullptr, true);
EXPECT_EQ(CommandContainer::ErrorCode::SUCCESS, code);
EXPECT_EQ(nullptr, cmdContainer.getIndirectHeap(HeapType::DYNAMIC_STATE));
EXPECT_EQ(nullptr, cmdContainer.getIndirectHeap(HeapType::SURFACE_STATE));
EXPECT_THROW(cmdContainer.getHeapSpaceAllowGrow(HeapType::DYNAMIC_STATE, 0), std::exception);
EXPECT_THROW(cmdContainer.getHeapWithRequiredSizeAndAlignment(HeapType::DYNAMIC_STATE, 0, 0), std::exception);
EXPECT_THROW(cmdContainer.getHeapSpaceAllowGrow(HeapType::SURFACE_STATE, 0), std::exception);
EXPECT_THROW(cmdContainer.getHeapWithRequiredSizeAndAlignment(HeapType::SURFACE_STATE, 0, 0), std::exception);
cmdContainer.ensureHeapSizePrepared(0, 0);
EXPECT_EQ(nullptr, cmdContainer.getIndirectHeap(HeapType::DYNAMIC_STATE));
EXPECT_NE(nullptr, cmdContainer.getIndirectHeap(HeapType::SURFACE_STATE));
EXPECT_THROW(cmdContainer.getHeapSpaceAllowGrow(HeapType::DYNAMIC_STATE, 0), std::exception);
EXPECT_THROW(cmdContainer.getHeapWithRequiredSizeAndAlignment(HeapType::DYNAMIC_STATE, 0, 0), std::exception);
EXPECT_NO_THROW(cmdContainer.getHeapSpaceAllowGrow(HeapType::SURFACE_STATE, 0));
EXPECT_NO_THROW(cmdContainer.getHeapWithRequiredSizeAndAlignment(HeapType::SURFACE_STATE, 0, 0));
cmdContainer.ensureHeapSizePrepared(4 * MemoryConstants::kiloByte, 4 * MemoryConstants::kiloByte);
auto dshHeap = cmdContainer.getIndirectHeap(HeapType::DYNAMIC_STATE);
EXPECT_NE(nullptr, dshHeap);
auto sshHeap = cmdContainer.getIndirectHeap(HeapType::SURFACE_STATE);
EXPECT_NE(nullptr, sshHeap);
size_t sizeUsedDsh = dshHeap->getUsed();
size_t sizeUsedSsh = sshHeap->getUsed();
void *dshPtr = cmdContainer.getHeapSpaceAllowGrow(HeapType::DYNAMIC_STATE, 64);
void *sshPtr = cmdContainer.getHeapSpaceAllowGrow(HeapType::SURFACE_STATE, 64);
EXPECT_EQ(ptrOffset(dshHeap->getCpuBase(), sizeUsedDsh), dshPtr);
EXPECT_EQ(ptrOffset(sshHeap->getCpuBase(), sizeUsedSsh), sshPtr);
auto alignedHeapDsh = cmdContainer.getHeapWithRequiredSizeAndAlignment(HeapType::DYNAMIC_STATE, 128, 128);
auto alignedHeapSsh = cmdContainer.getHeapWithRequiredSizeAndAlignment(HeapType::SURFACE_STATE, 128, 128);
EXPECT_EQ(dshHeap, alignedHeapDsh);
EXPECT_EQ(sshHeap, alignedHeapSsh);
dshHeap->getSpace(dshHeap->getAvailableSpace() - 32);
sshHeap->getSpace(sshHeap->getAvailableSpace() - 32);
EXPECT_THROW(cmdContainer.getHeapSpaceAllowGrow(HeapType::DYNAMIC_STATE, 64), std::exception);
EXPECT_THROW(cmdContainer.getHeapWithRequiredSizeAndAlignment(HeapType::DYNAMIC_STATE, 64, 64), std::exception);
EXPECT_THROW(cmdContainer.getHeapSpaceAllowGrow(HeapType::SURFACE_STATE, 64), std::exception);
EXPECT_THROW(cmdContainer.getHeapWithRequiredSizeAndAlignment(HeapType::SURFACE_STATE, 64, 64), std::exception);
}

View File

@@ -2124,3 +2124,27 @@ using SystolicSupport = IsAnyProducts<IGFX_ALDERLAKE_P, IGFX_XE_HP_SDV, IGFX_DG2
HWTEST2_F(CommandStreamReceiverSystolicTests, givenSystolicModeChangedWhenFlushTaskCalledThenSystolicStateIsUpdated, SystolicSupport) {
testBody<FamilyType>();
}
HWTEST_F(CommandStreamReceiverTest, givenSshDirtyStateWhenUpdatingStateWithNewHeapThenExpectDirtyStateTrue) {
MockGraphicsAllocation allocation{};
allocation.gpuAddress = 0xABC000;
allocation.size = 0x1000;
IndirectHeap dummyHeap(&allocation, false);
auto dirtyStateCopy = static_cast<CommandStreamReceiverHw<FamilyType> *>(commandStreamReceiver)->getSshState();
bool check = dirtyStateCopy.updateAndCheck(&dummyHeap);
EXPECT_TRUE(check);
check = dirtyStateCopy.updateAndCheck(&dummyHeap);
EXPECT_FALSE(check);
auto dirtyState = static_cast<CommandStreamReceiverHw<FamilyType> *>(commandStreamReceiver)->getSshState();
check = dirtyState.updateAndCheck(&dummyHeap);
EXPECT_TRUE(check);
check = dirtyState.updateAndCheck(&dummyHeap);
EXPECT_FALSE(check);
}

View File

@@ -17,6 +17,7 @@
#include "shared/test/common/helpers/debug_manager_state_restore.h"
#include "shared/test/common/helpers/default_hw_info.h"
#include "shared/test/common/helpers/gtest_helpers.h"
#include "shared/test/common/helpers/unit_test_helper.h"
#include "shared/test/common/mocks/mock_device.h"
#include "shared/test/common/test_macros/test.h"
#include "shared/test/unit_test/fixtures/command_container_fixture.h"
@@ -1324,3 +1325,67 @@ HWTEST_F(BindlessCommandEncodeStatesTest, givenBindlessModeDisabledelWithSampler
EXPECT_EQ(std::find(cmdContainer->getResidencyContainer().begin(), cmdContainer->getResidencyContainer().end(), pDevice->getBindlessHeapsHelper()->getHeap(BindlessHeapsHelper::GLOBAL_DSH)->getGraphicsAllocation()), cmdContainer->getResidencyContainer().end());
}
HWTEST_F(CommandEncodeStatesTest, givenKernelInfoWhenGettingRequiredDshSpaceThenReturnCorrectValues) {
using INTERFACE_DESCRIPTOR_DATA = typename FamilyType::INTERFACE_DESCRIPTOR_DATA;
using SAMPLER_STATE = typename FamilyType::SAMPLER_STATE;
size_t additionalSize = UnitTestHelper<FamilyType>::getAdditionalDshSize();
size_t expectedSize = alignUp(additionalSize, EncodeStates<FamilyType>::alignInterfaceDescriptorData);
// no samplers
kernelInfo.kernelDescriptor.payloadMappings.samplerTable.numSamplers = 0;
size_t size = EncodeDispatchKernel<FamilyType>::getSizeRequiredDsh(kernelInfo);
EXPECT_EQ(expectedSize, size);
// two samplers, no border color state
kernelInfo.kernelDescriptor.payloadMappings.samplerTable.numSamplers = 2;
kernelInfo.kernelDescriptor.payloadMappings.samplerTable.tableOffset = 0;
kernelInfo.kernelDescriptor.payloadMappings.samplerTable.borderColor = 0;
// align samplers
size_t alignedSamplers = alignUp(2 * sizeof(SAMPLER_STATE), INTERFACE_DESCRIPTOR_DATA::SAMPLERSTATEPOINTER_ALIGN_SIZE);
// additional IDD for requiring platforms
if (additionalSize > 0) {
expectedSize = alignUp(alignedSamplers + additionalSize, EncodeStates<FamilyType>::alignInterfaceDescriptorData);
} else {
expectedSize = alignedSamplers;
}
size = EncodeDispatchKernel<FamilyType>::getSizeRequiredDsh(kernelInfo);
EXPECT_EQ(expectedSize, size);
// three samplers, border color state
kernelInfo.kernelDescriptor.payloadMappings.samplerTable.numSamplers = 3;
kernelInfo.kernelDescriptor.payloadMappings.samplerTable.tableOffset = 32;
// align border color state and samplers
alignedSamplers = alignUp(alignUp(32, EncodeStates<FamilyType>::alignIndirectStatePointer) + 3 * sizeof(SAMPLER_STATE), INTERFACE_DESCRIPTOR_DATA::SAMPLERSTATEPOINTER_ALIGN_SIZE);
// additional IDD for requiring platforms
if (additionalSize > 0) {
expectedSize = alignUp(alignedSamplers + additionalSize, EncodeStates<FamilyType>::alignInterfaceDescriptorData);
} else {
expectedSize = alignedSamplers;
}
size = EncodeDispatchKernel<FamilyType>::getSizeRequiredDsh(kernelInfo);
EXPECT_EQ(expectedSize, size);
}
HWTEST_F(CommandEncodeStatesTest, givenKernelInfoWhenGettingRequiredSshSpaceThenReturnCorrectValues) {
using BINDING_TABLE_STATE = typename FamilyType::BINDING_TABLE_STATE;
using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE;
// no surface states
kernelInfo.heapInfo.SurfaceStateHeapSize = 0;
size_t size = EncodeDispatchKernel<FamilyType>::getSizeRequiredSsh(kernelInfo);
EXPECT_EQ(0u, size);
// two surface states and BTI indices
kernelInfo.heapInfo.SurfaceStateHeapSize = 2 * sizeof(RENDER_SURFACE_STATE) + 2 * sizeof(uint32_t);
size_t expectedSize = alignUp(kernelInfo.heapInfo.SurfaceStateHeapSize, BINDING_TABLE_STATE::SURFACESTATEPOINTER_ALIGN_SIZE);
size = EncodeDispatchKernel<FamilyType>::getSizeRequiredSsh(kernelInfo);
EXPECT_EQ(expectedSize, size);
}

View File

@@ -8,6 +8,7 @@
#pragma once
#include "shared/source/command_container/command_encoder.h"
#include "shared/source/kernel/kernel_descriptor.h"
#include "shared/source/program/kernel_info.h"
#include "shared/test/common/fixtures/device_fixture.h"
#include "shared/test/common/test_macros/hw_test.h"
@@ -44,6 +45,7 @@ class CommandEncodeStatesFixture : public DeviceFixture {
}
KernelDescriptor descriptor;
KernelInfo kernelInfo;
std::unique_ptr<MyMockCommandContainer> cmdContainer;
};