diff --git a/opencl/source/api/api.cpp b/opencl/source/api/api.cpp index af62bc2ca2..d1f420e27d 100644 --- a/opencl/source/api/api.cpp +++ b/opencl/source/api/api.cpp @@ -428,7 +428,7 @@ cl_context CL_API_CALL clCreateContextFromType(const cl_context_properties *prop retVal = clGetDeviceIDs(nullptr, deviceType, numDevices, supportedDevs.begin(), nullptr); DEBUG_BREAK_IF(retVal != CL_SUCCESS); - ClDeviceVector allDevs(supportedDevs.begin(), numDevices); + ClDeviceVector allDevs(supportedDevs.begin(), std::min(numDevices, 1u)); pContext = Context::create(properties, allDevs, funcNotify, userData, retVal); if (pContext != nullptr) { gtpinNotifyContextCreate((cl_context)pContext); diff --git a/opencl/source/context/context.cpp b/opencl/source/context/context.cpp index 90ef6689bd..5e026df832 100644 --- a/opencl/source/context/context.cpp +++ b/opencl/source/context/context.cpp @@ -172,9 +172,18 @@ bool Context::createImpl(const cl_context_properties *properties, } this->driverDiagnostics = driverDiagnostics.release(); + if (inputDevices.size() > 1) { + auto rootDeviceIndex = inputDevices[0]->getRootDeviceIndex(); + for (const auto &device : inputDevices) { + if (device->getRootDeviceIndex() != rootDeviceIndex) { + DEBUG_BREAK_IF("No support for context with multiple root devices"); + errcodeRet = CL_OUT_OF_HOST_MEMORY; + return false; + } + } + } this->devices = inputDevices; - // We currently assume each device uses the same MemoryManager if (devices.size() > 0) { auto device = this->getDevice(0); this->memoryManager = device->getMemoryManager(); diff --git a/opencl/test/unit_test/api/cl_create_context_from_type_tests.inl b/opencl/test/unit_test/api/cl_create_context_from_type_tests.inl index a0e961e9b2..3dcc2423e0 100644 --- a/opencl/test/unit_test/api/cl_create_context_from_type_tests.inl +++ b/opencl/test/unit_test/api/cl_create_context_from_type_tests.inl @@ -26,7 +26,7 @@ void CL_CALLBACK contextCallBack(const char *, const void *, size_t, void *) { } -TEST_F(clCreateContextFromTypeTests, GivenOnlyGpuDeviceTypeAndReturnValueWhenCreatingContextFromTypeThenCallSucceeds) { +TEST_F(clCreateContextFromTypeTests, GivenOnlyGpuDeviceTypeAndReturnValueWhenCreatingContextFromTypeThenContextWithSingleDeviceIsCreated) { auto context = clCreateContextFromType(nullptr, CL_DEVICE_TYPE_GPU, nullptr, nullptr, &retVal); @@ -35,6 +35,9 @@ TEST_F(clCreateContextFromTypeTests, GivenOnlyGpuDeviceTypeAndReturnValueWhenCre EXPECT_NE(nullptr, context->dispatch.icdDispatch); EXPECT_NE(nullptr, context->dispatch.crtDispatch); + auto pContext = castToObject(context); + EXPECT_EQ(1u, pContext->getNumDevices()); + retVal = clReleaseContext(context); ASSERT_EQ(CL_SUCCESS, retVal); } diff --git a/opencl/test/unit_test/api/cl_create_context_tests.inl b/opencl/test/unit_test/api/cl_create_context_tests.inl index 8553c37a76..e78734be49 100644 --- a/opencl/test/unit_test/api/cl_create_context_tests.inl +++ b/opencl/test/unit_test/api/cl_create_context_tests.inl @@ -82,6 +82,15 @@ TEST_F(clCreateContextTests, nullUserData) { EXPECT_EQ(CL_SUCCESS, retVal); } +TEST_F(clCreateContextTests, givenMultipleRootDevicesWhenCreateContextThenOutOrHostMemoryErrorIsReturned) { + auto firstDeviceRootDeviceIndex = castToObject(devices[testedRootDeviceIndex])->getRootDeviceIndex(); + auto secondDeviceRootDeviceIndex = castToObject(devices[testedRootDeviceIndex + 1])->getRootDeviceIndex(); + EXPECT_NE(firstDeviceRootDeviceIndex, secondDeviceRootDeviceIndex); + auto context = clCreateContext(nullptr, 2u, &devices[testedRootDeviceIndex], eventCallBack, nullptr, &retVal); + EXPECT_EQ(nullptr, context); + EXPECT_EQ(CL_OUT_OF_HOST_MEMORY, retVal); +} + TEST_F(clCreateContextTests, givenInvalidContextCreationPropertiesThenContextCreationFails) { cl_context_properties invalidProperties[3] = {CL_CONTEXT_PLATFORM, (cl_context_properties) nullptr, 0}; auto context = clCreateContext(invalidProperties, 1u, &testedClDevice, nullptr, nullptr, &retVal); diff --git a/opencl/test/unit_test/api/cl_get_context_info_tests.inl b/opencl/test/unit_test/api/cl_get_context_info_tests.inl index 354c829ff3..8cc6efb9a6 100644 --- a/opencl/test/unit_test/api/cl_get_context_info_tests.inl +++ b/opencl/test/unit_test/api/cl_get_context_info_tests.inl @@ -44,13 +44,18 @@ TEST_F(clGetContextInfoTests, GivenContextWithSingleDeviceAndContextDevicesParam } TEST_F(clGetContextInfoTests, GivenContextWithMultipleDevicesAndContextDevicesParamWhenGettingContextInfoThenListOfDevicesContainsAllDevices) { - auto devicesReturned = new cl_device_id[this->num_devices - 1]; - cl_uint numDevices = this->num_devices - 1; + cl_uint numDevices = 2u; + auto inputDevices = std::make_unique(numDevices); + auto outputDevices = std::make_unique(numDevices); + + for (auto i = 0u; i < numDevices; i++) { + inputDevices[i] = testedClDevice; + } auto context = clCreateContext( nullptr, - this->num_devices - 1, - this->devices + 1, + numDevices, + inputDevices.get(), nullptr, nullptr, &retVal); @@ -61,16 +66,15 @@ TEST_F(clGetContextInfoTests, GivenContextWithMultipleDevicesAndContextDevicesPa context, CL_CONTEXT_DEVICES, numDevices * sizeof(cl_device_id), - devicesReturned, + outputDevices.get(), nullptr); ASSERT_EQ(CL_SUCCESS, retVal); - for (size_t deviceOrdinal = 0; deviceOrdinal < this->num_devices - 1; ++deviceOrdinal) { - EXPECT_EQ(this->devices[deviceOrdinal + 1], devicesReturned[deviceOrdinal]); + for (size_t deviceOrdinal = 0; deviceOrdinal < numDevices; ++deviceOrdinal) { + EXPECT_EQ(inputDevices[deviceOrdinal], outputDevices[deviceOrdinal]); } clReleaseContext(context); - delete[] devicesReturned; } TEST(clGetContextInfo, GivenNullContextWhenGettingContextInfoThenInvalidContextErrorIsReturned) { diff --git a/opencl/test/unit_test/context/context_tests.cpp b/opencl/test/unit_test/context/context_tests.cpp index 62941684c9..d63b08a096 100644 --- a/opencl/test/unit_test/context/context_tests.cpp +++ b/opencl/test/unit_test/context/context_tests.cpp @@ -334,23 +334,20 @@ TEST(Context, whenCreateContextThenSpecialQueueUsesInternalEngine) { TEST(MultiDeviceContextTest, givenContextWithMultipleDevicesWhenGettingTotalNumberOfDevicesThenNumberOfAllAvailableDevicesIsReturned) { DebugManagerStateRestore restorer; - const uint32_t numDevices = 2u; + const uint32_t numRootDevices = 1u; const uint32_t numSubDevices = 3u; - DebugManager.flags.CreateMultipleRootDevices.set(numDevices); DebugManager.flags.CreateMultipleSubDevices.set(numSubDevices); initPlatform(); - auto device0 = platform()->getClDevice(0); - auto device1 = platform()->getClDevice(1); - cl_device_id clDevices[2]{device0, device1}; + auto device = platform()->getClDevice(0); - ClDeviceVector deviceVector(clDevices, 2); + cl_device_id clDevice = device; + ClDeviceVector deviceVector(&clDevice, numRootDevices); cl_int retVal = CL_OUT_OF_HOST_MEMORY; auto context = std::unique_ptr(Context::create(nullptr, deviceVector, nullptr, nullptr, retVal)); EXPECT_EQ(CL_SUCCESS, retVal); - EXPECT_EQ(numSubDevices, device0->getNumAvailableDevices()); - EXPECT_EQ(numSubDevices, device1->getNumAvailableDevices()); - EXPECT_EQ(numDevices, context->getNumDevices()); - EXPECT_EQ(numDevices * numSubDevices, context->getTotalNumDevices()); + EXPECT_EQ(numSubDevices, device->getNumAvailableDevices()); + EXPECT_EQ(numRootDevices, context->getNumDevices()); + EXPECT_EQ(numRootDevices * numSubDevices, context->getTotalNumDevices()); } class ContextWithAsyncDeleterTest : public ::testing::WithParamInterface,