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

IntelPython / dpctl / 14754782295

30 Apr 2025 12:39PM UTC coverage: 86.419%. Remained the same
14754782295

Pull #2068

github

web-flow
Merge c8700ceb2 into b7a6b67c7
Pull Request #2068: Correct a path to `cl.cfg` file

3020 of 3716 branches covered (81.27%)

Branch coverage included in aggregate %.

12195 of 13890 relevant lines covered (87.8%)

6998.91 hits per line

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

44.15
/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 <sstream>
35
#include <stddef.h>
36
#include <sycl/backend/opencl.hpp>
37
#include <sycl/sycl.hpp> /* Sycl headers       */
38
#include <utility>
39

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

49
using namespace sycl;
50

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

56
using namespace dpctl::syclinterface;
57

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

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

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

75
constexpr backend cl_be = backend::opencl;
76

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

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

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

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

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

116
    return st_clCreateProgramWithSourceF;
28✔
117
}
28✔
118

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

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

144
    return st_clBuildProgramF;
82✔
145
}
82✔
146

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

154
    return st_clCreateKernelF;
131✔
155
}
131✔
156

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

173
DPCTLSyclKernelBundleRef
174
_CreateKernelBundle_common_ocl_impl(cl_program clProgram,
175
                                    const context &ctx,
176
                                    const device &dev,
177
                                    const char *CompileOpts)
178
{
82✔
179
    backend_traits<cl_be>::return_type<device> clDevice;
82✔
180
    clDevice = get_native<cl_be>(dev);
82✔
181

182
    // Last two pointers are notification function pointer and user-data pointer
183
    // that can be passed to the notification function.
184
    auto clBuildProgramF = get_clBuldProgram();
82✔
185
    if (clBuildProgramF == nullptr) {
82!
186
        return nullptr;
×
187
    }
×
188
    cl_int build_status =
82✔
189
        clBuildProgramF(clProgram, 1, &clDevice, CompileOpts, nullptr, nullptr);
82✔
190

191
    if (build_status != CL_SUCCESS) {
82✔
192
        error_handler("clBuildProgram failed: " +
2✔
193
                          _GetErrorCode_ocl_impl(build_status),
2✔
194
                      __FILE__, __func__, __LINE__);
2✔
195
        return nullptr;
2✔
196
    }
2✔
197

198
    using ekbTy = kernel_bundle<bundle_state::executable>;
80✔
199
    const ekbTy &kb =
80✔
200
        make_kernel_bundle<cl_be, bundle_state::executable>(clProgram, ctx);
80✔
201
    return wrap<ekbTy>(new ekbTy(kb));
80✔
202
}
82✔
203

204
DPCTLSyclKernelBundleRef
205
_CreateKernelBundleWithOCLSource_ocl_impl(const context &ctx,
206
                                          const device &dev,
207
                                          const char *oclSrc,
208
                                          const char *CompileOpts)
209
{
28✔
210
    auto clCreateProgramWithSourceF = get_clCreateProgramWithSource();
28✔
211
    if (clCreateProgramWithSourceF == nullptr) {
28!
212
        return nullptr;
×
213
    }
×
214

215
    backend_traits<cl_be>::return_type<context> clContext;
28✔
216
    clContext = get_native<cl_be>(ctx);
28✔
217

218
    cl_int build_with_source_err_code = CL_SUCCESS;
28✔
219
    cl_program clProgram = clCreateProgramWithSourceF(
28✔
220
        clContext, 1, &oclSrc, nullptr, &build_with_source_err_code);
28✔
221

222
    if (build_with_source_err_code != CL_SUCCESS) {
28!
223
        error_handler("clPCreateProgramWithSource failed with " +
×
224
                          _GetErrorCode_ocl_impl(build_with_source_err_code),
×
225
                      __FILE__, __func__, __LINE__);
×
226
        return nullptr;
×
227
    }
×
228

229
    return _CreateKernelBundle_common_ocl_impl(clProgram, ctx, dev,
28✔
230
                                               CompileOpts);
28✔
231
}
28✔
232

