Skip to content

Commit e026a5a

Browse files
authored
Merge pull request opencv#26281 from kallaballa:clgl_device_discovery
Rewrote OpenCL-OpenGL-interop device discovery routine without extensions and with Apple support
2 parents c79b72a + 3edcf41 commit e026a5a

File tree

1 file changed

+123
-63
lines changed

1 file changed

+123
-63
lines changed

modules/core/src/opengl.cpp

Lines changed: 123 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@
4242

4343
#include "precomp.hpp"
4444

45+
#if defined (__APPLE__) || defined(MACOSX)
46+
#define GL_SHARING_EXTENSION "cl_APPLE_gl_sharing"
47+
#else
48+
#define GL_SHARING_EXTENSION "cl_khr_gl_sharing"
49+
#endif
50+
4551
#ifdef HAVE_OPENGL
4652
# include "gl_core_3_1.hpp"
4753
# ifdef HAVE_CUDA
@@ -1635,94 +1641,148 @@ Context& initializeContextFromGL()
16351641
#elif !defined(HAVE_OPENCL_OPENGL_SHARING)
16361642
NO_OPENCL_SHARING_ERROR;
16371643
#else
1638-
cl_uint numPlatforms;
1639-
cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
1644+
cl_uint platformsCnt = 0;
1645+
cl_uint devCnt = 0;
1646+
cl_device_id* devices = nullptr;
1647+
cl_uint devUsed = 0;
1648+
cl_context context = nullptr;
1649+
1650+
cl_int status = clGetPlatformIDs(0, NULL, &platformsCnt);
16401651
if (status != CL_SUCCESS)
16411652
CV_Error_(cv::Error::OpenCLInitError, ("OpenCL: Can't get number of platforms: %d", status));
1642-
if (numPlatforms == 0)
1653+
if (platformsCnt == 0)
16431654
CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");
16441655

1645-
std::vector<cl_platform_id> platforms(numPlatforms);
1646-
status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
1656+
std::vector<cl_platform_id> platforms(platformsCnt);
1657+
status = clGetPlatformIDs(platformsCnt, &platforms[0], NULL);
16471658
if (status != CL_SUCCESS)
1648-
CV_Error_(cv::Error::OpenCLInitError, ("OpenCL: Can't get number of platforms: %d", status));
1659+
CV_Error_(cv::Error::OpenCLInitError, ("OpenCL: Can't get platforms: %d", status));
1660+
16491661

16501662
// TODO Filter platforms by name from OPENCV_OPENCL_DEVICE
1663+
bool sharingSupported = false;
16511664

1652-
int found = -1;
1653-
cl_device_id device = NULL;
1654-
cl_context context = NULL;
1665+
for (unsigned int i = 0; (!sharingSupported && (i < platformsCnt)); ++i) {
1666+
status = clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_GPU, 0, NULL, &devCnt);
1667+
if (status != CL_SUCCESS)
1668+
CV_Error_(cv::Error::OpenCLInitError, ("OpenCL: No devices available: %d", status));
16551669

1656-
for (int i = 0; i < (int)numPlatforms; i++)
1657-
{
1658-
// query platform extension: presence of "cl_khr_gl_sharing" extension is required
1659-
{
1660-
AutoBuffer<char> extensionStr;
1670+
try {
1671+
devices = new cl_device_id[devCnt];
16611672

1662-
size_t extensionSize;
1663-
status = clGetPlatformInfo(platforms[i], CL_PLATFORM_EXTENSIONS, 0, NULL, &extensionSize);
1664-
if (status == CL_SUCCESS)
1665-
{
1666-
extensionStr.allocate(extensionSize+1);
1667-
status = clGetPlatformInfo(platforms[i], CL_PLATFORM_EXTENSIONS, extensionSize, (char*)extensionStr.data(), NULL);
1668-
}
1673+
status = clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_GPU, devCnt, devices, NULL);
16691674
if (status != CL_SUCCESS)
1670-
CV_Error_(cv::Error::OpenCLInitError, ("OpenCL: Can't get platform extension string: %d", status));
1671-
1672-
if (!strstr((const char*)extensionStr.data(), "cl_khr_gl_sharing"))
1673-
continue;
1674-
}
1675-
1676-
clGetGLContextInfoKHR_fn clGetGLContextInfoKHR = (clGetGLContextInfoKHR_fn)
1677-
clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetGLContextInfoKHR");
1678-
if (!clGetGLContextInfoKHR)
1675+
CV_Error_(cv::Error::OpenCLInitError, ("OpenCL: Can't get platform devices: %d", status));
1676+
1677+
for (unsigned int j = 0; (!sharingSupported && (j < devCnt)); ++j) {
1678+
size_t extensionSize;
1679+
status = clGetDeviceInfo(devices[j], CL_DEVICE_EXTENSIONS, 0, NULL, &extensionSize );
1680+
if (status != CL_SUCCESS)
1681+
CV_Error_(cv::Error::OpenCLInitError, ("OpenCL: No devices available: %d", status));
1682+
1683+
if(extensionSize > 0)
1684+
{
1685+
char* extensions = nullptr;
1686+
1687+
try {
1688+
extensions = new char[extensionSize];
1689+
1690+
status = clGetDeviceInfo(devices[j], CL_DEVICE_EXTENSIONS, extensionSize, extensions, &extensionSize);
1691+
if (status != CL_SUCCESS)
1692+
continue;
1693+
} catch(...) {
1694+
CV_Error(cv::Error::OpenCLInitError, "OpenCL: Exception thrown during device extensions gathering");
1695+
}
1696+
1697+
std::string devString;
1698+
1699+
if(extensions != nullptr) {
1700+
devString = extensions;
1701+
delete[] extensions;
1702+
}
1703+
else {
1704+
CV_Error(cv::Error::OpenCLInitError, "OpenCL: Unexpected error during device extensions gathering");
1705+
}
1706+
1707+
size_t oldPos = 0;
1708+
size_t spacePos = devString.find(' ', oldPos); // extensions string is space delimited
1709+
while (spacePos != devString.npos) {
1710+
if (strcmp(GL_SHARING_EXTENSION,
1711+
devString.substr(oldPos, spacePos - oldPos).c_str())
1712+
== 0) {
1713+
// Device supports context sharing with OpenGL
1714+
devUsed = i;
1715+
sharingSupported = true;
1716+
break;
1717+
}
1718+
do {
1719+
oldPos = spacePos + 1;
1720+
spacePos = devString.find(' ', oldPos);
1721+
} while (spacePos == oldPos);
1722+
}
1723+
}
1724+
}
1725+
} catch(...) {
1726+
CV_Error(cv::Error::OpenCLInitError, "OpenCL: Exception thrown during device information gathering");
1727+
if(devices != nullptr) {
1728+
delete[] devices;
1729+
}
16791730
continue;
1731+
}
16801732

