• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IntelPython / dpctl / 14222426726

02 Apr 2025 02:39PM UTC coverage: 86.307% (-0.07%) from 86.379%
14222426726

Pull #2038

github

web-flow
Merge 301707497 into 67317b094
Pull Request #2038: Add support for raw_kernel_arg extension

3018 of 3716 branches covered (81.22%)

Branch coverage included in aggregate %.

46 of 67 new or added lines in 3 files covered. (68.66%)

1 existing line in 1 file now uncovered.

12160 of 13870 relevant lines covered (87.67%)

7005.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.17
/libsyclinterface/source/dpctl_sycl_queue_interface.cpp
1
//===----- dpctl_sycl_queue_interface.cpp - Implements C API for sycl::queue =//
2
//
3
//                      Data Parallel Control (dpctl)
4
//
5
// Copyright 2020-2025 Intel Corporation
6
//
7
// Licensed under the Apache License, Version 2.0 (the "License");
8
// you may not use this file except in compliance with the License.
9
// You may obtain a copy of the License at
10
//
11
//    http://www.apache.org/licenses/LICENSE-2.0
12
//
13
// Unless required by applicable law or agreed to in writing, software
14
// distributed under the License is distributed on an "AS IS" BASIS,
15
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
// See the License for the specific language governing permissions and
17
// limitations under the License.
18
//
19
//===----------------------------------------------------------------------===//
20
///
21
/// \file
22
/// This file implements the data types and functions declared in
23
/// dpctl_sycl_queue_interface.h.
24
///
25
//===----------------------------------------------------------------------===//
26

27
#include "dpctl_sycl_queue_interface.h"
28
#include "Config/dpctl_config.h"
29
#include "dpctl_error_handlers.h"
30
#include "dpctl_sycl_context_interface.h"
31
#include "dpctl_sycl_device_interface.h"
32
#include "dpctl_sycl_device_manager.h"
33
#include "dpctl_sycl_type_casters.hpp"
34

35
#include <stddef.h>
36
#include <stdint.h>
37

38
#include <cstdint>
39
#include <exception>
40
#include <sstream>
41
#include <stdexcept>
42
#include <sycl/sycl.hpp> /* SYCL headers   */
43
#include <utility>
44

45
#if defined(SYCL_EXT_ONEAPI_WORK_GROUP_MEMORY) ||                              \
46
    defined(SYCL_EXT_ONEAPI_RAW_KERNEL_ARG)
47
#include "dpctl_sycl_extension_interface.h"
48
#endif
49

50
using namespace sycl;
51

52
#define SET_LOCAL_ACCESSOR_ARG(CGH, NDIM, ARGTY, R, IDX)                       \
53
    do {                                                                       \
31 ✔
54
        switch ((ARGTY)) {                                                     \
31 ✔
55
        case DPCTL_INT8_T:                                                     \
3 ✔
56
        {                                                                      \
3 ✔
57
            auto la = local_accessor<std::int8_t, NDIM>(R, CGH);               \
3 ✔
58
            CGH.set_arg(IDX, la);                                              \
3 ✔
59
            return true;                                                       \
3 ✔
60
        }                                                                      \
×
61
        case DPCTL_UINT8_T:                                                    \
3 ✔
62
        {                                                                      \
3 ✔
63
            auto la = local_accessor<std::uint8_t, NDIM>(R, CGH);              \
3 ✔
64
            CGH.set_arg(IDX, la);                                              \
3 ✔
65
            return true;                                                       \
3 ✔
66
        }                                                                      \
×
67
        case DPCTL_INT16_T:                                                    \
3 ✔
68
        {                                                                      \
3 ✔
69
            auto la = local_accessor<std::int16_t, NDIM>(R, CGH);              \
3 ✔
70
            CGH.set_arg(IDX, la);                                              \
3 ✔
71
            return true;                                                       \
3 ✔
72
        }                                                                      \
×
73
        case DPCTL_UINT16_T:                                                   \
3 ✔
74
        {                                                                      \
3 ✔
75
            auto la = local_accessor<std::uint16_t, NDIM>(R, CGH);             \
3 ✔
76
            CGH.set_arg(IDX, la);                                              \
3 ✔
77
            return true;                                                       \
3 ✔
78
        }                                                                      \
×
79
        case DPCTL_INT32_T:                                                    \
3 ✔
80
        {                                                                      \
3 ✔
81
            auto la = local_accessor<std::int32_t, NDIM>(R, CGH);              \
3 ✔
82
            CGH.set_arg(IDX, la);                                              \
3 ✔
83
            return true;                                                       \
3 ✔
84
        }                                                                      \
×
85
        case DPCTL_UINT32_T:                                                   \
3 ✔
86
        {                                                                      \
3 ✔
87
            auto la = local_accessor<std::uint32_t, NDIM>(R, CGH);             \
3 ✔
88
            CGH.set_arg(IDX, la);                                              \
3 ✔
89
            return true;                                                       \
3 ✔
90
        }                                                                      \
×
91
        case DPCTL_INT64_T:                                                    \
3 ✔
92
        {                                                                      \
3 ✔
93
            auto la = local_accessor<std::int64_t, NDIM>(R, CGH);              \
3 ✔
94
            CGH.set_arg(IDX, la);                                              \
3 ✔
95
            return true;                                                       \
3 ✔
96
        }                                                                      \
×
97
        case DPCTL_UINT64_T:                                                   \
3 ✔
98
        {                                                                      \
3 ✔
99
            auto la = local_accessor<std::uint64_t, NDIM>(R, CGH);             \
3 ✔
100
            CGH.set_arg(IDX, la);                                              \
3 ✔
101
            return true;                                                       \
3 ✔
102
        }                                                                      \
×
103
        case DPCTL_FLOAT32_T:                                                  \
3 ✔
104
        {                                                                      \
3 ✔
105
            auto la = local_accessor<float, NDIM>(R, CGH);                     \
3 ✔
106
            CGH.set_arg(IDX, la);                                              \
3 ✔
107
            return true;                                                       \
3 ✔
108
        }                                                                      \
×
109
        case DPCTL_FLOAT64_T:                                                  \
3 ✔
110
        {                                                                      \
3 ✔
111
            auto la = local_accessor<double, NDIM>(R, CGH);                    \
3 ✔
112
            CGH.set_arg(IDX, la);                                              \
3 ✔
113
            return true;                                                       \
3 ✔
114
        }                                                                      \
×
115
        default:                                                               \
1 ✔
116
            error_handler("Kernel argument could not be created.", __FILE__,   \
1 ✔
117
                          __func__, __LINE__, error_level::error);             \
1 ✔
118
            return false;                                                      \
1 ✔
119
        }                                                                      \
31 ✔
120
    } while (0);
