// RUN: %target-run-simple-swift // REQUIRES: executable_test // REQUIRES: OS=macosx // Translated from standard OpenCL hello.c program // Abstract: A simple "Hello World" compute example showing basic usage of OpenCL which // calculates the mathematical square (X[i] = pow(X[i],2)) for a buffer of // floating point values. // // // Version: <1.0> // // Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") // in consideration of your agreement to the following terms, and your use, // installation, modification or redistribution of this Apple software // constitutes acceptance of these terms. If you do not agree with these // terms, please do not use, install, modify or redistribute this Apple // software. // // In consideration of your agreement to abide by the following terms, and // subject to these terms, Apple grants you a personal, non - exclusive // license, under Apple's copyrights in this original Apple software ( the // "Apple Software" ), to use, reproduce, modify and redistribute the Apple // Software, with or without modifications, in source and / or binary forms // provided that if you redistribute the Apple Software in its entirety and // without modifications, you must retain this notice and the following text // and disclaimers in all such redistributions of the Apple Software. Neither // the name, trademarks, service marks or logos of Apple Inc. may be used to // endorse or promote products derived from the Apple Software without specific // prior written permission from Apple. Except as expressly stated in this // notice, no other rights or licenses, express or implied, are granted by // Apple herein, including but not limited to any patent rights that may be // infringed by your derivative works or by other works in which the Apple // Software may be incorporated. // // The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO // WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED // WARRANTIES OF NON - INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A // PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION // ALONE OR IN COMBINATION WITH YOUR PRODUCTS. // // IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR // CONSEQUENTIAL DAMAGES ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION ) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION // AND / OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER // UNDER THEORY OF CONTRACT, TORT ( INCLUDING NEGLIGENCE ), STRICT LIABILITY OR // OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Copyright ( C ) 2008 Apple Inc. All Rights Reserved. // import OpenCL import StdlibUnittest // Also import modules which are used by StdlibUnittest internally. This // workaround is needed to link all required libraries in case we compile // StdlibUnittest with -sil-serialize-all. import SwiftPrivate #if _runtime(_ObjC) import ObjectiveC #endif import Foundation import Darwin let KernelSource = "\n" + "__kernel void square( \n" + " __global float* input, \n" + " __global float* output, \n" + " const unsigned int count) \n" + "{ \n" + " int i = get_global_id(0); \n" + " if(i < count) \n" + " output[i] = input[i] * input[i]; \n" + "} \n" + "\n" let DATA_SIZE = 1024 var tests = TestSuite("MiscSDKOverlay") tests.test("clSetKernelArgsListAPPLE") { var err: cl_int // error code returned from api calls var data = [Float](count: DATA_SIZE, repeatedValue: 0) // original data set given to device var results = [Float](count: DATA_SIZE, repeatedValue: 0) // results returned from device var correct: Int // number of correct results returned var global: size_t // global domain size for our calculation var local: size_t = 0 // local domain size for our calculation var device_id: cl_device_id = nil // compute device id var context: cl_context // compute context var commands: cl_command_queue // compute command queue var program: cl_program // compute program var kernel: cl_kernel // compute kernel var input: cl_mem // device memory used for the input array var output: cl_mem // device memory used for the output array // Fill our data set with random float values // var i = 0 var count = DATA_SIZE for i = 0; i < count; i++ { data[i] = Float(rand()) / Float(RAND_MAX) } // Connect to a compute device // var gpu = 1 err = clGetDeviceIDs(nil, cl_device_type(gpu != 0 ? CL_DEVICE_TYPE_GPU : CL_DEVICE_TYPE_CPU), 1, &device_id, nil) if (err != CL_SUCCESS) { print("Error: Failed to create a device group!") exit(EXIT_FAILURE) } // Create a compute context // context = clCreateContext(nil, 1, &device_id, nil, nil, &err) if (context == nil) { print("Error: Failed to create a compute context!") exit(EXIT_FAILURE) } // Create a command commands // commands = clCreateCommandQueue(context, device_id, 0, &err) if (commands == nil) { print("Error: Failed to create a command commands!") exit(EXIT_FAILURE) } // Create the compute program from the source buffer // program = KernelSource.withCString { (s: UnsafePointer) -> cl_program in var s = s return withUnsafeMutablePointer(&s) { return clCreateProgramWithSource(context, 1, $0, nil, &err) } } if (program == nil) { print("Error: Failed to create compute program!") exit(EXIT_FAILURE) } // Build the program executable // err = clBuildProgram(program, 0, nil, nil, nil, nil) if (err != CL_SUCCESS) { var len: Int = 0 var buffer = [CChar](count:2048, repeatedValue: 0) print("Error: Failed to build program executable!") clGetProgramBuildInfo( program, device_id, cl_program_build_info(CL_PROGRAM_BUILD_LOG), 2048, &buffer, &len) print("\(String.fromCString(buffer)!)") exit(1) } // Create the compute kernel in the program we wish to run // kernel = clCreateKernel(program, "square", &err) if (kernel == nil || err != cl_int(CL_SUCCESS)) { print("Error: Failed to create compute kernel!") exit(1) } // Create the input and output arrays in device memory for our calculation // input = clCreateBuffer(context, cl_mem_flags(CL_MEM_READ_ONLY), sizeof(Float.self) * count, nil, nil) output = clCreateBuffer(context, cl_mem_flags(CL_MEM_WRITE_ONLY), sizeof(Float.self) * count, nil, nil) if (input == nil || output == nil) { print("Error: Failed to allocate device memory!") exit(1) } // Write our data set into the input array in device memory // err = clEnqueueWriteBuffer(commands, input, cl_bool(CL_TRUE), 0, sizeof(Float.self) * count, data, 0, nil, nil) if (err != CL_SUCCESS) { print("Error: Failed to write to source array!") exit(1) } // Set the arguments to our compute kernel // err = 0 err = withUnsafePointers(&input, &output, &count) { inputPtr, outputPtr, countPtr in clSetKernelArgsListAPPLE( kernel, 3, 0, sizeof(cl_mem.self), inputPtr, 1, sizeof(cl_mem.self), outputPtr, 2, sizeofValue(count), countPtr) } if (err != CL_SUCCESS) { print("Error: Failed to set kernel arguments! \(err)") exit(1) } // Get the maximum work group size for executing the kernel on the device // err = clGetKernelWorkGroupInfo(kernel, device_id, cl_kernel_work_group_info(CL_KERNEL_WORK_GROUP_SIZE), sizeofValue(local), &local, nil) if (err != CL_SUCCESS) { print("Error: Failed to retrieve kernel work group info! \(err)") exit(1) } // Execute the kernel over the entire range of our 1d input data set // using the maximum number of work group items for this device // global = count err = clEnqueueNDRangeKernel(commands, kernel, 1, nil, &global, &local, 0, nil, nil) if (err != 0) { print("Error: Failed to execute kernel!") exit(EXIT_FAILURE) } // Wait for the command commands to get serviced before reading back results // clFinish(commands) // Read back the results from the device to verify the output // err = clEnqueueReadBuffer( commands, output, cl_bool(CL_TRUE), 0, sizeof(Float.self) * count, &results, cl_uint(0), nil, nil ) if (err != CL_SUCCESS) { print("Error: Failed to read output array! \(err)") exit(1) } // Validate our results // correct = 0 for(i = 0; i < count; i++) { if(results[i] == data[i] * data[i]){ correct += 1 } } // Print a brief summary detailing the results // print("Computed '\(correct)/\(count)' correct values!") // Shutdown and cleanup // clReleaseMemObject(input) clReleaseMemObject(output) clReleaseProgram(program) clReleaseKernel(kernel) clReleaseCommandQueue(commands) clReleaseContext(context) } runAllTests()