compute-runtime/shared/test/unit_test/command_container/command_container_tests.cpp

1874 lines
88 KiB
C++

/*
* Copyright (C) 2019-2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/command_container/cmdcontainer.h"
#include "shared/source/command_container/command_encoder.h"
#include "shared/source/command_stream/linear_stream.h"
#include "shared/source/helpers/gfx_core_helper.h"
#include "shared/source/helpers/heap_helper.h"
#include "shared/source/indirect_heap/indirect_heap.h"
#include "shared/source/memory_manager/allocations_list.h"
#include "shared/source/memory_manager/internal_allocation_storage.h"
#include "shared/test/common/cmd_parse/gen_cmd_parse.h"
#include "shared/test/common/fixtures/device_fixture.h"
#include "shared/test/common/helpers/debug_manager_state_restore.h"
#include "shared/test/common/libult/ult_command_stream_receiver.h"
#include "shared/test/common/mocks/mock_bindless_heaps_helper.h"
#include "shared/test/common/mocks/mock_device.h"
#include "shared/test/common/mocks/mock_graphics_allocation.h"
#include "shared/test/common/mocks/mock_memory_manager.h"
#include "shared/test/common/test_macros/hw_test.h"
using namespace NEO;
constexpr uint32_t defaultNumIddsPerBlock = 64;
using CommandContainerFixture = DeviceFixture;
using CommandContainerTest = Test<CommandContainerFixture>;
class MyMockCommandContainer : public CommandContainer {
public:
using CommandContainer::allocationIndirectHeaps;
using CommandContainer::defaultSshSize;
using CommandContainer::dirtyHeaps;
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 {
MyMockCommandContainer myCommandContainer;
};
TEST_F(CommandContainerHeapStateTests, givenDirtyHeapsWhenSettingStateForAllThenValuesAreCorrect) {
EXPECT_EQ(std::numeric_limits<uint32_t>::max(), myCommandContainer.dirtyHeaps);
EXPECT_TRUE(myCommandContainer.isAnyHeapDirty());
myCommandContainer.setDirtyStateForAllHeaps(false);
EXPECT_EQ(0u, myCommandContainer.dirtyHeaps);
EXPECT_FALSE(myCommandContainer.isAnyHeapDirty());
for (uint32_t i = 0; i < HeapType::numTypes; i++) {
HeapType heapType = static_cast<HeapType>(i);
EXPECT_FALSE(myCommandContainer.isHeapDirty(heapType));
}
myCommandContainer.setDirtyStateForAllHeaps(true);
EXPECT_EQ(std::numeric_limits<uint32_t>::max(), myCommandContainer.dirtyHeaps);
for (uint32_t i = 0; i < HeapType::numTypes; i++) {
HeapType heapType = static_cast<HeapType>(i);
EXPECT_TRUE(myCommandContainer.isHeapDirty(heapType));
}
}
TEST_F(CommandContainerHeapStateTests, givenDirtyHeapsWhenSettingStateForSingleHeapThenValuesAreCorrect) {
myCommandContainer.dirtyHeaps = 0;
EXPECT_FALSE(myCommandContainer.isAnyHeapDirty());
uint32_t controlVariable = 0;
for (uint32_t i = 0; i < HeapType::numTypes; i++) {
HeapType heapType = static_cast<HeapType>(i);
EXPECT_FALSE(myCommandContainer.isHeapDirty(heapType));
myCommandContainer.setHeapDirty(heapType);
EXPECT_TRUE(myCommandContainer.isHeapDirty(heapType));
EXPECT_TRUE(myCommandContainer.isAnyHeapDirty());
controlVariable |= (1 << i);
EXPECT_EQ(controlVariable, myCommandContainer.dirtyHeaps);
}
for (uint32_t i = 0; i < HeapType::numTypes; i++) {
HeapType heapType = static_cast<HeapType>(i);
EXPECT_TRUE(myCommandContainer.isHeapDirty(heapType));
}
}
TEST_F(CommandContainerTest, givenCmdContainerWhenCreatingCommandBufferThenCorrectAllocationTypeIsSet) {
CommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
ASSERT_NE(0u, cmdContainer.getCmdBufferAllocations().size());
EXPECT_EQ(AllocationType::commandBuffer, cmdContainer.getCmdBufferAllocations()[0]->getAllocationType());
cmdContainer.allocateNextCommandBuffer();
ASSERT_LE(2u, cmdContainer.getCmdBufferAllocations().size());
EXPECT_EQ(AllocationType::commandBuffer, cmdContainer.getCmdBufferAllocations()[1]->getAllocationType());
}
TEST_F(CommandContainerTest, givenCreateSecondaryCmdBufferInHostMemWhenInitializeThenCreateAdditionalLinearStream) {
MyMockCommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, true);
EXPECT_NE(cmdContainer.secondaryCommandStreamForImmediateCmdList.get(), nullptr);
auto secondaryCmdStream = cmdContainer.secondaryCommandStreamForImmediateCmdList.get();
auto cmdStream = cmdContainer.getCommandStream();
EXPECT_TRUE(cmdContainer.swapStreams());
EXPECT_EQ(cmdContainer.getCommandStream(), secondaryCmdStream);
EXPECT_EQ(cmdContainer.secondaryCommandStreamForImmediateCmdList.get(), cmdStream);
}
TEST_F(CommandContainerTest, whenInitializeThenNotCreateAdditionalLinearStream) {
MyMockCommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
EXPECT_EQ(cmdContainer.secondaryCommandStreamForImmediateCmdList.get(), nullptr);
auto cmdStream = cmdContainer.getCommandStream();
EXPECT_FALSE(cmdContainer.swapStreams());
EXPECT_EQ(cmdContainer.getCommandStream(), cmdStream);
}
TEST_F(CommandContainerTest, givenCmdContainerWhenAllocatingHeapsThenSetCorrectAllocationTypes) {
CommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
for (uint32_t i = 0; i < HeapType::numTypes; i++) {
HeapType heapType = static_cast<HeapType>(i);
auto heap = cmdContainer.getIndirectHeap(heapType);
if (!pDevice->getHardwareInfo().capabilityTable.supportsImages && HeapType::dynamicState == heapType) {
EXPECT_EQ(heap, nullptr);
} else {
if (HeapType::indirectObject == heapType) {
EXPECT_EQ(AllocationType::internalHeap, heap->getGraphicsAllocation()->getAllocationType());
EXPECT_NE(0u, heap->getHeapGpuStartOffset());
} else {
EXPECT_EQ(AllocationType::linearStream, heap->getGraphicsAllocation()->getAllocationType());
EXPECT_EQ(0u, heap->getHeapGpuStartOffset());
}
}
}
}
TEST_F(CommandContainerTest, givenCommandContainerWhenInitializeThenEverythingIsInitialized) {
CommandContainer cmdContainer;
auto status = cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
EXPECT_EQ(CommandContainer::ErrorCode::success, status);
EXPECT_EQ(pDevice, cmdContainer.getDevice());
EXPECT_NE(cmdContainer.getHeapHelper(), nullptr);
EXPECT_EQ(cmdContainer.getCmdBufferAllocations().size(), 1u);
EXPECT_NE(cmdContainer.getCommandStream(), nullptr);
EXPECT_EQ(0u, cmdContainer.currentLinearStreamStartOffsetRef());
for (uint32_t i = 0; i < HeapType::numTypes; i++) {
auto heapType = static_cast<HeapType>(i);
auto indirectHeap = cmdContainer.getIndirectHeap(heapType);
if (!pDevice->getHardwareInfo().capabilityTable.supportsImages && HeapType::dynamicState == heapType) {
EXPECT_EQ(indirectHeap, nullptr);
} else {
auto heapAllocation = cmdContainer.getIndirectHeapAllocation(heapType);
EXPECT_EQ(indirectHeap->getGraphicsAllocation(), heapAllocation);
}
}
EXPECT_EQ(cmdContainer.getIddBlock(), nullptr);
EXPECT_EQ(cmdContainer.getNumIddPerBlock(), defaultNumIddsPerBlock);
auto &gfxCoreHelper = pDevice->getGfxCoreHelper();
EXPECT_EQ(cmdContainer.getInstructionHeapBaseAddress(),
pDevice->getMemoryManager()->getInternalHeapBaseAddress(0, !gfxCoreHelper.useSystemMemoryPlacementForISA(pDevice->getHardwareInfo())));
}
TEST_F(CommandContainerTest, givenCommandContainerWhenHeapNotRequiredThenHeapIsNotInitialized) {
CommandContainer cmdContainer;
auto status = cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, false, false);
EXPECT_EQ(CommandContainer::ErrorCode::success, status);
EXPECT_EQ(pDevice, cmdContainer.getDevice());
EXPECT_EQ(cmdContainer.getHeapHelper(), nullptr);
EXPECT_EQ(cmdContainer.getCmdBufferAllocations().size(), 1u);
EXPECT_NE(cmdContainer.getCommandStream(), nullptr);
for (uint32_t i = 0; i < HeapType::numTypes; i++) {
auto indirectHeap = cmdContainer.getIndirectHeap(static_cast<HeapType>(i));
EXPECT_EQ(indirectHeap, nullptr);
}
EXPECT_EQ(cmdContainer.getIddBlock(), nullptr);
EXPECT_EQ(cmdContainer.getNumIddPerBlock(), defaultNumIddsPerBlock);
EXPECT_EQ(cmdContainer.getInstructionHeapBaseAddress(), 0u);
}
TEST_F(CommandContainerTest, givenEnabledLocalMemoryAndIsaInSystemMemoryWhenCmdContainerIsInitializedThenInstructionBaseAddressIsSetToInternalHeap) {
DebugManagerStateRestore dbgRestore;
debugManager.flags.ForceSystemMemoryPlacement.set(1 << (static_cast<uint32_t>(AllocationType::kernelIsa) - 1));
auto executionEnvironment = new NEO::ExecutionEnvironment();
const size_t numDevices = 1;
executionEnvironment->prepareRootDeviceEnvironments(numDevices);
executionEnvironment->rootDeviceEnvironments[0]->setHwInfoAndInitHelpers(defaultHwInfo.get());
executionEnvironment->rootDeviceEnvironments[0]->initGmm();
auto hwInfo = executionEnvironment->rootDeviceEnvironments[0]->getMutableHardwareInfo();
hwInfo->featureTable.flags.ftrLocalMemory = true;
auto device = std::unique_ptr<MockDevice>(Device::create<MockDevice>(executionEnvironment, 0u));
auto instructionHeapBaseAddress = device->getMemoryManager()->getInternalHeapBaseAddress(0, false);
CommandContainer cmdContainer;
auto status = cmdContainer.initialize(device.get(), nullptr, HeapSize::defaultHeapSize, true, false);
EXPECT_EQ(CommandContainer::ErrorCode::success, status);
EXPECT_EQ(instructionHeapBaseAddress, cmdContainer.getInstructionHeapBaseAddress());
}
TEST_F(CommandContainerTest, givenForceDefaultHeapSizeWhenCmdContainerIsInitializedThenHeapIsCreatedWithProperSize) {
DebugManagerStateRestore restorer;
debugManager.flags.ForceDefaultHeapSize.set(32); // in KB
auto executionEnvironment = new NEO::ExecutionEnvironment();
const size_t numDevices = 1;
executionEnvironment->prepareRootDeviceEnvironments(numDevices);
executionEnvironment->rootDeviceEnvironments[0]->setHwInfoAndInitHelpers(defaultHwInfo.get());
executionEnvironment->rootDeviceEnvironments[0]->initGmm();
auto device = std::unique_ptr<MockDevice>(Device::create<MockDevice>(executionEnvironment, 0u));
CommandContainer cmdContainer;
auto status = cmdContainer.initialize(device.get(), nullptr, HeapSize::defaultHeapSize, true, false);
EXPECT_EQ(CommandContainer::ErrorCode::success, status);
auto indirectHeap = cmdContainer.getIndirectHeap(IndirectHeap::Type::indirectObject);
EXPECT_EQ(indirectHeap->getAvailableSpace(), 32 * MemoryConstants::kiloByte);
}
TEST_F(CommandContainerTest, givenCommandContainerDuringInitWhenAllocateGfxMemoryFailsThenErrorIsReturned) {
CommandContainer cmdContainer;
pDevice->executionEnvironment->memoryManager.reset(new FailMemoryManager(0, *pDevice->executionEnvironment));
auto status = cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
EXPECT_EQ(CommandContainer::ErrorCode::outOfDeviceMemory, status);
}
TEST_F(CommandContainerTest, givenCreateSecondaryCmdBufferInHostMemWhenAllocateSecondaryCmdStreamFailsDuringInitializeThenErrorIsReturned) {
CommandContainer cmdContainer;
static_cast<MockMemoryManager *>(pDevice->getMemoryManager())->maxSuccessAllocatedGraphicsMemoryIndex = 7;
auto status = cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, true);
EXPECT_EQ(CommandContainer::ErrorCode::outOfDeviceMemory, status);
}
TEST_F(CommandContainerTest, givenCmdContainerWithAllocsListWhenAllocateAndResetThenCmdBufferAllocIsReused) {
AllocationsList allocList;
auto cmdContainer = std::make_unique<CommandContainer>();
cmdContainer->initialize(pDevice, &allocList, true, HeapSize::defaultHeapSize, false);
auto &cmdBufferAllocs = cmdContainer->getCmdBufferAllocations();
auto memoryManager = static_cast<MockMemoryManager *>(pDevice->getMemoryManager());
EXPECT_EQ(memoryManager->handleFenceCompletionCalled, 0u);
EXPECT_EQ(cmdBufferAllocs.size(), 1u);
EXPECT_TRUE(allocList.peekIsEmpty());
cmdContainer->allocateNextCommandBuffer();
EXPECT_EQ(cmdBufferAllocs.size(), 2u);
auto cmdBuffer0 = cmdBufferAllocs[0];
auto cmdBuffer1 = cmdBufferAllocs[1];
cmdContainer->reset();
EXPECT_EQ(memoryManager->handleFenceCompletionCalled, 1u);
EXPECT_EQ(cmdBufferAllocs.size(), 1u);
EXPECT_EQ(cmdBufferAllocs[0], cmdBuffer0);
EXPECT_FALSE(allocList.peekIsEmpty());
cmdContainer->allocateNextCommandBuffer();
EXPECT_EQ(cmdBufferAllocs.size(), 2u);
EXPECT_EQ(cmdBufferAllocs[0], cmdBuffer0);
EXPECT_EQ(cmdBufferAllocs[1], cmdBuffer1);
EXPECT_TRUE(allocList.peekIsEmpty());
cmdContainer.reset();
EXPECT_EQ(memoryManager->handleFenceCompletionCalled, 3u);
EXPECT_FALSE(allocList.peekIsEmpty());
allocList.freeAllGraphicsAllocations(pDevice);
}
TEST_F(CommandContainerTest, givenReusableAllocationsAndRemoveUserFenceInCmdlistResetAndDestroyFlagWhenAllocateAndResetThenHandleFenceCompletionIsCalled) {
DebugManagerStateRestore restore;
debugManager.flags.RemoveUserFenceInCmdlistResetAndDestroy.set(0);
AllocationsList allocList;
auto cmdContainer = std::make_unique<CommandContainer>();
cmdContainer->initialize(pDevice, &allocList, HeapSize::defaultHeapSize, true, false);
auto &cmdBufferAllocs = cmdContainer->getCmdBufferAllocations();
auto memoryManager = static_cast<MockMemoryManager *>(pDevice->getMemoryManager());
EXPECT_EQ(0u, memoryManager->handleFenceCompletionCalled);
EXPECT_EQ(cmdBufferAllocs.size(), 1u);
cmdContainer->allocateNextCommandBuffer();
EXPECT_EQ(cmdBufferAllocs.size(), 2u);
cmdContainer->reset();
EXPECT_EQ(1u, memoryManager->handleFenceCompletionCalled);
cmdContainer->allocateNextCommandBuffer();
EXPECT_EQ(cmdBufferAllocs.size(), 2u);
cmdContainer.reset();
EXPECT_EQ(3u, memoryManager->handleFenceCompletionCalled);
allocList.freeAllGraphicsAllocations(pDevice);
}
TEST_F(CommandContainerTest, givenCommandContainerDuringInitWhenAllocateHeapMemoryFailsThenErrorIsReturned) {
CommandContainer cmdContainer;
auto tempMemoryManager = pDevice->executionEnvironment->memoryManager.release();
pDevice->executionEnvironment->memoryManager.reset(new FailMemoryManager(1, *pDevice->executionEnvironment));
auto status = cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
EXPECT_EQ(CommandContainer::ErrorCode::outOfDeviceMemory, status);
delete tempMemoryManager;
}
TEST_F(CommandContainerTest, givenCommandContainerWhenSettingIndirectHeapAllocationThenAllocationIsSet) {
CommandContainer cmdContainer;
MockGraphicsAllocation mockAllocation;
auto heapType = HeapType::dynamicState;
cmdContainer.setIndirectHeapAllocation(heapType, &mockAllocation);
EXPECT_EQ(cmdContainer.getIndirectHeapAllocation(heapType), &mockAllocation);
}
TEST_F(CommandContainerTest, givenHeapAllocationsWhenDestroyCommandContainerThenHeapAllocationsAreReused) {
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
cmdContainer->initialize(pDevice, nullptr, true, HeapSize::defaultHeapSize, false);
auto heapAllocationsAddress = cmdContainer->getIndirectHeapAllocation(HeapType::surfaceState)->getUnderlyingBuffer();
cmdContainer.reset(new CommandContainer);
cmdContainer->initialize(pDevice, nullptr, true, HeapSize::defaultHeapSize, false);
bool status = true;
for (uint32_t i = 0; i < HeapType::numTypes && !status; i++) {
auto heapType = static_cast<HeapType>(i);
if (!pDevice->getHardwareInfo().capabilityTable.supportsImages && HeapType::dynamicState == heapType) {
status = status && cmdContainer->getIndirectHeapAllocation(heapType) == nullptr;
} else {
status = status && cmdContainer->getIndirectHeapAllocation(heapType)->getUnderlyingBuffer() == heapAllocationsAddress;
}
}
EXPECT_TRUE(status);
}
TEST_F(CommandContainerTest, givenCommandContainerWhenResetThenStateIsReset) {
CommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
LinearStream stream;
uint32_t usedSize = 1;
cmdContainer.getCommandStream()->getSpace(usedSize);
EXPECT_EQ(usedSize, cmdContainer.getCommandStream()->getUsed());
cmdContainer.reset();
EXPECT_NE(usedSize, cmdContainer.getCommandStream()->getUsed());
EXPECT_EQ(0u, cmdContainer.getCommandStream()->getUsed());
EXPECT_EQ(cmdContainer.getIddBlock(), nullptr);
EXPECT_EQ(cmdContainer.getNumIddPerBlock(), defaultNumIddsPerBlock);
}
TEST_F(CommandContainerTest, givenCommandContainerWhenWantToAddNullPtrToResidencyContainerThenNothingIsAdded) {
CommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
auto size = cmdContainer.getResidencyContainer().size();
cmdContainer.addToResidencyContainer(nullptr);
EXPECT_EQ(cmdContainer.getResidencyContainer().size(), size);
}
TEST_F(CommandContainerTest, givenCommandContainerWhenInitializeThenCmdBuffersAreAddedToResidencyContainer) {
CommandContainer cmdContainer;
EXPECT_EQ(cmdContainer.getResidencyContainer().size(), 0u);
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, false, true);
EXPECT_EQ(cmdContainer.getResidencyContainer().size(), 2u);
EXPECT_EQ(cmdContainer.getResidencyContainer().size(), cmdContainer.getCmdBufferAllocations().size());
}
TEST_F(CommandContainerTest, givenCommandContainerWhenWantToAddAlreadyAddedAllocationAndDuplicatesRemovedThenExpectedSizeIsReturned) {
CommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
MockGraphicsAllocation mockAllocation;
auto sizeBefore = cmdContainer.getResidencyContainer().size();
cmdContainer.addToResidencyContainer(&mockAllocation);
auto sizeAfterFirstAdd = cmdContainer.getResidencyContainer().size();
EXPECT_NE(sizeBefore, sizeAfterFirstAdd);
cmdContainer.addToResidencyContainer(&mockAllocation);
auto sizeAfterSecondAdd = cmdContainer.getResidencyContainer().size();
EXPECT_NE(sizeAfterFirstAdd, sizeAfterSecondAdd);
cmdContainer.removeDuplicatesFromResidencyContainer();
auto sizeAfterDuplicatesRemoved = cmdContainer.getResidencyContainer().size();
EXPECT_EQ(sizeAfterFirstAdd, sizeAfterDuplicatesRemoved);
}
HWTEST_F(CommandContainerTest, givenCmdContainerWhenInitializeCalledThenSSHHeapHasBindlessOffsetReserved) {
using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE;
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
cmdContainer->setReservedSshSize(4 * MemoryConstants::pageSize);
cmdContainer->initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
cmdContainer->setDirtyStateForAllHeaps(false);
auto heap = cmdContainer->getIndirectHeap(HeapType::surfaceState);
ASSERT_NE(nullptr, heap);
EXPECT_EQ(4 * MemoryConstants::pageSize, heap->getUsed());
}
HWTEST_F(CommandContainerTest, givenNotEnoughSpaceInSSHWhenGettingHeapWithRequiredSizeAndAlignmentThenSSHHeapHasBindlessOffsetReserved) {
using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE;
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
cmdContainer->setReservedSshSize(4 * MemoryConstants::pageSize);
cmdContainer->initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
cmdContainer->setDirtyStateForAllHeaps(false);
auto heap = cmdContainer->getIndirectHeap(HeapType::surfaceState);
ASSERT_NE(nullptr, heap);
heap->getSpace(heap->getAvailableSpace());
cmdContainer->getHeapWithRequiredSizeAndAlignment(HeapType::surfaceState, sizeof(RENDER_SURFACE_STATE), 0);
EXPECT_EQ(4 * MemoryConstants::pageSize, heap->getUsed());
EXPECT_EQ(cmdContainer->getSshAllocations().size(), 1u);
}
TEST_F(CommandContainerTest, givenAvailableSpaceWhenGetHeapWithRequiredSizeAndAlignmentCalledThenExistingAllocationIsReturned) {
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
cmdContainer->initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
cmdContainer->setDirtyStateForAllHeaps(false);
HeapType heapTypes[] = {HeapType::surfaceState,
HeapType::dynamicState};
for (auto heapType : heapTypes) {
auto heapAllocation = cmdContainer->getIndirectHeapAllocation(heapType);
auto heap = cmdContainer->getIndirectHeap(heapType);
if (!pDevice->getHardwareInfo().capabilityTable.supportsImages && HeapType::dynamicState == heapType) {
EXPECT_EQ(heap, nullptr);
} else {
const size_t sizeRequested = 32;
const size_t alignment = 32;
EXPECT_GE(heap->getAvailableSpace(), sizeRequested + alignment);
auto sizeBefore = heap->getUsed();
auto heapRequested = cmdContainer->getHeapWithRequiredSizeAndAlignment(heapType, sizeRequested, alignment);
auto newAllocation = heapRequested->getGraphicsAllocation();
EXPECT_EQ(heap, heapRequested);
EXPECT_EQ(heapAllocation, newAllocation);
EXPECT_TRUE((reinterpret_cast<size_t>(heapRequested->getSpace(0)) & (alignment - 1)) == 0);
EXPECT_FALSE(cmdContainer->isHeapDirty(heapType));
auto sizeAfter = heapRequested->getUsed();
EXPECT_EQ(sizeBefore, sizeAfter);
}
}
}
TEST_F(CommandContainerTest, givenUnalignedAvailableSpaceWhenGetHeapWithRequiredSizeAndAlignmentCalledThenHeapReturnedIsCorrectlyAligned) {
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
cmdContainer->initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
cmdContainer->setDirtyStateForAllHeaps(false);
auto heapAllocation = cmdContainer->getIndirectHeapAllocation(HeapType::surfaceState);
auto heap = cmdContainer->getIndirectHeap(HeapType::surfaceState);
const size_t sizeRequested = 32;
const size_t alignment = 32;
heap->getSpace(sizeRequested / 2);
EXPECT_GE(heap->getAvailableSpace(), sizeRequested + alignment);
auto heapRequested = cmdContainer->getHeapWithRequiredSizeAndAlignment(HeapType::surfaceState, sizeRequested, alignment);
auto newAllocation = heapRequested->getGraphicsAllocation();
EXPECT_EQ(heap, heapRequested);
EXPECT_EQ(heapAllocation, newAllocation);
EXPECT_TRUE((reinterpret_cast<size_t>(heapRequested->getSpace(0)) & (alignment - 1)) == 0);
EXPECT_FALSE(cmdContainer->isHeapDirty(HeapType::surfaceState));
}
TEST_F(CommandContainerTest, givenNoAlignmentAndAvailableSpaceWhenGetHeapWithRequiredSizeAndAlignmentCalledThenHeapReturnedIsNotAligned) {
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
cmdContainer->initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
cmdContainer->setDirtyStateForAllHeaps(false);
auto heapAllocation = cmdContainer->getIndirectHeapAllocation(HeapType::surfaceState);
auto heap = cmdContainer->getIndirectHeap(HeapType::surfaceState);
const size_t sizeRequested = 32;
const size_t alignment = 0;
heap->getSpace(sizeRequested / 2);
EXPECT_GE(heap->getAvailableSpace(), sizeRequested + alignment);
auto heapRequested = cmdContainer->getHeapWithRequiredSizeAndAlignment(HeapType::surfaceState, sizeRequested, alignment);
auto newAllocation = heapRequested->getGraphicsAllocation();
EXPECT_EQ(heap, heapRequested);
EXPECT_EQ(heapAllocation, newAllocation);
EXPECT_TRUE((reinterpret_cast<size_t>(heapRequested->getSpace(0)) & (sizeRequested / 2)) == sizeRequested / 2);
EXPECT_FALSE(cmdContainer->isHeapDirty(HeapType::surfaceState));
}
TEST_F(CommandContainerTest, givenNotEnoughSpaceWhenGetHeapWithRequiredSizeAndAlignmentCalledThenNewAllocationIsReturned) {
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
cmdContainer->initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
cmdContainer->setDirtyStateForAllHeaps(false);
HeapType heapTypes[] = {HeapType::surfaceState,
HeapType::dynamicState};
for (auto heapType : heapTypes) {
auto heapAllocation = cmdContainer->getIndirectHeapAllocation(heapType);
auto heap = cmdContainer->getIndirectHeap(heapType);
if (!pDevice->getHardwareInfo().capabilityTable.supportsImages && HeapType::dynamicState == heapType) {
EXPECT_EQ(heap, nullptr);
} else {
const size_t sizeRequested = 32;
const size_t alignment = 32;
size_t availableSize = heap->getAvailableSpace();
heap->getSpace(availableSize - sizeRequested / 2);
EXPECT_LT(heap->getAvailableSpace(), sizeRequested + alignment);
auto heapRequested = cmdContainer->getHeapWithRequiredSizeAndAlignment(heapType, sizeRequested, alignment);
auto newAllocation = heapRequested->getGraphicsAllocation();
EXPECT_EQ(heap, heapRequested);
EXPECT_NE(heapAllocation, newAllocation);
EXPECT_TRUE((reinterpret_cast<size_t>(heapRequested->getSpace(0)) & (alignment - 1)) == 0);
EXPECT_TRUE(cmdContainer->isHeapDirty(heapType));
}
}
for (auto deallocation : cmdContainer->getDeallocationContainer()) {
cmdContainer->getDevice()->getMemoryManager()->freeGraphicsMemory(deallocation);
}
cmdContainer->getDeallocationContainer().clear();
}
TEST_F(CommandContainerTest, givenNotEnoughSpaceWhenCreatedAlocationHaveDifferentBaseThenHeapIsDirty) {
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
cmdContainer->initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
cmdContainer->setDirtyStateForAllHeaps(false);
HeapType type = HeapType::indirectObject;
auto heapAllocation = cmdContainer->getIndirectHeapAllocation(type);
auto heap = cmdContainer->getIndirectHeap(type);
const size_t sizeRequested = 32;
const size_t alignment = 32;
size_t availableSize = heap->getAvailableSpace();
heap->getSpace(availableSize - sizeRequested / 2);
EXPECT_LT(heap->getAvailableSpace(), sizeRequested + alignment);
auto heapRequested = cmdContainer->getHeapWithRequiredSizeAndAlignment(type, sizeRequested, alignment);
auto newAllocation = heapRequested->getGraphicsAllocation();
EXPECT_EQ(heap, heapRequested);
EXPECT_NE(heapAllocation, newAllocation);
EXPECT_TRUE((reinterpret_cast<size_t>(heapRequested->getSpace(0)) & (alignment - 1)) == 0);
EXPECT_FALSE(cmdContainer->isHeapDirty(type));
for (auto deallocation : cmdContainer->getDeallocationContainer()) {
cmdContainer->getDevice()->getMemoryManager()->freeGraphicsMemory(deallocation);
}
cmdContainer->getDeallocationContainer().clear();
}
TEST_F(CommandContainerTest, whenAllocateNextCmdBufferIsCalledThenNewAllocationIsCreatedAndCommandStreamReplaced) {
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
cmdContainer->initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
auto stream = cmdContainer->getCommandStream();
ASSERT_NE(nullptr, stream);
auto initialBuffer = stream->getSpace(0);
EXPECT_NE(nullptr, initialBuffer);
cmdContainer->allocateNextCommandBuffer();
auto nextBuffer = stream->getSpace(0);
auto sizeUsed = stream->getUsed();
auto availableSize = stream->getMaxAvailableSpace();
EXPECT_NE(nullptr, nextBuffer);
EXPECT_EQ(0u, sizeUsed);
EXPECT_NE(initialBuffer, nextBuffer);
size_t alignedSize = alignUp<size_t>(CommandContainer::totalCmdBufferSize, MemoryConstants::pageSize64k);
const size_t cmdBufSize = alignedSize - CommandContainer::cmdBufferReservedSize;
EXPECT_EQ(cmdBufSize, availableSize);
ASSERT_EQ(2u, cmdContainer->getCmdBufferAllocations().size());
EXPECT_EQ(cmdContainer->getCmdBufferAllocations()[1], cmdContainer->getCommandStream()->getGraphicsAllocation());
EXPECT_EQ(cmdContainer->getCmdBufferAllocations()[1], cmdContainer->getResidencyContainer().back());
}
TEST_F(CommandContainerTest, whenResettingCommandContainerThenStoredCmdBuffersAreFreedAndStreamIsReplacedWithInitialBuffer) {
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
cmdContainer->initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
cmdContainer->allocateNextCommandBuffer();
cmdContainer->allocateNextCommandBuffer();
EXPECT_EQ(3u, cmdContainer->getCmdBufferAllocations().size());
cmdContainer->reset();
ASSERT_EQ(1u, cmdContainer->getCmdBufferAllocations().size());
auto stream = cmdContainer->getCommandStream();
ASSERT_NE(nullptr, stream);
auto buffer = stream->getSpace(0);
const size_t cmdBufSize = alignUp<size_t>(CommandContainer::totalCmdBufferSize, MemoryConstants::pageSize64k) - CommandContainer::cmdBufferReservedSize;
EXPECT_EQ(cmdContainer->getCmdBufferAllocations()[0]->getUnderlyingBuffer(), buffer);
EXPECT_EQ(cmdBufSize, stream->getMaxAvailableSpace());
}
class CommandContainerHeaps : public DeviceFixture,
public ::testing::TestWithParam<IndirectHeap::Type> {
public:
void SetUp() override {
DeviceFixture::setUp();
}
void TearDown() override {
DeviceFixture::tearDown();
}
};
INSTANTIATE_TEST_CASE_P(
Device,
CommandContainerHeaps,
testing::Values(
IndirectHeap::Type::dynamicState,
IndirectHeap::Type::indirectObject,
IndirectHeap::Type::surfaceState));
TEST_P(CommandContainerHeaps, givenCommandContainerWhenGetAllowHeapGrowCalledThenHeapIsReturned) {
HeapType heapType = GetParam();
CommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
if (!pDevice->getHardwareInfo().capabilityTable.supportsImages && HeapType::dynamicState == heapType) {
EXPECT_EQ(cmdContainer.getIndirectHeap(heapType), nullptr);
} else {
auto usedSpaceBefore = cmdContainer.getIndirectHeap(heapType)->getUsed();
size_t size = 5000;
void *ptr = cmdContainer.getHeapSpaceAllowGrow(heapType, size);
ASSERT_NE(nullptr, ptr);
auto usedSpaceAfter = cmdContainer.getIndirectHeap(heapType)->getUsed();
ASSERT_EQ(usedSpaceBefore + size, usedSpaceAfter);
}
}
TEST_P(CommandContainerHeaps, givenCommandContainerWhenGetingMoreThanAvailableSizeThenBiggerHeapIsReturned) {
HeapType heapType = GetParam();
CommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
cmdContainer.setDirtyStateForAllHeaps(false);
auto heap = cmdContainer.getIndirectHeap(heapType);
if (!pDevice->getHardwareInfo().capabilityTable.supportsImages && HeapType::dynamicState == heapType) {
EXPECT_EQ(heap, nullptr);
} else {
auto usedSpaceBefore = heap->getUsed();
auto availableSizeBefore = heap->getAvailableSpace();
void *ptr = cmdContainer.getHeapSpaceAllowGrow(heapType, availableSizeBefore + 1);
ASSERT_NE(nullptr, ptr);
auto usedSpaceAfter = heap->getUsed();
auto availableSizeAfter = heap->getAvailableSpace();
EXPECT_GT(usedSpaceAfter + availableSizeAfter, usedSpaceBefore + availableSizeBefore);
EXPECT_EQ(!cmdContainer.isHeapDirty(heapType), heapType == IndirectHeap::Type::indirectObject);
}
}
TEST_P(CommandContainerHeaps, givenCommandContainerForDifferentRootDevicesThenHeapsAreCreatedWithCorrectRootDeviceIndex) {
HeapType heapType = GetParam();
auto executionEnvironment = new NEO::ExecutionEnvironment();
const size_t numDevices = 2;
executionEnvironment->prepareRootDeviceEnvironments(numDevices);
for (auto i = 0u; i < numDevices; i++) {
executionEnvironment->rootDeviceEnvironments[i]->setHwInfoAndInitHelpers(defaultHwInfo.get());
executionEnvironment->rootDeviceEnvironments[i]->initGmm();
}
executionEnvironment->calculateMaxOsContextCount();
auto device0 = std::unique_ptr<MockDevice>(Device::create<MockDevice>(executionEnvironment, 0u));
auto device1 = std::unique_ptr<MockDevice>(Device::create<MockDevice>(executionEnvironment, 1u));
CommandContainer cmdContainer0;
cmdContainer0.initialize(device0.get(), nullptr, HeapSize::defaultHeapSize, true, false);
CommandContainer cmdContainer1;
cmdContainer1.initialize(device1.get(), nullptr, HeapSize::defaultHeapSize, true, false);
if (!pDevice->getHardwareInfo().capabilityTable.supportsImages && HeapType::dynamicState == heapType) {
EXPECT_EQ(cmdContainer0.getIndirectHeap(heapType), nullptr);
EXPECT_EQ(cmdContainer1.getIndirectHeap(heapType), nullptr);
} else {
uint32_t heapRootDeviceIndex0 = cmdContainer0.getIndirectHeap(heapType)->getGraphicsAllocation()->getRootDeviceIndex();
EXPECT_EQ(device0->getRootDeviceIndex(), heapRootDeviceIndex0);
uint32_t heapRootDeviceIndex1 = cmdContainer1.getIndirectHeap(heapType)->getGraphicsAllocation()->getRootDeviceIndex();
EXPECT_EQ(device1->getRootDeviceIndex(), heapRootDeviceIndex1);
}
}
TEST_F(CommandContainerHeaps, givenCommandContainerForDifferentRootDevicesThenCmdBufferAllocationIsCreatedWithCorrectRootDeviceIndex) {
auto executionEnvironment = new NEO::ExecutionEnvironment();
const size_t numDevices = 2;
executionEnvironment->prepareRootDeviceEnvironments(numDevices);
for (auto i = 0u; i < numDevices; i++) {
executionEnvironment->rootDeviceEnvironments[i]->setHwInfoAndInitHelpers(defaultHwInfo.get());
executionEnvironment->rootDeviceEnvironments[i]->initGmm();
}
executionEnvironment->calculateMaxOsContextCount();
auto device0 = std::unique_ptr<MockDevice>(Device::create<MockDevice>(executionEnvironment, 0u));
auto device1 = std::unique_ptr<MockDevice>(Device::create<MockDevice>(executionEnvironment, 1u));
CommandContainer cmdContainer0;
cmdContainer0.initialize(device0.get(), nullptr, HeapSize::defaultHeapSize, true, false);
EXPECT_EQ(1u, cmdContainer0.getCmdBufferAllocations().size());
uint32_t cmdBufferAllocationIndex0 = cmdContainer0.getCmdBufferAllocations().front()->getRootDeviceIndex();
EXPECT_EQ(device0->getRootDeviceIndex(), cmdBufferAllocationIndex0);
CommandContainer cmdContainer1;
cmdContainer1.initialize(device1.get(), nullptr, HeapSize::defaultHeapSize, true, false);
EXPECT_EQ(1u, cmdContainer1.getCmdBufferAllocations().size());
uint32_t cmdBufferAllocationIndex1 = cmdContainer1.getCmdBufferAllocations().front()->getRootDeviceIndex();
EXPECT_EQ(device1->getRootDeviceIndex(), cmdBufferAllocationIndex1);
}
TEST_F(CommandContainerHeaps, givenCommandContainerForDifferentRootDevicesThenInternalHeapIsCreatedWithCorrectRootDeviceIndex) {
auto executionEnvironment = new NEO::ExecutionEnvironment();
const size_t numDevices = 2;
executionEnvironment->prepareRootDeviceEnvironments(numDevices);
for (auto i = 0u; i < numDevices; i++) {
executionEnvironment->rootDeviceEnvironments[i]->setHwInfoAndInitHelpers(defaultHwInfo.get());
executionEnvironment->rootDeviceEnvironments[i]->initGmm();
}
executionEnvironment->calculateMaxOsContextCount();
auto device0 = std::unique_ptr<MockDevice>(Device::create<MockDevice>(executionEnvironment, 0u));
auto device1 = std::unique_ptr<MockDevice>(Device::create<MockDevice>(executionEnvironment, 1u));
auto &gfxCoreHelper0 = device0->getGfxCoreHelper();
auto &gfxCoreHelper1 = device1->getGfxCoreHelper();
CommandContainer cmdContainer0;
cmdContainer0.initialize(device0.get(), nullptr, HeapSize::defaultHeapSize, true, false);
bool useLocalMemory0 = !gfxCoreHelper0.useSystemMemoryPlacementForISA(device0->getHardwareInfo());
uint64_t baseAddressHeapDevice0 = device0->getMemoryManager()->getInternalHeapBaseAddress(device0->getRootDeviceIndex(), useLocalMemory0);
EXPECT_EQ(cmdContainer0.getInstructionHeapBaseAddress(), baseAddressHeapDevice0);
CommandContainer cmdContainer1;
cmdContainer1.initialize(device1.get(), nullptr, HeapSize::defaultHeapSize, true, false);
bool useLocalMemory1 = !gfxCoreHelper1.useSystemMemoryPlacementForISA(device0->getHardwareInfo());
uint64_t baseAddressHeapDevice1 = device1->getMemoryManager()->getInternalHeapBaseAddress(device1->getRootDeviceIndex(), useLocalMemory1);
EXPECT_EQ(cmdContainer1.getInstructionHeapBaseAddress(), baseAddressHeapDevice1);
}
TEST_F(CommandContainerTest, givenCommandContainerWhenDestructionThenNonHeapAllocationAreNotDestroyed) {
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer());
MockGraphicsAllocation alloc;
size_t size = 0x1000;
alloc.setSize(size);
cmdContainer->initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
cmdContainer->getDeallocationContainer().push_back(&alloc);
cmdContainer.reset();
EXPECT_EQ(alloc.getUnderlyingBufferSize(), size);
}
TEST_F(CommandContainerTest, givenContainerAllocatesNextCommandBufferWhenResetingContainerThenExpectFirstCommandBufferAllocationIsReused) {
auto cmdContainer = std::make_unique<CommandContainer>();
cmdContainer->initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
auto stream = cmdContainer->getCommandStream();
ASSERT_NE(nullptr, stream);
auto firstCmdBufferAllocation = stream->getGraphicsAllocation();
ASSERT_NE(nullptr, firstCmdBufferAllocation);
auto firstCmdBufferCpuPointer = stream->getSpace(0);
EXPECT_EQ(firstCmdBufferCpuPointer, firstCmdBufferAllocation->getUnderlyingBuffer());
cmdContainer->allocateNextCommandBuffer();
auto secondCmdBufferAllocation = stream->getGraphicsAllocation();
ASSERT_NE(nullptr, secondCmdBufferAllocation);
EXPECT_NE(firstCmdBufferAllocation, secondCmdBufferAllocation);
auto secondCmdBufferCpuPointer = stream->getSpace(0);
EXPECT_EQ(secondCmdBufferCpuPointer, secondCmdBufferAllocation->getUnderlyingBuffer());
EXPECT_NE(firstCmdBufferCpuPointer, secondCmdBufferCpuPointer);
cmdContainer->reset();
auto aferResetCmdBufferAllocation = stream->getGraphicsAllocation();
ASSERT_NE(nullptr, aferResetCmdBufferAllocation);
auto afterResetCmdBufferCpuPointer = stream->getSpace(0);
EXPECT_EQ(afterResetCmdBufferCpuPointer, aferResetCmdBufferAllocation->getUnderlyingBuffer());
EXPECT_EQ(firstCmdBufferAllocation, aferResetCmdBufferAllocation);
EXPECT_EQ(firstCmdBufferCpuPointer, afterResetCmdBufferCpuPointer);
bool firstAllocationFound = false;
auto &residencyContainer = cmdContainer->getResidencyContainer();
for (auto *allocation : residencyContainer) {
if (allocation == firstCmdBufferAllocation) {
firstAllocationFound = true;
break;
}
}
EXPECT_TRUE(firstAllocationFound);
}
class MyLinearStreamMock : public LinearStream {
public:
using LinearStream::cmdContainer;
};
TEST_F(CommandContainerTest, givenCmdContainerWhenContainerIsInitializedThenStreamContainsContainerPtr) {
CommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
EXPECT_EQ(reinterpret_cast<MyLinearStreamMock *>(cmdContainer.getCommandStream())->cmdContainer, &cmdContainer);
}
TEST_F(CommandContainerTest, givenCmdContainerWhenContainerIsInitializedThenStreamSizeEqualAlignedTotalCmdBuffSizeDecreasedOfReservedSize) {
CommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
size_t alignedSize = alignUp<size_t>(CommandContainer::totalCmdBufferSize, MemoryConstants::pageSize64k);
EXPECT_EQ(cmdContainer.getCommandStream()->getMaxAvailableSpace(), alignedSize - CommandContainer::cmdBufferReservedSize);
}
TEST_F(CommandContainerTest, GivenCmdContainerAndDebugFlagWhenContainerIsInitializedThenStreamSizeEqualsAlignedTotalCmdBuffSizeDecreasedOfReservedSize) {
DebugManagerStateRestore restorer;
debugManager.flags.OverrideCmdListCmdBufferSizeInKb.set(0);
MyMockCommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
size_t alignedSize = alignUp<size_t>(cmdContainer.getAlignedCmdBufferSize(), MemoryConstants::pageSize64k);
EXPECT_EQ(cmdContainer.getCommandStream()->getMaxAvailableSpace(), alignedSize - MyMockCommandContainer::cmdBufferReservedSize);
auto newSizeInKB = 512;
debugManager.flags.OverrideCmdListCmdBufferSizeInKb.set(newSizeInKB);
MyMockCommandContainer cmdContainer2;
cmdContainer2.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
alignedSize = alignUp<size_t>(cmdContainer.getAlignedCmdBufferSize(), MemoryConstants::pageSize64k);
EXPECT_EQ(cmdContainer2.getCommandStream()->getMaxAvailableSpace(), alignedSize - MyMockCommandContainer::cmdBufferReservedSize);
}
TEST_F(CommandContainerTest, givenCmdContainerWhenAlocatingNextCmdBufferThenStreamSizeEqualAlignedTotalCmdBuffSizeDecreasedOfReservedSize) {
CommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
cmdContainer.allocateNextCommandBuffer();
size_t alignedSize = alignUp<size_t>(CommandContainer::totalCmdBufferSize, MemoryConstants::pageSize64k);
EXPECT_EQ(cmdContainer.getCommandStream()->getMaxAvailableSpace(), alignedSize - CommandContainer::cmdBufferReservedSize);
}
TEST_F(CommandContainerTest, givenCmdContainerWhenCloseAndAllocateNextCommandBufferCalledThenBBEndPlacedAtEndOfLinearStream) {
CommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
auto &gfxCoreHelper = pDevice->getGfxCoreHelper();
auto ptr = cmdContainer.getCommandStream()->getSpace(0u);
cmdContainer.closeAndAllocateNextCommandBuffer();
EXPECT_EQ(memcmp(ptr, gfxCoreHelper.getBatchBufferEndReference(), gfxCoreHelper.getBatchBufferEndSize()), 0);
}
TEST_F(CommandContainerTest, givenCmdContainerWhenCloseAndAllocateNextCommandBufferCalledThenNewCmdBufferAllocationCreated) {
CommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
EXPECT_EQ(cmdContainer.getCmdBufferAllocations().size(), 1u);
cmdContainer.closeAndAllocateNextCommandBuffer();
EXPECT_EQ(cmdContainer.getCmdBufferAllocations().size(), 2u);
}
TEST_F(CommandContainerTest, givenCmdContainerWhenSetCmdBufferThenCmdBufferSetCorrectly) {
CommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
AllocationProperties properties{pDevice->getRootDeviceIndex(),
true /* allocateMemory*/,
2048,
AllocationType::commandBuffer,
(pDevice->getNumGenericSubDevices() > 1u) /* multiOsContextCapable */,
false,
pDevice->getDeviceBitfield()};
auto alloc = pDevice->getMemoryManager()->allocateGraphicsMemoryWithProperties(properties);
cmdContainer.setCmdBuffer(alloc);
EXPECT_EQ(cmdContainer.getCommandStream()->getGraphicsAllocation(), alloc);
pDevice->getMemoryManager()->freeGraphicsMemory(alloc);
}
TEST_F(CommandContainerTest, givenCmdContainerWhenReuseExistingCmdBufferWithoutAnyAllocationInListThenReturnNullptr) {
auto cmdContainer = std::make_unique<MyMockCommandContainer>();
AllocationsList allocList;
cmdContainer->initialize(pDevice, &allocList, HeapSize::defaultHeapSize, false, false);
auto csr = pDevice->getDefaultEngine().commandStreamReceiver;
cmdContainer->setImmediateCmdListCsr(csr);
cmdContainer->immediateReusableAllocationList = std::make_unique<NEO::AllocationsList>();
EXPECT_EQ(cmdContainer->reuseExistingCmdBuffer(), nullptr);
cmdContainer.reset();
allocList.freeAllGraphicsAllocations(pDevice);
}
HWTEST_F(CommandContainerTest, givenCmdContainerWhenReuseExistingCmdBufferWithAllocationInListAndCsrTaskCountLowerThanAllocationThenReturnNullptr) {
auto cmdContainer = std::make_unique<MyMockCommandContainer>();
auto &csr = pDevice->getUltCommandStreamReceiver<FamilyType>();
*csr.tagAddress = 0u;
AllocationsList allocList;
cmdContainer->initialize(pDevice, &allocList, HeapSize::defaultHeapSize, false, false);
cmdContainer->setImmediateCmdListCsr(&csr);
cmdContainer->immediateReusableAllocationList = std::make_unique<NEO::AllocationsList>();
cmdContainer->getCmdBufferAllocations()[0]->updateTaskCount(10, 0);
auto currectContainerSize = cmdContainer->getCmdBufferAllocations().size();
cmdContainer->addCurrentCommandBufferToReusableAllocationList();
EXPECT_EQ(cmdContainer->getCmdBufferAllocations().size(), currectContainerSize - 1);
EXPECT_EQ(cmdContainer->reuseExistingCmdBuffer(), nullptr);
cmdContainer.reset();
allocList.freeAllGraphicsAllocations(pDevice);
}
HWTEST_F(CommandContainerTest, givenCmdContainerWhenReuseExistingCmdBufferWithAllocationInListAndCsrTaskCountSameAsAllocationThenReturnAlloc) {
auto cmdContainer = std::make_unique<MyMockCommandContainer>();
auto &csr = pDevice->getUltCommandStreamReceiver<FamilyType>();
*csr.tagAddress = 10u;
AllocationsList allocList;
cmdContainer->initialize(pDevice, &allocList, HeapSize::defaultHeapSize, false, false);
cmdContainer->setImmediateCmdListCsr(&csr);
cmdContainer->immediateReusableAllocationList = std::make_unique<NEO::AllocationsList>();
cmdContainer->getCmdBufferAllocations()[0]->updateTaskCount(10, 0);
cmdContainer->addCurrentCommandBufferToReusableAllocationList();
auto currectContainerSize = cmdContainer->getCmdBufferAllocations().size();
EXPECT_NE(cmdContainer->reuseExistingCmdBuffer(), nullptr);
EXPECT_EQ(cmdContainer->getCmdBufferAllocations().size(), currectContainerSize + 1);
cmdContainer.reset();
allocList.freeAllGraphicsAllocations(pDevice);
}
TEST_F(CommandContainerTest, GivenCmdContainerWhenContainerIsInitializedThenSurfaceStateIndirectHeapSizeIsCorrect) {
MyMockCommandContainer cmdContainer;
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
auto size = cmdContainer.allocationIndirectHeaps[IndirectHeap::Type::surfaceState]->getUnderlyingBufferSize();
constexpr size_t expectedHeapSize = MemoryConstants::pageSize64k;
EXPECT_EQ(expectedHeapSize, size);
}
HWTEST_F(CommandContainerTest, givenCmdContainerHasImmediateCsrWhenGettingHeapWithoutEnsuringSpaceThenExpectNullptrReturnedOrUnrecoverable) {
MyMockCommandContainer cmdContainer;
auto &containerSshReserve = cmdContainer.getSurfaceStateHeapReserve();
EXPECT_NE(nullptr, containerSshReserve.indirectHeapReservation);
auto &containerDshReserve = cmdContainer.getDynamicStateHeapReserve();
EXPECT_NE(nullptr, containerDshReserve.indirectHeapReservation);
NEO::ReservedIndirectHeap reservedSsh(nullptr, false);
NEO::ReservedIndirectHeap reservedDsh(nullptr, false);
auto sshHeapPtr = &reservedSsh;
auto dshHeapPtr = &reservedDsh;
HeapReserveArguments sshReserveArgs = {sshHeapPtr, 0, 0};
HeapReserveArguments dshReserveArgs = {dshHeapPtr, 0, 0};
const size_t dshAlign = NEO::EncodeDispatchKernel<FamilyType>::getDefaultDshAlignment();
const size_t sshAlign = NEO::EncodeDispatchKernel<FamilyType>::getDefaultSshAlignment();
sshReserveArgs.alignment = sshAlign;
dshReserveArgs.alignment = dshAlign;
cmdContainer.enableHeapSharing();
EXPECT_TRUE(cmdContainer.immediateCmdListSharedHeap(HeapType::surfaceState));
EXPECT_TRUE(cmdContainer.immediateCmdListSharedHeap(HeapType::dynamicState));
EXPECT_FALSE(cmdContainer.immediateCmdListSharedHeap(HeapType::indirectObject));
cmdContainer.setImmediateCmdListCsr(pDevice->getDefaultEngine().commandStreamReceiver);
cmdContainer.immediateReusableAllocationList = std::make_unique<NEO::AllocationsList>();
cmdContainer.setNumIddPerBlock(1);
auto code = cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
EXPECT_EQ(CommandContainer::ErrorCode::success, code);
EXPECT_EQ(nullptr, cmdContainer.getIndirectHeap(HeapType::dynamicState));
EXPECT_EQ(nullptr, cmdContainer.getIndirectHeap(HeapType::surfaceState));
EXPECT_THROW(cmdContainer.getHeapSpaceAllowGrow(HeapType::dynamicState, 0), std::exception);
EXPECT_THROW(cmdContainer.getHeapWithRequiredSizeAndAlignment(HeapType::dynamicState, 0, 0), std::exception);
EXPECT_THROW(cmdContainer.getHeapSpaceAllowGrow(HeapType::surfaceState, 0), std::exception);
EXPECT_THROW(cmdContainer.getHeapWithRequiredSizeAndAlignment(HeapType::surfaceState, 0, 0), std::exception);
auto &ultCsr = pDevice->getUltCommandStreamReceiver<FamilyType>();
ultCsr.recursiveLockCounter = 0;
sshReserveArgs.size = 0;
dshReserveArgs.size = 0;
cmdContainer.reserveSpaceForDispatch(sshReserveArgs, dshReserveArgs, false);
EXPECT_EQ(1u, ultCsr.recursiveLockCounter);
EXPECT_EQ(nullptr, cmdContainer.getIndirectHeap(HeapType::dynamicState));
EXPECT_EQ(nullptr, reservedDsh.getCpuBase());
EXPECT_NE(nullptr, cmdContainer.getIndirectHeap(HeapType::surfaceState));
EXPECT_NE(nullptr, reservedSsh.getCpuBase());
EXPECT_EQ(cmdContainer.getIndirectHeap(HeapType::surfaceState)->getCpuBase(), reservedSsh.getCpuBase());
EXPECT_THROW(cmdContainer.getHeapSpaceAllowGrow(HeapType::dynamicState, 0), std::exception);
EXPECT_THROW(cmdContainer.getHeapWithRequiredSizeAndAlignment(HeapType::dynamicState, 0, 0), std::exception);
EXPECT_NO_THROW(cmdContainer.getHeapSpaceAllowGrow(HeapType::surfaceState, 0));
EXPECT_NO_THROW(cmdContainer.getHeapWithRequiredSizeAndAlignment(HeapType::surfaceState, 0, 0));
cmdContainer.reserveSpaceForDispatch(sshReserveArgs, dshReserveArgs, true);
EXPECT_EQ(2u, ultCsr.recursiveLockCounter);
ASSERT_NE(nullptr, cmdContainer.getIndirectHeap(HeapType::dynamicState));
ASSERT_NE(nullptr, cmdContainer.getIndirectHeap(HeapType::surfaceState));
auto sshHeap = cmdContainer.getIndirectHeap(HeapType::surfaceState);
EXPECT_NE(nullptr, sshHeap);
size_t sizeUsedDsh = 0;
size_t sizeUsedSsh = sshHeap->getUsed();
size_t initSshSize = sizeUsedSsh;
constexpr size_t misAlignedSize = 3;
sshReserveArgs.size = misAlignedSize;
dshReserveArgs.size = misAlignedSize;
cmdContainer.reserveSpaceForDispatch(sshReserveArgs, dshReserveArgs, true);
EXPECT_EQ(3u, ultCsr.recursiveLockCounter);
auto dshHeap = cmdContainer.getIndirectHeap(HeapType::dynamicState);
EXPECT_NE(nullptr, dshHeap);
EXPECT_EQ(sshHeapPtr->getCpuBase(), sshReserveArgs.indirectHeapReservation->getCpuBase());
EXPECT_EQ(dshHeapPtr->getCpuBase(), dshReserveArgs.indirectHeapReservation->getCpuBase());
EXPECT_EQ(sshHeap->getCpuBase(), sshReserveArgs.indirectHeapReservation->getCpuBase());
EXPECT_EQ(dshHeap->getCpuBase(), dshReserveArgs.indirectHeapReservation->getCpuBase());
EXPECT_EQ(sshHeap->getHeapSizeInPages(), sshReserveArgs.indirectHeapReservation->getHeapSizeInPages());
EXPECT_EQ(dshHeap->getHeapSizeInPages(), dshReserveArgs.indirectHeapReservation->getHeapSizeInPages());
EXPECT_EQ(sshHeap->getGraphicsAllocation(), sshReserveArgs.indirectHeapReservation->getGraphicsAllocation());
EXPECT_EQ(dshHeap->getGraphicsAllocation(), dshReserveArgs.indirectHeapReservation->getGraphicsAllocation());
sshHeapPtr->getSpace(misAlignedSize);
dshHeapPtr->getSpace(misAlignedSize);
EXPECT_EQ(0u, sshHeapPtr->getAvailableSpace());
EXPECT_EQ(0u, dshHeapPtr->getAvailableSpace());
sshReserveArgs.size = sshAlign;
dshReserveArgs.size = dshAlign;
cmdContainer.reserveSpaceForDispatch(sshReserveArgs, dshReserveArgs, true);
EXPECT_EQ(4u, ultCsr.recursiveLockCounter);
EXPECT_EQ(sshHeapPtr->getCpuBase(), sshReserveArgs.indirectHeapReservation->getCpuBase());
EXPECT_EQ(dshHeapPtr->getCpuBase(), dshReserveArgs.indirectHeapReservation->getCpuBase());
sshHeapPtr->align(sshAlign);
sshHeapPtr->getSpace(sshAlign);
dshHeapPtr->align(dshAlign);
dshHeapPtr->getSpace(dshAlign);
EXPECT_EQ(0u, sshHeapPtr->getAvailableSpace());
EXPECT_EQ(0u, dshHeapPtr->getAvailableSpace());
EXPECT_EQ(sshHeap->getCpuBase(), sshReserveArgs.indirectHeapReservation->getCpuBase());
EXPECT_EQ(dshHeap->getCpuBase(), dshReserveArgs.indirectHeapReservation->getCpuBase());
EXPECT_EQ(sshHeap->getHeapSizeInPages(), sshReserveArgs.indirectHeapReservation->getHeapSizeInPages());
EXPECT_EQ(dshHeap->getHeapSizeInPages(), dshReserveArgs.indirectHeapReservation->getHeapSizeInPages());
EXPECT_EQ(sshHeap->getGraphicsAllocation(), sshReserveArgs.indirectHeapReservation->getGraphicsAllocation());
EXPECT_EQ(dshHeap->getGraphicsAllocation(), dshReserveArgs.indirectHeapReservation->getGraphicsAllocation());
sizeUsedDsh = dshHeap->getUsed();
sizeUsedSsh = sshHeap->getUsed();
EXPECT_EQ(2 * sshAlign + initSshSize, sizeUsedSsh);
EXPECT_EQ(2 * dshAlign, sizeUsedDsh);
constexpr size_t nonZeroSshSize = 4 * MemoryConstants::kiloByte;
constexpr size_t nonZeroDshSize = 4 * MemoryConstants::kiloByte;
sshReserveArgs.size = nonZeroSshSize;
dshReserveArgs.size = nonZeroDshSize;
cmdContainer.reserveSpaceForDispatch(sshReserveArgs, dshReserveArgs, true);
EXPECT_EQ(5u, ultCsr.recursiveLockCounter);
dshHeap = cmdContainer.getIndirectHeap(HeapType::dynamicState);
EXPECT_NE(nullptr, dshHeap);
sshHeap = cmdContainer.getIndirectHeap(HeapType::surfaceState);
EXPECT_NE(nullptr, sshHeap);
EXPECT_EQ(sshHeap->getCpuBase(), sshReserveArgs.indirectHeapReservation->getCpuBase());
EXPECT_EQ(dshHeap->getCpuBase(), dshReserveArgs.indirectHeapReservation->getCpuBase());
EXPECT_EQ(sshHeap->getHeapSizeInPages(), sshReserveArgs.indirectHeapReservation->getHeapSizeInPages());
EXPECT_EQ(dshHeap->getHeapSizeInPages(), dshReserveArgs.indirectHeapReservation->getHeapSizeInPages());
EXPECT_EQ(sshHeap->getGraphicsAllocation(), sshReserveArgs.indirectHeapReservation->getGraphicsAllocation());
EXPECT_EQ(dshHeap->getGraphicsAllocation(), dshReserveArgs.indirectHeapReservation->getGraphicsAllocation());
sizeUsedDsh = dshHeap->getUsed();
sizeUsedSsh = sshHeap->getUsed();
size_t sizeReserveUsedDsh = reservedDsh.getUsed();
size_t sizeReserveUsedSsh = reservedSsh.getUsed();
EXPECT_EQ(sizeUsedDsh, sizeReserveUsedDsh + nonZeroDshSize);
EXPECT_EQ(sizeUsedSsh, sizeReserveUsedSsh + nonZeroSshSize);
EXPECT_EQ(nonZeroDshSize, reservedDsh.getAvailableSpace());
EXPECT_EQ(nonZeroSshSize, reservedSsh.getAvailableSpace());
EXPECT_EQ(sizeUsedDsh, reservedDsh.getMaxAvailableSpace());
EXPECT_EQ(sizeUsedSsh, reservedSsh.getMaxAvailableSpace());
void *dshReservePtr = reservedDsh.getSpace(64);
void *sshReservePtr = reservedSsh.getSpace(64);
EXPECT_EQ(ptrOffset(reservedDsh.getCpuBase(), sizeReserveUsedDsh), dshReservePtr);
EXPECT_EQ(ptrOffset(reservedSsh.getCpuBase(), sizeReserveUsedSsh), sshReservePtr);
auto alignedHeapDsh = cmdContainer.getHeapWithRequiredSizeAndAlignment(HeapType::dynamicState, 128, 128);
auto alignedHeapSsh = cmdContainer.getHeapWithRequiredSizeAndAlignment(HeapType::surfaceState, 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::dynamicState, 64), std::exception);
EXPECT_THROW(cmdContainer.getHeapWithRequiredSizeAndAlignment(HeapType::dynamicState, 64, 64), std::exception);
EXPECT_THROW(cmdContainer.getHeapSpaceAllowGrow(HeapType::surfaceState, 64), std::exception);
EXPECT_THROW(cmdContainer.getHeapWithRequiredSizeAndAlignment(HeapType::surfaceState, 64, 64), std::exception);
}
HWTEST_F(CommandContainerTest, givenCmdContainerUsedInRegularCmdListWhenGettingHeapWithEnsuringSpaceThenExpectCorrectHeap) {
if (!pDevice->getDeviceInfo().imageSupport) {
GTEST_SKIP();
}
const size_t dshAlign = NEO::EncodeDispatchKernel<FamilyType>::getDefaultDshAlignment();
const size_t sshAlign = NEO::EncodeDispatchKernel<FamilyType>::getDefaultSshAlignment();
MyMockCommandContainer cmdContainer;
constexpr size_t zeroSize = 0;
NEO::ReservedIndirectHeap reservedSsh(nullptr, zeroSize);
NEO::ReservedIndirectHeap reservedDsh(nullptr, zeroSize);
auto sshHeapPtr = &reservedSsh;
auto dshHeapPtr = &reservedDsh;
HeapReserveArguments sshReserveArgs = {sshHeapPtr, 0, sshAlign};
HeapReserveArguments dshReserveArgs = {dshHeapPtr, 0, dshAlign};
auto code = cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
EXPECT_EQ(CommandContainer::ErrorCode::success, code);
cmdContainer.reserveSpaceForDispatch(sshReserveArgs, dshReserveArgs, true);
EXPECT_EQ(nullptr, sshReserveArgs.indirectHeapReservation);
EXPECT_EQ(nullptr, dshReserveArgs.indirectHeapReservation);
auto dsh = cmdContainer.getIndirectHeap(HeapType::dynamicState);
auto ssh = cmdContainer.getIndirectHeap(HeapType::surfaceState);
EXPECT_EQ(0u, reservedDsh.getAvailableSpace());
EXPECT_EQ(0u, reservedSsh.getAvailableSpace());
EXPECT_NE(nullptr, dsh);
EXPECT_NE(nullptr, ssh);
dsh->getSpace(dsh->getAvailableSpace() - 64);
constexpr size_t nonZeroSize = 4 * MemoryConstants::kiloByte;
sshReserveArgs.size = nonZeroSize;
dshReserveArgs.size = nonZeroSize;
sshReserveArgs.indirectHeapReservation = sshHeapPtr;
dshReserveArgs.indirectHeapReservation = dshHeapPtr;
cmdContainer.reserveSpaceForDispatch(sshReserveArgs, dshReserveArgs, true);
dsh = cmdContainer.getIndirectHeap(HeapType::dynamicState);
EXPECT_EQ(dsh->getMaxAvailableSpace(), dsh->getAvailableSpace());
EXPECT_EQ(nullptr, sshReserveArgs.indirectHeapReservation);
EXPECT_EQ(nullptr, dshReserveArgs.indirectHeapReservation);
}
HWTEST_F(CommandContainerTest, givenCmdContainerUsingPrivateHeapsWhenGettingReserveHeapThenExpectReserveNullified) {
const bool dshSupport = pDevice->getDeviceInfo().imageSupport;
MyMockCommandContainer cmdContainer;
NEO::ReservedIndirectHeap reservedSsh(nullptr);
NEO::ReservedIndirectHeap reservedDsh(nullptr);
auto sshHeapPtr = &reservedSsh;
auto dshHeapPtr = &reservedDsh;
const size_t dshAlign = NEO::EncodeDispatchKernel<FamilyType>::getDefaultDshAlignment();
const size_t sshAlign = NEO::EncodeDispatchKernel<FamilyType>::getDefaultSshAlignment();
HeapReserveArguments sshReserveArgs = {sshHeapPtr, 0, sshAlign};
HeapReserveArguments dshReserveArgs = {dshHeapPtr, 0, dshAlign};
auto code = cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
EXPECT_EQ(CommandContainer::ErrorCode::success, code);
constexpr size_t nonZeroSshSize = 4 * MemoryConstants::kiloByte;
constexpr size_t nonZeroDshSize = 4 * MemoryConstants::kiloByte + 64;
sshReserveArgs.size = nonZeroSshSize;
dshReserveArgs.size = nonZeroDshSize;
cmdContainer.reserveSpaceForDispatch(sshReserveArgs, dshReserveArgs, dshSupport);
if (dshSupport) {
auto dshHeap = cmdContainer.getIndirectHeap(HeapType::dynamicState);
ASSERT_NE(nullptr, dshHeap);
EXPECT_EQ(nullptr, dshReserveArgs.indirectHeapReservation);
}
auto sshHeap = cmdContainer.getIndirectHeap(HeapType::surfaceState);
ASSERT_NE(nullptr, sshHeap);
EXPECT_EQ(nullptr, sshReserveArgs.indirectHeapReservation);
}
HWTEST_F(CommandContainerTest,
givenCmdContainerUsesSharedHeapsWhenGettingSpaceAfterMisalignedHeapCurrentPointerAndAlignmentIsProvidedThenExpectToProvideAlignmentPaddingToReserveHeap) {
const bool dshSupport = pDevice->getDeviceInfo().imageSupport;
MyMockCommandContainer cmdContainer;
NEO::ReservedIndirectHeap reservedSsh(nullptr, false);
NEO::ReservedIndirectHeap reservedDsh(nullptr, false);
auto sshHeapPtr = &reservedSsh;
auto dshHeapPtr = &reservedDsh;
constexpr size_t dshExampleAlignment = 64;
constexpr size_t sshExampleAlignment = 64;
HeapReserveArguments sshReserveArgs = {sshHeapPtr, 0, sshExampleAlignment};
HeapReserveArguments dshReserveArgs = {dshHeapPtr, 0, dshExampleAlignment};
cmdContainer.enableHeapSharing();
cmdContainer.setImmediateCmdListCsr(pDevice->getDefaultEngine().commandStreamReceiver);
cmdContainer.immediateReusableAllocationList = std::make_unique<NEO::AllocationsList>();
cmdContainer.setNumIddPerBlock(1);
auto code = cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
EXPECT_EQ(CommandContainer::ErrorCode::success, code);
constexpr size_t misalignedSize = 11;
sshReserveArgs.size = misalignedSize;
dshReserveArgs.size = misalignedSize;
cmdContainer.reserveSpaceForDispatch(sshReserveArgs, dshReserveArgs, dshSupport);
size_t oldUsedDsh = 0;
if (dshSupport) {
auto dshHeap = cmdContainer.getIndirectHeap(HeapType::dynamicState);
ASSERT_NE(nullptr, dshHeap);
size_t sizeUsedDsh = dshHeap->getUsed();
size_t sizeReserveUsedDsh = reservedDsh.getUsed();
EXPECT_EQ(sizeUsedDsh, sizeReserveUsedDsh + misalignedSize);
EXPECT_EQ(misalignedSize, reservedDsh.getAvailableSpace());
EXPECT_EQ(sizeUsedDsh, reservedDsh.getMaxAvailableSpace());
void *dshReservePtr = reservedDsh.getSpace(8);
EXPECT_EQ(ptrOffset(reservedDsh.getCpuBase(), sizeReserveUsedDsh), dshReservePtr);
oldUsedDsh = sizeUsedDsh;
}
size_t oldUsedSsh = 0;
auto sshHeap = cmdContainer.getIndirectHeap(HeapType::surfaceState);
ASSERT_NE(nullptr, sshHeap);
size_t sizeUsedSsh = sshHeap->getUsed();
size_t sizeReserveUsedSsh = reservedSsh.getUsed();
EXPECT_EQ(sizeUsedSsh, sizeReserveUsedSsh + misalignedSize);
EXPECT_EQ(misalignedSize, reservedSsh.getAvailableSpace());
EXPECT_EQ(sizeUsedSsh, reservedSsh.getMaxAvailableSpace());
void *sshReservePtr = reservedSsh.getSpace(8);
EXPECT_EQ(ptrOffset(reservedSsh.getCpuBase(), sizeReserveUsedSsh), sshReservePtr);
oldUsedSsh = sizeUsedSsh;
constexpr size_t zeroSize = 0;
sshReserveArgs.size = zeroSize;
dshReserveArgs.size = zeroSize;
cmdContainer.reserveSpaceForDispatch(sshReserveArgs, dshReserveArgs, dshSupport);
if (dshSupport) {
auto dshHeap = cmdContainer.getIndirectHeap(HeapType::dynamicState);
ASSERT_NE(nullptr, dshHeap);
size_t sizeUsedDsh = dshHeap->getUsed();
size_t sizeReserveUsedDsh = reservedDsh.getUsed();
EXPECT_EQ(oldUsedDsh, sizeUsedDsh);
EXPECT_EQ(zeroSize, reservedDsh.getAvailableSpace());
EXPECT_EQ(sizeReserveUsedDsh, reservedDsh.getMaxAvailableSpace());
}
sshHeap = cmdContainer.getIndirectHeap(HeapType::surfaceState);
ASSERT_NE(nullptr, sshHeap);
sizeUsedSsh = sshHeap->getUsed();
sizeReserveUsedSsh = reservedSsh.getUsed();
EXPECT_EQ(oldUsedSsh, sizeUsedSsh);
EXPECT_EQ(zeroSize, reservedSsh.getAvailableSpace());
EXPECT_EQ(sizeReserveUsedSsh, reservedSsh.getMaxAvailableSpace());
sshReserveArgs.size = misalignedSize;
dshReserveArgs.size = misalignedSize;
cmdContainer.reserveSpaceForDispatch(sshReserveArgs, dshReserveArgs, dshSupport);
if (dshSupport) {
auto dshHeap = cmdContainer.getIndirectHeap(HeapType::dynamicState);
ASSERT_NE(nullptr, dshHeap);
size_t alignedDshSize = alignUp(misalignedSize, dshExampleAlignment);
size_t sizeUsedDsh = dshHeap->getUsed();
size_t sizeReserveUsedDsh = reservedDsh.getUsed();
EXPECT_EQ(sizeUsedDsh, sizeReserveUsedDsh + alignedDshSize);
EXPECT_EQ(alignedDshSize, reservedDsh.getAvailableSpace());
EXPECT_EQ(sizeUsedDsh, reservedDsh.getMaxAvailableSpace());
void *dshReservePtr = reservedDsh.getSpace(4);
EXPECT_EQ(ptrOffset(reservedDsh.getCpuBase(), sizeReserveUsedDsh), dshReservePtr);
}
sshHeap = cmdContainer.getIndirectHeap(HeapType::surfaceState);
ASSERT_NE(nullptr, sshHeap);
size_t alignedSshSize = alignUp(misalignedSize, sshExampleAlignment);
sizeUsedSsh = sshHeap->getUsed();
sizeReserveUsedSsh = reservedSsh.getUsed();
EXPECT_EQ(sizeUsedSsh, sizeReserveUsedSsh + alignedSshSize);
EXPECT_EQ(alignedSshSize, reservedSsh.getAvailableSpace());
EXPECT_EQ(sizeUsedSsh, reservedSsh.getMaxAvailableSpace());
sshReservePtr = reservedSsh.getSpace(4);
EXPECT_EQ(ptrOffset(reservedSsh.getCpuBase(), sizeReserveUsedSsh), sshReservePtr);
}
struct MockHeapHelper : public HeapHelper {
public:
using HeapHelper::storageForReuse;
};
TEST_F(CommandContainerTest, givenCmdContainerWhenFillReusableAllocationListsThenAllocListsNotEmptyAndMadeResident) {
DebugManagerStateRestore dbgRestore;
debugManager.flags.SetAmountOfReusableAllocations.set(1);
auto cmdContainer = std::make_unique<MyMockCommandContainer>();
auto csr = pDevice->getDefaultEngine().commandStreamReceiver;
AllocationsList allocList;
cmdContainer->initialize(pDevice, &allocList, HeapSize::defaultHeapSize, true, false);
cmdContainer->setImmediateCmdListCsr(csr);
auto heapHelper = reinterpret_cast<MockHeapHelper *>(cmdContainer->getHeapHelper());
EXPECT_EQ(cmdContainer->immediateReusableAllocationList, nullptr);
EXPECT_TRUE(heapHelper->storageForReuse->getAllocationsForReuse().peekIsEmpty());
auto actualResidencyContainerSize = cmdContainer->getResidencyContainer().size();
cmdContainer->fillReusableAllocationLists();
ASSERT_NE(cmdContainer->immediateReusableAllocationList, nullptr);
EXPECT_FALSE(cmdContainer->immediateReusableAllocationList->peekIsEmpty());
EXPECT_FALSE(heapHelper->storageForReuse->getAllocationsForReuse().peekIsEmpty());
EXPECT_EQ(heapHelper->storageForReuse->getAllocationsForReuse().peekHead()->getResidencyTaskCount(csr->getOsContext().getContextId()), 1u);
EXPECT_EQ(cmdContainer->getResidencyContainer().size(), actualResidencyContainerSize + 1);
cmdContainer.reset();
allocList.freeAllGraphicsAllocations(pDevice);
}
TEST_F(CommandContainerTest, givenCreateSecondaryCmdBufferInHostMemWhenFillReusableAllocationListsThenCreateAlocsForSecondaryCmdBuffer) {
DebugManagerStateRestore dbgRestore;
debugManager.flags.SetAmountOfReusableAllocations.set(1);
auto cmdContainer = std::make_unique<MyMockCommandContainer>();
auto csr = pDevice->getDefaultEngine().commandStreamReceiver;
AllocationsList allocList;
cmdContainer->initialize(pDevice, &allocList, HeapSize::defaultHeapSize, true, true);
cmdContainer->setImmediateCmdListCsr(csr);
auto actualResidencyContainerSize = cmdContainer->getResidencyContainer().size();
EXPECT_EQ(cmdContainer->immediateReusableAllocationList, nullptr);
cmdContainer->fillReusableAllocationLists();
ASSERT_NE(cmdContainer->immediateReusableAllocationList, nullptr);
EXPECT_FALSE(cmdContainer->immediateReusableAllocationList->peekIsEmpty());
EXPECT_EQ(cmdContainer->getResidencyContainer().size(), actualResidencyContainerSize + 2);
cmdContainer.reset();
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);
auto cmdContainer = std::make_unique<CommandContainer>();
auto csr = pDevice->getDefaultEngine().commandStreamReceiver;
AllocationsList allocList;
cmdContainer->enableHeapSharing();
cmdContainer->initialize(pDevice, &allocList, HeapSize::defaultHeapSize, true, false);
cmdContainer->setImmediateCmdListCsr(csr);
auto &reusableHeapsList = reinterpret_cast<MockHeapHelper *>(cmdContainer->getHeapHelper())->storageForReuse->getAllocationsForReuse();
EXPECT_TRUE(reusableHeapsList.peekIsEmpty());
cmdContainer->fillReusableAllocationLists();
EXPECT_FALSE(reusableHeapsList.peekIsEmpty());
EXPECT_EQ(reusableHeapsList.peekHead()->countThisAndAllConnected(), 1u);
cmdContainer.reset();
allocList.freeAllGraphicsAllocations(pDevice);
}
TEST_F(CommandContainerTest, givenCmdContainerWhenFillReusableAllocationListsWithGlobalSshEnabledThenTwoHeapsFilled) {
DebugManagerStateRestore dbgRestore;
debugManager.flags.SetAmountOfReusableAllocations.set(1);
debugManager.flags.UseExternalAllocatorForSshAndDsh.set(true);
auto csr = pDevice->getDefaultEngine().commandStreamReceiver;
auto mockHelper = std::make_unique<MockBindlesHeapsHelper>(pDevice->getMemoryManager(),
pDevice->getNumGenericSubDevices() > 1,
pDevice->getRootDeviceIndex(),
pDevice->getDeviceBitfield());
mockHelper->globalBindlessDsh = false;
pDevice->getExecutionEnvironment()->rootDeviceEnvironments[pDevice->getRootDeviceIndex()]->bindlessHeapsHelper.reset(mockHelper.release());
auto cmdContainer = std::make_unique<CommandContainer>();
AllocationsList allocList;
cmdContainer->initialize(pDevice, &allocList, HeapSize::defaultHeapSize, true, false);
cmdContainer->setImmediateCmdListCsr(csr);
auto &reusableHeapsList = reinterpret_cast<MockHeapHelper *>(cmdContainer->getHeapHelper())->storageForReuse->getAllocationsForReuse();
EXPECT_TRUE(reusableHeapsList.peekIsEmpty());
cmdContainer->fillReusableAllocationLists();
EXPECT_FALSE(reusableHeapsList.peekIsEmpty());
auto expectedHeapCount = hardwareInfo.capabilityTable.supportsImages ? 2u : 1u;
EXPECT_EQ(reusableHeapsList.peekHead()->countThisAndAllConnected(), expectedHeapCount);
cmdContainer.reset();
allocList.freeAllGraphicsAllocations(pDevice);
}
TEST_F(CommandContainerTest, givenCmdContainerWhenFillReusableAllocationListsWithoutHeapsThenAllocListNotEmpty) {
DebugManagerStateRestore dbgRestore;
debugManager.flags.SetAmountOfReusableAllocations.set(1);
auto cmdContainer = std::make_unique<MyMockCommandContainer>();
AllocationsList allocList;
cmdContainer->initialize(pDevice, &allocList, HeapSize::defaultHeapSize, false, false);
EXPECT_EQ(cmdContainer->immediateReusableAllocationList, nullptr);
cmdContainer->fillReusableAllocationLists();
EXPECT_FALSE(cmdContainer->immediateReusableAllocationList->peekIsEmpty());
cmdContainer.reset();
allocList.freeAllGraphicsAllocations(pDevice);
}
TEST_F(CommandContainerTest, givenCmdContainerWhenFillReusableAllocationListsAndDestroyCmdContainerThenGlobalAllocListNotEmpty) {
DebugManagerStateRestore dbgRestore;
debugManager.flags.SetAmountOfReusableAllocations.set(1);
auto cmdContainer = std::make_unique<MyMockCommandContainer>();
AllocationsList allocList;
cmdContainer->initialize(pDevice, &allocList, HeapSize::defaultHeapSize, false, false);
EXPECT_EQ(cmdContainer->immediateReusableAllocationList, nullptr);
EXPECT_TRUE(allocList.peekIsEmpty());
cmdContainer->fillReusableAllocationLists();
EXPECT_FALSE(cmdContainer->immediateReusableAllocationList->peekIsEmpty());
EXPECT_TRUE(allocList.peekIsEmpty());
cmdContainer.reset();
EXPECT_FALSE(allocList.peekIsEmpty());
allocList.freeAllGraphicsAllocations(pDevice);
}
TEST_F(CommandContainerTest, givenCmdContainerWithoutGlobalListWhenFillReusableAllocationListsAndDestroyCmdContainerThenImmediateListUnused) {
DebugManagerStateRestore dbgRestore;
debugManager.flags.SetAmountOfReusableAllocations.set(1);
auto cmdContainer = std::make_unique<MyMockCommandContainer>();
cmdContainer->initialize(pDevice, nullptr, HeapSize::defaultHeapSize, false, false);
EXPECT_EQ(cmdContainer->immediateReusableAllocationList, nullptr);
cmdContainer->fillReusableAllocationLists();
EXPECT_FALSE(cmdContainer->immediateReusableAllocationList->peekIsEmpty());
cmdContainer->handleCmdBufferAllocations(0);
EXPECT_FALSE(cmdContainer->immediateReusableAllocationList->peekIsEmpty());
cmdContainer->immediateReusableAllocationList->freeAllGraphicsAllocations(pDevice);
cmdContainer->getCmdBufferAllocations().pop_back();
}
TEST_F(CommandContainerTest, givenCmdContainerWhenFillReusableAllocationListsWithSpecifiedAmountThenAllocationsCreated) {
DebugManagerStateRestore dbgRestore;
debugManager.flags.SetAmountOfReusableAllocations.set(10);
auto cmdContainer = std::make_unique<MyMockCommandContainer>();
auto csr = pDevice->getDefaultEngine().commandStreamReceiver;
AllocationsList allocList;
cmdContainer->initialize(pDevice, &allocList, HeapSize::defaultHeapSize, false, false);
cmdContainer->setImmediateCmdListCsr(csr);
EXPECT_EQ(cmdContainer->immediateReusableAllocationList, nullptr);
cmdContainer->fillReusableAllocationLists();
EXPECT_EQ(cmdContainer->immediateReusableAllocationList->peekHead()->countThisAndAllConnected(), 10u);
cmdContainer.reset();
allocList.freeAllGraphicsAllocations(pDevice);
}
TEST_F(CommandContainerTest, givenCmdContainerAndCsrWhenGetHeapWithRequiredSizeAndAlignmentThenReuseAllocationIfAvailable) {
DebugManagerStateRestore dbgRestore;
debugManager.flags.SetAmountOfReusableAllocations.set(1);
auto cmdContainer = std::make_unique<CommandContainer>();
auto csr = pDevice->getDefaultEngine().commandStreamReceiver;
AllocationsList allocList;
cmdContainer->initialize(pDevice, &allocList, HeapSize::defaultHeapSize, true, false);
cmdContainer->setImmediateCmdListCsr(csr);
cmdContainer->fillReusableAllocationLists();
auto &reusableHeapsList = reinterpret_cast<MockHeapHelper *>(cmdContainer->getHeapHelper())->storageForReuse->getAllocationsForReuse();
auto baseAlloc = cmdContainer->getIndirectHeapAllocation(HeapType::indirectObject);
auto reusableAlloc = reusableHeapsList.peekHead();
cmdContainer->getIndirectHeap(HeapType::indirectObject)->getSpace(cmdContainer->getIndirectHeap(HeapType::indirectObject)->getMaxAvailableSpace());
auto heap = cmdContainer->getHeapWithRequiredSizeAndAlignment(HeapType::indirectObject, 1024, 1024);
EXPECT_EQ(heap->getGraphicsAllocation(), reusableAlloc);
EXPECT_TRUE(reusableHeapsList.peekContains(*baseAlloc));
cmdContainer.reset();
allocList.freeAllGraphicsAllocations(pDevice);
}
TEST_F(CommandContainerTest, givenCmdContainerWhenFillReusableAllocationListsAndFlagDisabledThenAllocListEmpty) {
DebugManagerStateRestore dbgRestore;
debugManager.flags.SetAmountOfReusableAllocations.set(0);
auto cmdContainer = std::make_unique<MyMockCommandContainer>();
auto csr = pDevice->getDefaultEngine().commandStreamReceiver;
AllocationsList allocList;
cmdContainer->initialize(pDevice, &allocList, HeapSize::defaultHeapSize, false, false);
cmdContainer->setImmediateCmdListCsr(csr);
cmdContainer->fillReusableAllocationLists();
EXPECT_TRUE(cmdContainer->immediateReusableAllocationList->peekIsEmpty());
cmdContainer.reset();
allocList.freeAllGraphicsAllocations(pDevice);
}
TEST_F(CommandContainerHeapStateTests, givenCmdContainerWhenSettingHeapAddressModelThenGeterReturnsTheSameValue) {
myCommandContainer.setHeapAddressModel(HeapAddressModel::globalStateless);
EXPECT_EQ(HeapAddressModel::globalStateless, myCommandContainer.getHeapAddressModel());
myCommandContainer.setHeapAddressModel(HeapAddressModel::globalBindless);
EXPECT_EQ(HeapAddressModel::globalBindless, myCommandContainer.getHeapAddressModel());
myCommandContainer.setHeapAddressModel(HeapAddressModel::globalBindful);
EXPECT_EQ(HeapAddressModel::globalBindful, myCommandContainer.getHeapAddressModel());
}
TEST_F(CommandContainerTest, givenGlobalHeapModelSelectedWhenCmdContainerIsInitializedThenNoSurfaceAndDynamicHeapCreated) {
MyMockCommandContainer cmdContainer;
cmdContainer.setHeapAddressModel(HeapAddressModel::globalStateless);
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
EXPECT_EQ(nullptr, cmdContainer.getIndirectHeap(NEO::HeapType::surfaceState));
EXPECT_EQ(nullptr, cmdContainer.getIndirectHeap(NEO::HeapType::dynamicState));
}
TEST_F(CommandContainerTest, givenCmdContainerAllocatesIndirectHeapWhenGettingMemoryPlacementThenFlagMatchesGraphicsAllocationPlacement) {
auto cmdContainer = std::make_unique<MyMockCommandContainer>();
cmdContainer->initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
EXPECT_EQ(cmdContainer->isIndirectHeapInLocalMemory(), cmdContainer->getIndirectHeap(NEO::HeapType::indirectObject)->getGraphicsAllocation()->isAllocatedInLocalMemoryPool());
}
TEST_F(CommandContainerTest, givenCmdContainerSetToSbaTrackingWhenStateHeapsConsumedAndContainerResetThenHeapsCurrentPositionRetained) {
bool useDsh = pDevice->getHardwareInfo().capabilityTable.supportsImages;
auto cmdContainer = std::make_unique<MyMockCommandContainer>();
cmdContainer->setStateBaseAddressTracking(true);
cmdContainer->initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
NEO::IndirectHeap *ioh = cmdContainer->getIndirectHeap(NEO::HeapType::indirectObject);
ioh->getSpace(64);
NEO::IndirectHeap *ssh = cmdContainer->getIndirectHeap(NEO::HeapType::surfaceState);
ssh->getSpace(64);
size_t sshUsed = ssh->getUsed();
NEO::IndirectHeap *dsh = cmdContainer->getIndirectHeap(NEO::HeapType::dynamicState);
size_t dshUsed = 0;
if (useDsh) {
dsh->getSpace(64);
dshUsed = dsh->getUsed();
}
cmdContainer->reset();
EXPECT_EQ(0u, ioh->getUsed());
EXPECT_EQ(sshUsed, ssh->getUsed());
if (useDsh) {
EXPECT_EQ(dshUsed, dsh->getUsed());
}
}
TEST_F(CommandContainerTest, givenCmdContainerSetToSbaTrackingWhenContainerIsInitializedThenSurfaceHeapDefaultValueIsUsed) {
constexpr size_t sshDefaultSize = 2 * HeapSize::defaultHeapSize;
auto cmdContainer = std::make_unique<MyMockCommandContainer>();
cmdContainer->initialize(pDevice, nullptr, sshDefaultSize, true, false);
EXPECT_EQ(HeapSize::defaultHeapSize, cmdContainer->defaultSshSize);
cmdContainer = std::make_unique<MyMockCommandContainer>();
cmdContainer->setStateBaseAddressTracking(true);
cmdContainer->initialize(pDevice, nullptr, sshDefaultSize, true, false);
EXPECT_EQ(2 * HeapSize::defaultHeapSize, cmdContainer->defaultSshSize);
}
HWTEST_F(CommandContainerTest,
givenCmdContainerUsingPrimaryBatchBufferWhenCloseAndAllocateNextCommandBufferCalledThenNewCmdBufferAllocationCreatedAndChainedWithOldCmdBuffer) {
using MI_BATCH_BUFFER_START = typename FamilyType::MI_BATCH_BUFFER_START;
CommandContainer cmdContainer;
cmdContainer.setUsingPrimaryBuffer(true);
EXPECT_TRUE(cmdContainer.isUsingPrimaryBuffer());
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
ASSERT_EQ(cmdContainer.getCmdBufferAllocations().size(), 1u);
auto firstCmdBufferAllocation = cmdContainer.getCmdBufferAllocations()[0];
cmdContainer.closeAndAllocateNextCommandBuffer();
ASSERT_EQ(cmdContainer.getCmdBufferAllocations().size(), 2u);
auto chainedCmdBufferAllocation = cmdContainer.getCmdBufferAllocations()[1];
auto bbStartGpuAddress = chainedCmdBufferAllocation->getGpuAddress();
auto bbStart = genCmdCast<MI_BATCH_BUFFER_START *>(firstCmdBufferAllocation->getUnderlyingBuffer());
ASSERT_NE(nullptr, bbStart);
EXPECT_EQ(bbStartGpuAddress, bbStart->getBatchBufferStartAddress());
EXPECT_EQ(MI_BATCH_BUFFER_START::SECOND_LEVEL_BATCH_BUFFER::SECOND_LEVEL_BATCH_BUFFER_FIRST_LEVEL_BATCH, bbStart->getSecondLevelBatchBuffer());
size_t expectedEndSize = alignUp(sizeof(MI_BATCH_BUFFER_START), CommandContainer::minCmdBufferPtrAlign);
cmdContainer.endAlignedPrimaryBuffer();
void *endPtr = cmdContainer.getEndCmdPtr();
size_t alignedSize = cmdContainer.getAlignedPrimarySize();
EXPECT_EQ(chainedCmdBufferAllocation->getUnderlyingBuffer(), endPtr);
EXPECT_EQ(expectedEndSize, alignedSize);
}
HWTEST_F(CommandContainerTest,
givenCmdContainerUsingPrimaryBatchBufferWhenCloseAndAllocateMultipleCommandBuffersThenNewCmdBufferAllocationsCreatedAndChainedWithOldCmdBuffers) {
using MI_BATCH_BUFFER_START = typename FamilyType::MI_BATCH_BUFFER_START;
CommandContainer cmdContainer;
cmdContainer.setUsingPrimaryBuffer(true);
EXPECT_TRUE(cmdContainer.isUsingPrimaryBuffer());
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
ASSERT_EQ(cmdContainer.getCmdBufferAllocations().size(), 1u);
auto firstCmdBufferAllocation = cmdContainer.getCmdBufferAllocations()[0];
size_t consumedSize = sizeof(int);
cmdContainer.getCommandStream()->getSpace(consumedSize);
size_t expectedEndSize = alignUp(sizeof(MI_BATCH_BUFFER_START) + consumedSize, CommandContainer::minCmdBufferPtrAlign);
cmdContainer.closeAndAllocateNextCommandBuffer();
ASSERT_EQ(cmdContainer.getCmdBufferAllocations().size(), 2u);
auto chainedCmdBufferAllocation = cmdContainer.getCmdBufferAllocations()[1];
auto bbStartGpuAddress = chainedCmdBufferAllocation->getGpuAddress();
auto bbStart = genCmdCast<MI_BATCH_BUFFER_START *>(ptrOffset(firstCmdBufferAllocation->getUnderlyingBuffer(), consumedSize));
ASSERT_NE(nullptr, bbStart);
EXPECT_EQ(bbStartGpuAddress, bbStart->getBatchBufferStartAddress());
EXPECT_EQ(MI_BATCH_BUFFER_START::SECOND_LEVEL_BATCH_BUFFER::SECOND_LEVEL_BATCH_BUFFER_FIRST_LEVEL_BATCH, bbStart->getSecondLevelBatchBuffer());
consumedSize *= 2;
cmdContainer.getCommandStream()->getSpace(consumedSize);
cmdContainer.closeAndAllocateNextCommandBuffer();
ASSERT_EQ(cmdContainer.getCmdBufferAllocations().size(), 3u);
auto closingCmdBufferAllocation = cmdContainer.getCmdBufferAllocations()[2];
bbStartGpuAddress = closingCmdBufferAllocation->getGpuAddress();
bbStart = genCmdCast<MI_BATCH_BUFFER_START *>(ptrOffset(chainedCmdBufferAllocation->getUnderlyingBuffer(), consumedSize));
ASSERT_NE(nullptr, bbStart);
EXPECT_EQ(bbStartGpuAddress, bbStart->getBatchBufferStartAddress());
EXPECT_EQ(MI_BATCH_BUFFER_START::SECOND_LEVEL_BATCH_BUFFER::SECOND_LEVEL_BATCH_BUFFER_FIRST_LEVEL_BATCH, bbStart->getSecondLevelBatchBuffer());
consumedSize = alignUp(sizeof(MI_BATCH_BUFFER_START), CommandContainer::minCmdBufferPtrAlign) - sizeof(MI_BATCH_BUFFER_START);
cmdContainer.getCommandStream()->getSpace(consumedSize);
cmdContainer.endAlignedPrimaryBuffer();
void *endPtr = cmdContainer.getEndCmdPtr();
size_t alignedSize = cmdContainer.getAlignedPrimarySize();
EXPECT_EQ(ptrOffset(closingCmdBufferAllocation->getUnderlyingBuffer(), consumedSize), endPtr);
EXPECT_EQ(expectedEndSize, alignedSize);
}
HWTEST_F(CommandContainerTest,
givenCmdContainerUsingPrimaryBatchBufferWhenEndingPrimaryBufferAndFirstChainInUseThenProvideFirstChainBufferAlignedSize) {
using MI_BATCH_BUFFER_START = typename FamilyType::MI_BATCH_BUFFER_START;
CommandContainer cmdContainer;
cmdContainer.setUsingPrimaryBuffer(true);
EXPECT_TRUE(cmdContainer.isUsingPrimaryBuffer());
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
ASSERT_EQ(cmdContainer.getCmdBufferAllocations().size(), 1u);
auto firstCmdBufferAllocation = cmdContainer.getCmdBufferAllocations()[0];
size_t consumedSize = 20;
cmdContainer.getCommandStream()->getSpace(consumedSize);
size_t expectedEndSize = alignUp(sizeof(MI_BATCH_BUFFER_START) + consumedSize, CommandContainer::minCmdBufferPtrAlign);
void *expectedEndPtr = ptrOffset(firstCmdBufferAllocation->getUnderlyingBuffer(), consumedSize);
cmdContainer.endAlignedPrimaryBuffer();
void *endPtr = cmdContainer.getEndCmdPtr();
size_t alignedSize = cmdContainer.getAlignedPrimarySize();
EXPECT_EQ(expectedEndPtr, endPtr);
EXPECT_EQ(expectedEndSize, alignedSize);
cmdContainer.reset();
EXPECT_EQ(nullptr, cmdContainer.getEndCmdPtr());
EXPECT_EQ(0u, cmdContainer.getAlignedPrimarySize());
}
HWTEST_F(CommandContainerTest,
givenCmdContainerUsingPrimaryBatchBufferWhenEndingPrimaryBufferWhenSecondChainInUseThenProvideFirstChainBufferAlignedSize) {
using MI_BATCH_BUFFER_START = typename FamilyType::MI_BATCH_BUFFER_START;
CommandContainer cmdContainer;
cmdContainer.setUsingPrimaryBuffer(true);
EXPECT_TRUE(cmdContainer.isUsingPrimaryBuffer());
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
ASSERT_EQ(cmdContainer.getCmdBufferAllocations().size(), 1u);
size_t consumedSize = 28;
cmdContainer.getCommandStream()->getSpace(consumedSize);
void *bbStartSpace = ptrOffset(cmdContainer.getCommandStream()->getCpuBase(), consumedSize);
size_t expectedEndSize = alignUp(sizeof(MI_BATCH_BUFFER_START) + consumedSize, CommandContainer::minCmdBufferPtrAlign);
cmdContainer.closeAndAllocateNextCommandBuffer();
ASSERT_EQ(cmdContainer.getCmdBufferAllocations().size(), 2u);
auto secondCmdBufferAllocation = cmdContainer.getCmdBufferAllocations()[1];
auto bbStart = genCmdCast<MI_BATCH_BUFFER_START *>(bbStartSpace);
ASSERT_NE(nullptr, bbStart);
EXPECT_EQ(secondCmdBufferAllocation->getGpuAddress(), bbStart->getBatchBufferStartAddress());
EXPECT_EQ(MI_BATCH_BUFFER_START::SECOND_LEVEL_BATCH_BUFFER::SECOND_LEVEL_BATCH_BUFFER_FIRST_LEVEL_BATCH, bbStart->getSecondLevelBatchBuffer());
consumedSize = 64;
cmdContainer.getCommandStream()->getSpace(consumedSize);
void *expectedEndPtr = ptrOffset(secondCmdBufferAllocation->getUnderlyingBuffer(), consumedSize);
cmdContainer.endAlignedPrimaryBuffer();
void *endPtr = cmdContainer.getEndCmdPtr();
size_t alignedSize = cmdContainer.getAlignedPrimarySize();
EXPECT_EQ(expectedEndPtr, endPtr);
EXPECT_EQ(expectedEndSize, alignedSize);
cmdContainer.reset();
EXPECT_EQ(nullptr, cmdContainer.getEndCmdPtr());
EXPECT_EQ(0u, cmdContainer.getAlignedPrimarySize());
}
TEST_F(CommandContainerTest, givenCmdContainerWhenImmediateCmdListCsrIsSetThenCommandStreamHasCmdContainerSetToNullptr) {
CommandContainer cmdContainer;
cmdContainer.setImmediateCmdListCsr(pDevice->getDefaultEngine().commandStreamReceiver);
cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, false, false);
EXPECT_EQ(cmdContainer.getCommandStream()->getCmdContainer(), nullptr);
}