31 ✔
121

122
namespace
123
{
124
static_assert(__SYCL_COMPILER_VERSION >= __SYCL_COMPILER_VERSION_REQUIRED,
125
              "The compiler does not meet minimum version requirement");
126

127
using namespace dpctl::syclinterface;
128

129
typedef struct complex
130
{
131
    std::uint64_t real;
132
    std::uint64_t imag;
133
} complexNumber;
134

135
void set_dependent_events(handler &cgh,
136
                          __dpctl_keep const DPCTLSyclEventRef *DepEvents,
137
                          size_t NDepEvents)
138
{
174 ✔
139
    for (auto i = 0ul; i < NDepEvents; ++i) {
319 ✔
140
        auto ei = unwrap<event>(DepEvents[i]);
145 ✔
141
        if (ei)
145 !
142
            cgh.depends_on(*ei);
145 ✔
143
    }
145 ✔
144
}
174 ✔
145

146
bool set_local_accessor_arg(handler &cgh,
147
                            size_t idx,
148
                            const MDLocalAccessor *mdstruct)
149
{
31 ✔
150
    switch (mdstruct->ndim) {
31 ✔
151
    case 1:
11 !
152
    {
11 ✔
153
        auto r = range<1>(mdstruct->dim0);
11 ✔
154
        SET_LOCAL_ACCESSOR_ARG(cgh, 1, mdstruct->dpctl_type_id, r, idx);
11 !
155
    }
×
156
    case 2:
10 !
157
    {
10 ✔
158
        auto r = range<2>(mdstruct->dim0, mdstruct->dim1);
10 ✔
159
        SET_LOCAL_ACCESSOR_ARG(cgh, 2, mdstruct->dpctl_type_id, r, idx);
10 !
160
    }
×
161
    case 3:
10 !
162
    {
10 ✔
163
        auto r = range<3>(mdstruct->dim0, mdstruct->dim1, mdstruct->dim2);
10 ✔
164
        SET_LOCAL_ACCESSOR_ARG(cgh, 3, mdstruct->dpctl_type_id, r, idx);
10 !
165
    }
×
166
    default:
×
167
        return false;
×
168
    }
31 ✔
169
}
31 ✔
170
/*!
171
 * @brief Set the kernel arg object
172
 *
173
 * @param cgh   SYCL command group handler using which a kernel is going to
174
 *              be submitted.
175
 * @param idx   The position of the argument in the list of arguments passed
176
 * to a kernel.
177
 * @param Arg   A void* representing a kernel argument.
178
 * @param Argty A typeid specifying the C++ type of the Arg parameter.
179
 */
180
bool set_kernel_arg(handler &cgh,
181
                    size_t idx,
182
                    __dpctl_keep void *Arg,
183
                    DPCTLKernelArgType ArgTy)
184
{
490 ✔
185
    bool arg_set = true;
490 ✔
186

187
    switch (ArgTy) {
490 ✔
188
    case DPCTL_INT8_T:
3 !
189
        cgh.set_arg(idx, *(std::int8_t *)Arg);
3 ✔
190
        break;
3 ✔
191
    case DPCTL_UINT8_T:
3 !
192
        cgh.set_arg(idx, *(std::uint8_t *)Arg);
3 ✔
193
        break;
3 ✔
194
    case DPCTL_INT16_T:
9 !
195
        cgh.set_arg(idx, *(std::int16_t *)Arg);
9 ✔
196
        break;
9 ✔
197
    case DPCTL_UINT16_T:
3 !
198
        cgh.set_arg(idx, *(std::uint16_t *)Arg);
3 ✔
199
        break;
3 ✔
200
    case DPCTL_INT32_T:
9 !
201
        cgh.set_arg(idx, *(std::int32_t *)Arg);
9 ✔
202
        break;
9 ✔
203
    case DPCTL_UINT32_T:
11 !
204
        cgh.set_arg(idx, *(std::uint32_t *)Arg);
11 ✔
205
        break;
11 ✔
206
    case DPCTL_INT64_T:
9 !
207
        cgh.set_arg(idx, *(std::int64_t *)Arg);
9 ✔
208
        break;
9 ✔
209
    case DPCTL_UINT64_T:
9 !
210
        cgh.set_arg(idx, *(std::uint64_t *)Arg);
9 ✔
211
        break;
9 ✔
212
    case DPCTL_FLOAT32_T:
9 !
213
        cgh.set_arg(idx, *(float *)Arg);
9 ✔
214
        break;
9 ✔
215
    case DPCTL_FLOAT64_T:
9 !
216
        cgh.set_arg(idx, *(double *)Arg);
9 ✔
217
        break;
9 ✔
218
    case DPCTL_VOID_PTR:
323 !
219
        cgh.set_arg(idx, Arg);
323 ✔
220
        break;
323 ✔
221
    case DPCTL_LOCAL_ACCESSOR:
31 !
222
        arg_set = set_local_accessor_arg(cgh, idx, (MDLocalAccessor *)Arg);
31 ✔
223
        break;
31 ✔
224
#ifdef SYCL_EXT_ONEAPI_WORK_GROUP_MEMORY
×
225
    case DPCTL_WORK_GROUP_MEMORY:
31 !
226
    {
31 ✔
227
        auto ref = static_cast<DPCTLSyclWorkGroupMemoryRef>(Arg);
31 ✔
228
        RawWorkGroupMemory *raw_mem = unwrap<RawWorkGroupMemory>(ref);
31 ✔
229
        size_t num_bytes = raw_mem->nbytes;
31 ✔
230
        sycl::ext::oneapi::experimental::work_group_memory<char[]> mem{
31 ✔
231
            num_bytes, cgh};
31 ✔
232
        cgh.set_arg(idx, mem);
31 ✔
233
        break;
31 ✔
234
    }
×
NEW
235
#endif
×
NEW
236
#ifdef SYCL_EXT_ONEAPI_RAW_KERNEL_ARG
×
237
    case DPCTL_RAW_KERNEL_ARG:
30 !
238
    {
30 ✔
239
        auto ref = static_cast<DPCTLSyclRawKernelArgRef>(Arg);
30 ✔
240
        RawKernelArgData *raw_arg = unwrap<RawKernelArgData>(ref);
30 ✔
241
        void *bytes = raw_arg->bytes;
30 ✔
242
        size_t count = raw_arg->count;
30 ✔
243
        sycl::ext::oneapi::experimental::raw_kernel_arg arg{bytes, count};
30 ✔
244
        cgh.set_arg(idx, arg);
30 ✔
245
        break;
30 ✔
NEW
246
    }
×
UNCOV
247
#endif
×
248
    default:
1 !
249
        arg_set = false;
1 ✔
250
        break;
1 ✔
251
    }
490 ✔
252
    return arg_set;
490 ✔
253
}
490 ✔
254

255
void set_kernel_args(handler &cgh,
256
                     __dpctl_keep void **Args,
257
                     __dpctl_keep const DPCTLKernelArgType *ArgTypes,
258
                     size_t NArgs)
259
{
174 ✔
260
    for (auto i = 0ul; i < NArgs; ++i) {
662 ✔
261
        if (!set_kernel_arg(cgh, i, Args[i], ArgTypes[i])) {
490 ✔
262
            error_handler("Kernel argument could not be created.", __FILE__,
2 ✔
263
                          __func__, __LINE__);
2 ✔
264
            throw std::invalid_argument(
2 ✔
265
                "Kernel argument could not be created.");
2 ✔
266
        }
2 ✔
267
    }
490 ✔
268
}
174 ✔
269

270
std::unique_ptr<property_list> create_property_list(int properties)
271
{
40,058 ✔
272
    std::unique_ptr<property_list> propList;
40,058 ✔
273
    int _prop = properties;
40,058 ✔
274
    if (_prop & DPCTL_ENABLE_PROFILING) {
40,058 ✔
275
        _prop = _prop ^ DPCTL_ENABLE_PROFILING;
71 ✔
276
        if (_prop & DPCTL_IN_ORDER) {
71 ✔
277
            _prop = _prop ^ DPCTL_IN_ORDER;
24 ✔
278
            propList = std::make_unique<property_list>(
24 ✔
279
                sycl::property::queue::enable_profiling(),
24 ✔
280
                sycl::property::queue::in_order());
24 ✔
281
        }
24 ✔
282
        else {
47 ✔
283
            propList = std::make_unique<property_list>(
47 ✔
284
                sycl::property::queue::enable_profiling());
47 ✔
285
        }
47 ✔
286
    }
71 ✔
287
    else if (_prop & DPCTL_IN_ORDER) {
39,987 ✔
288
        _prop = _prop ^ DPCTL_IN_ORDER;
436 ✔
289
        propList =
436 ✔
290
            std::make_unique<property_list>(sycl::property::queue::in_order());
436 ✔
291
    }
436 ✔
292
    else {
39,551 ✔
293
        propList = std::make_unique<property_list>();
39,551 ✔
294
    }
39,551 ✔
295

296
    if (_prop) {
40,058 ✔
297
        std::stringstream ss;
1 ✔
298
        ss << "Invalid queue property argument (" << std::hex << properties
1 ✔
299
           << "), interpreted as (" << (properties ^ _prop) << ").";
1 ✔
300
        error_handler(ss.str(), __FILE__, __func__, __LINE__);
1 ✔
301
    }
1 ✔
302
    return propList;
40,058 ✔
303
}
40,058 ✔
304

305
__dpctl_give DPCTLSyclQueueRef
306
getQueueImpl(__dpctl_keep DPCTLSyclContextRef cRef,
307
             __dpctl_keep DPCTLSyclDeviceRef dRef,
308
             error_handler_callback *handler,
309
             int properties)
310
{
159 ✔
311
    DPCTLSyclQueueRef qRef = nullptr;
159 ✔
312
    qRef = DPCTLQueue_Create(cRef, dRef, handler, properties);
159 ✔
313
    return qRef;
159 ✔
314
}
159 ✔
315

316
} /* end of anonymous namespace */
317

