Mali OpenCL SDK v1.1.0
 All Classes Files Functions Variables Macros Pages
mandelbrot.cpp
Go to the documentation of this file.
1 /*
2  * This confidential and proprietary software may be used only as
3  * authorised by a licensing agreement from ARM Limited
4  * (C) COPYRIGHT 2013 ARM Limited
5  * ALL RIGHTS RESERVED
6  * The entire notice above must be reproduced on all authorised
7  * copies and copies may only be made to the extent permitted
8  * by a licensing agreement from ARM Limited.
9  */
10 
11 #include "common.h"
12 #include "image.h"
13 
14 #include <CL/cl.h>
15 #include <iostream>
16 #include <fstream>
17 #include <sstream>
18 #include <cstddef>
19 #include <cmath>
20 #include <sys/time.h>
21 
22 using namespace std;
23 
33 int main(void)
34 {
35  cl_context context = 0;
36  cl_command_queue commandQueue = 0;
37  cl_program program = 0;
38  cl_device_id device = 0;
39  cl_kernel kernel = 0;
40  const unsigned int numberOfMemoryObjects = 1;
41  cl_mem memoryObjects[numberOfMemoryObjects] = {0};
42  cl_int errorNumber;
43 
44  if (!createContext(&context))
45  {
46  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
47  cerr << "Failed to create an OpenCL context. " << __FILE__ << ":"<< __LINE__ << endl;
48  return 1;
49  }
50 
51  if (!createCommandQueue(context, &commandQueue, &device))
52  {
53  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
54  cerr << "Failed to create the OpenCL command queue. " << __FILE__ << ":"<< __LINE__ << endl;
55  return 1;
56  }
57 
58  if (!createProgram(context, device, "assets/mandelbrot.cl", &program))
59  {
60  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
61  cerr << "Failed to create OpenCL program." << __FILE__ << ":"<< __LINE__ << endl;
62  return 1;
63  }
64 
65  kernel = clCreateKernel(program, "mandelbrot", &errorNumber);
66  if (!checkSuccess(errorNumber))
67  {
68  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
69  cerr << "Failed to create OpenCL kernel. " << __FILE__ << ":"<< __LINE__ << endl;
70  return 1;
71  }
72 
73  /* Width and height of the Mandelbrot data you want to be produced. */
74  cl_int width = 4096;
75  cl_int height = 3280;
76 
77  /* The output buffer is the size of the Mandelbrot data. */
78  size_t bufferSize = width * height * sizeof(cl_uchar);
79 
80  /* Create an output buffer for final data. */
81  memoryObjects[0] = clCreateBuffer(context, CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, bufferSize, NULL, &errorNumber);
82  if (!checkSuccess(errorNumber))
83  {
84  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
85  cerr << "Failed to create OpenCL buffer. " << __FILE__ << ":"<< __LINE__ << endl;
86  return 1;
87  }
88 
89  /* Setup the kernel arguments. */
90  bool setKernelArgumentsSuccess = true;
91  setKernelArgumentsSuccess &= checkSuccess(clSetKernelArg(kernel, 0, sizeof(cl_mem), &memoryObjects[0]));
92  setKernelArgumentsSuccess &= checkSuccess(clSetKernelArg(kernel, 1, sizeof(cl_int), &width));
93  setKernelArgumentsSuccess &= checkSuccess(clSetKernelArg(kernel, 2, sizeof(cl_int), &height));
94 
95  if (!setKernelArgumentsSuccess)
96  {
97  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
98  cerr << "Failed setting OpenCL kernel arguments. " << __FILE__ << ":"<< __LINE__ << endl;
99  return 1;
100  }
101 
102  /* An event to associate with the Kernel. Allows us to retreive profiling information later. */
103  cl_event event = 0;
104 
105  /* [Kernel size] */
106  /*
107  * The OpenCL kernel calculates four pixels at a time (all in the same row).
108  * Therefore, we only need to run the kernel width / 4 times in the x dimension.
109  */
110  size_t globalWorksize[2] = {width / 4, height};
111  /* [Kernel size] */
112 
113  /* Enqueue the kernel */
114  if (!checkSuccess(clEnqueueNDRangeKernel(commandQueue, kernel, 2, NULL, globalWorksize, NULL, 0, NULL, &event)))
115  {
116  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
117  cerr << "Failed enqueuing the kernel. " << __FILE__ << ":"<< __LINE__ << endl;
118  return 1;
119  }
120 
121  /* Wait for kernel execution completion. */
122  if (!checkSuccess(clFinish(commandQueue)))
123  {
124  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
125  cerr << "Failed waiting for kernel execution to finish. " << __FILE__ << ":"<< __LINE__ << endl;
126  return 1;
127  }
128 
129  /* Print the profiling information for the event. */
130  printProfilingInfo(event);
131  /* Release the event object. */
132  if (!checkSuccess(clReleaseEvent(event)))
133  {
134  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
135  cerr << "Failed releasing the event object. " << __FILE__ << ":"<< __LINE__ << endl;
136  return 1;
137  }
138 
139  /* Map the output memory to a host side pointer. */
140  cl_uchar* output = (cl_uchar*)clEnqueueMapBuffer(commandQueue, memoryObjects[0], CL_TRUE, CL_MAP_READ, 0, bufferSize, 0, NULL, NULL, &errorNumber);
141  if (!checkSuccess(errorNumber))
142  {
143  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
144  cerr << "Mapping memory objects failed " << __FILE__ << ":"<< __LINE__ << endl;
145  return 1;
146  }
147 
148  /* Convert the output luminance array to RGB and save it out to a file. */
149  unsigned char* rgbOut = new unsigned char[width * height * 3];
150  luminanceToRGB(output, rgbOut, width, height);
151  saveToBitmap("output.bmp", width, height, rgbOut);
152 
153  /* Unmap the output. */
154  if (!checkSuccess(clEnqueueUnmapMemObject(commandQueue, memoryObjects[0], output, 0, NULL, NULL)))
155  {
156  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
157  cerr << "Unmapping memory objects failed " << __FILE__ << ":"<< __LINE__ << endl;
158  return 1;
159  }
160 
161  /* Release OpenCL objects. */
162  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
163 
164  delete [] rgbOut;
165 
166  return 0;
167 }