Skip to content

Commit 9a72889

Browse files
committed
Support wp.Function parameters (GH-1424)
wp.Function parameters let user functions accept another Warp function as a specialization argument. Before this, helpers had to hard-code the callee, which made higher-order patterns unavailable and left specialization-sensitive behavior untested. Use wp.Function as the public annotation so the API describes the supported target set directly. Keep Callable handling internal for built-in signatures while updating codegen, module hashing, dependency tracking, generated stubs, docs, and tests around function target specialization. Signed-off-by: Eric Shi <ershi@nvidia.com>
1 parent 24ee010 commit 9a72889

11 files changed

Lines changed: 1567 additions & 77 deletions

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
to an addressable expression for use with native snippets, and allow `@wp.func_native` ref-parameter functions to
1717
provide manual adjoints with `adj_snippet`
1818
([GH-1277](https://github.com/NVIDIA/warp/issues/1277)).
19+
- Add support for `wp.Function`-typed parameters in user-defined `@wp.func` functions, allowing user-defined Warp
20+
functions and simple built-in Warp functions such as `wp.sin()` and `wp.min()` to be used as function targets from
21+
kernels or other functions, including through defaults ([GH-1424](https://github.com/NVIDIA/warp/issues/1424)).
1922
- Add mipmap (texture level-of-detail) support to `wp.Texture1D`, `wp.Texture2D`, and `wp.Texture3D` via the new
2023
`num_mip_levels` and `mip_filter_mode` constructor parameters, and allow `wp.texture_sample()` to accept an optional
2124
trailing `lod` argument for controlling sampled detail level ([GH-1409](https://github.com/NVIDIA/warp/issues/1409)).

docs/user_guide/basics.rst

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,67 @@ User functions may also be overloaded by defining multiple function signatures w
360360
def custom(x: wp.vec3):
361361
return x + wp.vec3(1.0, 0.0, 0.0)
362362
363+
.. _callable-parameters:
364+
365+
Function Parameters
366+
^^^^^^^^^^^^^^^^^^^
367+
368+
User functions can accept another user-defined Warp function or simple built-in
369+
Warp function by annotating the parameter as :class:`warp.Function`.
370+
Function targets are chosen when Warp generates code, not while the kernel is
371+
running. Warp compiles a separate version of the user function for each distinct
372+
set of target functions used at a call site. This is similar to generic
373+
specialization: many target combinations mean more specialized versions to
374+
compile, including for ``wp.grad()`` calls. The function target is chosen where
375+
the user function is called and can be invoked directly inside the user function
376+
body:
377+
378+
.. code-block:: python
379+
380+
import warp as wp
381+
382+
@wp.func
383+
def square(x: float):
384+
return x * x
385+
386+
387+
@wp.func
388+
def cube(x: float):
389+
return x * x * x
390+
391+
392+
@wp.func
393+
def apply(f: wp.Function, x: float):
394+
return f(x)
395+
396+
397+
@wp.kernel
398+
def apply_kernel(
399+
values: wp.array[float],
400+
square_out: wp.array[float],
401+
cube_out: wp.array[float],
402+
):
403+
i = wp.tid()
404+
square_out[i] = apply(square, values[i])
405+
cube_out[i] = apply(cube, values[i])
406+
407+
The :class:`warp.Function` annotation is type-erased. It does not encode or
408+
validate the target function signature. The target is checked only through the
409+
actual calls made in the function body during code generation.
410+
411+
Function parameters may also use defaults and keyword arguments:
412+
413+
.. code-block:: python
414+
415+
@wp.func
416+
def apply_default(f: wp.Function = square, x: float = 0.0):
417+
return f(x)
418+
419+
Pass only user-defined :func:`@wp.func <warp.func>` functions or simple built-in
420+
functions such as ``wp.sin``, ``wp.cos``, ``wp.sqrt``, ``wp.add``, and ``wp.min``
421+
as function targets. See :doc:`limitations` for unsupported function targets and
422+
other restrictions.
423+
363424
Tiles may also be passed to user functions. The function signature tile argument should include
364425
dtype and shape parameters to match the tile type intended to be used in the function. For example:
365426

docs/user_guide/limitations.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ Kernels and User Functions
3737
(e.g., ``wp.float64(wp.PI)`` or ``wp.int64(large_value)``).
3838
* Python ``IntFlag`` values behave like raw integers in Warp kernels: bitwise negation (``~``)
3939
produces the integer negation, not a masked combination of flags as in standard Python ``IntFlag`` behavior.
40+
* :ref:`Function parameters <callable-parameters>` in user functions only support direct inline calls with
41+
user-defined :func:`@wp.func <warp.func>` functions and simple built-in Warp functions such as ``wp.sin``,
42+
``wp.cos``, ``wp.sqrt``, ``wp.add``, and ``wp.min``.
43+
Arbitrary Python callables are not supported. Some built-in Warp functions, such as ``wp.printf``, cannot be used
44+
as ``wp.Function`` arguments because they need special handling during kernel compilation.
45+
Rebinding a function-valued local to a different function or to a non-function value is not supported.
46+
User functions with ``wp.Function`` parameters also cannot define custom gradient or replay functions.
4047

4148
A limitation of Warp is that each dimension of the grid used to launch a kernel must be representable as a 32-bit
4249
signed integer. Therefore, no single dimension of a grid should exceed :math:`2^{31}-1`.

0 commit comments

Comments
 (0)