233
DPCTLSyclKernelBundleRef
234
_CreateKernelBundleWithIL_ocl_impl(const context &ctx,
235
                                   const device &dev,
236
                                   const void *IL,
237
                                   size_t il_length,
238
                                   const char *CompileOpts)
239
{
54✔
240
    auto clCreateProgramWithILF = get_clCreateProgramWithIL();
54✔
241
    if (clCreateProgramWithILF == nullptr) {
54!
242
        return nullptr;
×
243
    }
×
244

245
    backend_traits<cl_be>::return_type<context> clContext;
54✔
246
    clContext = get_native<cl_be>(ctx);
54✔
247

248
    cl_int create_err_code = CL_SUCCESS;
54✔
249
    cl_program clProgram =
54✔
250
        clCreateProgramWithILF(clContext, IL, il_length, &create_err_code);
54✔
251

252
    if (create_err_code != CL_SUCCESS) {
54!
253
        error_handler("OpenCL program could not be created from the SPIR-V "
×
254
                      "binary. OpenCL Error " +
×
255
                          _GetErrorCode_ocl_impl(create_err_code),
×
256
                      __FILE__, __func__, __LINE__);
×
257
        return nullptr;
×
258
    }
×
259

260
    return _CreateKernelBundle_common_ocl_impl(clProgram, ctx, dev,
54✔
261
                                               CompileOpts);
54✔
262
}
54✔
263

264
bool _HasKernel_ocl_impl(const kernel_bundle<bundle_state::executable> &kb,
265
                         const char *kernel_name)
266
{
52✔
267
    auto clCreateKernelF = get_clCreateKernel();
52✔
268
    if (clCreateKernelF == nullptr) {
52!
269
        return false;
×
270
    }
×
271

272
    std::vector<cl_program> oclKB = get_native<cl_be>(kb);
52✔
273

274
    bool found = false;
52✔
275
    for (auto &cl_pr : oclKB) {
52!
276
        cl_int create_kernel_err_code = CL_SUCCESS;
52✔
277
        [[maybe_unused]] cl_kernel try_kern =
52✔
278
            clCreateKernelF(cl_pr, kernel_name, &create_kernel_err_code);
52✔
279
        if (create_kernel_err_code == CL_SUCCESS) {
52!
280
            found = true;
52✔
281
            break;
52✔
282
        }
52✔
283
    }
52✔
284
    return found;
52✔
285
}
52✔
286

287
__dpctl_give DPCTLSyclKernelRef
288
_GetKernel_ocl_impl(const kernel_bundle<bundle_state::executable> &kb,
289
                    const char *kernel_name)
290
{
79✔
291
    auto clCreateKernelF = get_clCreateKernel();
79✔
292
    if (clCreateKernelF == nullptr) {
79!
293
        return nullptr;
×
294
    }
×
295

296
    std::vector<cl_program> oclKB = get_native<cl_be>(kb);
79✔
297

298
    bool found = false;
79✔
299
    cl_kernel ocl_kernel_from_kb;
79✔
300
    for (auto &cl_pr : oclKB) {
79✔
301
        cl_int create_kernel_err_code = CL_SUCCESS;
79✔
302
        cl_kernel try_kern =
79✔
303
            clCreateKernelF(cl_pr, kernel_name, &create_kernel_err_code);
79✔
304
        if (create_kernel_err_code == CL_SUCCESS) {
79✔
305
            found = true;
78✔
306
            ocl_kernel_from_kb = try_kern;
78✔
307
            break;
78✔
308
        }
78✔
309
    }
79✔
310
    if (found) {
79✔
311
        try {
78✔
312
            context ctx = kb.get_context();
78✔
313

314
            const kernel &interop_kernel =
78✔
315
                make_kernel<cl_be>(ocl_kernel_from_kb, ctx);
78✔
316

317
            return wrap<kernel>(new kernel(interop_kernel));
78✔
318
        } catch (std::exception const &e) {
78✔
319
            error_handler(e, __FILE__, __func__, __LINE__);
×
320
            return nullptr;
×
321
        }
×
322
    }
78✔
323
    else {
1✔
324
        error_handler("Kernel " + std::string(kernel_name) + " not found.",
1✔
325
                      __FILE__, __func__, __LINE__);
1✔
326
        return nullptr;
1✔
327
    }
1✔
328
}
79✔
329

