1
0

ClGenerators.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. #include "ClGenerators.h"
  2. #include "Mandel.h"
  3. #include "OpenClInternal.h"
  4. #include "OpenClCode.h"
  5. #ifdef WITH_OPENCL
  6. #include <iostream>
  7. #include <iterator>
  8. #include <utility>
  9. using namespace cl;
  10. using mnd::ClGenerator;
  11. using mnd::ClGeneratorFloat;
  12. using mnd::ClGeneratorDoubleFloat;
  13. using mnd::ClGeneratorDouble;
  14. using mnd::ClGeneratorDoubleDouble;
  15. using mnd::ClGeneratorQuadDouble;
  16. using mnd::ClGenerator128;
  17. using mnd::ClGenerator64;
  18. Platform getPlatform() {
  19. /* Returns the first platform found. */
  20. std::vector<Platform> all_platforms;
  21. Platform::get(&all_platforms);
  22. if (all_platforms.size() == 0) {
  23. std::cout << "No platforms found. Check OpenCL installation!\n";
  24. exit(1);
  25. }
  26. for (auto& p : all_platforms) {
  27. std::string name = p.getInfo<CL_PLATFORM_NAME>();
  28. std::string profile = p.getInfo<CL_PLATFORM_PROFILE>();
  29. printf("Platform: %s, %s\n", name.c_str(), profile.c_str());
  30. }
  31. return all_platforms[0];
  32. }
  33. Device getDevice(Platform& platform, int i, bool display = false) {
  34. /* Returns the deviced specified by the index i on platform.
  35. * If display is true, then all of the platforms are listed.
  36. */
  37. std::vector<Device> all_devices;
  38. platform.getDevices(CL_DEVICE_TYPE_ALL, &all_devices);
  39. if (all_devices.size() == 0) {
  40. std::cout << "No devices found. Check OpenCL installation!\n";
  41. exit(1);
  42. }
  43. if (display) {
  44. for (::size_t j = 0; j < all_devices.size(); j++) {
  45. printf("Device %d: %s\n", int(j), all_devices[j].getInfo<CL_DEVICE_NAME>().c_str());
  46. printf("preferred float width: %d\n", all_devices[j].getInfo<CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT>());
  47. printf("vendor: %s\n", all_devices[j].getInfo<CL_DEVICE_VENDOR>().c_str());
  48. }
  49. }
  50. return all_devices[i];
  51. }
  52. ClGenerator::ClGenerator(mnd::MandelDevice& device, const std::string& source, mnd::Precision type) :
  53. MandelGenerator{ type },
  54. device{ device },
  55. context{ device.getClDevice().context }
  56. {
  57. const cl::Device& dev = device.getClDevice().device;
  58. Program::Sources sources;
  59. sources.push_back({ source.c_str(), source.length() });
  60. program = Program{ context, sources };
  61. if (program.build({ dev }) != CL_SUCCESS) {
  62. printf("code -> %s\n", source.c_str());
  63. throw std::string(program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(dev));
  64. }
  65. queue = CommandQueue(context, dev);
  66. /*Platform p = getPlatform();
  67. device = getDevice(p, 0, true);
  68. context = Context{ device };
  69. Program::Sources sources;
  70. std::string kcode = this->getKernelCode();
  71. sources.push_back({ kcode.c_str(), kcode.length() });
  72. program = Program{ context, sources };
  73. if (program.build({ device }) != CL_SUCCESS) {
  74. std::cout << "Error building: " << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device) << std::endl;
  75. exit(1);
  76. }
  77. queue = CommandQueue(context, device);*/
  78. }
  79. ClGenerator::~ClGenerator(void)
  80. {
  81. queue.flush();
  82. queue.finish();
  83. }
  84. mnd::MandelDevice* ClGenerator::getDevice(void)
  85. {
  86. return &device;
  87. }
  88. ClGeneratorFloat::ClGeneratorFloat(mnd::MandelDevice& device, const std::string& code) :
  89. ClGenerator{ device, code, mnd::Precision::FLOAT }
  90. {
  91. const cl::Device& dev = device.getClDevice().device;
  92. useVec = dev.getInfo<CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT>() >= 4;
  93. kernel = Kernel(program, useVec ? "iterate_vec4" : "iterate");
  94. }
  95. void ClGeneratorFloat::generate(const mnd::MandelInfo& info, float* data)
  96. {
  97. ::size_t bufferSize = info.bWidth * info.bHeight * sizeof(float);
  98. Buffer buffer_A(context, CL_MEM_WRITE_ONLY, bufferSize);
  99. float pixelScaleX = float(info.view.width / info.bWidth);
  100. float pixelScaleY = float(info.view.height / info.bHeight);
  101. kernel.setArg(0, buffer_A);
  102. kernel.setArg(1, int(info.bWidth));
  103. kernel.setArg(2, float(info.view.x));
  104. kernel.setArg(3, float(info.view.y));
  105. kernel.setArg(4, float(pixelScaleX));
  106. kernel.setArg(5, float(pixelScaleY));
  107. kernel.setArg(6, int(info.maxIter));
  108. kernel.setArg(7, int(info.smooth ? 1 : 0));
  109. kernel.setArg(8, int(info.julia ? 1 : 0));
  110. kernel.setArg(9, float(info.juliaX));
  111. kernel.setArg(10, float(info.juliaY));
  112. if (useVec) {
  113. queue.enqueueNDRangeKernel(kernel, 0, NDRange(info.bWidth * info.bHeight / 4));
  114. } else {
  115. queue.enqueueNDRangeKernel(kernel, 0, NDRange(info.bWidth * info.bHeight));
  116. }
  117. cl::Event event;
  118. queue.enqueueReadBuffer(buffer_A, CL_FALSE, 0, bufferSize, data, nullptr, &event);
  119. queue.flush();
  120. event.wait();
  121. }
  122. std::string ClGeneratorFloat::getKernelCode(bool smooth) const
  123. {
  124. return mnd::getFloat_cl();
  125. }
  126. ClGeneratorDoubleFloat::ClGeneratorDoubleFloat(mnd::MandelDevice& device) :
  127. ClGenerator{ device, this->getKernelCode(false), mnd::Precision::DOUBLE_FLOAT }
  128. {
  129. kernel = Kernel(program, "iterate");
  130. }
  131. std::pair<float, float> twoSum(float a, float b) {
  132. float s = a + b;
  133. float v = s - a;
  134. float r = (a - (s - v)) + (b - v);
  135. return { s, r };
  136. }
  137. std::pair<float, float> split(float a) {
  138. float c = (4096 + 1) * a;
  139. float abig = c - a;
  140. float ahi = c - abig;
  141. float alo = a - ahi;
  142. return { ahi, alo };
  143. }
  144. std::pair<float, float> twoProd(float a, float b) {
  145. float x = a * b;
  146. auto aex = split(a);
  147. auto bex = split(b);
  148. float errx = x - (aex.first * bex.first);
  149. float erry = errx - (aex.second * bex.first);
  150. float errz = erry - (aex.first * bex.second);
  151. float y = (aex.second * bex.second) - errz;
  152. return { x, y };
  153. }
  154. std::pair<float, float> add(std::pair<float, float> a, std::pair<float, float> b) {
  155. float r = a.first + b.first;
  156. float s;
  157. if (fabs(a.first) >= fabs(b.first)) {
  158. s = (((a.first - r) + b.first) + b.second) + a.second;
  159. }
  160. else {
  161. s = (((b.first - r) + a.first) + a.second) + b.second;
  162. }
  163. return twoSum(r, s);
  164. }
  165. std::pair<float, float> mul(std::pair<float, float> a, std::pair<float, float> b) {
  166. auto t = twoProd(a.first, b.first);
  167. t.second += ((a.first * b.second) + (a.second * b.first));
  168. return twoSum(t.first, t.second);
  169. }
  170. std::pair<float, float> mulFloat(std::pair<float, float> a, float b) {
  171. std::pair<float, float> t = twoProd(a.first, b);
  172. float t3 = (a.second * b) + t.second;
  173. return twoSum(t.first, t.second);
  174. }
  175. void ClGeneratorDoubleFloat::generate(const mnd::MandelInfo& info, float* data)
  176. {
  177. ::size_t bufferSize = info.bWidth * info.bHeight * sizeof(float);
  178. Buffer buffer_A(context, CL_MEM_WRITE_ONLY, bufferSize);
  179. mnd::LightDoubleFloat pixelScX = double(info.view.width / info.bWidth);
  180. mnd::LightDoubleFloat pixelScY = double(info.view.height / info.bHeight);
  181. mnd::LightDoubleFloat x = double(info.view.x);
  182. mnd::LightDoubleFloat y = double(info.view.y);
  183. mnd::LightDoubleFloat jx = double(info.juliaX);
  184. mnd::LightDoubleFloat jy = double(info.juliaY);
  185. kernel.setArg(0, buffer_A);
  186. kernel.setArg(1, int(info.bWidth));
  187. kernel.setArg(2, x[0]);
  188. kernel.setArg(3, x[1]);
  189. kernel.setArg(4, y[0]);
  190. kernel.setArg(5, y[1]);
  191. kernel.setArg(6, pixelScX[0]);
  192. kernel.setArg(7, pixelScX[1]);
  193. kernel.setArg(8, pixelScY[0]);
  194. kernel.setArg(9, pixelScY[1]);
  195. kernel.setArg(10, int(info.maxIter));
  196. kernel.setArg(11, int(info.smooth ? 1 : 0));
  197. kernel.setArg(12, int(info.julia ? 1 : 0));
  198. kernel.setArg(13, jx[0]);
  199. kernel.setArg(14, jx[1]);
  200. kernel.setArg(15, jy[0]);
  201. kernel.setArg(16, jy[1]);
  202. cl_int result = queue.enqueueNDRangeKernel(kernel, 0, NDRange(info.bWidth * info.bHeight));
  203. queue.enqueueReadBuffer(buffer_A, CL_TRUE, 0, bufferSize, data);
  204. }
  205. std::string ClGeneratorDoubleFloat::getKernelCode(bool smooth) const
  206. {
  207. return getDoubleFloat_cl();
  208. }
  209. ClGeneratorDouble::ClGeneratorDouble(mnd::MandelDevice& device, const std::string& source) :
  210. ClGenerator{ device, source, mnd::Precision::DOUBLE }
  211. {
  212. kernel = Kernel(program, "iterate");
  213. }
  214. void ClGeneratorDouble::generate(const mnd::MandelInfo& info, float* data)
  215. {
  216. ::size_t bufferSize = info.bWidth * info.bHeight * sizeof(float);
  217. Buffer buffer_A(context, CL_MEM_WRITE_ONLY, bufferSize);
  218. double pixelScaleX = double(info.view.width / info.bWidth);
  219. double pixelScaleY = double(info.view.height / info.bHeight);
  220. kernel.setArg(0, buffer_A);
  221. kernel.setArg(1, int(info.bWidth));
  222. kernel.setArg(2, double(info.view.x));
  223. kernel.setArg(3, double(info.view.y));
  224. kernel.setArg(4, double(pixelScaleX));
  225. kernel.setArg(5, double(pixelScaleY));
  226. kernel.setArg(6, int(info.maxIter));
  227. kernel.setArg(7, int(info.smooth ? 1 : 0));
  228. kernel.setArg(8, int(info.julia ? 1 : 0));
  229. kernel.setArg(9, double(info.juliaX));
  230. kernel.setArg(10, double(info.juliaY));
  231. cl_int result = queue.enqueueNDRangeKernel(kernel, 0, NDRange(info.bWidth * info.bHeight));
  232. cl::Event event;
  233. queue.enqueueReadBuffer(buffer_A, CL_FALSE, 0, bufferSize, data, nullptr, &event);
  234. queue.flush();
  235. event.wait();
  236. }
  237. std::string ClGeneratorDouble::getKernelCode(bool smooth) const
  238. {
  239. return
  240. "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"
  241. "__kernel void iterate(__global float* A, const int width, double xl, double yt, double pixelScaleX, double pixelScaleY, int max, int smooth) {\n"
  242. " int index = get_global_id(0);\n"
  243. " int x = index % width;"
  244. " int y = index / width;"
  245. " double a = x * pixelScaleX + xl;"
  246. " double b = y * pixelScaleY + yt;"
  247. " double ca = a;"
  248. " double cb = b;"
  249. ""
  250. " int n = 0;"
  251. " while (n < max - 1) {"
  252. " double aa = a * a;"
  253. " double bb = b * b;"
  254. " double ab = a * b;"
  255. " if (aa + bb > 16) break;"
  256. " a = aa - bb + ca;"
  257. " b = ab + ab + cb;"
  258. " n++;"
  259. " }\n"
  260. // N + 1 - log (log |Z(N)|) / log 2
  261. " if (n >= max - 1)\n"
  262. " A[index] = max;\n"
  263. " else {"
  264. " if (smooth != 0)\n"
  265. " A[index] = ((float)n) + 1 - log(log((float)(a * a + b * b)) / 2) / log(2.0f);\n"
  266. " else\n"
  267. " A[index] = ((float)n);\n"
  268. " }"
  269. "}";
  270. }
  271. ClGeneratorDoubleDouble::ClGeneratorDoubleDouble(mnd::MandelDevice& device) :
  272. ClGenerator{ device, getDoubleDouble_cl(), mnd::Precision::DOUBLE_DOUBLE }
  273. {
  274. kernel = Kernel(program, "iterate");
  275. }
  276. void ClGeneratorDoubleDouble::generate(const mnd::MandelInfo& info, float* data)
  277. {
  278. ::size_t bufferSize = info.bWidth * info.bHeight * sizeof(float);
  279. Buffer buffer_A(context, CL_MEM_WRITE_ONLY, bufferSize);
  280. mnd::DoubleDouble x = mnd::convert<mnd::DoubleDouble>(info.view.x);
  281. mnd::DoubleDouble y = mnd::convert<mnd::DoubleDouble>(info.view.y);
  282. mnd::DoubleDouble psx = mnd::convert<mnd::DoubleDouble>(info.view.width / info.bWidth);
  283. mnd::DoubleDouble psy = mnd::convert<mnd::DoubleDouble>(info.view.height / info.bHeight);
  284. mnd::DoubleDouble juliaX = mnd::convert<mnd::DoubleDouble>(info.juliaX);
  285. mnd::DoubleDouble juliaY = mnd::convert<mnd::DoubleDouble>(info.juliaY);
  286. kernel.setArg(0, buffer_A);
  287. kernel.setArg(1, int(info.bWidth));
  288. kernel.setArg(2, x.x[0]);
  289. kernel.setArg(3, x.x[1]);
  290. kernel.setArg(4, y.x[0]);
  291. kernel.setArg(5, y.x[1]);
  292. kernel.setArg(6, psx.x[0]);
  293. kernel.setArg(7, psx.x[1]);
  294. kernel.setArg(8, psy.x[0]);
  295. kernel.setArg(9, psy.x[1]);
  296. kernel.setArg(10, int(info.maxIter));
  297. kernel.setArg(11, int(info.smooth ? 1 : 0));
  298. kernel.setArg(12, info.julia ? 1 : 0);
  299. kernel.setArg(13, juliaX.x[0]);
  300. kernel.setArg(14, juliaX.x[1]);
  301. kernel.setArg(15, juliaY.x[0]);
  302. kernel.setArg(16, juliaY.x[1]);
  303. cl_int result = queue.enqueueNDRangeKernel(kernel, 0, NDRange(info.bWidth * info.bHeight));
  304. queue.enqueueReadBuffer(buffer_A, CL_TRUE, 0, bufferSize, data);
  305. }
  306. std::string ClGeneratorDoubleDouble::getKernelCode(bool smooth) const
  307. {
  308. return getDoubleDouble_cl();
  309. }
  310. ClGeneratorQuadDouble::ClGeneratorQuadDouble(mnd::MandelDevice& device) :
  311. ClGenerator{ device, getQuadDouble_cl(), mnd::Precision::QUAD_DOUBLE }
  312. {
  313. kernel = Kernel(program, "iterate");
  314. }
  315. void ClGeneratorQuadDouble::generate(const mnd::MandelInfo& info, float* data)
  316. {
  317. ::size_t bufferSize = info.bWidth * info.bHeight * sizeof(float);
  318. Buffer buffer_A(context, CL_MEM_WRITE_ONLY, bufferSize);
  319. mnd::QuadDouble x = mnd::convert<mnd::QuadDouble>(info.view.x);
  320. mnd::QuadDouble y = mnd::convert<mnd::QuadDouble>(info.view.y);
  321. mnd::QuadDouble psx = mnd::convert<mnd::QuadDouble>(info.view.width / info.bWidth);
  322. mnd::QuadDouble psy = mnd::convert<mnd::QuadDouble>(info.view.height / info.bHeight);
  323. mnd::QuadDouble jx = mnd::convert<mnd::QuadDouble>(info.juliaX);
  324. mnd::QuadDouble jy = mnd::convert<mnd::QuadDouble>(info.juliaY);
  325. kernel.setArg(0, buffer_A);
  326. kernel.setArg(1, int(info.bWidth));
  327. kernel.setArg(2, x.x[0]);
  328. kernel.setArg(3, x.x[1]);
  329. kernel.setArg(4, x.x[2]);
  330. kernel.setArg(5, x.x[3]);
  331. kernel.setArg(6, y.x[0]);
  332. kernel.setArg(7, y.x[1]);
  333. kernel.setArg(8, y.x[2]);
  334. kernel.setArg(9, y.x[3]);
  335. kernel.setArg(10, psx.x[0]);
  336. kernel.setArg(11, psx.x[1]);
  337. kernel.setArg(12, psx.x[2]);
  338. kernel.setArg(13, psx.x[3]);
  339. kernel.setArg(14, psy.x[0]);
  340. kernel.setArg(15, psy.x[1]);
  341. kernel.setArg(16, psy.x[2]);
  342. kernel.setArg(17, psy.x[3]);
  343. kernel.setArg(18, int(info.maxIter));
  344. kernel.setArg(19, int(info.smooth ? 1 : 0));
  345. kernel.setArg(20, int(info.julia ? 1 : 0));
  346. kernel.setArg(21, jx.x[0]);
  347. kernel.setArg(22, jx.x[1]);
  348. kernel.setArg(23, jx.x[2]);
  349. kernel.setArg(24, jx.x[3]);
  350. kernel.setArg(25, jy.x[0]);
  351. kernel.setArg(26, jy.x[1]);
  352. kernel.setArg(27, jy.x[2]);
  353. kernel.setArg(28, jy.x[3]);
  354. cl_int result = queue.enqueueNDRangeKernel(kernel, 0, NDRange(info.bWidth * info.bHeight));
  355. queue.enqueueReadBuffer(buffer_A, CL_TRUE, 0, bufferSize, data);
  356. }
  357. std::string ClGeneratorQuadDouble::getKernelCode(bool smooth) const
  358. {
  359. return getQuadDouble_cl();
  360. }
  361. ClGenerator128::ClGenerator128(mnd::MandelDevice& device) :
  362. ClGenerator{ device, getFixed512_cl(), mnd::Precision::FIXED128 }
  363. {
  364. kernel = Kernel(program, "iterate");
  365. }
  366. void ClGenerator128::generate(const mnd::MandelInfo& info, float* data)
  367. {
  368. ::size_t bufferSize = info.bWidth * info.bHeight * sizeof(float);
  369. Buffer buffer_A(context, CL_MEM_WRITE_ONLY, bufferSize);
  370. float pixelScaleX = float(info.view.width / info.bWidth);
  371. float pixelScaleY = float(info.view.height / info.bHeight);
  372. using ull = unsigned long long;
  373. ull x1 = ull(double(info.view.x) * 0x10000ULL);
  374. ull x2 = 0;
  375. ull y1 = ull(double(info.view.y) * 0x10000ULL);
  376. ull y2 = 0;
  377. ull w1 = ull(double(pixelScaleX) * 0x10000ULL);
  378. ull w2 = 0;
  379. ull h1 = ull(double(pixelScaleY) * 0x10000ULL);
  380. ull h2 = 0;
  381. ull jx1 = ull(double(info.juliaX) * 0x10000ULL);
  382. ull jx2 = 0;
  383. ull jy1 = ull(double(info.juliaY) * 0x10000ULL);
  384. ull jy2 = 0;
  385. kernel.setArg(0, buffer_A);
  386. kernel.setArg(1, int(info.bWidth));
  387. kernel.setArg(2, ull(x1));
  388. kernel.setArg(3, ull(x2));
  389. kernel.setArg(4, ull(y1));
  390. kernel.setArg(5, ull(y2));
  391. kernel.setArg(6, ull(w1));
  392. kernel.setArg(7, ull(w2));
  393. kernel.setArg(8, ull(h1));
  394. kernel.setArg(9, ull(h2));
  395. kernel.setArg(10, int(info.maxIter));
  396. kernel.setArg(11, int(info.smooth ? 1 : 0));
  397. kernel.setArg(12, int(info.julia ? 1 : 0));
  398. kernel.setArg(13, ull(jx1));
  399. kernel.setArg(14, ull(jx2));
  400. kernel.setArg(15, ull(jy1));
  401. kernel.setArg(16, ull(jy2));
  402. queue.enqueueNDRangeKernel(kernel, 0, NDRange(info.bWidth * info.bHeight));
  403. queue.enqueueReadBuffer(buffer_A, CL_TRUE, 0, bufferSize, data);
  404. }
  405. std::string ClGenerator128::getKernelCode(bool smooth) const
  406. {
  407. /*//fprintf(stderr, "starting file read\n");
  408. std::ifstream t("mandel128.cl");
  409. std::string str((std::istreambuf_iterator<char>(t)),
  410. std::istreambuf_iterator<char>());
  411. //fprintf(stderr, "%s\n", str);
  412. return str;*/
  413. return getFixed128_cl();
  414. }
  415. ClGenerator64::ClGenerator64(mnd::MandelDevice& device) :
  416. ClGenerator{ device, getFixed64_cl(), mnd::Precision::FIXED64 }
  417. {
  418. kernel = Kernel(program, "iterate");
  419. }
  420. #include "CpuGenerators.h"
  421. void ClGenerator64::generate(const mnd::MandelInfo& info, float* data)
  422. {
  423. ::size_t bufferSize = info.bWidth * info.bHeight * sizeof(float);
  424. Buffer buffer_A(context, CL_MEM_WRITE_ONLY, bufferSize);
  425. float pixelScaleX = float(info.view.width / info.bWidth);
  426. float pixelScaleY = float(info.view.height / info.bHeight);
  427. using ull = uint64_t;
  428. ull x = ull(::round(double(info.view.x) * (1LL << 48)));
  429. ull y = ull(::round(double(info.view.y) * (1LL << 48)));
  430. ull w = ull(::round(double(pixelScaleX) * (1LL << 48)));
  431. ull h = ull(::round(double(pixelScaleY) * (1LL << 48)));
  432. ull jx = ull(::round(double(info.juliaX) * (1LL << 48)));
  433. ull jy = ull(::round(double(info.juliaY) * (1LL << 48)));
  434. //x = 0;
  435. //y = 0;
  436. kernel.setArg(0, buffer_A);
  437. kernel.setArg(1, int(info.bWidth));
  438. kernel.setArg(2, ull(x));
  439. kernel.setArg(3, ull(y));
  440. kernel.setArg(4, ull(w));
  441. kernel.setArg(5, ull(h));
  442. kernel.setArg(6, int(info.maxIter));
  443. kernel.setArg(7, int(info.smooth ? 1 : 0));
  444. kernel.setArg(8, int(info.julia ? 1 : 0));
  445. kernel.setArg(9, ull(jx));
  446. kernel.setArg(10, ull(jy));
  447. queue.enqueueNDRangeKernel(kernel, 0, NDRange(info.bWidth * info.bHeight));
  448. queue.enqueueReadBuffer(buffer_A, CL_TRUE, 0, bufferSize, data);
  449. //CpuGenerator<Fixed64> fx;
  450. //fx.generate(info, data);
  451. }
  452. std::string ClGenerator64::getKernelCode(bool smooth) const
  453. {
  454. /*//fprintf(stderr, "starting file read\n");
  455. std::ifstream t("mandel128.cl");
  456. std::string str((std::istreambuf_iterator<char>(t)),
  457. std::istreambuf_iterator<char>());
  458. //fprintf(stderr, "%s\n", str);
  459. return str;*/
  460. return getFixed64_cl();
  461. }
  462. #endif // WITH_OPENCL