Mali OpenCL SDK v1.1.0
 All Classes Files Functions Variables Macros Pages
mandelbrot.cl
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 /*
12  * The number of iterations before we assume a point is in the Mandelbrot set.
13  * Increasing this value has no effect since as we are returning the output as unsigned chars,
14  * 255 is the maximum value that can be returned.
15  */
16 #define MAX_ITER 255
17 
23 float4 createStartX(int x)
24 {
25  return (float4)(x, x + 1, x + 2, x + 3);
26 }
27 
41 __kernel void mandelbrot(__global uchar* restrict output,
42  const int width,
43  const int height)
44 {
45  /* [Kernel size] */
46  /*
47  * Each kernel calculates 4 output pixels in the same row (hence the '* 4').
48  * x is in the range [0, width] in steps of 4.
49  * y is in the range [0, height].
50  */
51  int x = get_global_id(0) * 4;
52  int y = get_global_id(1);
53  /* [Kernel size] */
54 
55  /* [Create inputs] */
56  /*
57  * Calculate the coordinates of the four pixels in the real and imaginary space.
58  * Scale the coordinates by the height and width such that the same image is produced for all values, just at different resolutions.
59  * The real coordinate is scaled to the range [0, 2.5] (using '/ width * 2.5f') and then shifted to be in the range [-2, 0.5] (using '-2').
60  * The imaginary coordinate is scaled to the range [0, 2] (using '/ ((float) height) * 2' and then shifted to be in the range [-1, 1] (using '-1').
61  * The resulting ranges ([-2, 0.5], [-1, 1]) are the limits of the interesting parts of the Mandelbrot set.
62  * Four pixels (adjacent in x (real) dimension) are calulated per kernel instance. Therefore, we calculate real coordinates for 4 pixels.
63  */
64  float4 initialReal = -2 + (createStartX(x) / (float)width * 2.5f);
65  float4 initialImaginary = -1 + (y / (float)height * 2);
66 
67  float4 real = initialReal;
68  float4 imaginary = initialImaginary;
69  /* [Create inputs] */
70 
71  /* This will store the number of iterations for each of the four pixels */
72  int4 iterationsPerPixel = (int4)(0, 0, 0, 0);
73  /* Total number of iterations for this kernel instance. */
74  int iterations = 0;
75  int4 mask;
76 
77  /* [Calculation] */
78  /*
79  * Loop until we can say that all pixels are not part
80  * of the Mandelbrot set or the maximum number of
81  * iterations has been reached.
82  */
83  do
84  {
85  iterations++;
86  if (iterations > MAX_ITER)
87  {
88  break;
89  }
90 
91  /* Backup the real value as its used in both calculations but changed by the first. */
92  float4 oldReal = real;
93 
94  /* Evaluate the equation. */
95  real = real * real - imaginary * imaginary + initialReal;
96  imaginary = 2 * oldReal * imaginary + initialImaginary;
97 
98  /*
99  * Calculate which indices to update.
100  * Mathematically, if the result of the calculation becomes greater that 2, it will continue to infinity.
101  * Therefore, if the result becomes greater than 2 it cannot be part of the Mandelbrot set and we stop adding to it's iteration count.
102  * To get the absolute value of the calculation we have squared and added the components, therefore we must test it against
103  * 4 (2 squared).
104  */
105  float4 absoluteValue = real * real + imaginary * imaginary;
106  /* For vector input isless(x, y) returns -1 per component if x < y. */
107  mask = isless(absoluteValue, (float4) 4.0f);
108  /* Increase the iterations per pixel (if they are less than 4). */
109  iterationsPerPixel -= mask;
110  } while(any(mask));
111  /* [Calculation] */
112 
113  /* [Store] */
114  /*
115  * Write the result to the output buffer.
116  * Convert the output to unsigned char to make it easier to write to a bitmap.
117  */
118  vstore4(convert_uchar4(iterationsPerPixel), 0, output + x + y * width);
119  /* [Store] */
120 }