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 &region, 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 &region) {
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 &region) {
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 &region) {
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 &region) {
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 &region) {
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 &region) {
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 &region) {
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 &region) {
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