@@ -51,6 +51,9 @@ from ._backend cimport ( # noqa: E211
5151 DPCTLQueue_SubmitNDRange,
5252 DPCTLQueue_SubmitRange,
5353 DPCTLQueue_Wait,
54+ DPCTLRawKernelArg_Available,
55+ DPCTLRawKernelArg_Create,
56+ DPCTLRawKernelArg_Delete,
5457 DPCTLSyclContextRef,
5558 DPCTLSyclDeviceSelectorRef,
5659 DPCTLSyclEventRef,
@@ -364,6 +367,15 @@ cdef class _kernel_arg_type:
364367 _arg_data_type._WORK_GROUP_MEMORY
365368 )
366369
370+ @property
371+ def dpctl_raw_kernel_arg (self ):
372+ cdef str p_name = " dpctl_raw_kernel_arg"
373+ return kernel_arg_type_attribute(
374+ self ._name,
375+ p_name,
376+ _arg_data_type._RAW_KERNEL_ARG
377+ )
378+
367379
368380kernel_arg_type = _kernel_arg_type()
369381
@@ -973,6 +985,9 @@ cdef class SyclQueue(_SyclQueue):
973985 elif isinstance (arg, LocalAccessor):
974986 kargs[idx] = < void * > ((< LocalAccessor> arg).addressof())
975987 kargty[idx] = _arg_data_type._LOCAL_ACCESSOR
988+ elif isinstance (arg, RawKernelArg):
989+ kargs[idx] = < void * > (< size_t> arg._ref)
990+ kargty[idx] = _arg_data_type._RAW_KERNEL_ARG
976991 else :
977992 ret = - 1
978993 return ret
@@ -1738,3 +1753,98 @@ cdef class WorkGroupMemory:
17381753 """
17391754 def __get__ (self ):
17401755 return < size_t> self ._mem_ref
1756+
1757+
1758+ cdef class _RawKernelArg:
1759+ def __dealloc (self ):
1760+ if (self ._arg_ref):
1761+ DPCTLRawKernelArg_Delete(self ._arg_ref)
1762+
1763+
1764+ cdef class RawKernelArg:
1765+ """
1766+ RawKernelArg(*args)
1767+ Python class representing the ``raw_kernel_arg`` class from the Raw Kernel
1768+ Argument oneAPI SYCL extension for passing binary data as data to kernels.
1769+
1770+ This class is intended to be used as kernel argument when launching kernels.
1771+
1772+ This is based on a DPC++ SYCL extension and only available in newer
1773+ versions. Use ``is_available()`` to check availability in your build.
1774+
1775+ There are multiple ways to create a ``RawKernelArg``.
1776+
1777+ - If the constructor is invoked with just a single argument, this argument
1778+ is expected to expose the Python buffer interface. The raw kernel arg will
1779+ be constructed from the data in that buffer.
1780+
1781+ - If the constructor is invoked with two arguments, the first argument is
1782+ interpreted as the number of bytes in the binary argument, while the
1783+ second argument is interpreted as a pointer to the data.
1784+
1785+ Note that construction of the ``RawKernelArg`` copies the bytes, so
1786+ modifications made after construction of the ``RawKernelArg`` will not be
1787+ reflected in the kernel launch.
1788+
1789+ Args:
1790+ args:
1791+ Variadic argument, see class documentation.
1792+
1793+ Raises:
1794+ TypeError: In case of incorrect arguments given to constructurs,
1795+ unexpected types of input arguments.
1796+ """
1797+ def __cinit__ (self , *args ):
1798+ cdef void * ptr = NULL
1799+ cdef size_t count
1800+ cdef int ret_code = 0
1801+ cdef Py_buffer _buffer
1802+ cdef bint _is_buf
1803+
1804+ if not DPCTLRawKernelArg_Available():
1805+ raise RuntimeError (" Raw kernel arg extension not available" )
1806+
1807+ if not (0 < len (args) < 3 ):
1808+ raise TypeError (" RawKernelArg constructor takes 1 or 2 "
1809+ f" arguments, but {len(args)} were given" )
1810+
1811+ if len (args) == 1 :
1812+ if not _is_buffer(args[0 ]):
1813+ raise TypeError (" RawKernelArg single argument constructor"
1814+ " expects argument to be buffer" ,
1815+ f" but got {type(args[0])}" )
1816+
1817+ ret_code = PyObject_GetBuffer(args[0 ], & (_buffer),
1818+ PyBUF_SIMPLE | PyBUF_ANY_CONTIGUOUS)
1819+ if ret_code != 0 : # pragma: no cover
1820+ raise RuntimeError (" Could not access buffer" )
1821+
1822+ ptr = _buffer.buf
1823+ count = _buffer.len
1824+ _is_buf = True
1825+ else :
1826+ if not isinstance (args[0 ], numbers.Integral):
1827+ raise TypeError (" RawKernelArg constructor expects first"
1828+ " argument to be `int`, but got {type(args[0])}" )
1829+ if not isinstance (args[1 ], numbers.Integral):
1830+ raise TypeError (" RawKernelArg constructor expects second"
1831+ " argument to be `int`, but got {type(args[1])}" )
1832+
1833+ _is_buf = False
1834+ count = args[0 ]
1835+ ptr = < void * > (< unsigned long long > args[1 ])
1836+
1837+ self ._arg_ref = DPCTLRawKernelArg_Create(ptr, count)
1838+ if (_is_buf):
1839+ PyBuffer_Release(& (_buffer))
1840+
1841+ @staticmethod
1842+ def is_available ():
1843+ return DPCTLRawKernelArg_Available()
1844+
1845+ property _ref :
1846+ """ Returns the address of the C API ``DPCTLRawKernelArgRef`` pointer
1847+ as a ``size_t``.
1848+ """
1849+ def __get__ (self ):
1850+ return < size_t> self ._arg_ref
0 commit comments