330
#ifdef DPCTL_ENABLE_L0_PROGRAM_CREATION
331

332
#ifdef __linux__
333
static const char *zeLoaderName = DPCTL_LIBZE_LOADER_FILENAME;
334
static const int zeLibLoadFlags = RTLD_NOLOAD | RTLD_NOW | RTLD_LOCAL;
335
#elif defined(_WIN64)
336
static const char *zeLoaderName = "ze_loader.dll";
337
static const int zeLibLoadFlags = 0;
338
#else
339
#error "Level Zero program compilation is unavailable for this platform"
340
#endif
341

342
constexpr sycl::backend ze_be = sycl::backend::ext_oneapi_level_zero;
343

344
struct ze_loader
345
{
346
public:
347
    static ze_loader &get()
348
    {
×
349
        static ze_loader _loader;
×
350
        return _loader;
×
351
    }
×
352

353
    template <typename retTy> retTy getSymbol(const char *name)
354
    {
×
355
        if (!opened) {
×
356
            error_handler("The Level-Zero loader dynamic library could not "
×
357
                          "be opened.",
×
358
                          __FILE__, __func__, __LINE__);
×
359

360
            return nullptr;
×
361
        }
×
362
        return zeLib.getSymbol<retTy>(name);
×
363
    }
×
364

365
private:
366
    dpctl::DynamicLibHelper zeLib;
367
    bool opened;
368
    ze_loader() : zeLib(zeLoaderName, zeLibLoadFlags), opened(zeLib.opened()) {}
×
369
};
370

371
typedef ze_result_t (*zeModuleCreateFT)(ze_context_handle_t,
372
                                        ze_device_handle_t,
373
                                        const ze_module_desc_t *,
374
                                        ze_module_handle_t *,
375
                                        ze_module_build_log_handle_t *);
376
const char *zeModuleCreate_Name = "zeModuleCreate";
377
zeModuleCreateFT get_zeModuleCreate()
378
{
×
379
    static auto st_zeModuleCreateF =
×
380
        ze_loader::get().getSymbol<zeModuleCreateFT>(zeModuleCreate_Name);
×
381

382
    return st_zeModuleCreateF;
×
383
}
×
384

385
typedef ze_result_t (*zeModuleDestroyFT)(ze_module_handle_t);
386
const char *zeModuleDestroy_Name = "zeModuleDestroy";
387
zeModuleDestroyFT get_zeModuleDestroy()
388
{
×
389
    static auto st_zeModuleDestroyF =
×
390
        ze_loader::get().getSymbol<zeModuleDestroyFT>(zeModuleDestroy_Name);
×
391

392
    return st_zeModuleDestroyF;
×
393
}
×
394

395
typedef ze_result_t (*zeKernelCreateFT)(ze_module_handle_t,
396
                                        const ze_kernel_desc_t *,
397
                                        ze_kernel_handle_t *);
398
const char *zeKernelCreate_Name = "zeKernelCreate";
399
zeKernelCreateFT get_zeKernelCreate()
400
{
×
401
    static auto st_zeKernelCreateF =
×
402
        ze_loader::get().getSymbol<zeKernelCreateFT>(zeKernelCreate_Name);
×
403

404
    return st_zeKernelCreateF;
×
405
}
×
406

407
std::string _GetErrorCode_ze_impl(ze_result_t code)
408
{
×
409
    switch (code) {
×
410
        EnumCaseString(ZE_RESULT_ERROR_UNINITIALIZED);
×
411
        EnumCaseString(ZE_RESULT_ERROR_DEVICE_LOST);
×
412
        EnumCaseString(ZE_RESULT_ERROR_INVALID_NULL_HANDLE);
×
413
        EnumCaseString(ZE_RESULT_ERROR_INVALID_NULL_POINTER);
×
414
        EnumCaseString(ZE_RESULT_ERROR_INVALID_ENUMERATION);
×
415
        EnumCaseString(ZE_RESULT_ERROR_INVALID_NATIVE_BINARY);
×
416
        EnumCaseString(ZE_RESULT_ERROR_INVALID_SIZE);
×
417
        EnumCaseString(ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY);
×
418
        EnumCaseString(ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY);
×
419
        EnumCaseString(ZE_RESULT_ERROR_MODULE_BUILD_FAILURE);
×
420
        EnumCaseString(ZE_RESULT_ERROR_INVALID_MODULE_UNLINKED);
×
421
    default:
×
422
        return "<< UNRECOGNIZED ZE_RESULT_T CODE >> " + CodeStringSuffix(code);
×
423
    }
×
424
}
×
425

