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

IntelPython / dpctl / 25470260757

07 May 2026 01:12AM UTC coverage: 75.295%. First build
25470260757

Pull #2304

github

web-flow
Merge 97871d969 into 1a0a91064
Pull Request #2304: Add support for specialization constants

858 of 1198 branches covered (71.62%)

Branch coverage included in aggregate %.

101 of 135 new or added lines in 4 files covered. (74.81%)

3287 of 4307 relevant lines covered (76.32%)

264.67 hits per line

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

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

28
#include "dpctl_sycl_kernel_bundle_interface.h"
29
#include "Config/dpctl_config.h"
30
#include "dpctl_dynamic_lib_helper.h"
31
#include "dpctl_error_handlers.h"
32
#include "dpctl_sycl_type_casters.hpp"
33
#include <CL/cl.h> /* OpenCL headers     */
34
#include <cstdint>
35
#include <sstream>
36
#include <stddef.h>
37
#include <sycl/backend/opencl.hpp>
38
#include <sycl/sycl.hpp> /* Sycl headers       */
39
#include <utility>
40

41
#ifdef DPCTL_ENABLE_L0_PROGRAM_CREATION
42
// Note: include ze_api.h before level_zero.hpp. Make sure clang-format does
43
// not reorder the includes.
44
// clang-format off
45
#include "ze_api.h" /* Level Zero headers */
46
#include <sycl/ext/oneapi/backend/level_zero.hpp>
47
// clang-format on
48
#endif
49

50
using namespace sycl;
51

