/* * This confidential and proprietary software may be used only as * authorised by a licensing agreement from ARM Limited * (C) COPYRIGHT 2013 ARM Limited * ALL RIGHTS RESERVED * The entire notice above must be reproduced on all authorised * copies and copies may only be made to the extent permitted * by a licensing agreement from ARM Limited. */ #include "common.h" #include "image.h" #include #include #include #include #include #include #include using namespace std; /** * \brief A sample which generates Mandelbrot data for a given data size. * \details For a given height and width, the sample will test each pixel * to work out how many iterations it takes to determine if the * value is not part of the Mandelbrot set. This data is output * as a greyscale bitmap image. White pixels could not be ruled out * of the Mandelbrot set in the number of iterations used. * \return The exit code of the application, non-zero if a problem occurred. */ int main(void) { cl_context context = 0; cl_command_queue commandQueue = 0; cl_program program = 0; cl_device_id device = 0; cl_kernel kernel = 0; const unsigned int numberOfMemoryObjects = 1; cl_mem memoryObjects[numberOfMemoryObjects] = {0}; cl_int errorNumber; if (!createContext(&context)) { cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects); cerr << "Failed to create an OpenCL context. " << __FILE__ << ":"<< __LINE__ << endl; return 1; } if (!createCommandQueue(context, &commandQueue, &device)) { cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects); cerr << "Failed to create the OpenCL command queue. " << __FILE__ << ":"<< __LINE__ << endl; return 1; } if (!createProgram(context, device, "assets/mandelbrot.cl", &program)) { cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects); cerr << "Failed to create OpenCL program." << __FILE__ << ":"<< __LINE__ << endl; return 1; } kernel = clCreateKernel(program, "mandelbrot", &errorNumber); if (!checkSuccess(errorNumber)) { cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects); cerr << "Failed to create OpenCL kernel. " << __FILE__ << ":"<< __LINE__ << endl; return 1; } /* Width and height of the Mandelbrot data you want to be produced. */ cl_int width = 4096; cl_int height = 3280; /* The output buffer is the size of the Mandelbrot data. */ size_t bufferSize = width * height * sizeof(cl_uchar); /* Create an output buffer for final data. */ memoryObjects[0] = clCreateBuffer(context, CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, bufferSize, NULL, &errorNumber); if (!checkSuccess(errorNumber)) { cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects); cerr << "Failed to create OpenCL buffer. " << __FILE__ << ":"<< __LINE__ << endl; return 1; } /* Setup the kernel arguments. */ bool setKernelArgumentsSuccess = true; setKernelArgumentsSuccess &= checkSuccess(clSetKernelArg(kernel, 0, sizeof(cl_mem), &memoryObjects[0])); setKernelArgumentsSuccess &= checkSuccess(clSetKernelArg(kernel, 1, sizeof(cl_int), &width)); setKernelArgumentsSuccess &= checkSuccess(clSetKernelArg(kernel, 2, sizeof(cl_int), &height)); if (!setKernelArgumentsSuccess) { cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects); cerr << "Failed setting OpenCL kernel arguments. " << __FILE__ << ":"<< __LINE__ << endl; return 1; } /* An event to associate with the Kernel. Allows us to retreive profiling information later. */ cl_event event = 0; /* [Kernel size] */ /* * The OpenCL kernel calculates four pixels at a time (all in the same row). * Therefore, we only need to run the kernel width / 4 times in the x dimension. */ size_t globalWorksize[2] = {width / 4, height}; /* [Kernel size] */ /* Enqueue the kernel */ if (!checkSuccess(clEnqueueNDRangeKernel(commandQueue, kernel, 2, NULL, globalWorksize, NULL, 0, NULL, &event))) { cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects); cerr << "Failed enqueuing the kernel. " << __FILE__ << ":"<< __LINE__ << endl; return 1; } /* Wait for kernel execution completion. */ if (!checkSuccess(clFinish(commandQueue))) { cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects); cerr << "Failed waiting for kernel execution to finish. " << __FILE__ << ":"<< __LINE__ << endl; return 1; } /* Print the profiling information for the event. */ printProfilingInfo(event); /* Release the event object. */ if (!checkSuccess(clReleaseEvent(event))) { cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects); cerr << "Failed releasing the event object. " << __FILE__ << ":"<< __LINE__ << endl; return 1; } /* Map the output memory to a host side pointer. */ cl_uchar* output = (cl_uchar*)clEnqueueMapBuffer(commandQueue, memoryObjects[0], CL_TRUE, CL_MAP_READ, 0, bufferSize, 0, NULL, NULL, &errorNumber); if (!checkSuccess(errorNumber)) { cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects); cerr << "Mapping memory objects failed " << __FILE__ << ":"<< __LINE__ << endl; return 1; } /* Convert the output luminance array to RGB and save it out to a file. */ unsigned char* rgbOut = new unsigned char[width * height * 3]; luminanceToRGB(output, rgbOut, width, height); saveToBitmap("output.bmp", width, height, rgbOut); /* Unmap the output. */ if (!checkSuccess(clEnqueueUnmapMemObject(commandQueue, memoryObjects[0], output, 0, NULL, NULL))) { cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects); cerr << "Unmapping memory objects failed " << __FILE__ << ":"<< __LINE__ << endl; return 1; } /* Release OpenCL objects. */ cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects); delete [] rgbOut; return 0; }