318
DPCTL_API
319
__dpctl_give DPCTLSyclQueueRef
320
DPCTLQueue_Create(__dpctl_keep const DPCTLSyclContextRef CRef,
321
                  __dpctl_keep const DPCTLSyclDeviceRef DRef,
322
                  error_handler_callback *handler,
323
                  int properties)
324
{
40,060 ✔
325
    DPCTLSyclQueueRef q = nullptr;
40,060 ✔
326
    auto dev = unwrap<device>(DRef);
40,060 ✔
327
    auto ctx = unwrap<context>(CRef);
40,060 ✔
328

329
    if (!(dev && ctx)) {
40,060 ✔
330
        error_handler("Cannot create queue from DPCTLSyclContextRef and "
2 ✔
331
                      "DPCTLSyclDeviceRef as input is a nullptr.",
2 ✔
332
                      __FILE__, __func__, __LINE__);
2 ✔
333
        return q;
2 ✔
334
    }
2 ✔
335
    auto propList = create_property_list(properties);
40,058 ✔
336

337
    if (handler) {
40,058 ✔
338
        try {
44 ✔
339
            auto Queue = new queue(*ctx, *dev, DPCTL_AsyncErrorHandler(handler),
44 ✔
340
                                   *propList);
44 ✔
341
            q = wrap<queue>(Queue);
44 ✔
342
        } catch (std::exception const &e) {
44 ✔
343
            error_handler(e, __FILE__, __func__, __LINE__);
×
344
        }
×
345
    }
44 ✔
346
    else {
40,014 ✔
347
        try {
40,014 ✔
348
            auto Queue = new queue(*ctx, *dev, *propList);
40,014 ✔
349
            q = wrap<queue>(Queue);
40,014 ✔
350
        } catch (std::exception const &e) {
40,014 ✔
351
            error_handler(e, __FILE__, __func__, __LINE__);
3 ✔
352
        }
3 ✔
353
    }
40,014 ✔
354

355
    return q;
40,058 ✔
356
}
40,058 ✔
357

