@@ -28,6 +28,10 @@ a OpenCL source string or a SPIR-V binary file.
2828from libc.stdint cimport uint32_t
2929
3030from dpctl._backend cimport ( # noqa: E211, E402;
31+ DPCTLBuildOptionList_Append,
32+ DPCTLBuildOptionList_Create,
33+ DPCTLBuildOptionList_Delete,
34+ DPCTLBuildOptionListRef,
3135 DPCTLKernel_Copy,
3236 DPCTLKernel_Delete,
3337 DPCTLKernel_GetCompileNumSubGroups,
@@ -38,16 +42,31 @@ from dpctl._backend cimport ( # noqa: E211, E402;
3842 DPCTLKernel_GetPreferredWorkGroupSizeMultiple,
3943 DPCTLKernel_GetPrivateMemSize,
4044 DPCTLKernel_GetWorkGroupSize,
45+ DPCTLKernelBuildLog_Create,
46+ DPCTLKernelBuildLog_Delete,
47+ DPCTLKernelBuildLog_Get,
48+ DPCTLKernelBuildLogRef,
4149 DPCTLKernelBundle_Copy,
4250 DPCTLKernelBundle_CreateFromOCLSource,
4351 DPCTLKernelBundle_CreateFromSpirv,
52+ DPCTLKernelBundle_CreateFromSYCLSource,
4453 DPCTLKernelBundle_Delete,
4554 DPCTLKernelBundle_GetKernel,
55+ DPCTLKernelBundle_GetSyclKernel,
4656 DPCTLKernelBundle_HasKernel,
57+ DPCTLKernelBundle_HasSyclKernel,
58+ DPCTLKernelNameList_Append,
59+ DPCTLKernelNameList_Create,
60+ DPCTLKernelNameList_Delete,
61+ DPCTLKernelNameListRef,
4762 DPCTLSyclContextRef,
4863 DPCTLSyclDeviceRef,
4964 DPCTLSyclKernelBundleRef,
5065 DPCTLSyclKernelRef,
66+ DPCTLVirtualHeaderList_Append,
67+ DPCTLVirtualHeaderList_Create,
68+ DPCTLVirtualHeaderList_Delete,
69+ DPCTLVirtualHeaderListRef,
5170)
5271
5372__all__ = [
@@ -196,9 +215,11 @@ cdef class SyclProgram:
196215 """
197216
198217 @staticmethod
199- cdef SyclProgram _create(DPCTLSyclKernelBundleRef KBRef):
218+ cdef SyclProgram _create(DPCTLSyclKernelBundleRef KBRef,
219+ bint is_sycl_source):
200220 cdef SyclProgram ret = SyclProgram.__new__ (SyclProgram)
201221 ret._program_ref = KBRef
222+ ret._is_sycl_source = is_sycl_source
202223 return ret
203224
204225 def __dealloc__ (self ):
@@ -209,13 +230,19 @@ cdef class SyclProgram:
209230
210231 cpdef SyclKernel get_sycl_kernel(self , str kernel_name):
211232 name = kernel_name.encode(" utf8" )
233+ if self ._is_sycl_source:
234+ return SyclKernel._create(
235+ DPCTLKernelBundle_GetSyclKernel(self ._program_ref, name),
236+ kernel_name)
212237 return SyclKernel._create(
213238 DPCTLKernelBundle_GetKernel(self ._program_ref, name),
214239 kernel_name
215240 )
216241
217242 def has_sycl_kernel (self , str kernel_name ):
218243 name = kernel_name.encode(" utf8" )
244+ if self ._is_sycl_source:
245+ return DPCTLKernelBundle_HasSyclKernel(self ._program_ref, name)
219246 return DPCTLKernelBundle_HasKernel(self ._program_ref, name)
220247
221248 def addressof_ref (self ):
@@ -271,7 +298,7 @@ cpdef create_program_from_source(SyclQueue q, str src, str copts=""):
271298 if KBref is NULL :
272299 raise SyclProgramCompilationError()
273300
274- return SyclProgram._create(KBref)
301+ return SyclProgram._create(KBref, False )
275302
276303
277304cpdef create_program_from_spirv(SyclQueue q, const unsigned char [:] IL,
@@ -317,7 +344,120 @@ cpdef create_program_from_spirv(SyclQueue q, const unsigned char[:] IL,
317344 if KBref is NULL :
318345 raise SyclProgramCompilationError()
319346
320- return SyclProgram._create(KBref)
347+ return SyclProgram._create(KBref, False )
348+
349+
350+ cpdef create_program_from_sycl_source(SyclQueue q, unicode source,
351+ list headers = None ,
352+ list registered_names = None ,
353+ list copts = None ):
354+ """
355+ Creates an executable SYCL kernel_bundle from SYCL source code.
356+
357+ This uses the DPC++ ``kernel_compiler`` extension to create a
358+ ``sycl::kernel_bundle<sycl::bundle_state::executable>`` object from
359+ SYCL source code.
360+
361+ Parameters:
362+ q (:class:`dpctl.SyclQueue`)
363+ The :class:`dpctl.SyclQueue` for which the
364+ :class:`.SyclProgram` is going to be built.
365+ source (unicode)
366+ SYCL source code string.
367+ headers (list)
368+ Optional list of virtual headers, where each entry in the list
369+ needs to be a tuple of header name and header content. See the
370+ documentation of the ``include_files`` property in the DPC++
371+ ``kernel_compiler`` extension for more information.
372+ Default: []
373+ registered_names (list, optional)
374+ Optional list of kernel names to register. See the
375+ documentation of the ``registered_names`` property in the DPC++
376+ ``kernel_compiler`` extension for more information.
377+ Default: []
378+ copts (list)
379+ Optional list of compilation flags that will be used
380+ when compiling the program. Default: ``""``.
381+
382+ Returns:
383+ program (:class:`.SyclProgram`)
384+ A :class:`.SyclProgram` object wrapping the
385+ ``sycl::kernel_bundle<sycl::bundle_state::executable>``
386+ returned by the C API.
387+
388+ Raises:
389+ SyclProgramCompilationError
390+ If a SYCL kernel bundle could not be created. The exception
391+ message contains the build log for more details.
392+ """
393+ cdef DPCTLSyclKernelBundleRef KBref
394+ cdef DPCTLSyclContextRef CRef = q.get_sycl_context().get_context_ref()
395+ cdef DPCTLSyclDeviceRef DRef = q.get_sycl_device().get_device_ref()
396+ cdef bytes bSrc = source.encode(" utf8" )
397+ cdef const char * Src = < const char * > bSrc
398+ cdef DPCTLBuildOptionListRef BuildOpts = DPCTLBuildOptionList_Create()
399+ cdef bytes bOpt
400+ cdef const char * sOpt
401+ cdef bytes bName
402+ cdef const char * sName
403+ cdef bytes bContent
404+ cdef const char * sContent
405+ cdef const char * buildLogContent
406+ for opt in copts:
407+ if not isinstance (opt, unicode ):
408+ DPCTLBuildOptionList_Delete(BuildOpts)
409+ raise SyclProgramCompilationError()
410+ bOpt = opt.encode(" utf8" )
411+ sOpt = < const char * > bOpt
412+ DPCTLBuildOptionList_Append(BuildOpts, sOpt)
413+
414+ cdef DPCTLKernelNameListRef KernelNames = DPCTLKernelNameList_Create()
415+ for name in registered_names:
416+ if not isinstance (name, unicode ):
417+ DPCTLBuildOptionList_Delete(BuildOpts)
418+ DPCTLKernelNameList_Delete(KernelNames)
419+ raise SyclProgramCompilationError()
420+ bName = name.encode(" utf8" )
421+ sName = < const char * > bName
422+ DPCTLKernelNameList_Append(KernelNames, sName)
423+
424+ cdef DPCTLVirtualHeaderListRef VirtualHeaders
425+ VirtualHeaders = DPCTLVirtualHeaderList_Create()
426+
427+ for name, content in headers:
428+ if not isinstance (name, unicode ) or not isinstance (content, unicode ):
429+ DPCTLBuildOptionList_Delete(BuildOpts)
430+ DPCTLKernelNameList_Delete(KernelNames)
431+ DPCTLVirtualHeaderList_Delete(VirtualHeaders)
432+ raise SyclProgramCompilationError()
433+ bName = name.encode(" utf8" )
434+ sName = < const char * > bName
435+ bContent = content.encode(" utf8" )
436+ sContent = < const char * > bContent
437+ DPCTLVirtualHeaderList_Append(VirtualHeaders, sName, sContent)
438+
439+ cdef DPCTLKernelBuildLogRef BuildLog
440+ BuildLog = DPCTLKernelBuildLog_Create()
441+
442+ KBref = DPCTLKernelBundle_CreateFromSYCLSource(CRef, DRef, Src,
443+ VirtualHeaders, KernelNames,
444+ BuildOpts, BuildLog)
445+
446+ if KBref is NULL :
447+ buildLogContent = DPCTLKernelBuildLog_Get(BuildLog)
448+ buildLogStr = str (buildLogContent, " utf-8" )
449+ DPCTLBuildOptionList_Delete(BuildOpts)
450+ DPCTLKernelNameList_Delete(KernelNames)
451+ DPCTLVirtualHeaderList_Delete(VirtualHeaders)
452+ DPCTLKernelBuildLog_Delete(BuildLog)
453+ raise SyclProgramCompilationError(buildLogStr)
454+
455+ DPCTLBuildOptionList_Delete(BuildOpts)
456+ DPCTLKernelNameList_Delete(KernelNames)
457+ DPCTLVirtualHeaderList_Delete(VirtualHeaders)
458+ DPCTLKernelBuildLog_Delete(BuildLog)
459+
460+ return SyclProgram._create(KBref, True )
321461
322462
323463cdef api DPCTLSyclKernelBundleRef SyclProgram_GetKernelBundleRef(
@@ -336,4 +476,4 @@ cdef api SyclProgram SyclProgram_Make(DPCTLSyclKernelBundleRef KBRef):
336476 reference.
337477 """
338478 cdef DPCTLSyclKernelBundleRef copied_KBRef = DPCTLKernelBundle_Copy(KBRef)
339- return SyclProgram._create(copied_KBRef)
479+ return SyclProgram._create(copied_KBRef, False )
0 commit comments