mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-30 18:37:46 +08:00
840 lines
47 KiB
C++
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());
|
|
}
|
|
} |