358
__dpctl_give DPCTLSyclQueueRef
359
DPCTLQueue_CreateForDevice(__dpctl_keep const DPCTLSyclDeviceRef DRef,
360
                           error_handler_callback *handler,
361
                           int properties)
362
{
345 ✔
363
    DPCTLSyclContextRef CRef = nullptr;
345 ✔
364
    DPCTLSyclQueueRef QRef = nullptr;
345 ✔
365
    auto Device = unwrap<device>(DRef);
345 ✔
366

367
    if (!Device) {
345 ✔
368
        error_handler("Cannot create queue from NULL device reference.",
186 ✔
369
                      __FILE__, __func__, __LINE__);
186 ✔
370
        return QRef;
186 ✔
371
    }
186 ✔
372
    // Check if a cached default context exists for the device.
373
    CRef = DPCTLDeviceMgr_GetCachedContext(DRef);
159 ✔
374
    // If a cached default context was found, that context will be used to use
375
    // create the new queue. When a default cached context was not found, as
376
    // will be the case for non-root devices, i.e., sub-devices, a new context
377
    // will be allocated. Note that any newly allocated context is not cached.
378
    if (!CRef) {
159 !
379
        context *ContextPtr = nullptr;
×
380
        try {
×
381
            ContextPtr = new context(*Device);
×
382
            CRef = wrap<context>(ContextPtr);
×
383
        } catch (std::exception const &e) {
×
384
            error_handler(e, __FILE__, __func__, __LINE__);
×
385
            delete ContextPtr;
×
386
            return QRef;
×
387
        }
×
388
    }
×
389
    // At this point we have a valid context and the queue can be allocated.
390
    QRef = getQueueImpl(CRef, DRef, handler, properties);
159 ✔
391
    // Free the context
392
    DPCTLContext_Delete(CRef);
159 ✔
393
    return QRef;
159 ✔
394
}
159 ✔
395

396
/*!
397
 * Delete the passed in pointer after verifying it points to a sycl::queue.
398
 */
399
void DPCTLQueue_Delete(__dpctl_take DPCTLSyclQueueRef QRef)
400
{
227,610 ✔
401
    delete unwrap<queue>(QRef);
227,610 ✔
402
}
227,610 ✔
403

404
/*!
405
 * Make copy of sycl::queue referenced by passed pointer
406
 */
407
__dpctl_give DPCTLSyclQueueRef
408
DPCTLQueue_Copy(__dpctl_keep const DPCTLSyclQueueRef QRef)
409
{
585,436 ✔
410
    auto Queue = unwrap<queue>(QRef);
585,436 ✔
411
    if (Queue) {
585,436 ✔
412
        try {
585,435 ✔
413
            auto CopiedQueue = new queue(*Queue);
585,435 ✔
414
            return wrap<queue>(CopiedQueue);
585,435 ✔
415
        } catch (std::exception const &e) {
585,435 ✔
416
            error_handler(e, __FILE__, __func__, __LINE__);
×
417
            return nullptr;
×
418
        }
×
419
    }
585,435 ✔
420
    else {
1 ✔
421
        error_handler("Cannot copy DPCTLSyclQueueRef as input is a nullptr",
1 ✔
422
                      __FILE__, __func__, __LINE__);
1 ✔
423
        return nullptr;
1 ✔
424
    }
1 ✔
425
}
585,436 ✔
426

427
bool DPCTLQueue_AreEq(__dpctl_keep const DPCTLSyclQueueRef QRef1,
428
                      __dpctl_keep const DPCTLSyclQueueRef QRef2)
429
{
44,365 ✔
430
    if (!(QRef1 && QRef2)) {
44,365 ✔
431
        error_handler("DPCTLSyclQueueRefs are nullptr.", __FILE__, __func__,
2 ✔
432
                      __LINE__);
2 ✔
433
        return false;
2 ✔
434
    }
2 ✔
435
    return (*unwrap<queue>(QRef1) == *unwrap<queue>(QRef2));
44,363 ✔
436
}
44,365 ✔
437

438
DPCTLSyclBackendType DPCTLQueue_GetBackend(__dpctl_keep DPCTLSyclQueueRef QRef)
439
{
10 ✔
440
    auto Q = unwrap<queue>(QRef);
10 ✔
441
    if (Q) {
10 ✔
442
        try {
9 ✔
443
            auto C = Q->get_context();
9 ✔
444
            return DPCTLContext_GetBackend(wrap<context>(&C));
9 ✔
445
        } catch (std::exception const &e) {
9 ✔
446
            error_handler(e, __FILE__, __func__, __LINE__);
×
447
            return DPCTL_UNKNOWN_BACKEND;
×
448
        }
×
449
    }
9 ✔
450
    else
1 ✔
451
        return DPCTL_UNKNOWN_BACKEND;
1 ✔
452
}
10 ✔
453

454
__dpctl_give DPCTLSyclDeviceRef
455
DPCTLQueue_GetDevice(__dpctl_keep const DPCTLSyclQueueRef QRef)
456
{
93,706 ✔
457
    DPCTLSyclDeviceRef DRef = nullptr;
93,706 ✔
458
    auto Q = unwrap<queue>(QRef);
93,706 ✔
459
    if (Q) {
93,706 ✔
460
        try {
93,705 ✔
461
            auto Device = new device(Q->get_device());
93,705 ✔
462
            DRef = wrap<device>(Device);
93,705 ✔
463
        } catch (std::exception const &e) {
93,705 ✔
464
            error_handler(e, __FILE__, __func__, __LINE__);
×
465
        }
×
466
    }
93,705 ✔
467
    else {
1 ✔
468
        error_handler("Could not get the device for this queue.", __FILE__,
1 ✔
469
                      __func__, __LINE__);
1 ✔
470
    }
1 ✔
471
    return DRef;
93,706 ✔
472
}
93,706 ✔
473

