AcademySoftwareFoundation / AcademySoftwareFoundation/openvdb

[REQUEST] User function support for OpenVDB AX

Open
#1,637 4 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
C++
Stars
3.4k
Forks
774
Avg merge
3d 9h
Merged PRs (30d)
34

Description

### Is your feature request related to a problem? Please describe.
Currently, it is not possible to define and call user functions from OpenVDB AX programs, where by 'user function' I mean some native function implemented in e.g. C/C++, the address and signature of which would have to be bound to the AX program when it is compiled. A simple example would be to add a new math operator that would be difficult or inefficient to express directly in the AX language, for example some operator that requires accessing a lookup table.

The OpenVDB AX language specification states that "User function declarations are not currently supported, but exist on the AX Roadmap as a near future feature." but without any current status or ETA.

### Describe the solution you'd like
Similar to how custom data can be bound to the program using `CustomData`/`TypedMetaData` which can then be accessed using the `$` operator, there would be a way to bind a function using a combination of its function pointer, function name, and the types of its arguments and return type. The bound function can then be called from the AX program as if it were one of the built-in functions (edit: or, using some special syntax of course, for example something like `f@density = f$my_function(f@P)`)

This is assuming standard C ABI calling conventions, and (at most) support for native AX data types, but even a subset that only includes simple scalars and vectors would already be useful. Thread-safety and memory access/lifetime of any data used by the function can be explicitly left out of scope (ie: 'user code' is entirely responsible to ensure memory & concurrency safety, AX should not need to add any kind of locking or allocation/deallocation).

I expect AX programs that would rely on this functionality can not be compiled to a static/standalone executable anymore, as binding the function code by its address has to be done at run-time, and the resulting binary would have to include all code dependencies of the user function, which I assume is not something the AX compiler can (wants, should want to) do. If support for user functions would be added, this can be an explicit limitation of the feature ('user functions can only be used in AX programs that are compiled inline/on-line, within the scope of a host program that uses OpenVDB/AX')

### Describe alternatives you've considered
The most obvious alternative to user functions in AX programs, would be to not use AX programs at all but instead iterate VDB grids directly using the regular OpenVDB C++ API's and apply per-voxel/point logic. This is not really a viable alternative for our use case though, as this would imply any required per-voxel/per-point logic that is not covered by some standard OpenVDB API, needs to be defined at compile-time and linked into the executable. The application we are working on allows user-scripted operations that may require exotic per-voxel operations with highly specific input/data requirements, and trying to cover that by building our own set of primitives for per-voxel operations is not realistic.

Another alternative we've considered is to try to bend the current AX language to our will by passing in things like lookup tables as custom data and accessing them directly from the AX main program, but since AX does not support array-types in any form, this would involve binding separate custom data values for every table element, which is most likely not going to work for a lookup table that could be several KB's of data.

### Additional context
The context of this feature is an application that uses an OpenVDB-based backend for modeling volumetric geometries that are highly-domain specific and require operations on the volume data that may only make sense for a single use-case. To accommodate this the application is user-scriptable (using Lua), with user scripts calling into an intermediate API layer that abstracts all OpenVDB details. This works mostly fine for per-volume operations, but it does not work for per-voxel/per-point operations, since calling out to Lua for every voxel/point in a grid to perform custom processing is extremely inefficient. Instead, our Lua scripting engine allows creating 'kernels' defined as OpenVDB AX programs, which can then be applied to the volume. This allows (to some extent) user-defined per-voxel/point operations.

A more concrete example use case that is currently *not* possible because of the lack of user functions in AX could be a user script that wants to do the following: given a VDB point data grid and a 2D intensity map (bitmap) + associated XY world-coordinate space, assign to each point in the VDB grid a new attribute, the value of which is sampled (bilinear) from the intensity map using the point XY coordinates. To take this idea a little further, instead of 2D intensity map, the attribute values could also be sampled from some other dense VDB grid using more advanced OpenVDB stencils.

This kind of functionality can easily be written using the normal OpenVDB C++ API's, but not by means of an AX program.

Contributor guide

Open the contributing guide

Research direction

Start with the AX language specification and the existing CustomData/TypedMetaData binding path described in the issue. Define the binding API, supported native types, calling and lifetime rules, and how inline compilation invokes the function; done means an AX program can bind and call a native user function with documented limitations.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.