@@ -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,
@@ -353,6 +356,15 @@ cdef class _kernel_arg_type:
353356 _arg_data_type._WORK_GROUP_MEMORY
354357 )
355358
359+ @property
360+ def dpctl_raw_kernel_arg (self ):
361+ cdef str p_name = " dpctl_raw_kernel_arg"
362+ return kernel_arg_type_attribute(
363+ self ._name,
364+ p_name,
365+ _arg_data_type._RAW_KERNEL_ARG
366+ )
367+
356368
357369kernel_arg_type = _kernel_arg_type()
358370
@@ -958,6 +970,9 @@ cdef class SyclQueue(_SyclQueue):
958970 elif isinstance (arg, LocalAccessor):
959971 kargs[idx] = < void * > ((< LocalAccessor> arg).addressof())
960972 kargty[idx] = _arg_data_type._LOCAL_ACCESSOR
973+ elif isinstance (arg, RawKernelArg):
974+ kargs[idx] = < void * > (< size_t> arg._ref)
975+ kargty[idx] = _arg_data_type._RAW_KERNEL_ARG
961976 else :
962977 ret = - 1
963978 return ret
@@ -1719,3 +1734,99 @@ cdef class WorkGroupMemory:
17191734 """
17201735 def __get__ (self ):
17211736 return < size_t> self ._mem_ref
1737+
1738+
1739+ cdef class _RawKernelArg:
1740+ def __dealloc (self ):
1741+ if (self ._arg_ref):
1742+ DPCTLRawKernelArg_Delete(self ._arg_ref)
1743+
1744+
1745+ cdef class RawKernelArg:
1746+ """
1747+ RawKernelArg(*args)
1748+ Python class representing the ``raw_kernel_arg`` class from the Raw Kernel
1749+ Argument oneAPI SYCL extension for passing binary data as data to kernels.
1750+
1751+ This class is intended to be used as kernel argument when launching kernels.
1752+
1753+ This is based on a DPC++ SYCL extension and only available in newer
1754+ versions. Use ``is_available()`` to check availability in your build.
1755+
1756+ There are multiple ways to create a ``RawKernelArg``.
1757+
1758+ - If the constructor is invoked with just a single argument, this argument
1759+ is expected to expose the Python buffer interface. The raw kernel arg will
1760+ be constructed from the data in that buffer.
1761+
1762+ - If the constructor is invoked with two arguments, the first argument is
1763+ interpreted as the number of bytes in the binary argument, while the
1764+ second argument is interpreted as a pointer to the data.
1765+
1766+ Note that construction of the ``RawKernelArg`` copies the bytes, so
1767+ modifications made after construction of the ``RawKernelArg`` will not be
1768+ reflected in the kernel launch.
1769+
1770+ Args:
1771+ args:
1772+ Variadic argument, see class documentation.
1773+
1774+ Raises:
1775+ TypeError: In case of incorrect arguments given to constructurs,
1776+ unexpected types of input arguments.
1777+ """
1778+ def __cinit__ (self , *args ):
1779+ cdef void * ptr = NULL
1780+ cdef size_t count
1781+ cdef int ret_code = 0
1782+ cdef Py_buffer _buffer
1783+ cdef bint _is_buf
1784+
1785+ if not DPCTLRawKernelArg_Available():
1786+ raise RuntimeError (" Raw kernel arg extension not available" )
1787+
1788+ if not (0 < len (args) < 3 ):
1789+ raise TypeError (" RawKernelArg constructor takes 1 or 2 "
1790+ f" arguments, but {len(args)} were given" )
1791+
1792+ if len (args) == 1 :
1793+ if not _is_buffer(args[0 ]):
1794+ raise TypeError (" RawKernelArg single argument constructor"
1795+ " expects argument to be buffer" ,
1796+ f" but got {type(args[0])}" )
1797+
1798+ ret_code = PyObject_GetBuffer(args[0 ], & (_buffer), PyBUF_SIMPLE | PyBUF_ANY_CONTIGUOUS)
1799+ if ret_code != 0 : # pragma: no cover
1800+ raise RuntimeError (" Could not access buffer" )
1801+
1802+ ptr = _buffer.buf
1803+ count = _buffer.len
1804+ _is_buf = True
1805+ else :
1806+ if not isinstance (args[0 ], numbers.Integral):
1807+ raise TypeError (" RawKernelArg constructor expects first"
1808+ " argument to be `int`, but got {type(args[0])}" )
1809+ if not isinstance (args[1 ], numbers.Integral):
1810+ raise TypeError (" RawKernelArg constructor expects second"
1811+ " argument to be `int`, but got {type(args[1])}" )
1812+
1813+ _is_buf = False
1814+ count = args[0 ]
1815+ ptr = < void * > (< unsigned long long > args[1 ])
1816+
1817+ self ._arg_ref = DPCTLRawKernelArg_Create(ptr, count)
1818+ if (_is_buf):
1819+ PyBuffer_Release(& (_buffer))
1820+
1821+
1822+ """ Check whether the raw_kernel_arg extension is available"""
1823+ @staticmethod
1824+ def is_available ():
1825+ return DPCTLRawKernelArg_Available();
1826+
1827+ property _ref :
1828+ """ Returns the address of the C API ``DPCTLRawKernelArgRef`` pointer
1829+ as a ``size_t``.
1830+ """
1831+ def __get__ (self ):
1832+ return < size_t> self ._arg_ref
0 commit comments