474
__dpctl_give DPCTLSyclContextRef
475
DPCTLQueue_GetContext(__dpctl_keep const DPCTLSyclQueueRef QRef)
476
{
94,695 ✔
477
    auto Q = unwrap<queue>(QRef);
94,695 ✔
478
    DPCTLSyclContextRef CRef = nullptr;
94,695 ✔
479
    if (Q)
94,695 ✔
480
        CRef = wrap<context>(new context(Q->get_context()));
94,685 ✔
481
    else {
10 ✔
482
        error_handler("Could not get the context for this queue.", __FILE__,
10 ✔
483
                      __func__, __LINE__);
10 ✔
484
    }
10 ✔
485
    return CRef;
94,695 ✔
486
}
94,695 ✔
487

488
__dpctl_give DPCTLSyclEventRef
489
DPCTLQueue_SubmitRange(__dpctl_keep const DPCTLSyclKernelRef KRef,
490
                       __dpctl_keep const DPCTLSyclQueueRef QRef,
491
                       __dpctl_keep void **Args,
492
                       __dpctl_keep const DPCTLKernelArgType *ArgTypes,
493
                       size_t NArgs,
494
                       __dpctl_keep const size_t Range[3],
495
                       size_t NDims,
496
                       __dpctl_keep const DPCTLSyclEventRef *DepEvents,
497
                       size_t NDepEvents)
498
{
61 ✔
499
    auto Kernel = unwrap<kernel>(KRef);
61 ✔
500
    auto Queue = unwrap<queue>(QRef);
61 ✔
501
    event e;
61 ✔
502

503
    try {
61 ✔
504
        switch (NDims) {
61 ✔
505
        case 1:
27 !
506
        {
27 ✔
507
            e = Queue->submit([&](handler &cgh) {
27 ✔
508
                // Depend on any event that was specified by the caller.
509
                set_dependent_events(cgh, DepEvents, NDepEvents);
27 ✔
510
                set_kernel_args(cgh, Args, ArgTypes, NArgs);
27 ✔
511
                cgh.parallel_for(range<1>{Range[0]}, *Kernel);
27 ✔
512
            });
27 ✔
513
            return wrap<event>(new event(std::move(e)));
27 ✔
514
        }
×
515
        case 2:
17 !
516
        {
17 ✔
517
            e = Queue->submit([&](handler &cgh) {
17 ✔
518
                // Depend on any event that was specified by the caller.
519
                set_dependent_events(cgh, DepEvents, NDepEvents);
17 ✔
520
                set_kernel_args(cgh, Args, ArgTypes, NArgs);
17 ✔
521
                cgh.parallel_for(range<2>{Range[0], Range[1]}, *Kernel);
17 ✔
522
            });
17 ✔
523
            return wrap<event>(new event(std::move(e)));
17 ✔
524
        }
×
525
        case 3:
17 !
526
        {
17 ✔
527
            e = Queue->submit([&](handler &cgh) {
17 ✔
528
                // Depend on any event that was specified by the caller.
529
                set_dependent_events(cgh, DepEvents, NDepEvents);
17 ✔
530
                set_kernel_args(cgh, Args, ArgTypes, NArgs);
17 ✔
531
                cgh.parallel_for(range<3>{Range[0], Range[1], Range[2]},
17 ✔
532
                                 *Kernel);
17 ✔
533
            });
17 ✔
534
            return wrap<event>(new event(std::move(e)));
17 ✔
535
        }
×
536
        default:
×
537
            error_handler("Range cannot be greater than three "
×
538
                          "dimensions.",
×
539
                          __FILE__, __func__, __LINE__, error_level::error);
×
540
            return nullptr;
×
541
        }
61 ✔
542
    } catch (std::exception const &e) {
61 ✔
543
        error_handler(e, __FILE__, __func__, __LINE__, error_level::error);
1 ✔
544
        return nullptr;
1 ✔
545
    } catch (...) {
1 ✔
546
        error_handler("Unknown exception encountered", __FILE__, __func__,
×
547
                      __LINE__, error_level::error);
×
548
        return nullptr;
×
549
    }
×
550
}
61 ✔
551

552
__dpctl_give DPCTLSyclEventRef
553
DPCTLQueue_SubmitNDRange(__dpctl_keep const DPCTLSyclKernelRef KRef,
554
                         __dpctl_keep const DPCTLSyclQueueRef QRef,
555
                         __dpctl_keep void **Args,
556
                         __dpctl_keep const DPCTLKernelArgType *ArgTypes,
557
                         size_t NArgs,
558
                         __dpctl_keep const size_t gRange[3],
559
                         __dpctl_keep const size_t lRange[3],
560
                         size_t NDims,
561
                         __dpctl_keep const DPCTLSyclEventRef *DepEvents,
562
                         size_t NDepEvents)
