diff --git a/shared/source/os_interface/linux/drm_memory_manager.cpp b/shared/source/os_interface/linux/drm_memory_manager.cpp index 7e0d16c89e..1a00d22505 100644 --- a/shared/source/os_interface/linux/drm_memory_manager.cpp +++ b/shared/source/os_interface/linux/drm_memory_manager.cpp @@ -27,6 +27,7 @@ #include "shared/source/memory_manager/allocation_properties.h" #include "shared/source/memory_manager/gfx_partition.h" #include "shared/source/memory_manager/host_ptr_manager.h" +#include "shared/source/memory_manager/local_memory_usage.h" #include "shared/source/memory_manager/memory_banks.h" #include "shared/source/memory_manager/memory_pool.h" #include "shared/source/memory_manager/multi_graphics_allocation.h" @@ -352,6 +353,30 @@ void DrmMemoryManager::emitPinningRequest(BufferObject *bo, const AllocationData StorageInfo DrmMemoryManager::createStorageInfoFromProperties(const AllocationProperties &properties) { auto storageInfo{MemoryManager::createStorageInfoFromProperties(properties)}; + auto *memoryInfo = getDrm(properties.rootDeviceIndex).getMemoryInfo(); + + if (memoryInfo == nullptr || localMemorySupported[properties.rootDeviceIndex] == false) { + return storageInfo; + } + + const auto &localMemoryRegions{memoryInfo->getLocalMemoryRegions()}; + DEBUG_BREAK_IF(localMemoryRegions.empty()); + + DeviceBitfield allMemoryBanks{0b0}; + for (auto i = 0u; i < localMemoryRegions.size(); ++i) { + if ((properties.subDevicesBitfield & localMemoryRegions[i].tilesMask).any()) { + allMemoryBanks.set(i); + } + } + if (allMemoryBanks.none()) { + return storageInfo; + } + + DeviceBitfield preferredMemoryBanks{storageInfo.memoryBanks}; + if (localMemoryRegions.size() == 1u) { + preferredMemoryBanks = allMemoryBanks; + } + storageInfo.memoryBanks = computeStorageInfoMemoryBanks(properties, preferredMemoryBanks, allMemoryBanks); return storageInfo; } diff --git a/shared/test/common/mocks/linux/mock_drm_memory_manager.h b/shared/test/common/mocks/linux/mock_drm_memory_manager.h index b15b3caecb..dcce0359e2 100644 --- a/shared/test/common/mocks/linux/mock_drm_memory_manager.h +++ b/shared/test/common/mocks/linux/mock_drm_memory_manager.h @@ -51,6 +51,7 @@ class TestedDrmMemoryManager : public MemoryManagerCreate { using DrmMemoryManager::createGraphicsAllocation; using DrmMemoryManager::createMultiHostAllocation; using DrmMemoryManager::createSharedUnifiedMemoryAllocation; + using DrmMemoryManager::createStorageInfoFromProperties; using DrmMemoryManager::eraseSharedBoHandleWrapper; using DrmMemoryManager::eraseSharedBufferObject; using DrmMemoryManager::getBOTypeFromPatIndex; @@ -89,6 +90,10 @@ class TestedDrmMemoryManager : public MemoryManagerCreate { using MemoryManager::heapAssigners; using MemoryManager::localMemorySupported; + StorageInfo createStorageInfoFromPropertiesGeneric(const AllocationProperties &properties) { + return MemoryManager::createStorageInfoFromProperties(properties); + } + TestedDrmMemoryManager(ExecutionEnvironment &executionEnvironment); TestedDrmMemoryManager(bool enableLocalMemory, bool allowForcePin, @@ -165,9 +170,15 @@ class TestedDrmMemoryManager : public MemoryManagerCreate { } ADDMETHOD(isLimitedRange, bool, true, false, (uint32_t rootDeviceIndex), (rootDeviceIndex)); + DeviceBitfield computeStorageInfoMemoryBanks(const AllocationProperties &properties, DeviceBitfield preferredBank, DeviceBitfield allBanks) override { + ++computeStorageInfoMemoryBanksCalled; + return MemoryManager::computeStorageInfoMemoryBanks(properties, preferredBank, allBanks); + } + uint32_t acquireGpuRangeCalledTimes = 0u; uint32_t acquireGpuRangeWithCustomAlignmenCalledTimes = 0u; size_t acquireGpuRangeWithCustomAlignmenPassedAlignment = 0u; + size_t computeStorageInfoMemoryBanksCalled = 0u; ExecutionEnvironment *executionEnvironment = nullptr; protected: diff --git a/shared/test/common/os_interface/linux/device_command_stream_fixture.h b/shared/test/common/os_interface/linux/device_command_stream_fixture.h index 003327de31..9c3943e06f 100644 --- a/shared/test/common/os_interface/linux/device_command_stream_fixture.h +++ b/shared/test/common/os_interface/linux/device_command_stream_fixture.h @@ -6,6 +6,7 @@ */ #pragma once +#include "shared/source/helpers/driver_model_type.h" #include "shared/source/helpers/hw_info.h" #include "shared/source/os_interface/linux/drm_memory_manager.h" #include "shared/source/os_interface/linux/drm_neo.h" @@ -97,6 +98,8 @@ class DrmMockTime : public DrmMockSuccess { class DrmMockCustom : public Drm { public: + static constexpr NEO::DriverModelType driverModelType = NEO::DriverModelType::drm; + using Drm::bindAvailable; using Drm::cacheInfo; using Drm::checkToDisableScratchPage; diff --git a/shared/test/common/os_interface/linux/drm_memory_manager_fixture.cpp b/shared/test/common/os_interface/linux/drm_memory_manager_fixture.cpp index 004878f1ea..571db6d9d2 100644 --- a/shared/test/common/os_interface/linux/drm_memory_manager_fixture.cpp +++ b/shared/test/common/os_interface/linux/drm_memory_manager_fixture.cpp @@ -13,6 +13,7 @@ #include "shared/test/common/mocks/linux/mock_drm_memory_manager.h" #include "shared/test/common/mocks/mock_builtins.h" #include "shared/test/common/mocks/mock_device.h" +#include "shared/test/common/os_interface/linux/drm_mock_memory_info.h" #include "shared/test/common/os_interface/linux/sys_calls_linux_ult.h" #include "hw_cmds_default.h" @@ -112,7 +113,10 @@ void DrmMemoryManagerWithLocalMemoryFixture::setUp() { MemoryManagementFixture::setUp(); executionEnvironment = MockDevice::prepareExecutionEnvironment(defaultHwInfo.get(), numRootDevices - 1); - DrmMemoryManagerFixture::setUp(new DrmMockCustom(*executionEnvironment->rootDeviceEnvironments[0]), true); + auto drmMock = new DrmMockCustom{*executionEnvironment->rootDeviceEnvironments[1]}; + drmMock->memoryInfo.reset(new MockMemoryInfo{*drmMock}); + DrmMemoryManagerFixture::setUp(drmMock, true); + drmMock->reset(); } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) void DrmMemoryManagerWithLocalMemoryFixture::tearDown() { DrmMemoryManagerFixture::tearDown(); diff --git a/shared/test/common/os_interface/linux/drm_memory_manager_prelim_fixtures.h b/shared/test/common/os_interface/linux/drm_memory_manager_prelim_fixtures.h index 8f1944656d..db72553a6a 100644 --- a/shared/test/common/os_interface/linux/drm_memory_manager_prelim_fixtures.h +++ b/shared/test/common/os_interface/linux/drm_memory_manager_prelim_fixtures.h @@ -103,6 +103,7 @@ class DrmMemoryManagerLocalMemoryWithCustomPrelimMockTest : public ::testing::Te executionEnvironment->rootDeviceEnvironments[0]->setHwInfoAndInitHelpers(defaultHwInfo.get()); mock = new DrmMockCustomPrelim(*executionEnvironment->rootDeviceEnvironments[0]); + mock->memoryInfo.reset(new MockMemoryInfo{*mock}); executionEnvironment->rootDeviceEnvironments[0]->osInterface = std::make_unique(); executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr(mock)); diff --git a/shared/test/common/os_interface/linux/drm_mock_memory_info.h b/shared/test/common/os_interface/linux/drm_mock_memory_info.h index 3f76bbfb30..504a0f18d4 100644 --- a/shared/test/common/os_interface/linux/drm_mock_memory_info.h +++ b/shared/test/common/os_interface/linux/drm_mock_memory_info.h @@ -18,6 +18,8 @@ const std::vector memoryRegions = { {{drm_i915_gem_memory_class::I915_MEMORY_CLASS_DEVICE, 0}, 8 * MemoryConstants::gigaByte, 0}}; struct MockMemoryInfo : public NEO::MemoryInfo { + using NEO::MemoryInfo::localMemoryRegions; + MockMemoryInfo(const NEO::Drm &drm) : MemoryInfo(memoryRegions, drm) {} }; diff --git a/shared/test/unit_test/os_interface/linux/drm_memory_manager_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_memory_manager_tests.cpp index bb3096c146..d2a3de502a 100644 --- a/shared/test/unit_test/os_interface/linux/drm_memory_manager_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_memory_manager_tests.cpp @@ -34,6 +34,7 @@ #include "shared/test/common/mocks/mock_host_ptr_manager.h" #include "shared/test/common/os_interface/linux/drm_memory_manager_fixture.h" #include "shared/test/common/os_interface/linux/drm_mock_cache_info.h" +#include "shared/test/common/os_interface/linux/drm_mock_memory_info.h" #include "shared/test/common/os_interface/linux/sys_calls_linux_ult.h" #include "shared/test/common/test_macros/hw_test.h" @@ -5202,6 +5203,83 @@ TEST_F(DrmMemoryManagerWithLocalMemoryTest, givenDrmMemoryManagerWithLocalMemory memoryManager->unlockResource(&drmAllocation); } +TEST_F(DrmMemoryManagerWithLocalMemoryTest, givenSingleLocalMemoryWhenParticularSubdeviceIndicatedThenCorrectBankIsSelected) { + auto *memoryInfo = static_cast(mock->memoryInfo.get()); + auto &localMemoryRegions = memoryInfo->localMemoryRegions; + localMemoryRegions.resize(1U); + localMemoryRegions[0].tilesMask = 0b11; + + AllocationProperties properties{1, true, 4096, AllocationType::buffer, false, {}}; + properties.subDevicesBitfield = 0b10; + + memoryManager->computeStorageInfoMemoryBanksCalled = 0U; + auto storageInfo = memoryManager->createStorageInfoFromProperties(properties); + + constexpr auto expectedMemoryBanks = 0b01; + EXPECT_EQ(storageInfo.memoryBanks, expectedMemoryBanks); + EXPECT_EQ(memoryManager->computeStorageInfoMemoryBanksCalled, 2UL); +} + +TEST_F(DrmMemoryManagerWithLocalMemoryTest, givenSingleLocalMemoryWhenAllSubdevicesIndicatedThenCorrectBankIsSelected) { + auto *memoryInfo = static_cast(mock->memoryInfo.get()); + auto &localMemoryRegions = memoryInfo->localMemoryRegions; + localMemoryRegions.resize(1U); + localMemoryRegions[0].tilesMask = 0b11; + + AllocationProperties properties{1, true, 4096, AllocationType::buffer, false, {}}; + properties.subDevicesBitfield = 0b11; + + memoryManager->computeStorageInfoMemoryBanksCalled = 0U; + auto storageInfo = memoryManager->createStorageInfoFromProperties(properties); + + constexpr auto expectedMemoryBanks = 0b01; + EXPECT_EQ(storageInfo.memoryBanks, expectedMemoryBanks); + EXPECT_EQ(memoryManager->computeStorageInfoMemoryBanksCalled, 2UL); +} + +TEST_F(DrmMemoryManagerWithLocalMemoryTest, givenMultipleLocalMemoryRegionsWhenParticularSubdeviceIndicatedThenItIsSelected) { + auto *memoryInfo = static_cast(mock->memoryInfo.get()); + auto &localMemoryRegions = memoryInfo->localMemoryRegions; + constexpr auto leastOccupiedBankBitPosition = 1u; + debugManager.flags.OverrideLeastOccupiedBank.set(leastOccupiedBankBitPosition); + + localMemoryRegions.resize(2U); + localMemoryRegions[0].tilesMask = 0b01; + localMemoryRegions[1].tilesMask = 0b10; + + AllocationProperties properties{1, true, 4096, AllocationType::buffer, false, {}}; + properties.subDevicesBitfield = 0b10; + const auto expectedMemoryBanks = properties.subDevicesBitfield; + + memoryManager->computeStorageInfoMemoryBanksCalled = 0U; + auto storageInfo = memoryManager->createStorageInfoFromProperties(properties); + + EXPECT_EQ(storageInfo.memoryBanks, expectedMemoryBanks); + EXPECT_EQ(memoryManager->computeStorageInfoMemoryBanksCalled, 2UL); +} + +TEST_F(DrmMemoryManagerWithLocalMemoryTest, givenMultipleLocalMemoryRegionsWhenAllSubdevicesIndicatedThenTheLeastOccuppiedBankIsSelected) { + auto *memoryInfo = static_cast(mock->memoryInfo.get()); + auto &localMemoryRegions = memoryInfo->localMemoryRegions; + constexpr auto leastOccupiedBankBitPosition = 1u; + debugManager.flags.OverrideLeastOccupiedBank.set(leastOccupiedBankBitPosition); + + localMemoryRegions.resize(2U); + localMemoryRegions[0].tilesMask = 0b01; + localMemoryRegions[1].tilesMask = 0b10; + + AllocationProperties properties{1, true, 4096, AllocationType::buffer, false, {}}; + properties.subDevicesBitfield = 0b11; + + const auto expectedMemoryBanks = memoryManager->createStorageInfoFromPropertiesGeneric(properties).memoryBanks; + + memoryManager->computeStorageInfoMemoryBanksCalled = 0U; + auto storageInfo = memoryManager->createStorageInfoFromProperties(properties); + + EXPECT_EQ(storageInfo.memoryBanks, expectedMemoryBanks); + EXPECT_EQ(memoryManager->computeStorageInfoMemoryBanksCalled, 2UL); +} + using DrmMemoryManagerTest = Test; TEST_F(DrmMemoryManagerTest, givenDrmMemoryManagerWhenCopyMemoryToAllocationThenAllocationIsFilledWithCorrectData) {