1681-
cl_context_properties properties[] =
1682-
{
1683-
#if defined(_WIN32)
1684-
CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
1685-
CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(),
1686-
CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC(),
1733+
if (sharingSupported) {
1734+
// Define OS-specific context properties and create the OpenCL context
1735+
#if defined (__APPLE__)
1736+
CGLContextObj cglContext = CGLGetCurrentContext();
1737+
CGLShareGroupObj cglShareGroup = CGLGetShareGroup(cglContext);
1738+
cl_context_properties props[] =
1739+
{
1740+
CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties)cglShareGroup,
1741+
0
1742+
};
1743+
context = clCreateContext(props, 0,0, NULL, NULL, &ciErrNum);
16871744
#elif defined(__ANDROID__)
1688-
CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
1689-
CL_GL_CONTEXT_KHR, (cl_context_properties)eglGetCurrentContext(),
1690-
CL_EGL_DISPLAY_KHR, (cl_context_properties)eglGetCurrentDisplay(),
1745+
cl_context_properties props[] =
1746+
{
1747+
CL_GL_CONTEXT_KHR, (cl_context_properties)glXGetCurrentContext(),
1748+
CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay(),
1749+
CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
1750+
0
1751+
};
1752+
context = clCreateContext(props, 1, &devices[devUsed], NULL, NULL, &status);
1753+
#elif defined(_WIN32)
1754+
cl_context_properties props[] =
1755+
{
1756+
CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(),
1757+
CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC(),
1758+
CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
1759+
0
1760+
};
1761+
context = clCreateContext(props, 1, &devices[devUsed], NULL, NULL, &status);
16911762
#elif defined(__linux__)
1692-
CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
1693-
CL_GL_CONTEXT_KHR, (cl_context_properties)glXGetCurrentContext(),
1694-
CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay(),
1763+
cl_context_properties props[] =
1764+
{
1765+
CL_GL_CONTEXT_KHR, (cl_context_properties)glXGetCurrentContext(),
1766+
CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay(),
1767+
CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
1768+
0
1769+
};
1770+
context = clCreateContext(props, 1, &devices[devUsed], NULL, NULL, &status);
16951771
#endif
1696-
0
1697-
};
1698-
1699-
// query device
1700-
device = NULL;
1701-
status = clGetGLContextInfoKHR(properties, CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR, sizeof(cl_device_id), (void*)&device, NULL);
1702-
if (status != CL_SUCCESS)
1703-
continue;
1772+
}
17041773

1705-
// create context
1706-
context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
17071774
if (status != CL_SUCCESS)
1708-
{
1709-
clReleaseDevice(device);
1710-
}
1775+
CV_Error_(cv::Error::OpenCLInitError, ("OpenCL: Can't create context for OpenGL interop: %d", status));
17111776
else
1712-
{
1713-
found = i;
17141777
break;
1715-
}
17161778
}
17171779

1718-
if (found < 0)
1719-
CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for OpenGL interop");
17201780

1721-
cl_platform_id platform = platforms[found];
1781+
cl_platform_id platform = platforms[devUsed];
17221782
std::string platformName = PlatformInfo(&platform).name();
17231783

1724-
OpenCLExecutionContext clExecCtx = OpenCLExecutionContext::create(platformName, platform, context, device);
1725-
clReleaseDevice(device);
1784+
OpenCLExecutionContext clExecCtx = OpenCLExecutionContext::create(platformName, platform, context, devices[devUsed]);
1785+
clReleaseDevice(devices[devUsed]);
17261786
clReleaseContext(context);
17271787
clExecCtx.bind();
17281788
return const_cast<Context&>(clExecCtx.getContext());

0 commit comments

Comments
 (0)