563
{
113 ✔
564
    auto Kernel = unwrap<kernel>(KRef);
113 ✔
565
    auto Queue = unwrap<queue>(QRef);
113 ✔
566
    event e;
113 ✔
567

568
    try {
113 ✔
569
        switch (NDims) {
113 ✔
570
        case 1:
99 !
571
        {
99 ✔
572
            e = Queue->submit([&](handler &cgh) {
99 ✔
573
                // Depend on any event that was specified by the caller.
574
                set_dependent_events(cgh, DepEvents, NDepEvents);
99 ✔
575
                set_kernel_args(cgh, Args, ArgTypes, NArgs);
99 ✔
576
                cgh.parallel_for(nd_range<1>{{gRange[0]}, {lRange[0]}},
99 ✔
577
                                 *Kernel);
99 ✔
578
            });
99 ✔
579
            return wrap<event>(new event(std::move(e)));
99 ✔
580
        }
×
581
        case 2:
7 !
582
        {
7 ✔
583
            e = Queue->submit([&](handler &cgh) {
7 ✔
584
                // Depend on any event that was specified by the caller.
585
                set_dependent_events(cgh, DepEvents, NDepEvents);
7 ✔
586
                set_kernel_args(cgh, Args, ArgTypes, NArgs);
7 ✔
587
                cgh.parallel_for(
7 ✔
588
                    nd_range<2>{{gRange[0], gRange[1]}, {lRange[0], lRange[1]}},
7 ✔
589
                    *Kernel);
7 ✔
590
            });
7 ✔
591
            return wrap<event>(new event(std::move(e)));
7 ✔
592
        }
×
593
        case 3:
7 !
594
        {
7 ✔
595
            e = Queue->submit([&](handler &cgh) {
7 ✔
596
                // Depend on any event that was specified by the caller.
597
                set_dependent_events(cgh, DepEvents, NDepEvents);
7 ✔
598
                set_kernel_args(cgh, Args, ArgTypes, NArgs);
7 ✔
599
                cgh.parallel_for(nd_range<3>{{gRange[0], gRange[1], gRange[2]},
7 ✔
600
                                             {lRange[0], lRange[1], lRange[2]}},
7 ✔
601
                                 *Kernel);
7 ✔
602
            });
7 ✔
603
            return wrap<event>(new event(std::move(e)));
7 ✔
604
        }
×
605
        default:
×
606
            error_handler("Range cannot be greater than three "
×
607
                          "dimensions.",
×
608
                          __FILE__, __func__, __LINE__, error_level::error);
×
609
            return nullptr;
×
610
        }
113 ✔
611
    } catch (std::exception const &e) {
113 ✔
612
        error_handler(e, __FILE__, __func__, __LINE__, error_level::error);
1 ✔
613
        return nullptr;
1 ✔
614
    } catch (...) {
1 ✔
615
        error_handler("Unknown exception encountered", __FILE__, __func__,
×
616
                      __LINE__, error_level::error);
×
617
        return nullptr;
×
618
    }
×
619
}
113 ✔
620

621
void DPCTLQueue_Wait(__dpctl_keep DPCTLSyclQueueRef QRef)
622
{
110,023 ✔
623
    // \todo what happens if the QRef is null or a pointer to a valid sycl
624
    // queue
625
    if (QRef) {
110,023 !
626
        auto SyclQueue = unwrap<queue>(QRef);
110,023 ✔
627
        if (SyclQueue)
110,023 !
628
            SyclQueue->wait();
110,023 ✔
629
    }
110,023 ✔
630
    else {
×
631
        error_handler("Argument QRef is NULL.", __FILE__, __func__, __LINE__);
×
632
    }
×
633
}
110,023 ✔
634

635
__dpctl_give DPCTLSyclEventRef
636
DPCTLQueue_Memcpy(__dpctl_keep const DPCTLSyclQueueRef QRef,
637
                  void *Dest,
638
                  const void *Src,
639
                  size_t Count)
640
{
92,853 ✔
641
    auto Q = unwrap<queue>(QRef);
92,853 ✔
642
    if (Q) {
92,853 ✔
643
        sycl::event ev;
92,852 ✔
644
        try {
92,852 ✔
645
            ev = Q->memcpy(Dest, Src, Count);
92,852 ✔
646
        } catch (std::exception const &e) {
92,852 ✔
647
            error_handler(e, __FILE__, __func__, __LINE__);
8 ✔
648
            return nullptr;
8 ✔
649
        }
8 ✔
650
        return wrap<event>(new event(std::move(ev)));
92,844 ✔
651
    }
92,852 ✔
652
    else {
1 ✔
653
        error_handler("QRef passed to memcpy was NULL.", __FILE__, __func__,
1 ✔
654
                      __LINE__);
1 ✔
655
        return nullptr;
1 ✔
656
    }
1 ✔
657
}
92,853 ✔
658

659
__dpctl_give DPCTLSyclEventRef
660
DPCTLQueue_MemcpyWithEvents(__dpctl_keep const DPCTLSyclQueueRef QRef,
661
                            void *Dest,
662
                            const void *Src,
663
                            size_t Count,
664
                            const DPCTLSyclEventRef *DepEvents,
665
                            size_t DepEventsCount)
666
{
59 ✔
667
    event ev;
59 ✔
668
    auto Q = unwrap<queue>(QRef);
59 ✔
669
    if (Q) {
59 ✔
670
        try {
58 ✔
671
            ev = Q->submit([&](handler &cgh) {
58 ✔
672
                if (DepEvents)
58 ✔
673
                    for (size_t i = 0; i < DepEventsCount; ++i) {
100 ✔
674
                        event *ei = unwrap<event>(DepEvents[i]);
50 ✔
675
                        if (ei)
50 !
676
                            cgh.depends_on(*ei);
50 ✔
677
                    }
50 ✔
678

679
                cgh.memcpy(Dest, Src, Count);
58 ✔
680
            });
58 ✔
681
        } catch (const std::exception &ex) {
58 ✔
682
            error_handler(ex, __FILE__, __func__, __LINE__);
8 ✔
683
            return nullptr;
8 ✔
684
        }
8 ✔
685
    }
58 ✔
686
    else {
1 ✔
687
        error_handler("QRef passed to memcpy was NULL.", __FILE__, __func__,
1 ✔
688
                      __LINE__);
1 ✔
689
        return nullptr;
1 ✔
690
    }
1 ✔
691

692
    return wrap<event>(new event(ev));
50 ✔
693
}
59 ✔
694

695
__dpctl_give DPCTLSyclEventRef
696
DPCTLQueue_Prefetch(__dpctl_keep DPCTLSyclQueueRef QRef,
697
                    const void *Ptr,
698
                    size_t Count)
