1 // 2 // Copyright 2012 Francisco Jerez 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 // OTHER DEALINGS IN THE SOFTWARE. 21 // 22 23 #include <cstring> 24 25 #include "api/util.hpp" 26 #include "core/event.hpp" 27 #include "core/memory.hpp" 28 29 using namespace clover; 30 31 namespace { 32 typedef resource::vector vector_t; 33 34 vector_t 35 vector(const size_t *p) { 36 return range(p, 3); 37 } 38 39 vector_t 40 pitch(const vector_t ®ion, vector_t pitch) { 41 for (auto x : zip(tail(pitch), 42 map(multiplies(), region, pitch))) { 43 // The spec defines a value of zero as the natural pitch, 44 // i.e. the unaligned size of the previous dimension. 45 if (std::get<0>(x) == 0) 46 std::get<0>(x) = std::get<1>(x); 47 } 48 49 return pitch; 50 } 51 52 /// 53 /// Size of a region in bytes. 54 /// 55 size_t 56 size(const vector_t &pitch, const vector_t ®ion) { 57 if (any_of(is_zero(), region)) 58 return 0; 59 else 60 return dot(pitch, region - vector_t{ 0, 1, 1 }); 61 } 62 63 /// 64 /// Common argument checking shared by memory transfer commands. 65 /// 66 void 67 validate_common(command_queue &q, 68 const ref_vector<event> &deps) { 69 if (any_of([&](const event &ev) { 70 return ev.context() != q.context(); 71 }, deps)) 72 throw error(CL_INVALID_CONTEXT); 73 } 74 75 /// 76 /// Common error checking for a buffer object argument. 77 /// 78 void 79 validate_object(command_queue &q, buffer &mem, const vector_t &origin, 80 const vector_t &pitch, const vector_t ®ion) { 81 if (mem.context() != q.context()) 82 throw error(CL_INVALID_CONTEXT); 83 84 // The region must fit within the specified pitch, 85 if (any_of(greater(), map(multiplies(), pitch, region), tail(pitch))) 86 throw error(CL_INVALID_VALUE); 87 88 // ...and within the specified object. 89 if (dot(pitch, origin) + size(pitch, region) > mem.size()) 90 throw error(CL_INVALID_VALUE); 91 92 if (any_of(is_zero(), region)) 93 throw error(CL_INVALID_VALUE); 94 } 95 96 /// 97 /// Common error checking for an image argument. 98 /// 99 void 100 validate_object(command_queue &q, image &img, 101 const vector_t &orig, const vector_t ®ion) { 102 vector_t size = { img.width(), img.height(), img.depth() }; 103 104 if (!q.device().image_support()) 105 throw error(CL_INVALID_OPERATION); 106 107 if (img.context() != q.context()) 108 throw error(CL_INVALID_CONTEXT); 109 110 if (any_of(greater(), orig + region, size)) 111 throw error(CL_INVALID_VALUE); 112 113 if (any_of(is_zero(), region)) 114 throw error(CL_INVALID_VALUE); 115 } 116 117 /// 118 /// Common error checking for a host pointer argument. 119 /// 120 void 121 validate_object(command_queue &q, const void *ptr, const vector_t &orig, 122 const vector_t &pitch, const vector_t ®ion) { 123 if (!ptr) 124 throw error(CL_INVALID_VALUE); 125 126 // The region must fit within the specified pitch. 127 if (any_of(greater(), map(multiplies(), pitch, region), tail(pitch))) 128 throw error(CL_INVALID_VALUE); 129 } 130 131 /// 132 /// Common argument checking for a copy between two buffer objects. 133 /// 134 void 135 validate_copy(command_queue &q, buffer &dst_mem, 136 const vector_t &dst_orig, const vector_t &dst_pitch, 137 buffer &src_mem, 138 const vector_t &src_orig, const vector_t &src_pitch, 139 const vector_t ®ion) { 140 if (dst_mem == src_mem) { 141 auto dst_offset = dot(dst_pitch, dst_orig); 142 auto src_offset = dot(src_pitch, src_orig); 143 144 if (interval_overlaps()( 145 dst_offset, dst_offset + size(dst_pitch, region), 146 src_offset, src_offset + size(src_pitch, region))) 147 throw error(CL_MEM_COPY_OVERLAP); 148 } 149 } 150 151 /// 152 /// Common argument checking for a copy between two image objects. 153 /// 154 void 155 validate_copy(command_queue &q, 156 image &dst_img, const vector_t &dst_orig, 157 image &src_img, const vector_t &src_orig, 158 const vector_t ®ion) { 159 if (dst_img.format() != src_img.format()) 160 throw error(CL_IMAGE_FORMAT_MISMATCH); 161 162 if (dst_img == src_img) { 163 if (all_of(interval_overlaps(), 164 dst_orig, dst_orig + region, 165 src_orig, src_orig + region)) 166 throw error(CL_MEM_COPY_OVERLAP); 167 } 168 } 169 170 /// 171 /// Checks that the host access flags of the memory object are 172 /// within the allowed set \a flags. 173 /// 174 void 175 validate_object_access(const memory_obj &mem, const cl_mem_flags flags) { 176 if (mem.flags() & ~flags & 177 (CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_WRITE_ONLY | 178 CL_MEM_HOST_NO_ACCESS)) 179 throw error(CL_INVALID_OPERATION); 180 } 181 182 /// 183 /// Checks that the mapping flags are correct. 184 /// 185 void 186 validate_map_flags(const memory_obj &mem, const cl_map_flags flags) { 187 if ((flags & (CL_MAP_WRITE | CL_MAP_READ)) && 188 (flags & CL_MAP_WRITE_INVALIDATE_REGION)) 189 throw error(CL_INVALID_VALUE); 190 191 if (flags & CL_MAP_READ) 192 validate_object_access(mem, CL_MEM_HOST_READ_ONLY); 193 194 if (flags & (CL_MAP_WRITE | CL_MAP_WRITE_INVALIDATE_REGION)) 195 validate_object_access(mem, CL_MEM_HOST_WRITE_ONLY); 196 } 197 198 /// 199 /// Class that encapsulates the task of mapping an object of type 200 /// \a T. The return value of get() should be implicitly 201 /// convertible to \a void *. 202 /// 203 template<typename T> 204 struct _map { 205 static mapping 206 get(command_queue &q, T obj, cl_map_flags flags, 207 size_t offset, size_t size) { 208 return { q, obj->resource(q), flags, true, 209 {{ offset }}, {{ size, 1, 1 }} }; 210 } 211 }; 212 213 template<> 214 struct _map<void *> { 215 static void * 216 get(command_queue &q, void *obj, cl_map_flags flags, 217 size_t offset, size_t size) { 218 return (char *)obj + offset; 219 } 220 }; 221 222 template<> 223 struct _map<const void *> { 224 static const void * 225 get(command_queue &q, const void *obj, cl_map_flags flags, 226 size_t offset, size_t size) { 227 return (const char *)obj + offset; 228 } 229 }; 230 231 /// 232 /// Software copy from \a src_obj to \a dst_obj. They can be 233 /// either pointers or memory objects. 234 /// 235 template<typename T, typename S> 236 std::function<void (event &)> 237 soft_copy_op(command_queue &q, 238 T dst_obj, const vector_t &dst_orig, const vector_t &dst_pitch, 239 S src_obj, const vector_t &src_orig, const vector_t &src_pitch, 240 const vector_t ®ion) { 241 return [=, &q](event &) { 242 auto dst = _map<T>::get(q, dst_obj, CL_MAP_WRITE, 243 dot(dst_pitch, dst_orig), 244 size(dst_pitch, region)); 245 auto src = _map<S>::get(q, src_obj, CL_MAP_READ, 246 dot(src_pitch, src_orig), 247 size(src_pitch, region)); 248 vector_t v = {}; 249 250 for (v[2] = 0; v[2] < region[2]; ++v[2]) { 251 for (v[1] = 0; v[1] < region[1]; ++v[1]) { 252 std::memcpy( 253 static_cast<char *>(dst) + dot(dst_pitch, v), 254 static_cast<const char *>(src) + dot(src_pitch, v), 255 src_pitch[0] * region[0]); 256 } 257 } 258 }; 259 } 260 261 /// 262 /// Hardware copy from \a src_obj to \a dst_obj. 263 /// 264 template<typename T, typename S> 265 std::function<void (event &)> 266 hard_copy_op(command_queue &q, T dst_obj, const vector_t &dst_orig, 267 S src_obj, const vector_t &src_orig, const vector_t ®ion) { 268 return [=, &q](event &) { 269 dst_obj->resource(q).copy(q, dst_orig, region, 270 src_obj->resource(q), src_orig); 271 }; 272 } 273 } 274 275 CLOVER_API cl_int 276 clEnqueueReadBuffer(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, 277 size_t offset, size_t size, void *ptr, 278 cl_uint num_deps, const cl_event *d_deps, 279 cl_event *rd_ev) try { 280 auto &q = obj(d_q); 281 auto &mem = obj<buffer>(d_mem); 282 auto deps = objs<wait_list_tag>(d_deps, num_deps); 283 vector_t region = { size, 1, 1 }; 284 vector_t obj_origin = { offset }; 285 auto obj_pitch = pitch(region, {{ 1 }}); 286 287 validate_common(q, deps); 288 validate_object(q, ptr, {}, obj_pitch, region); 289 validate_object(q, mem, obj_origin, obj_pitch, region); 290 validate_object_access(mem, CL_MEM_HOST_READ_ONLY); 291 292 auto hev = create<hard_event>( 293 q, CL_COMMAND_READ_BUFFER, deps, 294 soft_copy_op(q, ptr, {}, obj_pitch, 295 &mem, obj_origin, obj_pitch, 296 region)); 297 298 ret_object(rd_ev, hev); 299 return CL_SUCCESS; 300 301 } catch (error &e) { 302 return e.get(); 303 } 304 305 CLOVER_API cl_int 306 clEnqueueWriteBuffer(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, 307 size_t offset, size_t size, const void *ptr, 308 cl_uint num_deps, const cl_event *d_deps, 309 cl_event *rd_ev) try { 310 auto &q = obj(d_q); 311 auto &mem = obj<buffer>(d_mem); 312 auto deps = objs<wait_list_tag>(d_deps, num_deps); 313 vector_t region = { size, 1, 1 }; 314 vector_t obj_origin = { offset }; 315 auto obj_pitch = pitch(region, {{ 1 }}); 316 317 validate_common(q, deps); 318 validate_object(q, mem, obj_origin, obj_pitch, region); 319 validate_object(q, ptr, {}, obj_pitch, region); 320 validate_object_access(mem, CL_MEM_HOST_WRITE_ONLY); 321 322 auto hev = create<hard_event>( 323 q, CL_COMMAND_WRITE_BUFFER, deps, 324 soft_copy_op(q, &mem, obj_origin, obj_pitch, 325 ptr, {}, obj_pitch, 326 region)); 327 328 ret_object(rd_ev, hev); 329 return CL_SUCCESS; 330 331 } catch (error &e) { 332 return e.get(); 333 } 334 335 CLOVER_API cl_int 336 clEnqueueReadBufferRect(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, 337 const size_t *p_obj_origin, 338 const size_t *p_host_origin, 339 const size_t *p_region, 340 size_t obj_row_pitch, size_t obj_slice_pitch, 341 size_t host_row_pitch, size_t host_slice_pitch, 342 void *ptr, 343 cl_uint num_deps, const cl_event *d_deps, 344 cl_event *rd_ev) try { 345 auto &q = obj(d_q); 346 auto &mem = obj<buffer>(d_mem); 347 auto deps = objs<wait_list_tag>(d_deps, num_deps); 348 auto region = vector(p_region); 349 auto obj_origin = vector(p_obj_origin); 350 auto obj_pitch = pitch(region, {{ 1, obj_row_pitch, obj_slice_pitch }}); 351 auto host_origin = vector(p_host_origin); 352 auto host_pitch = pitch(region, {{ 1, host_row_pitch, host_slice_pitch }}); 353 354 validate_common(q, deps); 355 validate_object(q, ptr, host_origin, host_pitch, region); 356 validate_object(q, mem, obj_origin, obj_pitch, region); 357 validate_object_access(mem, CL_MEM_HOST_READ_ONLY); 358 359 auto hev = create<hard_event>( 360 q, CL_COMMAND_READ_BUFFER_RECT, deps, 361 soft_copy_op(q, ptr, host_origin, host_pitch, 362 &mem, obj_origin, obj_pitch, 363 region)); 364 365 ret_object(rd_ev, hev); 366 return CL_SUCCESS; 367 368 } catch (error &e) { 369 return e.get(); 370 } 371 372 CLOVER_API cl_int 373 clEnqueueWriteBufferRect(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, 374 const size_t *p_obj_origin, 375 const size_t *p_host_origin, 376 const size_t *p_region, 377 size_t obj_row_pitch, size_t obj_slice_pitch, 378 size_t host_row_pitch, size_t host_slice_pitch, 379 const void *ptr, 380 cl_uint num_deps, const cl_event *d_deps, 381 cl_event *rd_ev) try { 382 auto &q = obj(d_q); 383 auto &mem = obj<buffer>(d_mem); 384 auto deps = objs<wait_list_tag>(d_deps, num_deps); 385 auto region = vector(p_region); 386 auto obj_origin = vector(p_obj_origin); 387 auto obj_pitch = pitch(region, {{ 1, obj_row_pitch, obj_slice_pitch }}); 388 auto host_origin = vector(p_host_origin); 389 auto host_pitch = pitch(region, {{ 1, host_row_pitch, host_slice_pitch }}); 390 391 validate_common(q, deps); 392 validate_object(q, mem, obj_origin, obj_pitch, region); 393 validate_object(q, ptr, host_origin, host_pitch, region); 394 validate_object_access(mem, CL_MEM_HOST_WRITE_ONLY); 395 396 auto hev = create<hard_event>( 397 q, CL_COMMAND_WRITE_BUFFER_RECT, deps, 398 soft_copy_op(q, &mem, obj_origin, obj_pitch, 399 ptr, host_origin, host_pitch, 400 region)); 401 402 ret_object(rd_ev, hev); 403 return CL_SUCCESS; 404 405 } catch (error &e) { 406 return e.get(); 407 } 408 409 CLOVER_API cl_int 410 clEnqueueCopyBuffer(cl_command_queue d_q, cl_mem d_src_mem, cl_mem d_dst_mem, 411 size_t src_offset, size_t dst_offset, size_t size, 412 cl_uint num_deps, const cl_event *d_deps, 413 cl_event *rd_ev) try { 414 auto &q = obj(d_q); 415 auto &src_mem = obj<buffer>(d_src_mem); 416 auto &dst_mem = obj<buffer>(d_dst_mem); 417 auto deps = objs<wait_list_tag>(d_deps, num_deps); 418 vector_t region = { size, 1, 1 }; 419 vector_t dst_origin = { dst_offset }; 420 auto dst_pitch = pitch(region, {{ 1 }}); 421 vector_t src_origin = { src_offset }; 422 auto src_pitch = pitch(region, {{ 1 }}); 423 424 validate_common(q, deps); 425 validate_object(q, dst_mem, dst_origin, dst_pitch, region); 426 validate_object(q, src_mem, src_origin, src_pitch, region); 427 validate_copy(q, dst_mem, dst_origin, dst_pitch, 428 src_mem, src_origin, src_pitch, region); 429 430 auto hev = create<hard_event>( 431 q, CL_COMMAND_COPY_BUFFER, deps, 432 hard_copy_op(q, &dst_mem, dst_origin, 433 &src_mem, src_origin, region)); 434 435 ret_object(rd_ev, hev); 436 return CL_SUCCESS; 437 438 } catch (error &e) { 439 return e.get(); 440 } 441 442 CLOVER_API cl_int 443 clEnqueueCopyBufferRect(cl_command_queue d_q, cl_mem d_src_mem, 444 cl_mem d_dst_mem, 445 const size_t *p_src_origin, const size_t *p_dst_origin, 446 const size_t *p_region, 447 size_t src_row_pitch, size_t src_slice_pitch, 448 size_t dst_row_pitch, size_t dst_slice_pitch, 449 cl_uint num_deps, const cl_event *d_deps, 450 cl_event *rd_ev) try { 451 auto &q = obj(d_q); 452 auto &src_mem = obj<buffer>(d_src_mem); 453 auto &dst_mem = obj<buffer>(d_dst_mem); 454 auto deps = objs<wait_list_tag>(d_deps, num_deps); 455 auto region = vector(p_region); 456 auto dst_origin = vector(p_dst_origin); 457 auto dst_pitch = pitch(region, {{ 1, dst_row_pitch, dst_slice_pitch }}); 458 auto src_origin = vector(p_src_origin); 459 auto src_pitch = pitch(region, {{ 1, src_row_pitch, src_slice_pitch }}); 460 461 validate_common(q, deps); 462 validate_object(q, dst_mem, dst_origin, dst_pitch, region); 463 validate_object(q, src_mem, src_origin, src_pitch, region); 464 validate_copy(q, dst_mem, dst_origin, dst_pitch, 465 src_mem, src_origin, src_pitch, region); 466 467 auto hev = create<hard_event>( 468 q, CL_COMMAND_COPY_BUFFER_RECT, deps, 469 soft_copy_op(q, &dst_mem, dst_origin, dst_pitch, 470 &src_mem, src_origin, src_pitch, 471 region)); 472 473 ret_object(rd_ev, hev); 474 return CL_SUCCESS; 475 476 } catch (error &e) { 477 return e.get(); 478 } 479 480 CLOVER_API cl_int 481 clEnqueueReadImage(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, 482 const size_t *p_origin, const size_t *p_region, 483 size_t row_pitch, size_t slice_pitch, void *ptr, 484 cl_uint num_deps, const cl_event *d_deps, 485 cl_event *rd_ev) try { 486 auto &q = obj(d_q); 487 auto &img = obj<image>(d_mem); 488 auto deps = objs<wait_list_tag>(d_deps, num_deps); 489 auto region = vector(p_region); 490 auto dst_pitch = pitch(region, {{ img.pixel_size(), 491 row_pitch, slice_pitch }}); 492 auto src_origin = vector(p_origin); 493 auto src_pitch = pitch(region, {{ img.pixel_size(), 494 img.row_pitch(), img.slice_pitch() }}); 495 496 validate_common(q, deps); 497 validate_object(q, ptr, {}, dst_pitch, region); 498 validate_object(q, img, src_origin, region); 499 validate_object_access(img, CL_MEM_HOST_READ_ONLY); 500 501 auto hev = create<hard_event>( 502 q, CL_COMMAND_READ_IMAGE, deps, 503 soft_copy_op(q, ptr, {}, dst_pitch, 504 &img, src_origin, src_pitch, 505 region)); 506 507 ret_object(rd_ev, hev); 508 return CL_SUCCESS; 509 510 } catch (error &e) { 511 return e.get(); 512 } 513 514 CLOVER_API cl_int 515 clEnqueueWriteImage(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, 516 const size_t *p_origin, const size_t *p_region, 517 size_t row_pitch, size_t slice_pitch, const void *ptr, 518 cl_uint num_deps, const cl_event *d_deps, 519 cl_event *rd_ev) try { 520 auto &q = obj(d_q); 521 auto &img = obj<image>(d_mem); 522 auto deps = objs<wait_list_tag>(d_deps, num_deps); 523 auto region = vector(p_region); 524 auto dst_origin = vector(p_origin); 525 auto dst_pitch = pitch(region, {{ img.pixel_size(), 526 img.row_pitch(), img.slice_pitch() }}); 527 auto src_pitch = pitch(region, {{ img.pixel_size(), 528 row_pitch, slice_pitch }}); 529 530 validate_common(q, deps); 531 validate_object(q, img, dst_origin, region); 532 validate_object(q, ptr, {}, src_pitch, region); 533 validate_object_access(img, CL_MEM_HOST_WRITE_ONLY); 534 535 auto hev = create<hard_event>( 536 q, CL_COMMAND_WRITE_IMAGE, deps, 537 soft_copy_op(q, &img, dst_origin, dst_pitch, 538 ptr, {}, src_pitch, 539 region)); 540 541 ret_object(rd_ev, hev); 542 return CL_SUCCESS; 543 544 } catch (error &e) { 545 return e.get(); 546 } 547 548 CLOVER_API cl_int 549 clEnqueueCopyImage(cl_command_queue d_q, cl_mem d_src_mem, cl_mem d_dst_mem, 550 const size_t *p_src_origin, const size_t *p_dst_origin, 551 const size_t *p_region, 552 cl_uint num_deps, const cl_event *d_deps, 553 cl_event *rd_ev) try { 554 auto &q = obj(d_q); 555 auto &src_img = obj<image>(d_src_mem); 556 auto &dst_img = obj<image>(d_dst_mem); 557 auto deps = objs<wait_list_tag>(d_deps, num_deps); 558 auto region = vector(p_region); 559 auto dst_origin = vector(p_dst_origin); 560 auto src_origin = vector(p_src_origin); 561 562 validate_common(q, deps); 563 validate_object(q, dst_img, dst_origin, region); 564 validate_object(q, src_img, src_origin, region); 565 validate_copy(q, dst_img, dst_origin, src_img, src_origin, region); 566 567 auto hev = create<hard_event>( 568 q, CL_COMMAND_COPY_IMAGE, deps, 569 hard_copy_op(q, &dst_img, dst_origin, 570 &src_img, src_origin, 571 region)); 572 573 ret_object(rd_ev, hev); 574 return CL_SUCCESS; 575 576 } catch (error &e) { 577 return e.get(); 578 } 579 580 CLOVER_API cl_int 581 clEnqueueCopyImageToBuffer(cl_command_queue d_q, 582 cl_mem d_src_mem, cl_mem d_dst_mem, 583 const size_t *p_src_origin, const size_t *p_region, 584 size_t dst_offset, 585 cl_uint num_deps, const cl_event *d_deps, 586 cl_event *rd_ev) try { 587 auto &q = obj(d_q); 588 auto &src_img = obj<image>(d_src_mem); 589 auto &dst_mem = obj<buffer>(d_dst_mem); 590 auto deps = objs<wait_list_tag>(d_deps, num_deps); 591 auto region = vector(p_region); 592 vector_t dst_origin = { dst_offset }; 593 auto dst_pitch = pitch(region, {{ src_img.pixel_size() }}); 594 auto src_origin = vector(p_src_origin); 595 auto src_pitch = pitch(region, {{ src_img.pixel_size(), 596 src_img.row_pitch(), 597 src_img.slice_pitch() }}); 598 599 validate_common(q, deps); 600 validate_object(q, dst_mem, dst_origin, dst_pitch, region); 601 validate_object(q, src_img, src_origin, region); 602 603 auto hev = create<hard_event>( 604 q, CL_COMMAND_COPY_IMAGE_TO_BUFFER, deps, 605 soft_copy_op(q, &dst_mem, dst_origin, dst_pitch, 606 &src_img, src_origin, src_pitch, 607 region)); 608 609 ret_object(rd_ev, hev); 610 return CL_SUCCESS; 611 612 } catch (error &e) { 613 return e.get(); 614 } 615 616 CLOVER_API cl_int 617 clEnqueueCopyBufferToImage(cl_command_queue d_q, 618 cl_mem d_src_mem, cl_mem d_dst_mem, 619 size_t src_offset, 620 const size_t *p_dst_origin, const size_t *p_region, 621 cl_uint num_deps, const cl_event *d_deps, 622 cl_event *rd_ev) try { 623 auto &q = obj(d_q); 624 auto &src_mem = obj<buffer>(d_src_mem); 625 auto &dst_img = obj<image>(d_dst_mem); 626 auto deps = objs<wait_list_tag>(d_deps, num_deps); 627 auto region = vector(p_region); 628 auto dst_origin = vector(p_dst_origin); 629 auto dst_pitch = pitch(region, {{ dst_img.pixel_size(), 630 dst_img.row_pitch(), 631 dst_img.slice_pitch() }}); 632 vector_t src_origin = { src_offset }; 633 auto src_pitch = pitch(region, {{ dst_img.pixel_size() }}); 634 635 validate_common(q, deps); 636 validate_object(q, dst_img, dst_origin, region); 637 validate_object(q, src_mem, src_origin, src_pitch, region); 638 639 auto hev = create<hard_event>( 640 q, CL_COMMAND_COPY_BUFFER_TO_IMAGE, deps, 641 soft_copy_op(q, &dst_img, dst_origin, dst_pitch, 642 &src_mem, src_origin, src_pitch, 643 region)); 644 645 ret_object(rd_ev, hev); 646 return CL_SUCCESS; 647 648 } catch (error &e) { 649 return e.get(); 650 } 651 652 CLOVER_API void * 653 clEnqueueMapBuffer(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, 654 cl_map_flags flags, size_t offset, size_t size, 655 cl_uint num_deps, const cl_event *d_deps, 656 cl_event *rd_ev, cl_int *r_errcode) try { 657 auto &q = obj(d_q); 658 auto &mem = obj<buffer>(d_mem); 659 auto deps = objs<wait_list_tag>(d_deps, num_deps); 660 vector_t region = { size, 1, 1 }; 661 vector_t obj_origin = { offset }; 662 auto obj_pitch = pitch(region, {{ 1 }}); 663 664 validate_common(q, deps); 665 validate_object(q, mem, obj_origin, obj_pitch, region); 666 validate_map_flags(mem, flags); 667 668 void *map = mem.resource(q).add_map(q, flags, blocking, obj_origin, region); 669 670 ret_object(rd_ev, create<hard_event>(q, CL_COMMAND_MAP_BUFFER, deps)); 671 ret_error(r_errcode, CL_SUCCESS); 672 return map; 673 674 } catch (error &e) { 675 ret_error(r_errcode, e); 676 return NULL; 677 } 678 679 CLOVER_API void * 680 clEnqueueMapImage(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, 681 cl_map_flags flags, 682 const size_t *p_origin, const size_t *p_region, 683 size_t *row_pitch, size_t *slice_pitch, 684 cl_uint num_deps, const cl_event *d_deps, 685 cl_event *rd_ev, cl_int *r_errcode) try { 686 auto &q = obj(d_q); 687 auto &img = obj<image>(d_mem); 688 auto deps = objs<wait_list_tag>(d_deps, num_deps); 689 auto region = vector(p_region); 690 auto origin = vector(p_origin); 691 692 validate_common(q, deps); 693 validate_object(q, img, origin, region); 694 validate_map_flags(img, flags); 695 696 void *map = img.resource(q).add_map(q, flags, blocking, origin, region); 697 698 ret_object(rd_ev, create<hard_event>(q, CL_COMMAND_MAP_IMAGE, deps)); 699 ret_error(r_errcode, CL_SUCCESS); 700 return map; 701 702 } catch (error &e) { 703 ret_error(r_errcode, e); 704 return NULL; 705 } 706 707 CLOVER_API cl_int 708 clEnqueueUnmapMemObject(cl_command_queue d_q, cl_mem d_mem, void *ptr, 709 cl_uint num_deps, const cl_event *d_deps, 710 cl_event *rd_ev) try { 711 auto &q = obj(d_q); 712 auto &mem = obj(d_mem); 713 auto deps = objs<wait_list_tag>(d_deps, num_deps); 714 715 validate_common(q, deps); 716 717 auto hev = create<hard_event>( 718 q, CL_COMMAND_UNMAP_MEM_OBJECT, deps, 719 [=, &q, &mem](event &) { 720 mem.resource(q).del_map(ptr); 721 }); 722 723 ret_object(rd_ev, hev); 724 return CL_SUCCESS; 725 726 } catch (error &e) { 727 return e.get(); 728 } 729 730 CLOVER_API cl_int 731 clEnqueueMigrateMemObjects(cl_command_queue command_queue, 732 cl_uint num_mem_objects, 733 const cl_mem *mem_objects, 734 cl_mem_migration_flags flags, 735 cl_uint num_events_in_wait_list, 736 const cl_event *event_wait_list, 737 cl_event *event) { 738 CLOVER_NOT_SUPPORTED_UNTIL("1.2"); 739 return CL_INVALID_VALUE; 740 } 741