1 /*
2 * Copyright (C) 2019-2021 Intel Corporation
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 */
7
8 #include "shared/source/command_container/cmdcontainer.h"
9 #include "shared/source/memory_manager/allocations_list.h"
10 #include "shared/test/common/fixtures/device_fixture.h"
11 #include "shared/test/common/helpers/debug_manager_state_restore.h"
12 #include "shared/test/common/mocks/mock_graphics_allocation.h"
13 #include "shared/test/common/mocks/mock_memory_manager.h"
14 #include "shared/test/common/test_macros/test.h"
15
16 using namespace NEO;
17
18 constexpr uint32_t defaultNumIddsPerBlock = 64;
19
20 class CommandContainerTest : public DeviceFixture,
21 public ::testing::Test {
22
23 public:
SetUp()24 void SetUp() override {
25 ::testing::Test::SetUp();
26 DeviceFixture::SetUp();
27 }
TearDown()28 void TearDown() override {
29 DeviceFixture::TearDown();
30 ::testing::Test::TearDown();
31 }
32 };
33
34 struct CommandContainerHeapStateTests : public ::testing::Test {
35 class MyMockCommandContainer : public CommandContainer {
36 public:
37 using CommandContainer::dirtyHeaps;
38 };
39
40 MyMockCommandContainer myCommandContainer;
41 };
42
TEST_F(CommandContainerHeapStateTests,givenDirtyHeapsWhenSettingStateForAllThenValuesAreCorrect)43 TEST_F(CommandContainerHeapStateTests, givenDirtyHeapsWhenSettingStateForAllThenValuesAreCorrect) {
44 EXPECT_EQ(std::numeric_limits<uint32_t>::max(), myCommandContainer.dirtyHeaps);
45 EXPECT_TRUE(myCommandContainer.isAnyHeapDirty());
46
47 myCommandContainer.setDirtyStateForAllHeaps(false);
48 EXPECT_EQ(0u, myCommandContainer.dirtyHeaps);
49 EXPECT_FALSE(myCommandContainer.isAnyHeapDirty());
50
51 for (uint32_t i = 0; i < HeapType::NUM_TYPES; i++) {
52 HeapType heapType = static_cast<HeapType>(i);
53 EXPECT_FALSE(myCommandContainer.isHeapDirty(heapType));
54 }
55
56 myCommandContainer.setDirtyStateForAllHeaps(true);
57 EXPECT_EQ(std::numeric_limits<uint32_t>::max(), myCommandContainer.dirtyHeaps);
58
59 for (uint32_t i = 0; i < HeapType::NUM_TYPES; i++) {
60 HeapType heapType = static_cast<HeapType>(i);
61 EXPECT_TRUE(myCommandContainer.isHeapDirty(heapType));
62 }
63 }
64
TEST_F(CommandContainerHeapStateTests,givenDirtyHeapsWhenSettingStateForSingleHeapThenValuesAreCorrect)65 TEST_F(CommandContainerHeapStateTests, givenDirtyHeapsWhenSettingStateForSingleHeapThenValuesAreCorrect) {
66 myCommandContainer.dirtyHeaps = 0;
67 EXPECT_FALSE(myCommandContainer.isAnyHeapDirty());
68
69 uint32_t controlVariable = 0;
70 for (uint32_t i = 0; i < HeapType::NUM_TYPES; i++) {
71 HeapType heapType = static_cast<HeapType>(i);
72
73 EXPECT_FALSE(myCommandContainer.isHeapDirty(heapType));
74 myCommandContainer.setHeapDirty(heapType);
75 EXPECT_TRUE(myCommandContainer.isHeapDirty(heapType));
76 EXPECT_TRUE(myCommandContainer.isAnyHeapDirty());
77
78 controlVariable |= (1 << i);
79 EXPECT_EQ(controlVariable, myCommandContainer.dirtyHeaps);
80 }
81
82 for (uint32_t i = 0; i < HeapType::NUM_TYPES; i++) {
83 HeapType heapType = static_cast<HeapType>(i);
84 EXPECT_TRUE(myCommandContainer.isHeapDirty(heapType));
85 }
86 }
87
TEST_F(CommandContainerTest,givenCmdContainerWhenCreatingCommandBufferThenCorrectAllocationTypeIsSet)88 TEST_F(CommandContainerTest, givenCmdContainerWhenCreatingCommandBufferThenCorrectAllocationTypeIsSet) {
89 CommandContainer cmdContainer;
90 cmdContainer.initialize(pDevice, nullptr);
91
92 ASSERT_NE(0u, cmdContainer.getCmdBufferAllocations().size());
93 EXPECT_EQ(GraphicsAllocation::AllocationType::COMMAND_BUFFER, cmdContainer.getCmdBufferAllocations()[0]->getAllocationType());
94
95 cmdContainer.allocateNextCommandBuffer();
96
97 ASSERT_LE(2u, cmdContainer.getCmdBufferAllocations().size());
98 EXPECT_EQ(GraphicsAllocation::AllocationType::COMMAND_BUFFER, cmdContainer.getCmdBufferAllocations()[1]->getAllocationType());
99 }
100
TEST_F(CommandContainerTest,givenCmdContainerWhenAllocatingHeapsThenSetCorrectAllocationTypes)101 TEST_F(CommandContainerTest, givenCmdContainerWhenAllocatingHeapsThenSetCorrectAllocationTypes) {
102 CommandContainer cmdContainer;
103 cmdContainer.initialize(pDevice, nullptr);
104
105 for (uint32_t i = 0; i < HeapType::NUM_TYPES; i++) {
106 HeapType heapType = static_cast<HeapType>(i);
107 auto heap = cmdContainer.getIndirectHeap(heapType);
108
109 if (HeapType::INDIRECT_OBJECT == heapType) {
110 EXPECT_EQ(GraphicsAllocation::AllocationType::INTERNAL_HEAP, heap->getGraphicsAllocation()->getAllocationType());
111 EXPECT_NE(0u, heap->getHeapGpuStartOffset());
112 } else {
113 EXPECT_EQ(GraphicsAllocation::AllocationType::LINEAR_STREAM, heap->getGraphicsAllocation()->getAllocationType());
114 EXPECT_EQ(0u, heap->getHeapGpuStartOffset());
115 }
116 }
117 }
118
TEST_F(CommandContainerTest,givenCommandContainerWhenInitializeThenEverythingIsInitialized)119 TEST_F(CommandContainerTest, givenCommandContainerWhenInitializeThenEverythingIsInitialized) {
120 CommandContainer cmdContainer;
121 auto status = cmdContainer.initialize(pDevice, nullptr);
122 EXPECT_EQ(ErrorCode::SUCCESS, status);
123
124 EXPECT_EQ(pDevice, cmdContainer.getDevice());
125 EXPECT_NE(cmdContainer.getHeapHelper(), nullptr);
126 EXPECT_EQ(cmdContainer.getCmdBufferAllocations().size(), 1u);
127 EXPECT_NE(cmdContainer.getCommandStream(), nullptr);
128
129 for (uint32_t i = 0; i < HeapType::NUM_TYPES; i++) {
130 auto indirectHeap = cmdContainer.getIndirectHeap(static_cast<HeapType>(i));
131 auto heapAllocation = cmdContainer.getIndirectHeapAllocation(static_cast<HeapType>(i));
132 EXPECT_EQ(indirectHeap->getGraphicsAllocation(), heapAllocation);
133 }
134
135 EXPECT_EQ(cmdContainer.getIddBlock(), nullptr);
136 EXPECT_EQ(cmdContainer.getNumIddPerBlock(), defaultNumIddsPerBlock);
137
138 auto &hwHelper = HwHelper::get(pDevice->getHardwareInfo().platform.eRenderCoreFamily);
139
140 EXPECT_EQ(cmdContainer.getInstructionHeapBaseAddress(),
141 pDevice->getMemoryManager()->getInternalHeapBaseAddress(0, !hwHelper.useSystemMemoryPlacementForISA(pDevice->getHardwareInfo())));
142 }
143
TEST_F(CommandContainerTest,givenEnabledLocalMemoryAndIsaInSystemMemoryWhenCmdContainerIsInitializedThenInstructionBaseAddressIsSetToInternalHeap)144 TEST_F(CommandContainerTest, givenEnabledLocalMemoryAndIsaInSystemMemoryWhenCmdContainerIsInitializedThenInstructionBaseAddressIsSetToInternalHeap) {
145 DebugManagerStateRestore dbgRestore;
146 DebugManager.flags.ForceSystemMemoryPlacement.set(1 << (static_cast<uint32_t>(GraphicsAllocation::AllocationType::KERNEL_ISA) - 1));
147
148 auto executionEnvironment = new NEO::ExecutionEnvironment();
149 const size_t numDevices = 1;
150 executionEnvironment->prepareRootDeviceEnvironments(numDevices);
151 executionEnvironment->rootDeviceEnvironments[0]->setHwInfo(defaultHwInfo.get());
152
153 auto hwInfo = executionEnvironment->rootDeviceEnvironments[0]->getMutableHardwareInfo();
154 hwInfo->featureTable.flags.ftrLocalMemory = true;
155
156 auto device = std::unique_ptr<MockDevice>(Device::create<MockDevice>(executionEnvironment, 0u));
157
158 auto instructionHeapBaseAddress = device->getMemoryManager()->getInternalHeapBaseAddress(0, false);
159
160 CommandContainer cmdContainer;
161 auto status = cmdContainer.initialize(device.get(), nullptr);
162 EXPECT_EQ(ErrorCode::SUCCESS, status);
163
164 EXPECT_EQ(instructionHeapBaseAddress, cmdContainer.getInstructionHeapBaseAddress());
165 }
166
TEST_F(CommandContainerTest,givenCommandContainerDuringInitWhenAllocateGfxMemoryFailsThenErrorIsReturned)167 TEST_F(CommandContainerTest, givenCommandContainerDuringInitWhenAllocateGfxMemoryFailsThenErrorIsReturned) {
168 CommandContainer cmdContainer;
169 pDevice->executionEnvironment->memoryManager.reset(new FailMemoryManager(0, *pDevice->executionEnvironment));
170 auto status = cmdContainer.initialize(pDevice, nullptr);
171 EXPECT_EQ(ErrorCode::OUT_OF_DEVICE_MEMORY, status);
172 }
173
TEST_F(CommandContainerTest,givenCmdContainerWithAllocsListWhenAllocateAndResetThenCmdBufferAllocIsReused)174 TEST_F(CommandContainerTest, givenCmdContainerWithAllocsListWhenAllocateAndResetThenCmdBufferAllocIsReused) {
175 AllocationsList allocList;
176 auto cmdContainer = std::make_unique<CommandContainer>();
177 cmdContainer->initialize(pDevice, &allocList);
178 auto &cmdBufferAllocs = cmdContainer->getCmdBufferAllocations();
179 auto memoryManager = static_cast<MockMemoryManager *>(pDevice->getMemoryManager());
180 EXPECT_EQ(memoryManager->handleFenceCompletionCalled, 0u);
181 EXPECT_EQ(cmdBufferAllocs.size(), 1u);
182 EXPECT_TRUE(allocList.peekIsEmpty());
183
184 cmdContainer->allocateNextCommandBuffer();
185 EXPECT_EQ(cmdBufferAllocs.size(), 2u);
186
187 auto cmdBuffer0 = cmdBufferAllocs[0];
188 auto cmdBuffer1 = cmdBufferAllocs[1];
189
190 cmdContainer->reset();
191 EXPECT_EQ(memoryManager->handleFenceCompletionCalled, 1u);
192 EXPECT_EQ(cmdBufferAllocs.size(), 1u);
193 EXPECT_EQ(cmdBufferAllocs[0], cmdBuffer0);
194 EXPECT_FALSE(allocList.peekIsEmpty());
195
196 cmdContainer->allocateNextCommandBuffer();
197 EXPECT_EQ(cmdBufferAllocs.size(), 2u);
198 EXPECT_EQ(cmdBufferAllocs[0], cmdBuffer0);
199 EXPECT_EQ(cmdBufferAllocs[1], cmdBuffer1);
200 EXPECT_TRUE(allocList.peekIsEmpty());
201
202 cmdContainer.reset();
203 EXPECT_EQ(memoryManager->handleFenceCompletionCalled, 3u);
204 EXPECT_FALSE(allocList.peekIsEmpty());
205 allocList.freeAllGraphicsAllocations(pDevice);
206 }
207
TEST_F(CommandContainerTest,givenCommandContainerDuringInitWhenAllocateHeapMemoryFailsThenErrorIsReturned)208 TEST_F(CommandContainerTest, givenCommandContainerDuringInitWhenAllocateHeapMemoryFailsThenErrorIsReturned) {
209 CommandContainer cmdContainer;
210 auto temp_memoryManager = pDevice->executionEnvironment->memoryManager.release();
211 pDevice->executionEnvironment->memoryManager.reset(new FailMemoryManager(1, *pDevice->executionEnvironment));
212 auto status = cmdContainer.initialize(pDevice, nullptr);
213 EXPECT_EQ(ErrorCode::OUT_OF_DEVICE_MEMORY, status);
214 delete temp_memoryManager;
215 }
216
TEST_F(CommandContainerTest,givenCommandContainerWhenSettingIndirectHeapAllocationThenAllocationIsSet)217 TEST_F(CommandContainerTest, givenCommandContainerWhenSettingIndirectHeapAllocationThenAllocationIsSet) {
218 CommandContainer cmdContainer;
219 MockGraphicsAllocation mockAllocation;
220 auto heapType = HeapType::DYNAMIC_STATE;
221 cmdContainer.setIndirectHeapAllocation(heapType, &mockAllocation);
222 EXPECT_EQ(cmdContainer.getIndirectHeapAllocation(heapType), &mockAllocation);
223 }
224
TEST_F(CommandContainerTest,givenHeapAllocationsWhenDestroyCommandContainerThenHeapAllocationsAreReused)225 TEST_F(CommandContainerTest, givenHeapAllocationsWhenDestroyCommandContainerThenHeapAllocationsAreReused) {
226 std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
227 cmdContainer->initialize(pDevice, nullptr);
228 auto heapAllocationsAddress = cmdContainer->getIndirectHeapAllocation(HeapType::DYNAMIC_STATE)->getUnderlyingBuffer();
229 cmdContainer.reset(new CommandContainer);
230 cmdContainer->initialize(pDevice, nullptr);
231 bool status = false;
232 for (uint32_t i = 0; i < HeapType::NUM_TYPES && !status; i++) {
233 status = cmdContainer->getIndirectHeapAllocation(static_cast<HeapType>(i))->getUnderlyingBuffer() == heapAllocationsAddress;
234 }
235 EXPECT_TRUE(status);
236 }
237
TEST_F(CommandContainerTest,givenCommandContainerWhenResetThenStateIsReset)238 TEST_F(CommandContainerTest, givenCommandContainerWhenResetThenStateIsReset) {
239 CommandContainer cmdContainer;
240 cmdContainer.initialize(pDevice, nullptr);
241 LinearStream stream;
242 uint32_t usedSize = 1;
243 cmdContainer.lastSentNumGrfRequired = 64;
244 cmdContainer.getCommandStream()->getSpace(usedSize);
245 EXPECT_EQ(usedSize, cmdContainer.getCommandStream()->getUsed());
246 cmdContainer.reset();
247 EXPECT_NE(usedSize, cmdContainer.getCommandStream()->getUsed());
248 EXPECT_EQ(0u, cmdContainer.getCommandStream()->getUsed());
249 EXPECT_EQ(0u, cmdContainer.lastSentNumGrfRequired);
250 EXPECT_EQ(cmdContainer.getIddBlock(), nullptr);
251 EXPECT_EQ(cmdContainer.getNumIddPerBlock(), defaultNumIddsPerBlock);
252 }
253
TEST_F(CommandContainerTest,givenCommandContainerWhenWantToAddNullPtrToResidencyContainerThenNothingIsAdded)254 TEST_F(CommandContainerTest, givenCommandContainerWhenWantToAddNullPtrToResidencyContainerThenNothingIsAdded) {
255 CommandContainer cmdContainer;
256 cmdContainer.initialize(pDevice, nullptr);
257 auto size = cmdContainer.getResidencyContainer().size();
258 cmdContainer.addToResidencyContainer(nullptr);
259 EXPECT_EQ(cmdContainer.getResidencyContainer().size(), size);
260 }
261
TEST_F(CommandContainerTest,givenCommandContainerWhenWantToAddAlreadyAddedAllocationAndDuplicatesRemovedThenExpectedSizeIsReturned)262 TEST_F(CommandContainerTest, givenCommandContainerWhenWantToAddAlreadyAddedAllocationAndDuplicatesRemovedThenExpectedSizeIsReturned) {
263 CommandContainer cmdContainer;
264 cmdContainer.initialize(pDevice, nullptr);
265 MockGraphicsAllocation mockAllocation;
266
267 auto sizeBefore = cmdContainer.getResidencyContainer().size();
268
269 cmdContainer.addToResidencyContainer(&mockAllocation);
270 auto sizeAfterFirstAdd = cmdContainer.getResidencyContainer().size();
271
272 EXPECT_NE(sizeBefore, sizeAfterFirstAdd);
273
274 cmdContainer.addToResidencyContainer(&mockAllocation);
275 auto sizeAfterSecondAdd = cmdContainer.getResidencyContainer().size();
276
277 EXPECT_NE(sizeAfterFirstAdd, sizeAfterSecondAdd);
278
279 cmdContainer.removeDuplicatesFromResidencyContainer();
280 auto sizeAfterDuplicatesRemoved = cmdContainer.getResidencyContainer().size();
281
282 EXPECT_EQ(sizeAfterFirstAdd, sizeAfterDuplicatesRemoved);
283 }
284
HWTEST_F(CommandContainerTest,givenCmdContainerWhenInitializeCalledThenSSHHeapHasBindlessOffsetReserved)285 HWTEST_F(CommandContainerTest, givenCmdContainerWhenInitializeCalledThenSSHHeapHasBindlessOffsetReserved) {
286 using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE;
287 std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
288 cmdContainer->setReservedSshSize(4 * MemoryConstants::pageSize);
289 cmdContainer->initialize(pDevice, nullptr);
290 cmdContainer->setDirtyStateForAllHeaps(false);
291
292 auto heap = cmdContainer->getIndirectHeap(HeapType::SURFACE_STATE);
293
294 ASSERT_NE(nullptr, heap);
295 EXPECT_EQ(4 * MemoryConstants::pageSize, heap->getUsed());
296 }
297
HWTEST_F(CommandContainerTest,givenNotEnoughSpaceInSSHWhenGettingHeapWithRequiredSizeAndAlignmentThenSSHHeapHasBindlessOffsetReserved)298 HWTEST_F(CommandContainerTest, givenNotEnoughSpaceInSSHWhenGettingHeapWithRequiredSizeAndAlignmentThenSSHHeapHasBindlessOffsetReserved) {
299 using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE;
300 std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
301 cmdContainer->setReservedSshSize(4 * MemoryConstants::pageSize);
302 cmdContainer->initialize(pDevice, nullptr);
303 cmdContainer->setDirtyStateForAllHeaps(false);
304
305 auto heap = cmdContainer->getIndirectHeap(HeapType::SURFACE_STATE);
306 ASSERT_NE(nullptr, heap);
307 heap->getSpace(heap->getAvailableSpace());
308
309 cmdContainer->getHeapWithRequiredSizeAndAlignment(HeapType::SURFACE_STATE, sizeof(RENDER_SURFACE_STATE), 0);
310
311 EXPECT_EQ(4 * MemoryConstants::pageSize, heap->getUsed());
312 EXPECT_EQ(cmdContainer->sshAllocations.size(), 1u);
313 }
314
TEST_F(CommandContainerTest,givenAvailableSpaceWhenGetHeapWithRequiredSizeAndAlignmentCalledThenExistingAllocationIsReturned)315 TEST_F(CommandContainerTest, givenAvailableSpaceWhenGetHeapWithRequiredSizeAndAlignmentCalledThenExistingAllocationIsReturned) {
316 std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
317 cmdContainer->initialize(pDevice, nullptr);
318 cmdContainer->setDirtyStateForAllHeaps(false);
319 HeapType types[] = {HeapType::SURFACE_STATE,
320 HeapType::DYNAMIC_STATE};
321
322 for (auto type : types) {
323 auto heapAllocation = cmdContainer->getIndirectHeapAllocation(type);
324 auto heap = cmdContainer->getIndirectHeap(type);
325
326 const size_t sizeRequested = 32;
327 const size_t alignment = 32;
328
329 EXPECT_GE(heap->getAvailableSpace(), sizeRequested + alignment);
330 auto sizeBefore = heap->getUsed();
331
332 auto heapRequested = cmdContainer->getHeapWithRequiredSizeAndAlignment(type, sizeRequested, alignment);
333 auto newAllocation = heapRequested->getGraphicsAllocation();
334
335 EXPECT_EQ(heap, heapRequested);
336 EXPECT_EQ(heapAllocation, newAllocation);
337
338 EXPECT_TRUE((reinterpret_cast<size_t>(heapRequested->getSpace(0)) & (alignment - 1)) == 0);
339 EXPECT_FALSE(cmdContainer->isHeapDirty(type));
340
341 auto sizeAfter = heapRequested->getUsed();
342 EXPECT_EQ(sizeBefore, sizeAfter);
343 }
344 }
345
TEST_F(CommandContainerTest,givenUnalignedAvailableSpaceWhenGetHeapWithRequiredSizeAndAlignmentCalledThenHeapReturnedIsCorrectlyAligned)346 TEST_F(CommandContainerTest, givenUnalignedAvailableSpaceWhenGetHeapWithRequiredSizeAndAlignmentCalledThenHeapReturnedIsCorrectlyAligned) {
347 std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
348 cmdContainer->initialize(pDevice, nullptr);
349 cmdContainer->setDirtyStateForAllHeaps(false);
350 auto heapAllocation = cmdContainer->getIndirectHeapAllocation(HeapType::SURFACE_STATE);
351 auto heap = cmdContainer->getIndirectHeap(HeapType::SURFACE_STATE);
352
353 const size_t sizeRequested = 32;
354 const size_t alignment = 32;
355
356 heap->getSpace(sizeRequested / 2);
357
358 EXPECT_GE(heap->getAvailableSpace(), sizeRequested + alignment);
359
360 auto heapRequested = cmdContainer->getHeapWithRequiredSizeAndAlignment(HeapType::SURFACE_STATE, sizeRequested, alignment);
361 auto newAllocation = heapRequested->getGraphicsAllocation();
362
363 EXPECT_EQ(heap, heapRequested);
364 EXPECT_EQ(heapAllocation, newAllocation);
365
366 EXPECT_TRUE((reinterpret_cast<size_t>(heapRequested->getSpace(0)) & (alignment - 1)) == 0);
367 EXPECT_FALSE(cmdContainer->isHeapDirty(HeapType::SURFACE_STATE));
368 }
369
TEST_F(CommandContainerTest,givenNoAlignmentAndAvailableSpaceWhenGetHeapWithRequiredSizeAndAlignmentCalledThenHeapReturnedIsNotAligned)370 TEST_F(CommandContainerTest, givenNoAlignmentAndAvailableSpaceWhenGetHeapWithRequiredSizeAndAlignmentCalledThenHeapReturnedIsNotAligned) {
371 std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
372 cmdContainer->initialize(pDevice, nullptr);
373 cmdContainer->setDirtyStateForAllHeaps(false);
374 auto heapAllocation = cmdContainer->getIndirectHeapAllocation(HeapType::SURFACE_STATE);
375 auto heap = cmdContainer->getIndirectHeap(HeapType::SURFACE_STATE);
376
377 const size_t sizeRequested = 32;
378 const size_t alignment = 0;
379
380 heap->getSpace(sizeRequested / 2);
381
382 EXPECT_GE(heap->getAvailableSpace(), sizeRequested + alignment);
383
384 auto heapRequested = cmdContainer->getHeapWithRequiredSizeAndAlignment(HeapType::SURFACE_STATE, sizeRequested, alignment);
385 auto newAllocation = heapRequested->getGraphicsAllocation();
386
387 EXPECT_EQ(heap, heapRequested);
388 EXPECT_EQ(heapAllocation, newAllocation);
389
390 EXPECT_TRUE((reinterpret_cast<size_t>(heapRequested->getSpace(0)) & (sizeRequested / 2)) == sizeRequested / 2);
391 EXPECT_FALSE(cmdContainer->isHeapDirty(HeapType::SURFACE_STATE));
392 }
393
TEST_F(CommandContainerTest,givenNotEnoughSpaceWhenGetHeapWithRequiredSizeAndAlignmentCalledThenNewAllocationIsReturned)394 TEST_F(CommandContainerTest, givenNotEnoughSpaceWhenGetHeapWithRequiredSizeAndAlignmentCalledThenNewAllocationIsReturned) {
395 std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
396 cmdContainer->initialize(pDevice, nullptr);
397 cmdContainer->setDirtyStateForAllHeaps(false);
398 HeapType types[] = {HeapType::SURFACE_STATE,
399 HeapType::DYNAMIC_STATE};
400
401 for (auto type : types) {
402 auto heapAllocation = cmdContainer->getIndirectHeapAllocation(type);
403 auto heap = cmdContainer->getIndirectHeap(type);
404
405 const size_t sizeRequested = 32;
406 const size_t alignment = 32;
407 size_t availableSize = heap->getAvailableSpace();
408
409 heap->getSpace(availableSize - sizeRequested / 2);
410
411 EXPECT_LT(heap->getAvailableSpace(), sizeRequested + alignment);
412
413 auto heapRequested = cmdContainer->getHeapWithRequiredSizeAndAlignment(type, sizeRequested, alignment);
414 auto newAllocation = heapRequested->getGraphicsAllocation();
415
416 EXPECT_EQ(heap, heapRequested);
417 EXPECT_NE(heapAllocation, newAllocation);
418
419 EXPECT_TRUE((reinterpret_cast<size_t>(heapRequested->getSpace(0)) & (alignment - 1)) == 0);
420 EXPECT_TRUE(cmdContainer->isHeapDirty(type));
421 }
422 for (auto deallocation : cmdContainer->getDeallocationContainer()) {
423 cmdContainer->getDevice()->getMemoryManager()->freeGraphicsMemory(deallocation);
424 }
425 cmdContainer->getDeallocationContainer().clear();
426 }
427
TEST_F(CommandContainerTest,givenNotEnoughSpaceWhenCreatedAlocationHaveDifferentBaseThenHeapIsDirty)428 TEST_F(CommandContainerTest, givenNotEnoughSpaceWhenCreatedAlocationHaveDifferentBaseThenHeapIsDirty) {
429 std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
430 cmdContainer->initialize(pDevice, nullptr);
431 cmdContainer->setDirtyStateForAllHeaps(false);
432 HeapType type = HeapType::INDIRECT_OBJECT;
433
434 auto heapAllocation = cmdContainer->getIndirectHeapAllocation(type);
435 auto heap = cmdContainer->getIndirectHeap(type);
436
437 const size_t sizeRequested = 32;
438 const size_t alignment = 32;
439 size_t availableSize = heap->getAvailableSpace();
440
441 heap->getSpace(availableSize - sizeRequested / 2);
442
443 EXPECT_LT(heap->getAvailableSpace(), sizeRequested + alignment);
444
445 auto heapRequested = cmdContainer->getHeapWithRequiredSizeAndAlignment(type, sizeRequested, alignment);
446 auto newAllocation = heapRequested->getGraphicsAllocation();
447
448 EXPECT_EQ(heap, heapRequested);
449 EXPECT_NE(heapAllocation, newAllocation);
450
451 EXPECT_TRUE((reinterpret_cast<size_t>(heapRequested->getSpace(0)) & (alignment - 1)) == 0);
452 EXPECT_FALSE(cmdContainer->isHeapDirty(type));
453
454 for (auto deallocation : cmdContainer->getDeallocationContainer()) {
455 cmdContainer->getDevice()->getMemoryManager()->freeGraphicsMemory(deallocation);
456 }
457 cmdContainer->getDeallocationContainer().clear();
458 }
459
TEST_F(CommandContainerTest,whenAllocateNextCmdBufferIsCalledThenNewAllocationIsCreatedAndCommandStreamReplaced)460 TEST_F(CommandContainerTest, whenAllocateNextCmdBufferIsCalledThenNewAllocationIsCreatedAndCommandStreamReplaced) {
461 std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
462 cmdContainer->initialize(pDevice, nullptr);
463 auto stream = cmdContainer->getCommandStream();
464 ASSERT_NE(nullptr, stream);
465
466 auto initialBuffer = stream->getSpace(0);
467 EXPECT_NE(nullptr, initialBuffer);
468
469 cmdContainer->allocateNextCommandBuffer();
470
471 auto nextBuffer = stream->getSpace(0);
472 auto sizeUsed = stream->getUsed();
473 auto availableSize = stream->getMaxAvailableSpace();
474
475 EXPECT_NE(nullptr, nextBuffer);
476 EXPECT_EQ(0u, sizeUsed);
477 EXPECT_NE(initialBuffer, nextBuffer);
478 const size_t cmdBufSize = CommandContainer::defaultListCmdBufferSize;
479 EXPECT_EQ(cmdBufSize, availableSize);
480
481 ASSERT_EQ(2u, cmdContainer->getCmdBufferAllocations().size());
482 EXPECT_EQ(cmdContainer->getCmdBufferAllocations()[1], cmdContainer->getCommandStream()->getGraphicsAllocation());
483
484 EXPECT_EQ(cmdContainer->getCmdBufferAllocations()[1], cmdContainer->getResidencyContainer().back());
485 }
486
TEST_F(CommandContainerTest,whenResettingCommandContainerThenStoredCmdBuffersAreFreedAndStreamIsReplacedWithInitialBuffer)487 TEST_F(CommandContainerTest, whenResettingCommandContainerThenStoredCmdBuffersAreFreedAndStreamIsReplacedWithInitialBuffer) {
488 std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
489 cmdContainer->initialize(pDevice, nullptr);
490
491 cmdContainer->allocateNextCommandBuffer();
492 cmdContainer->allocateNextCommandBuffer();
493
494 EXPECT_EQ(3u, cmdContainer->getCmdBufferAllocations().size());
495
496 cmdContainer->reset();
497
498 ASSERT_EQ(1u, cmdContainer->getCmdBufferAllocations().size());
499
500 auto stream = cmdContainer->getCommandStream();
501 ASSERT_NE(nullptr, stream);
502
503 auto buffer = stream->getSpace(0);
504 const size_t cmdBufSize = CommandContainer::defaultListCmdBufferSize;
505
506 EXPECT_EQ(cmdContainer->getCmdBufferAllocations()[0]->getUnderlyingBuffer(), buffer);
507 EXPECT_EQ(cmdBufSize, stream->getMaxAvailableSpace());
508 }
509
510 class CommandContainerHeaps : public DeviceFixture,
511 public ::testing::TestWithParam<IndirectHeap::Type> {
512 public:
SetUp()513 void SetUp() override {
514 DeviceFixture::SetUp();
515 }
516
TearDown()517 void TearDown() override {
518 DeviceFixture::TearDown();
519 }
520 };
521
522 INSTANTIATE_TEST_CASE_P(
523 Device,
524 CommandContainerHeaps,
525 testing::Values(
526 IndirectHeap::DYNAMIC_STATE,
527 IndirectHeap::INDIRECT_OBJECT,
528 IndirectHeap::SURFACE_STATE));
529
TEST_P(CommandContainerHeaps,givenCommandContainerWhenGetAllowHeapGrowCalledThenHeapIsReturned)530 TEST_P(CommandContainerHeaps, givenCommandContainerWhenGetAllowHeapGrowCalledThenHeapIsReturned) {
531 HeapType heap = GetParam();
532
533 CommandContainer cmdContainer;
534 cmdContainer.initialize(pDevice, nullptr);
535 auto usedSpaceBefore = cmdContainer.getIndirectHeap(heap)->getUsed();
536 size_t size = 5000;
537 void *ptr = cmdContainer.getHeapSpaceAllowGrow(heap, size);
538 ASSERT_NE(nullptr, ptr);
539
540 auto usedSpaceAfter = cmdContainer.getIndirectHeap(heap)->getUsed();
541 ASSERT_EQ(usedSpaceBefore + size, usedSpaceAfter);
542 }
543
TEST_P(CommandContainerHeaps,givenCommandContainerWhenGetingMoreThanAvailableSizeThenBiggerHeapIsReturned)544 TEST_P(CommandContainerHeaps, givenCommandContainerWhenGetingMoreThanAvailableSizeThenBiggerHeapIsReturned) {
545 HeapType heap = GetParam();
546
547 CommandContainer cmdContainer;
548 cmdContainer.initialize(pDevice, nullptr);
549 cmdContainer.setDirtyStateForAllHeaps(false);
550
551 auto usedSpaceBefore = cmdContainer.getIndirectHeap(heap)->getUsed();
552 auto availableSizeBefore = cmdContainer.getIndirectHeap(heap)->getAvailableSpace();
553
554 void *ptr = cmdContainer.getHeapSpaceAllowGrow(heap, availableSizeBefore + 1);
555 ASSERT_NE(nullptr, ptr);
556
557 auto usedSpaceAfter = cmdContainer.getIndirectHeap(heap)->getUsed();
558 auto availableSizeAfter = cmdContainer.getIndirectHeap(heap)->getAvailableSpace();
559 EXPECT_GT(usedSpaceAfter + availableSizeAfter, usedSpaceBefore + availableSizeBefore);
560 EXPECT_EQ(!cmdContainer.isHeapDirty(heap), heap == IndirectHeap::INDIRECT_OBJECT);
561 }
562
TEST_P(CommandContainerHeaps,givenCommandContainerForDifferentRootDevicesThenHeapsAreCreatedWithCorrectRootDeviceIndex)563 TEST_P(CommandContainerHeaps, givenCommandContainerForDifferentRootDevicesThenHeapsAreCreatedWithCorrectRootDeviceIndex) {
564 HeapType heap = GetParam();
565
566 auto executionEnvironment = new NEO::ExecutionEnvironment();
567 const size_t numDevices = 2;
568 executionEnvironment->prepareRootDeviceEnvironments(numDevices);
569 for (auto i = 0u; i < numDevices; i++) {
570 executionEnvironment->rootDeviceEnvironments[i]->setHwInfo(defaultHwInfo.get());
571 }
572 auto device0 = std::unique_ptr<MockDevice>(Device::create<MockDevice>(executionEnvironment, 0u));
573 auto device1 = std::unique_ptr<MockDevice>(Device::create<MockDevice>(executionEnvironment, 1u));
574
575 CommandContainer cmdContainer0;
576 cmdContainer0.initialize(device0.get(), nullptr);
577 uint32_t heapRootDeviceIndex0 = cmdContainer0.getIndirectHeap(heap)->getGraphicsAllocation()->getRootDeviceIndex();
578 EXPECT_EQ(device0->getRootDeviceIndex(), heapRootDeviceIndex0);
579
580 CommandContainer cmdContainer1;
581 cmdContainer1.initialize(device1.get(), nullptr);
582 uint32_t heapRootDeviceIndex1 = cmdContainer1.getIndirectHeap(heap)->getGraphicsAllocation()->getRootDeviceIndex();
583 EXPECT_EQ(device1->getRootDeviceIndex(), heapRootDeviceIndex1);
584 }
585
TEST_F(CommandContainerHeaps,givenCommandContainerForDifferentRootDevicesThenCmdBufferAllocationIsCreatedWithCorrectRootDeviceIndex)586 TEST_F(CommandContainerHeaps, givenCommandContainerForDifferentRootDevicesThenCmdBufferAllocationIsCreatedWithCorrectRootDeviceIndex) {
587 auto executionEnvironment = new NEO::ExecutionEnvironment();
588 const size_t numDevices = 2;
589 executionEnvironment->prepareRootDeviceEnvironments(numDevices);
590 for (auto i = 0u; i < numDevices; i++) {
591 executionEnvironment->rootDeviceEnvironments[i]->setHwInfo(defaultHwInfo.get());
592 }
593 auto device0 = std::unique_ptr<MockDevice>(Device::create<MockDevice>(executionEnvironment, 0u));
594 auto device1 = std::unique_ptr<MockDevice>(Device::create<MockDevice>(executionEnvironment, 1u));
595
596 CommandContainer cmdContainer0;
597 cmdContainer0.initialize(device0.get(), nullptr);
598 EXPECT_EQ(1u, cmdContainer0.getCmdBufferAllocations().size());
599 uint32_t cmdBufferAllocationIndex0 = cmdContainer0.getCmdBufferAllocations().front()->getRootDeviceIndex();
600 EXPECT_EQ(device0->getRootDeviceIndex(), cmdBufferAllocationIndex0);
601
602 CommandContainer cmdContainer1;
603 cmdContainer1.initialize(device1.get(), nullptr);
604 EXPECT_EQ(1u, cmdContainer1.getCmdBufferAllocations().size());
605 uint32_t cmdBufferAllocationIndex1 = cmdContainer1.getCmdBufferAllocations().front()->getRootDeviceIndex();
606 EXPECT_EQ(device1->getRootDeviceIndex(), cmdBufferAllocationIndex1);
607 }
608
TEST_F(CommandContainerHeaps,givenCommandContainerForDifferentRootDevicesThenInternalHeapIsCreatedWithCorrectRootDeviceIndex)609 TEST_F(CommandContainerHeaps, givenCommandContainerForDifferentRootDevicesThenInternalHeapIsCreatedWithCorrectRootDeviceIndex) {
610 auto executionEnvironment = new NEO::ExecutionEnvironment();
611 const size_t numDevices = 2;
612 executionEnvironment->prepareRootDeviceEnvironments(numDevices);
613 for (auto i = 0u; i < numDevices; i++) {
614 executionEnvironment->rootDeviceEnvironments[i]->setHwInfo(defaultHwInfo.get());
615 }
616 auto device0 = std::unique_ptr<MockDevice>(Device::create<MockDevice>(executionEnvironment, 0u));
617 auto device1 = std::unique_ptr<MockDevice>(Device::create<MockDevice>(executionEnvironment, 1u));
618
619 auto &hwHelper0 = HwHelper::get(device0->getHardwareInfo().platform.eRenderCoreFamily);
620 auto &hwHelper1 = HwHelper::get(device1->getHardwareInfo().platform.eRenderCoreFamily);
621
622 CommandContainer cmdContainer0;
623 cmdContainer0.initialize(device0.get(), nullptr);
624 bool useLocalMemory0 = !hwHelper0.useSystemMemoryPlacementForISA(device0->getHardwareInfo());
625 uint64_t baseAddressHeapDevice0 = device0.get()->getMemoryManager()->getInternalHeapBaseAddress(device0->getRootDeviceIndex(), useLocalMemory0);
626 EXPECT_EQ(cmdContainer0.getInstructionHeapBaseAddress(), baseAddressHeapDevice0);
627
628 CommandContainer cmdContainer1;
629 cmdContainer1.initialize(device1.get(), nullptr);
630 bool useLocalMemory1 = !hwHelper1.useSystemMemoryPlacementForISA(device0->getHardwareInfo());
631 uint64_t baseAddressHeapDevice1 = device1.get()->getMemoryManager()->getInternalHeapBaseAddress(device1->getRootDeviceIndex(), useLocalMemory1);
632 EXPECT_EQ(cmdContainer1.getInstructionHeapBaseAddress(), baseAddressHeapDevice1);
633 }
634
TEST_F(CommandContainerTest,givenCommandContainerWhenDestructionThenNonHeapAllocationAreNotDestroyed)635 TEST_F(CommandContainerTest, givenCommandContainerWhenDestructionThenNonHeapAllocationAreNotDestroyed) {
636 std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer());
637 MockGraphicsAllocation alloc;
638 size_t size = 0x1000;
639 alloc.setSize(size);
640 cmdContainer->initialize(pDevice, nullptr);
641 cmdContainer->getDeallocationContainer().push_back(&alloc);
642 cmdContainer.reset();
643 EXPECT_EQ(alloc.getUnderlyingBufferSize(), size);
644 }
645
TEST_F(CommandContainerTest,givenContainerAllocatesNextCommandBufferWhenResetingContainerThenExpectFirstCommandBufferAllocationIsReused)646 TEST_F(CommandContainerTest, givenContainerAllocatesNextCommandBufferWhenResetingContainerThenExpectFirstCommandBufferAllocationIsReused) {
647 auto cmdContainer = std::make_unique<CommandContainer>();
648 cmdContainer->initialize(pDevice, nullptr);
649
650 auto stream = cmdContainer->getCommandStream();
651 ASSERT_NE(nullptr, stream);
652 auto firstCmdBufferAllocation = stream->getGraphicsAllocation();
653 ASSERT_NE(nullptr, firstCmdBufferAllocation);
654 auto firstCmdBufferCpuPointer = stream->getSpace(0);
655 EXPECT_EQ(firstCmdBufferCpuPointer, firstCmdBufferAllocation->getUnderlyingBuffer());
656
657 cmdContainer->allocateNextCommandBuffer();
658 auto secondCmdBufferAllocation = stream->getGraphicsAllocation();
659 ASSERT_NE(nullptr, secondCmdBufferAllocation);
660 EXPECT_NE(firstCmdBufferAllocation, secondCmdBufferAllocation);
661 auto secondCmdBufferCpuPointer = stream->getSpace(0);
662 EXPECT_EQ(secondCmdBufferCpuPointer, secondCmdBufferAllocation->getUnderlyingBuffer());
663 EXPECT_NE(firstCmdBufferCpuPointer, secondCmdBufferCpuPointer);
664
665 cmdContainer->reset();
666
667 auto aferResetCmdBufferAllocation = stream->getGraphicsAllocation();
668 ASSERT_NE(nullptr, aferResetCmdBufferAllocation);
669 auto afterResetCmdBufferCpuPointer = stream->getSpace(0);
670 EXPECT_EQ(afterResetCmdBufferCpuPointer, aferResetCmdBufferAllocation->getUnderlyingBuffer());
671
672 EXPECT_EQ(firstCmdBufferAllocation, aferResetCmdBufferAllocation);
673 EXPECT_EQ(firstCmdBufferCpuPointer, afterResetCmdBufferCpuPointer);
674
675 bool firstAllocationFound = false;
676 auto &residencyContainer = cmdContainer->getResidencyContainer();
677 for (auto *allocation : residencyContainer) {
678 if (allocation == firstCmdBufferAllocation) {
679 firstAllocationFound = true;
680 break;
681 }
682 }
683 EXPECT_TRUE(firstAllocationFound);
684 }
685