/* * Copyright (C) 2020 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "shared/source/program/program_initialization.h" #include "shared/test/unit_test/compiler_interface/linker_mock.h" #include "shared/test/unit_test/helpers/debug_manager_state_restore.h" #include "shared/test/unit_test/mocks/mock_device.h" #include "shared/test/unit_test/test_macros/test_checks_shared.h" #include "opencl/test/unit_test/mocks/mock_cl_device.h" #include "opencl/test/unit_test/mocks/mock_memory_manager.h" #include "opencl/test/unit_test/mocks/mock_svm_manager.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include using namespace NEO; TEST(AllocateGlobalSurfaceTest, GivenSvmAllocsManagerWhenGlobalsAreNotExportedThenMemoryIsAllocatedAsNonSvmAllocation) { auto &device = *(new MockDevice); REQUIRE_SVM_OR_SKIP(&device); MockClDevice clDevice{&device}; MockSVMAllocsManager svmAllocsManager(device.getMemoryManager()); WhiteBox emptyLinkerInput; std::vector initData; initData.resize(64, 7U); GraphicsAllocation *alloc = nullptr; alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), true /* constant */, nullptr /* linker input */, initData.data()); ASSERT_NE(nullptr, alloc); ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize()); EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size())); EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast(static_cast(alloc->getGpuAddress())))); EXPECT_EQ(GraphicsAllocation::AllocationType::CONSTANT_SURFACE, alloc->getAllocationType()); device.getMemoryManager()->freeGraphicsMemory(alloc); alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), false /* constant */, nullptr /* linker input */, initData.data()); ASSERT_NE(nullptr, alloc); ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize()); EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size())); EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast(static_cast(alloc->getGpuAddress())))); EXPECT_EQ(GraphicsAllocation::AllocationType::GLOBAL_SURFACE, alloc->getAllocationType()); device.getMemoryManager()->freeGraphicsMemory(alloc); alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), true /* constant */, &emptyLinkerInput, initData.data()); ASSERT_NE(nullptr, alloc); ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize()); EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size())); EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast(static_cast(alloc->getGpuAddress())))); EXPECT_EQ(GraphicsAllocation::AllocationType::CONSTANT_SURFACE, alloc->getAllocationType()); device.getMemoryManager()->freeGraphicsMemory(alloc); alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), false /* constant */, &emptyLinkerInput, initData.data()); ASSERT_NE(nullptr, alloc); ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize()); EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size())); EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast(static_cast(alloc->getGpuAddress())))); EXPECT_EQ(GraphicsAllocation::AllocationType::GLOBAL_SURFACE, alloc->getAllocationType()); device.getMemoryManager()->freeGraphicsMemory(alloc); } TEST(AllocateGlobalSurfaceTest, GivenSvmAllocsManagerWhenGlobalsAreExportedThenMemoryIsAllocatedAsSvmAllocation) { auto &device = *(new MockDevice); REQUIRE_SVM_OR_SKIP(&device); MockClDevice clDevice{&device}; MockMemoryManager memoryManager; MockSVMAllocsManager svmAllocsManager(&memoryManager); WhiteBox linkerInputExportGlobalVariables; WhiteBox linkerInputExportGlobalConstants; linkerInputExportGlobalVariables.traits.exportsGlobalVariables = true; linkerInputExportGlobalConstants.traits.exportsGlobalConstants = true; std::vector initData; initData.resize(64, 7U); GraphicsAllocation *alloc = nullptr; alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), true /* constant */, &linkerInputExportGlobalConstants, initData.data()); ASSERT_NE(nullptr, alloc); ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize()); EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size())); ASSERT_NE(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast(static_cast(alloc->getGpuAddress())))); EXPECT_FALSE(alloc->isMemObjectsAllocationWithWritableFlags()); svmAllocsManager.freeSVMAlloc(reinterpret_cast(static_cast(alloc->getGpuAddress()))); alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), true /* constant */, &linkerInputExportGlobalVariables, initData.data()); ASSERT_NE(nullptr, alloc); ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize()); EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size())); EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast(static_cast(alloc->getGpuAddress())))); device.getMemoryManager()->freeGraphicsMemory(alloc); alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), false /* constant */, &linkerInputExportGlobalConstants, initData.data()); ASSERT_NE(nullptr, alloc); ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize()); EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size())); EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast(static_cast(alloc->getGpuAddress())))); device.getMemoryManager()->freeGraphicsMemory(alloc); alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), false /* constant */, &linkerInputExportGlobalVariables, initData.data()); ASSERT_NE(nullptr, alloc); ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize()); EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size())); EXPECT_NE(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast(static_cast(alloc->getGpuAddress())))); EXPECT_TRUE(alloc->isMemObjectsAllocationWithWritableFlags()); svmAllocsManager.freeSVMAlloc(reinterpret_cast(static_cast(alloc->getGpuAddress()))); } TEST(AllocateGlobalSurfaceTest, GivenNullSvmAllocsManagerWhenGlobalsAreExportedThenMemoryIsAllocatedAsNonSvmAllocation) { auto pDevice = new MockDevice{}; MockClDevice clDevice{pDevice}; WhiteBox linkerInputExportGlobalVariables; WhiteBox linkerInputExportGlobalConstants; linkerInputExportGlobalVariables.traits.exportsGlobalVariables = true; linkerInputExportGlobalConstants.traits.exportsGlobalConstants = true; std::vector initData; initData.resize(64, 7U); GraphicsAllocation *alloc = nullptr; alloc = allocateGlobalsSurface(nullptr, *pDevice, initData.size(), true /* constant */, &linkerInputExportGlobalConstants, initData.data()); ASSERT_NE(nullptr, alloc); ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize()); EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size())); EXPECT_EQ(GraphicsAllocation::AllocationType::CONSTANT_SURFACE, alloc->getAllocationType()); pDevice->getMemoryManager()->freeGraphicsMemory(alloc); alloc = allocateGlobalsSurface(nullptr, *pDevice, initData.size(), true /* constant */, &linkerInputExportGlobalVariables, initData.data()); ASSERT_NE(nullptr, alloc); ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize()); EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size())); EXPECT_EQ(GraphicsAllocation::AllocationType::CONSTANT_SURFACE, alloc->getAllocationType()); pDevice->getMemoryManager()->freeGraphicsMemory(alloc); alloc = allocateGlobalsSurface(nullptr, *pDevice, initData.size(), false /* constant */, &linkerInputExportGlobalConstants, initData.data()); ASSERT_NE(nullptr, alloc); ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize()); EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size())); EXPECT_EQ(GraphicsAllocation::AllocationType::GLOBAL_SURFACE, alloc->getAllocationType()); pDevice->getMemoryManager()->freeGraphicsMemory(alloc); alloc = allocateGlobalsSurface(nullptr, *pDevice, initData.size(), false /* constant */, &linkerInputExportGlobalVariables, initData.data()); ASSERT_NE(nullptr, alloc); ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize()); EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size())); EXPECT_EQ(GraphicsAllocation::AllocationType::GLOBAL_SURFACE, alloc->getAllocationType()); pDevice->getMemoryManager()->freeGraphicsMemory(alloc); } TEST(AllocateGlobalSurfaceTest, WhenGlobalsAreNotExportedAndAllocationFailsThenGracefullyReturnsNullptr) { auto pDevice = new MockDevice{}; MockClDevice clDevice{pDevice}; auto memoryManager = std::make_unique(*clDevice.getExecutionEnvironment()); memoryManager->failInAllocateWithSizeAndAlignment = true; clDevice.injectMemoryManager(memoryManager.release()); MockSVMAllocsManager mockSvmAllocsManager(clDevice.getMemoryManager()); WhiteBox emptyLinkerInput; std::vector initData; initData.resize(64, 7U); GraphicsAllocation *alloc = nullptr; alloc = allocateGlobalsSurface(&mockSvmAllocsManager, *pDevice, initData.size(), true /* constant */, nullptr /* linker input */, initData.data()); EXPECT_EQ(nullptr, alloc); alloc = allocateGlobalsSurface(&mockSvmAllocsManager, *pDevice, initData.size(), false /* constant */, nullptr /* linker input */, initData.data()); EXPECT_EQ(nullptr, alloc); alloc = allocateGlobalsSurface(&mockSvmAllocsManager, *pDevice, initData.size(), true /* constant */, &emptyLinkerInput, initData.data()); EXPECT_EQ(nullptr, alloc); alloc = allocateGlobalsSurface(&mockSvmAllocsManager, *pDevice, initData.size(), false /* constant */, &emptyLinkerInput, initData.data()); EXPECT_EQ(nullptr, alloc); alloc = allocateGlobalsSurface(nullptr /* svmAllocsManager */, *pDevice, initData.size(), true /* constant */, nullptr /* linker input */, initData.data()); EXPECT_EQ(nullptr, alloc); alloc = allocateGlobalsSurface(nullptr /* svmAllocsManager */, *pDevice, initData.size(), false /* constant */, nullptr /* linker input */, initData.data()); EXPECT_EQ(nullptr, alloc); alloc = allocateGlobalsSurface(nullptr /* svmAllocsManager */, *pDevice, initData.size(), true /* constant */, &emptyLinkerInput, initData.data()); EXPECT_EQ(nullptr, alloc); alloc = allocateGlobalsSurface(nullptr /* svmAllocsManager */, *pDevice, initData.size(), false /* constant */, &emptyLinkerInput, initData.data()); EXPECT_EQ(nullptr, alloc); } TEST(AllocateGlobalSurfaceTest, WhenGlobalsAreExportedAndAllocationFailsThenGracefullyReturnsNullptr) { auto pDevice = new MockDevice{}; MockClDevice clDevice{pDevice}; MockMemoryManager memoryManager{*clDevice.getExecutionEnvironment()}; MockSVMAllocsManager svmAllocsManager(&memoryManager); memoryManager.failInAllocateWithSizeAndAlignment = true; WhiteBox linkerInputExportGlobalVariables; WhiteBox linkerInputExportGlobalConstants; linkerInputExportGlobalVariables.traits.exportsGlobalVariables = true; linkerInputExportGlobalConstants.traits.exportsGlobalConstants = true; std::vector initData; initData.resize(64, 7U); GraphicsAllocation *alloc = nullptr; alloc = allocateGlobalsSurface(&svmAllocsManager, *pDevice, initData.size(), true /* constant */, &linkerInputExportGlobalConstants, initData.data()); EXPECT_EQ(nullptr, alloc); alloc = allocateGlobalsSurface(&svmAllocsManager, *pDevice, initData.size(), false /* constant */, &linkerInputExportGlobalVariables, initData.data()); EXPECT_EQ(nullptr, alloc); } TEST(AllocateGlobalSurfaceTest, GivenAllocationInLocalMemoryWhichRequiresBlitterWhenAllocatingNonSvmAllocationThenBlitterIsUsed) { REQUIRE_SVM_OR_SKIP(defaultHwInfo.get()); DebugManagerStateRestore restorer; uint32_t blitsCounter = 0; uint32_t expectedBlitsCount = 0; auto mockBlitMemoryToAllocation = [&blitsCounter](const Device &device, GraphicsAllocation *memory, size_t offset, const void *hostPtr, Vec3 size) -> BlitOperationResult { blitsCounter++; return BlitOperationResult::Success; }; VariableBackup blitMemoryToAllocationFuncBackup{ &BlitHelperFunctions::blitMemoryToAllocation, mockBlitMemoryToAllocation}; LocalMemoryAccessMode localMemoryAccessModes[] = { LocalMemoryAccessMode::Default, LocalMemoryAccessMode::CpuAccessAllowed, LocalMemoryAccessMode::CpuAccessDisallowed}; std::vector initData; initData.resize(64, 7U); for (auto localMemoryAccessMode : localMemoryAccessModes) { DebugManager.flags.ForceLocalMemoryAccessMode.set(static_cast(localMemoryAccessMode)); for (auto isLocalMemorySupported : ::testing::Bool()) { DebugManager.flags.EnableLocalMemory.set(isLocalMemorySupported); MockDevice device; device.getExecutionEnvironment()->rootDeviceEnvironments[0]->getMutableHardwareInfo()->capabilityTable.blitterOperationsSupported = true; MockSVMAllocsManager svmAllocsManager(device.getMemoryManager()); auto pAllocation = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), true /* constant */, nullptr /* linker input */, initData.data()); ASSERT_NE(nullptr, pAllocation); EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast(static_cast(pAllocation->getGpuAddress())))); EXPECT_EQ(GraphicsAllocation::AllocationType::CONSTANT_SURFACE, pAllocation->getAllocationType()); if (pAllocation->isAllocatedInLocalMemoryPool() && (localMemoryAccessMode == LocalMemoryAccessMode::CpuAccessDisallowed)) { expectedBlitsCount++; } EXPECT_EQ(expectedBlitsCount, blitsCounter); device.getMemoryManager()->freeGraphicsMemory(pAllocation); } } }