mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-11 08:07:19 +08:00
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:
committed by
Compute-Runtime-Automation
parent
71bef6094d
commit
3d92186362
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user