426
__dpctl_give DPCTLSyclKernelBundleRef
427
_CreateKernelBundleWithIL_ze_impl(const context &SyclCtx,
428
                                  const device &SyclDev,
429
                                  const void *IL,
430
                                  size_t il_length,
431
                                  const char *CompileOpts)
432
{
×
433
    auto zeModuleCreateFn = get_zeModuleCreate();
×
434
    if (zeModuleCreateFn == nullptr) {
×
435
        error_handler("ZeModuleCreateFn is invalid.", __FILE__, __func__,
×
436
                      __LINE__);
×
437
        return nullptr;
×
438
    }
×
439

440
    backend_traits<ze_be>::return_type<context> ZeContext;
×
441
    ZeContext = get_native<ze_be>(SyclCtx);
×
442

443
    backend_traits<ze_be>::return_type<device> ZeDevice;
×
444
    ZeDevice = get_native<ze_be>(SyclDev);
×
445

446
    // Specialization constants are not supported by DPCTL at the moment
447
    ze_module_constants_t ZeSpecConstants = {};
×
448
    ZeSpecConstants.numConstants = 0;
×
449

450
    // Populate the Level Zero module descriptions
451
    ze_module_desc_t ZeModuleDesc = {};
×
452
    ZeModuleDesc.stype = ZE_STRUCTURE_TYPE_MODULE_DESC;
×
453
    ZeModuleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV;
×
454
    ZeModuleDesc.inputSize = il_length;
×
455
    ZeModuleDesc.pInputModule = (uint8_t *)IL;
×
456
    ZeModuleDesc.pBuildFlags = CompileOpts;
×
457
    ZeModuleDesc.pConstants = &ZeSpecConstants;
×
458

459
    ze_module_handle_t ZeModule;
×
460

461
    auto ret_code = zeModuleCreateFn(ZeContext, ZeDevice, &ZeModuleDesc,
×
462
                                     &ZeModule, nullptr);
×
463
    if (ret_code != ZE_RESULT_SUCCESS) {
×
464
        error_handler("Module creation failed " +
×
465
                          _GetErrorCode_ze_impl(ret_code),
×
466
                      __FILE__, __func__, __LINE__);
×
467
        return nullptr;
×
468
    }
×
469

470
    try {
×
471
        const auto &kb = make_kernel_bundle<ze_be, bundle_state::executable>(
×
472
            {ZeModule, ext::oneapi::level_zero::ownership::keep}, SyclCtx);
×
473

474
        return wrap<kernel_bundle<bundle_state::executable>>(
×
475
            new kernel_bundle<bundle_state::executable>(kb));
×
476
    } catch (std::exception const &e) {
×
477
        error_handler(e, __FILE__, __func__, __LINE__);
×
478
        auto zeModuleDestroyFn = get_zeModuleDestroy();
×
479
        if (zeModuleDestroyFn) {
×
480
            zeModuleDestroyFn(ZeModule);
×
481
        }
×
482
        return nullptr;
×
483
    }
×
484
}
×
485

486
__dpctl_give DPCTLSyclKernelRef
487
_GetKernel_ze_impl(const kernel_bundle<bundle_state::executable> &kb,
488
                   const char *kernel_name)