52
namespace
53
{
54
static_assert(__SYCL_COMPILER_VERSION >= __SYCL_COMPILER_VERSION_REQUIRED,
55
              "The compiler does not meet minimum version requirement");
56

57
using namespace dpctl::syclinterface;
58

59
#ifdef __linux__
60
static const char *clLoaderName = DPCTL_LIBCL_LOADER_FILENAME;
61
static const int clLibLoadFlags = RTLD_NOLOAD | RTLD_NOW | RTLD_LOCAL;
62
#elif defined(_WIN64)
63
static const char *clLoaderName = "OpenCL.dll";
64
static const int clLibLoadFlags = 0;
65
#else
66
#error "OpenCL program compilation is unavailable for this platform"
67
#endif
68

69
#define CodeStringSuffix(code)                                                 \
70
    std::string(" (code=") + std::to_string(static_cast<int>(code)) + ")"
6 ✔
71

72
#define EnumCaseString(code)                                                   \
73
    case code:                                                                 \
2 ✔
74
        return std::string(#code) + CodeStringSuffix(code)
2 ✔
75

76
static constexpr backend cl_be = backend::opencl;
77

78
struct cl_loader
79
{
80
public:
81
    static cl_loader &get()
82
    {
9 ✔
83
        static cl_loader _loader;
9 ✔
84
        return _loader;
9 ✔
85
    }
9 ✔
86

87
    template <typename retTy> retTy getSymbol(const char *name)
88
    {
9 ✔
89
        if (!opened) {
9 !
90
            error_handler("The OpenCL loader dynamic library could not "
×
91
                          "be opened.",
×
92
                          __FILE__, __func__, __LINE__);
×
93

94
            return nullptr;
×
95
        }
×
96
        return clLib.getSymbol<retTy>(name);
9 ✔
97
    }
9 ✔
98

99
private:
100
    dpctl::DynamicLibHelper clLib;
101
    bool opened;
102
    cl_loader() : clLib(clLoaderName, clLibLoadFlags), opened(clLib.opened()) {}
2 ✔
103
};
104

105
typedef cl_program (*clCreateProgramWithSourceFT)(cl_context,
106
                                                  cl_uint,
107
                                                  const char **,
108
                                                  const size_t *,
109
                                                  cl_int *);
110
const char *clCreateProgramWithSource_Name = "clCreateProgramWithSource";
111
clCreateProgramWithSourceFT get_clCreateProgramWithSource()
112
{
28 ✔
113
    static auto st_clCreateProgramWithSourceF =
28 ✔
114
        cl_loader::get().getSymbol<clCreateProgramWithSourceFT>(
28 ✔
115
            clCreateProgramWithSource_Name);
28 ✔
116

117
    return st_clCreateProgramWithSourceF;
28 ✔
118
}
28 ✔
119

120
typedef cl_program (*clCreateProgramWithILFT)(cl_context,
121
                                              const void *,
122
                                              size_t,
123
                                              cl_int *);
124
const char *clCreateProgramWithIL_Name = "clCreateProgramWithIL";
125
clCreateProgramWithILFT get_clCreateProgramWithIL()
126
{
66 ✔
127
    static auto st_clCreateProgramWithILF =
66 ✔
128
        cl_loader::get().getSymbol<clCreateProgramWithILFT>(
66 ✔
129
            clCreateProgramWithIL_Name);
66 ✔
130

131
    return st_clCreateProgramWithILF;
66 ✔
132
}
66 ✔
133
typedef cl_int (*clBuildProgramFT)(cl_program,
134
                                   cl_uint,
135
                                   const cl_device_id *,
136
                                   const char *,
137
                                   void (*)(cl_program, void *),
138
                                   void *);
139
const char *clBuildProgram_Name = "clBuildProgram";
140
clBuildProgramFT get_clBuldProgram()
141
{
94 ✔
142
    static auto st_clBuildProgramF =
94 ✔
143
        cl_loader::get().getSymbol<clBuildProgramFT>(clBuildProgram_Name);
94 ✔
144

145
    return st_clBuildProgramF;
94 ✔
146
}
94 ✔
147

148
typedef cl_kernel (*clCreateKernelFT)(cl_program, const char *, cl_int *);
149
const char *clCreateKernel_Name = "clCreateKernel";
150
clCreateKernelFT get_clCreateKernel()
151
{
153 ✔
152
    static auto st_clCreateKernelF =
153 ✔
153
        cl_loader::get().getSymbol<clCreateKernelFT>(clCreateKernel_Name);
153 ✔
154

155
    return st_clCreateKernelF;
153 ✔
156
}
153 ✔
157

158
std::string _GetErrorCode_ocl_impl(cl_int code)
159
{
2 ✔
160
    switch (code) {
2 ✔
161
        EnumCaseString(CL_BUILD_PROGRAM_FAILURE);
2 !
162
        EnumCaseString(CL_INVALID_CONTEXT);
×
163
        EnumCaseString(CL_INVALID_DEVICE);
×
164
        EnumCaseString(CL_INVALID_VALUE);
×
165
        EnumCaseString(CL_OUT_OF_RESOURCES);
×
166
        EnumCaseString(CL_OUT_OF_HOST_MEMORY);
×
167
        EnumCaseString(CL_INVALID_OPERATION);
×
168
        EnumCaseString(CL_INVALID_BINARY);
×
169
    default:
×
170
        return "<< ERROR CODE UNRECOGNIZED >>" + CodeStringSuffix(code);
×
171
    }
2 ✔
172
}
2 ✔
173

174
typedef cl_int (*clSetProgramSpecializationConstantFT)(cl_program,
175
                                                       cl_uint,
176
                                                       size_t,
177
                                                       const void *);
178
const char *clSetProgramSpecializationConstant_Name =
179
    "clSetProgramSpecializationConstant";
180
clSetProgramSpecializationConstantFT get_clSetProgramSpecializationConstant()
181
{
2 ✔
182
    static auto st_clSetProgramSpecializationConstantF =
2 ✔
183
        cl_loader::get().getSymbol<clSetProgramSpecializationConstantFT>(
2 ✔
184
            clSetProgramSpecializationConstant_Name);
2 ✔
185

186
    return st_clSetProgramSpecializationConstantF;
2 ✔
187
}
2 ✔
188

189
DPCTLSyclKernelBundleRef
190
_CreateKernelBundle_common_ocl_impl(cl_program clProgram,
191
                                    const context &ctx,
192
                                    const device &dev,
193
                                    const char *CompileOpts)
194
{
94 ✔
195
    backend_traits<cl_be>::return_type<device> clDevice;
94 ✔
196
    clDevice = get_native<cl_be>(dev);
94 ✔
197

198
    // Last two pointers are notification function pointer and user-data pointer
199
    // that can be passed to the notification function.
200
    auto clBuildProgramF = get_clBuldProgram();
94 ✔
201
    if (clBuildProgramF == nullptr) {
94 !
202
        return nullptr;
×
203
    }
×
204
    cl_int build_status =
94 ✔
205
        clBuildProgramF(clProgram, 1, &clDevice, CompileOpts, nullptr, nullptr);
94 ✔
206

207
    if (build_status != CL_SUCCESS) {
94 ✔
208
        error_handler("clBuildProgram failed: " +
2 ✔
209
                          _GetErrorCode_ocl_impl(build_status),
2 ✔
210
                      __FILE__, __func__, __LINE__);
2 ✔
211
        return nullptr;
2 ✔
212
    }
2 ✔
213

214
    using ekbTy = kernel_bundle<bundle_state::executable>;
92 ✔
215
    const ekbTy &kb =
92 ✔
216
        make_kernel_bundle<cl_be, bundle_state::executable>(clProgram, ctx);
92 ✔
217
    return wrap<ekbTy>(new ekbTy(kb));
92 ✔
218
}
94 ✔
219

220
DPCTLSyclKernelBundleRef
221
_CreateKernelBundleWithOCLSource_ocl_impl(const context &ctx,
222
                                          const device &dev,
223
                                          const char *oclSrc,
224
                                          const char *CompileOpts)
225
{
28 ✔
226
    auto clCreateProgramWithSourceF = get_clCreateProgramWithSource();
28 ✔
227
    if (clCreateProgramWithSourceF == nullptr) {
28 !
228
        return nullptr;
×
229
    }
×
230

231
    backend_traits<cl_be>::return_type<context> clContext;
28 ✔
232
    clContext = get_native<cl_be>(ctx);
28 ✔
233

234
    cl_int build_with_source_err_code = CL_SUCCESS;
28 ✔
235
    cl_program clProgram = clCreateProgramWithSourceF(
28 ✔
236
        clContext, 1, &oclSrc, nullptr, &build_with_source_err_code);
28 ✔
237

238
    if (build_with_source_err_code != CL_SUCCESS) {
28 !
239
        error_handler("clPCreateProgramWithSource failed with " +
×
240
                          _GetErrorCode_ocl_impl(build_with_source_err_code),
×
241
                      __FILE__, __func__, __LINE__);
×
242
        return nullptr;
×
243
    }
×
244

245
    return _CreateKernelBundle_common_ocl_impl(clProgram, ctx, dev,
28 ✔
246
                                               CompileOpts);
28 ✔
247
}
28 ✔
248

249
DPCTLSyclKernelBundleRef
250
_CreateKernelBundleWithIL_ocl_impl(const context &ctx,
251
                                   const device &dev,
252
                                   const void *IL,
253
                                   size_t il_length,
254
                                   const char *CompileOpts,
255
                                   size_t NumSpecConsts,
256
                                   const DPCTLSpecConst *SpecConsts)
257
{
66 ✔
258
    auto clCreateProgramWithILF = get_clCreateProgramWithIL();
66 ✔
259
    if (clCreateProgramWithILF == nullptr) {
66 !
260
        return nullptr;
×
261
    }
×
262

263
    backend_traits<cl_be>::return_type<context> clContext;
66 ✔
264
    clContext = get_native<cl_be>(ctx);
66 ✔
265

266
    cl_int create_err_code = CL_SUCCESS;
66 ✔
267
    cl_program clProgram =
66 ✔
268
        clCreateProgramWithILF(clContext, IL, il_length, &create_err_code);
66 ✔
269

270
    if (create_err_code != CL_SUCCESS) {
66 !
271
        error_handler("OpenCL program could not be created from the SPIR-V "
×
272
                      "binary. OpenCL Error " +
×
273
                          _GetErrorCode_ocl_impl(create_err_code),
×
274
                      __FILE__, __func__, __LINE__);
×
275
        return nullptr;
×
276
    }
×
277

278
    if (SpecConsts != nullptr && NumSpecConsts > 0) {
66 !
279
        auto clSetProgramSpecConstF = get_clSetProgramSpecializationConstant();
2 ✔
280
        if (clSetProgramSpecConstF) {
2 !
281
            for (size_t i = 0; i < NumSpecConsts; ++i) {
6 ✔
282
                clSetProgramSpecConstF(clProgram, SpecConsts[i].id,
4 ✔
283
                                       SpecConsts[i].size, SpecConsts[i].value);
4 ✔
284
            }
4 ✔
285
        }
2 ✔
NEW
286
        else {
×
NEW
287
            error_handler("clSetProgramSpecializationConstant is not available "
×
NEW
288
                          "in the OpenCL implementation.",
×
NEW
289
                          __FILE__, __func__, __LINE__);
×
NEW
290
            return nullptr;
×
NEW
291
        }
×
292
    }
2 ✔
293

294
    return _CreateKernelBundle_common_ocl_impl(clProgram, ctx, dev,
66 ✔
295
                                               CompileOpts);
66 ✔
296
}
66 ✔
297

298
bool _HasKernel_ocl_impl(const kernel_bundle<bundle_state::executable> &kb,
299
                         const char *kernel_name)
300
{
62 ✔
301
    auto clCreateKernelF = get_clCreateKernel();
62 ✔
302
    if (clCreateKernelF == nullptr) {
62 !
303
        return false;
×
304
    }
×
305

306
    std::vector<cl_program> oclKB = get_native<cl_be>(kb);
62 ✔
307

308
    bool found = false;
62 ✔
309
    for (auto &cl_pr : oclKB) {
62 !
310
        cl_int create_kernel_err_code = CL_SUCCESS;
62 ✔
311
        [[maybe_unused]] cl_kernel try_kern =
62 ✔
312
            clCreateKernelF(cl_pr, kernel_name, &create_kernel_err_code);
62 ✔
313
        if (create_kernel_err_code == CL_SUCCESS) {
62 !
314
            found = true;
62 ✔
315
            break;
62 ✔
316
        }
62 ✔
317
    }
62 ✔
318
    return found;
62 ✔
319
}
62 ✔
320

321
__dpctl_give DPCTLSyclKernelRef
322
_GetKernel_ocl_impl(const kernel_bundle<bundle_state::executable> &kb,
323
                    const char *kernel_name)
324
{
91 ✔
325
    auto clCreateKernelF = get_clCreateKernel();
91 ✔
326
    if (clCreateKernelF == nullptr) {
91 !
327
        return nullptr;
×
328
    }
×
329

330
    std::vector<cl_program> oclKB = get_native<cl_be>(kb);
91 ✔
331

332
    bool found = false;
91 ✔
333
    cl_kernel ocl_kernel_from_kb;
91 ✔
334
    for (auto &cl_pr : oclKB) {
91 ✔
335
        cl_int create_kernel_err_code = CL_SUCCESS;
91 ✔
336
        cl_kernel try_kern =
91 ✔
337
            clCreateKernelF(cl_pr, kernel_name, &create_kernel_err_code);
91 ✔
338
        if (create_kernel_err_code == CL_SUCCESS) {
91 ✔
339
            found = true;
90 ✔
340
            ocl_kernel_from_kb = try_kern;
90 ✔
341
            break;
90 ✔
342
        }
90 ✔
343
    }
91 ✔
344
    if (found) {
91 ✔
345
        try {
90 ✔
346
            context ctx = kb.get_context();
90 ✔
347

348
            const kernel &interop_kernel =
90 ✔
349
                make_kernel<cl_be>(ocl_kernel_from_kb, ctx);
90 ✔
350

351
            return wrap<kernel>(new kernel(interop_kernel));
90 ✔
352
        } catch (std::exception const &e) {
90 ✔
353
            error_handler(e, __FILE__, __func__, __LINE__);
×
354
            return nullptr;
×
355
        }
×
356
    }
90 ✔
357
    else {
1 ✔
358
        error_handler("Kernel " + std::string(kernel_name) + " not found.",
1 ✔
359
                      __FILE__, __func__, __LINE__);
1 ✔
360
        return nullptr;
1 ✔
361
    }
1 ✔
362
}
91 ✔
363

364
#ifdef DPCTL_ENABLE_L0_PROGRAM_CREATION
365

366
#ifdef __linux__
367
static const char *zeLoaderName = DPCTL_LIBZE_LOADER_FILENAME;
368
static const int zeLibLoadFlags = RTLD_NOLOAD | RTLD_NOW | RTLD_LOCAL;
369
#elif defined(_WIN64)
370
static const char *zeLoaderName = "ze_loader.dll";
371
static const int zeLibLoadFlags = 0;
372
#else
373
#error "Level Zero program compilation is unavailable for this platform"
374
#endif
375

376
static constexpr sycl::backend ze_be = sycl::backend::ext_oneapi_level_zero;
377

378
struct ze_loader
379
{
380
public:
381
    static ze_loader &get()
382
    {
×
383
        static ze_loader _loader;
×
384
        return _loader;
×
385
    }
×
386

387
    template <typename retTy> retTy getSymbol(const char *name)
388
    {
×
389
        if (!opened) {
×
390
            error_handler("The Level-Zero loader dynamic library could not "
×
391
                          "be opened.",
×
392
                          __FILE__, __func__, __LINE__);
×
393

394
            return nullptr;
×
395
        }
×
396
        return zeLib.getSymbol<retTy>(name);
×
397
    }
×
398

399
private:
400
    dpctl::DynamicLibHelper zeLib;
401
    bool opened;
402
    ze_loader() : zeLib(zeLoaderName, zeLibLoadFlags), opened(zeLib.opened()) {}
×
403
};
404

405
typedef ze_result_t (*zeModuleCreateFT)(ze_context_handle_t,
406
                                        ze_device_handle_t,
407
                                        const ze_module_desc_t *,
408
                                        ze_module_handle_t *,
409
                                        ze_module_build_log_handle_t *);
410
const char *zeModuleCreate_Name = "zeModuleCreate";
411
zeModuleCreateFT get_zeModuleCreate()
412
{
×
413
    static auto st_zeModuleCreateF =
×
414
        ze_loader::get().getSymbol<zeModuleCreateFT>(zeModuleCreate_Name);
×
415

416
    return st_zeModuleCreateF;
×
417
}
×
418

419
typedef ze_result_t (*zeModuleDestroyFT)(ze_module_handle_t);
420
const char *zeModuleDestroy_Name = "zeModuleDestroy";
421
zeModuleDestroyFT get_zeModuleDestroy()
422
{
×
423
    static auto st_zeModuleDestroyF =
×
424
        ze_loader::get().getSymbol<zeModuleDestroyFT>(zeModuleDestroy_Name);
×
425

426
    return st_zeModuleDestroyF;
×
427
}
×
428

429
typedef ze_result_t (*zeKernelCreateFT)(ze_module_handle_t,
430
                                        const ze_kernel_desc_t *,
431
                                        ze_kernel_handle_t *);
432
const char *zeKernelCreate_Name = "zeKernelCreate";
433
zeKernelCreateFT get_zeKernelCreate()
434
{
×
435
    static auto st_zeKernelCreateF =
×
436
        ze_loader::get().getSymbol<zeKernelCreateFT>(zeKernelCreate_Name);
×
437

438
    return st_zeKernelCreateF;
×
439
}
×
440

441
std::string _GetErrorCode_ze_impl(ze_result_t code)
442
{
×
443
    switch (code) {
×
444
        EnumCaseString(ZE_RESULT_ERROR_UNINITIALIZED);
×
445
        EnumCaseString(ZE_RESULT_ERROR_DEVICE_LOST);
×
446
        EnumCaseString(ZE_RESULT_ERROR_INVALID_NULL_HANDLE);
×
447
        EnumCaseString(ZE_RESULT_ERROR_INVALID_NULL_POINTER);
×
448
        EnumCaseString(ZE_RESULT_ERROR_INVALID_ENUMERATION);
×
449
        EnumCaseString(ZE_RESULT_ERROR_INVALID_NATIVE_BINARY);
×
450
        EnumCaseString(ZE_RESULT_ERROR_INVALID_SIZE);
×
451
        EnumCaseString(ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY);
×
452
        EnumCaseString(ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY);
×
453
        EnumCaseString(ZE_RESULT_ERROR_MODULE_BUILD_FAILURE);
×
454
        EnumCaseString(ZE_RESULT_ERROR_INVALID_MODULE_UNLINKED);
×
455
    default:
×
456
        return "<< UNRECOGNIZED ZE_RESULT_T CODE >> " + CodeStringSuffix(code);
×
457
    }
×
458
}
×
459

460
__dpctl_give DPCTLSyclKernelBundleRef
461
_CreateKernelBundleWithIL_ze_impl(const context &SyclCtx,
462
                                  const device &SyclDev,
463
                                  const void *IL,
464
                                  size_t il_length,
465
                                  const char *CompileOpts,
466
                                  size_t NumSpecConsts,
467
                                  const DPCTLSpecConst *SpecConsts)
468
{
×
469
    auto zeModuleCreateFn = get_zeModuleCreate();
×
470
    if (zeModuleCreateFn == nullptr) {
×
471
        error_handler("ZeModuleCreateFn is invalid.", __FILE__, __func__,
×
472
                      __LINE__);
×
473
        return nullptr;
×
474
    }
×
475

476
    backend_traits<ze_be>::return_type<context> ZeContext;
×
477
    ZeContext = get_native<ze_be>(SyclCtx);
×
478

479
    backend_traits<ze_be>::return_type<device> ZeDevice;
×
480
    ZeDevice = get_native<ze_be>(SyclDev);
×
481

482
    // Specialization constants are not supported by DPCTL at the moment
NEW
483
    std::vector<std::uint32_t> spec_ids;
×
NEW
484
    std::vector<const void *> spec_values;
×
485

NEW
486
    if (SpecConsts != nullptr && NumSpecConsts > 0) {
×
NEW
487
        spec_ids.reserve(NumSpecConsts);
×
NEW
488
        spec_values.reserve(NumSpecConsts);
×
NEW
489
        for (size_t i = 0; i < NumSpecConsts; ++i) {
×
NEW
490
            spec_ids.push_back(SpecConsts[i].id);
×
NEW
491
            spec_values.push_back(SpecConsts[i].value);
×
NEW
492
        }
×
NEW
493
    }
×
494
    ze_module_constants_t ZeSpecConstants = {};
×
NEW
495
    ZeSpecConstants.numConstants = static_cast<std::uint32_t>(NumSpecConsts);
×
NEW
496
    ZeSpecConstants.pConstantIds = spec_ids.empty() ? nullptr : spec_ids.data();
×
NEW
497
    ZeSpecConstants.pConstantValues =
×
NEW
498
        spec_values.empty() ? nullptr : spec_values.data();
×
499

500
    // Populate the Level Zero module descriptions
501
    ze_module_desc_t ZeModuleDesc = {};
×
502
    ZeModuleDesc.stype = ZE_STRUCTURE_TYPE_MODULE_DESC;
×
503
    ZeModuleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV;
×
504
    ZeModuleDesc.inputSize = il_length;
×
505
    ZeModuleDesc.pInputModule = (uint8_t *)IL;
×
506
    ZeModuleDesc.pBuildFlags = CompileOpts;
×
507
    ZeModuleDesc.pConstants = &ZeSpecConstants;
×
508

509
    ze_module_handle_t ZeModule;
×
510

511
    auto ret_code = zeModuleCreateFn(ZeContext, ZeDevice, &ZeModuleDesc,
×
512
                                     &ZeModule, nullptr);
×
513
    if (ret_code != ZE_RESULT_SUCCESS) {
×
514
        error_handler("Module creation failed " +
×
515
                          _GetErrorCode_ze_impl(ret_code),
×
516
                      __FILE__, __func__, __LINE__);
×
517
        return nullptr;
×
518
    }
×
519

520
    try {
×
521
        const auto &kb = make_kernel_bundle<ze_be, bundle_state::executable>(
×
522
            {ZeModule, ext::oneapi::level_zero::ownership::keep}, SyclCtx);
×
523

524
        return wrap<kernel_bundle<bundle_state::executable>>(
×
525
            new kernel_bundle<bundle_state::executable>(kb));
×
526
    } catch (std::exception const &e) {
×
527
        error_handler(e, __FILE__, __func__, __LINE__);
×
528
        auto zeModuleDestroyFn = get_zeModuleDestroy();
×
529
        if (zeModuleDestroyFn) {
×
530
            zeModuleDestroyFn(ZeModule);
×
531
        }
×
532
        return nullptr;
×
533
    }
×
534
}
×
535

536
__dpctl_give DPCTLSyclKernelRef
537
_GetKernel_ze_impl(const kernel_bundle<bundle_state::executable> &kb,
538
                   const char *kernel_name)
539
{
×
540
    auto zeKernelCreateFn = get_zeKernelCreate();
×
541
    if (zeKernelCreateFn == nullptr) {
×
542
        error_handler("Could not load zeKernelCreate function.", __FILE__,
×
543
                      __func__, __LINE__);
×
544
        return nullptr;
×
545
    }
×
546

547
    auto ZeKernelBundle = sycl::get_native<ze_be>(kb);
×
548
    bool found = false;
×
549

550
    // Populate the Level Zero kernel descriptions
551
    ze_kernel_desc_t ZeKernelDescr = {ZE_STRUCTURE_TYPE_KERNEL_DESC, nullptr,
×
552
                                      0, // flags
×
553
                                      kernel_name};
×
554

555
    std::unique_ptr<sycl::kernel> syclInteropKern_ptr;
×
556
    ze_kernel_handle_t ZeKern;
×
557
    for (auto &ZeM : ZeKernelBundle) {
×
558
        ze_result_t ze_status = zeKernelCreateFn(ZeM, &ZeKernelDescr, &ZeKern);
×
559

560
        if (ze_status == ZE_RESULT_SUCCESS) {
×
561
            found = true;
×
562
            const auto &ctx = kb.get_context();
×
563
            const auto &k = make_kernel<ze_be>(
×
564
                {kb, ZeKern, ext::oneapi::level_zero::ownership::keep}, ctx);
×
565
            syclInteropKern_ptr = std::unique_ptr<kernel>(new kernel(k));
×
566
            break;
×
567
        }
×
568
        else {
×
569
            if (ze_status != ZE_RESULT_ERROR_INVALID_KERNEL_NAME) {
×
570
                error_handler("zeKernelCreate failed: " +
×
571
                                  _GetErrorCode_ze_impl(ze_status),
×
572
                              __FILE__, __func__, __LINE__);
×
573
                return nullptr;
×
574
            }
×
575
        }
×
576
    }
×
577

578
    if (found) {
×
579
        return wrap<kernel>(new kernel(*syclInteropKern_ptr));
×
580
    }
×
581
    else {
×
582
        error_handler("Kernel named " + std::string(kernel_name) +
×
583
                          " could not be found.",
×
584
                      __FILE__, __func__, __LINE__, error_level::error);
×
585
        return nullptr;
×
586
    }
×
587
}
×
588

589
bool _HasKernel_ze_impl(const kernel_bundle<bundle_state::executable> &kb,
590
                        const char *kernel_name)
591
{
×
592
    auto zeKernelCreateFn = get_zeKernelCreate();
×
593
    if (zeKernelCreateFn == nullptr) {
×
594
        error_handler("Could not load zeKernelCreate function.", __FILE__,
×
595
                      __func__, __LINE__, error_level::error);
×
596
        return false;
×
597
    }
×
598

599
    auto ZeKernelBundle = sycl::get_native<ze_be>(kb);
×
600

601
    // Populate the Level Zero kernel descriptions
602
    ze_kernel_desc_t ZeKernelDescr = {ZE_STRUCTURE_TYPE_KERNEL_DESC, nullptr,
×
603
                                      0, // flags
×
604
                                      kernel_name};
×
605

606
    std::unique_ptr<sycl::kernel> syclInteropKern_ptr;
×
607
    ze_kernel_handle_t ZeKern;
×
608
    for (auto &ZeM : ZeKernelBundle) {
×
609
        ze_result_t ze_status = zeKernelCreateFn(ZeM, &ZeKernelDescr, &ZeKern);
×
610

611
        if (ze_status == ZE_RESULT_SUCCESS) {
×
612
            return true;
×
613
        }
×
614
        else {
×
615
            if (ze_status != ZE_RESULT_ERROR_INVALID_KERNEL_NAME) {
×
616
                error_handler("zeKernelCreate failed: " +
×
617
                                  _GetErrorCode_ze_impl(ze_status),
×
618
                              __FILE__, __func__, __LINE__, error_level::error);
×
619
                return false;
×
620
            }
×
621
        }
×
622
    }
×
623

624
    return false;
×
625
}
×
626

627
#endif /* #ifdef DPCTL_ENABLE_L0_PROGRAM_CREATION */
628

629
} /* end of anonymous namespace */
630

631
__dpctl_give DPCTLSyclKernelBundleRef
632
DPCTLKernelBundle_CreateFromSpirv(__dpctl_keep const DPCTLSyclContextRef CtxRef,
633
                                  __dpctl_keep const DPCTLSyclDeviceRef DevRef,
634
                                  __dpctl_keep const void *IL,
635
                                  size_t length,
636
                                  const char *CompileOpts,
637
                                  size_t NumSpecConsts,
638
                                  const DPCTLSpecConst *SpecConsts)
639
{
75 ✔
640
    DPCTLSyclKernelBundleRef KBRef = nullptr;
75 ✔
641
    if (!CtxRef) {
75 ✔
642
        error_handler("Cannot create program from SPIR-V as the supplied SYCL "
3 ✔
643
                      "context is NULL.",
3 ✔
644
                      __FILE__, __func__, __LINE__);
3 ✔
645
        return KBRef;
3 ✔
646
    }
3 ✔
647
    if (!DevRef) {
72 ✔
648
        error_handler("Cannot create program from SPIR-V as the supplied SYCL "
3 ✔
649
                      "device is NULL.",
3 ✔
650
                      __FILE__, __func__, __LINE__);
3 ✔
651
        return KBRef;
3 ✔
652
    }
3 ✔
653
    if ((!IL) || (length == 0)) {
69 !
654
        error_handler("Cannot create program from null SPIR-V buffer.",
3 ✔
655
                      __FILE__, __func__, __LINE__);
3 ✔
656
        return KBRef;
3 ✔
657
    }
3 ✔
658

659
    context *SyclCtx = unwrap<context>(CtxRef);
66 ✔
660
    device *SyclDev = unwrap<device>(DevRef);
66 ✔
661
    // get the backend type
662
    auto BE = SyclCtx->get_platform().get_backend();
66 ✔
663
    switch (BE) {
66 ✔
664
    case backend::opencl:
66 !
665
        KBRef = _CreateKernelBundleWithIL_ocl_impl(*SyclCtx, *SyclDev, IL,
66 ✔
666
                                                   length, CompileOpts,
66 ✔
667
                                                   NumSpecConsts, SpecConsts);
66 ✔
668
        break;
66 ✔
669
    case backend::ext_oneapi_level_zero:
×
670
#ifdef DPCTL_ENABLE_L0_PROGRAM_CREATION
×
671
        KBRef = _CreateKernelBundleWithIL_ze_impl(*SyclCtx, *SyclDev, IL,
×
NEW
672
                                                  length, CompileOpts,
×
NEW
673
                                                  NumSpecConsts, SpecConsts);
×
674
        break;
×
675
#endif
×
676
    default:
×
677
        std::ostringstream os;
×
678
        os << "Backend " << BE << " is not supported";
×
679
        error_handler(os.str(), __FILE__, __func__, __LINE__);
×
680
        break;
×
681
    }
66 ✔
682
    return KBRef;
66 ✔
683
}
66 ✔
684

685
__dpctl_give DPCTLSyclKernelBundleRef DPCTLKernelBundle_CreateFromOCLSource(
686
    __dpctl_keep const DPCTLSyclContextRef Ctx,
687
    __dpctl_keep const DPCTLSyclDeviceRef Dev,
688
    __dpctl_keep const char *Source,
689
    __dpctl_keep const char *CompileOpts)
690
{
39 ✔
691
    context *SyclCtx = nullptr;
39 ✔
692
    device *SyclDev = nullptr;
39 ✔
693

694
    if (!Ctx) {
39 ✔
695
        error_handler("Input Ctx is nullptr.", __FILE__, __func__, __LINE__);
10 ✔
696
        return nullptr;
10 ✔
697
    }
10 ✔
698
    if (!Dev) {
29 ✔
699
        error_handler("Input Dev is nullptr.", __FILE__, __func__, __LINE__);
1 ✔
700
        return nullptr;
1 ✔
701
    }
1 ✔
702
    if (!Source) {
28 !
703
        error_handler("Input Source is nullptr.", __FILE__, __func__, __LINE__);
×
704
        return nullptr;
×
705
    }
×
706

707
    SyclCtx = unwrap<context>(Ctx);
28 ✔
708
    SyclDev = unwrap<device>(Dev);
28 ✔
709

710
    // get the backend type
711
    auto BE = SyclCtx->get_platform().get_backend();
28 ✔
712
    switch (BE) {
28 ✔
713
    case backend::opencl:
28 !
714
        try {
28 ✔
715
            return _CreateKernelBundleWithOCLSource_ocl_impl(
28 ✔
716
                *SyclCtx, *SyclDev, Source, CompileOpts);
28 ✔
717
        } catch (std::exception const &e) {
28 ✔
718
            error_handler(e, __FILE__, __func__, __LINE__);
×
719
            return nullptr;
×
720
        }
×
721
        break;
×
722
    case backend::ext_oneapi_level_zero:
×
723
        error_handler(
×
724
            "CreateFromSource is not supported for Level Zero backend.",
×
725
            __FILE__, __func__, __LINE__);
×
726
        return nullptr;
×
727
    default:
×
728
        error_handler("CreateFromSource is not supported in unknown backend.",
×
729
                      __FILE__, __func__, __LINE__);
×
730
        return nullptr;
×
731
    }
28 ✔
732
}
28 ✔
733

734
__dpctl_give DPCTLSyclKernelRef
735
DPCTLKernelBundle_GetKernel(__dpctl_keep DPCTLSyclKernelBundleRef KBRef,
736
                            __dpctl_keep const char *KernelName)
737
{
115 ✔
738
    if (!KBRef) {
115 ✔
739
        error_handler("Input KBRef is nullptr", __FILE__, __func__, __LINE__);
21 ✔
740
        return nullptr;
21 ✔
741
    }
21 ✔
742
    if (!KernelName) {
94 ✔
743
        error_handler("Input KernelName is nullptr", __FILE__, __func__,
3 ✔
744
                      __LINE__);
3 ✔
745
        return nullptr;
3 ✔
746
    }
3 ✔
747
    auto SyclKB = unwrap<kernel_bundle<bundle_state::executable>>(KBRef);
91 ✔
748
    sycl::backend be = SyclKB->get_backend();
91 ✔
749
    switch (be) {
91 ✔
750
    case sycl::backend::opencl:
91 !
751
        return _GetKernel_ocl_impl(*SyclKB, KernelName);
91 ✔
752
    case sycl::backend::ext_oneapi_level_zero:
×
753
#ifdef DPCTL_ENABLE_L0_PROGRAM_CREATION
×
754
        return _GetKernel_ze_impl(*SyclKB, KernelName);
×
755
#endif
×
756
    default:
×
757
        std::ostringstream os;
×
758
        os << "Backend " << be << " is not supported";
×
759
        error_handler(os.str(), __FILE__, __func__, __LINE__);
×
760
        return nullptr;
×
761
    }
91 ✔
762
}
91 ✔
763

764
bool DPCTLKernelBundle_HasKernel(__dpctl_keep DPCTLSyclKernelBundleRef KBRef,
765
                                 __dpctl_keep const char *KernelName)
766
{
68 ✔
767
    if (!KBRef) {
68 ✔
768
        error_handler("Input KBRef is nullptr", __FILE__, __func__, __LINE__);
3 ✔
769
        return false;
3 ✔
770
    }
3 ✔
771
    if (!KernelName) {
65 ✔
772
        error_handler("Input KernelName is nullptr", __FILE__, __func__,
3 ✔
773
                      __LINE__);
3 ✔
774
        return false;
3 ✔
775
    }
3 ✔
776

777
    auto SyclKB = unwrap<kernel_bundle<bundle_state::executable>>(KBRef);
62 ✔
778
    sycl::backend be = SyclKB->get_backend();
62 ✔
779
    switch (be) {
62 ✔
780
    case sycl::backend::opencl:
62 !
781
        return _HasKernel_ocl_impl(*SyclKB, KernelName);
62 ✔
782
    case sycl::backend::ext_oneapi_level_zero:
×
783
#ifdef DPCTL_ENABLE_L0_PROGRAM_CREATION
×
784
        return _HasKernel_ze_impl(*SyclKB, KernelName);
×
785
#endif
×
786
    default:
×
787
        std::ostringstream os;
×
788
        os << "Backend " << be << " is not supported";
×
789
        error_handler(os.str(), __FILE__, __func__, __LINE__);
×
790
        return false;
×
791
    }
62 ✔
792
}
62 ✔
793

794
void DPCTLKernelBundle_Delete(__dpctl_take DPCTLSyclKernelBundleRef KBRef)
795
{
106 ✔
796
    delete unwrap<kernel_bundle<bundle_state::executable>>(KBRef);
106 ✔
797
}
106 ✔
798

799
__dpctl_give DPCTLSyclKernelBundleRef
800
DPCTLKernelBundle_Copy(__dpctl_keep const DPCTLSyclKernelBundleRef KBRef)
801
{
8 ✔
802
    auto Bundle = unwrap<kernel_bundle<bundle_state::executable>>(KBRef);
8 ✔
803
    if (!Bundle) {
8 ✔
804
        error_handler(
3 ✔
805
            "Cannot copy DPCTLSyclKernelBundleRef as input is a nullptr",
3 ✔
806
            __FILE__, __func__, __LINE__);
3 ✔
807
        return nullptr;
3 ✔
808
    }
3 ✔
809
    try {
5 ✔
810
        auto CopiedBundle =
5 ✔
811
            new kernel_bundle<bundle_state::executable>(*Bundle);
5 ✔
812
        return wrap<kernel_bundle<bundle_state::executable>>(CopiedBundle);
5 ✔
813
    } catch (std::exception const &e) {
5 ✔
814
        error_handler(e, __FILE__, __func__, __LINE__);
×
815
        return nullptr;
×
816
    }
×
817
}
5 ✔
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