mandelbrot.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. //---------------------------------------------------------------------------//
  2. // Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@gmail.com>
  3. //
  4. // Distributed under the Boost Software License, Version 1.0
  5. // See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt
  7. //
  8. // See http://boostorg.github.com/compute for more information.
  9. //---------------------------------------------------------------------------//
  10. #include <iostream>
  11. #include <algorithm>
  12. #include <QtGlobal>
  13. #if QT_VERSION >= 0x050000
  14. #include <QtWidgets>
  15. #else
  16. #include <QtGui>
  17. #endif
  18. #include <QtOpenGL>
  19. #ifndef Q_MOC_RUN
  20. #include <boost/compute/command_queue.hpp>
  21. #include <boost/compute/kernel.hpp>
  22. #include <boost/compute/program.hpp>
  23. #include <boost/compute/system.hpp>
  24. #include <boost/compute/interop/opengl.hpp>
  25. #include <boost/compute/utility/dim.hpp>
  26. #include <boost/compute/utility/source.hpp>
  27. #endif // Q_MOC_RUN
  28. namespace compute = boost::compute;
  29. // opencl source code
  30. const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
  31. // map value to color
  32. float4 color(uint i)
  33. {
  34. uchar c = i;
  35. uchar x = 35;
  36. uchar y = 25;
  37. uchar z = 15;
  38. uchar max = 255;
  39. if(i == 256)
  40. return (float4)(0, 0, 0, 255);
  41. else
  42. return (float4)(max-x*i, max-y*i, max-z*i, max) / 255.f;
  43. }
  44. __kernel void mandelbrot(__write_only image2d_t image)
  45. {
  46. const uint x_coord = get_global_id(0);
  47. const uint y_coord = get_global_id(1);
  48. const uint width = get_global_size(0);
  49. const uint height = get_global_size(1);
  50. float x_origin = ((float) x_coord / width) * 3.25f - 2.0f;
  51. float y_origin = ((float) y_coord / height) * 2.5f - 1.25f;
  52. float x = 0.0f;
  53. float y = 0.0f;
  54. uint i = 0;
  55. while(x*x + y*y <= 4.f && i < 256){
  56. float tmp = x*x - y*y + x_origin;
  57. y = 2*x*y + y_origin;
  58. x = tmp;
  59. i++;
  60. }
  61. int2 coord = { x_coord, y_coord };
  62. write_imagef(image, coord, color(i));
  63. };
  64. );
  65. class MandelbrotWidget : public QGLWidget
  66. {
  67. Q_OBJECT
  68. public:
  69. MandelbrotWidget(QWidget *parent = 0);
  70. ~MandelbrotWidget();
  71. void initializeGL();
  72. void resizeGL(int width, int height);
  73. void paintGL();
  74. void keyPressEvent(QKeyEvent* event);
  75. private:
  76. compute::context context_;
  77. compute::command_queue queue_;
  78. compute::program program_;
  79. GLuint gl_texture_;
  80. compute::opengl_texture cl_texture_;
  81. };
  82. MandelbrotWidget::MandelbrotWidget(QWidget *parent)
  83. : QGLWidget(parent)
  84. {
  85. gl_texture_ = 0;
  86. }
  87. MandelbrotWidget::~MandelbrotWidget()
  88. {
  89. }
  90. void MandelbrotWidget::initializeGL()
  91. {
  92. // setup opengl
  93. glDisable(GL_LIGHTING);
  94. // create the OpenGL/OpenCL shared context
  95. context_ = compute::opengl_create_shared_context();
  96. // get gpu device
  97. compute::device gpu = context_.get_device();
  98. std::cout << "device: " << gpu.name() << std::endl;
  99. // setup command queue
  100. queue_ = compute::command_queue(context_, gpu);
  101. // build mandelbrot program
  102. program_ = compute::program::create_with_source(source, context_);
  103. program_.build();
  104. }
  105. void MandelbrotWidget::resizeGL(int width, int height)
  106. {
  107. #if QT_VERSION >= 0x050000
  108. // scale height/width based on device pixel ratio
  109. width /= windowHandle()->devicePixelRatio();
  110. height /= windowHandle()->devicePixelRatio();
  111. #endif
  112. // resize viewport
  113. glViewport(0, 0, width, height);
  114. // delete old texture
  115. if(gl_texture_){
  116. glDeleteTextures(1, &gl_texture_);
  117. gl_texture_ = 0;
  118. }
  119. // generate new texture
  120. glGenTextures(1, &gl_texture_);
  121. glBindTexture(GL_TEXTURE_2D, gl_texture_);
  122. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  123. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  124. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  125. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  126. glTexImage2D(
  127. GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0
  128. );
  129. // create opencl object for the texture
  130. cl_texture_ = compute::opengl_texture(
  131. context_, GL_TEXTURE_2D, 0, gl_texture_, CL_MEM_WRITE_ONLY
  132. );
  133. }
  134. void MandelbrotWidget::paintGL()
  135. {
  136. using compute::dim;
  137. float w = width();
  138. float h = height();
  139. glMatrixMode(GL_PROJECTION);
  140. glLoadIdentity();
  141. glOrtho(0.0, w, 0.0, h, -1.0, 1.0);
  142. glMatrixMode(GL_MODELVIEW);
  143. glLoadIdentity();
  144. // setup the mandelbrot kernel
  145. compute::kernel kernel(program_, "mandelbrot");
  146. kernel.set_arg(0, cl_texture_);
  147. // acquire the opengl texture so it can be used in opencl
  148. compute::opengl_enqueue_acquire_gl_objects(1, &cl_texture_.get(), queue_);
  149. // execute the mandelbrot kernel
  150. queue_.enqueue_nd_range_kernel(
  151. kernel, dim(0, 0), dim(width(), height()), dim(1, 1)
  152. );
  153. // release the opengl texture so it can be used by opengl
  154. compute::opengl_enqueue_release_gl_objects(1, &cl_texture_.get(), queue_);
  155. // ensure opencl is finished before rendering in opengl
  156. queue_.finish();
  157. // draw a single quad with the mandelbrot image texture
  158. glEnable(GL_TEXTURE_2D);
  159. glBindTexture(GL_TEXTURE_2D, gl_texture_);
  160. glBegin(GL_QUADS);
  161. glTexCoord2f(0, 0); glVertex2f(0, 0);
  162. glTexCoord2f(0, 1); glVertex2f(0, h);
  163. glTexCoord2f(1, 1); glVertex2f(w, h);
  164. glTexCoord2f(1, 0); glVertex2f(w, 0);
  165. glEnd();
  166. }
  167. void MandelbrotWidget::keyPressEvent(QKeyEvent* event)
  168. {
  169. if(event->key() == Qt::Key_Escape) {
  170. this->close();
  171. }
  172. }
  173. // the mandelbrot example shows how to create a mandelbrot image in
  174. // OpenCL and render the image as a texture in OpenGL
  175. int main(int argc, char *argv[])
  176. {
  177. QApplication app(argc, argv);
  178. MandelbrotWidget widget;
  179. widget.show();
  180. return app.exec();
  181. }
  182. #include "mandelbrot.moc"