489
{
×
490
    auto zeKernelCreateFn = get_zeKernelCreate();
×
491
    if (zeKernelCreateFn == nullptr) {
×
492
        error_handler("Could not load zeKernelCreate function.", __FILE__,
×
493
                      __func__, __LINE__);
×
494
        return nullptr;
×
495
    }
×
496

497
    auto ZeKernelBundle = sycl::get_native<ze_be>(kb);
×
498
    bool found = false;
×
499

500
    // Populate the Level Zero kernel descriptions
501
    ze_kernel_desc_t ZeKernelDescr = {ZE_STRUCTURE_TYPE_KERNEL_DESC, nullptr,
×
502
                                      0, // flags
×
503
                                      kernel_name};
×
504

505
    std::unique_ptr<sycl::kernel> syclInteropKern_ptr;
×
506
    ze_kernel_handle_t ZeKern;
×
507
    for (auto &ZeM : ZeKernelBundle) {
×
508
        ze_result_t ze_status = zeKernelCreateFn(ZeM, &ZeKernelDescr, &ZeKern);
×
509

510
        if (ze_status == ZE_RESULT_SUCCESS) {
×
511
            found = true;
×
512
            const auto &ctx = kb.get_context();
×
513
            const auto &k = make_kernel<ze_be>(
×
514
                {kb, ZeKern, ext::oneapi::level_zero::ownership::keep}, ctx);
×
515
            syclInteropKern_ptr = std::unique_ptr<kernel>(new kernel(k));
×
516
            break;
×
517
        }
×
518
        else {
×
519
            if (ze_status != ZE_RESULT_ERROR_INVALID_KERNEL_NAME) {
×
520
                error_handler("zeKernelCreate failed: " +
×
521
                                  _GetErrorCode_ze_impl(ze_status),
×
522
                              __FILE__, __func__, __LINE__);
×
523
                return nullptr;
×
524
            }
×
525
        }
×
526
    }
×
527

528
    if (found) {
×
529
        return wrap<kernel>(new kernel(*syclInteropKern_ptr));
×
530
    }
×
531
    else {
×
532
        error_handler("Kernel named " + std::string(kernel_name) +
×
533
                          " could not be found.",
×
534
                      __FILE__, __func__, __LINE__, error_level::error);
×
535
        return nullptr;
×
536
    }
×
537
}
×
538

539
bool _HasKernel_ze_impl(const kernel_bundle<bundle_state::executable> &kb,
540
                        const char *kernel_name)
541
{
×
542
    auto zeKernelCreateFn = get_zeKernelCreate();
×
543
    if (zeKernelCreateFn == nullptr) {
×
544
        error_handler("Could not load zeKernelCreate function.", __FILE__,
×
545
                      __func__, __LINE__, error_level::error);
×
546
        return false;
×
547
    }
×
548

549
    auto ZeKernelBundle = sycl::get_native<ze_be>(kb);
×
550

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

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

561
        if (ze_status == ZE_RESULT_SUCCESS) {
×
562
            return true;
×
563
        }
×
564
        else {
×
565
            if (ze_status != ZE_RESULT_ERROR_INVALID_KERNEL_NAME) {
×
566
                error_handler("zeKernelCreate failed: " +
×
567
                                  _GetErrorCode_ze_impl(ze_status),
×
568
                              __FILE__, __func__, __LINE__, error_level::error);
×
569
                return false;
×
570
            }
×
571
        }
×
572
    }
×
573

574
    return false;
×
575
}
×
576

577
#endif /* #ifdef DPCTL_ENABLE_L0_PROGRAM_CREATION */
578

579
} /* end of anonymous namespace */
580

581
__dpctl_give DPCTLSyclKernelBundleRef
582
DPCTLKernelBundle_CreateFromSpirv(__dpctl_keep const DPCTLSyclContextRef CtxRef,
583
                                  __dpctl_keep const DPCTLSyclDeviceRef DevRef,
584
                                  __dpctl_keep const void *IL,
585
                                  size_t length,
586
                                  const char *CompileOpts)