699
{
16 ✔
700
    auto Q = unwrap<queue>(QRef);
16 ✔
701
    if (Q) {
16 ✔
702
        if (Ptr) {
15 ✔
703
            sycl::event ev;
7 ✔
704
            try {
7 ✔
705
                ev = Q->prefetch(Ptr, Count);
7 ✔
706
            } catch (std::exception const &e) {
7 ✔
707
                error_handler(e, __FILE__, __func__, __LINE__);
×
708
                return nullptr;
×
709
            }
×
710
            return wrap<event>(new event(std::move(ev)));
7 ✔
711
        }
7 ✔
712
        else {
8 ✔
713
            error_handler("Attempt to prefetch USM-allocation at nullptr.",
8 ✔
714
                          __FILE__, __func__, __LINE__);
8 ✔
715
            return nullptr;
8 ✔
716
        }
8 ✔
717
    }
15 ✔
718
    else {
1 ✔
719
        error_handler("QRef passed to prefetch was NULL.", __FILE__, __func__,
1 ✔
720
                      __LINE__);
1 ✔
721
        return nullptr;
1 ✔
722
    }
1 ✔
723
}
16 ✔
724

725
__dpctl_give DPCTLSyclEventRef
726
DPCTLQueue_MemAdvise(__dpctl_keep DPCTLSyclQueueRef QRef,
727
                     const void *Ptr,
728
                     size_t Count,
729
                     int Advice)
730
{
16 ✔
731
    auto Q = unwrap<queue>(QRef);
16 ✔
732
    if (Q) {
16 ✔
733
        sycl::event ev;
15 ✔
734
        try {
15 ✔
735
            ev = Q->mem_advise(Ptr, Count, Advice);
15 ✔
736
        } catch (std::exception const &e) {
15 ✔
737
            error_handler(e, __FILE__, __func__, __LINE__);
×
738
            return nullptr;
×
739
        }
×
740
        return wrap<event>(new event(std::move(ev)));
15 ✔
741
    }
15 ✔
742
    else {
1 ✔
743
        error_handler("QRef passed to prefetch was NULL.", __FILE__, __func__,
1 ✔
744
                      __LINE__);
1 ✔
745
        return nullptr;
1 ✔
746
    }
1 ✔
747
}
16 ✔
748

749
bool DPCTLQueue_IsInOrder(__dpctl_keep const DPCTLSyclQueueRef QRef)
750
{
830 ✔
751
    auto Q = unwrap<queue>(QRef);
830 ✔
752
    if (Q) {
830 ✔
753
        return Q->is_in_order();
829 ✔
754
    }
829 ✔
755
    else
1 ✔
756
        return false;
1 ✔
757
}
830 ✔
758

759
bool DPCTLQueue_HasEnableProfiling(__dpctl_keep const DPCTLSyclQueueRef QRef)
760
{
75 ✔
761
    auto Q = unwrap<queue>(QRef);
75 ✔
762
    if (Q) {
75 ✔
763
        return Q->has_property<sycl::property::queue::enable_profiling>();
74 ✔
764
    }
74 ✔
765
    else
1 ✔
766
        return false;
1 ✔
767
}
75 ✔
768

769
size_t DPCTLQueue_Hash(__dpctl_keep const DPCTLSyclQueueRef QRef)
770
{
325,638 ✔
771
    auto Q = unwrap<queue>(QRef);
325,638 ✔
772
    if (Q) {
325,638 ✔
773
        std::hash<queue> hash_fn;
325,635 ✔
774
        return hash_fn(*Q);
325,635 ✔
775
    }
325,635 ✔
776
    else {
3 ✔
777
        error_handler("Argument QRef is NULL.", __FILE__, __func__, __LINE__);
3 ✔
778
        return 0;
3 ✔
779
    }
3 ✔
780
}
325,638 ✔
781

782
__dpctl_give DPCTLSyclEventRef DPCTLQueue_SubmitBarrierForEvents(
783
    __dpctl_keep const DPCTLSyclQueueRef QRef,
784
    __dpctl_keep const DPCTLSyclEventRef *DepEvents,
785
    size_t NDepEvents)
786
{
117 ✔
787
    auto Q = unwrap<queue>(QRef);
117 ✔
788
    event e;
117 ✔
789
    if (Q) {
117 !
790
        try {
117 ✔
791
            e = Q->submit([&](handler &cgh) {
117 ✔
792
                // Depend on any event that was specified by the caller.
793
                if (NDepEvents)
117 ✔
794
                    for (auto i = 0ul; i < NDepEvents; ++i)
28 ✔
795
                        cgh.depends_on(*unwrap<event>(DepEvents[i]));
17 ✔
796

797
                cgh.ext_oneapi_barrier();
117 ✔
798
            });
117 ✔
799
        } catch (std::exception const &e) {
117 ✔
800
            error_handler(e, __FILE__, __func__, __LINE__);
×
801
            return nullptr;
×
802
        }
×
803

804
        return wrap<event>(new event(std::move(e)));
117 ✔
805
    }
117 ✔
806
    else {
×
807
        error_handler("Argument QRef is NULL", __FILE__, __func__, __LINE__);
×
808
        return nullptr;
×
809
    }
×
810
}
117 ✔
811

812
__dpctl_give DPCTLSyclEventRef
813
DPCTLQueue_SubmitBarrier(__dpctl_keep const DPCTLSyclQueueRef QRef)
814
{
1 ✔
815
    return DPCTLQueue_SubmitBarrierForEvents(QRef, nullptr, 0);
1 ✔
816
}
1 ✔
817

818
__dpctl_give DPCTLSyclEventRef
819
DPCTLQueue_Memset(__dpctl_keep const DPCTLSyclQueueRef QRef,
820
                  void *USMRef,
821
                  uint8_t Value,
822
                  size_t Count)
823
{
25 ✔
824
    auto Q = unwrap<queue>(QRef);
25 ✔
825
    if (Q && USMRef) {
25 !
826
        sycl::event ev;
24 ✔
827
        try {
24 ✔
828
            ev = Q->memset(USMRef, static_cast<int>(Value), Count);
24 ✔
829
        } catch (std::exception const &e) {
24 ✔
830
            error_handler(e, __FILE__, __func__, __LINE__);
×
831
            return nullptr;
×
832
        }
×
833
        return wrap<event>(new event(std::move(ev)));
24 ✔
834
    }
24 ✔
835
    else {
1 ✔
836
        error_handler("QRef or USMRef passed to fill8 were NULL.", __FILE__,
1 ✔
837
                      __func__, __LINE__);
1 ✔
838
        return nullptr;
1 ✔
839
    }
1 ✔
840
};
25 ✔
841

