Beispiel #1
0
static QList<QCLDevice> qt_cl_getDevicesForPlatform
    (QCLDevice::DeviceTypes types, const QCLPlatform &platform, bool break_on_first)
{
    QList<QCLDevice> devs;
    QList<QCLPlatform> platforms;
    if (platform.isNull())
        platforms = QCLPlatform::platforms();
    else
        platforms.append(platform);
    for (int plat = 0; plat < platforms.size(); ++plat) {
        cl_uint size;
        if (clGetDeviceIDs(platforms[plat].platformId(), cl_device_type(types),
                           0, 0, &size) != CL_SUCCESS)
            continue;
        if (!size)
            continue;
        QVarLengthArray<cl_device_id> buf(size);
        clGetDeviceIDs(platforms[plat].platformId(), cl_device_type(types),
                       size, buf.data(), &size);
        for (int index = 0; index < buf.size(); ++index)
            devs.append(QCLDevice(buf[index]));
        if (break_on_first) break;
    }
    return devs;
}
Beispiel #2
0
/*!
    Returns the default device in use by this context, which is typically
    the first element of the devices() list; or a null QCLDevice if the
    context has not been created yet.

    \sa devices()
*/
QCLDevice QCLContext::defaultDevice() const
{
    Q_D(const QCLContext);
    if (d->isCreated) {
        if (!d->defaultDevice.isNull())
            return d->defaultDevice;
        size_t size = 0;
        if (clGetContextInfo(d->id, CL_CONTEXT_DEVICES, 0, 0, &size)
                == CL_SUCCESS && size > 0) {
            QVarLengthArray<cl_device_id> buf(size);
            if (clGetContextInfo(d->id, CL_CONTEXT_DEVICES,
                                 size, buf.data(), 0) == CL_SUCCESS) {
                return QCLDevice(buf[0]);
            }
        }
    }
    return QCLDevice();
}
Beispiel #3
0
/*!
    Releases this context; destroying it if the reference count is zero.
    Does nothing if the context has not been created or is already released.

    \sa create()
*/
void QCLContext::release()
{
    Q_D(QCLContext);
    if (d->isCreated) {
        d->commandQueue = QCLCommandQueue();
        d->defaultCommandQueue = QCLCommandQueue();
        clReleaseContext(d->id);
        d->id = 0;
        d->defaultDevice = QCLDevice();
        d->isCreated = false;
    }
}
Beispiel #4
0
/*!
    Returns a list of all OpenCL devices on all platforms on this system.

    \sa devices()
*/
QList<QCLDevice> QCLDevice::allDevices()
{
    QList<QCLPlatform> platforms = QCLPlatform::platforms();
    QList<QCLDevice> devs;
    for (int plat = 0; plat < platforms.size(); ++plat) {
        cl_uint size;
        if (clGetDeviceIDs(platforms[plat].platformId(), CL_DEVICE_TYPE_ALL,
                           0, 0, &size) != CL_SUCCESS)
            continue;
        QVarLengthArray<cl_device_id> buf(size);
        clGetDeviceIDs(platforms[plat].platformId(), CL_DEVICE_TYPE_ALL,
                       size, buf.data(), &size);
        for (int index = 0; index < buf.size(); ++index)
            devs.append(QCLDevice(buf[index]));
    }
    return devs;
}
Beispiel #5
0
/*!
    Returns the list of devices that are in use by this context.
    If the context has not been created, returns an empty list.

    \sa defaultDevice()
*/
QList<QCLDevice> QCLContext::devices() const
{
    Q_D(const QCLContext);
    QList<QCLDevice> devs;
    if (d->isCreated) {
        size_t size = 0;
        if (clGetContextInfo(d->id, CL_CONTEXT_DEVICES, 0, 0, &size)
                == CL_SUCCESS && size > 0) {
            QVarLengthArray<cl_device_id> buf(size);
            if (clGetContextInfo(d->id, CL_CONTEXT_DEVICES,
                                 size, buf.data(), 0) == CL_SUCCESS) {
                for (size_t index = 0; index < size; ++index)
                    devs.append(QCLDevice(buf[index]));
            }
        }
    }
    return devs;
}
Beispiel #6
0
/*!
    Creates an OpenCL context that is compatible with the current
    QGLContext and \a platform.  Returns false if there is no OpenGL
    context current or the OpenCL context could not be created for
    some reason.

    This function will first try to create a QCLDevice::GPU device,
    and will then fall back to QCLDevice::Default if a GPU is not found.

    If \a platform is null, then the first platform that has a GPU
    will be used.  If there is no GPU, then the first platform with a
    default device will be used.

    \sa supportsObjectSharing()
*/
bool QCLContextGL::create(const QCLPlatform &platform)
{
    Q_D(QCLContextGL);

    // Bail out if the context already exists.
    if (isCreated())
        return true;

    // Bail out if we don't have an OpenGL context.
    if (!QGLContext::currentContext()) {
        qWarning() << "QCLContextGL::create: needs a current GL context";
        setLastError(CL_INVALID_CONTEXT);
        return false;
    }

    // Find the first gpu device.
    QList<QCLDevice> devices;
    cl_device_type deviceType = CL_DEVICE_TYPE_GPU;
    devices = QCLDevice::devices(QCLDevice::GPU, platform);
    if (devices.isEmpty()) {
        // Find the first default device.
        devices = QCLDevice::devices(QCLDevice::Default, platform);
        deviceType = CL_DEVICE_TYPE_DEFAULT;
    }
    if (devices.isEmpty()) {
        qWarning() << "QCLContextGL::create: no gpu devices found";
        setLastError(CL_DEVICE_NOT_FOUND);
        return false;
    }
    QCLDevice gpu = devices[0];
    QVarLengthArray<cl_device_id> devs;
    foreach (QCLDevice dev, devices)
        devs.append(dev.deviceId());

    // Add the platform identifier to the properties.
    QVarLengthArray<cl_context_properties> properties;
    properties.append(CL_CONTEXT_PLATFORM);
    properties.append(cl_context_properties(gpu.platform().platformId()));

    bool hasSharing = false;
#ifndef QT_NO_CL_OPENGL
    // Determine what kind of OpenCL-OpenGL sharing we have and enable it.
#if defined(__APPLE__) || defined(__MACOSX)
    bool appleSharing = gpu.hasExtension("cl_apple_gl_sharing");
    if (appleSharing) {
        CGLContextObj cglContext = CGLGetCurrentContext();
        CGLShareGroupObj cglShareGroup = CGLGetShareGroup(cglContext);
        properties.append(CL_CGL_SHAREGROUP_KHR);
        properties.append(cl_context_properties(cglShareGroup));
        hasSharing = true;
    }
#else
    bool khrSharing = gpu.hasExtension("cl_khr_gl_sharing");
#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_ES)
    if (khrSharing) {
        properties.append(CL_EGL_DISPLAY_KHR);
        properties.append(cl_context_properties(eglGetCurrentDisplay()));
#ifdef EGL_OPENGL_ES_API
        eglBindAPI(EGL_OPENGL_ES_API);
#endif
        properties.append(CL_GL_CONTEXT_KHR);
        properties.append(cl_context_properties(eglGetCurrentContext()));
        hasSharing = true;
    }
#elif defined(Q_WS_X11)
    if (khrSharing) {
        properties.append(CL_GLX_DISPLAY_KHR);
        properties.append(cl_context_properties(glXGetCurrentDisplay()));
        properties.append(CL_GL_CONTEXT_KHR);
        properties.append(cl_context_properties(glXGetCurrentContext()));
        hasSharing = true;
    }
#else
    // Needs to be ported to other platforms.
    if (khrSharing)
        qWarning() << "QCLContextGL::create: do not know how to enable sharing";
#endif
#endif
#endif // !QT_NO_CL_OPENGL
    properties.append(0);

#ifndef QT_NO_CL_OPENGL
    // Query the actual OpenCL devices we should use with the OpenGL context.
    typedef cl_int (*q_PFNCLGETGLCONTEXTINFOKHR)
        (const cl_context_properties *, cl_uint, size_t, void *, size_t *);
    q_PFNCLGETGLCONTEXTINFOKHR getGLContextInfo =
        (q_PFNCLGETGLCONTEXTINFOKHR)clGetExtensionFunctionAddress
            ("clGetGLContextInfoKHR");
    if (getGLContextInfo && hasSharing) {
        size_t size;
        cl_device_id currentDev;
        if(getGLContextInfo(properties.data(),
                            CL_DEVICES_FOR_GL_CONTEXT_KHR,
                            0, 0, &size) == CL_SUCCESS && size > 0) {
            QVarLengthArray<cl_device_id> buf(size / sizeof(cl_device_id));
            getGLContextInfo(properties.data(),
                             CL_DEVICES_FOR_GL_CONTEXT_KHR,
                             size, buf.data(), 0);
            devs = buf;
            gpu = QCLDevice(devs[0]);
        }
        if (getGLContextInfo(properties.data(),
                             CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR,
                             sizeof(currentDev), &currentDev, 0)
                == CL_SUCCESS) {
            gpu = QCLDevice(currentDev);
        }
    }
#endif

    // Create the OpenCL context.
    cl_context id;
    cl_int error;
    id = clCreateContext
        (properties.data(), devs.size(), devs.data(),
         qt_clgl_context_notify, 0, &error);
    if (!id && hasSharing) {
        // Try again without the sharing parameters.
        properties.resize(2);
        properties.append(0);
        hasSharing = false;
        id = clCreateContext
            (properties.data(), devs.size(), devs.data(),
             qt_clgl_context_notify, 0, &error);
    }
    setLastError(error);
    if (id == 0) {
        qWarning() << "QCLContextGL::create:" << errorName(error);
        d->supportsSharing = false;
    } else {
        setContextId(id);
        clReleaseContext(id);   // setContextId() adds an extra reference.
        setDefaultDevice(gpu);
        d->supportsSharing = hasSharing;
    }
    return id != 0;
}