587
{
63✔
588
    DPCTLSyclKernelBundleRef KBRef = nullptr;
63✔
589
    if (!CtxRef) {
63✔
590
        error_handler("Cannot create program from SPIR-V as the supplied SYCL "
3✔
591
                      "context is NULL.",
3✔
592
                      __FILE__, __func__, __LINE__);
3✔
593
        return KBRef;
3✔
594
    }
3✔
595
    if (!DevRef) {
60✔
596
        error_handler("Cannot create program from SPIR-V as the supplied SYCL "
3✔
597
                      "device is NULL.",
3✔
598
                      __FILE__, __func__, __LINE__);
3✔
599
        return KBRef;
3✔
600
    }
3✔
601
    if ((!IL) || (length == 0)) {
57!
602
        error_handler("Cannot create program from null SPIR-V buffer.",
3✔
603
                      __FILE__, __func__, __LINE__);
3✔
604
        return KBRef;
3✔
605
    }
3✔
606

607
    context *SyclCtx = unwrap<context>(CtxRef);
54✔
608
    device *SyclDev = unwrap<device>(DevRef);
54✔
609
    // get the backend type
610
    auto BE = SyclCtx->get_platform().get_backend();
54✔
611
    switch (BE) {
54✔
612
    case backend::opencl:
54!
613
        KBRef = _CreateKernelBundleWithIL_ocl_impl(*SyclCtx, *SyclDev, IL,
54✔
614
                                                   length, CompileOpts);
54✔
615
        break;
54✔
616
    case backend::ext_oneapi_level_zero:
×
617
#ifdef DPCTL_ENABLE_L0_PROGRAM_CREATION
×
618
        KBRef = _CreateKernelBundleWithIL_ze_impl(*SyclCtx, *SyclDev, IL,
×
619
                                                  length, CompileOpts);
×
620
        break;
×
621
#endif
×
622
    default:
×
623
        error_handler("Backend " + std::to_string(static_cast<int>(BE)) +
×
624
                          " is not supported",
×
625
                      __FILE__, __func__, __LINE__);
×
626
        break;
×
627
    }
54✔
628
    return KBRef;
54✔
629
}
54✔
630

631
__dpctl_give DPCTLSyclKernelBundleRef DPCTLKernelBundle_CreateFromOCLSource(
632
    __dpctl_keep const DPCTLSyclContextRef Ctx,
633
    __dpctl_keep const DPCTLSyclDeviceRef Dev,
634
    __dpctl_keep const char *Source,
635
    __dpctl_keep const char *CompileOpts)
636
{
39✔
637
    context *SyclCtx = nullptr;
39✔
638
    device *SyclDev = nullptr;
39✔
639

640
    if (!Ctx) {
39✔
641
        error_handler("Input Ctx is nullptr.", __FILE__, __func__, __LINE__);
10✔
642
        return nullptr;
10✔
643
    }
10✔
644
    if (!Dev) {
29✔
645
        error_handler("Input Dev is nullptr.", __FILE__, __func__, __LINE__);
1✔
646
        return nullptr;
1✔
647
    }
1✔
648
    if (!Source) {
28!
649
        error_handler("Input Source is nullptr.", __FILE__, __func__, __LINE__);
×
650
        return nullptr;
×
651
    }
×
652

653
    SyclCtx = unwrap<context>(Ctx);
28✔
654
    SyclDev = unwrap<device>(Dev);
28✔
655

656
    // get the backend type
657
    auto BE = SyclCtx->get_platform().get_backend();
28✔
658
    switch (BE) {
28✔
659
    case backend::opencl:
28!
660
        try {
28✔
661
            return _CreateKernelBundleWithOCLSource_ocl_impl(
28✔
662
                *SyclCtx, *SyclDev, Source, CompileOpts);
28✔
663
        } catch (std::exception const &e) {
28✔
664
            error_handler(e, __FILE__, __func__, __LINE__);
×
665
            return nullptr;
×
666
        }
×
667
        break;
×
668
    case backend::ext_oneapi_level_zero:
×
669
        error_handler(
×
670
            "CreateFromSource is not supported for Level Zero backend.",
×
671
            __FILE__, __func__, __LINE__);
×
672
        return nullptr;
×
673
    default:
×
674
        error_handler("CreateFromSource is not supported in unknown backend.",
×
675
                      __FILE__, __func__, __LINE__);
×
676
        return nullptr;
×
677
    }
28✔
678
}
28✔
679

680
__dpctl_give DPCTLSyclKernelRef
681
DPCTLKernelBundle_GetKernel(__dpctl_keep DPCTLSyclKernelBundleRef KBRef,
682
                            __dpctl_keep const char *KernelName)
