Clover Git
OpenCL 1.1 software implementation
|
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 }