From 749f98c8f28ffd06d5caccffe60edc94f280f6f7 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 1 May 2015 22:14:20 +0200 Subject: Move helpers from item to context Change-Id: I61ef7f15799af2cbd7e245285b7c04f2bfd04989 Reviewed-by: Laszlo Agocs --- examples/quickcl/histogram/histogram.cpp | 10 ++- examples/quickcl/imageprocess/imageprocess.cpp | 6 +- examples/quickcl/particles/particles.cpp | 15 ++-- src/quickcl/qquickclcontext.cpp | 112 +++++++++++++++++++++++++ src/quickcl/qquickclcontext.h | 5 ++ src/quickcl/qquickclimagerunnable.cpp | 13 ++- src/quickcl/qquickclitem.cpp | 111 +----------------------- src/quickcl/qquickclitem.h | 10 +-- 8 files changed, 150 insertions(+), 132 deletions(-) diff --git a/examples/quickcl/histogram/histogram.cpp b/examples/quickcl/histogram/histogram.cpp index 6ba0b65..3bd062d 100644 --- a/examples/quickcl/histogram/histogram.cpp +++ b/examples/quickcl/histogram/histogram.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include static bool profile = false; @@ -159,9 +160,10 @@ CLRunnable::CLRunnable(CLItem *item) m_sharedBuf(0), m_doneEvent(0) { - QByteArray platform = m_item->platformName(); + QQuickCLContext *clctx = m_item->context(); + QByteArray platform = clctx->platformName(); qDebug("Using platform %s", platform.constData()); - m_program = m_item->buildProgramFromFile(QStringLiteral(":/histogram.cl")); + m_program = clctx->buildProgramFromFile(QStringLiteral(":/histogram.cl")); if (!m_program) return; cl_int err; @@ -175,7 +177,7 @@ CLRunnable::CLRunnable(CLItem *item) qWarning("Failed to create sum histogram OpenCL kernel: %d", err); return; } - m_resultBuf = clCreateBuffer(m_item->context(), CL_MEM_WRITE_ONLY, 256 * sizeof(cl_uint), 0, &err); + m_resultBuf = clCreateBuffer(clctx->context(), CL_MEM_WRITE_ONLY, 256 * sizeof(cl_uint), 0, &err); if (!m_resultBuf) { qWarning("Failed to create OpenCL buffer: %d", err); return; @@ -235,7 +237,7 @@ void CLRunnable::runKernel(cl_mem inImage, cl_mem, const QSize &size) cl_int err; if (!m_sharedBuf) { const size_t sharedBufSize = num_groups * 256 * sizeof(cl_uint); - m_sharedBuf = clCreateBuffer(m_item->context(), CL_MEM_READ_WRITE, sharedBufSize, 0, &err); + m_sharedBuf = clCreateBuffer(m_item->context()->context(), CL_MEM_READ_WRITE, sharedBufSize, 0, &err); if (!m_sharedBuf) { qWarning("Failed to create shared buffer: %d", err); return; diff --git a/examples/quickcl/imageprocess/imageprocess.cpp b/examples/quickcl/imageprocess/imageprocess.cpp index 9738ea4..5534bbb 100644 --- a/examples/quickcl/imageprocess/imageprocess.cpp +++ b/examples/quickcl/imageprocess/imageprocess.cpp @@ -46,6 +46,7 @@ #include #include #include +#include static bool profile = false; @@ -120,9 +121,10 @@ CLRunnable::CLRunnable(CLItem *item) m_clProgram(0), m_clKernel(0) { - QByteArray platform = m_item->platformName(); + QQuickCLContext *clctx = m_item->context(); + QByteArray platform = clctx->platformName(); qDebug("Using platform %s", platform.constData()); - m_clProgram = m_item->buildProgram(openclSrc); + m_clProgram = clctx->buildProgram(openclSrc); if (!m_clProgram) return; cl_int err; diff --git a/examples/quickcl/particles/particles.cpp b/examples/quickcl/particles/particles.cpp index e687084..c1e89df 100644 --- a/examples/quickcl/particles/particles.cpp +++ b/examples/quickcl/particles/particles.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include const int PARTICLE_COUNT = 1024; @@ -219,16 +220,18 @@ CLRunnable::CLRunnable(CLItem *item) m_lastT(-1), m_clBufParticleInfo(0) { - qDebug() << "Platform" << m_item->platformName() << "Device extensions" << m_item->deviceExtensions(); + QQuickCLContext *clctx = m_item->context(); + + qDebug() << "Platform" << clctx->platformName() << "Device extensions" << clctx->deviceExtensions(); cl_int err; - m_queue = clCreateCommandQueue(m_item->context(), m_item->device(), 0, &err); + m_queue = clCreateCommandQueue(clctx->context(), clctx->device(), 0, &err); if (!m_queue) { qWarning("Failed to create OpenCL command queue: %d", err); return; } - m_program = m_item->buildProgramFromFile(QStringLiteral(":/particles.cl")); + m_program = clctx->buildProgramFromFile(QStringLiteral(":/particles.cl")); if (!m_program) return; m_kernel = clCreateKernel(m_program, "updateParticles", &err); @@ -237,11 +240,11 @@ CLRunnable::CLRunnable(CLItem *item) return; } - m_needsExplicitSync = !m_item->deviceExtensions().contains(QByteArrayLiteral("cl_khr_gl_event")); + m_needsExplicitSync = !clctx->deviceExtensions().contains(QByteArrayLiteral("cl_khr_gl_event")); // m_clBufParticleInfo is an ordinary OpenCL buffer. size_t velBufSize = PARTICLE_COUNT * sizeof(cl_float) * 4; - m_clBufParticleInfo = clCreateBuffer(m_item->context(), CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, velBufSize, 0, &err); + m_clBufParticleInfo = clCreateBuffer(clctx->context(), CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, velBufSize, 0, &err); if (!m_clBufParticleInfo) { qWarning("Failed to create CL buffer: %d", err); return; @@ -292,7 +295,7 @@ void CLRunnable::createBuffer() if (m_node->m_clBuf) clReleaseMemObject(m_node->m_clBuf); cl_int err; - m_node->m_clBuf = clCreateFromGLBuffer(m_item->context(), CL_MEM_READ_WRITE, buf, &err); + m_node->m_clBuf = clCreateFromGLBuffer(m_item->context()->context(), CL_MEM_READ_WRITE, buf, &err); if (!m_node->m_clBuf) qWarning("Failed to create OpenCL object for OpenGL buffer: %d", err); } diff --git a/src/quickcl/qquickclcontext.cpp b/src/quickcl/qquickclcontext.cpp index 14f1647..7aae3fa 100644 --- a/src/quickcl/qquickclcontext.cpp +++ b/src/quickcl/qquickclcontext.cpp @@ -102,6 +102,11 @@ bool QQuickCLContext::isValid() const /*! \return the OpenCL platform chosen in create(). + + \note For contexts belonging to a QQuickCLItem the value is only available + after the item is first rendered. It is always safe to call this function + from QQuickCLRunnable's constructor, destructor and + \l{QQuickCLRunnable::update()}{update()} function. */ cl_platform_id QQuickCLContext::platform() const { @@ -111,6 +116,11 @@ cl_platform_id QQuickCLContext::platform() const /*! \return the OpenCL device chosen in create(). + + \note For contexts belonging to a QQuickCLItem the value is only available + after the item is first rendered. It is always safe to call this function + from QQuickCLRunnable's constructor, destructor and + \l{QQuickCLRunnable::update()}{update()} function. */ cl_device_id QQuickCLContext::device() const { @@ -120,6 +130,11 @@ cl_device_id QQuickCLContext::device() const /*! \return the OpenCL context or \c 0 if not yet created. + + \note For contexts belonging to a QQuickCLItem the value is only available + after the item is first rendered. It is always safe to call this function + from QQuickCLRunnable's constructor, destructor and + \l{QQuickCLRunnable::update()}{update()} function. */ cl_context QQuickCLContext::context() const { @@ -285,4 +300,101 @@ void QQuickCLContext::destroy() d->platform = 0; } +/*! + \return the name of the current platform in use. + + \note The value is valid only after create() has been called successfully. + + \note For contexts belonging to a QQuickCLItem this function can only be + called from a QQuickCLRunnable's constructor, destructor and + \l{QQuickCLRunnable::update()}{update()} function, or after the item has + been rendered at least once. + */ +QByteArray QQuickCLContext::platformName() const +{ + QByteArray name(1024, '\0'); + clGetPlatformInfo(platform(), CL_PLATFORM_NAME, name.size(), name.data(), 0); + name.resize(int(strlen(name.constData()))); + return name; +} + +/*! + \return the list of device extensions. + + \note The value is valid only after create() has been called successfully. + + \note For contexts belonging to a QQuickCLItem this function can only be + called from a QQuickCLRunnable's constructor, destructor and + \l{QQuickCLRunnable::update()}{update()} function, or after the item has + been rendered at least once. + */ +QByteArray QQuickCLContext::deviceExtensions() const +{ + QByteArray ext(8192, '\0'); + clGetDeviceInfo(device(), CL_DEVICE_EXTENSIONS, ext.size(), ext.data(), 0); + ext.resize(int(strlen(ext.constData()))); + return ext; +} + +/*! + Creates and builds an OpenCL program from the source code in \a src. + + \return the cl_program or \c 0 when failed. Errors and build logs are + printed to the warning output. + + \note The value is valid only after create() has been called successfully. + + \note For contexts belonging to a QQuickCLItem this function can only be + called from a QQuickCLRunnable's constructor, destructor and + \l{QQuickCLRunnable::update()}{update()} function, or after the item has + been rendered at least once. + + \sa buildProgramFromFile() + */ +cl_program QQuickCLContext::buildProgram(const QByteArray &src) +{ + cl_int err; + const char *str = src.constData(); + cl_program prog = clCreateProgramWithSource(context(), 1, &str, 0, &err); + if (!prog) { + qWarning("Failed to create OpenCL program: %d", err); + qWarning("Source was:\n%s", str); + return 0; + } + cl_device_id dev = device(); + err = clBuildProgram(prog, 1, &dev, 0, 0, 0); + if (err != CL_SUCCESS) { + qWarning("Failed to build OpenCL program: %d", err); + qWarning("Source was:\n%s", str); + QByteArray log; + log.resize(8192); + clGetProgramBuildInfo(prog, dev, CL_PROGRAM_BUILD_LOG, log.size(), log.data(), 0); + qWarning("Build log:\n%s", log.constData()); + return 0; + } + return prog; +} + +/*! + Creates and builds an OpenCL program from the source file \a filename. + + \note The value is valid only after create() has been called successfully. + + \note For contexts belonging to a QQuickCLItem this function can only be + called from a QQuickCLRunnable's constructor, destructor and + \l{QQuickCLRunnable::update()}{update()} function, or after the item has + been rendered at least once. + + \sa buildProgram() + */ +cl_program QQuickCLContext::buildProgramFromFile(const QString &filename) +{ + QFile f(filename); + if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { + qWarning("Failed to open OpenCL program source file %s", qPrintable(filename)); + return 0; + } + return buildProgram(f.readAll()); +} + QT_END_NAMESPACE diff --git a/src/quickcl/qquickclcontext.h b/src/quickcl/qquickclcontext.h index 2a7e94c..d780ad5 100644 --- a/src/quickcl/qquickclcontext.h +++ b/src/quickcl/qquickclcontext.h @@ -60,6 +60,11 @@ public: cl_device_id device() const; cl_context context() const; + QByteArray platformName() const; + QByteArray deviceExtensions() const; + cl_program buildProgram(const QByteArray &src); + cl_program buildProgramFromFile(const QString &filename); + private: QQuickCLContextPrivate *d_ptr; }; diff --git a/src/quickcl/qquickclimagerunnable.cpp b/src/quickcl/qquickclimagerunnable.cpp index 01a7be1..bd1fb51 100644 --- a/src/quickcl/qquickclimagerunnable.cpp +++ b/src/quickcl/qquickclimagerunnable.cpp @@ -36,6 +36,7 @@ #include "qquickclimagerunnable.h" #include "qquickclitem.h" +#include "qquickclcontext.h" #include #include #include @@ -173,12 +174,14 @@ QQuickCLImageRunnable::QQuickCLImageRunnable(QQuickCLItem *item, Flags flags) Q_D(QQuickCLImageRunnable); cl_int err; cl_command_queue_properties queueProps = flags.testFlag(Profile) ? CL_QUEUE_PROFILING_ENABLE : 0; - d->queue = clCreateCommandQueue(item->context(), item->device(), queueProps, &err); + QQuickCLContext *clctx = item->context(); + Q_ASSERT(clctx); + d->queue = clCreateCommandQueue(clctx->context(), clctx->device(), queueProps, &err); if (!d->queue) { qWarning("Failed to create OpenCL command queue: %d", err); return; } - d->needsExplicitSync = !item->deviceExtensions().contains(QByteArrayLiteral("cl_khr_gl_event")); + d->needsExplicitSync = !clctx->deviceExtensions().contains(QByteArrayLiteral("cl_khr_gl_event")); } QQuickCLImageRunnable::~QQuickCLImageRunnable() @@ -243,9 +246,11 @@ QSGNode *QQuickCLImageRunnable::update(QSGNode *node) node = 0; } + QQuickCLContext *clctx = d->item->context(); + Q_ASSERT(clctx); cl_int err = 0; if (!d->image[0]) - d->image[0] = clCreateFromGLTexture2D(d->item->context(), CL_MEM_READ_ONLY, GL_TEXTURE_2D, 0, + d->image[0] = clCreateFromGLTexture2D(clctx->context(), CL_MEM_READ_ONLY, GL_TEXTURE_2D, 0, texture->textureId(), &err); if (!d->image[0]) { if (err == CL_INVALID_GL_OBJECT) // the texture provider may not be ready yet, try again later @@ -264,7 +269,7 @@ QSGNode *QQuickCLImageRunnable::update(QSGNode *node) d->outputTexture = new QOpenGLTexture(QImage(d->textureSize, QImage::Format_RGB32)); if (!d->image[1]) - d->image[1] = clCreateFromGLTexture2D(d->item->context(), CL_MEM_WRITE_ONLY, GL_TEXTURE_2D, 0, + d->image[1] = clCreateFromGLTexture2D(clctx->context(), CL_MEM_WRITE_ONLY, GL_TEXTURE_2D, 0, d->outputTexture->textureId(), &err); if (!d->image[1]) { qWarning("Failed to create OpenCL image object for output OpenGL texture: %d", err); diff --git a/src/quickcl/qquickclitem.cpp b/src/quickcl/qquickclitem.cpp index 6c88b5d..6947fed 100644 --- a/src/quickcl/qquickclitem.cpp +++ b/src/quickcl/qquickclitem.cpp @@ -122,42 +122,16 @@ QQuickCLItem::QQuickCLItem(QQuickItem *parent) } /*! - \return the selected OpenCL platform. Matches the OpenGL context in use. + \return the associated QQuickCLContext. \note The value is only available after the item is first rendered. It is always safe to call this function from QQuickCLRunnable's constructor, destructor and \l{QQuickCLRunnable::update()}{update()} function. */ -cl_platform_id QQuickCLItem::platform() const +QQuickCLContext *QQuickCLItem::context() const { Q_D(const QQuickCLItem); - return d->clctx ? d->clctx->platform() : 0; -} - -/*! - \return the selected OpenCL device. Matches the OpenGL context in use. - - \note The value is only available after the item is first rendered. It is - always safe to call this function from QQuickCLRunnable's constructor, - destructor and \l{QQuickCLRunnable::update()}{update()} function. - */ -cl_device_id QQuickCLItem::device() const -{ - Q_D(const QQuickCLItem); - return d->clctx ? d->clctx->device() : 0; -} - -/*! - \return the OpenCL context. - - \note The value is only available after the item is first rendered. It is - always safe to call this function from QQuickCLRunnable's constructor, - destructor and \l{QQuickCLRunnable::update()}{update()} function. - */ -cl_context QQuickCLItem::context() const -{ - Q_D(const QQuickCLItem); - return d->clctx ? d->clctx->context() : 0; + return d->clctx; } QSGNode *QQuickCLItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *) @@ -253,85 +227,6 @@ void QQuickCLItem::scheduleUpdate() QCoreApplication::postEvent(this, new QEvent(QEvent::Type(EV_UPDATE))); } -/*! - \return the name of the current platform in use. - - \note This function can only be called from a QQuickCLRunnable's - constructor, destructor and \l{QQuickCLRunnable::update()}{update()} - function, or after the item has been rendered at least once. - */ -QByteArray QQuickCLItem::platformName() const -{ - QByteArray name(1024, '\0'); - clGetPlatformInfo(platform(), CL_PLATFORM_NAME, name.size(), name.data(), 0); - name.resize(int(strlen(name.constData()))); - return name; -} - -/*! - \return the list of device extensions. - - \note This function can only be called from a QQuickCLRunnable's - constructor, destructor and \l{QQuickCLRunnable::update()}{update()} - function, or after the item has been rendered at least once. - */ -QByteArray QQuickCLItem::deviceExtensions() const -{ - QByteArray ext(8192, '\0'); - clGetDeviceInfo(device(), CL_DEVICE_EXTENSIONS, ext.size(), ext.data(), 0); - ext.resize(int(strlen(ext.constData()))); - return ext; -} - -/*! - Creates and builds an OpenCL program from the source code in \a src. - - \return the cl_program or \c 0 when failed. Errors and build logs are - printed to the warning output. - - \note This function can only be called from a QQuickCLRunnable's - constructor, destructor and \l{QQuickCLRunnable::update()}{update()} - function, or after the item has been rendered at least once. - */ -cl_program QQuickCLItem::buildProgram(const QByteArray &src) -{ - cl_int err; - const char *str = src.constData(); - cl_program prog = clCreateProgramWithSource(context(), 1, &str, 0, &err); - if (!prog) { - qWarning("Failed to create OpenCL program: %d", err); - qWarning("Source was:\n%s", str); - return 0; - } - cl_device_id dev = device(); - err = clBuildProgram(prog, 1, &dev, 0, 0, 0); - if (err != CL_SUCCESS) { - qWarning("Failed to build OpenCL program: %d", err); - qWarning("Source was:\n%s", str); - QByteArray log; - log.resize(8192); - clGetProgramBuildInfo(prog, dev, CL_PROGRAM_BUILD_LOG, log.size(), log.data(), 0); - qWarning("Build log:\n%s", log.constData()); - return 0; - } - return prog; -} - -/*! - Creates and builds an OpenCL program from the source file \a filename. - - \sa buildProgram() - */ -cl_program QQuickCLItem::buildProgramFromFile(const QString &filename) -{ - QFile f(filename); - if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { - qWarning("Failed to open OpenCL program source file %s", qPrintable(filename)); - return 0; - } - return buildProgram(f.readAll()); -} - struct EventCallbackParam { EventCallbackParam(QQuickCLItem *item) : item(item) { } diff --git a/src/quickcl/qquickclitem.h b/src/quickcl/qquickclitem.h index 98ce7fc..c3e93bf 100644 --- a/src/quickcl/qquickclitem.h +++ b/src/quickcl/qquickclitem.h @@ -44,6 +44,7 @@ QT_BEGIN_NAMESPACE class QQuickCLItemPrivate; +class QQuickCLContext; class Q_QUICKCL_EXPORT QQuickCLItem : public QQuickItem { @@ -53,17 +54,10 @@ class Q_QUICKCL_EXPORT QQuickCLItem : public QQuickItem public: QQuickCLItem(QQuickItem *parent = 0); - cl_platform_id platform() const; - cl_device_id device() const; - cl_context context() const; + QQuickCLContext *context() const; void scheduleUpdate(); - QByteArray platformName() const; - QByteArray deviceExtensions() const; - cl_program buildProgram(const QByteArray &src); - cl_program buildProgramFromFile(const QString &filename); - void watchEvent(cl_event event); virtual void eventCompleted(cl_event event); -- cgit v1.2.3