683
{
103✔
684
    if (!KBRef) {
103✔
685
        error_handler("Input KBRef is nullptr", __FILE__, __func__, __LINE__);
21✔
686
        return nullptr;
21✔
687
    }
21✔
688
    if (!KernelName) {
82✔
689
        error_handler("Input KernelName is nullptr", __FILE__, __func__,
3✔
690
                      __LINE__);
3✔
691
        return nullptr;
3✔
692
    }
3✔
693
    auto SyclKB = unwrap<kernel_bundle<bundle_state::executable>>(KBRef);
79✔
694
    sycl::backend be = SyclKB->get_backend();
79✔
695
    switch (be) {
79✔
696
    case sycl::backend::opencl:
79!
697
        return _GetKernel_ocl_impl(*SyclKB, KernelName);
79✔
698
    case sycl::backend::ext_oneapi_level_zero:
×
699
#ifdef DPCTL_ENABLE_L0_PROGRAM_CREATION
×
700
        return _GetKernel_ze_impl(*SyclKB, KernelName);
×
701
#endif
×
702
    default:
×
703
        error_handler("Backend " + std::to_string(static_cast<int>(be)) +
×
704
                          " is not supported.",
×
705
                      __FILE__, __func__, __LINE__);
×
706
        return nullptr;
×
707
    }
79✔
708
}
79✔
709

710
bool DPCTLKernelBundle_HasKernel(__dpctl_keep DPCTLSyclKernelBundleRef KBRef,
711
                                 __dpctl_keep const char *KernelName)
712
{
58✔
713
    if (!KBRef) {
58✔
714
        error_handler("Input KBRef is nullptr", __FILE__, __func__, __LINE__);
3✔
715
        return false;
3✔
716
    }
3✔
717
    if (!KernelName) {
55✔
718
        error_handler("Input KernelName is nullptr", __FILE__, __func__,
3✔
719
                      __LINE__);
3✔
720
        return false;
3✔
721
    }
3✔
722

723
    auto SyclKB = unwrap<kernel_bundle<bundle_state::executable>>(KBRef);
52✔
724
    sycl::backend be = SyclKB->get_backend();
52✔
725
    switch (be) {
52✔
726
    case sycl::backend::opencl:
52!
727
        return _HasKernel_ocl_impl(*SyclKB, KernelName);
52✔
728
    case sycl::backend::ext_oneapi_level_zero:
×
729
#ifdef DPCTL_ENABLE_L0_PROGRAM_CREATION
×
730
        return _HasKernel_ze_impl(*SyclKB, KernelName);
×
731
#endif
×
732
    default:
×
733
        error_handler("Backend " + std::to_string(static_cast<int>(be)) +
×
734
                          " is not supported.",
×
735
                      __FILE__, __func__, __LINE__);
×
736
        return false;
×
737
    }
52✔
738
}
52✔
739

740
void DPCTLKernelBundle_Delete(__dpctl_take DPCTLSyclKernelBundleRef KBRef)
741
{
94✔
742
    delete unwrap<kernel_bundle<bundle_state::executable>>(KBRef);
94✔
743
}
94✔
744

745
__dpctl_give DPCTLSyclKernelBundleRef
746
DPCTLKernelBundle_Copy(__dpctl_keep const DPCTLSyclKernelBundleRef KBRef)
747
{
8✔
748
    auto Bundle = unwrap<kernel_bundle<bundle_state::executable>>(KBRef);
8✔
749
    if (!Bundle) {
8✔
750
        error_handler(
3✔
751
            "Cannot copy DPCTLSyclKernelBundleRef as input is a nullptr",
3✔
752
            __FILE__, __func__, __LINE__);
3✔
753
        return nullptr;
3✔
754
    }
3✔
755
    try {
5✔
756
        auto CopiedBundle =
5✔
757
            new kernel_bundle<bundle_state::executable>(*Bundle);
5✔
758
        return wrap<kernel_bundle<bundle_state::executable>>(CopiedBundle);
5✔
759
    } catch (std::exception const &e) {
5✔
760
        error_handler(e, __FILE__, __func__, __LINE__);
×
761
        return nullptr;
×
762
    }
×
763
}
5✔
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