Files
compute-runtime/shared/test/unit_test/program/program_initialization_tests.cpp
Fabian Zwoliński 3c43276dab feature: add global/const surface nonUSM allocation pooling
Related-To: NEO-12287
Signed-off-by: Fabian Zwoliński <fabian.zwolinski@intel.com>
2025-10-29 16:56:59 +01:00

840 lines
47 KiB
C++

/*
* Copyright (C) 2020-2025 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/compiler_interface/external_functions.h"
#include "shared/source/gmm_helper/gmm.h"
#include "shared/source/helpers/aligned_memory.h"
#include "shared/source/helpers/blit_helper.h"
#include "shared/source/helpers/local_memory_access_modes.h"
#include "shared/source/memory_manager/unified_memory_pooling.h"
#include "shared/source/program/program_initialization.h"
#include "shared/test/common/compiler_interface/linker_mock.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_device.h"
#include "shared/test/common/mocks/mock_memory_manager.h"
#include "shared/test/common/mocks/mock_product_helper.h"
#include "shared/test/common/mocks/mock_svm_manager.h"
#include "shared/test/common/mocks/mock_usm_memory_pool.h"
#include "shared/test/common/test_macros/hw_test.h"
#include "gtest/gtest.h"
#include <cstdint>
using namespace NEO;
struct AllocateGlobalSurfacePoolingDisabledTest : public ::testing::Test {
void SetUp() override {
device.injectMemoryManager(new MockMemoryManager());
device.resetUsmConstantSurfaceAllocPool(nullptr);
device.resetUsmGlobalSurfaceAllocPool(nullptr);
mockProductHelper = new MockProductHelper;
device.getRootDeviceEnvironmentRef().productHelper.reset(mockProductHelper);
mockProductHelper->is2MBLocalMemAlignmentEnabledResult = false;
}
MockProductHelper *mockProductHelper{nullptr};
MockDevice device{};
DebugManagerStateRestore restore;
};
TEST_F(AllocateGlobalSurfacePoolingDisabledTest, GivenSvmAllocsManagerWhenGlobalsAreNotExportedThenMemoryIsAllocatedAsNonSvmAllocation) {
MockSVMAllocsManager svmAllocsManager(device.getMemoryManager());
WhiteBox<LinkerInput> emptyLinkerInput;
std::vector<uint8_t> initData;
initData.resize(64, 7U);
std::unique_ptr<SharedPoolAllocation> globalSurface;
GraphicsAllocation *alloc{nullptr};
size_t alignmentSize = alignUp(initData.size(), MemoryConstants::pageSize);
globalSurface.reset(allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), 0u, true /* constant */, nullptr /* linker input */, initData.data()));
ASSERT_NE(nullptr, globalSurface);
alloc = globalSurface->getGraphicsAllocation();
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(alignmentSize, alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress()))));
EXPECT_EQ(AllocationType::constantSurface, alloc->getAllocationType());
EXPECT_FALSE(globalSurface->isFromPool());
device.getMemoryManager()->freeGraphicsMemory(alloc);
globalSurface.reset(allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), 0u, false /* constant */, nullptr /* linker input */, initData.data()));
ASSERT_NE(nullptr, globalSurface);
alloc = globalSurface->getGraphicsAllocation();
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(alignmentSize, alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress()))));
EXPECT_EQ(AllocationType::globalSurface, alloc->getAllocationType());
EXPECT_FALSE(globalSurface->isFromPool());
device.getMemoryManager()->freeGraphicsMemory(alloc);
globalSurface.reset(allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), 0u, true /* constant */, &emptyLinkerInput, initData.data()));
ASSERT_NE(nullptr, globalSurface);
alloc = globalSurface->getGraphicsAllocation();
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(alignmentSize, alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress()))));
EXPECT_EQ(AllocationType::constantSurface, alloc->getAllocationType());
EXPECT_FALSE(globalSurface->isFromPool());
device.getMemoryManager()->freeGraphicsMemory(alloc);
globalSurface.reset(allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), 0u, false /* constant */, &emptyLinkerInput, initData.data()));
ASSERT_NE(nullptr, globalSurface);
alloc = globalSurface->getGraphicsAllocation();
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(alignmentSize, alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress()))));
EXPECT_EQ(AllocationType::globalSurface, alloc->getAllocationType());
EXPECT_FALSE(globalSurface->isFromPool());
device.getMemoryManager()->freeGraphicsMemory(alloc);
}
TEST_F(AllocateGlobalSurfacePoolingDisabledTest, GivenSvmAllocsManagerWhenGlobalsAreExportedThenMemoryIsAllocatedAsUsmDeviceAllocation) {
debugManager.flags.ForceLocalMemoryAccessMode.set(0);
MockSVMAllocsManager svmAllocsManager(device.getMemoryManager());
WhiteBox<LinkerInput> linkerInputExportGlobalVariables;
WhiteBox<LinkerInput> linkerInputExportGlobalConstants;
linkerInputExportGlobalVariables.traits.exportsGlobalVariables = true;
linkerInputExportGlobalConstants.traits.exportsGlobalConstants = true;
std::vector<uint8_t> initData;
initData.resize(64, 7U);
std::unique_ptr<SharedPoolAllocation> globalSurface;
GraphicsAllocation *alloc{nullptr};
size_t expectedAlignedSize = alignUp(initData.size(), MemoryConstants::pageSize);
globalSurface.reset(allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), 0u, true /* constant */, &linkerInputExportGlobalConstants, initData.data()));
ASSERT_NE(nullptr, globalSurface);
alloc = globalSurface->getGraphicsAllocation();
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(MemoryConstants::pageSize64k, alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
ASSERT_NE(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress()))));
EXPECT_TRUE(alloc->isMemObjectsAllocationWithWritableFlags());
auto svmData = svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(alloc->getGpuAddress()));
EXPECT_EQ(InternalMemoryType::deviceUnifiedMemory, svmData->memoryType);
EXPECT_TRUE(svmData->isInternalAllocation);
EXPECT_EQ(AllocationType::constantSurface, alloc->getAllocationType());
EXPECT_FALSE(alloc->getDefaultGmm()->resourceParams.Flags.Info.NotLockable);
EXPECT_TRUE(svmAllocsManager.requestedZeroedOutAllocation);
svmAllocsManager.freeSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress())));
globalSurface.reset(allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), 0u, true /* constant */, &linkerInputExportGlobalVariables, initData.data()));
ASSERT_NE(nullptr, globalSurface);
alloc = globalSurface->getGraphicsAllocation();
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(expectedAlignedSize, alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress()))));
EXPECT_EQ(AllocationType::constantSurface, alloc->getAllocationType());
device.getMemoryManager()->freeGraphicsMemory(alloc);
globalSurface.reset(allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), 0u, false /* constant */, &linkerInputExportGlobalConstants, initData.data()));
ASSERT_NE(nullptr, globalSurface);
alloc = globalSurface->getGraphicsAllocation();
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(expectedAlignedSize, alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress()))));
EXPECT_EQ(AllocationType::globalSurface, alloc->getAllocationType());
device.getMemoryManager()->freeGraphicsMemory(alloc);
globalSurface.reset(allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), 0u, false /* constant */, &linkerInputExportGlobalVariables, initData.data()));
ASSERT_NE(nullptr, globalSurface);
alloc = globalSurface->getGraphicsAllocation();
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(MemoryConstants::pageSize64k, alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_NE(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress()))));
EXPECT_TRUE(alloc->isMemObjectsAllocationWithWritableFlags());
EXPECT_EQ(InternalMemoryType::deviceUnifiedMemory, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(alloc->getGpuAddress()))->memoryType);
EXPECT_EQ(AllocationType::globalSurface, alloc->getAllocationType());
EXPECT_FALSE(alloc->getDefaultGmm()->resourceParams.Flags.Info.NotLockable);
svmAllocsManager.freeSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress())));
}
TEST_F(AllocateGlobalSurfacePoolingDisabledTest, GivenNullSvmAllocsManagerWhenGlobalsAreExportedThenMemoryIsAllocatedAsNonSvmAllocation) {
WhiteBox<LinkerInput> linkerInputExportGlobalVariables;
WhiteBox<LinkerInput> linkerInputExportGlobalConstants;
linkerInputExportGlobalVariables.traits.exportsGlobalVariables = true;
linkerInputExportGlobalConstants.traits.exportsGlobalConstants = true;
std::vector<uint8_t> initData;
initData.resize(64, 7U);
std::unique_ptr<SharedPoolAllocation> globalSurface;
GraphicsAllocation *alloc{nullptr};
size_t expectedAlignedSize = alignUp(initData.size(), MemoryConstants::pageSize);
globalSurface.reset(allocateGlobalsSurface(nullptr, device, initData.size(), 0u, true /* constant */, &linkerInputExportGlobalConstants, initData.data()));
ASSERT_NE(nullptr, globalSurface);
alloc = globalSurface->getGraphicsAllocation();
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(expectedAlignedSize, alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(AllocationType::constantSurface, alloc->getAllocationType());
device.getMemoryManager()->freeGraphicsMemory(alloc);
globalSurface.reset(allocateGlobalsSurface(nullptr, device, initData.size(), 0u, true /* constant */, &linkerInputExportGlobalVariables, initData.data()));
ASSERT_NE(nullptr, globalSurface);
alloc = globalSurface->getGraphicsAllocation();
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(expectedAlignedSize, alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(AllocationType::constantSurface, alloc->getAllocationType());
device.getMemoryManager()->freeGraphicsMemory(alloc);
globalSurface.reset(allocateGlobalsSurface(nullptr, device, initData.size(), 0u, false /* constant */, &linkerInputExportGlobalConstants, initData.data()));
ASSERT_NE(nullptr, globalSurface);
alloc = globalSurface->getGraphicsAllocation();
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(expectedAlignedSize, alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(AllocationType::globalSurface, alloc->getAllocationType());
device.getMemoryManager()->freeGraphicsMemory(alloc);
globalSurface.reset(allocateGlobalsSurface(nullptr, device, initData.size(), 0u, false /* constant */, &linkerInputExportGlobalVariables, initData.data()));
ASSERT_NE(nullptr, globalSurface);
alloc = globalSurface->getGraphicsAllocation();
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(expectedAlignedSize, alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(AllocationType::globalSurface, alloc->getAllocationType());
device.getMemoryManager()->freeGraphicsMemory(alloc);
}
TEST(AllocateGlobalSurfaceTest, WhenGlobalsAreNotExportedAndAllocationFailsThenGracefullyReturnsNullptr) {
MockDevice device{};
auto memoryManager = std::make_unique<MockMemoryManager>(*device.getExecutionEnvironment());
memoryManager->failInAllocateWithSizeAndAlignment = true;
device.injectMemoryManager(memoryManager.release());
MockSVMAllocsManager mockSvmAllocsManager(device.getMemoryManager());
WhiteBox<LinkerInput> emptyLinkerInput;
std::vector<uint8_t> initData;
initData.resize(64, 7U);
std::unique_ptr<SharedPoolAllocation> globalSurface;
globalSurface.reset(allocateGlobalsSurface(&mockSvmAllocsManager, device, initData.size(), 0u, true /* constant */, nullptr /* linker input */, initData.data()));
EXPECT_EQ(nullptr, globalSurface);
globalSurface.reset(allocateGlobalsSurface(&mockSvmAllocsManager, device, initData.size(), 0u, false /* constant */, nullptr /* linker input */, initData.data()));
EXPECT_EQ(nullptr, globalSurface);
globalSurface.reset(allocateGlobalsSurface(&mockSvmAllocsManager, device, initData.size(), 0u, true /* constant */, &emptyLinkerInput, initData.data()));
EXPECT_EQ(nullptr, globalSurface);
globalSurface.reset(allocateGlobalsSurface(&mockSvmAllocsManager, device, initData.size(), 0u, false /* constant */, &emptyLinkerInput, initData.data()));
EXPECT_EQ(nullptr, globalSurface);
globalSurface.reset(allocateGlobalsSurface(nullptr /* svmAllocsManager */, device, initData.size(), 0u, true /* constant */, nullptr /* linker input */, initData.data()));
EXPECT_EQ(nullptr, globalSurface);
globalSurface.reset(allocateGlobalsSurface(nullptr /* svmAllocsManager */, device, initData.size(), 0u, false /* constant */, nullptr /* linker input */, initData.data()));
EXPECT_EQ(nullptr, globalSurface);
globalSurface.reset(allocateGlobalsSurface(nullptr /* svmAllocsManager */, device, initData.size(), 0u, true /* constant */, &emptyLinkerInput, initData.data()));
EXPECT_EQ(nullptr, globalSurface);
globalSurface.reset(allocateGlobalsSurface(nullptr /* svmAllocsManager */, device, initData.size(), 0u, false /* constant */, &emptyLinkerInput, initData.data()));
EXPECT_EQ(nullptr, globalSurface);
}
TEST(AllocateGlobalSurfaceTest, GivenAllocationInLocalMemoryWhichRequiresBlitterWhenAllocatingNonSvmAllocationThenBlitterIsUsed) {
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_t> size) -> BlitOperationResult {
blitsCounter++;
return BlitOperationResult::success;
};
VariableBackup<BlitHelperFunctions::BlitMemoryToAllocationFunc> blitMemoryToAllocationFuncBackup{
&BlitHelperFunctions::blitMemoryToAllocation, mockBlitMemoryToAllocation};
LocalMemoryAccessMode localMemoryAccessModes[] = {
LocalMemoryAccessMode::defaultMode,
LocalMemoryAccessMode::cpuAccessAllowed,
LocalMemoryAccessMode::cpuAccessDisallowed};
std::vector<uint8_t> initData;
initData.resize(64, 7U);
for (auto localMemoryAccessMode : localMemoryAccessModes) {
debugManager.flags.ForceLocalMemoryAccessMode.set(static_cast<int32_t>(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());
std::unique_ptr<SharedPoolAllocation> globalSurface = std::unique_ptr<SharedPoolAllocation>(allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), 0u, true /* constant */, nullptr /* linker input */, initData.data()));
ASSERT_NE(nullptr, globalSurface);
GraphicsAllocation *pAllocation{globalSurface->getGraphicsAllocation()};
ASSERT_NE(nullptr, pAllocation);
EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(pAllocation->getGpuAddress()))));
EXPECT_EQ(AllocationType::constantSurface, pAllocation->getAllocationType());
if (pAllocation->isAllocatedInLocalMemoryPool() && (localMemoryAccessMode == LocalMemoryAccessMode::cpuAccessDisallowed)) {
expectedBlitsCount++;
}
EXPECT_EQ(expectedBlitsCount, blitsCounter);
if (device.getConstantSurfacePoolAllocator().isPoolBuffer(pAllocation)) {
device.getConstantSurfacePoolAllocator().freeSharedAllocation(globalSurface.release());
} else {
device.getMemoryManager()->freeGraphicsMemory(pAllocation);
}
}
}
}
TEST_F(AllocateGlobalSurfacePoolingDisabledTest, whenAllocatingGlobalSurfaceWithNonZeroZeroInitSizeThenTransferOnlyInitDataToAllocation) {
WhiteBox<LinkerInput> emptyLinkerInput;
emptyLinkerInput.traits.exportsGlobalConstants = true;
std::vector<uint8_t> initData;
initData.resize(64, 7u);
std::fill(initData.begin() + 32, initData.end(), 16u); // this data should not be transferred
std::unique_ptr<SharedPoolAllocation> globalSurface;
GraphicsAllocation *alloc{nullptr};
size_t zeroInitSize = 32u;
size_t expectedAlignedSize = alignUp(initData.size(), MemoryConstants::pageSize);
globalSurface.reset(allocateGlobalsSurface(nullptr, device, initData.size(), zeroInitSize, true, &emptyLinkerInput, initData.data()));
ASSERT_NE(nullptr, globalSurface);
alloc = globalSurface->getGraphicsAllocation();
ASSERT_NE(nullptr, alloc);
EXPECT_EQ(expectedAlignedSize, alloc->getUnderlyingBufferSize());
auto dataPtr = reinterpret_cast<uint8_t *>(alloc->getUnderlyingBuffer());
EXPECT_EQ(0, memcmp(dataPtr, initData.data(), 32u));
EXPECT_NE(0, memcmp(dataPtr + 32, initData.data() + 32, 32u));
device.getMemoryManager()->freeGraphicsMemory(alloc);
}
TEST(AllocateGlobalSurfaceTest, whenAllocatingGlobalSurfaceWithZeroInitSizeGreaterThanZeroAndInitDataSizeSetToZeroThenDoNotTransferMemoryToAllocation) {
MockDevice device{};
auto memoryManager = std::make_unique<MockMemoryManager>(*device.getExecutionEnvironment());
device.injectMemoryManager(memoryManager.release());
ASSERT_EQ(0u, static_cast<MockMemoryManager *>(device.getMemoryManager())->copyMemoryToAllocationBanksCalled);
size_t totalSize = 64u, zeroInitSize = 64u;
std::unique_ptr<SharedPoolAllocation> globalSurface;
GraphicsAllocation *alloc{nullptr};
globalSurface.reset(allocateGlobalsSurface(nullptr, device, totalSize, zeroInitSize, true, nullptr, nullptr));
ASSERT_NE(nullptr, globalSurface);
alloc = globalSurface->getGraphicsAllocation();
ASSERT_NE(nullptr, alloc);
EXPECT_EQ(0u, static_cast<MockMemoryManager *>(device.getMemoryManager())->copyMemoryToAllocationBanksCalled);
if (device.getConstantSurfacePoolAllocator().isPoolBuffer(alloc)) {
device.getConstantSurfacePoolAllocator().freeSharedAllocation(globalSurface.release());
} else {
device.getMemoryManager()->freeGraphicsMemory(alloc);
}
}
struct AllocateGlobalSurfaceWithUsmPoolTest : public ::testing::Test {
void SetUp() override {
device.injectMemoryManager(new MockMemoryManager());
device.resetUsmConstantSurfaceAllocPool(new UsmMemAllocPool);
device.resetUsmGlobalSurfaceAllocPool(new UsmMemAllocPool);
mockProductHelper = new MockProductHelper;
device.getRootDeviceEnvironmentRef().productHelper.reset(mockProductHelper);
svmAllocsManager = std::make_unique<MockSVMAllocsManager>(device.getMemoryManager());
}
MockProductHelper *mockProductHelper{nullptr};
std::unique_ptr<MockSVMAllocsManager> svmAllocsManager;
WhiteBox<LinkerInput> linkerInputExportGlobalVariables;
WhiteBox<LinkerInput> linkerInputExportGlobalConstants;
MockDevice device{};
DebugManagerStateRestore restore;
};
TEST_F(AllocateGlobalSurfaceWithUsmPoolTest, GivenUsmAllocPoolAnd2MBLocalMemAlignmentDisabledThenGlobalSurfaceAllocationNotTakenFromUsmPool) {
mockProductHelper->is2MBLocalMemAlignmentEnabledResult = false;
linkerInputExportGlobalVariables.traits.exportsGlobalVariables = true;
linkerInputExportGlobalConstants.traits.exportsGlobalConstants = true;
std::vector<uint8_t> initData;
initData.resize(64, 7U);
std::unique_ptr<SharedPoolAllocation> globalSurface;
globalSurface.reset(allocateGlobalsSurface(svmAllocsManager.get(), device, initData.size(), 0u, true /* constant */, &linkerInputExportGlobalConstants, initData.data()));
ASSERT_NE(nullptr, globalSurface);
EXPECT_FALSE(device.getUsmConstantSurfaceAllocPool()->isInPool(reinterpret_cast<void *>(globalSurface->getGpuAddress())));
EXPECT_FALSE(globalSurface->isFromPool());
EXPECT_EQ(globalSurface->getGraphicsAllocation()->getUnderlyingBufferSize(), globalSurface->getSize());
EXPECT_EQ(0u, globalSurface->getOffset());
svmAllocsManager->freeSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(globalSurface->getGpuAddress())));
globalSurface.reset(allocateGlobalsSurface(svmAllocsManager.get(), device, initData.size(), 0u, false /* constant */, &linkerInputExportGlobalVariables, initData.data()));
ASSERT_NE(nullptr, globalSurface);
EXPECT_FALSE(device.getUsmGlobalSurfaceAllocPool()->isInPool(reinterpret_cast<void *>(globalSurface->getGpuAddress())));
EXPECT_FALSE(globalSurface->isFromPool());
EXPECT_EQ(globalSurface->getGraphicsAllocation()->getUnderlyingBufferSize(), globalSurface->getSize());
EXPECT_EQ(0u, globalSurface->getOffset());
svmAllocsManager->freeSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(globalSurface->getGpuAddress())));
}
TEST_F(AllocateGlobalSurfaceWithUsmPoolTest, GivenUsmAllocPoolAnd2MBLocalMemAlignmentEnabledThenGlobalSurfaceAllocationTakenFromUsmPool) {
mockProductHelper->is2MBLocalMemAlignmentEnabledResult = true;
linkerInputExportGlobalVariables.traits.exportsGlobalVariables = true;
linkerInputExportGlobalConstants.traits.exportsGlobalConstants = true;
std::vector<uint8_t> initData;
initData.resize(64, 7U);
{
std::unique_ptr<SharedPoolAllocation> constantSurface1;
std::unique_ptr<SharedPoolAllocation> constantSurface2;
constantSurface1.reset(allocateGlobalsSurface(svmAllocsManager.get(), device, initData.size(), 0u, true /* constant */, &linkerInputExportGlobalConstants, initData.data()));
ASSERT_NE(nullptr, constantSurface1);
EXPECT_TRUE(device.getUsmConstantSurfaceAllocPool()->isInPool(reinterpret_cast<void *>(constantSurface1->getGpuAddress())));
EXPECT_TRUE(constantSurface1->isFromPool());
EXPECT_NE(constantSurface1->getGraphicsAllocation()->getUnderlyingBufferSize(), constantSurface1->getSize());
EXPECT_EQ(0, memcmp(constantSurface1->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_TRUE(constantSurface1->getGraphicsAllocation()->isMemObjectsAllocationWithWritableFlags());
EXPECT_EQ(AllocationType::constantSurface, constantSurface1->getGraphicsAllocation()->getAllocationType());
constantSurface2.reset(allocateGlobalsSurface(svmAllocsManager.get(), device, initData.size(), 0u, true /* constant */, &linkerInputExportGlobalConstants, initData.data()));
ASSERT_NE(nullptr, constantSurface2);
EXPECT_TRUE(device.getUsmConstantSurfaceAllocPool()->isInPool(reinterpret_cast<void *>(constantSurface2->getGpuAddress())));
EXPECT_TRUE(constantSurface2->isFromPool());
EXPECT_NE(constantSurface2->getGraphicsAllocation()->getUnderlyingBufferSize(), constantSurface2->getSize());
EXPECT_EQ(0, memcmp(constantSurface2->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_TRUE(constantSurface2->getGraphicsAllocation()->isMemObjectsAllocationWithWritableFlags());
EXPECT_EQ(AllocationType::constantSurface, constantSurface2->getGraphicsAllocation()->getAllocationType());
EXPECT_EQ(constantSurface1->getGraphicsAllocation(), constantSurface2->getGraphicsAllocation());
EXPECT_EQ(constantSurface1->getSize(), constantSurface2->getSize());
EXPECT_NE(constantSurface1->getGpuAddress(), constantSurface2->getGpuAddress());
EXPECT_NE(constantSurface1->getOffset(), constantSurface2->getOffset());
}
{
std::unique_ptr<SharedPoolAllocation> globalSurface1;
std::unique_ptr<SharedPoolAllocation> globalSurface2;
globalSurface1.reset(allocateGlobalsSurface(svmAllocsManager.get(), device, initData.size(), 0u, false /* constant */, &linkerInputExportGlobalVariables, initData.data()));
ASSERT_NE(nullptr, globalSurface1);
EXPECT_TRUE(device.getUsmGlobalSurfaceAllocPool()->isInPool(reinterpret_cast<void *>(globalSurface1->getGpuAddress())));
EXPECT_TRUE(globalSurface1->isFromPool());
EXPECT_NE(globalSurface1->getGraphicsAllocation()->getUnderlyingBufferSize(), globalSurface1->getSize());
EXPECT_EQ(0, memcmp(globalSurface1->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_TRUE(globalSurface1->getGraphicsAllocation()->isMemObjectsAllocationWithWritableFlags());
EXPECT_EQ(AllocationType::globalSurface, globalSurface1->getGraphicsAllocation()->getAllocationType());
globalSurface2.reset(allocateGlobalsSurface(svmAllocsManager.get(), device, initData.size(), 0u, false /* constant */, &linkerInputExportGlobalVariables, initData.data()));
ASSERT_NE(nullptr, globalSurface2);
EXPECT_TRUE(device.getUsmGlobalSurfaceAllocPool()->isInPool(reinterpret_cast<void *>(globalSurface2->getGpuAddress())));
EXPECT_TRUE(globalSurface2->isFromPool());
EXPECT_NE(globalSurface2->getGraphicsAllocation()->getUnderlyingBufferSize(), globalSurface2->getSize());
EXPECT_EQ(0, memcmp(globalSurface2->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_TRUE(globalSurface2->getGraphicsAllocation()->isMemObjectsAllocationWithWritableFlags());
EXPECT_EQ(AllocationType::globalSurface, globalSurface2->getGraphicsAllocation()->getAllocationType());
EXPECT_EQ(globalSurface1->getGraphicsAllocation(), globalSurface2->getGraphicsAllocation());
EXPECT_EQ(globalSurface1->getSize(), globalSurface2->getSize());
EXPECT_NE(globalSurface1->getGpuAddress(), globalSurface2->getGpuAddress());
EXPECT_NE(globalSurface1->getOffset(), globalSurface2->getOffset());
}
}
TEST_F(AllocateGlobalSurfaceWithUsmPoolTest, givenPooledUSMAllocationWhenReusedChunkThenDataIsProperlyInitializedAndRestIsZeroed) {
mockProductHelper->is2MBLocalMemAlignmentEnabledResult = true;
linkerInputExportGlobalVariables.traits.exportsGlobalVariables = true;
constexpr size_t initSize = 32u;
constexpr size_t zeroInitSize = 32u;
constexpr size_t totalSize = initSize + zeroInitSize;
constexpr uint8_t initValue = 7u;
constexpr uint8_t dirtyValue = 9u;
std::vector<uint8_t> initData(initSize, initValue);
auto verifyAllocation = [&](SharedPoolAllocation *allocation) {
ASSERT_NE(nullptr, allocation);
EXPECT_TRUE(device.getUsmGlobalSurfaceAllocPool()->isInPool(
reinterpret_cast<void *>(allocation->getGpuAddress())));
EXPECT_NE(allocation->getGraphicsAllocation()->getUnderlyingBufferSize(),
allocation->getSize());
EXPECT_TRUE(allocation->getGraphicsAllocation()->isMemObjectsAllocationWithWritableFlags());
EXPECT_EQ(AllocationType::globalSurface,
allocation->getGraphicsAllocation()->getAllocationType());
};
std::unique_ptr<SharedPoolAllocation> globalSurface1;
std::unique_ptr<SharedPoolAllocation> globalSurface2;
// First allocation - new chunk from pool
globalSurface1.reset(allocateGlobalsSurface(svmAllocsManager.get(), device, totalSize, zeroInitSize, false, &linkerInputExportGlobalVariables, initData.data()));
verifyAllocation(globalSurface1.get());
EXPECT_EQ(0, memcmp(globalSurface1->getUnderlyingBuffer(), initData.data(), initSize));
// Dirty the chunk before returning to pool
std::memset(globalSurface1->getUnderlyingBuffer(), dirtyValue, globalSurface1->getSize());
device.getUsmGlobalSurfaceAllocPool()->freeSVMAlloc(reinterpret_cast<void *>(globalSurface1->getGpuAddress()), false);
// Second allocation - should reuse the same chunk
globalSurface2.reset(allocateGlobalsSurface(svmAllocsManager.get(), device, totalSize, zeroInitSize, false, &linkerInputExportGlobalVariables, initData.data()));
verifyAllocation(globalSurface2.get());
// Verify it's the same chunk
EXPECT_EQ(globalSurface1->getGraphicsAllocation(), globalSurface2->getGraphicsAllocation());
EXPECT_EQ(globalSurface1->getGpuAddress(), globalSurface2->getGpuAddress());
EXPECT_EQ(globalSurface1->getOffset(), globalSurface2->getOffset());
EXPECT_EQ(globalSurface1->getSize(), globalSurface2->getSize());
// Verify proper initialization: initData followed by zeros for entire chunk
std::vector<uint8_t> expectedData(globalSurface2->getSize(), 0);
std::memcpy(expectedData.data(), initData.data(), initSize);
EXPECT_EQ(0, memcmp(globalSurface2->getUnderlyingBuffer(), expectedData.data(), expectedData.size()));
}
TEST_F(AllocateGlobalSurfaceWithUsmPoolTest, givenPooledUSMAllocationWhenReusedChunkWithBssOnlyDataThenEntireChunkIsZeroed) {
mockProductHelper->is2MBLocalMemAlignmentEnabledResult = true;
linkerInputExportGlobalVariables.traits.exportsGlobalVariables = true;
constexpr size_t totalSize = 64u;
constexpr size_t zeroInitSize = totalSize; // BSS only - no init data
constexpr uint8_t dirtyValue = 9u;
auto verifyAllocation = [&](SharedPoolAllocation *allocation) {
ASSERT_NE(nullptr, allocation);
EXPECT_TRUE(device.getUsmGlobalSurfaceAllocPool()->isInPool(
reinterpret_cast<void *>(allocation->getGpuAddress())));
EXPECT_NE(allocation->getGraphicsAllocation()->getUnderlyingBufferSize(),
allocation->getSize());
EXPECT_TRUE(allocation->getGraphicsAllocation()->isMemObjectsAllocationWithWritableFlags());
EXPECT_EQ(AllocationType::globalSurface,
allocation->getGraphicsAllocation()->getAllocationType());
};
std::unique_ptr<SharedPoolAllocation> globalSurface1;
std::unique_ptr<SharedPoolAllocation> globalSurface2;
// First allocation - BSS only (no init data)
globalSurface1.reset(allocateGlobalsSurface(svmAllocsManager.get(), device, totalSize, zeroInitSize, false, &linkerInputExportGlobalVariables, nullptr));
verifyAllocation(globalSurface1.get());
// Verify initial allocation is zeroed
std::vector<uint8_t> expectedZeros(globalSurface1->getSize(), 0);
EXPECT_EQ(0, memcmp(globalSurface1->getUnderlyingBuffer(), expectedZeros.data(), expectedZeros.size()));
// Dirty the chunk before returning to pool
std::memset(globalSurface1->getUnderlyingBuffer(), dirtyValue, globalSurface1->getSize());
device.getUsmGlobalSurfaceAllocPool()->freeSVMAlloc(reinterpret_cast<void *>(globalSurface1->getGpuAddress()), false);
// Second allocation - should reuse the same chunk
globalSurface2.reset(allocateGlobalsSurface(svmAllocsManager.get(), device, totalSize, zeroInitSize, false, &linkerInputExportGlobalVariables, nullptr));
verifyAllocation(globalSurface2.get());
// Verify it's the same chunk
EXPECT_EQ(globalSurface1->getGraphicsAllocation(), globalSurface2->getGraphicsAllocation());
EXPECT_EQ(globalSurface1->getGpuAddress(), globalSurface2->getGpuAddress());
EXPECT_EQ(globalSurface1->getOffset(), globalSurface2->getOffset());
EXPECT_EQ(globalSurface1->getSize(), globalSurface2->getSize());
// Verify entire chunk is zeroed (no dirty data from previous use)
EXPECT_EQ(0, memcmp(globalSurface2->getUnderlyingBuffer(), expectedZeros.data(), expectedZeros.size()));
}
TEST_F(AllocateGlobalSurfaceWithUsmPoolTest, givenPooledUSMAllocationWhenOnlyInitDataWithoutBssSectionThenMemsetAllocationIsNotCalled) {
mockProductHelper->isBlitCopyRequiredForLocalMemoryResult = false;
mockProductHelper->is2MBLocalMemAlignmentEnabledResult = true;
linkerInputExportGlobalVariables.traits.exportsGlobalVariables = true;
constexpr size_t initSize = 64u;
constexpr size_t zeroInitSize = 0u;
constexpr size_t totalSize = initSize + zeroInitSize;
constexpr uint8_t initValue = 7u;
std::vector<uint8_t> initData(initSize, initValue);
auto mockMemoryManager = static_cast<MockMemoryManager *>(device.getMemoryManager());
mockMemoryManager->memsetAllocationCalled = 0;
auto globalSurface = std::unique_ptr<SharedPoolAllocation>(allocateGlobalsSurface(svmAllocsManager.get(), device, totalSize, zeroInitSize, false, &linkerInputExportGlobalVariables, initData.data()));
ASSERT_NE(nullptr, globalSurface);
EXPECT_EQ(0u, mockMemoryManager->memsetAllocationCalled);
}
TEST_F(AllocateGlobalSurfaceWithUsmPoolTest, givenPooledUSMAllocationWhenInitDataAndBssSectionThenMemsetAllocationIsCalledOnceForBssSection) {
mockProductHelper->isBlitCopyRequiredForLocalMemoryResult = false;
mockProductHelper->is2MBLocalMemAlignmentEnabledResult = true;
linkerInputExportGlobalVariables.traits.exportsGlobalVariables = true;
constexpr size_t initSize = 32u;
constexpr size_t zeroInitSize = 32u;
constexpr size_t totalSize = initSize + zeroInitSize;
constexpr uint8_t initValue = 7u;
std::vector<uint8_t> initData(initSize, initValue);
auto mockMemoryManager = static_cast<MockMemoryManager *>(device.getMemoryManager());
mockMemoryManager->memsetAllocationCalled = 0;
auto globalSurface = std::unique_ptr<SharedPoolAllocation>(allocateGlobalsSurface(svmAllocsManager.get(), device, totalSize, zeroInitSize, false, &linkerInputExportGlobalVariables, initData.data()));
ASSERT_NE(nullptr, globalSurface);
EXPECT_EQ(1u, mockMemoryManager->memsetAllocationCalled);
}
TEST_F(AllocateGlobalSurfaceWithUsmPoolTest, Given2MBLocalMemAlignmentEnabledButUsmPoolInitializeFailsThenDoNotUseUsmPool) {
mockProductHelper->is2MBLocalMemAlignmentEnabledResult = true;
auto usmConstantSurfaceAllocPool = new MockUsmMemAllocPool;
auto usmGlobalSurfaceAllocPool = new MockUsmMemAllocPool;
device.resetUsmConstantSurfaceAllocPool(usmConstantSurfaceAllocPool);
device.resetUsmGlobalSurfaceAllocPool(usmGlobalSurfaceAllocPool);
usmConstantSurfaceAllocPool->callBaseInitialize = false;
usmConstantSurfaceAllocPool->initializeResult = false;
usmGlobalSurfaceAllocPool->callBaseInitialize = false;
usmGlobalSurfaceAllocPool->initializeResult = false;
linkerInputExportGlobalVariables.traits.exportsGlobalVariables = true;
linkerInputExportGlobalConstants.traits.exportsGlobalConstants = true;
std::vector<uint8_t> initData;
initData.resize(64, 7U);
std::unique_ptr<SharedPoolAllocation> globalSurface;
globalSurface.reset(allocateGlobalsSurface(svmAllocsManager.get(), device, initData.size(), 0u, true /* constant */, &linkerInputExportGlobalConstants, initData.data()));
ASSERT_NE(nullptr, globalSurface);
EXPECT_FALSE(device.getUsmConstantSurfaceAllocPool()->isInPool(reinterpret_cast<void *>(globalSurface->getGpuAddress())));
svmAllocsManager->freeSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(globalSurface->getGpuAddress())));
globalSurface.reset(allocateGlobalsSurface(svmAllocsManager.get(), device, initData.size(), 0u, false /* constant */, &linkerInputExportGlobalVariables, initData.data()));
ASSERT_NE(nullptr, globalSurface);
EXPECT_FALSE(device.getUsmGlobalSurfaceAllocPool()->isInPool(reinterpret_cast<void *>(globalSurface->getGpuAddress())));
svmAllocsManager->freeSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(globalSurface->getGpuAddress())));
}
TEST_F(AllocateGlobalSurfaceWithUsmPoolTest, Given2MBLocalMemAlignmentEnabledButAllocatingFromUsmPoolFailsThenDoNotUseUsmPool) {
mockProductHelper->is2MBLocalMemAlignmentEnabledResult = true;
auto usmConstantSurfaceAllocPool = new MockUsmMemAllocPool;
auto usmGlobalSurfaceAllocPool = new MockUsmMemAllocPool;
device.resetUsmConstantSurfaceAllocPool(usmConstantSurfaceAllocPool);
device.resetUsmGlobalSurfaceAllocPool(usmGlobalSurfaceAllocPool);
usmConstantSurfaceAllocPool->callBaseCreateUnifiedMemoryAllocation = false;
usmConstantSurfaceAllocPool->createUnifiedMemoryAllocationResult = nullptr;
usmGlobalSurfaceAllocPool->callBaseCreateUnifiedMemoryAllocation = false;
usmGlobalSurfaceAllocPool->createUnifiedMemoryAllocationResult = nullptr;
linkerInputExportGlobalVariables.traits.exportsGlobalVariables = true;
linkerInputExportGlobalConstants.traits.exportsGlobalConstants = true;
std::vector<uint8_t> initData;
initData.resize(64, 7U);
std::unique_ptr<SharedPoolAllocation> globalSurface;
globalSurface.reset(allocateGlobalsSurface(svmAllocsManager.get(), device, initData.size(), 0u, true /* constant */, &linkerInputExportGlobalConstants, initData.data()));
ASSERT_NE(nullptr, globalSurface);
EXPECT_FALSE(device.getUsmConstantSurfaceAllocPool()->isInPool(reinterpret_cast<void *>(globalSurface->getGpuAddress())));
svmAllocsManager->freeSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(globalSurface->getGpuAddress())));
globalSurface.reset(allocateGlobalsSurface(svmAllocsManager.get(), device, initData.size(), 0u, false /* constant */, &linkerInputExportGlobalVariables, initData.data()));
ASSERT_NE(nullptr, globalSurface);
EXPECT_FALSE(device.getUsmGlobalSurfaceAllocPool()->isInPool(reinterpret_cast<void *>(globalSurface->getGpuAddress())));
svmAllocsManager->freeSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(globalSurface->getGpuAddress())));
}
struct AllocateGlobalSurfaceWithGenericPoolTest : public ::testing::Test {
void SetUp() override {
device.injectMemoryManager(new MockMemoryManager());
mockProductHelper = new MockProductHelper;
device.getRootDeviceEnvironmentRef().productHelper.reset(mockProductHelper);
mockProductHelper->is2MBLocalMemAlignmentEnabledResult = true;
}
MockProductHelper *mockProductHelper{nullptr};
WhiteBox<LinkerInput> linkerInput;
MockDevice device{};
DebugManagerStateRestore restore;
};
TEST_F(AllocateGlobalSurfaceWithGenericPoolTest, Given2MBLocalMemAlignmentDisabledThenGlobalSurfaceAllocationNotTakenFromGenericPool) {
mockProductHelper->is2MBLocalMemAlignmentEnabledResult = false;
std::vector<uint8_t> initData;
initData.resize(64, 7U);
std::unique_ptr<SharedPoolAllocation> globalSurface;
size_t expectedAlignedSize = alignUp(initData.size(), MemoryConstants::pageSize);
for (auto isConstant : {true, false}) {
auto expectedAllocType = isConstant ? AllocationType::constantSurface : AllocationType::globalSurface;
globalSurface.reset(allocateGlobalsSurface(nullptr, device, initData.size(), 0u, isConstant /* constant */, &linkerInput, initData.data()));
ASSERT_NE(nullptr, globalSurface);
EXPECT_FALSE(globalSurface->isFromPool());
EXPECT_EQ(expectedAlignedSize, globalSurface->getGraphicsAllocation()->getUnderlyingBufferSize());
EXPECT_EQ(globalSurface->getGraphicsAllocation()->getUnderlyingBufferSize(), globalSurface->getSize());
EXPECT_EQ(0u, globalSurface->getOffset());
EXPECT_EQ(0, memcmp(globalSurface->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(expectedAllocType, globalSurface->getGraphicsAllocation()->getAllocationType());
EXPECT_FALSE(device.getGlobalSurfacePoolAllocator().isPoolBuffer(globalSurface->getGraphicsAllocation()));
EXPECT_FALSE(device.getConstantSurfacePoolAllocator().isPoolBuffer(globalSurface->getGraphicsAllocation()));
device.getMemoryManager()->freeGraphicsMemory(globalSurface->getGraphicsAllocation());
}
}
TEST_F(AllocateGlobalSurfaceWithGenericPoolTest, Given2MBLocalMemAlignmentEnabledThenGlobalSurfaceAllocationTakenFromGenericPool) {
std::vector<uint8_t> initData;
initData.resize(64, 7U);
for (auto isConstant : {true, false}) {
auto expectedAllocType = isConstant ? AllocationType::constantSurface : AllocationType::globalSurface;
std::unique_ptr<SharedPoolAllocation> globalSurface1;
std::unique_ptr<SharedPoolAllocation> globalSurface2;
globalSurface1.reset(allocateGlobalsSurface(nullptr, device, initData.size(), 0u, isConstant /* constant */, &linkerInput, initData.data()));
ASSERT_NE(nullptr, globalSurface1);
EXPECT_TRUE(globalSurface1->isFromPool());
EXPECT_NE(globalSurface1->getGraphicsAllocation()->getUnderlyingBufferSize(), globalSurface1->getSize());
EXPECT_EQ(0, memcmp(globalSurface1->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(expectedAllocType, globalSurface1->getGraphicsAllocation()->getAllocationType());
globalSurface2.reset(allocateGlobalsSurface(nullptr, device, initData.size(), 0u, isConstant /* constant */, &linkerInput, initData.data()));
ASSERT_NE(nullptr, globalSurface2);
EXPECT_TRUE(globalSurface2->isFromPool());
EXPECT_NE(globalSurface2->getGraphicsAllocation()->getUnderlyingBufferSize(), globalSurface2->getSize());
EXPECT_EQ(0, memcmp(globalSurface2->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(expectedAllocType, globalSurface2->getGraphicsAllocation()->getAllocationType());
// Both allocations should come from the same pool
EXPECT_EQ(globalSurface1->getGraphicsAllocation(), globalSurface2->getGraphicsAllocation());
EXPECT_EQ(globalSurface1->getSize(), globalSurface2->getSize());
EXPECT_NE(globalSurface1->getGpuAddress(), globalSurface2->getGpuAddress());
EXPECT_NE(globalSurface1->getOffset(), globalSurface2->getOffset());
if (isConstant) {
EXPECT_TRUE(device.getConstantSurfacePoolAllocator().isPoolBuffer(globalSurface1->getGraphicsAllocation()));
EXPECT_TRUE(device.getConstantSurfacePoolAllocator().isPoolBuffer(globalSurface2->getGraphicsAllocation()));
device.getConstantSurfacePoolAllocator().freeSharedAllocation(globalSurface1.release());
device.getConstantSurfacePoolAllocator().freeSharedAllocation(globalSurface2.release());
} else {
EXPECT_TRUE(device.getGlobalSurfacePoolAllocator().isPoolBuffer(globalSurface1->getGraphicsAllocation()));
EXPECT_TRUE(device.getGlobalSurfacePoolAllocator().isPoolBuffer(globalSurface2->getGraphicsAllocation()));
device.getGlobalSurfacePoolAllocator().freeSharedAllocation(globalSurface1.release());
device.getGlobalSurfacePoolAllocator().freeSharedAllocation(globalSurface2.release());
}
}
}
TEST_F(AllocateGlobalSurfaceWithGenericPoolTest, givenPooledAllocationWhenDataIsInitializedThenNoCorruptionOccurs) {
constexpr size_t initSize = 32u;
constexpr size_t zeroInitSize = 32u;
constexpr size_t totalSize = initSize + zeroInitSize;
constexpr uint8_t initValue = 7u;
std::vector<uint8_t> initData(initSize, initValue);
auto verifyAllocation = [&](SharedPoolAllocation *allocation) {
ASSERT_NE(nullptr, allocation);
EXPECT_TRUE(allocation->isFromPool());
EXPECT_NE(allocation->getGraphicsAllocation()->getUnderlyingBufferSize(),
allocation->getSize());
EXPECT_EQ(AllocationType::globalSurface,
allocation->getGraphicsAllocation()->getAllocationType());
};
for (int i = 0; i < 3; ++i) {
auto globalSurface = allocateGlobalsSurface(nullptr, device, totalSize, zeroInitSize,
false, &linkerInput, initData.data());
verifyAllocation(globalSurface);
// Verify proper initialization: initData followed by zeros
std::vector<uint8_t> expectedData(totalSize, 0);
std::memcpy(expectedData.data(), initData.data(), initSize);
EXPECT_EQ(0, memcmp(globalSurface->getUnderlyingBuffer(), expectedData.data(), totalSize));
device.getGlobalSurfacePoolAllocator().freeSharedAllocation(globalSurface);
}
}
TEST_F(AllocateGlobalSurfaceWithGenericPoolTest, givenPooledAllocationWithBssOnlyWhenAllocatedMultipleTimesThenAlwaysZeroed) {
constexpr size_t totalSize = 64u;
constexpr size_t zeroInitSize = totalSize;
std::vector<uint8_t> expectedZeros(totalSize, 0);
for (int i = 0; i < 3; ++i) {
auto constantSurface = allocateGlobalsSurface(nullptr, device, totalSize, zeroInitSize,
true, &linkerInput, nullptr);
ASSERT_NE(nullptr, constantSurface);
EXPECT_TRUE(constantSurface->isFromPool());
// Verify entire allocation is zeroed
EXPECT_EQ(0, memcmp(constantSurface->getUnderlyingBuffer(), expectedZeros.data(), totalSize));
device.getConstantSurfacePoolAllocator().freeSharedAllocation(constantSurface);
}
}
TEST_F(AllocateGlobalSurfaceWithGenericPoolTest, givenPooledAllocationWhenOnlyInitDataWithoutBssSectionThenMemsetAllocationIsNotCalled) {
mockProductHelper->isBlitCopyRequiredForLocalMemoryResult = false;
constexpr size_t initSize = 64u;
constexpr size_t zeroInitSize = 0u;
constexpr size_t totalSize = initSize + zeroInitSize;
constexpr uint8_t initValue = 7u;
std::vector<uint8_t> initData(initSize, initValue);
auto mockMemoryManager = static_cast<MockMemoryManager *>(device.getMemoryManager());
mockMemoryManager->memsetAllocationCalled = 0;
auto globalSurface = std::unique_ptr<SharedPoolAllocation>(allocateGlobalsSurface(nullptr, device, totalSize, zeroInitSize, false, &linkerInput, initData.data()));
ASSERT_NE(nullptr, globalSurface);
EXPECT_EQ(0u, mockMemoryManager->memsetAllocationCalled);
device.getGlobalSurfacePoolAllocator().freeSharedAllocation(globalSurface.release());
}
TEST_F(AllocateGlobalSurfaceWithGenericPoolTest, GivenAllocationExceedsMaxSizeThenFallbackToDirectAllocation) {
for (auto isConstant : {false, true}) {
auto expectedAllocType = isConstant ? AllocationType::constantSurface : AllocationType::globalSurface;
size_t oversizedAllocation = isConstant ? ConstantSurfacePoolTraits::maxAllocationSize : GlobalSurfacePoolTraits::maxAllocationSize;
oversizedAllocation += 1;
std::vector<uint8_t> initData(oversizedAllocation, 7u);
auto globalSurface = std::unique_ptr<SharedPoolAllocation>(allocateGlobalsSurface(nullptr, device, oversizedAllocation, 0u, isConstant, &linkerInput, initData.data()));
ASSERT_NE(nullptr, globalSurface);
EXPECT_FALSE(globalSurface->isFromPool());
EXPECT_EQ(0u, globalSurface->getOffset());
EXPECT_EQ(expectedAllocType, globalSurface->getGraphicsAllocation()->getAllocationType());
EXPECT_FALSE(device.getConstantSurfacePoolAllocator().isPoolBuffer(globalSurface->getGraphicsAllocation()));
EXPECT_FALSE(device.getGlobalSurfacePoolAllocator().isPoolBuffer(globalSurface->getGraphicsAllocation()));
device.getMemoryManager()->freeGraphicsMemory(globalSurface->getGraphicsAllocation());
}
}