Clover Git
OpenCL 1.1 software implementation

events.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011, Denis Steckelmacher <steckdenis@yahoo.fr>
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *     * Redistributions of source code must retain the above copyright
00008  *       notice, this list of conditions and the following disclaimer.
00009  *     * Redistributions in binary form must reproduce the above copyright
00010  *       notice, this list of conditions and the following disclaimer in the
00011  *       documentation and/or other materials provided with the distribution.
00012  *     * Neither the name of the copyright holder nor the
00013  *       names of its contributors may be used to endorse or promote products
00014  *       derived from this software without specific prior written permission.
00015  *
00016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00017  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
00020  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00022  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00023  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00024  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00025  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  */
00027 
00033 #include "events.h"
00034 #include "commandqueue.h"
00035 #include "memobject.h"
00036 #include "kernel.h"
00037 #include "deviceinterface.h"
00038 
00039 #include <cstdlib>
00040 #include <cstring>
00041 #include <iostream>
00042 
00043 using namespace Coal;
00044 
00045 /*
00046  * Read/Write buffers
00047  */
00048 
00049 BufferEvent::BufferEvent(CommandQueue *parent,
00050                          MemObject *buffer,
00051                          cl_uint num_events_in_wait_list,
00052                          const Event **event_wait_list,
00053                          cl_int *errcode_ret)
00054 : Event(parent, Queued, num_events_in_wait_list, event_wait_list, errcode_ret),
00055   p_buffer(buffer)
00056 {
00057     if (*errcode_ret != CL_SUCCESS) return;
00058 
00059     // Correct buffer
00060     if (!buffer)
00061     {
00062         *errcode_ret = CL_INVALID_MEM_OBJECT;
00063         return;
00064     }
00065 
00066     // Buffer's context must match the CommandQueue one
00067     Context *ctx = 0;
00068     *errcode_ret = parent->info(CL_QUEUE_CONTEXT, sizeof(Context *), &ctx, 0);
00069 
00070     if (*errcode_ret != CL_SUCCESS) return;
00071 
00072     if ((Context *)buffer->parent() != ctx)
00073     {
00074         *errcode_ret = CL_INVALID_CONTEXT;
00075         return;
00076     }
00077 
00078     // Alignment of SubBuffers
00079     DeviceInterface *device = 0;
00080     *errcode_ret = parent->info(CL_QUEUE_DEVICE, sizeof(DeviceInterface *),
00081                                 &device, 0);
00082 
00083     if (*errcode_ret != CL_SUCCESS)
00084         return;
00085 
00086     if (!isSubBufferAligned(buffer, device))
00087     {
00088         *errcode_ret = CL_MISALIGNED_SUB_BUFFER_OFFSET;
00089         return;
00090     }
00091 
00092     // Allocate the buffer for the device
00093     if (!buffer->allocate(device))
00094     {
00095         *errcode_ret = CL_MEM_OBJECT_ALLOCATION_FAILURE;
00096         return;
00097     }
00098 }
00099 
00100 MemObject *BufferEvent::buffer() const
00101 {
00102     return p_buffer;
00103 }
00104 
00105 bool BufferEvent::isSubBufferAligned(const MemObject *buffer,
00106                                      const DeviceInterface *device)
00107 {
00108     cl_uint align;
00109     cl_int rs;
00110 
00111     if (buffer->type() != MemObject::SubBuffer)
00112         return true;
00113 
00114     rs = device->info(CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof(uint),
00115                       &align, 0);
00116 
00117     if (rs != CL_SUCCESS)
00118         return false;
00119 
00120     size_t mask = 0;
00121 
00122     for (cl_uint i=0; i<align; ++i)
00123         mask = 1 | (mask << 1);
00124 
00125     if (((SubBuffer *)buffer)->offset() & mask)
00126         return false;
00127 
00128     return true;
00129 }
00130 
00131 ReadWriteBufferEvent::ReadWriteBufferEvent(CommandQueue *parent,
00132                                            MemObject *buffer,
00133                                            size_t offset,
00134                                            size_t cb,
00135                                            void *ptr,
00136                                            cl_uint num_events_in_wait_list,
00137                                            const Event **event_wait_list,
00138                                            cl_int *errcode_ret)
00139 : BufferEvent(parent, buffer, num_events_in_wait_list, event_wait_list, errcode_ret),
00140   p_offset(offset), p_cb(cb), p_ptr(ptr)
00141 {
00142     if (*errcode_ret != CL_SUCCESS) return;
00143 
00144     // Check for out-of-bounds reads
00145     if (!ptr)
00146     {
00147         *errcode_ret = CL_INVALID_VALUE;
00148         return;
00149     }
00150 
00151     if (offset + cb > buffer->size())
00152     {
00153         *errcode_ret = CL_INVALID_VALUE;
00154         return;
00155     }
00156 }
00157 
00158 size_t ReadWriteBufferEvent::offset() const
00159 {
00160     return p_offset;
00161 }
00162 
00163 size_t ReadWriteBufferEvent::cb() const
00164 {
00165     return p_cb;
00166 }
00167 
00168 void *ReadWriteBufferEvent::ptr() const
00169 {
00170     return p_ptr;
00171 }
00172 
00173 ReadBufferEvent::ReadBufferEvent(CommandQueue *parent,
00174                                  MemObject *buffer,
00175                                  size_t offset,
00176                                  size_t cb,
00177                                  void *ptr,
00178                                  cl_uint num_events_in_wait_list,
00179                                  const Event **event_wait_list,
00180                                  cl_int *errcode_ret)
00181 : ReadWriteBufferEvent(parent, buffer, offset, cb, ptr, num_events_in_wait_list,
00182                        event_wait_list, errcode_ret)
00183 {}
00184 
00185 Event::Type ReadBufferEvent::type() const
00186 {
00187     return Event::ReadBuffer;
00188 }
00189 
00190 WriteBufferEvent::WriteBufferEvent(CommandQueue *parent,
00191                                    MemObject *buffer,
00192                                    size_t offset,
00193                                    size_t cb,
00194                                    void *ptr,
00195                                    cl_uint num_events_in_wait_list,
00196                                    const Event **event_wait_list,
00197                                    cl_int *errcode_ret)
00198 : ReadWriteBufferEvent(parent, buffer, offset, cb, ptr, num_events_in_wait_list,
00199                        event_wait_list, errcode_ret)
00200 {}
00201 
00202 Event::Type WriteBufferEvent::type() const
00203 {
00204     return Event::WriteBuffer;
00205 }
00206 
00207 MapBufferEvent::MapBufferEvent(CommandQueue *parent,
00208                                MemObject *buffer,
00209                                size_t offset,
00210                                size_t cb,
00211                                cl_map_flags map_flags,
00212                                cl_uint num_events_in_wait_list,
00213                                const Event **event_wait_list,
00214                                cl_int *errcode_ret)
00215 : BufferEvent(parent, buffer, num_events_in_wait_list, event_wait_list, errcode_ret),
00216   p_offset(offset), p_cb(cb), p_map_flags(map_flags)
00217 {
00218     if (*errcode_ret != CL_SUCCESS) return;
00219 
00220     // Check flags
00221     if (map_flags & ~(CL_MAP_READ | CL_MAP_WRITE))
00222     {
00223         *errcode_ret = CL_INVALID_VALUE;
00224         return;
00225     }
00226 
00227     // Check for out-of-bounds values
00228     if (offset + cb > buffer->size())
00229     {
00230         *errcode_ret = CL_INVALID_VALUE;
00231         return;
00232     }
00233 }
00234 
00235 Event::Type MapBufferEvent::type() const
00236 {
00237     return Event::MapBuffer;
00238 }
00239 
00240 size_t MapBufferEvent::offset() const
00241 {
00242     return p_offset;
00243 }
00244 
00245 size_t MapBufferEvent::cb() const
00246 {
00247     return p_cb;
00248 }
00249 
00250 cl_map_flags MapBufferEvent::flags() const
00251 {
00252     return p_map_flags;
00253 }
00254 
00255 void *MapBufferEvent::ptr() const
00256 {
00257     return p_ptr;
00258 }
00259 
00260 void MapBufferEvent::setPtr(void *ptr)
00261 {
00262     p_ptr = ptr;
00263 }
00264 
00265 MapImageEvent::MapImageEvent(CommandQueue *parent,
00266                              Image2D *image,
00267                              cl_map_flags map_flags,
00268                              const size_t origin[3],
00269                              const size_t region[3],
00270                              cl_uint num_events_in_wait_list,
00271                              const Event **event_wait_list,
00272                              cl_int *errcode_ret)
00273 : BufferEvent (parent, image, num_events_in_wait_list, event_wait_list, errcode_ret)
00274 {
00275     if (*errcode_ret != CL_SUCCESS) return;
00276 
00277     // Check flags
00278     if (map_flags & ~(CL_MAP_READ | CL_MAP_WRITE))
00279     {
00280         *errcode_ret = CL_INVALID_VALUE;
00281         return;
00282     }
00283 
00284     // Copy the vectors
00285     if (origin)
00286         std::memcpy(&p_origin, origin, 3 * sizeof(size_t));
00287     else
00288         std::memset(&p_origin, 0, 3 * sizeof(size_t));
00289 
00290     for (unsigned int i=0; i<3; ++i)
00291     {
00292         if (!region[i])
00293         {
00294             *errcode_ret = CL_INVALID_VALUE;
00295             return;
00296         }
00297 
00298         p_region[i] = region[i];
00299     }
00300 
00301     // Multiply the elements (for images)
00302     p_region[0] *= image->pixel_size();
00303     p_origin[0] *= image->pixel_size();
00304 
00305     // Check for overflow
00306     if (image->type() == MemObject::Image2D &&
00307         (origin[2] != 0 || region[2] != 1))
00308     {
00309         *errcode_ret = CL_INVALID_VALUE;
00310         return;
00311     }
00312 
00313     // Check for out-of-bounds
00314     if ((p_origin[0] + p_region[0]) > image->row_pitch() ||
00315         (p_origin[1] + p_region[1]) * image->row_pitch() > image->slice_pitch() ||
00316         (p_origin[2] + p_region[2]) * image->slice_pitch() > image->size())
00317     {
00318         *errcode_ret = CL_INVALID_VALUE;
00319         return;
00320     }
00321 }
00322 
00323 Event::Type MapImageEvent::type() const
00324 {
00325     return Event::MapImage;
00326 }
00327 
00328 
00329 cl_map_flags MapImageEvent::flags() const
00330 {
00331     return p_map_flags;
00332 }
00333 
00334 size_t MapImageEvent::origin (unsigned int index) const
00335 {
00336     return p_origin[index];
00337 }
00338 
00339 size_t MapImageEvent::region (unsigned int index) const
00340 {
00341     return p_region[index];
00342 }
00343 
00344 size_t MapImageEvent::row_pitch() const
00345 {
00346     return p_row_pitch;
00347 }
00348 
00349 size_t MapImageEvent::slice_pitch() const
00350 {
00351     return p_slice_pitch;
00352 }
00353 
00354 void *MapImageEvent::ptr() const
00355 {
00356     return p_ptr;
00357 }
00358 
00359 void MapImageEvent::setRowPitch (size_t row_pitch)
00360 {
00361     p_row_pitch = row_pitch;
00362 }
00363 
00364 void MapImageEvent::setSlicePitch (size_t slice_pitch)
00365 {
00366     p_slice_pitch = slice_pitch;
00367 }
00368 
00369 void MapImageEvent::setPtr (void *ptr)
00370 {
00371     p_ptr = ptr;
00372 }
00373 
00374 UnmapBufferEvent::UnmapBufferEvent(CommandQueue *parent,
00375                                    MemObject *buffer,
00376                                    void *mapped_addr,
00377                                    cl_uint num_events_in_wait_list,
00378                                    const Event **event_wait_list,
00379                                    cl_int *errcode_ret)
00380 : BufferEvent(parent, buffer, num_events_in_wait_list, event_wait_list, errcode_ret),
00381   p_mapping(mapped_addr)
00382 {
00383     if (*errcode_ret != CL_SUCCESS) return;
00384 
00385     // TODO: Check that p_mapping is ok (will be done in the drivers)
00386     if (!mapped_addr)
00387     {
00388         *errcode_ret = CL_INVALID_VALUE;
00389         return;
00390     }
00391 }
00392 
00393 Event::Type UnmapBufferEvent::type() const
00394 {
00395     return Event::UnmapMemObject;
00396 }
00397 
00398 void *UnmapBufferEvent::mapping() const
00399 {
00400     return p_mapping;
00401 }
00402 
00403 CopyBufferEvent::CopyBufferEvent(CommandQueue *parent,
00404                                  MemObject *source,
00405                                  MemObject *destination,
00406                                  size_t src_offset,
00407                                  size_t dst_offset,
00408                                  size_t cb,
00409                                  cl_uint num_events_in_wait_list,
00410                                  const Event **event_wait_list,
00411                                  cl_int *errcode_ret)
00412 : BufferEvent(parent, source, num_events_in_wait_list, event_wait_list,
00413               errcode_ret), p_destination(destination), p_src_offset(src_offset),
00414   p_dst_offset(dst_offset), p_cb(cb)
00415 {
00416     if (*errcode_ret != CL_SUCCESS) return;
00417 
00418     if (!destination)
00419     {
00420         *errcode_ret = CL_INVALID_MEM_OBJECT;
00421         return;
00422     }
00423 
00424     // Check for out-of-bounds
00425     if (src_offset + cb > source->size() ||
00426         dst_offset + cb > destination->size())
00427     {
00428         *errcode_ret = CL_INVALID_VALUE;
00429         return;
00430     }
00431 
00432     // Check for overlap
00433     if (source == destination)
00434     {
00435         if ((src_offset < dst_offset && src_offset + cb > dst_offset) ||
00436             (dst_offset < src_offset && dst_offset + cb > src_offset))
00437         {
00438             *errcode_ret = CL_MEM_COPY_OVERLAP;
00439             return;
00440         }
00441     }
00442 
00443     // Check alignement of destination
00444     DeviceInterface *device = 0;
00445     *errcode_ret = parent->info(CL_QUEUE_DEVICE, sizeof(DeviceInterface *),
00446                                 &device, 0);
00447 
00448     if (*errcode_ret != CL_SUCCESS)
00449         return;
00450 
00451     if (!isSubBufferAligned(destination, device))
00452     {
00453         *errcode_ret = CL_MISALIGNED_SUB_BUFFER_OFFSET;
00454         return;
00455     }
00456 
00457     // Allocate the buffer for the device
00458     if (!destination->allocate(device))
00459     {
00460         *errcode_ret = CL_MEM_OBJECT_ALLOCATION_FAILURE;
00461         return;
00462     }
00463 }
00464 
00465 MemObject *CopyBufferEvent::source() const
00466 {
00467     return buffer();
00468 }
00469 
00470 MemObject *CopyBufferEvent::destination() const
00471 {
00472     return p_destination;
00473 }
00474 
00475 size_t CopyBufferEvent::src_offset() const
00476 {
00477     return p_src_offset;
00478 }
00479 
00480 size_t CopyBufferEvent::dst_offset() const
00481 {
00482     return p_dst_offset;
00483 }
00484 
00485 size_t CopyBufferEvent::cb() const
00486 {
00487     return p_cb;
00488 }
00489 
00490 Event::Type CopyBufferEvent::type() const
00491 {
00492     return Event::CopyBuffer;
00493 }
00494 
00495 /*
00496  * Native kernel
00497  */
00498 NativeKernelEvent::NativeKernelEvent(CommandQueue *parent,
00499                                      void (*user_func)(void *),
00500                                      void *args,
00501                                      size_t cb_args,
00502                                      cl_uint num_mem_objects,
00503                                      const MemObject **mem_list,
00504                                      const void **args_mem_loc,
00505                                      cl_uint num_events_in_wait_list,
00506                                      const Event **event_wait_list,
00507                                      cl_int *errcode_ret)
00508 : Event (parent, Queued, num_events_in_wait_list, event_wait_list, errcode_ret),
00509   p_user_func((void *)user_func), p_args(0)
00510 {
00511     if (*errcode_ret != CL_SUCCESS) return;
00512 
00513     // Parameters sanity
00514     if (!user_func)
00515     {
00516         *errcode_ret = CL_INVALID_VALUE;
00517         return;
00518     }
00519 
00520     if (!args && (cb_args || num_mem_objects))
00521     {
00522         *errcode_ret = CL_INVALID_VALUE;
00523         return;
00524     }
00525 
00526     if (args && !cb_args)
00527     {
00528         *errcode_ret = CL_INVALID_VALUE;
00529         return;
00530     }
00531 
00532     if (num_mem_objects && (!mem_list || !args_mem_loc))
00533     {
00534         *errcode_ret = CL_INVALID_VALUE;
00535         return;
00536     }
00537 
00538     if (!num_mem_objects && (mem_list || args_mem_loc))
00539     {
00540         *errcode_ret = CL_INVALID_VALUE;
00541         return;
00542     }
00543 
00544     // Check that the device can execute a native kernel
00545     DeviceInterface *device;
00546     cl_device_exec_capabilities caps;
00547 
00548     *errcode_ret = parent->info(CL_QUEUE_DEVICE, sizeof(DeviceInterface *),
00549                                 &device, 0);
00550 
00551     if (*errcode_ret != CL_SUCCESS)
00552         return;
00553 
00554     *errcode_ret = device->info(CL_DEVICE_EXECUTION_CAPABILITIES,
00555                                 sizeof(cl_device_exec_capabilities), &caps, 0);
00556 
00557     if (*errcode_ret != CL_SUCCESS)
00558         return;
00559 
00560     if ((caps & CL_EXEC_NATIVE_KERNEL) == 0)
00561     {
00562         *errcode_ret = CL_INVALID_OPERATION;
00563         return;
00564     }
00565 
00566     // Copy the arguments in a new list
00567     if (cb_args)
00568     {
00569         p_args = std::malloc(cb_args);
00570 
00571         if (!p_args)
00572         {
00573             *errcode_ret = CL_OUT_OF_HOST_MEMORY;
00574             return;
00575         }
00576 
00577         std::memcpy((void *)p_args, (void *)args, cb_args);
00578 
00579         // Replace memory objects with global pointers
00580         for (cl_uint i=0; i<num_mem_objects; ++i)
00581         {
00582             const MemObject *buffer = mem_list[i];
00583             const char *loc = (const char *)args_mem_loc[i];
00584 
00585             if (!buffer)
00586             {
00587                 *errcode_ret = CL_INVALID_MEM_OBJECT;
00588                 return;
00589             }
00590 
00591             // We need to do relocation : loc is in args, we need it in p_args
00592             size_t delta = (char *)p_args - (char *)args;
00593             loc += delta;
00594 
00595             *(void **)loc = buffer->deviceBuffer(device)->nativeGlobalPointer();
00596         }
00597     }
00598 }
00599 
00600 NativeKernelEvent::~NativeKernelEvent()
00601 {
00602     if (p_args)
00603         std::free((void *)p_args);
00604 }
00605 
00606 Event::Type NativeKernelEvent::type() const
00607 {
00608     return Event::NativeKernel;
00609 }
00610 
00611 void *NativeKernelEvent::function() const
00612 {
00613     return p_user_func;
00614 }
00615 
00616 void *NativeKernelEvent::args() const
00617 {
00618     return p_args;
00619 }
00620 
00621 /*
00622  * Kernel event
00623  */
00624 KernelEvent::KernelEvent(CommandQueue *parent,
00625                          Kernel *kernel,
00626                          cl_uint work_dim,
00627                          const size_t *global_work_offset,
00628                          const size_t *global_work_size,
00629                          const size_t *local_work_size,
00630                          cl_uint num_events_in_wait_list,
00631                          const Event **event_wait_list,
00632                          cl_int *errcode_ret)
00633 : Event(parent, Queued, num_events_in_wait_list, event_wait_list, errcode_ret),
00634   p_work_dim(work_dim), p_kernel(kernel)
00635 {
00636     if (*errcode_ret != CL_SUCCESS) return;
00637 
00638     *errcode_ret = CL_SUCCESS;
00639 
00640     // Sanity checks
00641     if (!kernel)
00642     {
00643         *errcode_ret = CL_INVALID_KERNEL;
00644         return;
00645     }
00646 
00647     // Check that the kernel was built for parent's device.
00648     DeviceInterface *device;
00649     Context *k_ctx, *q_ctx;
00650     size_t max_work_group_size;
00651     cl_uint max_dims = 0;
00652 
00653     *errcode_ret = parent->info(CL_QUEUE_DEVICE, sizeof(DeviceInterface *),
00654                                 &device, 0);
00655 
00656     if (*errcode_ret != CL_SUCCESS)
00657         return;
00658 
00659     *errcode_ret = parent->info(CL_QUEUE_CONTEXT, sizeof(Context *), &q_ctx, 0);
00660     *errcode_ret |= kernel->info(CL_KERNEL_CONTEXT, sizeof(Context *), &k_ctx, 0);
00661     *errcode_ret |= device->info(CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t),
00662                                 &max_work_group_size, 0);
00663     *errcode_ret |= device->info(CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(size_t),
00664                                 &max_dims, 0);
00665     *errcode_ret |= device->info(CL_DEVICE_MAX_WORK_ITEM_SIZES,
00666                                 max_dims * sizeof(size_t), p_max_work_item_sizes, 0);
00667 
00668     if (*errcode_ret != CL_SUCCESS)
00669         return;
00670 
00671     p_dev_kernel = kernel->deviceDependentKernel(device);
00672 
00673     if (!p_dev_kernel)
00674     {
00675         *errcode_ret = CL_INVALID_PROGRAM_EXECUTABLE;
00676         return;
00677     }
00678 
00679     // Check that contexts match
00680     if (k_ctx != q_ctx)
00681     {
00682         *errcode_ret = CL_INVALID_CONTEXT;
00683         return;
00684     }
00685 
00686     // Check args
00687     if (!kernel->argsSpecified())
00688     {
00689         *errcode_ret = CL_INVALID_KERNEL_ARGS;
00690         return;
00691     }
00692 
00693     // Check dimension
00694     if (work_dim == 0 || work_dim > max_dims)
00695     {
00696         *errcode_ret = CL_INVALID_WORK_DIMENSION;
00697         return;
00698     }
00699 
00700     // Populate work_offset, work_size and local_work_size
00701     size_t work_group_size = 1;
00702 
00703     for (cl_uint i=0; i<work_dim; ++i)
00704     {
00705         if (global_work_offset)
00706         {
00707             p_global_work_offset[i] = global_work_offset[i];
00708         }
00709         else
00710         {
00711             p_global_work_offset[i] = 0;
00712         }
00713 
00714         if (!global_work_size || !global_work_size[i])
00715         {
00716             *errcode_ret = CL_INVALID_GLOBAL_WORK_SIZE;
00717         }
00718         p_global_work_size[i] = global_work_size[i];
00719 
00720         if (!local_work_size)
00721         {
00722             // Guess the best value according to the device
00723             p_local_work_size[i] =
00724                 p_dev_kernel->guessWorkGroupSize(work_dim, i, global_work_size[i]);
00725 
00726             // TODO: CL_INVALID_WORK_GROUP_SIZE if
00727             // __attribute__((reqd_work_group_size(X, Y, Z))) is set
00728         }
00729         else
00730         {
00731             // Check divisibility
00732             if ((global_work_size[i] % local_work_size[i]) != 0)
00733             {
00734                 *errcode_ret = CL_INVALID_WORK_GROUP_SIZE;
00735                 return;
00736             }
00737 
00738             // Not too big ?
00739             if (local_work_size[i] > p_max_work_item_sizes[i])
00740             {
00741                 *errcode_ret = CL_INVALID_WORK_ITEM_SIZE;
00742                 return;
00743             }
00744 
00745             // TODO: CL_INVALID_WORK_GROUP_SIZE if
00746             // __attribute__((reqd_work_group_size(X, Y, Z))) doesn't match
00747 
00748             p_local_work_size[i] = local_work_size[i];
00749             work_group_size *= local_work_size[i];
00750         }
00751     }
00752 
00753     // Check we don't ask too much to the device
00754     if (work_group_size > max_work_group_size)
00755     {
00756         *errcode_ret = CL_INVALID_WORK_GROUP_SIZE;
00757         return;
00758     }
00759 
00760     // Check arguments (buffer alignment, image size, ...)
00761     for (unsigned int i=0; i<kernel->numArgs(); ++i)
00762     {
00763         const Kernel::Arg &a = kernel->arg(i);
00764 
00765         if (a.kind() == Kernel::Arg::Buffer)
00766         {
00767             const MemObject *buffer = *(const MemObject **)(a.value(0));
00768 
00769             if (!BufferEvent::isSubBufferAligned(buffer, device))
00770             {
00771                 *errcode_ret = CL_MISALIGNED_SUB_BUFFER_OFFSET;
00772                 return;
00773             }
00774         }
00775         else if (a.kind() == Kernel::Arg::Image2D)
00776         {
00777             const Image2D *image = *(const Image2D **)(a.value(0));
00778             size_t maxWidth, maxHeight;
00779 
00780             *errcode_ret = device->info(CL_DEVICE_IMAGE2D_MAX_WIDTH,
00781                                         sizeof(size_t), &maxWidth, 0);
00782             *errcode_ret |= device->info(CL_DEVICE_IMAGE2D_MAX_HEIGHT,
00783                                          sizeof(size_t), &maxHeight, 0);
00784 
00785             if (*errcode_ret != CL_SUCCESS)
00786                 return;
00787 
00788             if (image->width() > maxWidth || image->height() > maxHeight)
00789             {
00790                 *errcode_ret = CL_INVALID_IMAGE_SIZE;
00791                 return;
00792             }
00793         }
00794         else if (a.kind() == Kernel::Arg::Image3D)
00795         {
00796             const Image3D *image = *(const Image3D **)a.value(0);
00797             size_t maxWidth, maxHeight, maxDepth;
00798 
00799             *errcode_ret = device->info(CL_DEVICE_IMAGE3D_MAX_WIDTH,
00800                                         sizeof(size_t), &maxWidth, 0);
00801             *errcode_ret |= device->info(CL_DEVICE_IMAGE3D_MAX_HEIGHT,
00802                                          sizeof(size_t), &maxHeight, 0);
00803             *errcode_ret |= device->info(CL_DEVICE_IMAGE3D_MAX_DEPTH,
00804                                          sizeof(size_t), &maxDepth, 0);
00805 
00806             if (*errcode_ret != CL_SUCCESS)
00807                 return;
00808 
00809             if (image->width() > maxWidth || image->height() > maxHeight ||
00810                 image->depth() > maxDepth)
00811             {
00812                 *errcode_ret = CL_INVALID_IMAGE_SIZE;
00813                 return;
00814             }
00815         }
00816     }
00817 }
00818 
00819 KernelEvent::~KernelEvent()
00820 {
00821 
00822 }
00823 
00824 cl_uint KernelEvent::work_dim() const
00825 {
00826     return p_work_dim;
00827 }
00828 
00829 size_t KernelEvent::global_work_offset(cl_uint dim) const
00830 {
00831     return p_global_work_offset[dim];
00832 }
00833 
00834 size_t KernelEvent::global_work_size(cl_uint dim) const
00835 {
00836     return p_global_work_size[dim];
00837 }
00838 
00839 size_t KernelEvent::local_work_size(cl_uint dim) const
00840 {
00841     return p_local_work_size[dim];
00842 }
00843 
00844 Kernel *KernelEvent::kernel() const
00845 {
00846     return p_kernel;
00847 }
00848 
00849 DeviceKernel *KernelEvent::deviceKernel() const
00850 {
00851     return p_dev_kernel;
00852 }
00853 
00854 Event::Type KernelEvent::type() const
00855 {
00856     return Event::NDRangeKernel;
00857 }
00858 
00859 static size_t one = 1;
00860 
00861 TaskEvent::TaskEvent(CommandQueue *parent,
00862                      Kernel *kernel,
00863                      cl_uint num_events_in_wait_list,
00864                      const Event **event_wait_list,
00865                      cl_int *errcode_ret)
00866 : KernelEvent(parent, kernel, 1, 0, &one, &one, num_events_in_wait_list,
00867               event_wait_list, errcode_ret)
00868 {
00869     // TODO: CL_INVALID_WORK_GROUP_SIZE if
00870     // __attribute__((reqd_work_group_size(X, Y, Z))) != (1, 1, 1)
00871 }
00872 
00873 Event::Type TaskEvent::type() const
00874 {
00875     return Event::TaskKernel;
00876 }
00877 
00878 /*
00879  * User event
00880  */
00881 UserEvent::UserEvent(Context *context, cl_int *errcode_ret)
00882 : Event(0, Submitted, 0, 0, errcode_ret), p_context(context)
00883 {}
00884 
00885 Event::Type UserEvent::type() const
00886 {
00887     return Event::User;
00888 }
00889 
00890 Context *UserEvent::context() const
00891 {
00892     return p_context;
00893 }
00894 
00895 void UserEvent::addDependentCommandQueue(CommandQueue *queue)
00896 {
00897     std::vector<CommandQueue *>::const_iterator it;
00898 
00899     for (it = p_dependent_queues.begin(); it != p_dependent_queues.end(); ++it)
00900         if (*it == queue)
00901             return;
00902 
00903     p_dependent_queues.push_back(queue);
00904 }
00905 
00906 void UserEvent::flushQueues()
00907 {
00908     std::vector<CommandQueue *>::const_iterator it;
00909 
00910     for (it = p_dependent_queues.begin(); it != p_dependent_queues.end(); ++it)
00911         (*it)->pushEventsOnDevice();
00912 }
00913 
00914 /*
00915  * ReadWriteBufferRectEvent
00916  */
00917 ReadWriteCopyBufferRectEvent::ReadWriteCopyBufferRectEvent(CommandQueue *parent,
00918                                                            MemObject *source,
00919                                                            const size_t src_origin[3],
00920                                                            const size_t dst_origin[3],
00921                                                            const size_t region[3],
00922                                                            size_t src_row_pitch,
00923                                                            size_t src_slice_pitch,
00924                                                            size_t dst_row_pitch,
00925                                                            size_t dst_slice_pitch,
00926                                                            unsigned int bytes_per_element,
00927                                                            cl_uint num_events_in_wait_list,
00928                                                            const Event **event_wait_list,
00929                                                            cl_int *errcode_ret)
00930 : BufferEvent (parent, source, num_events_in_wait_list, event_wait_list,
00931                errcode_ret)
00932 {
00933     if (*errcode_ret != CL_SUCCESS) return;
00934 
00935     // Copy the vectors
00936     if (src_origin)
00937         std::memcpy(&p_src_origin, src_origin, 3 * sizeof(size_t));
00938     else
00939         std::memset(&p_src_origin, 0, 3 * sizeof(size_t));
00940 
00941     if (dst_origin)
00942         std::memcpy(&p_dst_origin, dst_origin, 3 * sizeof(size_t));
00943     else
00944         std::memset(&p_dst_origin, 0, 3 * sizeof(size_t));
00945 
00946     for (unsigned int i=0; i<3; ++i)
00947     {
00948         if (!region[i])
00949         {
00950             *errcode_ret = CL_INVALID_VALUE;
00951             return;
00952         }
00953 
00954         p_region[i] = region[i];
00955     }
00956 
00957     // Multiply the elements (for images)
00958     p_region[0] *= bytes_per_element;
00959     p_src_origin[0] *= bytes_per_element;
00960     p_dst_origin[0] *= bytes_per_element;
00961 
00962     // Compute the pitches
00963     p_src_row_pitch = p_region[0];
00964 
00965     if (src_row_pitch)
00966     {
00967         if (src_row_pitch < p_src_row_pitch)
00968         {
00969             *errcode_ret = CL_INVALID_VALUE;
00970             return;
00971         }
00972 
00973         p_src_row_pitch = src_row_pitch;
00974     }
00975 
00976     p_src_slice_pitch = p_region[1] * p_src_row_pitch;
00977 
00978     if (src_slice_pitch)
00979     {
00980         if (src_slice_pitch < p_src_slice_pitch)
00981         {
00982             *errcode_ret = CL_INVALID_VALUE;
00983             return;
00984         }
00985 
00986         p_src_slice_pitch = src_slice_pitch;
00987     }
00988 
00989     p_dst_row_pitch = p_region[0];
00990 
00991     if (dst_row_pitch)
00992     {
00993         if (dst_row_pitch < p_dst_row_pitch)
00994         {
00995             *errcode_ret = CL_INVALID_VALUE;
00996             return;
00997         }
00998 
00999         p_dst_row_pitch = dst_row_pitch;
01000     }
01001 
01002     p_dst_slice_pitch = p_region[1] * p_dst_row_pitch;
01003 
01004     if (dst_slice_pitch)
01005     {
01006         if (dst_slice_pitch < p_dst_slice_pitch)
01007         {
01008             *errcode_ret = CL_INVALID_VALUE;
01009             return;
01010         }
01011 
01012         p_dst_slice_pitch = dst_slice_pitch;
01013     }
01014 }
01015 
01016 size_t ReadWriteCopyBufferRectEvent::src_origin(unsigned int index) const
01017 {
01018     return p_src_origin[index];
01019 }
01020 
01021 size_t ReadWriteCopyBufferRectEvent::dst_origin(unsigned int index) const
01022 {
01023     return p_dst_origin[index];
01024 }
01025 
01026 size_t ReadWriteCopyBufferRectEvent::region(unsigned int index) const
01027 {
01028     return p_region[index];
01029 }
01030 
01031 size_t ReadWriteCopyBufferRectEvent::src_row_pitch() const
01032 {
01033     return p_src_row_pitch;
01034 }
01035 
01036 size_t ReadWriteCopyBufferRectEvent::src_slice_pitch() const
01037 {
01038     return p_src_slice_pitch;
01039 }
01040 
01041 size_t ReadWriteCopyBufferRectEvent::dst_row_pitch() const
01042 {
01043     return p_dst_row_pitch;
01044 }
01045 
01046 size_t ReadWriteCopyBufferRectEvent::dst_slice_pitch() const
01047 {
01048     return p_dst_slice_pitch;
01049 }
01050 
01051 MemObject *ReadWriteCopyBufferRectEvent::source() const
01052 {
01053     return buffer();
01054 }
01055 
01056 CopyBufferRectEvent::CopyBufferRectEvent(CommandQueue *parent,
01057                                          MemObject *source,
01058                                          MemObject *destination,
01059                                          const size_t src_origin[3],
01060                                          const size_t dst_origin[3],
01061                                          const size_t region[3],
01062                                          size_t src_row_pitch,
01063                                          size_t src_slice_pitch,
01064                                          size_t dst_row_pitch,
01065                                          size_t dst_slice_pitch,
01066                                          unsigned int bytes_per_element,
01067                                          cl_uint num_events_in_wait_list,
01068                                          const Event **event_wait_list,
01069                                          cl_int *errcode_ret)
01070 : ReadWriteCopyBufferRectEvent(parent, source, src_origin, dst_origin, region,
01071                                src_row_pitch, src_slice_pitch, dst_row_pitch,
01072                                dst_slice_pitch, bytes_per_element,
01073                                num_events_in_wait_list, event_wait_list, errcode_ret),
01074   p_destination(destination)
01075 {
01076     if (*errcode_ret != CL_SUCCESS) return;
01077 
01078     if (!destination)
01079     {
01080         *errcode_ret = CL_INVALID_MEM_OBJECT;
01081         return;
01082     }
01083 
01084     // Check for out-of-bounds
01085     if ((p_src_origin[0] + p_region[0]) > p_src_row_pitch ||
01086         (p_src_origin[1] + p_region[1]) * p_src_row_pitch > p_src_slice_pitch ||
01087         (p_src_origin[2] + p_region[2]) * p_src_slice_pitch > source->size())
01088     {
01089         *errcode_ret = CL_INVALID_VALUE;
01090         return;
01091     }
01092 
01093     if ((p_dst_origin[0] + p_region[0]) > p_dst_row_pitch ||
01094         (p_dst_origin[1] + p_region[1]) * p_dst_row_pitch > p_dst_slice_pitch ||
01095         (p_dst_origin[2] + p_region[2]) * p_dst_slice_pitch > destination->size())
01096     {
01097         *errcode_ret = CL_INVALID_VALUE;
01098         return;
01099     }
01100 
01101     // Check for overlapping
01102     if (source == destination)
01103     {
01104         unsigned char overlapping_dimensions = 0;
01105 
01106         for (unsigned int i=0; i<3; ++i)
01107         {
01108             if ((p_dst_origin[i] < p_src_origin[i] && p_dst_origin[i] + p_region[i] > p_src_origin[i]) ||
01109                 (p_src_origin[i] < p_dst_origin[i] && p_src_origin[i] + p_region[i] > p_dst_origin[i]))
01110                 overlapping_dimensions++;
01111         }
01112 
01113         if (overlapping_dimensions == 3)
01114         {
01115             // If all the dimensions are overlapping, the region is overlapping
01116             *errcode_ret = CL_MEM_COPY_OVERLAP;
01117             return;
01118         }
01119     }
01120 
01121     // Check alignment of destination (source already checked by BufferEvent)
01122     DeviceInterface *device = 0;
01123     *errcode_ret = parent->info(CL_QUEUE_DEVICE, sizeof(DeviceInterface *),
01124                                 &device, 0);
01125 
01126     if (*errcode_ret != CL_SUCCESS)
01127         return;
01128 
01129     if (!isSubBufferAligned(destination, device))
01130     {
01131         *errcode_ret = CL_MISALIGNED_SUB_BUFFER_OFFSET;
01132         return;
01133     }
01134 
01135     // Allocate the buffer for the device
01136     if (!destination->allocate(device))
01137     {
01138         *errcode_ret = CL_MEM_OBJECT_ALLOCATION_FAILURE;
01139         return;
01140     }
01141 }
01142 
01143 Event::Type CopyBufferRectEvent::type() const
01144 {
01145     return Event::CopyBufferRect;
01146 }
01147 
01148 MemObject *CopyBufferRectEvent::destination() const
01149 {
01150     return p_destination;
01151 }
01152 
01153 ReadWriteBufferRectEvent::ReadWriteBufferRectEvent(CommandQueue *parent,
01154                                                    MemObject *buffer,
01155                                                    const size_t buffer_origin[3],
01156                                                    const size_t host_origin[3],
01157                                                    const size_t region[3],
01158                                                    size_t buffer_row_pitch,
01159                                                    size_t buffer_slice_pitch,
01160                                                    size_t host_row_pitch,
01161                                                    size_t host_slice_pitch,
01162                                                    void *ptr,
01163                                                    unsigned int bytes_per_element,
01164                                                    cl_uint num_events_in_wait_list,
01165                                                    const Event **event_wait_list,
01166                                                    cl_int *errcode_ret)
01167 : ReadWriteCopyBufferRectEvent(parent, buffer, buffer_origin, host_origin, region,
01168                                buffer_row_pitch, buffer_slice_pitch,
01169                                host_row_pitch, host_slice_pitch, bytes_per_element,
01170                                num_events_in_wait_list, event_wait_list, errcode_ret),
01171   p_ptr(ptr)
01172 {
01173     if (*errcode_ret != CL_SUCCESS) return;
01174 
01175     if (!ptr)
01176     {
01177         *errcode_ret = CL_INVALID_VALUE;
01178         return;
01179     }
01180 
01181     // Check for out-of-bounds
01182     if ((p_src_origin[0] + p_region[0]) > p_src_row_pitch ||
01183         (p_src_origin[1] + p_region[1]) * p_src_row_pitch > p_src_slice_pitch ||
01184         (p_src_origin[2] + p_region[2]) * p_src_slice_pitch > buffer->size())
01185     {
01186         *errcode_ret = CL_INVALID_VALUE;
01187         return;
01188     }
01189 }
01190 
01191 void *ReadWriteBufferRectEvent::ptr() const
01192 {
01193     return p_ptr;
01194 }
01195 
01196 ReadBufferRectEvent::ReadBufferRectEvent (CommandQueue *parent,
01197                                           MemObject *buffer,
01198                                           const size_t buffer_origin[3],
01199                                           const size_t host_origin[3],
01200                                           const size_t region[3],
01201                                           size_t buffer_row_pitch,
01202                                           size_t buffer_slice_pitch,
01203                                           size_t host_row_pitch,
01204                                           size_t host_slice_pitch,
01205                                           void *ptr,
01206                                           cl_uint num_events_in_wait_list,
01207                                           const Event **event_wait_list,
01208                                           cl_int *errcode_ret)
01209 : ReadWriteBufferRectEvent(parent, buffer, buffer_origin, host_origin, region,
01210                            buffer_row_pitch, buffer_slice_pitch, host_row_pitch,
01211                            host_slice_pitch, ptr, 1, num_events_in_wait_list,
01212                            event_wait_list, errcode_ret)
01213 {
01214 }
01215 
01216 Event::Type ReadBufferRectEvent::type() const
01217 {
01218     return ReadBufferRect;
01219 }
01220 
01221 WriteBufferRectEvent::WriteBufferRectEvent (CommandQueue *parent,
01222                                             MemObject *buffer,
01223                                             const size_t buffer_origin[3],
01224                                             const size_t host_origin[3],
01225                                             const size_t region[3],
01226                                             size_t buffer_row_pitch,
01227                                             size_t buffer_slice_pitch,
01228                                             size_t host_row_pitch,
01229                                             size_t host_slice_pitch,
01230                                             void *ptr,
01231                                             cl_uint num_events_in_wait_list,
01232                                             const Event **event_wait_list,
01233                                             cl_int *errcode_ret)
01234 : ReadWriteBufferRectEvent (parent, buffer, buffer_origin, host_origin, region,
01235                             buffer_row_pitch, buffer_slice_pitch, host_row_pitch,
01236                             host_slice_pitch, ptr, 1, num_events_in_wait_list,
01237                             event_wait_list, errcode_ret)
01238 {
01239 }
01240 
01241 Event::Type WriteBufferRectEvent::type() const
01242 {
01243     return WriteBufferRect;
01244 }
01245 
01246 ReadWriteImageEvent::ReadWriteImageEvent (CommandQueue *parent,
01247                                           Image2D *image,
01248                                           const size_t origin[3],
01249                                           const size_t region[3],
01250                                           size_t row_pitch,
01251                                           size_t slice_pitch,
01252                                           void *ptr,
01253                                           cl_uint num_events_in_wait_list,
01254                                           const Event **event_wait_list,
01255                                           cl_int *errcode_ret)
01256 : ReadWriteBufferRectEvent(parent, image, origin, 0, region, image->row_pitch(),
01257                            image->slice_pitch(), row_pitch, slice_pitch, ptr,
01258                            image->pixel_size(), num_events_in_wait_list,
01259                            event_wait_list, errcode_ret)
01260 {
01261     if (*errcode_ret != CL_SUCCESS) return;
01262 
01263     if (image->type() == MemObject::Image2D &&
01264         (origin[2] != 0 || region[2] != 1))
01265     {
01266         *errcode_ret = CL_INVALID_VALUE;
01267         return;
01268     }
01269 }
01270 
01271 ReadImageEvent::ReadImageEvent(CommandQueue *parent,
01272                                Image2D *image,
01273                                const size_t origin[3],
01274                                const size_t region[3],
01275                                size_t row_pitch,
01276                                size_t slice_pitch,
01277                                void *ptr,
01278                                cl_uint num_events_in_wait_list,
01279                                const Event **event_wait_list,
01280                                cl_int *errcode_ret)
01281 : ReadWriteImageEvent(parent, image, origin, region, row_pitch, slice_pitch, ptr,
01282                       num_events_in_wait_list, event_wait_list, errcode_ret)
01283 {}
01284 
01285 Event::Type ReadImageEvent::type() const
01286 {
01287     return Event::ReadImage;
01288 }
01289 
01290 WriteImageEvent::WriteImageEvent(CommandQueue *parent,
01291                                  Image2D *image,
01292                                  const size_t origin[3],
01293                                  const size_t region[3],
01294                                  size_t row_pitch,
01295                                  size_t slice_pitch,
01296                                  void *ptr,
01297                                  cl_uint num_events_in_wait_list,
01298                                  const Event **event_wait_list,
01299                                  cl_int *errcode_ret)
01300 : ReadWriteImageEvent (parent, image, origin, region, row_pitch, slice_pitch, ptr,
01301                        num_events_in_wait_list, event_wait_list, errcode_ret)
01302 {}
01303 
01304 Event::Type WriteImageEvent::type() const
01305 {
01306     return Event::WriteImage;
01307 }
01308 
01309 static bool operator!=(const cl_image_format &a, const cl_image_format &b)
01310 {
01311     return (a.image_channel_data_type != b.image_channel_data_type) ||
01312            (a.image_channel_order != b.image_channel_order);
01313 }
01314 
01315 CopyImageEvent::CopyImageEvent(CommandQueue *parent,
01316                                Image2D *source,
01317                                Image2D *destination,
01318                                const size_t src_origin[3],
01319                                const size_t dst_origin[3],
01320                                const size_t region[3],
01321                                cl_uint num_events_in_wait_list,
01322                                const Event **event_wait_list,
01323                                cl_int *errcode_ret)
01324 : CopyBufferRectEvent (parent, source, destination, src_origin, dst_origin,
01325                        region, source->row_pitch(), source->slice_pitch(),
01326                        destination->row_pitch(), destination->slice_pitch(),
01327                        source->pixel_size(), num_events_in_wait_list,
01328                        event_wait_list, errcode_ret)
01329 {
01330     if (*errcode_ret != CL_SUCCESS) return;
01331 
01332     // Check bounds
01333     if (source->type() == MemObject::Image2D &&
01334         (src_origin[2] != 0 || region[2] != 1))
01335     {
01336         *errcode_ret = CL_INVALID_VALUE;
01337         return;
01338     }
01339 
01340     if (destination->type() == MemObject::Image2D &&
01341         (dst_origin[2] != 0 || region[2] != 1))
01342     {
01343         *errcode_ret = CL_INVALID_VALUE;
01344         return;
01345     }
01346 
01347     // Formats must match
01348     if (source->format() != destination->format())
01349     {
01350         *errcode_ret = CL_IMAGE_FORMAT_MISMATCH;
01351         return;
01352     }
01353 }
01354 
01355 Event::Type CopyImageEvent::type() const
01356 {
01357     return Event::CopyImage;
01358 }
01359 
01360 CopyImageToBufferEvent::CopyImageToBufferEvent(CommandQueue *parent,
01361                                                Image2D *source,
01362                                                MemObject *destination,
01363                                                const size_t src_origin[3],
01364                                                const size_t region[3],
01365                                                size_t dst_offset,
01366                                                cl_uint num_events_in_wait_list,
01367                                                const Event **event_wait_list,
01368                                                cl_int *errcode_ret)
01369 : CopyBufferRectEvent(parent, source, destination, src_origin, 0, region,
01370                       source->row_pitch(), source->slice_pitch(), 0, 0,
01371                       source->pixel_size(), num_events_in_wait_list,
01372                       event_wait_list, errcode_ret),
01373   p_offset(dst_offset)
01374 {
01375     if (*errcode_ret != CL_SUCCESS) return;
01376 
01377     // Check for buffer overflow
01378     size_t dst_cb = region[2] * region[1] * region[0] * source->pixel_size();
01379 
01380     if (dst_offset + dst_cb > destination->size())
01381     {
01382         *errcode_ret = CL_INVALID_VALUE;
01383         return;
01384     }
01385 
01386     // Check validity
01387     if (source->type() == MemObject::Image2D &&
01388         (src_origin[2] != 0 || region[2] != 1))
01389     {
01390         *errcode_ret = CL_INVALID_VALUE;
01391         return;
01392     }
01393 }
01394 
01395 size_t CopyImageToBufferEvent::offset() const
01396 {
01397     return p_offset;
01398 }
01399 
01400 Event::Type CopyImageToBufferEvent::type() const
01401 {
01402     return Event::CopyImageToBuffer;
01403 }
01404 
01405 CopyBufferToImageEvent::CopyBufferToImageEvent(CommandQueue *parent,
01406                                                MemObject *source,
01407                                                Image2D *destination,
01408                                                size_t src_offset,
01409                                                const size_t dst_origin[3],
01410                                                const size_t region[3],
01411                                                cl_uint num_events_in_wait_list,
01412                                                const Event **event_wait_list,
01413                                                cl_int *errcode_ret)
01414 : CopyBufferRectEvent(parent, source, destination, 0, dst_origin, region, 0, 0,
01415                       destination->row_pitch(), destination->slice_pitch(),
01416                       destination->pixel_size(), num_events_in_wait_list,
01417                       event_wait_list, errcode_ret),
01418   p_offset(src_offset)
01419 {
01420     if (*errcode_ret != CL_SUCCESS) return;
01421 
01422     // Check for buffer overflow
01423     size_t src_cb = region[2] * region[1] * region[0] * destination->pixel_size();
01424 
01425     if (src_offset + src_cb > source->size())
01426     {
01427         *errcode_ret = CL_INVALID_VALUE;
01428         return;
01429     }
01430 
01431     // Check validity
01432     if (destination->type() == MemObject::Image2D &&
01433         (dst_origin[2] != 0 || region[2] != 1))
01434     {
01435         *errcode_ret = CL_INVALID_VALUE;
01436         return;
01437     }
01438 }
01439 
01440 size_t CopyBufferToImageEvent::offset() const
01441 {
01442     return p_offset;
01443 }
01444 
01445 Event::Type CopyBufferToImageEvent::type() const
01446 {
01447     return Event::CopyBufferToImage;
01448 }
01449 
01450 /*
01451  * Barrier
01452  */
01453 
01454 BarrierEvent::BarrierEvent(CommandQueue *parent, cl_int *errcode_ret)
01455 : Event(parent, Queued, 0, 0, errcode_ret)
01456 {}
01457 
01458 Event::Type BarrierEvent::type() const
01459 {
01460     return Event::Barrier;
01461 }
01462 
01463 /*
01464  * WaitForEvents
01465  */
01466 
01467 WaitForEventsEvent::WaitForEventsEvent(CommandQueue *parent,
01468                                        cl_uint num_events_in_wait_list,
01469                                        const Event **event_wait_list,
01470                                        cl_int *errcode_ret)
01471 : Event(parent, Queued, num_events_in_wait_list, event_wait_list, errcode_ret)
01472 {}
01473 
01474 Event::Type WaitForEventsEvent::type() const
01475 {
01476     return Event::WaitForEvents;
01477 }
01478 
01479 /*
01480  * Marker
01481  */
01482 MarkerEvent::MarkerEvent(CommandQueue *parent,
01483                          cl_uint num_events_in_wait_list,
01484                          const Event **event_wait_list,
01485                          cl_int *errcode_ret)
01486 : WaitForEventsEvent(parent, num_events_in_wait_list, event_wait_list, errcode_ret)
01487 {}
01488 
01489 Event::Type MarkerEvent::type() const
01490 {
01491     return Event::Marker;
01492 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines