summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRhys Weatherley <rhys.weatherley@nokia.com>2010-11-19 08:04:43 +1000
committerRhys Weatherley <rhys.weatherley@nokia.com>2010-11-19 08:23:24 +1000
commit7e501c6dffd30b5770e886c3dfc6a33c1738093e (patch)
tree4420cd6fee8d4dd316d81eb5b21cc76ca3414838
parent0d4f060e2fd4e55d68db5b17de107e1440576a60 (diff)
Convenience functions for rounding work sizes
-rw-r--r--examples/opencl/colorize/colorizewidget.cpp2
-rw-r--r--examples/opencl/imagedrawing/imagewidget.cpp18
-rw-r--r--examples/opencl/pathdrawing/pathwidget.cpp10
-rw-r--r--examples/opencl/pathdrawing/pathwidget.h1
-rw-r--r--src/opencl/qclkernel.cpp29
-rw-r--r--src/opencl/qclkernel.h19
-rw-r--r--src/opencl/qclworksize.cpp27
-rw-r--r--src/opencl/qclworksize.h2
-rw-r--r--tests/auto/qcl/tst_qcl.cpp68
9 files changed, 156 insertions, 20 deletions
diff --git a/examples/opencl/colorize/colorizewidget.cpp b/examples/opencl/colorize/colorizewidget.cpp
index b5d7c41..4f2f1ab 100644
--- a/examples/opencl/colorize/colorizewidget.cpp
+++ b/examples/opencl/colorize/colorizewidget.cpp
@@ -58,7 +58,7 @@ ColorizeWidget::ColorizeWidget(QWidget *parent)
colorize = program.createKernel("colorize");
colorize.setGlobalWorkSize(img.size());
- colorize.setLocalWorkSize(8, 8);
+ colorize.setLocalWorkSize(colorize.bestLocalWorkSizeImage2D());
}
ColorizeWidget::~ColorizeWidget()
diff --git a/examples/opencl/imagedrawing/imagewidget.cpp b/examples/opencl/imagedrawing/imagewidget.cpp
index b2770ee..9a3c7c5 100644
--- a/examples/opencl/imagedrawing/imagewidget.cpp
+++ b/examples/opencl/imagedrawing/imagewidget.cpp
@@ -53,10 +53,10 @@ ImageWidget::ImageWidget(QWidget *parent)
program = context.buildProgramFromSourceFile(QLatin1String(":/imagedrawing.cl"));
fillRectWithColor = program.createKernel("fillRectWithColor");
- fillRectWithColor.setLocalWorkSize(8, 8);
+ fillRectWithColor.setLocalWorkSize(fillRectWithColor.bestLocalWorkSizeImage2D());
drawImageKernel = program.createKernel("drawImage");
- drawImageKernel.setLocalWorkSize(8, 8);
+ drawImageKernel.setLocalWorkSize(drawImageKernel.bestLocalWorkSizeImage2D());
flower = context.createImage2DCopy
(QImage(QLatin1String(":/flower.jpg")), QCLMemoryObject::ReadOnly);
@@ -104,9 +104,9 @@ void ImageWidget::fillRect(int x, int y, int width, int height,
const QColor& color)
{
// Round up the global work size so we can process the
- // rectangle in 8x8 local work size units. The kernel will
+ // rectangle in local work size units. The kernel will
// ignore pixels that are outside the rectangle limits.
- fillRectWithColor.setGlobalWorkSize((width + 7) & ~7, (height + 7) & ~7);
+ fillRectWithColor.setRoundedGlobalWorkSize(width, height);
fillRectWithColor(surfaceImage, x, y, x + width, y + height, color);
}
@@ -126,9 +126,8 @@ void ImageWidget::drawImage(const QCLImage2D& image, int x, int y, float opacity
if (srcRect.isEmpty() || dstRect.isEmpty())
return;
- // Set the global work size to the destination size rounded up to 8.
- drawImageKernel.setGlobalWorkSize
- ((dstRect.width() + 7) & ~7, (dstRect.height() + 7) & ~7);
+ // Set the global work size to the destination size rounded up to local.
+ drawImageKernel.setRoundedGlobalWorkSize(dstRect.size());
// Draw the image.
QVector4D src(srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height());
@@ -158,9 +157,8 @@ void ImageWidget::drawScaledImage
if (srcRect.isEmpty() || dstRect.isEmpty())
return;
- // Set the global work size to the destination size rounded up to 8.
- drawImageKernel.setGlobalWorkSize
- ((dstRect.width() + 7) & ~7, (dstRect.height() + 7) & ~7);
+ // Set the global work size to the destination size rounded up to local.
+ drawImageKernel.setRoundedGlobalWorkSize(dstRect.size());
// Draw the image.
QVector4D src(srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height());
diff --git a/examples/opencl/pathdrawing/pathwidget.cpp b/examples/opencl/pathdrawing/pathwidget.cpp
index 070341f..57404e1 100644
--- a/examples/opencl/pathdrawing/pathwidget.cpp
+++ b/examples/opencl/pathdrawing/pathwidget.cpp
@@ -52,11 +52,7 @@ PathWidget::PathWidget(QWidget *parent)
program = context.buildProgramFromSourceFile(QLatin1String(":/pathdrawing.cl"));
fillRectWithColor = program.createKernel("fillRectWithColor");
- if (fillRectWithColor.bestLocalWorkSizeImage2D().width() == 8)
- workSize = 8;
- else
- workSize = 1;
- fillRectWithColor.setLocalWorkSize(workSize, workSize);
+ fillRectWithColor.setLocalWorkSize(fillRectWithColor.bestLocalWorkSizeImage2D());
}
PathWidget::~PathWidget()
@@ -91,8 +87,8 @@ void PathWidget::fillRect(int x, int y, int width, int height,
const QColor& color)
{
// Round up the global work size so we can process the
- // rectangle in 8x8 local work size units. The kernel will
+ // rectangle in local work size units. The kernel will
// ignore pixels that are outside the rectangle limits.
- fillRectWithColor.setGlobalWorkSize((width + workSize - 1) & ~(workSize - 1), (height + workSize - 1) & ~(workSize - 1));
+ fillRectWithColor.setRoundedGlobalWorkSize(width, height);
fillRectWithColor(surfaceImage, x, y, x + width, y + height, color);
}
diff --git a/examples/opencl/pathdrawing/pathwidget.h b/examples/opencl/pathdrawing/pathwidget.h
index 512f94a..e084dc4 100644
--- a/examples/opencl/pathdrawing/pathwidget.h
+++ b/examples/opencl/pathdrawing/pathwidget.h
@@ -60,7 +60,6 @@ private:
QCLProgram program;
QCLKernel fillRectWithColor;
- int workSize;
QSize windowSize;
QCLImage2D surfaceImage;
diff --git a/src/opencl/qclkernel.cpp b/src/opencl/qclkernel.cpp
index 58a0db8..e23d820 100644
--- a/src/opencl/qclkernel.cpp
+++ b/src/opencl/qclkernel.cpp
@@ -418,7 +418,7 @@ QCLWorkSize QCLKernel::globalWorkSize() const
/*!
Sets the global work size for this instance of the kernel to \a size.
- \sa globalWorkSize(), setLocalWorkSize()
+ \sa globalWorkSize(), setLocalWorkSize(), setRoundedGlobalWorkSize()
*/
void QCLKernel::setGlobalWorkSize(const QCLWorkSize &size)
{
@@ -443,6 +443,33 @@ void QCLKernel::setGlobalWorkSize(const QCLWorkSize &size)
*/
/*!
+ \fn void QCLKernel::setRoundedGlobalWorkSize(const QCLWorkSize &size)
+
+ Sets the global work size for this instance of the kernel to \a size,
+ after rounding it up to the next multiple of localWorkSize().
+
+ \sa globalWorkSize(), QCLWorkSize::roundTo()
+*/
+
+/*!
+ \fn void QCLKernel::setRoundedGlobalWorkSize(size_t width, size_t height)
+ \overload
+
+ Sets the global work size for this instance of the kernel to
+ \a width x \a height, after rounding it up to the next multiple
+ of localWorkSize().
+*/
+
+/*!
+ \fn void QCLKernel::setRoundedGlobalWorkSize(size_t width, size_t height, size_t depth)
+ \overload
+
+ Sets the global work size for this instance of the kernel to
+ \a width x \a height x \a depth, after rounding it up to the
+ next multiple of localWorkSize().
+*/
+
+/*!
\fn void QCLKernel::setLocalWorkSize(size_t width, size_t height)
\overload
diff --git a/src/opencl/qclkernel.h b/src/opencl/qclkernel.h
index b03676b..e886aa6 100644
--- a/src/opencl/qclkernel.h
+++ b/src/opencl/qclkernel.h
@@ -101,6 +101,10 @@ public:
void setGlobalWorkSize(size_t width, size_t height);
void setGlobalWorkSize(size_t width, size_t height, size_t depth);
+ void setRoundedGlobalWorkSize(const QCLWorkSize &size);
+ void setRoundedGlobalWorkSize(size_t width, size_t height);
+ void setRoundedGlobalWorkSize(size_t width, size_t height, size_t depth);
+
QCLWorkSize localWorkSize() const;
void setLocalWorkSize(const QCLWorkSize &size);
void setLocalWorkSize(size_t width, size_t height);
@@ -298,6 +302,21 @@ inline void QCLKernel::setGlobalWorkSize(size_t width, size_t height, size_t dep
setGlobalWorkSize(QCLWorkSize(width, height, depth));
}
+inline void QCLKernel::setRoundedGlobalWorkSize(const QCLWorkSize &size)
+{
+ setGlobalWorkSize(size.roundTo(localWorkSize()));
+}
+
+inline void QCLKernel::setRoundedGlobalWorkSize(size_t width, size_t height)
+{
+ setRoundedGlobalWorkSize(QCLWorkSize(width, height));
+}
+
+inline void QCLKernel::setRoundedGlobalWorkSize(size_t width, size_t height, size_t depth)
+{
+ setRoundedGlobalWorkSize(QCLWorkSize(width, height, depth));
+}
+
inline void QCLKernel::setLocalWorkSize(size_t width, size_t height)
{
setLocalWorkSize(QCLWorkSize(width, height));
diff --git a/src/opencl/qclworksize.cpp b/src/opencl/qclworksize.cpp
index 840dc39..eb47213 100644
--- a/src/opencl/qclworksize.cpp
+++ b/src/opencl/qclworksize.cpp
@@ -222,6 +222,33 @@ QCLWorkSize QCLWorkSize::toLocalWorkSize(const QCLDevice &device) const
device.maximumWorkItemsPerGroup());
}
+static inline size_t qt_cl_round_to(size_t value, size_t multiple)
+{
+ if (multiple <= 1)
+ return value;
+ size_t remainder = value % multiple;
+ if (!remainder)
+ return value;
+ else
+ return value + multiple - remainder;
+}
+
+/*!
+ Returns the result of rounding this work size up to a multiple of \a size.
+*/
+QCLWorkSize QCLWorkSize::roundTo(const QCLWorkSize &size) const
+{
+ if (m_dim == 1)
+ return QCLWorkSize(qt_cl_round_to(m_sizes[0], size.m_sizes[0]));
+ else if (m_dim == 2)
+ return QCLWorkSize(qt_cl_round_to(m_sizes[0], size.m_sizes[0]),
+ qt_cl_round_to(m_sizes[1], size.m_sizes[1]));
+ else
+ return QCLWorkSize(qt_cl_round_to(m_sizes[0], size.m_sizes[0]),
+ qt_cl_round_to(m_sizes[1], size.m_sizes[1]),
+ qt_cl_round_to(m_sizes[2], size.m_sizes[2]));
+}
+
/*!
Returns the string form of this work size, with components
separated by 'x'.
diff --git a/src/opencl/qclworksize.h b/src/opencl/qclworksize.h
index 290197c..d13bfd5 100644
--- a/src/opencl/qclworksize.h
+++ b/src/opencl/qclworksize.h
@@ -82,6 +82,8 @@ public:
(const QCLWorkSize &maxWorkItemSize, size_t maxItemsPerGroup) const;
QCLWorkSize toLocalWorkSize(const QCLDevice &device) const;
+ QCLWorkSize roundTo(const QCLWorkSize &size) const;
+
QString toString() const;
static QCLWorkSize fromString(const QString &str);
diff --git a/tests/auto/qcl/tst_qcl.cpp b/tests/auto/qcl/tst_qcl.cpp
index 81de300..07d8a02 100644
--- a/tests/auto/qcl/tst_qcl.cpp
+++ b/tests/auto/qcl/tst_qcl.cpp
@@ -65,6 +65,8 @@ private slots:
void eventProfiling();
void sampler();
void workSize();
+ void roundWorkSize_data();
+ void roundWorkSize();
void imageFormat();
void qimageFormat_data();
void qimageFormat();
@@ -605,6 +607,72 @@ void tst_QCL::workSize()
QVERIFY(size4 == QCLWorkSize());
}
+// Test QCLWorkSize::roundTo().
+void tst_QCL::roundWorkSize_data()
+{
+ QTest::addColumn<int>("value");
+ QTest::addColumn<int>("multiple");
+ QTest::addColumn<int>("result");
+
+ QTest::newRow("0-20") << 0 << 20 << 0;
+ QTest::newRow("23-20") << 23 << 20 << 40;
+ QTest::newRow("23-2") << 23 << 2 << 24;
+ QTest::newRow("23-1") << 23 << 1 << 23;
+ QTest::newRow("23-0") << 23 << 0 << 23;
+}
+void tst_QCL::roundWorkSize()
+{
+ QFETCH(int, value);
+ QFETCH(int, multiple);
+ QFETCH(int, result);
+
+ size_t svalue = size_t(value);
+ size_t smultiple = size_t(multiple);
+ size_t sresult = size_t(result);
+
+ QCLWorkSize size1(svalue);
+ QCLWorkSize size2 = size1.roundTo(smultiple);
+ QCOMPARE(size2.width(), sresult);
+ QCOMPARE(size2.height(), size_t(1));
+ QCOMPARE(size2.depth(), size_t(1));
+ QCOMPARE(size2.dimensions(), size_t(1));
+
+ QCLWorkSize size3(svalue, 1);
+ QCLWorkSize size4 = size3.roundTo(QCLWorkSize(smultiple, smultiple));
+ QCOMPARE(size4.width(), sresult);
+ QCOMPARE(size4.height(), smultiple ? smultiple : size_t(1));
+ QCOMPARE(size4.depth(), size_t(1));
+ QCOMPARE(size4.dimensions(), size_t(2));
+
+ QCLWorkSize size5(1, svalue);
+ QCLWorkSize size6 = size5.roundTo(QCLWorkSize(smultiple, smultiple));
+ QCOMPARE(size6.width(), smultiple ? smultiple : size_t(1));
+ QCOMPARE(size6.height(), sresult);
+ QCOMPARE(size6.depth(), size_t(1));
+ QCOMPARE(size6.dimensions(), size_t(2));
+
+ QCLWorkSize size7(svalue, 1, 1);
+ QCLWorkSize size8 = size7.roundTo(QCLWorkSize(smultiple, smultiple, smultiple));
+ QCOMPARE(size8.width(), sresult);
+ QCOMPARE(size8.height(), smultiple ? smultiple : size_t(1));
+ QCOMPARE(size8.depth(), smultiple ? smultiple : size_t(1));
+ QCOMPARE(size8.dimensions(), size_t(3));
+
+ QCLWorkSize size9(1, svalue, 1);
+ QCLWorkSize size10 = size9.roundTo(QCLWorkSize(smultiple, smultiple, smultiple));
+ QCOMPARE(size10.width(), smultiple ? smultiple : size_t(1));
+ QCOMPARE(size10.height(), sresult);
+ QCOMPARE(size10.depth(), smultiple ? smultiple : size_t(1));
+ QCOMPARE(size10.dimensions(), size_t(3));
+
+ QCLWorkSize size11(1, 1, svalue);
+ QCLWorkSize size12 = size11.roundTo(QCLWorkSize(smultiple, smultiple, smultiple));
+ QCOMPARE(size12.width(), smultiple ? smultiple : size_t(1));
+ QCOMPARE(size12.height(), smultiple ? smultiple : size_t(1));
+ QCOMPARE(size12.depth(), sresult);
+ QCOMPARE(size12.dimensions(), size_t(3));
+}
+
// Test QCLImageFormat.
void tst_QCL::imageFormat()
{