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

IntelPython / dpctl / 14311659303

07 Apr 2025 02:19PM UTC coverage: 86.321% (-0.06%) from 86.379%
14311659303

Pull #2038

github

web-flow
Merge 1ea6b9cc2 into f75b04ca5
Pull Request #2038: Add support for raw_kernel_arg extension

3018 of 3716 branches covered (81.22%)

Branch coverage included in aggregate %.

52 of 71 new or added lines in 3 files covered. (73.24%)

21 existing lines in 2 files now uncovered.

12165 of 13873 relevant lines covered (87.69%)

7004.62 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 · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc