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

IntelPython / dpctl / 12303791715

12 Dec 2024 07:55PM UTC coverage: 87.659%. Remained the same
12303791715

Pull #1932

github

web-flow
Merge 63c19472a into 0bcd63568
Pull Request #1932: Speed up custom reductions

3120 of 3640 branches covered (85.71%)

Branch coverage included in aggregate %.

11810 of 13392 relevant lines covered (88.19%)

7079.71 hits per line

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

46.68
/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-2024 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 <sycl/backend/opencl.hpp>
36
#include <sycl/sycl.hpp> /* Sycl headers       */
37
#include <utility>
38

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

48
using namespace sycl;
49

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

55
using namespace dpctl::syclinterface;
56

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

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

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

74
constexpr backend cl_be = backend::opencl;
75

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

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

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

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

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

115
    return st_clCreateProgramWithSourceF;
27✔
116
}
27✔
117

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

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

143
    return st_clBuildProgramF;
71✔
144
}
71✔
145

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

153
    return st_clCreateKernelF;
110✔
154
}
110✔
155

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

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

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

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

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

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

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

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

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

228
    return _CreateKernelBundle_common_ocl_impl(clProgram, ctx, dev,
27✔
229
                                               CompileOpts);
27✔
230
}
27✔
231

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

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

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

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

259
    return _CreateKernelBundle_common_ocl_impl(clProgram, ctx, dev,
44✔
260
                                               CompileOpts);
44✔
261
}
44✔
262

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

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

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

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

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

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

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

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

329
#ifdef DPCTL_ENABLE_L0_PROGRAM_CREATION
330

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

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

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

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

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

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

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

381
    return st_zeModuleCreateF;
×
382
}
×
383

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

391
    return st_zeModuleDestroyF;
×
392
}
×
393

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

403
    return st_zeKernelCreateF;
×
404
}
×
405

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

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

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

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

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

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

458
    ze_module_handle_t ZeModule;
×
459

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

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

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

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

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

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

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

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

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

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

548
    auto ZeKernelBundle = sycl::get_native<ze_be>(kb);
×
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
            return true;
×
562
        }
×
563
        else {
×
564
            if (ze_status != ZE_RESULT_ERROR_INVALID_KERNEL_NAME) {
×
565
                error_handler("zeKernelCreate failed: " +
×
566
                                  _GetErrorCode_ze_impl(ze_status),
×
567
                              __FILE__, __func__, __LINE__, error_level::error);
×
568
                return false;
×
569
            }
×
570
        }
×
571
    }
×
572

573
    return false;
×
574
}
×
575

576
#endif /* #ifdef DPCTL_ENABLE_L0_PROGRAM_CREATION */
577

578
} /* end of anonymous namespace */
579

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

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

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

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

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

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

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

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

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

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

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