@@ -64,68 +64,7 @@ synchronization operations.
6464
6565This process is best illustrated with a fully worked example:
6666
67- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.cpp}
68- #include <arrayfire.h>
69- // 1. Add the af/opencl.h include to your project
70- #include <af/opencl.h>
71-
72- int main() {
73- size_t length = 10;
74-
75- // Create ArrayFire array objects:
76- af::array A = af::randu(length, f32);
77- af::array B = af::constant(0, length, f32);
78-
79- // ... additional ArrayFire operations here
80-
81- // 2. Obtain the device, context, and queue used by ArrayFire
82- static cl_context af_context = afcl::getContext();
83- static cl_device_id af_device_id = afcl::getDeviceId();
84- static cl_command_queue af_queue = afcl::getQueue();
85-
86- // 3. Obtain cl_mem references to af::array objects
87- cl_mem * d_A = A.device<cl_mem>();
88- cl_mem * d_B = B.device<cl_mem>();
89-
90- // 4. Load, build, and use your kernels.
91- // For the sake of readability, we have omitted error checking.
92- int status = CL_SUCCESS;
93-
94- // A simple copy kernel, uses C++11 syntax for multi-line strings.
95- const char * kernel_name = "copy_kernel";
96- const char * source = R"(
97- void __kernel
98- copy_kernel(__global float * gA, __global float * gB)
99- {
100- int id = get_global_id(0);
101- gB[id] = gA[id];
102- }
103- )";
104-
105- // Create the program, build the executable, and extract the entry point
106- // for the kernel.
107- cl_program program = clCreateProgramWithSource(af_context, 1, &source, NULL, &status);
108- status = clBuildProgram(program, 1, &af_device_id, NULL, NULL, NULL);
109- cl_kernel kernel = clCreateKernel(program, kernel_name, &status);
110-
111- // Set arguments and launch your kernels
112- clSetKernelArg(kernel, 0, sizeof(cl_mem), d_A);
113- clSetKernelArg(kernel, 1, sizeof(cl_mem), d_B);
114- clEnqueueNDRangeKernel(af_queue, kernel, 1, NULL, &length, NULL, 0, NULL, NULL);
115-
116- // 5. Return control of af::array memory to ArrayFire
117- A.unlock();
118- B.unlock();
119-
120- // ... resume ArrayFire operations
121-
122- // Because the device pointers, d_x and d_y, were returned to ArrayFire's
123- // control by the unlock function, there is no need to free them using
124- // clReleaseMemObject()
125-
126- return 0;
127- }
128- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
67+ \snippet test/interop_opencl_custom_kernel_snippet.cpp interop_opencl_custom_kernel_snippet
12968
13069If your kernels needs to operate in their own OpenCL queue, the process is
13170essentially identical, except you need to instruct ArrayFire to complete
@@ -187,64 +126,9 @@ so, please be cautious not to call `clReleaseMemObj` on a `cl_mem` when
187126ArrayFire might be using it!
188127
189128The eight steps above are best illustrated using a fully-worked example. Below we
190- use the OpenCL 2.0 C++ API and omit error checking to keep the code readable.
191-
192- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.cpp}
193- #include <CL/cl2.hpp>
194-
195- // 1. Add arrayfire.h and af/opencl.h to your application
196- #include "arrayfire.h"
197- #include "af/opencl.h"
198-
199- #include <cstdio>
200- #include <vector>
201-
202- int main() {
203-
204- // Set up the OpenCL context, device, and queues
205- cl::Context context(CL_DEVICE_TYPE_ALL);
206- vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
207- cl::Device device = devices[0];
208- cl::CommandQueue queue(context, device);
209-
210- // Create a buffer of size 10 filled with ones, copy it to the device
211- int length = 10;
212- vector<float> h_A(length, 1);
213- cl::Buffer cl_A(context, CL_MEM_READ_WRITE, length * sizeof(float), h_A.data());
129+ use the OpenCL C++ API and omit error checking to keep the code readable.
214130
215- // 2. Instruct OpenCL to complete its operations using clFinish (or similar)
216- queue.finish();
217-
218- // 3. Instruct ArrayFire to use the user-created context
219- // First, create a device from the current OpenCL device + context + queue
220- afcl::addDevice(device(), context(), queue());
221- // Next switch ArrayFire to the device using the device and context as
222- // identifiers:
223- afcl::setDevice(device(), context());
224-
225- // 4. Create ArrayFire arrays from OpenCL memory objects
226- af::array af_A = afcl::array(length, cl_A(), f32, true);
227-
228- // 5. Perform ArrayFire operations on the Arrays
229- af_A = af_A + af::randu(length);
230-
231- // NOTE: ArrayFire does not perform the above transaction using in-place memory,
232- // thus the underlying OpenCL buffers containing the memory containing memory to
233- // probably have changed
234-
235- // 6. Instruct ArrayFire to finish operations using af::sync
236- af::sync();
237-
238- // 7. Obtain cl_mem references for important memory
239- cl_A = *af_A.device<cl_mem>();
240-
241- // 8. Continue your OpenCL application
242-
243- // ...
244-
245- return 0;
246- }
247- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
131+ \snippet test/interop_opencl_external_context_snippet.cpp interop_opencl_external_context_snippet
248132
249133# Using multiple devices
250134
0 commit comments