1bf215546Sopenharmony_ci// 2bf215546Sopenharmony_ci// Copyright 2012 Francisco Jerez 3bf215546Sopenharmony_ci// 4bf215546Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci// copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci// to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci// the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci// and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci// Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci// 11bf215546Sopenharmony_ci// The above copyright notice and this permission notice shall be included in 12bf215546Sopenharmony_ci// all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci// 14bf215546Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15bf215546Sopenharmony_ci// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18bf215546Sopenharmony_ci// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19bf215546Sopenharmony_ci// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20bf215546Sopenharmony_ci// OTHER DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci// 22bf215546Sopenharmony_ci 23bf215546Sopenharmony_ci#include <cstring> 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include "util/bitscan.h" 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "api/dispatch.hpp" 28bf215546Sopenharmony_ci#include "api/util.hpp" 29bf215546Sopenharmony_ci#include "core/event.hpp" 30bf215546Sopenharmony_ci#include "core/memory.hpp" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ciusing namespace clover; 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_cinamespace { 35bf215546Sopenharmony_ci typedef resource::vector vector_t; 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci vector_t 38bf215546Sopenharmony_ci vector(const size_t *p) { 39bf215546Sopenharmony_ci if (!p) 40bf215546Sopenharmony_ci throw error(CL_INVALID_VALUE); 41bf215546Sopenharmony_ci return range(p, 3); 42bf215546Sopenharmony_ci } 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci vector_t 45bf215546Sopenharmony_ci pitch(const vector_t ®ion, vector_t pitch) { 46bf215546Sopenharmony_ci for (auto x : zip(tail(pitch), 47bf215546Sopenharmony_ci map(multiplies(), region, pitch))) { 48bf215546Sopenharmony_ci // The spec defines a value of zero as the natural pitch, 49bf215546Sopenharmony_ci // i.e. the unaligned size of the previous dimension. 50bf215546Sopenharmony_ci if (std::get<0>(x) == 0) 51bf215546Sopenharmony_ci std::get<0>(x) = std::get<1>(x); 52bf215546Sopenharmony_ci } 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci return pitch; 55bf215546Sopenharmony_ci } 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci /// 58bf215546Sopenharmony_ci /// Size of a region in bytes. 59bf215546Sopenharmony_ci /// 60bf215546Sopenharmony_ci size_t 61bf215546Sopenharmony_ci size(const vector_t &pitch, const vector_t ®ion) { 62bf215546Sopenharmony_ci if (any_of(is_zero(), region)) 63bf215546Sopenharmony_ci return 0; 64bf215546Sopenharmony_ci else 65bf215546Sopenharmony_ci return dot(pitch, region - vector_t{ 0, 1, 1 }); 66bf215546Sopenharmony_ci } 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci /// 69bf215546Sopenharmony_ci /// Common argument checking shared by memory transfer commands. 70bf215546Sopenharmony_ci /// 71bf215546Sopenharmony_ci void 72bf215546Sopenharmony_ci validate_common(command_queue &q, 73bf215546Sopenharmony_ci const ref_vector<event> &deps) { 74bf215546Sopenharmony_ci if (any_of([&](const event &ev) { 75bf215546Sopenharmony_ci return ev.context() != q.context(); 76bf215546Sopenharmony_ci }, deps)) 77bf215546Sopenharmony_ci throw error(CL_INVALID_CONTEXT); 78bf215546Sopenharmony_ci } 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci /// 81bf215546Sopenharmony_ci /// Common error checking for a buffer object argument. 82bf215546Sopenharmony_ci /// 83bf215546Sopenharmony_ci void 84bf215546Sopenharmony_ci validate_object(command_queue &q, buffer &mem, const vector_t &origin, 85bf215546Sopenharmony_ci const vector_t &pitch, const vector_t ®ion) { 86bf215546Sopenharmony_ci if (mem.context() != q.context()) 87bf215546Sopenharmony_ci throw error(CL_INVALID_CONTEXT); 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci // The region must fit within the specified pitch, 90bf215546Sopenharmony_ci if (any_of(greater(), map(multiplies(), pitch, region), tail(pitch))) 91bf215546Sopenharmony_ci throw error(CL_INVALID_VALUE); 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_ci // ...and within the specified object. 94bf215546Sopenharmony_ci if (dot(pitch, origin) + size(pitch, region) > mem.size()) 95bf215546Sopenharmony_ci throw error(CL_INVALID_VALUE); 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci if (any_of(is_zero(), region)) 98bf215546Sopenharmony_ci throw error(CL_INVALID_VALUE); 99bf215546Sopenharmony_ci } 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci /// 102bf215546Sopenharmony_ci /// Common error checking for an image argument. 103bf215546Sopenharmony_ci /// 104bf215546Sopenharmony_ci void 105bf215546Sopenharmony_ci validate_object(command_queue &q, image &img, 106bf215546Sopenharmony_ci const vector_t &orig, const vector_t ®ion) { 107bf215546Sopenharmony_ci size_t height = img.type() == CL_MEM_OBJECT_IMAGE1D_ARRAY ? img.array_size() : img.height(); 108bf215546Sopenharmony_ci size_t depth = img.type() == CL_MEM_OBJECT_IMAGE2D_ARRAY ? img.array_size() : img.depth(); 109bf215546Sopenharmony_ci vector_t size = { img.width(), height, depth }; 110bf215546Sopenharmony_ci const auto &dev = q.device(); 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci if (!dev.image_support()) 113bf215546Sopenharmony_ci throw error(CL_INVALID_OPERATION); 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci if (img.context() != q.context()) 116bf215546Sopenharmony_ci throw error(CL_INVALID_CONTEXT); 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci if (any_of(greater(), orig + region, size)) 119bf215546Sopenharmony_ci throw error(CL_INVALID_VALUE); 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci if (any_of(is_zero(), region)) 122bf215546Sopenharmony_ci throw error(CL_INVALID_VALUE); 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci switch (img.type()) { 125bf215546Sopenharmony_ci case CL_MEM_OBJECT_IMAGE1D: { 126bf215546Sopenharmony_ci const size_t max = dev.max_image_size(); 127bf215546Sopenharmony_ci if (img.width() > max) 128bf215546Sopenharmony_ci throw error(CL_INVALID_IMAGE_SIZE); 129bf215546Sopenharmony_ci break; 130bf215546Sopenharmony_ci } 131bf215546Sopenharmony_ci case CL_MEM_OBJECT_IMAGE1D_ARRAY: { 132bf215546Sopenharmony_ci const size_t max_size = dev.max_image_size(); 133bf215546Sopenharmony_ci const size_t max_array = dev.max_image_array_number(); 134bf215546Sopenharmony_ci if (img.width() > max_size || img.array_size() > max_array) 135bf215546Sopenharmony_ci throw error(CL_INVALID_IMAGE_SIZE); 136bf215546Sopenharmony_ci break; 137bf215546Sopenharmony_ci } 138bf215546Sopenharmony_ci case CL_MEM_OBJECT_IMAGE2D: { 139bf215546Sopenharmony_ci const size_t max = dev.max_image_size(); 140bf215546Sopenharmony_ci if (img.width() > max || img.height() > max) 141bf215546Sopenharmony_ci throw error(CL_INVALID_IMAGE_SIZE); 142bf215546Sopenharmony_ci break; 143bf215546Sopenharmony_ci } 144bf215546Sopenharmony_ci case CL_MEM_OBJECT_IMAGE2D_ARRAY: { 145bf215546Sopenharmony_ci const size_t max_size = dev.max_image_size(); 146bf215546Sopenharmony_ci const size_t max_array = dev.max_image_array_number(); 147bf215546Sopenharmony_ci if (img.width() > max_size || img.height() > max_size || img.array_size() > max_array) 148bf215546Sopenharmony_ci throw error(CL_INVALID_IMAGE_SIZE); 149bf215546Sopenharmony_ci break; 150bf215546Sopenharmony_ci } 151bf215546Sopenharmony_ci case CL_MEM_OBJECT_IMAGE3D: { 152bf215546Sopenharmony_ci const size_t max = dev.max_image_size_3d(); 153bf215546Sopenharmony_ci if (img.width() > max || img.height() > max || img.depth() > max) 154bf215546Sopenharmony_ci throw error(CL_INVALID_IMAGE_SIZE); 155bf215546Sopenharmony_ci break; 156bf215546Sopenharmony_ci } 157bf215546Sopenharmony_ci // XXX: Implement missing checks once Clover supports more image types. 158bf215546Sopenharmony_ci default: 159bf215546Sopenharmony_ci throw error(CL_INVALID_IMAGE_SIZE); 160bf215546Sopenharmony_ci } 161bf215546Sopenharmony_ci } 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci /// 164bf215546Sopenharmony_ci /// Common error checking for a host pointer argument. 165bf215546Sopenharmony_ci /// 166bf215546Sopenharmony_ci void 167bf215546Sopenharmony_ci validate_object(command_queue &q, const void *ptr, const vector_t &orig, 168bf215546Sopenharmony_ci const vector_t &pitch, const vector_t ®ion) { 169bf215546Sopenharmony_ci if (!ptr) 170bf215546Sopenharmony_ci throw error(CL_INVALID_VALUE); 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci // The region must fit within the specified pitch. 173bf215546Sopenharmony_ci if (any_of(greater(), map(multiplies(), pitch, region), tail(pitch))) 174bf215546Sopenharmony_ci throw error(CL_INVALID_VALUE); 175bf215546Sopenharmony_ci } 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci /// 178bf215546Sopenharmony_ci /// Common argument checking for a copy between two buffer objects. 179bf215546Sopenharmony_ci /// 180bf215546Sopenharmony_ci void 181bf215546Sopenharmony_ci validate_copy(command_queue &q, buffer &dst_mem, 182bf215546Sopenharmony_ci const vector_t &dst_orig, const vector_t &dst_pitch, 183bf215546Sopenharmony_ci buffer &src_mem, 184bf215546Sopenharmony_ci const vector_t &src_orig, const vector_t &src_pitch, 185bf215546Sopenharmony_ci const vector_t ®ion) { 186bf215546Sopenharmony_ci if (dst_mem == src_mem) { 187bf215546Sopenharmony_ci auto dst_offset = dot(dst_pitch, dst_orig); 188bf215546Sopenharmony_ci auto src_offset = dot(src_pitch, src_orig); 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci if (interval_overlaps()( 191bf215546Sopenharmony_ci dst_offset, dst_offset + size(dst_pitch, region), 192bf215546Sopenharmony_ci src_offset, src_offset + size(src_pitch, region))) 193bf215546Sopenharmony_ci throw error(CL_MEM_COPY_OVERLAP); 194bf215546Sopenharmony_ci } 195bf215546Sopenharmony_ci } 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci /// 198bf215546Sopenharmony_ci /// Common argument checking for a copy between two image objects. 199bf215546Sopenharmony_ci /// 200bf215546Sopenharmony_ci void 201bf215546Sopenharmony_ci validate_copy(command_queue &q, 202bf215546Sopenharmony_ci image &dst_img, const vector_t &dst_orig, 203bf215546Sopenharmony_ci image &src_img, const vector_t &src_orig, 204bf215546Sopenharmony_ci const vector_t ®ion) { 205bf215546Sopenharmony_ci if (dst_img.format() != src_img.format()) 206bf215546Sopenharmony_ci throw error(CL_IMAGE_FORMAT_MISMATCH); 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci if (dst_img == src_img) { 209bf215546Sopenharmony_ci if (all_of(interval_overlaps(), 210bf215546Sopenharmony_ci dst_orig, dst_orig + region, 211bf215546Sopenharmony_ci src_orig, src_orig + region)) 212bf215546Sopenharmony_ci throw error(CL_MEM_COPY_OVERLAP); 213bf215546Sopenharmony_ci } 214bf215546Sopenharmony_ci } 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci /// 217bf215546Sopenharmony_ci /// Checks that the host access flags of the memory object are 218bf215546Sopenharmony_ci /// within the allowed set \a flags. 219bf215546Sopenharmony_ci /// 220bf215546Sopenharmony_ci void 221bf215546Sopenharmony_ci validate_object_access(const memory_obj &mem, const cl_mem_flags flags) { 222bf215546Sopenharmony_ci if (mem.flags() & ~flags & 223bf215546Sopenharmony_ci (CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_WRITE_ONLY | 224bf215546Sopenharmony_ci CL_MEM_HOST_NO_ACCESS)) 225bf215546Sopenharmony_ci throw error(CL_INVALID_OPERATION); 226bf215546Sopenharmony_ci } 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci /// 229bf215546Sopenharmony_ci /// Checks that the mapping flags are correct. 230bf215546Sopenharmony_ci /// 231bf215546Sopenharmony_ci void 232bf215546Sopenharmony_ci validate_map_flags(const memory_obj &mem, const cl_map_flags flags) { 233bf215546Sopenharmony_ci if ((flags & (CL_MAP_WRITE | CL_MAP_READ)) && 234bf215546Sopenharmony_ci (flags & CL_MAP_WRITE_INVALIDATE_REGION)) 235bf215546Sopenharmony_ci throw error(CL_INVALID_VALUE); 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci if (flags & CL_MAP_READ) 238bf215546Sopenharmony_ci validate_object_access(mem, CL_MEM_HOST_READ_ONLY); 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci if (flags & (CL_MAP_WRITE | CL_MAP_WRITE_INVALIDATE_REGION)) 241bf215546Sopenharmony_ci validate_object_access(mem, CL_MEM_HOST_WRITE_ONLY); 242bf215546Sopenharmony_ci } 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci /// 245bf215546Sopenharmony_ci /// Checks that the memory migration flags are correct. 246bf215546Sopenharmony_ci /// 247bf215546Sopenharmony_ci void 248bf215546Sopenharmony_ci validate_mem_migration_flags(const cl_mem_migration_flags flags) { 249bf215546Sopenharmony_ci const cl_mem_migration_flags valid = 250bf215546Sopenharmony_ci CL_MIGRATE_MEM_OBJECT_HOST | 251bf215546Sopenharmony_ci CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED; 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci if (flags & ~valid) 254bf215546Sopenharmony_ci throw error(CL_INVALID_VALUE); 255bf215546Sopenharmony_ci } 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci /// 258bf215546Sopenharmony_ci /// Class that encapsulates the task of mapping an object of type 259bf215546Sopenharmony_ci /// \a T. The return value of get() should be implicitly 260bf215546Sopenharmony_ci /// convertible to \a void *. 261bf215546Sopenharmony_ci /// 262bf215546Sopenharmony_ci template<typename T> 263bf215546Sopenharmony_ci struct _map; 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci template<> 266bf215546Sopenharmony_ci struct _map<image*> { 267bf215546Sopenharmony_ci _map(command_queue &q, image *img, cl_map_flags flags, 268bf215546Sopenharmony_ci vector_t offset, vector_t pitch, vector_t region) : 269bf215546Sopenharmony_ci map(q, img->resource_in(q), flags, true, offset, region), 270bf215546Sopenharmony_ci pitch(map.pitch()) 271bf215546Sopenharmony_ci { } 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci template<typename T> 274bf215546Sopenharmony_ci operator T *() const { 275bf215546Sopenharmony_ci return static_cast<T *>(map); 276bf215546Sopenharmony_ci } 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci mapping map; 279bf215546Sopenharmony_ci vector_t pitch; 280bf215546Sopenharmony_ci }; 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_ci template<> 283bf215546Sopenharmony_ci struct _map<buffer*> { 284bf215546Sopenharmony_ci _map(command_queue &q, buffer *mem, cl_map_flags flags, 285bf215546Sopenharmony_ci vector_t offset, vector_t pitch, vector_t region) : 286bf215546Sopenharmony_ci map(q, mem->resource_in(q), flags, true, 287bf215546Sopenharmony_ci {{ dot(pitch, offset) }}, {{ size(pitch, region) }}), 288bf215546Sopenharmony_ci pitch(pitch) 289bf215546Sopenharmony_ci { } 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci template<typename T> 292bf215546Sopenharmony_ci operator T *() const { 293bf215546Sopenharmony_ci return static_cast<T *>(map); 294bf215546Sopenharmony_ci } 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci mapping map; 297bf215546Sopenharmony_ci vector_t pitch; 298bf215546Sopenharmony_ci }; 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_ci template<typename P> 301bf215546Sopenharmony_ci struct _map<P *> { 302bf215546Sopenharmony_ci _map(command_queue &q, P *ptr, cl_map_flags flags, 303bf215546Sopenharmony_ci vector_t offset, vector_t pitch, vector_t region) : 304bf215546Sopenharmony_ci ptr((P *)((char *)ptr + dot(pitch, offset))), pitch(pitch) 305bf215546Sopenharmony_ci { } 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci template<typename T> 308bf215546Sopenharmony_ci operator T *() const { 309bf215546Sopenharmony_ci return static_cast<T *>(ptr); 310bf215546Sopenharmony_ci } 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_ci P *ptr; 313bf215546Sopenharmony_ci vector_t pitch; 314bf215546Sopenharmony_ci }; 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci /// 317bf215546Sopenharmony_ci /// Software copy from \a src_obj to \a dst_obj. They can be 318bf215546Sopenharmony_ci /// either pointers or memory objects. 319bf215546Sopenharmony_ci /// 320bf215546Sopenharmony_ci template<typename T, typename S> 321bf215546Sopenharmony_ci std::function<void (event &)> 322bf215546Sopenharmony_ci soft_copy_op(command_queue &q, 323bf215546Sopenharmony_ci T dst_obj, const vector_t &dst_orig, const vector_t &dst_pitch, 324bf215546Sopenharmony_ci S src_obj, const vector_t &src_orig, const vector_t &src_pitch, 325bf215546Sopenharmony_ci const vector_t ®ion) { 326bf215546Sopenharmony_ci return [=, &q](event &) { 327bf215546Sopenharmony_ci _map<T> dst = { q, dst_obj, CL_MAP_WRITE, 328bf215546Sopenharmony_ci dst_orig, dst_pitch, region }; 329bf215546Sopenharmony_ci _map<S> src = { q, src_obj, CL_MAP_READ, 330bf215546Sopenharmony_ci src_orig, src_pitch, region }; 331bf215546Sopenharmony_ci assert(src.pitch[0] == dst.pitch[0]); 332bf215546Sopenharmony_ci vector_t v = {}; 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci for (v[2] = 0; v[2] < region[2]; ++v[2]) { 335bf215546Sopenharmony_ci for (v[1] = 0; v[1] < region[1]; ++v[1]) { 336bf215546Sopenharmony_ci std::memcpy( 337bf215546Sopenharmony_ci static_cast<char *>(dst) + dot(dst.pitch, v), 338bf215546Sopenharmony_ci static_cast<const char *>(src) + dot(src.pitch, v), 339bf215546Sopenharmony_ci src.pitch[0] * region[0]); 340bf215546Sopenharmony_ci } 341bf215546Sopenharmony_ci } 342bf215546Sopenharmony_ci }; 343bf215546Sopenharmony_ci } 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci /// 346bf215546Sopenharmony_ci /// Hardware copy from \a src_obj to \a dst_obj. 347bf215546Sopenharmony_ci /// 348bf215546Sopenharmony_ci template<typename T, typename S> 349bf215546Sopenharmony_ci std::function<void (event &)> 350bf215546Sopenharmony_ci hard_copy_op(command_queue &q, T dst_obj, const vector_t &dst_orig, 351bf215546Sopenharmony_ci S src_obj, const vector_t &src_orig, const vector_t ®ion) { 352bf215546Sopenharmony_ci return [=, &q](event &) { 353bf215546Sopenharmony_ci dst_obj->resource_in(q).copy(q, dst_orig, region, 354bf215546Sopenharmony_ci src_obj->resource_in(q), src_orig); 355bf215546Sopenharmony_ci }; 356bf215546Sopenharmony_ci } 357bf215546Sopenharmony_ci} 358bf215546Sopenharmony_ci 359bf215546Sopenharmony_ciCLOVER_API cl_int 360bf215546Sopenharmony_ciclEnqueueReadBuffer(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, 361bf215546Sopenharmony_ci size_t offset, size_t size, void *ptr, 362bf215546Sopenharmony_ci cl_uint num_deps, const cl_event *d_deps, 363bf215546Sopenharmony_ci cl_event *rd_ev) try { 364bf215546Sopenharmony_ci auto &q = obj(d_q); 365bf215546Sopenharmony_ci auto &mem = obj<buffer>(d_mem); 366bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 367bf215546Sopenharmony_ci vector_t region = { size, 1, 1 }; 368bf215546Sopenharmony_ci vector_t obj_origin = { offset }; 369bf215546Sopenharmony_ci auto obj_pitch = pitch(region, {{ 1 }}); 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci validate_common(q, deps); 372bf215546Sopenharmony_ci validate_object(q, ptr, {}, obj_pitch, region); 373bf215546Sopenharmony_ci validate_object(q, mem, obj_origin, obj_pitch, region); 374bf215546Sopenharmony_ci validate_object_access(mem, CL_MEM_HOST_READ_ONLY); 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci auto hev = create<hard_event>( 377bf215546Sopenharmony_ci q, CL_COMMAND_READ_BUFFER, deps, 378bf215546Sopenharmony_ci soft_copy_op(q, ptr, {}, obj_pitch, 379bf215546Sopenharmony_ci &mem, obj_origin, obj_pitch, 380bf215546Sopenharmony_ci region)); 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci if (blocking) 383bf215546Sopenharmony_ci hev().wait_signalled(); 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_ci ret_object(rd_ev, hev); 386bf215546Sopenharmony_ci return CL_SUCCESS; 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci} catch (error &e) { 389bf215546Sopenharmony_ci return e.get(); 390bf215546Sopenharmony_ci} 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ciCLOVER_API cl_int 393bf215546Sopenharmony_ciclEnqueueWriteBuffer(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, 394bf215546Sopenharmony_ci size_t offset, size_t size, const void *ptr, 395bf215546Sopenharmony_ci cl_uint num_deps, const cl_event *d_deps, 396bf215546Sopenharmony_ci cl_event *rd_ev) try { 397bf215546Sopenharmony_ci auto &q = obj(d_q); 398bf215546Sopenharmony_ci auto &mem = obj<buffer>(d_mem); 399bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 400bf215546Sopenharmony_ci vector_t region = { size, 1, 1 }; 401bf215546Sopenharmony_ci vector_t obj_origin = { offset }; 402bf215546Sopenharmony_ci auto obj_pitch = pitch(region, {{ 1 }}); 403bf215546Sopenharmony_ci 404bf215546Sopenharmony_ci validate_common(q, deps); 405bf215546Sopenharmony_ci validate_object(q, mem, obj_origin, obj_pitch, region); 406bf215546Sopenharmony_ci validate_object(q, ptr, {}, obj_pitch, region); 407bf215546Sopenharmony_ci validate_object_access(mem, CL_MEM_HOST_WRITE_ONLY); 408bf215546Sopenharmony_ci 409bf215546Sopenharmony_ci auto hev = create<hard_event>( 410bf215546Sopenharmony_ci q, CL_COMMAND_WRITE_BUFFER, deps, 411bf215546Sopenharmony_ci soft_copy_op(q, &mem, obj_origin, obj_pitch, 412bf215546Sopenharmony_ci ptr, {}, obj_pitch, 413bf215546Sopenharmony_ci region)); 414bf215546Sopenharmony_ci 415bf215546Sopenharmony_ci if (blocking) 416bf215546Sopenharmony_ci hev().wait_signalled(); 417bf215546Sopenharmony_ci 418bf215546Sopenharmony_ci ret_object(rd_ev, hev); 419bf215546Sopenharmony_ci return CL_SUCCESS; 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_ci} catch (error &e) { 422bf215546Sopenharmony_ci return e.get(); 423bf215546Sopenharmony_ci} 424bf215546Sopenharmony_ci 425bf215546Sopenharmony_ciCLOVER_API cl_int 426bf215546Sopenharmony_ciclEnqueueReadBufferRect(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, 427bf215546Sopenharmony_ci const size_t *p_obj_origin, 428bf215546Sopenharmony_ci const size_t *p_host_origin, 429bf215546Sopenharmony_ci const size_t *p_region, 430bf215546Sopenharmony_ci size_t obj_row_pitch, size_t obj_slice_pitch, 431bf215546Sopenharmony_ci size_t host_row_pitch, size_t host_slice_pitch, 432bf215546Sopenharmony_ci void *ptr, 433bf215546Sopenharmony_ci cl_uint num_deps, const cl_event *d_deps, 434bf215546Sopenharmony_ci cl_event *rd_ev) try { 435bf215546Sopenharmony_ci auto &q = obj(d_q); 436bf215546Sopenharmony_ci auto &mem = obj<buffer>(d_mem); 437bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 438bf215546Sopenharmony_ci auto region = vector(p_region); 439bf215546Sopenharmony_ci auto obj_origin = vector(p_obj_origin); 440bf215546Sopenharmony_ci auto obj_pitch = pitch(region, {{ 1, obj_row_pitch, obj_slice_pitch }}); 441bf215546Sopenharmony_ci auto host_origin = vector(p_host_origin); 442bf215546Sopenharmony_ci auto host_pitch = pitch(region, {{ 1, host_row_pitch, host_slice_pitch }}); 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ci validate_common(q, deps); 445bf215546Sopenharmony_ci validate_object(q, ptr, host_origin, host_pitch, region); 446bf215546Sopenharmony_ci validate_object(q, mem, obj_origin, obj_pitch, region); 447bf215546Sopenharmony_ci validate_object_access(mem, CL_MEM_HOST_READ_ONLY); 448bf215546Sopenharmony_ci 449bf215546Sopenharmony_ci auto hev = create<hard_event>( 450bf215546Sopenharmony_ci q, CL_COMMAND_READ_BUFFER_RECT, deps, 451bf215546Sopenharmony_ci soft_copy_op(q, ptr, host_origin, host_pitch, 452bf215546Sopenharmony_ci &mem, obj_origin, obj_pitch, 453bf215546Sopenharmony_ci region)); 454bf215546Sopenharmony_ci 455bf215546Sopenharmony_ci if (blocking) 456bf215546Sopenharmony_ci hev().wait_signalled(); 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci ret_object(rd_ev, hev); 459bf215546Sopenharmony_ci return CL_SUCCESS; 460bf215546Sopenharmony_ci 461bf215546Sopenharmony_ci} catch (error &e) { 462bf215546Sopenharmony_ci return e.get(); 463bf215546Sopenharmony_ci} 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ciCLOVER_API cl_int 466bf215546Sopenharmony_ciclEnqueueWriteBufferRect(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, 467bf215546Sopenharmony_ci const size_t *p_obj_origin, 468bf215546Sopenharmony_ci const size_t *p_host_origin, 469bf215546Sopenharmony_ci const size_t *p_region, 470bf215546Sopenharmony_ci size_t obj_row_pitch, size_t obj_slice_pitch, 471bf215546Sopenharmony_ci size_t host_row_pitch, size_t host_slice_pitch, 472bf215546Sopenharmony_ci const void *ptr, 473bf215546Sopenharmony_ci cl_uint num_deps, const cl_event *d_deps, 474bf215546Sopenharmony_ci cl_event *rd_ev) try { 475bf215546Sopenharmony_ci auto &q = obj(d_q); 476bf215546Sopenharmony_ci auto &mem = obj<buffer>(d_mem); 477bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 478bf215546Sopenharmony_ci auto region = vector(p_region); 479bf215546Sopenharmony_ci auto obj_origin = vector(p_obj_origin); 480bf215546Sopenharmony_ci auto obj_pitch = pitch(region, {{ 1, obj_row_pitch, obj_slice_pitch }}); 481bf215546Sopenharmony_ci auto host_origin = vector(p_host_origin); 482bf215546Sopenharmony_ci auto host_pitch = pitch(region, {{ 1, host_row_pitch, host_slice_pitch }}); 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci validate_common(q, deps); 485bf215546Sopenharmony_ci validate_object(q, mem, obj_origin, obj_pitch, region); 486bf215546Sopenharmony_ci validate_object(q, ptr, host_origin, host_pitch, region); 487bf215546Sopenharmony_ci validate_object_access(mem, CL_MEM_HOST_WRITE_ONLY); 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci auto hev = create<hard_event>( 490bf215546Sopenharmony_ci q, CL_COMMAND_WRITE_BUFFER_RECT, deps, 491bf215546Sopenharmony_ci soft_copy_op(q, &mem, obj_origin, obj_pitch, 492bf215546Sopenharmony_ci ptr, host_origin, host_pitch, 493bf215546Sopenharmony_ci region)); 494bf215546Sopenharmony_ci 495bf215546Sopenharmony_ci if (blocking) 496bf215546Sopenharmony_ci hev().wait_signalled(); 497bf215546Sopenharmony_ci 498bf215546Sopenharmony_ci ret_object(rd_ev, hev); 499bf215546Sopenharmony_ci return CL_SUCCESS; 500bf215546Sopenharmony_ci 501bf215546Sopenharmony_ci} catch (error &e) { 502bf215546Sopenharmony_ci return e.get(); 503bf215546Sopenharmony_ci} 504bf215546Sopenharmony_ci 505bf215546Sopenharmony_ciCLOVER_API cl_int 506bf215546Sopenharmony_ciclEnqueueFillBuffer(cl_command_queue d_queue, cl_mem d_mem, 507bf215546Sopenharmony_ci const void *pattern, size_t pattern_size, 508bf215546Sopenharmony_ci size_t offset, size_t size, 509bf215546Sopenharmony_ci cl_uint num_deps, const cl_event *d_deps, 510bf215546Sopenharmony_ci cl_event *rd_ev) try { 511bf215546Sopenharmony_ci auto &q = obj(d_queue); 512bf215546Sopenharmony_ci auto &mem = obj<buffer>(d_mem); 513bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 514bf215546Sopenharmony_ci vector_t region = { size, 1, 1 }; 515bf215546Sopenharmony_ci vector_t origin = { offset }; 516bf215546Sopenharmony_ci auto dst_pitch = pitch(region, {{ 1 }}); 517bf215546Sopenharmony_ci 518bf215546Sopenharmony_ci validate_common(q, deps); 519bf215546Sopenharmony_ci validate_object(q, mem, origin, dst_pitch, region); 520bf215546Sopenharmony_ci 521bf215546Sopenharmony_ci if (!pattern) 522bf215546Sopenharmony_ci return CL_INVALID_VALUE; 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_ci if (!util_is_power_of_two_nonzero(pattern_size) || 525bf215546Sopenharmony_ci pattern_size > 128 || size % pattern_size 526bf215546Sopenharmony_ci || offset % pattern_size) { 527bf215546Sopenharmony_ci return CL_INVALID_VALUE; 528bf215546Sopenharmony_ci } 529bf215546Sopenharmony_ci 530bf215546Sopenharmony_ci auto sub = dynamic_cast<sub_buffer *>(&mem); 531bf215546Sopenharmony_ci if (sub && sub->offset() % q.device().mem_base_addr_align()) { 532bf215546Sopenharmony_ci return CL_MISALIGNED_SUB_BUFFER_OFFSET; 533bf215546Sopenharmony_ci } 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci std::string data = std::string((char *)pattern, pattern_size); 536bf215546Sopenharmony_ci auto hev = create<hard_event>( 537bf215546Sopenharmony_ci q, CL_COMMAND_FILL_BUFFER, deps, 538bf215546Sopenharmony_ci [=, &q, &mem](event &) { 539bf215546Sopenharmony_ci mem.resource_in(q).clear(q, origin, region, data); 540bf215546Sopenharmony_ci }); 541bf215546Sopenharmony_ci 542bf215546Sopenharmony_ci ret_object(rd_ev, hev); 543bf215546Sopenharmony_ci return CL_SUCCESS; 544bf215546Sopenharmony_ci 545bf215546Sopenharmony_ci} catch (error &e) { 546bf215546Sopenharmony_ci return e.get(); 547bf215546Sopenharmony_ci} 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ciCLOVER_API cl_int 550bf215546Sopenharmony_ciclEnqueueCopyBuffer(cl_command_queue d_q, cl_mem d_src_mem, cl_mem d_dst_mem, 551bf215546Sopenharmony_ci size_t src_offset, size_t dst_offset, size_t size, 552bf215546Sopenharmony_ci cl_uint num_deps, const cl_event *d_deps, 553bf215546Sopenharmony_ci cl_event *rd_ev) try { 554bf215546Sopenharmony_ci auto &q = obj(d_q); 555bf215546Sopenharmony_ci auto &src_mem = obj<buffer>(d_src_mem); 556bf215546Sopenharmony_ci auto &dst_mem = obj<buffer>(d_dst_mem); 557bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 558bf215546Sopenharmony_ci vector_t region = { size, 1, 1 }; 559bf215546Sopenharmony_ci vector_t dst_origin = { dst_offset }; 560bf215546Sopenharmony_ci auto dst_pitch = pitch(region, {{ 1 }}); 561bf215546Sopenharmony_ci vector_t src_origin = { src_offset }; 562bf215546Sopenharmony_ci auto src_pitch = pitch(region, {{ 1 }}); 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_ci validate_common(q, deps); 565bf215546Sopenharmony_ci validate_object(q, dst_mem, dst_origin, dst_pitch, region); 566bf215546Sopenharmony_ci validate_object(q, src_mem, src_origin, src_pitch, region); 567bf215546Sopenharmony_ci validate_copy(q, dst_mem, dst_origin, dst_pitch, 568bf215546Sopenharmony_ci src_mem, src_origin, src_pitch, region); 569bf215546Sopenharmony_ci 570bf215546Sopenharmony_ci auto hev = create<hard_event>( 571bf215546Sopenharmony_ci q, CL_COMMAND_COPY_BUFFER, deps, 572bf215546Sopenharmony_ci hard_copy_op(q, &dst_mem, dst_origin, 573bf215546Sopenharmony_ci &src_mem, src_origin, region)); 574bf215546Sopenharmony_ci 575bf215546Sopenharmony_ci ret_object(rd_ev, hev); 576bf215546Sopenharmony_ci return CL_SUCCESS; 577bf215546Sopenharmony_ci 578bf215546Sopenharmony_ci} catch (error &e) { 579bf215546Sopenharmony_ci return e.get(); 580bf215546Sopenharmony_ci} 581bf215546Sopenharmony_ci 582bf215546Sopenharmony_ciCLOVER_API cl_int 583bf215546Sopenharmony_ciclEnqueueCopyBufferRect(cl_command_queue d_q, cl_mem d_src_mem, 584bf215546Sopenharmony_ci cl_mem d_dst_mem, 585bf215546Sopenharmony_ci const size_t *p_src_origin, const size_t *p_dst_origin, 586bf215546Sopenharmony_ci const size_t *p_region, 587bf215546Sopenharmony_ci size_t src_row_pitch, size_t src_slice_pitch, 588bf215546Sopenharmony_ci size_t dst_row_pitch, size_t dst_slice_pitch, 589bf215546Sopenharmony_ci cl_uint num_deps, const cl_event *d_deps, 590bf215546Sopenharmony_ci cl_event *rd_ev) try { 591bf215546Sopenharmony_ci auto &q = obj(d_q); 592bf215546Sopenharmony_ci auto &src_mem = obj<buffer>(d_src_mem); 593bf215546Sopenharmony_ci auto &dst_mem = obj<buffer>(d_dst_mem); 594bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 595bf215546Sopenharmony_ci auto region = vector(p_region); 596bf215546Sopenharmony_ci auto dst_origin = vector(p_dst_origin); 597bf215546Sopenharmony_ci auto dst_pitch = pitch(region, {{ 1, dst_row_pitch, dst_slice_pitch }}); 598bf215546Sopenharmony_ci auto src_origin = vector(p_src_origin); 599bf215546Sopenharmony_ci auto src_pitch = pitch(region, {{ 1, src_row_pitch, src_slice_pitch }}); 600bf215546Sopenharmony_ci 601bf215546Sopenharmony_ci validate_common(q, deps); 602bf215546Sopenharmony_ci validate_object(q, dst_mem, dst_origin, dst_pitch, region); 603bf215546Sopenharmony_ci validate_object(q, src_mem, src_origin, src_pitch, region); 604bf215546Sopenharmony_ci validate_copy(q, dst_mem, dst_origin, dst_pitch, 605bf215546Sopenharmony_ci src_mem, src_origin, src_pitch, region); 606bf215546Sopenharmony_ci 607bf215546Sopenharmony_ci auto hev = create<hard_event>( 608bf215546Sopenharmony_ci q, CL_COMMAND_COPY_BUFFER_RECT, deps, 609bf215546Sopenharmony_ci soft_copy_op(q, &dst_mem, dst_origin, dst_pitch, 610bf215546Sopenharmony_ci &src_mem, src_origin, src_pitch, 611bf215546Sopenharmony_ci region)); 612bf215546Sopenharmony_ci 613bf215546Sopenharmony_ci ret_object(rd_ev, hev); 614bf215546Sopenharmony_ci return CL_SUCCESS; 615bf215546Sopenharmony_ci 616bf215546Sopenharmony_ci} catch (error &e) { 617bf215546Sopenharmony_ci return e.get(); 618bf215546Sopenharmony_ci} 619bf215546Sopenharmony_ci 620bf215546Sopenharmony_ciCLOVER_API cl_int 621bf215546Sopenharmony_ciclEnqueueReadImage(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, 622bf215546Sopenharmony_ci const size_t *p_origin, const size_t *p_region, 623bf215546Sopenharmony_ci size_t row_pitch, size_t slice_pitch, void *ptr, 624bf215546Sopenharmony_ci cl_uint num_deps, const cl_event *d_deps, 625bf215546Sopenharmony_ci cl_event *rd_ev) try { 626bf215546Sopenharmony_ci auto &q = obj(d_q); 627bf215546Sopenharmony_ci auto &img = obj<image>(d_mem); 628bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 629bf215546Sopenharmony_ci auto region = vector(p_region); 630bf215546Sopenharmony_ci auto dst_pitch = pitch(region, {{ img.pixel_size(), 631bf215546Sopenharmony_ci row_pitch, slice_pitch }}); 632bf215546Sopenharmony_ci auto src_origin = vector(p_origin); 633bf215546Sopenharmony_ci auto src_pitch = pitch(region, {{ img.pixel_size(), 634bf215546Sopenharmony_ci img.row_pitch(), img.slice_pitch() }}); 635bf215546Sopenharmony_ci 636bf215546Sopenharmony_ci validate_common(q, deps); 637bf215546Sopenharmony_ci validate_object(q, ptr, {}, dst_pitch, region); 638bf215546Sopenharmony_ci validate_object(q, img, src_origin, region); 639bf215546Sopenharmony_ci validate_object_access(img, CL_MEM_HOST_READ_ONLY); 640bf215546Sopenharmony_ci 641bf215546Sopenharmony_ci auto hev = create<hard_event>( 642bf215546Sopenharmony_ci q, CL_COMMAND_READ_IMAGE, deps, 643bf215546Sopenharmony_ci soft_copy_op(q, ptr, {}, dst_pitch, 644bf215546Sopenharmony_ci &img, src_origin, src_pitch, 645bf215546Sopenharmony_ci region)); 646bf215546Sopenharmony_ci 647bf215546Sopenharmony_ci if (blocking) 648bf215546Sopenharmony_ci hev().wait_signalled(); 649bf215546Sopenharmony_ci 650bf215546Sopenharmony_ci ret_object(rd_ev, hev); 651bf215546Sopenharmony_ci return CL_SUCCESS; 652bf215546Sopenharmony_ci 653bf215546Sopenharmony_ci} catch (error &e) { 654bf215546Sopenharmony_ci return e.get(); 655bf215546Sopenharmony_ci} 656bf215546Sopenharmony_ci 657bf215546Sopenharmony_ciCLOVER_API cl_int 658bf215546Sopenharmony_ciclEnqueueWriteImage(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, 659bf215546Sopenharmony_ci const size_t *p_origin, const size_t *p_region, 660bf215546Sopenharmony_ci size_t row_pitch, size_t slice_pitch, const void *ptr, 661bf215546Sopenharmony_ci cl_uint num_deps, const cl_event *d_deps, 662bf215546Sopenharmony_ci cl_event *rd_ev) try { 663bf215546Sopenharmony_ci auto &q = obj(d_q); 664bf215546Sopenharmony_ci auto &img = obj<image>(d_mem); 665bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 666bf215546Sopenharmony_ci auto region = vector(p_region); 667bf215546Sopenharmony_ci auto dst_origin = vector(p_origin); 668bf215546Sopenharmony_ci auto dst_pitch = pitch(region, {{ img.pixel_size(), 669bf215546Sopenharmony_ci img.row_pitch(), img.slice_pitch() }}); 670bf215546Sopenharmony_ci auto src_pitch = pitch(region, {{ img.pixel_size(), 671bf215546Sopenharmony_ci row_pitch, slice_pitch }}); 672bf215546Sopenharmony_ci 673bf215546Sopenharmony_ci validate_common(q, deps); 674bf215546Sopenharmony_ci validate_object(q, img, dst_origin, region); 675bf215546Sopenharmony_ci validate_object(q, ptr, {}, src_pitch, region); 676bf215546Sopenharmony_ci validate_object_access(img, CL_MEM_HOST_WRITE_ONLY); 677bf215546Sopenharmony_ci 678bf215546Sopenharmony_ci auto hev = create<hard_event>( 679bf215546Sopenharmony_ci q, CL_COMMAND_WRITE_IMAGE, deps, 680bf215546Sopenharmony_ci soft_copy_op(q, &img, dst_origin, dst_pitch, 681bf215546Sopenharmony_ci ptr, {}, src_pitch, 682bf215546Sopenharmony_ci region)); 683bf215546Sopenharmony_ci 684bf215546Sopenharmony_ci if (blocking) 685bf215546Sopenharmony_ci hev().wait_signalled(); 686bf215546Sopenharmony_ci 687bf215546Sopenharmony_ci ret_object(rd_ev, hev); 688bf215546Sopenharmony_ci return CL_SUCCESS; 689bf215546Sopenharmony_ci 690bf215546Sopenharmony_ci} catch (error &e) { 691bf215546Sopenharmony_ci return e.get(); 692bf215546Sopenharmony_ci} 693bf215546Sopenharmony_ci 694bf215546Sopenharmony_ciCLOVER_API cl_int 695bf215546Sopenharmony_ciclEnqueueFillImage(cl_command_queue d_queue, cl_mem d_mem, 696bf215546Sopenharmony_ci const void *fill_color, 697bf215546Sopenharmony_ci const size_t *p_origin, const size_t *p_region, 698bf215546Sopenharmony_ci cl_uint num_deps, const cl_event *d_deps, 699bf215546Sopenharmony_ci cl_event *rd_ev) try { 700bf215546Sopenharmony_ci auto &q = obj(d_queue); 701bf215546Sopenharmony_ci auto &img = obj<image>(d_mem); 702bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 703bf215546Sopenharmony_ci auto origin = vector(p_origin); 704bf215546Sopenharmony_ci auto region = vector(p_region); 705bf215546Sopenharmony_ci 706bf215546Sopenharmony_ci validate_common(q, deps); 707bf215546Sopenharmony_ci validate_object(q, img, origin, region); 708bf215546Sopenharmony_ci 709bf215546Sopenharmony_ci if (!fill_color) 710bf215546Sopenharmony_ci return CL_INVALID_VALUE; 711bf215546Sopenharmony_ci 712bf215546Sopenharmony_ci std::string data = std::string((char *)fill_color, sizeof(cl_uint4)); 713bf215546Sopenharmony_ci auto hev = create<hard_event>( 714bf215546Sopenharmony_ci q, CL_COMMAND_FILL_IMAGE, deps, 715bf215546Sopenharmony_ci [=, &q, &img](event &) { 716bf215546Sopenharmony_ci img.resource_in(q).clear(q, origin, region, data); 717bf215546Sopenharmony_ci }); 718bf215546Sopenharmony_ci 719bf215546Sopenharmony_ci ret_object(rd_ev, hev); 720bf215546Sopenharmony_ci return CL_SUCCESS; 721bf215546Sopenharmony_ci 722bf215546Sopenharmony_ci} catch (error &e) { 723bf215546Sopenharmony_ci return e.get(); 724bf215546Sopenharmony_ci} 725bf215546Sopenharmony_ci 726bf215546Sopenharmony_ciCLOVER_API cl_int 727bf215546Sopenharmony_ciclEnqueueCopyImage(cl_command_queue d_q, cl_mem d_src_mem, cl_mem d_dst_mem, 728bf215546Sopenharmony_ci const size_t *p_src_origin, const size_t *p_dst_origin, 729bf215546Sopenharmony_ci const size_t *p_region, 730bf215546Sopenharmony_ci cl_uint num_deps, const cl_event *d_deps, 731bf215546Sopenharmony_ci cl_event *rd_ev) try { 732bf215546Sopenharmony_ci auto &q = obj(d_q); 733bf215546Sopenharmony_ci auto &src_img = obj<image>(d_src_mem); 734bf215546Sopenharmony_ci auto &dst_img = obj<image>(d_dst_mem); 735bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 736bf215546Sopenharmony_ci auto region = vector(p_region); 737bf215546Sopenharmony_ci auto dst_origin = vector(p_dst_origin); 738bf215546Sopenharmony_ci auto src_origin = vector(p_src_origin); 739bf215546Sopenharmony_ci 740bf215546Sopenharmony_ci validate_common(q, deps); 741bf215546Sopenharmony_ci validate_object(q, dst_img, dst_origin, region); 742bf215546Sopenharmony_ci validate_object(q, src_img, src_origin, region); 743bf215546Sopenharmony_ci validate_copy(q, dst_img, dst_origin, src_img, src_origin, region); 744bf215546Sopenharmony_ci 745bf215546Sopenharmony_ci auto hev = create<hard_event>( 746bf215546Sopenharmony_ci q, CL_COMMAND_COPY_IMAGE, deps, 747bf215546Sopenharmony_ci hard_copy_op(q, &dst_img, dst_origin, 748bf215546Sopenharmony_ci &src_img, src_origin, 749bf215546Sopenharmony_ci region)); 750bf215546Sopenharmony_ci 751bf215546Sopenharmony_ci ret_object(rd_ev, hev); 752bf215546Sopenharmony_ci return CL_SUCCESS; 753bf215546Sopenharmony_ci 754bf215546Sopenharmony_ci} catch (error &e) { 755bf215546Sopenharmony_ci return e.get(); 756bf215546Sopenharmony_ci} 757bf215546Sopenharmony_ci 758bf215546Sopenharmony_ciCLOVER_API cl_int 759bf215546Sopenharmony_ciclEnqueueCopyImageToBuffer(cl_command_queue d_q, 760bf215546Sopenharmony_ci cl_mem d_src_mem, cl_mem d_dst_mem, 761bf215546Sopenharmony_ci const size_t *p_src_origin, const size_t *p_region, 762bf215546Sopenharmony_ci size_t dst_offset, 763bf215546Sopenharmony_ci cl_uint num_deps, const cl_event *d_deps, 764bf215546Sopenharmony_ci cl_event *rd_ev) try { 765bf215546Sopenharmony_ci auto &q = obj(d_q); 766bf215546Sopenharmony_ci auto &src_img = obj<image>(d_src_mem); 767bf215546Sopenharmony_ci auto &dst_mem = obj<buffer>(d_dst_mem); 768bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 769bf215546Sopenharmony_ci auto region = vector(p_region); 770bf215546Sopenharmony_ci vector_t dst_origin = { dst_offset }; 771bf215546Sopenharmony_ci auto dst_pitch = pitch(region, {{ src_img.pixel_size() }}); 772bf215546Sopenharmony_ci auto src_origin = vector(p_src_origin); 773bf215546Sopenharmony_ci auto src_pitch = pitch(region, {{ src_img.pixel_size(), 774bf215546Sopenharmony_ci src_img.row_pitch(), 775bf215546Sopenharmony_ci src_img.slice_pitch() }}); 776bf215546Sopenharmony_ci 777bf215546Sopenharmony_ci validate_common(q, deps); 778bf215546Sopenharmony_ci validate_object(q, dst_mem, dst_origin, dst_pitch, region); 779bf215546Sopenharmony_ci validate_object(q, src_img, src_origin, region); 780bf215546Sopenharmony_ci 781bf215546Sopenharmony_ci auto hev = create<hard_event>( 782bf215546Sopenharmony_ci q, CL_COMMAND_COPY_IMAGE_TO_BUFFER, deps, 783bf215546Sopenharmony_ci soft_copy_op(q, &dst_mem, dst_origin, dst_pitch, 784bf215546Sopenharmony_ci &src_img, src_origin, src_pitch, 785bf215546Sopenharmony_ci region)); 786bf215546Sopenharmony_ci 787bf215546Sopenharmony_ci ret_object(rd_ev, hev); 788bf215546Sopenharmony_ci return CL_SUCCESS; 789bf215546Sopenharmony_ci 790bf215546Sopenharmony_ci} catch (error &e) { 791bf215546Sopenharmony_ci return e.get(); 792bf215546Sopenharmony_ci} 793bf215546Sopenharmony_ci 794bf215546Sopenharmony_ciCLOVER_API cl_int 795bf215546Sopenharmony_ciclEnqueueCopyBufferToImage(cl_command_queue d_q, 796bf215546Sopenharmony_ci cl_mem d_src_mem, cl_mem d_dst_mem, 797bf215546Sopenharmony_ci size_t src_offset, 798bf215546Sopenharmony_ci const size_t *p_dst_origin, const size_t *p_region, 799bf215546Sopenharmony_ci cl_uint num_deps, const cl_event *d_deps, 800bf215546Sopenharmony_ci cl_event *rd_ev) try { 801bf215546Sopenharmony_ci auto &q = obj(d_q); 802bf215546Sopenharmony_ci auto &src_mem = obj<buffer>(d_src_mem); 803bf215546Sopenharmony_ci auto &dst_img = obj<image>(d_dst_mem); 804bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 805bf215546Sopenharmony_ci auto region = vector(p_region); 806bf215546Sopenharmony_ci auto dst_origin = vector(p_dst_origin); 807bf215546Sopenharmony_ci auto dst_pitch = pitch(region, {{ dst_img.pixel_size(), 808bf215546Sopenharmony_ci dst_img.row_pitch(), 809bf215546Sopenharmony_ci dst_img.slice_pitch() }}); 810bf215546Sopenharmony_ci vector_t src_origin = { src_offset }; 811bf215546Sopenharmony_ci auto src_pitch = pitch(region, {{ dst_img.pixel_size() }}); 812bf215546Sopenharmony_ci 813bf215546Sopenharmony_ci validate_common(q, deps); 814bf215546Sopenharmony_ci validate_object(q, dst_img, dst_origin, region); 815bf215546Sopenharmony_ci validate_object(q, src_mem, src_origin, src_pitch, region); 816bf215546Sopenharmony_ci 817bf215546Sopenharmony_ci auto hev = create<hard_event>( 818bf215546Sopenharmony_ci q, CL_COMMAND_COPY_BUFFER_TO_IMAGE, deps, 819bf215546Sopenharmony_ci soft_copy_op(q, &dst_img, dst_origin, dst_pitch, 820bf215546Sopenharmony_ci &src_mem, src_origin, src_pitch, 821bf215546Sopenharmony_ci region)); 822bf215546Sopenharmony_ci 823bf215546Sopenharmony_ci ret_object(rd_ev, hev); 824bf215546Sopenharmony_ci return CL_SUCCESS; 825bf215546Sopenharmony_ci 826bf215546Sopenharmony_ci} catch (error &e) { 827bf215546Sopenharmony_ci return e.get(); 828bf215546Sopenharmony_ci} 829bf215546Sopenharmony_ci 830bf215546Sopenharmony_ciCLOVER_API void * 831bf215546Sopenharmony_ciclEnqueueMapBuffer(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, 832bf215546Sopenharmony_ci cl_map_flags flags, size_t offset, size_t size, 833bf215546Sopenharmony_ci cl_uint num_deps, const cl_event *d_deps, 834bf215546Sopenharmony_ci cl_event *rd_ev, cl_int *r_errcode) try { 835bf215546Sopenharmony_ci auto &q = obj(d_q); 836bf215546Sopenharmony_ci auto &mem = obj<buffer>(d_mem); 837bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 838bf215546Sopenharmony_ci vector_t region = { size, 1, 1 }; 839bf215546Sopenharmony_ci vector_t obj_origin = { offset }; 840bf215546Sopenharmony_ci auto obj_pitch = pitch(region, {{ 1 }}); 841bf215546Sopenharmony_ci 842bf215546Sopenharmony_ci validate_common(q, deps); 843bf215546Sopenharmony_ci validate_object(q, mem, obj_origin, obj_pitch, region); 844bf215546Sopenharmony_ci validate_map_flags(mem, flags); 845bf215546Sopenharmony_ci 846bf215546Sopenharmony_ci auto *map = mem.resource_in(q).add_map(q, flags, blocking, obj_origin, region); 847bf215546Sopenharmony_ci 848bf215546Sopenharmony_ci auto hev = create<hard_event>(q, CL_COMMAND_MAP_BUFFER, deps); 849bf215546Sopenharmony_ci if (blocking) 850bf215546Sopenharmony_ci hev().wait_signalled(); 851bf215546Sopenharmony_ci 852bf215546Sopenharmony_ci ret_object(rd_ev, hev); 853bf215546Sopenharmony_ci ret_error(r_errcode, CL_SUCCESS); 854bf215546Sopenharmony_ci return *map; 855bf215546Sopenharmony_ci 856bf215546Sopenharmony_ci} catch (error &e) { 857bf215546Sopenharmony_ci ret_error(r_errcode, e); 858bf215546Sopenharmony_ci return NULL; 859bf215546Sopenharmony_ci} 860bf215546Sopenharmony_ci 861bf215546Sopenharmony_ciCLOVER_API void * 862bf215546Sopenharmony_ciclEnqueueMapImage(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, 863bf215546Sopenharmony_ci cl_map_flags flags, 864bf215546Sopenharmony_ci const size_t *p_origin, const size_t *p_region, 865bf215546Sopenharmony_ci size_t *row_pitch, size_t *slice_pitch, 866bf215546Sopenharmony_ci cl_uint num_deps, const cl_event *d_deps, 867bf215546Sopenharmony_ci cl_event *rd_ev, cl_int *r_errcode) try { 868bf215546Sopenharmony_ci auto &q = obj(d_q); 869bf215546Sopenharmony_ci auto &img = obj<image>(d_mem); 870bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 871bf215546Sopenharmony_ci auto region = vector(p_region); 872bf215546Sopenharmony_ci auto origin = vector(p_origin); 873bf215546Sopenharmony_ci 874bf215546Sopenharmony_ci validate_common(q, deps); 875bf215546Sopenharmony_ci validate_object(q, img, origin, region); 876bf215546Sopenharmony_ci validate_map_flags(img, flags); 877bf215546Sopenharmony_ci 878bf215546Sopenharmony_ci if (!row_pitch) 879bf215546Sopenharmony_ci throw error(CL_INVALID_VALUE); 880bf215546Sopenharmony_ci 881bf215546Sopenharmony_ci if ((img.slice_pitch() || img.array_size()) && !slice_pitch) 882bf215546Sopenharmony_ci throw error(CL_INVALID_VALUE); 883bf215546Sopenharmony_ci 884bf215546Sopenharmony_ci auto *map = img.resource_in(q).add_map(q, flags, blocking, origin, region); 885bf215546Sopenharmony_ci *row_pitch = map->pitch()[1]; 886bf215546Sopenharmony_ci if (slice_pitch) 887bf215546Sopenharmony_ci *slice_pitch = map->pitch()[2]; 888bf215546Sopenharmony_ci 889bf215546Sopenharmony_ci auto hev = create<hard_event>(q, CL_COMMAND_MAP_IMAGE, deps); 890bf215546Sopenharmony_ci if (blocking) 891bf215546Sopenharmony_ci hev().wait_signalled(); 892bf215546Sopenharmony_ci 893bf215546Sopenharmony_ci ret_object(rd_ev, hev); 894bf215546Sopenharmony_ci ret_error(r_errcode, CL_SUCCESS); 895bf215546Sopenharmony_ci return *map; 896bf215546Sopenharmony_ci 897bf215546Sopenharmony_ci} catch (error &e) { 898bf215546Sopenharmony_ci ret_error(r_errcode, e); 899bf215546Sopenharmony_ci return NULL; 900bf215546Sopenharmony_ci} 901bf215546Sopenharmony_ci 902bf215546Sopenharmony_ciCLOVER_API cl_int 903bf215546Sopenharmony_ciclEnqueueUnmapMemObject(cl_command_queue d_q, cl_mem d_mem, void *ptr, 904bf215546Sopenharmony_ci cl_uint num_deps, const cl_event *d_deps, 905bf215546Sopenharmony_ci cl_event *rd_ev) try { 906bf215546Sopenharmony_ci auto &q = obj(d_q); 907bf215546Sopenharmony_ci auto &mem = obj(d_mem); 908bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 909bf215546Sopenharmony_ci 910bf215546Sopenharmony_ci validate_common(q, deps); 911bf215546Sopenharmony_ci 912bf215546Sopenharmony_ci auto hev = create<hard_event>( 913bf215546Sopenharmony_ci q, CL_COMMAND_UNMAP_MEM_OBJECT, deps, 914bf215546Sopenharmony_ci [=, &q, &mem](event &) { 915bf215546Sopenharmony_ci mem.resource_in(q).del_map(ptr); 916bf215546Sopenharmony_ci }); 917bf215546Sopenharmony_ci 918bf215546Sopenharmony_ci ret_object(rd_ev, hev); 919bf215546Sopenharmony_ci return CL_SUCCESS; 920bf215546Sopenharmony_ci 921bf215546Sopenharmony_ci} catch (error &e) { 922bf215546Sopenharmony_ci return e.get(); 923bf215546Sopenharmony_ci} 924bf215546Sopenharmony_ci 925bf215546Sopenharmony_ciCLOVER_API cl_int 926bf215546Sopenharmony_ciclEnqueueMigrateMemObjects(cl_command_queue d_q, 927bf215546Sopenharmony_ci cl_uint num_mems, 928bf215546Sopenharmony_ci const cl_mem *d_mems, 929bf215546Sopenharmony_ci cl_mem_migration_flags flags, 930bf215546Sopenharmony_ci cl_uint num_deps, 931bf215546Sopenharmony_ci const cl_event *d_deps, 932bf215546Sopenharmony_ci cl_event *rd_ev) try { 933bf215546Sopenharmony_ci auto &q = obj(d_q); 934bf215546Sopenharmony_ci auto mems = objs<memory_obj>(d_mems, num_mems); 935bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 936bf215546Sopenharmony_ci 937bf215546Sopenharmony_ci validate_common(q, deps); 938bf215546Sopenharmony_ci validate_mem_migration_flags(flags); 939bf215546Sopenharmony_ci 940bf215546Sopenharmony_ci if (any_of([&](const memory_obj &m) { 941bf215546Sopenharmony_ci return m.context() != q.context(); 942bf215546Sopenharmony_ci }, mems)) 943bf215546Sopenharmony_ci throw error(CL_INVALID_CONTEXT); 944bf215546Sopenharmony_ci 945bf215546Sopenharmony_ci auto hev = create<hard_event>( 946bf215546Sopenharmony_ci q, CL_COMMAND_MIGRATE_MEM_OBJECTS, deps, 947bf215546Sopenharmony_ci [=, &q](event &) { 948bf215546Sopenharmony_ci for (auto &mem: mems) { 949bf215546Sopenharmony_ci if (flags & CL_MIGRATE_MEM_OBJECT_HOST) { 950bf215546Sopenharmony_ci if ((flags & CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED)) 951bf215546Sopenharmony_ci mem.resource_out(q); 952bf215546Sopenharmony_ci 953bf215546Sopenharmony_ci // For flags == CL_MIGRATE_MEM_OBJECT_HOST only to be 954bf215546Sopenharmony_ci // efficient we would need cl*ReadBuffer* to implement 955bf215546Sopenharmony_ci // reading from host memory. 956bf215546Sopenharmony_ci 957bf215546Sopenharmony_ci } else { 958bf215546Sopenharmony_ci if (flags & CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED) 959bf215546Sopenharmony_ci mem.resource_undef(q); 960bf215546Sopenharmony_ci else 961bf215546Sopenharmony_ci mem.resource_in(q); 962bf215546Sopenharmony_ci } 963bf215546Sopenharmony_ci } 964bf215546Sopenharmony_ci }); 965bf215546Sopenharmony_ci 966bf215546Sopenharmony_ci ret_object(rd_ev, hev); 967bf215546Sopenharmony_ci return CL_SUCCESS;; 968bf215546Sopenharmony_ci 969bf215546Sopenharmony_ci} catch (error &e) { 970bf215546Sopenharmony_ci return e.get(); 971bf215546Sopenharmony_ci} 972bf215546Sopenharmony_ci 973bf215546Sopenharmony_cicl_int 974bf215546Sopenharmony_ciclover::EnqueueSVMFree(cl_command_queue d_q, 975bf215546Sopenharmony_ci cl_uint num_svm_pointers, 976bf215546Sopenharmony_ci void *svm_pointers[], 977bf215546Sopenharmony_ci void (CL_CALLBACK *pfn_free_func) ( 978bf215546Sopenharmony_ci cl_command_queue queue, cl_uint num_svm_pointers, 979bf215546Sopenharmony_ci void *svm_pointers[], void *user_data), 980bf215546Sopenharmony_ci void *user_data, 981bf215546Sopenharmony_ci cl_uint num_events_in_wait_list, 982bf215546Sopenharmony_ci const cl_event *event_wait_list, 983bf215546Sopenharmony_ci cl_event *event, 984bf215546Sopenharmony_ci cl_int cmd) try { 985bf215546Sopenharmony_ci 986bf215546Sopenharmony_ci if (bool(num_svm_pointers) != bool(svm_pointers)) 987bf215546Sopenharmony_ci return CL_INVALID_VALUE; 988bf215546Sopenharmony_ci 989bf215546Sopenharmony_ci auto &q = obj(d_q); 990bf215546Sopenharmony_ci 991bf215546Sopenharmony_ci if (!q.device().svm_support()) 992bf215546Sopenharmony_ci return CL_INVALID_OPERATION; 993bf215546Sopenharmony_ci 994bf215546Sopenharmony_ci bool can_emulate = q.device().has_system_svm(); 995bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(event_wait_list, num_events_in_wait_list); 996bf215546Sopenharmony_ci 997bf215546Sopenharmony_ci validate_common(q, deps); 998bf215546Sopenharmony_ci 999bf215546Sopenharmony_ci std::vector<void *> svm_pointers_cpy(svm_pointers, 1000bf215546Sopenharmony_ci svm_pointers + num_svm_pointers); 1001bf215546Sopenharmony_ci if (!pfn_free_func) { 1002bf215546Sopenharmony_ci if (!can_emulate) { 1003bf215546Sopenharmony_ci CLOVER_NOT_SUPPORTED_UNTIL("2.0"); 1004bf215546Sopenharmony_ci return CL_INVALID_VALUE; 1005bf215546Sopenharmony_ci } 1006bf215546Sopenharmony_ci pfn_free_func = [](cl_command_queue d_q, cl_uint num_svm_pointers, 1007bf215546Sopenharmony_ci void *svm_pointers[], void *) { 1008bf215546Sopenharmony_ci clover::context &ctx = obj(d_q).context(); 1009bf215546Sopenharmony_ci for (void *p : range(svm_pointers, num_svm_pointers)) { 1010bf215546Sopenharmony_ci ctx.remove_svm_allocation(p); 1011bf215546Sopenharmony_ci free(p); 1012bf215546Sopenharmony_ci } 1013bf215546Sopenharmony_ci }; 1014bf215546Sopenharmony_ci } 1015bf215546Sopenharmony_ci 1016bf215546Sopenharmony_ci auto hev = create<hard_event>(q, cmd, deps, 1017bf215546Sopenharmony_ci [=](clover::event &) mutable { 1018bf215546Sopenharmony_ci pfn_free_func(d_q, num_svm_pointers, svm_pointers_cpy.data(), 1019bf215546Sopenharmony_ci user_data); 1020bf215546Sopenharmony_ci }); 1021bf215546Sopenharmony_ci 1022bf215546Sopenharmony_ci ret_object(event, hev); 1023bf215546Sopenharmony_ci return CL_SUCCESS; 1024bf215546Sopenharmony_ci 1025bf215546Sopenharmony_ci} catch (error &e) { 1026bf215546Sopenharmony_ci return e.get(); 1027bf215546Sopenharmony_ci} 1028bf215546Sopenharmony_ci 1029bf215546Sopenharmony_ciCLOVER_API cl_int 1030bf215546Sopenharmony_ciclEnqueueSVMFree(cl_command_queue d_q, 1031bf215546Sopenharmony_ci cl_uint num_svm_pointers, 1032bf215546Sopenharmony_ci void *svm_pointers[], 1033bf215546Sopenharmony_ci void (CL_CALLBACK *pfn_free_func) ( 1034bf215546Sopenharmony_ci cl_command_queue queue, cl_uint num_svm_pointers, 1035bf215546Sopenharmony_ci void *svm_pointers[], void *user_data), 1036bf215546Sopenharmony_ci void *user_data, 1037bf215546Sopenharmony_ci cl_uint num_events_in_wait_list, 1038bf215546Sopenharmony_ci const cl_event *event_wait_list, 1039bf215546Sopenharmony_ci cl_event *event) { 1040bf215546Sopenharmony_ci 1041bf215546Sopenharmony_ci return EnqueueSVMFree(d_q, num_svm_pointers, svm_pointers, 1042bf215546Sopenharmony_ci pfn_free_func, user_data, num_events_in_wait_list, 1043bf215546Sopenharmony_ci event_wait_list, event, CL_COMMAND_SVM_FREE); 1044bf215546Sopenharmony_ci} 1045bf215546Sopenharmony_ci 1046bf215546Sopenharmony_cicl_int 1047bf215546Sopenharmony_ciclover::EnqueueSVMMemcpy(cl_command_queue d_q, 1048bf215546Sopenharmony_ci cl_bool blocking_copy, 1049bf215546Sopenharmony_ci void *dst_ptr, 1050bf215546Sopenharmony_ci const void *src_ptr, 1051bf215546Sopenharmony_ci size_t size, 1052bf215546Sopenharmony_ci cl_uint num_events_in_wait_list, 1053bf215546Sopenharmony_ci const cl_event *event_wait_list, 1054bf215546Sopenharmony_ci cl_event *event, 1055bf215546Sopenharmony_ci cl_int cmd) try { 1056bf215546Sopenharmony_ci auto &q = obj(d_q); 1057bf215546Sopenharmony_ci 1058bf215546Sopenharmony_ci if (!q.device().svm_support()) 1059bf215546Sopenharmony_ci return CL_INVALID_OPERATION; 1060bf215546Sopenharmony_ci 1061bf215546Sopenharmony_ci if (dst_ptr == nullptr || src_ptr == nullptr) 1062bf215546Sopenharmony_ci return CL_INVALID_VALUE; 1063bf215546Sopenharmony_ci 1064bf215546Sopenharmony_ci if (static_cast<size_t>(abs(reinterpret_cast<ptrdiff_t>(dst_ptr) - 1065bf215546Sopenharmony_ci reinterpret_cast<ptrdiff_t>(src_ptr))) < size) 1066bf215546Sopenharmony_ci return CL_MEM_COPY_OVERLAP; 1067bf215546Sopenharmony_ci 1068bf215546Sopenharmony_ci 1069bf215546Sopenharmony_ci bool can_emulate = q.device().has_system_svm(); 1070bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(event_wait_list, num_events_in_wait_list); 1071bf215546Sopenharmony_ci 1072bf215546Sopenharmony_ci validate_common(q, deps); 1073bf215546Sopenharmony_ci 1074bf215546Sopenharmony_ci if (can_emulate) { 1075bf215546Sopenharmony_ci auto hev = create<hard_event>(q, cmd, deps, 1076bf215546Sopenharmony_ci [=](clover::event &) { 1077bf215546Sopenharmony_ci memcpy(dst_ptr, src_ptr, size); 1078bf215546Sopenharmony_ci }); 1079bf215546Sopenharmony_ci 1080bf215546Sopenharmony_ci if (blocking_copy) 1081bf215546Sopenharmony_ci hev().wait(); 1082bf215546Sopenharmony_ci ret_object(event, hev); 1083bf215546Sopenharmony_ci return CL_SUCCESS; 1084bf215546Sopenharmony_ci } 1085bf215546Sopenharmony_ci 1086bf215546Sopenharmony_ci CLOVER_NOT_SUPPORTED_UNTIL("2.0"); 1087bf215546Sopenharmony_ci return CL_INVALID_VALUE; 1088bf215546Sopenharmony_ci 1089bf215546Sopenharmony_ci} catch (error &e) { 1090bf215546Sopenharmony_ci return e.get(); 1091bf215546Sopenharmony_ci} 1092bf215546Sopenharmony_ci 1093bf215546Sopenharmony_ciCLOVER_API cl_int 1094bf215546Sopenharmony_ciclEnqueueSVMMemcpy(cl_command_queue d_q, 1095bf215546Sopenharmony_ci cl_bool blocking_copy, 1096bf215546Sopenharmony_ci void *dst_ptr, 1097bf215546Sopenharmony_ci const void *src_ptr, 1098bf215546Sopenharmony_ci size_t size, 1099bf215546Sopenharmony_ci cl_uint num_events_in_wait_list, 1100bf215546Sopenharmony_ci const cl_event *event_wait_list, 1101bf215546Sopenharmony_ci cl_event *event) { 1102bf215546Sopenharmony_ci 1103bf215546Sopenharmony_ci return EnqueueSVMMemcpy(d_q, blocking_copy, dst_ptr, src_ptr, 1104bf215546Sopenharmony_ci size, num_events_in_wait_list, event_wait_list, 1105bf215546Sopenharmony_ci event, CL_COMMAND_SVM_MEMCPY); 1106bf215546Sopenharmony_ci} 1107bf215546Sopenharmony_ci 1108bf215546Sopenharmony_cicl_int 1109bf215546Sopenharmony_ciclover::EnqueueSVMMemFill(cl_command_queue d_q, 1110bf215546Sopenharmony_ci void *svm_ptr, 1111bf215546Sopenharmony_ci const void *pattern, 1112bf215546Sopenharmony_ci size_t pattern_size, 1113bf215546Sopenharmony_ci size_t size, 1114bf215546Sopenharmony_ci cl_uint num_events_in_wait_list, 1115bf215546Sopenharmony_ci const cl_event *event_wait_list, 1116bf215546Sopenharmony_ci cl_event *event, 1117bf215546Sopenharmony_ci cl_int cmd) try { 1118bf215546Sopenharmony_ci auto &q = obj(d_q); 1119bf215546Sopenharmony_ci 1120bf215546Sopenharmony_ci if (!q.device().svm_support()) 1121bf215546Sopenharmony_ci return CL_INVALID_OPERATION; 1122bf215546Sopenharmony_ci 1123bf215546Sopenharmony_ci if (svm_ptr == nullptr || pattern == nullptr || 1124bf215546Sopenharmony_ci !util_is_power_of_two_nonzero(pattern_size) || 1125bf215546Sopenharmony_ci pattern_size > 128 || 1126bf215546Sopenharmony_ci !ptr_is_aligned(svm_ptr, pattern_size) || 1127bf215546Sopenharmony_ci size % pattern_size) 1128bf215546Sopenharmony_ci return CL_INVALID_VALUE; 1129bf215546Sopenharmony_ci 1130bf215546Sopenharmony_ci bool can_emulate = q.device().has_system_svm(); 1131bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(event_wait_list, num_events_in_wait_list); 1132bf215546Sopenharmony_ci 1133bf215546Sopenharmony_ci validate_common(q, deps); 1134bf215546Sopenharmony_ci 1135bf215546Sopenharmony_ci if (can_emulate) { 1136bf215546Sopenharmony_ci auto hev = create<hard_event>(q, cmd, deps, 1137bf215546Sopenharmony_ci [=](clover::event &) { 1138bf215546Sopenharmony_ci void *ptr = svm_ptr; 1139bf215546Sopenharmony_ci for (size_t s = size; s; s -= pattern_size) { 1140bf215546Sopenharmony_ci memcpy(ptr, pattern, pattern_size); 1141bf215546Sopenharmony_ci ptr = static_cast<uint8_t*>(ptr) + pattern_size; 1142bf215546Sopenharmony_ci } 1143bf215546Sopenharmony_ci }); 1144bf215546Sopenharmony_ci 1145bf215546Sopenharmony_ci ret_object(event, hev); 1146bf215546Sopenharmony_ci return CL_SUCCESS; 1147bf215546Sopenharmony_ci } 1148bf215546Sopenharmony_ci 1149bf215546Sopenharmony_ci CLOVER_NOT_SUPPORTED_UNTIL("2.0"); 1150bf215546Sopenharmony_ci return CL_INVALID_VALUE; 1151bf215546Sopenharmony_ci 1152bf215546Sopenharmony_ci} catch (error &e) { 1153bf215546Sopenharmony_ci return e.get(); 1154bf215546Sopenharmony_ci} 1155bf215546Sopenharmony_ci 1156bf215546Sopenharmony_ciCLOVER_API cl_int 1157bf215546Sopenharmony_ciclEnqueueSVMMemFill(cl_command_queue d_q, 1158bf215546Sopenharmony_ci void *svm_ptr, 1159bf215546Sopenharmony_ci const void *pattern, 1160bf215546Sopenharmony_ci size_t pattern_size, 1161bf215546Sopenharmony_ci size_t size, 1162bf215546Sopenharmony_ci cl_uint num_events_in_wait_list, 1163bf215546Sopenharmony_ci const cl_event *event_wait_list, 1164bf215546Sopenharmony_ci cl_event *event) { 1165bf215546Sopenharmony_ci 1166bf215546Sopenharmony_ci return EnqueueSVMMemFill(d_q, svm_ptr, pattern, pattern_size, 1167bf215546Sopenharmony_ci size, num_events_in_wait_list, event_wait_list, 1168bf215546Sopenharmony_ci event, CL_COMMAND_SVM_MEMFILL); 1169bf215546Sopenharmony_ci} 1170bf215546Sopenharmony_ci 1171bf215546Sopenharmony_cicl_int 1172bf215546Sopenharmony_ciclover::EnqueueSVMMap(cl_command_queue d_q, 1173bf215546Sopenharmony_ci cl_bool blocking_map, 1174bf215546Sopenharmony_ci cl_map_flags map_flags, 1175bf215546Sopenharmony_ci void *svm_ptr, 1176bf215546Sopenharmony_ci size_t size, 1177bf215546Sopenharmony_ci cl_uint num_events_in_wait_list, 1178bf215546Sopenharmony_ci const cl_event *event_wait_list, 1179bf215546Sopenharmony_ci cl_event *event, 1180bf215546Sopenharmony_ci cl_int cmd) try { 1181bf215546Sopenharmony_ci auto &q = obj(d_q); 1182bf215546Sopenharmony_ci 1183bf215546Sopenharmony_ci if (!q.device().svm_support()) 1184bf215546Sopenharmony_ci return CL_INVALID_OPERATION; 1185bf215546Sopenharmony_ci 1186bf215546Sopenharmony_ci if (svm_ptr == nullptr || size == 0) 1187bf215546Sopenharmony_ci return CL_INVALID_VALUE; 1188bf215546Sopenharmony_ci 1189bf215546Sopenharmony_ci bool can_emulate = q.device().has_system_svm(); 1190bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(event_wait_list, num_events_in_wait_list); 1191bf215546Sopenharmony_ci 1192bf215546Sopenharmony_ci validate_common(q, deps); 1193bf215546Sopenharmony_ci 1194bf215546Sopenharmony_ci if (can_emulate) { 1195bf215546Sopenharmony_ci auto hev = create<hard_event>(q, cmd, deps, 1196bf215546Sopenharmony_ci [](clover::event &) { }); 1197bf215546Sopenharmony_ci 1198bf215546Sopenharmony_ci ret_object(event, hev); 1199bf215546Sopenharmony_ci return CL_SUCCESS; 1200bf215546Sopenharmony_ci } 1201bf215546Sopenharmony_ci 1202bf215546Sopenharmony_ci CLOVER_NOT_SUPPORTED_UNTIL("2.0"); 1203bf215546Sopenharmony_ci return CL_INVALID_VALUE; 1204bf215546Sopenharmony_ci 1205bf215546Sopenharmony_ci} catch (error &e) { 1206bf215546Sopenharmony_ci return e.get(); 1207bf215546Sopenharmony_ci} 1208bf215546Sopenharmony_ci 1209bf215546Sopenharmony_ciCLOVER_API cl_int 1210bf215546Sopenharmony_ciclEnqueueSVMMap(cl_command_queue d_q, 1211bf215546Sopenharmony_ci cl_bool blocking_map, 1212bf215546Sopenharmony_ci cl_map_flags map_flags, 1213bf215546Sopenharmony_ci void *svm_ptr, 1214bf215546Sopenharmony_ci size_t size, 1215bf215546Sopenharmony_ci cl_uint num_events_in_wait_list, 1216bf215546Sopenharmony_ci const cl_event *event_wait_list, 1217bf215546Sopenharmony_ci cl_event *event) { 1218bf215546Sopenharmony_ci 1219bf215546Sopenharmony_ci return EnqueueSVMMap(d_q, blocking_map, map_flags, svm_ptr, size, 1220bf215546Sopenharmony_ci num_events_in_wait_list, event_wait_list, event, 1221bf215546Sopenharmony_ci CL_COMMAND_SVM_MAP); 1222bf215546Sopenharmony_ci} 1223bf215546Sopenharmony_ci 1224bf215546Sopenharmony_cicl_int 1225bf215546Sopenharmony_ciclover::EnqueueSVMUnmap(cl_command_queue d_q, 1226bf215546Sopenharmony_ci void *svm_ptr, 1227bf215546Sopenharmony_ci cl_uint num_events_in_wait_list, 1228bf215546Sopenharmony_ci const cl_event *event_wait_list, 1229bf215546Sopenharmony_ci cl_event *event, 1230bf215546Sopenharmony_ci cl_int cmd) try { 1231bf215546Sopenharmony_ci auto &q = obj(d_q); 1232bf215546Sopenharmony_ci 1233bf215546Sopenharmony_ci if (!q.device().svm_support()) 1234bf215546Sopenharmony_ci return CL_INVALID_OPERATION; 1235bf215546Sopenharmony_ci 1236bf215546Sopenharmony_ci if (svm_ptr == nullptr) 1237bf215546Sopenharmony_ci return CL_INVALID_VALUE; 1238bf215546Sopenharmony_ci 1239bf215546Sopenharmony_ci bool can_emulate = q.device().has_system_svm(); 1240bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(event_wait_list, num_events_in_wait_list); 1241bf215546Sopenharmony_ci 1242bf215546Sopenharmony_ci validate_common(q, deps); 1243bf215546Sopenharmony_ci 1244bf215546Sopenharmony_ci if (can_emulate) { 1245bf215546Sopenharmony_ci auto hev = create<hard_event>(q, cmd, deps, 1246bf215546Sopenharmony_ci [](clover::event &) { }); 1247bf215546Sopenharmony_ci 1248bf215546Sopenharmony_ci ret_object(event, hev); 1249bf215546Sopenharmony_ci return CL_SUCCESS; 1250bf215546Sopenharmony_ci } 1251bf215546Sopenharmony_ci 1252bf215546Sopenharmony_ci CLOVER_NOT_SUPPORTED_UNTIL("2.0"); 1253bf215546Sopenharmony_ci return CL_INVALID_VALUE; 1254bf215546Sopenharmony_ci 1255bf215546Sopenharmony_ci} catch (error &e) { 1256bf215546Sopenharmony_ci return e.get(); 1257bf215546Sopenharmony_ci} 1258bf215546Sopenharmony_ci 1259bf215546Sopenharmony_ciCLOVER_API cl_int 1260bf215546Sopenharmony_ciclEnqueueSVMUnmap(cl_command_queue d_q, 1261bf215546Sopenharmony_ci void *svm_ptr, 1262bf215546Sopenharmony_ci cl_uint num_events_in_wait_list, 1263bf215546Sopenharmony_ci const cl_event *event_wait_list, 1264bf215546Sopenharmony_ci cl_event *event) { 1265bf215546Sopenharmony_ci 1266bf215546Sopenharmony_ci return EnqueueSVMUnmap(d_q, svm_ptr, num_events_in_wait_list, 1267bf215546Sopenharmony_ci event_wait_list, event, CL_COMMAND_SVM_UNMAP); 1268bf215546Sopenharmony_ci} 1269bf215546Sopenharmony_ci 1270bf215546Sopenharmony_ciCLOVER_API cl_int 1271bf215546Sopenharmony_ciclEnqueueSVMMigrateMem(cl_command_queue d_q, 1272bf215546Sopenharmony_ci cl_uint num_svm_pointers, 1273bf215546Sopenharmony_ci const void **svm_pointers, 1274bf215546Sopenharmony_ci const size_t *sizes, 1275bf215546Sopenharmony_ci const cl_mem_migration_flags flags, 1276bf215546Sopenharmony_ci cl_uint num_deps, 1277bf215546Sopenharmony_ci const cl_event *d_deps, 1278bf215546Sopenharmony_ci cl_event *rd_ev) try { 1279bf215546Sopenharmony_ci auto &q = obj(d_q); 1280bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 1281bf215546Sopenharmony_ci 1282bf215546Sopenharmony_ci validate_common(q, deps); 1283bf215546Sopenharmony_ci validate_mem_migration_flags(flags); 1284bf215546Sopenharmony_ci 1285bf215546Sopenharmony_ci if (!q.device().svm_support()) 1286bf215546Sopenharmony_ci return CL_INVALID_OPERATION; 1287bf215546Sopenharmony_ci 1288bf215546Sopenharmony_ci if (!num_svm_pointers || !svm_pointers) 1289bf215546Sopenharmony_ci return CL_INVALID_VALUE; 1290bf215546Sopenharmony_ci 1291bf215546Sopenharmony_ci std::vector<size_t> sizes_copy(num_svm_pointers); 1292bf215546Sopenharmony_ci std::vector<const void*> ptrs(num_svm_pointers); 1293bf215546Sopenharmony_ci 1294bf215546Sopenharmony_ci for (unsigned i = 0; i < num_svm_pointers; ++i) { 1295bf215546Sopenharmony_ci const void *ptr = svm_pointers[i]; 1296bf215546Sopenharmony_ci size_t size = sizes ? sizes[i] : 0; 1297bf215546Sopenharmony_ci if (!ptr) 1298bf215546Sopenharmony_ci return CL_INVALID_VALUE; 1299bf215546Sopenharmony_ci 1300bf215546Sopenharmony_ci auto p = q.context().find_svm_allocation(ptr); 1301bf215546Sopenharmony_ci if (!p.first) 1302bf215546Sopenharmony_ci return CL_INVALID_VALUE; 1303bf215546Sopenharmony_ci 1304bf215546Sopenharmony_ci std::ptrdiff_t pdiff = (uint8_t*)ptr - (uint8_t*)p.first; 1305bf215546Sopenharmony_ci if (size && size + pdiff > p.second) 1306bf215546Sopenharmony_ci return CL_INVALID_VALUE; 1307bf215546Sopenharmony_ci 1308bf215546Sopenharmony_ci sizes_copy[i] = size ? size : p.second; 1309bf215546Sopenharmony_ci ptrs[i] = size ? svm_pointers[i] : p.first; 1310bf215546Sopenharmony_ci } 1311bf215546Sopenharmony_ci 1312bf215546Sopenharmony_ci auto hev = create<hard_event>( 1313bf215546Sopenharmony_ci q, CL_COMMAND_MIGRATE_MEM_OBJECTS, deps, 1314bf215546Sopenharmony_ci [=, &q](event &) { 1315bf215546Sopenharmony_ci q.svm_migrate(ptrs, sizes_copy, flags); 1316bf215546Sopenharmony_ci }); 1317bf215546Sopenharmony_ci 1318bf215546Sopenharmony_ci ret_object(rd_ev, hev); 1319bf215546Sopenharmony_ci return CL_SUCCESS; 1320bf215546Sopenharmony_ci 1321bf215546Sopenharmony_ci} catch (error &e) { 1322bf215546Sopenharmony_ci return e.get(); 1323bf215546Sopenharmony_ci} 1324