842
__dpctl_give DPCTLSyclEventRef
843
DPCTLQueue_Fill8(__dpctl_keep const DPCTLSyclQueueRef QRef,
844
                 void *USMRef,
845
                 uint8_t Value,
846
                 size_t Count)
847
{
9 ✔
848
    auto Q = unwrap<queue>(QRef);
9 ✔
849
    if (Q && USMRef) {
9 !
850
        sycl::event ev;
8 ✔
851
        try {
8 ✔
852
            ev = Q->fill<uint8_t>(USMRef, Value, Count);
8 ✔
853
        } catch (std::exception const &e) {
8 ✔
854
            error_handler(e, __FILE__, __func__, __LINE__);
×
855
            return nullptr;
×
856
        }
×
857
        return wrap<event>(new event(std::move(ev)));
8 ✔
858
    }
8 ✔
859
    else {
1 ✔
860
        error_handler("QRef or USMRef passed to fill8 were NULL.", __FILE__,
1 ✔
861
                      __func__, __LINE__);
1 ✔
862
        return nullptr;
1 ✔
863
    }
1 ✔
864
}
9 ✔
865

866
__dpctl_give DPCTLSyclEventRef
867
DPCTLQueue_Fill16(__dpctl_keep const DPCTLSyclQueueRef QRef,
868
                  void *USMRef,
869
                  uint16_t Value,
870
                  size_t Count)
871
{
9 ✔
872
    auto Q = unwrap<queue>(QRef);
9 ✔
873
    if (Q && USMRef) {
9 !
874
        sycl::event ev;
8 ✔
875
        try {
8 ✔
876
            ev = Q->fill<uint16_t>(USMRef, Value, Count);
8 ✔
877
        } catch (std::exception const &e) {
8 ✔
878
            error_handler(e, __FILE__, __func__, __LINE__);
×
879
            return nullptr;
×
880
        }
×
881
        return wrap<event>(new event(std::move(ev)));
8 ✔
882
    }
8 ✔
883
    else {
1 ✔
884
        error_handler("QRef or USMRef passed to fill16 were NULL.", __FILE__,
1 ✔
885
                      __func__, __LINE__);
1 ✔
886
        return nullptr;
1 ✔
887
    }
1 ✔
888
}
9 ✔
889

890
__dpctl_give DPCTLSyclEventRef
891
DPCTLQueue_Fill32(__dpctl_keep const DPCTLSyclQueueRef QRef,
892
                  void *USMRef,
893
                  uint32_t Value,
894
                  size_t Count)
895
{
9 ✔
896
    auto Q = unwrap<queue>(QRef);
9 ✔
897
    if (Q && USMRef) {
9 !
898
        sycl::event ev;
8 ✔
899
        try {
8 ✔
900
            ev = Q->fill<uint32_t>(USMRef, Value, Count);
8 ✔
901
        } catch (std::exception const &e) {
8 ✔
902
            error_handler(e, __FILE__, __func__, __LINE__);
×
903
            return nullptr;
×
904
        }
×
905
        return wrap<event>(new event(std::move(ev)));
8 ✔
906
    }
8 ✔
907
    else {
1 ✔
908
        error_handler("QRef or USMRef passed to fill32 were NULL.", __FILE__,
1 ✔
909
                      __func__, __LINE__);
1 ✔
910
        return nullptr;
1 ✔
911
    }
1 ✔
912
}
9 ✔
913

914
__dpctl_give DPCTLSyclEventRef
915
DPCTLQueue_Fill64(__dpctl_keep const DPCTLSyclQueueRef QRef,
916
                  void *USMRef,
917
                  uint64_t Value,
918
                  size_t Count)
919
{
9 ✔
920
    auto Q = unwrap<queue>(QRef);
9 ✔
921
    if (Q && USMRef) {
9 !
922
        sycl::event ev;
8 ✔
923
        try {
8 ✔
924
            ev = Q->fill<uint64_t>(USMRef, Value, Count);
8 ✔
925
        } catch (std::exception const &e) {
8 ✔
926
            error_handler(e, __FILE__, __func__, __LINE__);
×
927
            return nullptr;
×
928
        }
×
929
        return wrap<event>(new event(std::move(ev)));
8 ✔
930
    }
8 ✔
931
    else {
1 ✔
932
        error_handler("QRef or USMRef passed to fill64 were NULL.", __FILE__,
1 ✔
933
                      __func__, __LINE__);
1 ✔
934
        return nullptr;
1 ✔
935
    }
1 ✔
936
}
9 ✔
937

938
__dpctl_give DPCTLSyclEventRef
939
DPCTLQueue_Fill128(__dpctl_keep const DPCTLSyclQueueRef QRef,
940
                   void *USMRef,
941
                   uint64_t *Value,
942
                   size_t Count)
943
{
9 ✔
944
    auto Q = unwrap<queue>(QRef);
9 ✔
945
    if (Q && USMRef) {
9 !
946
        sycl::event ev;
8 ✔
947
        try {
8 ✔
948
            complexNumber Val;
8 ✔
949
            Val.real = Value[0];
8 ✔
950
            Val.imag = Value[1];
8 ✔
951
            ev = Q->fill(USMRef, Val, Count);
8 ✔
952
        } catch (std::exception const &e) {
8 ✔
953
            error_handler(e, __FILE__, __func__, __LINE__);
×
954
            return nullptr;
×
955
        }
×
956
        return wrap<event>(new event(std::move(ev)));
8 ✔
957
    }
8 ✔
958
    else {
1 ✔
959
        error_handler("QRef or USMRef passed to fill128 were NULL.", __FILE__,
1 ✔
960
                      __func__, __LINE__);
961
        return nullptr;
1 ✔
962
    }
1 ✔
963
}
9 ✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc