diff --git a/level_zero/core/source/device/device_imp.cpp b/level_zero/core/source/device/device_imp.cpp index 43778bd644..3afe580017 100644 --- a/level_zero/core/source/device/device_imp.cpp +++ b/level_zero/core/source/device/device_imp.cpp @@ -56,13 +56,21 @@ void DeviceImp::setDriverHandle(DriverHandle *driverHandle) { } ze_result_t DeviceImp::canAccessPeer(ze_device_handle_t hPeerDevice, ze_bool_t *value) { - *value = false; - if (NEO::DebugManager.flags.CreateMultipleRootDevices.get() > 0) { - *value = true; - } - if (NEO::DebugManager.flags.CreateMultipleSubDevices.get() > 0) { - *value = true; + *value = true; + + DeviceImp *pPeerDevice = reinterpret_cast(Device::fromHandle(hPeerDevice)); + + NEO::MemoryManager *memoryManager = this->getDriverHandle()->getMemoryManager(); + bool isLocalMemorySupportedinDevice = + memoryManager->isLocalMemorySupported(this->getNEODevice()->getRootDeviceIndex()); + bool isLocalMemorySupportedinPeer = + memoryManager->isLocalMemorySupported(pPeerDevice->getNEODevice()->getRootDeviceIndex()); + if (isLocalMemorySupportedinDevice && isLocalMemorySupportedinPeer && + (this->getNEODevice()->getHardwareInfo().platform.eProductFamily != + pPeerDevice->getNEODevice()->getHardwareInfo().platform.eProductFamily)) { + *value = false; } + return ZE_RESULT_SUCCESS; } diff --git a/level_zero/core/test/unit_tests/mocks/mock_memory_manager.h b/level_zero/core/test/unit_tests/mocks/mock_memory_manager.h index 7fa731f261..6b2e17362a 100644 --- a/level_zero/core/test/unit_tests/mocks/mock_memory_manager.h +++ b/level_zero/core/test/unit_tests/mocks/mock_memory_manager.h @@ -26,6 +26,7 @@ namespace ult { template <> struct WhiteBox<::NEO::OsAgnosticMemoryManager> : public ::NEO::OsAgnosticMemoryManager { using BaseClass = ::NEO::OsAgnosticMemoryManager; + using BaseClass::localMemorySupported; WhiteBox(NEO::ExecutionEnvironment &executionEnvironment) : NEO::OsAgnosticMemoryManager(executionEnvironment) {} }; diff --git a/level_zero/core/test/unit_tests/sources/device/test_device.cpp b/level_zero/core/test/unit_tests/sources/device/test_device.cpp index e23d75a56a..a2c4cf0b76 100644 --- a/level_zero/core/test/unit_tests/sources/device/test_device.cpp +++ b/level_zero/core/test/unit_tests/sources/device/test_device.cpp @@ -5,9 +5,12 @@ * */ +#include "shared/source/os_interface/hw_info_config.h" #include "shared/test/unit_test/helpers/debug_manager_state_restore.h" #include "shared/test/unit_test/mocks/mock_device.h" +#include "test.h" + #include "level_zero/core/test/unit_tests/mocks/mock_driver_handle.h" #include "gtest/gtest.h" @@ -82,5 +85,150 @@ TEST_F(DeviceTest, givenKernelPropertiesStructureWhenKernelPropertiesCalledThenA EXPECT_NE(kernelPropertiesBefore.printfBufferSize, kernelProperties.printfBufferSize); } +struct MockMemoryManagerMultiDevice : public MemoryManagerMock { + MockMemoryManagerMultiDevice(NEO::ExecutionEnvironment &executionEnvironment) : MemoryManagerMock(const_cast(executionEnvironment)) {} +}; + +struct MultipleDevicesTest : public ::testing::Test { + void SetUp() override { + DebugManager.flags.CreateMultipleSubDevices.set(numSubDevices); + VariableBackup mockDeviceFlagBackup(&MockDevice::createSingleDevice, false); + + std::vector> devices; + NEO::ExecutionEnvironment *executionEnvironment = new NEO::ExecutionEnvironment(); + executionEnvironment->prepareRootDeviceEnvironments(numRootDevices); + for (auto i = 0u; i < executionEnvironment->rootDeviceEnvironments.size(); i++) { + executionEnvironment->rootDeviceEnvironments[i]->setHwInfo(NEO::defaultHwInfo.get()); + } + + for (auto i = 0u; i < executionEnvironment->rootDeviceEnvironments.size(); i++) { + devices.push_back(std::unique_ptr(NEO::MockDevice::createWithExecutionEnvironment(NEO::defaultHwInfo.get(), executionEnvironment, i))); + } + + memoryManager = new ::testing::NiceMock(*devices[0].get()->getExecutionEnvironment()); + devices[0].get()->getExecutionEnvironment()->memoryManager.reset(memoryManager); + + driverHandle = std::make_unique>(); + driverHandle->initialize(std::move(devices)); + } + + DebugManagerStateRestore restorer; + std::unique_ptr> driverHandle; + MockMemoryManagerMultiDevice *memoryManager = nullptr; + + const uint32_t numRootDevices = 2u; + const uint32_t numSubDevices = 2u; +}; + +TEST_F(MultipleDevicesTest, givenTheSameDeviceThenCanAccessPeerReturnsTrue) { + L0::Device *device0 = driverHandle->devices[0]; + + ze_bool_t canAccess = false; + ze_result_t res = device0->canAccessPeer(device0->toHandle(), &canAccess); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + EXPECT_TRUE(canAccess); +} + +TEST_F(MultipleDevicesTest, givenTwoDevicesFromSameFamilyThenCanAccessPeerReturnsTrue) { + L0::Device *device0 = driverHandle->devices[0]; + L0::Device *device1 = driverHandle->devices[1]; + + GFXCORE_FAMILY device0Family = device0->getNEODevice()->getHardwareInfo().platform.eRenderCoreFamily; + GFXCORE_FAMILY device1Family = device1->getNEODevice()->getHardwareInfo().platform.eRenderCoreFamily; + EXPECT_EQ(device0Family, device1Family); + + ze_bool_t canAccess = false; + ze_result_t res = device0->canAccessPeer(device1->toHandle(), &canAccess); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + EXPECT_TRUE(canAccess); +} + +TEST_F(MultipleDevicesTest, givenTwoSubDevicesFromTheSameRootDeviceThenCanAccessPeerReturnsTrue) { + L0::Device *device0 = driverHandle->devices[0]; + L0::Device *device1 = driverHandle->devices[1]; + + uint32_t subDeviceCount = 0; + ze_result_t res = device0->getSubDevices(&subDeviceCount, nullptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + EXPECT_EQ(numSubDevices, subDeviceCount); + + std::vector subDevices0(subDeviceCount); + res = device0->getSubDevices(&subDeviceCount, subDevices0.data()); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + + subDeviceCount = 0; + res = device1->getSubDevices(&subDeviceCount, nullptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + EXPECT_EQ(numSubDevices, subDeviceCount); + + std::vector subDevices1(subDeviceCount); + res = device1->getSubDevices(&subDeviceCount, subDevices1.data()); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + + ze_bool_t canAccess = false; + L0::Device *subDevice0_0 = Device::fromHandle(subDevices0[0]); + subDevice0_0->canAccessPeer(subDevices0[1], &canAccess); + EXPECT_TRUE(canAccess); + + canAccess = false; + L0::Device *subDevice1_0 = Device::fromHandle(subDevices1[0]); + subDevice1_0->canAccessPeer(subDevices1[1], &canAccess); + EXPECT_TRUE(canAccess); +} + +struct MultipleDevicesDifferentLocalMemorySupportTest : public MultipleDevicesTest { + void SetUp() override { + MultipleDevicesTest::SetUp(); + memoryManager->localMemorySupported[0] = 1; + + deviceWithLocalMemory = driverHandle->devices[0]; + deviceWithoutLocalMemory = driverHandle->devices[1]; + } + + L0::Device *deviceWithLocalMemory = nullptr; + L0::Device *deviceWithoutLocalMemory = nullptr; +}; + +TEST_F(MultipleDevicesDifferentLocalMemorySupportTest, givenTwoDevicesWithDifferentLocalMemorySupportThenCanAccessPeerReturnsTrue) { + ze_bool_t canAccess = false; + ze_result_t res = deviceWithLocalMemory->canAccessPeer(deviceWithoutLocalMemory->toHandle(), &canAccess); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + EXPECT_TRUE(canAccess); +} + +struct MultipleDevicesDifferentFamilyAndLocalMemorySupportTest : public MultipleDevicesTest { + void SetUp() override { + if ((NEO::HwInfoConfig::get(IGFX_SKYLAKE) == nullptr) || + (NEO::HwInfoConfig::get(IGFX_KABYLAKE) == nullptr)) { + GTEST_SKIP(); + } + + MultipleDevicesTest::SetUp(); + + memoryManager->localMemorySupported[0] = 1; + memoryManager->localMemorySupported[1] = 1; + + deviceSKL = driverHandle->devices[0]; + deviceKBL = driverHandle->devices[1]; + + deviceSKL->getNEODevice()->getRootDeviceEnvironment().getMutableHardwareInfo()->platform.eProductFamily = IGFX_SKYLAKE; + deviceKBL->getNEODevice()->getRootDeviceEnvironment().getMutableHardwareInfo()->platform.eProductFamily = IGFX_KABYLAKE; + } + + L0::Device *deviceSKL = nullptr; + L0::Device *deviceKBL = nullptr; +}; + +TEST_F(MultipleDevicesDifferentFamilyAndLocalMemorySupportTest, givenTwoDevicesFromDifferentFamiliesThenCanAccessPeerReturnsFalse) { + PRODUCT_FAMILY deviceSKLFamily = deviceSKL->getNEODevice()->getHardwareInfo().platform.eProductFamily; + PRODUCT_FAMILY deviceKBLFamily = deviceKBL->getNEODevice()->getHardwareInfo().platform.eProductFamily; + EXPECT_NE(deviceSKLFamily, deviceKBLFamily); + + ze_bool_t canAccess = true; + ze_result_t res = deviceSKL->canAccessPeer(deviceKBL->toHandle(), &canAccess); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + EXPECT_FALSE(canAccess); +} + } // namespace ult } // namespace L0 \ No newline at end of file