From c80ff3a158ee0f2b4c3045c8a1a97e3dec4845cd Mon Sep 17 00:00:00 2001 From: Mateusz Jablonski Date: Mon, 4 May 2020 14:38:11 +0200 Subject: [PATCH] Setup context type based on provided devices Related-To: NEO-4484 Change-Id: I1db354237b87167d4fa824e63737f6fff2ad77cb Signed-off-by: Mateusz Jablonski --- opencl/source/context/context.cpp | 18 ++++ opencl/source/context/context.h | 5 +- .../context/context_multi_device_tests.cpp | 93 +++++++++++++++++++ opencl/test/unit_test/mocks/mock_context.h | 1 + 4 files changed, 114 insertions(+), 3 deletions(-) diff --git a/opencl/source/context/context.cpp b/opencl/source/context/context.cpp index a5b08d4edd..7680178b1d 100644 --- a/opencl/source/context/context.cpp +++ b/opencl/source/context/context.cpp @@ -196,6 +196,7 @@ bool Context::createImpl(const cl_context_properties *properties, if (anySvmSupport) { this->svmAllocsManager = new SVMAllocsManager(this->memoryManager); } + setupContextType(); } auto commandQueue = CommandQueue::create(this, devices[0], nullptr, true, errcodeRet); @@ -427,4 +428,21 @@ DeviceBitfield Context::getDeviceBitfieldForAllocation() const { return deviceBitfield; } + +void Context::setupContextType() { + if (contextType == ContextType::CONTEXT_TYPE_DEFAULT) { + if (devices.size() > 1) { + for (const auto &pDevice : devices) { + if (!pDevice->getDeviceInfo().parentDevice) { + contextType = ContextType::CONTEXT_TYPE_UNRESTRICTIVE; + return; + } + } + } + if (devices[0]->getDeviceInfo().parentDevice) { + contextType = ContextType::CONTEXT_TYPE_SPECIALIZED; + } + } +} + } // namespace NEO diff --git a/opencl/source/context/context.h b/opencl/source/context/context.h index e93ae7dabf..69c8b01e57 100644 --- a/opencl/source/context/context.h +++ b/opencl/source/context/context.h @@ -134,7 +134,7 @@ class Context : public BaseObject<_cl_context> { void setInteropUserSyncEnabled(bool enabled) { interopUserSync = enabled; } bool areMultiStorageAllocationsPreferred(); - ContextType peekContextType() { return this->contextType; } + ContextType peekContextType() const { return contextType; } MOCKABLE_VIRTUAL BlitOperationResult blitMemoryToAllocation(MemObj &memObj, GraphicsAllocation *memory, void *hostPtr, Vec3 size) const; @@ -155,14 +155,13 @@ class Context : public BaseObject<_cl_context> { void *getOsContextInfo(cl_context_info ¶mName, size_t *srcParamSize); cl_int processExtraProperties(cl_context_properties propertyType, cl_context_properties propertyValue); + void setupContextType(); const cl_context_properties *properties = nullptr; size_t numProperties = 0u; void(CL_CALLBACK *contextCallback)(const char *, const void *, size_t, void *) = nullptr; void *userData = nullptr; - std::unique_ptr schedulerBuiltIn; - ClDeviceVector devices; MemoryManager *memoryManager = nullptr; SVMAllocsManager *svmAllocsManager = nullptr; diff --git a/opencl/test/unit_test/context/context_multi_device_tests.cpp b/opencl/test/unit_test/context/context_multi_device_tests.cpp index c82364b09d..6943da43d1 100644 --- a/opencl/test/unit_test/context/context_multi_device_tests.cpp +++ b/opencl/test/unit_test/context/context_multi_device_tests.cpp @@ -9,9 +9,12 @@ #include "shared/source/os_interface/device_factory.h" #include "shared/test/unit_test/helpers/debug_manager_state_restore.h" #include "shared/test/unit_test/helpers/variable_backup.h" +#include "shared/test/unit_test/utilities/base_object_utils.h" #include "opencl/source/context/context.h" #include "opencl/test/unit_test/fixtures/device_fixture.h" +#include "opencl/test/unit_test/mocks/mock_context.h" +#include "opencl/test/unit_test/mocks/ult_cl_device_factory.h" #include "test.h" #include "gtest/gtest.h" @@ -129,3 +132,93 @@ TEST(ContextMultiDevice, WhenGettingSubDeviceByIndexFromContextThenCorrectDevice EXPECT_EQ(nullptr, pContextWithRootDevices->getSubDeviceByIndex(1)); EXPECT_EQ(pSubDevice1, pContextWithSubDevices->getSubDeviceByIndex(1)); } + +TEST(ContextMultiDevice, givenContextWithNonDefaultContextTypeWhenSetupContextTypeThenDoNothing) { + UltClDeviceFactory deviceFactory{1, 2}; + + MockContext context0(deviceFactory.rootDevices[0]); + context0.contextType = ContextType::CONTEXT_TYPE_DEFAULT; + context0.setupContextType(); + EXPECT_EQ(ContextType::CONTEXT_TYPE_DEFAULT, context0.peekContextType()); + + MockContext context1(deviceFactory.rootDevices[0]); + context1.contextType = ContextType::CONTEXT_TYPE_SPECIALIZED; + context1.setupContextType(); + EXPECT_EQ(ContextType::CONTEXT_TYPE_SPECIALIZED, context1.peekContextType()); + + MockContext context2(deviceFactory.rootDevices[0]); + context2.contextType = ContextType::CONTEXT_TYPE_UNRESTRICTIVE; + context2.setupContextType(); + EXPECT_EQ(ContextType::CONTEXT_TYPE_UNRESTRICTIVE, context2.peekContextType()); + + MockContext context3(deviceFactory.subDevices[0]); + context3.contextType = ContextType::CONTEXT_TYPE_DEFAULT; + context3.setupContextType(); + EXPECT_EQ(ContextType::CONTEXT_TYPE_SPECIALIZED, context3.peekContextType()); + + MockContext context4(deviceFactory.subDevices[0]); + context4.contextType = ContextType::CONTEXT_TYPE_UNRESTRICTIVE; + context4.setupContextType(); + EXPECT_EQ(ContextType::CONTEXT_TYPE_UNRESTRICTIVE, context4.peekContextType()); +} + +TEST(ContextMultiDevice, givenRootDeviceWhenCreatingContextThenItHasDefaultType) { + UltClDeviceFactory deviceFactory{1, 2}; + cl_int retVal = CL_INVALID_CONTEXT; + cl_device_id device = deviceFactory.rootDevices[0]; + + auto context = clUniquePtr(Context::create(nullptr, ClDeviceVector(&device, 1), nullptr, nullptr, retVal)); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_NE(nullptr, context.get()); + EXPECT_EQ(ContextType::CONTEXT_TYPE_DEFAULT, context->peekContextType()); +} + +TEST(ContextMultiDevice, givenSubsetOfSubdevicesWhenCreatingContextThenItHasSpecializedType) { + UltClDeviceFactory deviceFactory{1, 2}; + cl_int retVal = CL_INVALID_CONTEXT; + cl_device_id firstSubDevice = deviceFactory.subDevices[0]; + cl_device_id secondSubDevice = deviceFactory.subDevices[1]; + cl_device_id bothSubDevices[]{firstSubDevice, secondSubDevice}; + + auto context0 = clUniquePtr(Context::create(nullptr, ClDeviceVector(&firstSubDevice, 1), nullptr, nullptr, retVal)); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_NE(nullptr, context0.get()); + EXPECT_EQ(ContextType::CONTEXT_TYPE_SPECIALIZED, context0->peekContextType()); + + retVal = CL_INVALID_CONTEXT; + auto context1 = clUniquePtr(Context::create(nullptr, ClDeviceVector(&secondSubDevice, 1), nullptr, nullptr, retVal)); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_NE(nullptr, context1.get()); + EXPECT_EQ(ContextType::CONTEXT_TYPE_SPECIALIZED, context1->peekContextType()); + + retVal = CL_INVALID_CONTEXT; + auto context2 = clUniquePtr(Context::create(nullptr, ClDeviceVector(bothSubDevices, 2), nullptr, nullptr, retVal)); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_NE(nullptr, context2.get()); + EXPECT_EQ(ContextType::CONTEXT_TYPE_SPECIALIZED, context2->peekContextType()); +} + +TEST(ContextMultiDevice, givenRootDeviceAndSubsetOfSubdevicesWhenCreatingContextThenItHasUnrestrictiveType) { + UltClDeviceFactory deviceFactory{1, 2}; + cl_int retVal = CL_INVALID_CONTEXT; + cl_device_id rootDeviceAndFirstSubDevice[]{deviceFactory.subDevices[0], deviceFactory.rootDevices[0]}; + cl_device_id rootDeviceAndSecondSubDevice[]{deviceFactory.subDevices[1], deviceFactory.rootDevices[0]}; + cl_device_id rootDeviceAndBothSubDevices[]{deviceFactory.subDevices[0], deviceFactory.subDevices[1], deviceFactory.rootDevices[0]}; + + auto context0 = clUniquePtr(Context::create(nullptr, ClDeviceVector(rootDeviceAndFirstSubDevice, 2), nullptr, nullptr, retVal)); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_NE(nullptr, context0.get()); + EXPECT_EQ(ContextType::CONTEXT_TYPE_UNRESTRICTIVE, context0->peekContextType()); + + retVal = CL_INVALID_CONTEXT; + auto context1 = clUniquePtr(Context::create(nullptr, ClDeviceVector(rootDeviceAndSecondSubDevice, 2), nullptr, nullptr, retVal)); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_NE(nullptr, context1.get()); + EXPECT_EQ(ContextType::CONTEXT_TYPE_UNRESTRICTIVE, context1->peekContextType()); + + retVal = CL_INVALID_CONTEXT; + auto context2 = clUniquePtr(Context::create(nullptr, ClDeviceVector(rootDeviceAndBothSubDevices, 3), nullptr, nullptr, retVal)); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_NE(nullptr, context2.get()); + EXPECT_EQ(ContextType::CONTEXT_TYPE_UNRESTRICTIVE, context2->peekContextType()); +} \ No newline at end of file diff --git a/opencl/test/unit_test/mocks/mock_context.h b/opencl/test/unit_test/mocks/mock_context.h index a0a19119eb..a8a71245ea 100644 --- a/opencl/test/unit_test/mocks/mock_context.h +++ b/opencl/test/unit_test/mocks/mock_context.h @@ -22,6 +22,7 @@ class MockContext : public Context { using Context::driverDiagnostics; using Context::memoryManager; using Context::preferD3dSharedResources; + using Context::setupContextType; using Context::sharingFunctions; using Context::svmAllocsManager; MockContext(ClDevice *pDevice, bool noSpecialQueue = false);