{"id":28614124,"url":"https://github.com/renderkit/openvkl","last_synced_at":"2025-06-12T01:12:48.566Z","repository":{"id":59837246,"uuid":"211395280","full_name":"RenderKit/openvkl","owner":"RenderKit","description":"Intel(R) Open Volume Kernel Library","archived":false,"fork":false,"pushed_at":"2024-11-28T15:19:18.000Z","size":6926,"stargazers_count":202,"open_issues_count":7,"forks_count":27,"subscribers_count":22,"default_branch":"devel","last_synced_at":"2024-11-28T16:24:48.673Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RenderKit.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-27T20:17:19.000Z","updated_at":"2024-11-22T23:25:04.000Z","dependencies_parsed_at":"2024-04-24T19:43:09.932Z","dependency_job_id":"67947dc7-fa5e-4bc7-816c-982720b36aec","html_url":"https://github.com/RenderKit/openvkl","commit_stats":null,"previous_names":["renderkit/openvkl"],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/RenderKit/openvkl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RenderKit%2Fopenvkl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RenderKit%2Fopenvkl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RenderKit%2Fopenvkl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RenderKit%2Fopenvkl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RenderKit","download_url":"https://codeload.github.com/RenderKit/openvkl/tar.gz/refs/heads/devel","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RenderKit%2Fopenvkl/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259374997,"owners_count":22847878,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-12T01:12:45.264Z","updated_at":"2025-06-12T01:12:48.509Z","avatar_url":"https://github.com/RenderKit.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Intel® Open Volume Kernel Library\n\nThis is release v2.0.1 of Intel® Open VKL. For changes and new features\nsee the [changelog](CHANGELOG.md). Visit http://www.openvkl.org for more\ninformation.\n\n# Overview\n\nIntel® Open Volume Kernel Library (Intel® Open VKL) is a collection of\nhigh-performance volume computation kernels, developed at Intel. The\ntarget users of Open VKL are graphics application engineers who want to\nimprove the performance of their volume rendering applications by\nleveraging Open VKL’s performance-optimized kernels, which include\nvolume traversal and sampling functionality for a variety of volumetric\ndata formats. Open VKL supports x86 CPUs under Linux, macOS, and\nWindows; ARM CPUs on macOS; as well as Intel® GPUs under Linux and\nWindows (currently in beta).\n\nOpen VKL contains kernels optimized for the latest x86 processors with\nsupport for SSE, AVX, AVX2, and AVX-512 instructions, and for ARM\nprocessors with support for NEON instructions. Open VKL supports Intel\nGPUs based on the Xe HPG microarchitecture (Intel® Arc™ GPU) under Linux\nand Windows and Xe HPC microarchitecture (Intel® Data Center GPU Flex\nSeries and Intel® Data Center GPU Max Series) under Linux. Intel GPU\nsupport leverages the [SYCL](https://www.khronos.org/sycl/) open\nstandard programming language; SYCL allows one to write C++ code that\ncan be run on various devices, such as CPUs and GPUs. Open VKL is part\nof the [Intel® oneAPI Rendering\nToolkit](https://software.intel.com/en-us/rendering-framework) and is\nreleased under the permissive [Apache 2.0\nlicense](http://www.apache.org/licenses/LICENSE-2.0).\n\nOpen VKL provides a C-based API on CPU and GPU, and also supports\napplications written with the Intel® Implicit SPMD Program Compiler\n(Intel® ISPC) for CPU by also providing an ISPC interface to the core\nvolume algorithms. This makes it possible to write a renderer in ISPC\nthat automatically vectorizes and leverages SSE, AVX, AVX2, AVX-512, and\nNEON instructions. ISPC also supports runtime code selection, thus ISPC\nwill select the best code path for your application.\n\nIn addition to the volume kernels, Open VKL provides tutorials and\nexample renderers to demonstrate how to best use the Open VKL API.\n\n## Version History\n\n### Open VKL 2.0.1\n\n- Removed ISPC runtime dependency and level zero loader requirement\n- Add DEPENDENTLOADFLAG linker parameter for Windows binaries,\n  restricting DLL loading behavior\n- Superbuild updates to latest versions of dependencies\n\n### Open VKL 2.0.0\n\n- This Open VKL release adds support for Intel® Arc™ GPUs, Intel® Data\n  Center GPU Flex Series and Intel® Data Center GPU Max Series through\n  SYCL.\n  - The SYCL support of Open VKL is in beta phase. Current\n    functionality, quality, and GPU performance may not reflect that of\n    the final product.\n  - Open VKL CPU support in this release remains at Gold level,\n    incorporating the same quality and performance as previous releases.\n- API changes:\n  - Handle types are now passed by pointer in the following APIs:\n    - `vklComputeSample*()`\n    - `vklComputeGradient*()`\n    - `vklGet*IteratorSize*()`\n    - `vklInit*Iterator*()`\n    - `vklIterate*()`\n  - `vklLoadModule()` has been removed; compile-time linkage to an Open\n    VKL device implementation (`cpu` or `gpu`) is now required\n  - Added `vklInit()` API, which must be called to initialize the\n    library\n  - `VKL_FILTER_[TRILINEAR,TRICUBIC]` are renamed to\n    `VKL_FILTER_[LINEAR,CUBIC]`\n  - `VKLAMRMethod` enum is now `uint32_t`\n  - `structuredSpherical` volumes: the `gridSpacing` default now results\n    in the volume occupying a full sphere\n- Added new examples demonstrating GPU usage: `vklExamplesGPU` and\n  `vklTutorialGPU`\n- Superbuild updates to latest versions of dependencies\n\n### Open VKL 1.3.2\n\n- Move to and require latest versions of RenderKit dependencies: Embree\n  v4.0.0 and rkcommon v1.11.0\n- ARM support: expose ISPC neon-i32x8 target via OPENVKL_ISA_NEON2X\n  CMake option\n- Superbuild updates to latest versions of dependencies\n\n### Open VKL 1.3.1\n\n- Superbuild updates to latest versions of dependencies\n- Note that the update to zlib v1.2.13 remedies CVE-2022-37434\n\n### Open VKL 1.3.0\n\n- Added AVX512 8-wide CPU device mode, enabled via the\n  `OPENVKL_ISA_AVX512SKX_8_WIDE` CMake option\n- VDB volumes: added support for packed / contiguous data layouts for\n  temporally constant volumes, which can provide improved performance\n  (`nodesPackedDense`, `nodesPackedTile` parameters)\n- VDB utility library: added `repackNodes` flag to toggle usage of\n  packed data layouts\n- Particle volumes: general memory efficiency and performance\n  improvements\n- Superbuild updates to latest versions of dependencies\n- Minimum ISPC version is now v1.18.0\n\n### Open VKL 1.2.0\n\n- Added `vklSetParam()` API function which can set parameters of any\n  supported type\n- Structured regular volumes:\n  - Added support for cell-centered data via the `cellCentered`\n    parameter; vertex-centered remains the default\n  - Added support for more general transformations via the\n    `indexToObject` parameter\n  - Added `indexOrigin` parameter which applies an index-space vec3i\n    translation\n- VDB volumes:\n  - Added `indexClippingBounds` parameter, which can restrict the active\n    voxel bounding box\n  - The `indexToObject` parameter can now be provided as a\n    `VKL_AFFINE3F`\n  - Corrected bounding box computations in `InnerNode` observer\n- Particle volumes:\n  - Now ignoring particles with zero radius\n- VDB utility library: added `commit` flag (default true) to volume\n  creation methods, allowing apps to set additional parameters before\n  first commit\n- Examples:\n  - Added new set of minimal examples, which step through creation of\n    basic volume and isosurface renderers\n  - Exposing `intervalResolutionHint` parameter in `vklExamples`\n    application\n- Superbuild updates to latest versions of dependencies\n\n### Open VKL 1.1.0\n\n- vklExamples improvements: asynchronous rendering, multiple viewports,\n  docking, and more\n- Fixed bug in `openvkl_utility_vdb` which could lead to crashes when\n  creating VDB volumes with temporally constant tiles\n- Superbuild updates to latest versions of dependencies\n- Minimum rkcommon version is now 1.8.0\n\n### Open VKL 1.0.1\n\n- Fixed issue in `structuredRegular` and `vdb` interval iterators that\n  could lead to erroneous initial intervals for certain ray inputs\n- Fixed handling of `intervalResolutionHint` interval iterator context\n  parameter for `amr`, `particle`, and `unstructured` volumes with small\n  numbers of cells / primitives\n\n### Open VKL 1.0.0\n\n- The version 1.0 release marks long term API stability (until v2.0)\n- Open VKL can now be built for ARM CPUs that support Neon\n- Iterator API updates:\n  - Introducing interval and hit iterator contexts, which hold\n    iterator-specific configuration (eliminates value selector objects)\n  - Interval and hit iteration is now supported on any volume attribute\n  - Interval iterators now include a `time` parameter\n  - Interval iterators now support the `intervalResolutionHint`\n    parameter, replacing `maxIteratorDepth` and\n    `elementaryCellIteration`\n- Supporting configurable background values; default is now\n  `VKL_BACKGROUND_UNDEFINED` (NaN) for all volume types\n- `vklGetValueRange()` now supports all volume attributes\n- Added ISPC-side API bindings for `vklGetNumAttributes()` and\n  `vklGetValueRange()`\n- Structured regular volumes:\n  - Added support for tricubic filtering\n  - More accurate gradient computations respecting filter mode\n  - Hit iteration robustness improvements\n- VDB volumes:\n  - Interval and hit iteration robustness improvements\n  - Corrected interval iterator `nominalDeltaT` computation for\n    non-normalized ray directions and non-uniform object-space grid\n    spacings\n  - Fixed bug which could cause incorrect value range computations for\n    temporally varying volumes\n- vklExamples additions demonstrating:\n  - Multi-attribute interval / hit iteration\n  - Configurable background values\n  - Temporally varying volumes\n- Superbuild updates to latest versions of dependencies\n- Now requiring minimum versions:\n  - Embree 3.13.1\n  - rkcommon 1.7.0\n  - ISPC 1.16.0\n\n### Open VKL 0.13.0\n\n- Driver (now device) API changes:\n  - Renamed `VKLDriver` to `VKLDevice` and updated associated device\n    setup APIs\n  - Use of multiple concurrent devices is now supported; therefore\n    `vklNewVolume()` and `vklNewData()` now require a device handle\n  - Renamed the `ispc_device` module and `ispc` device to `cpu_device`\n    and `cpu`, respectively\n  - The `OPENVKL_CPU_DEVICE_DEFAULT_WIDTH` environment variable can now\n    be used to change the `cpu` device’s default SIMD width at run time\n- Added new `VKLTemporalFormat` enum used for temporally varying volume\n  parameterization\n- VDB volumes:\n  - Support for temporally structured and temporally unstructured (TUV)\n    attribute data, which can be used for motion blurred rendering\n  - Supporting tricubic filtering via `VKL_FILTER_TRICUBIC` filter type\n  - Added support for half precision float-point (FP16) attribute data\n    via `VKL_HALF` data type\n  - Added a new `InnerNode` observer and associated utility functions\n    which allows applications to introspect inner nodes of the internal\n    tree structure, including bounding boxes and value ranges\n  - Renamed `VKL_FORMAT_CONSTANT_ZYX` to `VKL_FORMAT_DENSE_ZYX`\n- Structured regular and spherical volumes:\n  - Added support for half precision float-point (FP16) attribute data\n    via `VKL_HALF` data type\n- Unstructured volumes:\n  - Added support for elementary cell iteration via the\n    `elementaryCellIteration` parameter\n  - Robustness improvements for hit iteration\n- AMR volumes:\n  - Improved interval iterator implementation, resolving issues with\n    returned interval `nominalDeltaT` values\n  - Interval iterators now support `maxIteratorDepth` parameter\n- Interval and hit iteration performance improvements when multiple\n  values ranges / values are selected\n- Added new temporal compression utilities which applications can use\n  for processing temporally unstructured attribute data\n- vklExamples additions demonstrating:\n  - Motion blurred rendering on temporally structured and temporally\n    unstructured `vdb` volumes\n  - Tricubic filtering on `vdb` volumes\n  - Half-precision floating-point (FP16) support for\n    `structuredRegular`, `structuredSpherical`, and `vdb` volumes\n  - Elementary cell interval iteration on `unstructured` volumes\n  - Use of the `InnerNode` observer on `vdb` volumes\n- Superbuild updates to:\n  - Embree 3.13.0\n  - rkcommon 1.6.1\n- Minimum rkcommon version is now 1.6.1\n\n### Open VKL 0.12.1\n\n- Fixed bug in VDB volume interval iterator implementation which could\n  lead to missed intervals or incorrect value ranges in returned\n  intervals\n\n### Open VKL 0.12.0\n\n- Added support for temporally varying volumes with associated API\n  changes for sampling, gradients, and hit iteration. This feature can\n  be used to enable motion blurred rendering\n- Structured regular volumes:\n  - Support for temporally structured and temporally unstructured (TUV)\n    input data\n  - Improved `nominalDeltaT` for interval iteration\n  - Interval iterator robustness improvements for axis-aligned rays\n  - Sampling performance improvements\n- VDB volumes:\n  - Multi-attribute support (including three-component float grids)\n  - Interval iterator robustness improvements for axis-aligned rays\n  - Performance improvements for scalar sampling\n  - Now restricting volumes to exactly four levels\n  - Allowing leaf nodes on the lowest level only\n- Unstructured volumes:\n  - Improved `nominalDeltaT` for interval iteration\n- `vdb_util` updates:\n  - Support for loading multi-attribute .vdb files (`float` and `Vec3s`\n    grids)\n  - Fix order of rotation matrix coefficients loaded from .vdb files\n- vklExamples additions demonstrating:\n  - Motion blurred rendering on temporally structured and temporally\n    unstructured volumes (`structuredRegular` only)\n  - Support for `vdb` multi-attribute volumes\n  - Hit iterator time support\n- Superbuild updates to:\n  - Embree 3.12.2\n  - rkcommon 1.6.0\n  - ISPC 1.15.0\n  - OpenVDB 8.0.0\n- Minimum rkcommon version is now 1.6.0\n\n### Open VKL 0.11.0\n\n- Introduced API support for multi-attribute volumes, including APIs for\n  sampling multiple attributes simultaneously\n  - Initially only `structuredRegular` and `structuredSpherical` volume\n    types support multi-attribute data\n- Iterator APIs now work on sampler objects rather than volumes,\n  supporting finer-grained configurability\n- Observers can now be created for both volume and sampler objects\n  - `LeafNodeAccess` observers must now be created on sampler objects\n- Log and error callbacks now support a user pointer\n- `vdb` volume interval iterators:\n  - Added support for elementary cell iteration when `maxIteratorDepth`\n    is set to `VKL_VDB_NUM_LEVELS`-1\n  - Up to 2x faster iteration\n- `unstructured` and `particle` volume interval iterators:\n  - Improved interior empty space skipping behavior\n  - Added support for configurable iterator depth via the\n    `maxIteratorDepth` parameter\n- Added support for filter modes in `structuredRegular` and\n  `structuredSpherical` volumes\n- `amr` volumes now support `method` parameter on sampler objects\n- Added new `interval_iterator_debug` renderer in `vklExamples` to\n  visualize interval iteration behavior\n- Hit iterator accuracy improvements for `unstructured` volumes\n- Fixed bugs in `amr` and `vdb` volume bounding box computations\n- Fixed bug in `unstructured` volume gradient computations near empty\n  regions\n- Minimum ISPC version is now v1.14.1\n\n### Open VKL 0.10.0 (alpha)\n\n- Added new `particle` volume type supporting Gaussian radial basis\n  functions\n- Introduced `VKLSampler` objects allowing configuration of sampling and\n  gradient behavior\n- Added stream-wide sampling and gradient APIs\n- Introduced a new way to allocate iterators, giving the user more\n  freedom in choosing allocation schemes and reducing iterator size\n- Added support for strided data arrays\n- Added gradient implementations for `amr` and `vdb` volumes\n- Hit iterator accuracy improvements for `amr`, `structuredSpherical`,\n  `unstructured`, and `vdb` volumes\n- Up to 4x performance improvement for `structuredRegular` and\n  `structuredSpherical` sampling for volumes in the 1-2GB range\n- Up to 2x performance improvement for `structuredRegular` interval\n  iteration\n- Improved commit speed for `unstructured` volumes\n- Improved value range computation in `vdb` volumes\n- Improved isosurface shading in `vklExamples`\n- Improved parameter validation across all volume types\n- Aligned `VKLHit[4,8,16]` and `VKLInterval[4,8,16]` structs\n- Added hit epsilon to `VKLHit[4,8,16]`\n- Updated parameter names for `vdb` volumes\n- Renamed `VKLVdbLeafFormat` to `VKLFormat`\n- Fixed incorrect use of system-installed CMake in superbuild while\n  building dependencies\n- Fixed various memory leaks\n- Fixed crashes which could occur in `VdbVolume::cleanup()` and\n  `vklShutdown()`\n- Moved from ospcommon to rkcommon v1.4.1\n\n### Open VKL 0.9.0 (alpha)\n\n- Added support for VDB sparse structured volumes (`\"vdb\"` volume type)\n- Added `vdb_util` library to simplify instantiation of VDB volumes, and\n  support loading of .vdb files using OpenVDB\n- Added `VKLObserver` and associated APIs, which may used by volume\n  types to pass information back to the application\n  - A `LeafNodeAccess` observer is provided for VDB volumes to support\n    on-demand loading of leaf nodes\n- Structured regular volumes:\n  - Up to 6x performance improvement for scalar iterator initialization\n  - Up to 2x performance improvement for scalar iterator iteration\n- General improvements to the CMake Superbuild for building Open VKL and\n  all associated dependencies\n- Allowing instantiation of ISPC driver for any supported SIMD width (in\n  addition to the default automatically selected width)\n- Volume type names are now camelCase (legacy snake_case type names are\n  deprecated), impacting `structuredRegular` and `structuredSpherical`\n  volumes\n- Enabling `flushDenormals` driver mode by default\n- Aligning public `vkl_vvec3f[4,8,16]` and `vkl_vrange1f[4,8,16]` types\n- Added `VKL_LOG_NONE` log level\n- Fixed bug in `vklExamples` which could lead to improper rendering on\n  macOS Catalina\n- Fixed bug in unstructured volume interval iterator which could lead to\n  errors with some combinations of lane masks\n- Now providing binary releases for Linux, macOS, and Windows\n\n### Open VKL 0.8.0 (alpha)\n\n- Added support for structured volumes on spherical grids\n  (`\"structured_spherical\"` volume type)\n- Structured regular volumes:\n  - Up to 8x performance improvement for scalar (single-wide) sampling\n  - Fixed hit iterator bug which could lead to isosurfacing artifacts\n  - Renamed `voxelData` parameter to `data`\n- Unstructured volumes:\n  - Up to 4x performance improvement for scalar (single-wide) sampling\n  - Improved interval iterator implementation for more efficient space\n    skipping and tighter value bounds on returned intervals\n  - Now using Embree for BVH builds for faster build times / volume\n    commits\n  - Renamed `vertex.value` and `cell.value` parameters to `vertex.data`\n    and `cell.data`, respectively\n- AMR volumes:\n  - renamed `block.cellWidth` parameter to `cellWidth`, and clarified\n    API documentation\n- Added `vklGetValueRange()` API for querying volume value ranges\n- Added new driver parameters, APIs, and environment variables allowing\n  user control of log levels, log / error output redirection, number of\n  threads, and other options\n- `vklIterateHit[4,8,16]()` and `vklIterateInterval[4,8,16]()` calls now\n  only populate hit / interval data for active lanes\n- Changed `VKLDataType` enum values for better forward compatibility\n- ISPC-side hit and interval iterator objects must now be declared\n  `varying`\n- More flexible ISA build configuration through `OPENVKL_MAX_ISA` and\n  `OPENVKL_ISA_*` CMake build options\n- Minimum ospcommon version is now 1.1.0\n\n### Open VKL 0.7.0 (alpha)\n\n- Initial public alpha release, with support for structured,\n  unstructured, and AMR volumes.\n\n## Support and Contact\n\nOpen VKL is under active development, and though we do our best to\nguarantee stable release versions a certain number of bugs,\nas-yet-missing features, inconsistencies, or any other issues are still\npossible. Should you find any such issues please report them immediately\nvia [Open VKL’s GitHub Issue\nTracker](https://github.com/OpenVKL/openvkl/issues) (or, if you should\nhappen to have a fix for it, you can also send us a pull request); you\nmay also contact us via email at \u003copenvkl@googlegroups.com\u003e.\n\nJoin our [mailing\nlist](https://groups.google.com/forum/#!forum/openvkl-announce/join) to\nreceive release announcements and major news regarding Open VKL.\n\n# Open VKL API\n\nThe Open VKL API is provided in two parts: a host-side API which is\nresponsible for object creation and configuration (e.g. instantiating\nnew volumes and providing data from the application), and a device-side\nAPI which provides access to low-level kernels such as volume sampling\nand iteration. The host-side API is identical for all Open VKL device\nimplementations, while the device-side API varies slightly between\ndevice implementations.\n\nTo access the Open VKL host-side API you first need to include the Open\nVKL header. For C99 or C++:\n\n``` cpp\n#include \u003copenvkl/openvkl.h\u003e\n```\n\nAdditionally, the device-side APIs are provided through a\ndevice-specific header provided by the currently linked-to device:\n\n``` cpp\n#include \u003copenvkl/device/openvkl.h\u003e\n```\n\nCPU applications using the Intel® Implicit SPMD Program Compiler (Intel®\nISPC) can include the host- and device-side APIs similarly via:\n\n``` cpp\n#include \u003copenvkl/openvkl.isph\u003e\n#include \u003copenvkl/device/openvkl.isph\u003e\n```\n\nThis documentation will discuss the C99/C++ API. The ISPC version has\nthe same functionality and flavor. Looking at the headers, the\n`vklTutorialISPC` example, and this documentation should be enough to\nfigure it out.\n\n## Device initialization and shutdown\n\nTo use the API, one of the implemented backends must be linked at\ncompile time. Currently both a CPU and GPU device are available. To link\none of these devices within CMake, use for example:\n\n``` cpp\ntarget_link_libraries(myApp PRIVATE openvkl::openvkl openvkl::openvkl_module_cpu_device)\n```\n\nor\n\n``` cpp\ntarget_link_libraries(myApp PRIVATE openvkl::openvkl openvkl::openvkl_module_gpu_device)\n```\n\nThe application code must then first initialize Open VKL:\n\n``` cpp\nvklInit();\n```\n\nA device then needs to be instantiated, either via:\n\n``` cpp\nVKLDevice device = vklNewDevice(\"cpu\");\n```\n\nor\n\n``` cpp\nVKLDevice device = vklNewDevice(\"gpu\");\n```\n\nBy default, the CPU device selects the maximum supported SIMD width (and\nassociated ISA) for the system. Optionally, a specific width may be\nrequested using the `cpu_4`, `cpu_8`, or `cpu_16` device names. Note\nthat the system must support the given width (SSE4.1 for 4-wide, AVX for\n8-wide, and AVX512 for 16-wide).\n\nOnce a device is created, you can call\n\n``` cpp\nvoid vklDeviceSetInt(VKLDevice, const char *name, int val);\nvoid vklDeviceSetString(VKLDevice, const char *name, const char *val);\n```\n\nto set parameters on the device. The following parameters are understood\nby all devices:\n\n| Type   | Name           | Description                                                                                                                                                       |\n|:-------|:---------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| int    | logLevel       | logging level; valid values are `VKL_LOG_DEBUG`, `VKL_LOG_INFO`, `VKL_LOG_WARNING`, `VKL_LOG_ERROR` and `VKL_LOG_NONE`                                            |\n| string | logOutput      | convenience for setting where log messages go; valid values are `cout`, `cerr` and `none`                                                                         |\n| string | errorOutput    | convenience for setting where error messages go; valid values are `cout`, `cerr` and `none`                                                                       |\n| int    | numThreads     | number of threads which Open VKL can use                                                                                                                          |\n| int    | flushDenormals | sets the `Flush to Zero` and `Denormals are Zero` mode of the MXCSR control and status register (default: 1); see Performance Recommendations section for details |\n\nParameters shared by all devices.\n\nAdditionally, the following parameters are understood by the `gpu`\ndevice:\n\n| Type    | Name        | Description                                 |\n|:--------|:------------|:--------------------------------------------|\n| void \\* | syclContext | *REQUIRED*: pointer to a valid SYCL context |\n\nParameters understood by the `gpu` device\n\nOnce parameters are set, the device must be committed with\n\n``` cpp\nvklCommitDevice(device);\n```\n\nThe newly committed device is then ready to use. Users may change\nparameters on a device after initialization. In this case the device\nwould need to be re-committed.\n\nAll Open VKL objects are associated with a device. A device handle must\nbe explicitly provided when creating volume and data objects, via\n`vklNewVolume()` and `vklNewData()` respectively. Other object types are\nautomatically associated with a device via transitive dependency on a\nvolume.\n\nOn CPU, Open VKL provides vector-wide versions for several APIs. To\ndetermine the native vector width for a given device, call:\n\n``` cpp\nint width = vklGetNativeSIMDWidth(VKLDevice device);\n```\n\nWhen the application is finished with an Open VKL device or shutting\ndown, release the device via:\n\n``` cpp\nvklReleaseDevice(VKLDevice device);\n```\n\n### Environment variables\n\nThe generic device parameters can be overridden via environment\nvariables for easy changes to Open VKL’s behavior without needing to\nchange the application (variables are prefixed by convention with\n“`OPENVKL_`”):\n\n| Variable                | Description                                                                                                                                                       |\n|:------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| OPENVKL_LOG_LEVEL       | logging level; valid values are `debug`, `info`, `warning`, `error` and `none`                                                                                    |\n| OPENVKL_LOG_OUTPUT      | convenience for setting where log messages go; valid values are `cout`, `cerr` and `none`                                                                         |\n| OPENVKL_ERROR_OUTPUT    | convenience for setting where error messages go; valid values are `cout`, `cerr` and `none`                                                                       |\n| OPENVKL_THREADS         | number of threads which Open VKL can use                                                                                                                          |\n| OPENVKL_FLUSH_DENORMALS | sets the `Flush to Zero` and `Denormals are Zero` mode of the MXCSR control and status register (default: 1); see Performance Recommendations section for details |\n\nEnvironment variables understood by all devices.\n\nNote that these environment variables take precedence over values set\nthrough the `vklDeviceSet*()` functions.\n\nAdditionally, the CPU device’s default SIMD width can be overriden at\nrun time with the `OPENVKL_CPU_DEVICE_DEFAULT_WIDTH` environment\nvariable. Legal values are 4, 8, or 16. This setting is only applicable\nwhen the generic `cpu` device is instantiated; if a specific width is\nrequested via the `cpu_[4,8,16]` device names then the environment\nvariable is ignored.\n\n### Error handling and log messages\n\nThe following errors are currently used by Open VKL:\n\n| Name                  | Description                                           |\n|:----------------------|:------------------------------------------------------|\n| VKL_NO_ERROR          | no error occurred                                     |\n| VKL_UNKNOWN_ERROR     | an unknown error occurred                             |\n| VKL_INVALID_ARGUMENT  | an invalid argument was specified                     |\n| VKL_INVALID_OPERATION | the operation is not allowed for the specified object |\n| VKL_OUT_OF_MEMORY     | there is not enough memory to execute the command     |\n| VKL_UNSUPPORTED_CPU   | the CPU is not supported (minimum ISA is SSE4.1)      |\n\nPossible error codes, i.e., valid named constants of type `VKLError`.\n\nThese error codes are either directly returned by some API functions, or\nare recorded to be later queried by the application via\n\n``` cpp\nVKLError vklDeviceGetLastErrorCode(VKLDevice);\n```\n\nA more descriptive error message can be queried by calling\n\n``` cpp\nconst char* vklDeviceGetLastErrorMsg(VKLDevice);\n```\n\nAlternatively, the application can also register a callback function of\ntype\n\n``` cpp\ntypedef void (*VKLErrorCallback)(void *, VKLError, const char* message);\n```\n\nvia\n\n``` cpp\nvoid vklDeviceSetErrorCallback(VKLDevice, VKLErrorFunc, void *);\n```\n\nto get notified when errors occur. Applications may be interested in\nmessages which Open VKL emits, whether for debugging or logging events.\nApplications can register a callback function of type\n\n``` cpp\ntypedef void (*VKLLogCallback)(void *, const char* message);\n```\n\nvia\n\n``` cpp\nvoid vklDeviceSetLogCallback(VKLDevice, VKLLogCallback, void *);\n```\n\nwhich Open VKL will use to emit log messages. Applications can clear\neither callback by passing `nullptr` instead of an actual function\npointer. By default, Open VKL uses `cout` and `cerr` to emit log and\nerror messages, respectively. The last parameter to\n`vklDeviceSetErrorCallback` and `vklDeviceSetLogCallback` is a user data\npointer. Open VKL passes this pointer to the callback functions as the\nfirst parameter. Note that in addition to setting the above callbacks,\nthis behavior can be changed via the device parameters and environment\nvariables described previously.\n\n## Basic data types\n\nOpen VKL defines 3-component vectors of integer and float types:\n\n``` cpp\ntypedef struct\n{\n  int x, y, z;\n} vkl_vec3i;\n\ntypedef struct\n{\n  float x, y, z;\n} vkl_vec3f;\n```\n\nVector versions of these are also defined in structure-of-array format\nfor 4, 8, and 16 wide types.\n\n``` cpp\ntypedef struct\n{\n  float x[WIDTH];\n  float y[WIDTH];\n  float z[WIDTH];\n} vkl_vvec3f##WIDTH;\n\ntypedef struct\n{\n  float lower[WIDTH], upper[WIDTH];\n} vkl_vrange1f##WIDTH;\n```\n\n1-D range and 3-D ranges are defined as ranges and boxes, with no vector\nversions:\n\n``` cpp\ntypedef struct\n{\n  float lower, upper;\n} vkl_range1f;\n\ntypedef struct\n{\n  vkl_vec3f lower, upper;\n} vkl_box3f;\n```\n\n## Object model\n\nObjects in Open VKL are exposed to the APIs as handles with internal\nreference counting for lifetime determination. Objects are created with\neach particular type’s `vklNew...` API entry point. For example,\n`vklNewData` and `vklNewVolume`.\n\nIn general, modifiable parameters to objects are modified using\n`vklSet...` functions based on the type of the parameter being set. The\nparameter name is passed as a string. Below are variants of `vklSet...`.\n\n``` cpp\nvoid vklSetBool(VKLObject object, const char *name, int b);\nvoid vklSetFloat(VKLObject object, const char *name, float x);\nvoid vklSetVec3f(VKLObject object, const char *name, float x, float y, float z);\nvoid vklSetInt(VKLObject object, const char *name, int x);\nvoid vklSetVec3i(VKLObject object, const char *name, int x, int y, int z);\nvoid vklSetData(VKLObject object, const char *name, VKLData data);\nvoid vklSetString(VKLObject object, const char *name, const char *s);\nvoid vklSetVoidPtr(VKLObject object, const char *name, void *v);\n```\n\nA more generic parameter setter is also available, which allows setting\nparameters beyond the explicit types above:\n\n``` cpp\nvoid vklSetParam(VKLObject object,\n                 const char *name,\n                 VKLDataType dataType,\n                 const void *mem);\n```\n\nNote that `mem` must always be a pointer *to* the object, otherwise\naccidental type casting can occur. This is especially true for pointer\ntypes (`VKL_VOID_PTR` and `VKLObject` handles), as they will implicitly\ncast to `void\\ *`, but be incorrectly interpreted.\n\nAfter parameters have been set, `vklCommit` must be called on the object\nto make them take effect.\n\nOpen VKL uses reference counting to manage the lifetime of all objects.\nTherefore one cannot explicitly “delete” any object. Instead, one can\nindicate the application does not need or will not access the given\nobject anymore by calling\n\n``` cpp\nvoid vklRelease(VKLObject);\n```\n\nThis decreases the object’s reference count. If the count reaches `0`\nthe object will automatically be deleted.\n\n## Managed data\n\nLarge data is passed to Open VKL via a `VKLData` handle created with\n`vklNewData`:\n\n``` cpp\nVKLData vklNewData(VKLDevice device,\n                   size_t numItems,\n                   VKLDataType dataType,\n                   const void *source,\n                   VKLDataCreationFlags dataCreationFlags,\n                   size_t byteStride);\n```\n\nData objects can be created as Open VKL owned\n(`dataCreationFlags = VKL_DATA_DEFAULT`), in which the library will make\na copy of the data for its use, or shared\n(`dataCreationFlags = VKL_DATA_SHARED_BUFFER`), which will try to use\nthe passed pointer for usage. The library is allowed to copy data when a\nvolume is committed. Note that for the `gpu` device, shared data buffers\nonly support source data from USM shared allocations.\n\nThe distance between consecutive elements in `source` is given in bytes\nwith `byteStride`. If the provided `byteStride` is zero, then it will be\ndetermined automatically as `sizeof(type)`. Open VKL owned data will be\ncompacted into a naturally-strided array on copy, regardless of the\noriginal `byteStride`.\n\nAs with other object types, when data objects are no longer needed they\nshould be released via `vklRelease`.\n\nThe enum type `VKLDataType` describes the different element types that\ncan be represented in Open VKL. The types accepted vary per volume; see\nthe volume section for specifics. Valid constants are listed in the\ntable below.\n\n| Type/Name                    | Description                                                                                  |\n|:-----------------------------|:---------------------------------------------------------------------------------------------|\n| VKL_DEVICE                   | API device object reference                                                                  |\n| VKL_DATA                     | data reference                                                                               |\n| VKL_OBJECT                   | generic object reference                                                                     |\n| VKL_VOLUME                   | volume object reference                                                                      |\n| VKL_STRING                   | C-style zero-terminated character string                                                     |\n| VKL_CHAR, VKL_VEC\\[234\\]C    | 8 bit signed character scalar and \\[234\\]-element vector                                     |\n| VKL_UCHAR, VKL_VEC\\[234\\]UC  | 8 bit unsigned character scalar and \\[234\\]-element vector                                   |\n| VKL_SHORT, VKL_VEC\\[234\\]S   | 16 bit unsigned integer scalar and \\[234\\]-element vector                                    |\n| VKL_USHORT, VKL_VEC\\[234\\]US | 16 bit unsigned integer scalar and \\[234\\]-element vector                                    |\n| VKL_INT, VKL_VEC\\[234\\]I     | 32 bit signed integer scalar and \\[234\\]-element vector                                      |\n| VKL_UINT, VKL_VEC\\[234\\]UI   | 32 bit unsigned integer scalar and \\[234\\]-element vector                                    |\n| VKL_LONG, VKL_VEC\\[234\\]L    | 64 bit signed integer scalar and \\[234\\]-element vector                                      |\n| VKL_ULONG, VKL_VEC\\[234\\]UL  | 64 bit unsigned integer scalar and \\[234\\]-element vector                                    |\n| VKL_HALF, VKL_VEC\\[234\\]H    | 16 bit half precision floating-point scalar and \\[234\\]-element vector (IEEE 754 `binary16`) |\n| VKL_FLOAT, VKL_VEC\\[234\\]F   | 32 bit single precision floating-point scalar and \\[234\\]-element vector                     |\n| VKL_DOUBLE, VKL_VEC\\[234\\]D  | 64 bit double precision floating-point scalar and \\[234\\]-element vector                     |\n| VKL_BOX\\[1234\\]I             | 32 bit integer box (lower + upper bounds)                                                    |\n| VKL_BOX\\[1234\\]F             | 32 bit single precision floating-point box (lower + upper bounds)                            |\n| VKL_LINEAR\\[23\\]F            | 32 bit single precision floating-point linear transform (\\[23\\] vectors)                     |\n| VKL_AFFINE\\[23\\]F            | 32 bit single precision floating-point affine transform (linear transform plus translation)  |\n| VKL_VOID_PTR                 | raw memory address                                                                           |\n\nValid named constants for `VKLDataType`.\n\n## Volume types\n\nOpen VKL currently supports structured volumes on regular and spherical\ngrids; unstructured volumes with tetrahedral, wedge, pyramid, and\nhexahedral primitive types; adaptive mesh refinement (AMR) volumes;\nsparse VDB volumes; and particle volumes. Volumes are created with\n`vklNewVolume` with a device and appropriate type string:\n\n``` cpp\nVKLVolume vklNewVolume(VKLDevice device, const char *type);\n```\n\nIn addition to the usual `vklSet...()` and `vklCommit()` APIs, the\nvolume bounding box can be queried:\n\n``` cpp\nvkl_box3f vklGetBoundingBox(VKLVolume volume);\n```\n\nThe number of attributes in a volume can also be queried:\n\n``` cpp\nunsigned int vklGetNumAttributes(VKLVolume volume);\n```\n\nFinally, the value range of the volume for a given attribute can be\nqueried:\n\n``` cpp\nvkl_range1f vklGetValueRange(VKLVolume volume, unsigned int attributeIndex);\n```\n\n### Structured Volumes\n\nStructured volumes only need to store the values of the samples, because\ntheir addresses in memory can be easily computed from a 3D position.\nData can be provided either per cell or per vertex (the default),\nselectable via the `cellCentered` parameter. This parameter also affects\nthe interpretation of the volume’s dimensions, which will be in units of\ncells or vertices, respectively. A volume with $(x, y, z)$ vertices will\nhave $(x-1, y-1, z-1)$ cells.\n\n#### Structured Regular Volumes\n\nA common type of structured volumes are regular grids, which are created\nby passing a type string of `\"structuredRegular\"` to `vklNewVolume`. The\nparameters understood by structured regular volumes are summarized in\nthe table below.\n\n| Type                  | Name                             | Default                            | Description                                                                                                                                                                                                                                |\n|:----------------------|:---------------------------------|:-----------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| vec3i                 | dimensions                       |                                    | number of values in each dimension $(x, y, z)$                                                                                                                                                                                             |\n| VKLData VKLData\\[\\]   | data                             |                                    | VKLData object(s) of volume data, supported types are:                                                                                                                                                                                     |\n|                       |                                  |                                    | `VKL_UCHAR`                                                                                                                                                                                                                                |\n|                       |                                  |                                    | `VKL_SHORT`                                                                                                                                                                                                                                |\n|                       |                                  |                                    | `VKL_USHORT`                                                                                                                                                                                                                               |\n|                       |                                  |                                    | `VKL_HALF`                                                                                                                                                                                                                                 |\n|                       |                                  |                                    | `VKL_FLOAT`                                                                                                                                                                                                                                |\n|                       |                                  |                                    | `VKL_DOUBLE`                                                                                                                                                                                                                               |\n|                       |                                  |                                    | Multiple attributes are supported through passing an array of VKLData objects.                                                                                                                                                             |\n| bool                  | cellCentered                     | false                              | indicates if data is provided per cell (true) or per vertex (false)                                                                                                                                                                        |\n| vec3f                 | gridOrigin                       | $(0, 0, 0)$                        | origin of the grid in object space                                                                                                                                                                                                         |\n| vec3f                 | gridSpacing                      | $(1, 1, 1)$                        | size of the grid cells in object space                                                                                                                                                                                                     |\n| affine3f              | indexToObject                    | 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 | Defines the transformation from index space to object space. In index space, the grid is an axis-aligned regular grid, and grid cells have size (1,1,1). This parameter takes precedence over `gridOrigin` and `gridSpacing`, if provided. |\n| vec3i                 | indexOrigin                      | $(0, 0, 0)$                        | Defines the index space origin of the volume. This translation is applied before any (`gridOrigin`, `gridSpacing`) or `indexToObject` transformation.                                                                                      |\n| uint32                | temporalFormat                   | `VKL_TEMPORAL_FORMAT_CONSTANT`     | The temporal format for this volume. Use `VKLTemporalFormat` for named constants. Structured regular volumes support `VKL_TEMPORAL_FORMAT_CONSTANT`, `VKL_TEMPORAL_FORMAT_STRUCTURED`, and `VKL_TEMPORAL_FORMAT_UNSTRUCTURED`.             |\n| int                   | temporallyStructuredNumTimesteps |                                    | For temporally structured variation, number of timesteps per voxel. Only valid if `temporalFormat` is `VKL_TEMPORAL_FORMAT_STRUCTURED`.                                                                                                    |\n| uint32\\[\\] uint64\\[\\] | temporallyUnstructuredIndices    |                                    | For temporally unstructured variation, indices to `data` time series beginning per voxel. Only valid if `temporalFormat` is `VKL_TEMPORAL_FORMAT_UNSTRUCTURED`.                                                                            |\n| float\\[\\]             | temporallyUnstructuredTimes      |                                    | For temporally unstructured variation, time values corresponding to values in `data`. Only valid if `temporalFormat` is `VKL_TEMPORAL_FORMAT_UNSTRUCTURED`.                                                                                |\n| float\\[\\]             | background                       | `VKL_BACKGROUND_UNDEFINED`         | For each attribute, the value that is returned when sampling an undefined region outside the volume domain.                                                                                                                                |\n\nConfiguration parameters for structured regular (`\"structuredRegular\"`)\nvolumes.\n\nStructured regular volumes support temporally structured and temporally\nunstructured temporal variation. See section ‘Temporal Variation’ for\nmore detail.\n\nThe following additional parameters can be set both on\n`\"structuredRegular\"` volumes and their sampler objects. Sampler object\nparameters default to volume parameters.\n\n| Type | Name           | Default             | Description                                                                                                     |\n|:-----|:---------------|:--------------------|:----------------------------------------------------------------------------------------------------------------|\n| int  | filter         | `VKL_FILTER_LINEAR` | The filter used for reconstructing the field. Use `VKLFilter` for named constants.                              |\n| int  | gradientFilter | `filter`            | The filter used for reconstructing the field during gradient computations. Use `VKLFilter` for named constants. |\n\nConfiguration parameters for structured regular (`\"structuredRegular\"`)\nvolumes and their sampler objects.\n\n##### Reconstruction filters\n\nStructured regular volumes support the filter types\n`VKL_FILTER_NEAREST`, `VKL_FILTER_LINEAR`, and `VKL_FILTER_CUBIC` for\nboth `filter` and `gradientFilter`.\n\nNote that when `gradientFilter` is set to `VKL_FILTER_NEAREST`,\ngradients are always $(0, 0, 0)$.\n\n#### Structured Spherical Volumes\n\nStructured spherical volumes are also supported, which are created by\npassing a type string of `\"structuredSpherical\"` to `vklNewVolume`. The\ngrid dimensions and parameters are defined in terms of radial distance\n($r$), inclination angle ($\\theta$), and azimuthal angle ($\\phi$),\nconforming with the ISO convention for spherical coordinate systems.\nStructured spherical volumes currently only support vertex-centered\ndata. The coordinate system and parameters understood by structured\nspherical volumes are summarized below.\n\n![Structured spherical volume coordinate system: radial distance ($r$),\ninclination angle ($\\theta$), and azimuthal angle\n($\\phi$).](https://openvkl.github.io/images/structured_spherical_coords.png)\n\n| Type                | Name        |          Default           | Description                                                                                                                                          |\n|:--------------------|:------------|:--------------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------|\n| vec3i               | dimensions  |                            | number of voxels in each dimension $(r, \\theta, \\phi)$                                                                                               |\n| VKLData VKLData\\[\\] | data        |                            | VKLData object(s) of voxel data, supported types are:                                                                                                |\n|                     |             |                            | `VKL_UCHAR`                                                                                                                                          |\n|                     |             |                            | `VKL_SHORT`                                                                                                                                          |\n|                     |             |                            | `VKL_USHORT`                                                                                                                                         |\n|                     |             |                            | `VKL_HALF`                                                                                                                                           |\n|                     |             |                            | `VKL_FLOAT`                                                                                                                                          |\n|                     |             |                            | `VKL_DOUBLE`                                                                                                                                         |\n|                     |             |                            | Multiple attributes are supported through passing an array of VKLData objects.                                                                       |\n| vec3f               | gridOrigin  |        $(0, 0, 0)$         | origin of the grid in units of $(r, \\theta, \\phi)$; angles in degrees                                                                                |\n| vec3f               | gridSpacing |  $(1, \\theta_0, \\phi_0)$   | size of the grid cells in units of $(r, \\theta, \\phi)$; angles in degrees. The defaults \\_0 and \\_0 are such that the volume occupies a full sphere. |\n| float\\[\\]           | background  | `VKL_BACKGROUND_UNDEFINED` | For each attribute, the value that is returned when sampling an undefined region outside the volume domain.                                          |\n\nConfiguration parameters for structured spherical\n(`\"structuredSpherical\"`) volumes.\n\nThese grid parameters support flexible specification of spheres,\nhemispheres, spherical shells, spherical wedges, and so forth. The grid\nextents (computed as\n$[gridOrigin, gridOrigin + (dimensions - 1) * gridSpacing]$) however\nmust be constrained such that:\n\n- $r \\geq 0$\n- $0 \\leq \\theta \\leq 180$\n- $0 \\leq \\phi \\leq 360$\n\nThe following additional parameters can be set both on\n`\"structuredSpherical\"` volumes and their sampler objects. Sampler\nobject parameters default to volume parameters.\n\n| Type | Name           | Default             | Description                                                                                                     |\n|:-----|:---------------|:--------------------|:----------------------------------------------------------------------------------------------------------------|\n| int  | filter         | `VKL_FILTER_LINEAR` | The filter used for reconstructing the field. Use `VKLFilter` for named constants.                              |\n| int  | gradientFilter | `filter`            | The filter used for reconstructing the field during gradient computations. Use `VKLFilter` for named constants. |\n\nConfiguration parameters for structured spherical\n(`\"structuredSpherical\"`) volumes and their sampler objects.\n\n### Adaptive Mesh Refinement (AMR) Volumes\n\nOpen VKL currently supports block-structured (Berger-Colella) AMR\nvolumes. Volumes are specified as a list of blocks, which exist at\nlevels of refinement in potentially overlapping regions. Blocks exist in\na tree structure, with coarser refinement level blocks containing finer\nblocks. The cell width is equal for all blocks at the same refinement\nlevel, though blocks at a coarser level have a larger cell width than\nfiner levels.\n\nThere can be any number of refinement levels and any number of blocks at\nany level of refinement.\n\nBlocks are defined by three parameters: their bounds, the refinement\nlevel in which they reside, and the scalar data contained within each\nblock.\n\nNote that cell widths are defined *per refinement level*, not per block.\n\nAMR volumes are created by passing the type string `\"amr\"` to\n`vklNewVolume`, and have the following parameters:\n\n| Type        | Name         | Default                    | Description                                                                                                                          |\n|:------------|:-------------|:---------------------------|:-------------------------------------------------------------------------------------------------------------------------------------|\n| float\\[\\]   | cellWidth    |                            | \\[data\\] array of each level’s cell width                                                                                            |\n| box3i\\[\\]   | block.bounds |                            | \\[data\\] array of each block’s bounds (in voxels)                                                                                    |\n| int\\[\\]     | block.level  |                            | \\[data\\] array of each block’s refinement level                                                                                      |\n| VKLData\\[\\] | block.data   |                            | \\[data\\] array of each block’s VKLData object containing the actual scalar voxel data. Currently only `VKL_FLOAT` data is supported. |\n| vec3f       | gridOrigin   | $(0, 0, 0)$                | origin of the grid in object space                                                                                                   |\n| vec3f       | gridSpacing  | $(1, 1, 1)$                | size of the grid cells in object space                                                                                               |\n| float       | background   | `VKL_BACKGROUND_UNDEFINED` | The value that is returned when sampling an undefined region outside the volume domain.                                              |\n\nConfiguration parameters for AMR (`\"amr\"`) volumes.\n\nNote that the `gridOrigin` and `gridSpacing` parameters act just like\nthe structured volume equivalent, but they only modify the root\n(coarsest level) of refinement.\n\nThe following additional parameters can be set both on `\"amr\"` volumes\nand their sampler objects. Sampler object parameters default to volume\nparameters.\n\n| Type           | Name   |           Default | Description                                            |\n|:---------------|:-------|------------------:|:-------------------------------------------------------|\n| `VKLAMRMethod` | method | `VKL_AMR_CURRENT` | `VKLAMRMethod` sampling method. Supported methods are: |\n|                |        |                   | `VKL_AMR_CURRENT`                                      |\n|                |        |                   | `VKL_AMR_FINEST`                                       |\n|                |        |                   | `VKL_AMR_OCTANT`                                       |\n\nConfiguration parameters for AMR (`\"AMR\"`) volumes and their sampler\nobjects.\n\nOpen VKL’s AMR implementation was designed to cover Berger-Colella \\[1\\]\nand Chombo \\[2\\] AMR data. The `method` parameter above determines the\ninterpolation method used when sampling the volume.\n\n- `VKL_AMR_CURRENT` finds the finest refinement level at that cell and\n  interpolates through this “current” level\n- `VKL_AMR_FINEST` will interpolate at the closest existing cell in the\n  volume-wide finest refinement level regardless of the sample cell’s\n  level\n- `VKL_AMR_OCTANT` interpolates through all available refinement levels\n  at that cell. This method avoids discontinuities at refinement level\n  boundaries at the cost of performance\n\nGradients are computed using finite differences, using the `method`\ndefined on the sampler.\n\nDetails and more information can be found in the publication for the\nimplementation \\[3\\].\n\n1.  M. J. Berger, and P. Colella. “Local adaptive mesh refinement for\n    shock hydrodynamics.” Journal of Computational Physics 82.1 (1989):\n    64-84. DOI: 10.1016/0021-9991(89)90035-1\n2.  M. Adams, P. Colella, D. T. Graves, J.N. Johnson, N.D. Keen, T. J.\n    Ligocki. D. F. Martin. P.W. McCorquodale, D. Modiano. P.O. Schwartz,\n    T.D. Sternberg and B. Van Straalen, Chombo Software Package for AMR\n    Applications - Design Document, Lawrence Berkeley National\n    Laboratory Technical Report LBNL-6616E.\n3.  I. Wald, C. Brownlee, W. Usher, and A. Knoll. CPU volume rendering\n    of adaptive mesh refinement data. SIGGRAPH Asia 2017 Symposium on\n    Visualization on - SA ’17, 18(8), 1–8. DOI: 10.1145/3139295.3139305\n\n### Unstructured Volumes\n\nUnstructured volumes can have their topology and geometry freely\ndefined. Geometry can be composed of tetrahedral, hexahedral, wedge or\npyramid cell types. The data format used is compatible with VTK and\nconsists of multiple arrays: vertex positions and values, vertex\nindices, cell start indices, cell types, and cell values.\n\nSampled cell values can be specified either per-vertex (`vertex.data`)\nor per-cell (`cell.data`). If both arrays are set, `cell.data` takes\nprecedence.\n\nSimilar to a mesh, each cell is formed by a group of indices into the\nvertices. For each vertex, the corresponding (by array index) data value\nwill be used for sampling when rendering, if specified. The index order\nfor a tetrahedron is the same as `VTK_TETRA`: bottom triangle\ncounterclockwise, then the top vertex.\n\nFor hexahedral cells, each hexahedron is formed by a group of eight\nindices into the vertices and data values. Vertex ordering is the same\nas `VTK_HEXAHEDRON`: four bottom vertices counterclockwise, then top\nfour counterclockwise.\n\nFor wedge cells, each wedge is formed by a group of six indices into the\nvertices and data values. Vertex ordering is the same as `VTK_WEDGE`:\nthree bottom vertices counterclockwise, then top three counterclockwise.\n\nFor pyramid cells, each cell is formed by a group of five indices into\nthe vertices and data values. Vertex ordering is the same as\n`VTK_PYRAMID`: four bottom vertices counterclockwise, then the top\nvertex.\n\nTo maintain VTK data compatibility, the `index` array may be specified\nwith cell sizes interleaved with vertex indices in the following format:\n$n, id_1, ..., id_n, m, id_1, ..., id_m$. This alternative `index` array\nlayout can be enabled through the `indexPrefixed` flag (in which case,\nthe `cell.type` parameter should be omitted).\n\nGradients are computed using finite differences.\n\nUnstructured volumes are created by passing the type string\n`\"unstructured\"` to `vklNewVolume`, and have the following parameters:\n\n| Type                    | Name               | Default                    | Description                                                                                                                                             |\n|:------------------------|:-------------------|:---------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------|\n| vec3f\\[\\]               | vertex.position    |                            | \\[data\\] array of vertex positions                                                                                                                      |\n| float\\[\\]               | vertex.data        |                            | \\[data\\] array of vertex data values to be sampled                                                                                                      |\n| uint32\\[\\] / uint64\\[\\] | index              |                            | \\[data\\] array of indices (into the vertex array(s)) that form cells                                                                                    |\n| bool                    | indexPrefixed      | false                      | indicates that the `index` array is provided in a VTK-compatible format, where the indices of each cell are prefixed with the number of vertices        |\n| uint32\\[\\] / uint64\\[\\] | cell.index         |                            | \\[data\\] array of locations (into the index array), specifying the first index of each cell                                                             |\n| float\\[\\]               | cell.data          |                            | \\[data\\] array of cell data values to be sampled                                                                                                        |\n| uint8\\[\\]               | cell.type          |                            | \\[data\\] array of cell types (VTK compatible). Supported types are:                                                                                     |\n|                         |                    |                            | `VKL_TETRAHEDRON`                                                                                                                                       |\n|                         |                    |                            | `VKL_HEXAHEDRON`                                                                                                                                        |\n|                         |                    |                            | `VKL_WEDGE`                                                                                                                                             |\n|                         |                    |                            | `VKL_PYRAMID`                                                                                                                                           |\n| bool                    | hexIterative       | false                      | hexahedron interpolation method, defaults to fast non-iterative version which could have rendering inaccuracies may appear if hex is not parallelepiped |\n| bool                    | precomputedNormals | false                      | whether to accelerate by precomputing, at a cost of 12 bytes/face                                                                                       |\n| float                   | background         | `VKL_BACKGROUND_UNDEFINED` | The value that is returned when sampling an undefined region outside the volume domain.                                                                 |\n\nConfiguration parameters for unstructured (`\"unstructured\"`) volumes.\n\n### VDB Volumes\n\nVDB volumes implement a data structure that is very similar to the data\nstructure outlined in Museth \\[1\\].\n\nThe data structure is a hierarchical regular grid at its core: Nodes are\nregular grids, and each grid cell may either store a constant value\n(this is called a tile), or child pointers.\n\nNodes in VDB trees are wide: Nodes on the first level have a resolution\nof 32^3 voxels by default, on the next level 16^3, and on the leaf level\n8^3 voxels. All nodes on a given level have the same resolution. This\nmakes it easy to find the node containing a coordinate using shift\noperations (cp. \\[1\\]).\n\nVDB leaf nodes are implicit in Open VKL: they are stored as pointers to\nuser-provided data.\n\n![Structure of `\"vdb\"` volumes in the default\nconfiguration](https://openvkl.github.io/images/vdb_structure.png)\n\nVDB volumes interpret input data as constant cells (which are then\npotentially filtered). This is in contrast to `structuredRegular`\nvolumes, which can have either a vertex-centered or cell-centered\ninterpretation.\n\nThe VDB implementation in Open VKL follows the following goals:\n\n- Efficient data structure traversal on vector architectures.\n\n- Enable the use of industry-standard .vdb files created through the\n  OpenVDB library.\n\n- Compatibility with OpenVDB on a leaf data level, so that .vdb files\n  may be loaded with minimal overhead.\n\nVDB volumes are created by passing the type string `\"vdb\"` to\n`vklNewVolume`, and have the following parameters:\n\n| Type               | Name                                  | Default                            | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |\n|:-------------------|:--------------------------------------|:-----------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| affine3f float\\[\\] | indexToObject                         | 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 | Defines the transformation from index space to object space. In index space, the grid is an axis-aligned regular grid, and leaf voxels have size (1,1,1). A `vkl_affine3f` can be provided; alternatively an array of 12 values of type `float` can be used, where the first 9 values are interpreted as a row-major linear transformation matrix, and the last 3 values are the translation of the grid origin.                                                                                                                      |\n| uint32\\[\\]         | node.format                           |                                    | For each input node, the data format. Currently supported are `VKL_FORMAT_TILE` for tiles, and `VKL_FORMAT_DENSE_ZYX` for nodes that are dense regular grids.                                                                                                                                                                                                                                                                                                                                                                         |\n| uint32\\[\\]         | node.level                            |                                    | For each input node, the level on which this node exists. Tiles may exist on levels \\[1, `VKL_VDB_NUM_LEVELS-1`\\], all other nodes may only exist on level `VKL_VDB_NUM_LEVELS-1`.                                                                                                                                                                                                                                                                                                                                                    |\n| vec3i\\[\\]          | node.origin                           |                                    | For each input node, the node origin index.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |\n| VKLData\\[\\]        | node.data                             |                                    | For each input node, the attribute data. Single-attribute volumes may have one array provided per node, while multi-attribute volumes require an array per attribute for each node. Nodes with format `VKL_FORMAT_TILE` are expected to have single-entry arrays per attribute. Nodes with format `VKL_FORMAT_DENSE_ZYX` are expected to have arrays with `vklVdbLevelNumVoxels(level[i])` entries per attribute. `VKL_HALF` and `VKL_FLOAT` data is currently supported; all nodes for a given attribute must be the same data type. |\n| uint32\\[\\]         | node.temporalFormat                   | `VKL_TEMPORAL_FORMAT_CONSTANT`     | The temporal format for this volume. Use `VKLTemporalFormat` for named constants. VDB volumes support `VKL_TEMPORAL_FORMAT_CONSTANT`, `VKL_TEMPORAL_FORMAT_STRUCTURED`, and `VKL_TEMPORAL_FORMAT_UNSTRUCTURED`.                                                                                                                                                                                                                                                                                                                       |\n| int\\[\\]            | node.temporallyStructuredNumTimesteps |                                    | For temporally structured variation, number of timesteps per voxel. Only valid if `temporalFormat` is `VKL_TEMPORAL_FORMAT_STRUCTURED`.                                                                                                                                                                                                                                                                                                                                                                                               |\n| VKLData\\[\\]        | node.temporallyUnstructuredIndices    |                                    | For temporally unstructured variation, beginning per voxel. Supported data types for each node are `VKL_UINT` and `VKL_ULONG`. Only valid if `temporalFormat` is `VKL_TEMPORAL_FORMAT_UNSTRUCTURED`.                                                                                                                                                                                                                                                                                                                                  |\n| VKLData\\[\\]        | node.temporallyUnstructuredTimes      |                                    | For temporally unstructured variation, time values corresponding to values in `node.data`. For each node, the data must be of type `VKL_FLOAT`. Only valid if `temporalFormat` is `VKL_TEMPORAL_FORMAT_UNSTRUCTURED`.                                                                                                                                                                                                                                                                                                                 |\n| VKLData\\[\\]        | nodesPackedDense                      |                                    | Optionally provided instead of `node.data`, for each attribute a single array of all dense node data (`VKL_FORMAT_DENSE_ZYX` only) in a contiguous layout, provided in the same order as the corresponding `node.*` parameters. This packed layout may be more performant. Supported for temporally constant data only.                                                                                                                                                                                                               |\n| VKLData\\[\\]        | nodesPackedTile                       |                                    | Optionally provided instead of `node.data`, for each attribute a single array of all tile node data (`VKL_FORMAT_TILE` only) in a contiguous layout, provided in the same order as the corresponding `node.*` parameters. This packed layout may be more performant. Supported for temporally constant data only.                                                                                                                                                                                                                     |\n| float\\[\\]          | background                            | `VKL_BACKGROUND_UNDEFINED`         | For each attribute, the value that is returned when sampling an undefined region outside the volume domain.                                                                                                                                                                                                                                                                                                                                                                                                                           |\n| box3i              | indexClippingBounds                   |                                    | Clips the volume to the specified index-space bounding box. This is useful for volumes with dimensions that are not even multiples of the leaf node dimensions, or .vdb files with restrictive active voxel bounding boxes.                                                                                                                                                                                                                                                                                                           |\n\nConfiguration parameters for VDB (`\"vdb\"`) volumes.\n\nThe level, origin, format, and data parameters must have the same size,\nand there must be at least one valid node or `commit()` will fail. The\n`nodesPackedDense` and `nodesPackedTile` parameters may be provided\ninstead of `node.data`; this packed data layout may provide better\nperformance.\n\nVDB volumes support temporally structured and temporally unstructured\ntemporal variation. See section ‘Temporal Variation’ for more detail.\n\nThe following additional parameters can be set both on `vdb` volumes and\ntheir sampler objects (sampler object parameters default to volume\nparameters).\n\n| Type | Name             | Default                | Description                                                                                                     |\n|:-----|:-----------------|:-----------------------|:----------------------------------------------------------------------------------------------------------------|\n| int  | filter           | `VKL_FILTER_LINEAR`    | The filter used for reconstructing the field. Use `VKLFilter` for named constants.                              |\n| int  | gradientFilter   | `filter`               | The filter used for reconstructing the field during gradient computations. Use `VKLFilter` for named constants. |\n| int  | maxSamplingDepth | `VKL_VDB_NUM_LEVELS`-1 | Do not descend further than to this depth during sampling.                                                      |\n\nConfiguration parameters for VDB (`\"vdb\"`) volumes and their sampler\nobjects.\n\nVDB volume objects support the following observers:\n\n| Name      | Buffer Type | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |\n|:----------|-------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| InnerNode | float\\[\\]   | Return an array of bounding boxes, along with value ranges, of inner nodes in the data structure. The bounding box is given in object space. For a volume with M attributes, the entries in this array are (6+2\\*M)-tuples `(minX, minY, minZ, maxX, maxY, maxZ, lower_0, upper_0, lower_1, upper_1, ...)`. This is in effect a low resolution representation of the volume. The InnerNode observer can be parametrized using `int maxDepth` to control the depth at which inner nodes are returned. Note that the observer will also return leaf nodes or tiles at lower levels if they exist. |\n\nObservers supported by VDB (`\"vdb\"`) volumes.\n\nVDB sampler objects support the following observers:\n\n| Name           | Buffer Type | Description                                                                                                                                                                                                                                    |\n|:---------------|:------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| LeafNodeAccess | uint32\\[\\]  | This observer returns an array with as many entries as input nodes were passed. If the input node i was accessed during traversal, then the ith entry in this array has a nonzero value. This can be used for on-demand loading of leaf nodes. |\n\nObservers supported by sampler objects created on VDB (`\"vdb\"`) volumes.\n\n#### Reconstruction filters\n\nVDB volumes support the filter types `VKL_FILTER_NEAREST`,\n`VKL_FILTER_LINEAR`, and `VKL_FILTER_CUBIC` for both `filter` and\n`gradientFilter`.\n\nNote that when `gradientFilter` is set to `VKL_FILTER_NEAREST`,\ngradients are always $(0, 0, 0)$.\n\n#### Major differences to OpenVDB\n\n- Open VKL implements sampling in ISPC, and can exploit wide SIMD\n  architectures.\n\n- VDB volumes in Open VKL are read-only once committed, and designed for\n  rendering only. Authoring or manipulating datasets is not in the scope\n  of this implementation.\n\n- The only supported field types are `VKL_HALF` and `VKL_FLOAT` at this\n  point. Other field types may be supported in the future. Note that\n  multi-attribute volumes may be used to represent multi-component\n  (e.g. vector) fields.\n\n- The root level in Open VKL has a single node with resolution 64^3\n  (cp. \\[1\\]. OpenVDB uses a hash map, instead).\n\n- Open VKL supports four-level vdb volumes. The resolution of each level\n  can be configured at compile time using CMake variables.\n\n  - `VKL_VDB_LOG_RESOLUTION_0` sets the base 2 logarithm of the root\n    level resolution. This variable defaults to 6, which means that the\n    root level has a resolution of $(2^6)^3 = 64^3$.\n  - `VKL_VDB_LOG_RESOLUTION_1` and `VKL_VDB_LOG_RESOLUTION_2` default to\n    5 and 4, respectively. This matches the default Open VDB resolution\n    for inner levels.\n  - `VKL_VDB_LOG_RESOLUTION_3` set the base 2 logarithm of the leaf\n    level resolution, and defaults to 3. Therefore, leaf nodes have a\n    resolution of $8^3$ voxels. Again, this matches the Open VDB\n    default. The default settings lead to a domain resolution of\n    $2^18^3=262144^3$ voxels.\n\n#### Loading OpenVDB .vdb files\n\nFiles generated with OpenVDB can be loaded easily since Open VKL `vdb`\nvolumes implement the same leaf data layout. This means that OpenVDB\nleaf data pointers can be passed to Open VKL using shared data buffers,\navoiding copy operations.\n\nAn example of this can be found in\n`utility/vdb/include/openvkl/utility/vdb/OpenVdbGrid.h`, where the class\n`OpenVdbFloatGrid` encapsulates the necessary operations. This class is\nalso accessible through the `vklExamples` application using the `-file`\nand `-field` command line arguments.\n\nTo use this example feature, compile Open VKL with `OpenVDB_ROOT`\npointing to the OpenVDB prefix.\n\n1.  Museth, K. VDB: High-Resolution Sparse Volumes with Dynamic\n    Topology. ACM Transactions on Graphics 32(3), 2013. DOI:\n    10.1145/2487228.2487235\n\n### Particle Volumes\n\nParticle volumes consist of a set of points in space. Each point has a\nposition, a radius, and a weight typically associated with an attribute.\nA radial basis function defines the contribution of that particle.\nCurrently, we use the Gaussian radial basis function,\n\nphi(P) = w \\* exp( -0.5 \\* ((P - p) / r)^2 )\n\nwhere P is the particle position, p is the sample position, r is the\nradius and w is the weight.\n\nAt each sample, the scalar field value is then computed as the sum of\neach radial basis function phi, for each particle that overlaps it.\nGradients are similarly computed, based on the summed analytical\ncontributions of each contributing particle.\n\nParticles with a radius less than or equal to zero are ignored. At least\none valid particle (radius greater than zero) must be provided.\n\nThe Open VKL implementation is similar to direct evaluation of samples\nin Reda et al.\\[2\\]. It uses an Embree-built BVH with a custom\ntraversal, similar to the method in \\[1\\].\n\nParticle volumes are created by passing the type string `\"particle\"` to\n`vklNewVolume`, and have the following parameters:\n\n| Type      | Name                    | Default | Description                                                                                                                                                                                                                                                                                                                                                                                                                                        |\n|:----------|:------------------------|:--------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| vec3f\\[\\] | particle.position       |         | \\[data\\] array of particle positions                                                                                                                                                                                                                                                                                                                                                                                                               |\n| float\\[\\] | particle.radius         |         | \\[data\\] array of particle radii                                                                                                                                                                                                                                                                                                                                                                                                                   |\n| float\\[\\] | particle.weight         | null    | \\[data\\] (optional) array of particle weights, specifying the height of the kernel.                                                                                                                                                                                                                                                                                                                                                                |\n| float     | radiusSupportFactor     | 3.0     | The multipler of the particle radius required for support. Larger radii ensure smooth results at the cost of performance. In the Gaussian kernel, the the radius is one standard deviation (sigma), so a `radiusSupportFactor` of 3 corresponds to 3\\*sigma.                                                                                                                                                                                       |\n| float     | clampMaxCumulativeValue | 0       | The maximum cumulative value possible, set by user. All cumulative values will be clamped to this, and further traversal (RBF summation) of particle contributions will halt when this value is reached. A value of zero or less turns this off.                                                                                                                                                                                                   |\n| bool      | estimateValueRanges     | true    | Enable heuristic estimation of value ranges which are used in internal acceleration structures for interval and hit iterators, as well as for determining the volume’s overall value range. When set to `false`, the user *must* specify `clampMaxCumulativeValue`, and all value ranges will be assumed \\[0, `clampMaxCumulativeValue`\\]. Disabling this may improve volume commit time, but will make interval and hit iteration less efficient. |\n\nConfiguration parameters for particle (`\"particle\"`) volumes.\n\n1.  Knoll, A., Wald, I., Navratil, P., Bowen, A., Reda, K., Papka, M.E.\n    and Gaither, K. (2014), RBF Volume Ray Casting on Multicore and\n    Manycore CPUs. Computer Graphics Forum, 33: 71-80.\n    doi:10.1111/cgf.12363\n\n2.  K. Reda, A. Knoll, K. Nomura, M. E. Papka, A. E. Johnson and J.\n    Leigh, “Visualizing large-scale atomistic simulations in\n    ultra-resolution immersive environments,” 2013 IEEE Symposium on\n    Large-Scale Data Analysis and Visualization (LDAV), Atlanta, GA,\n    2013, pp. 59-65.\n\n## Temporal Variation\n\nOpen VKL supports two types of temporal variation: temporally structured\nand temporally unstructured. When one of these modes is enabled, the\nvolume can be sampled at different times. In both modes, time is assumed\nto vary between zero and one. This can be useful for implementing\nrenderers with motion blur, for example.\n\nTemporal variation is generally configured through a parameter\n`temporalFormat`, which accepts constants from the `VKLTemporalFormat`\nenum, though not all modes may be supported by all volumes. On volumes\nthat expect multiple input nodes, the parameter is an array\n`node.temporalFormat`, and must provide one value per node. Multiple\nattributes in a voxel share the same temporal configuration. Please\nrefer to the individual volume sections above to find out supported for\neach volume type.\n\n`temporalFormat` defaults to `VKL_TEMPORAL_FORMAT_CONSTANT` for all\nvolume types. This means that no temporal variation is present in the\ndata.\n\nTemporally structured variation is configured by setting\n`temporalFormat` to `VKL_TEMPORAL_FORMAT_STRUCTURED`. In this mode, the\nvolume expects an additional parameter\n`[node.]temporallyStructuredNumTimesteps`, which specifies how many time\nsteps are provided for all voxels, and must be at least 2. A volume, or\nnode, with $N$ voxels expects $N * temporallyStructuredNumTimesteps$\nvalues for each attribute. The values are assumed evenly spaced over\ntimes $[0, 1]$: $\\{0, 1/(N-1), ..., 1\\}$\n\nTemporally unstructured variation supports differing time step counts\nand sample times per voxel. For $N$ input voxels,\n`temporallyUnstructuredIndices` is an array of $N+1$ indices. Voxel $i$\nhas\n$N_i = [temporallyUnstructuredIndices[i+1]-temporallyUnstructuredIndices[i])$\ntemporal samples starting at index $temporallyUnstructuredIndices[i]$.\n`temporallyUnstructuredTimes` specifies the times corresponding to the\nsample values; the time values for each voxel must be between zero and\none and strictly increasing: $t0 \u003c t1 \u003c ... \u003c tN$. To return a value at\nsample time t, $t0 \u003c= t \u003c= tN$, Open VKL will interpolate linearly from\nthe two nearest time steps. Time values outside this range are clamped\nto $[t0, tN]$.\n\n## Sampler Objects\n\nComputing the value of a volume at an object space coordinate is done\nusing the sampling API, and sampler objects. Sampler objects can be\ncreated using\n\n``` cpp\nVKLSampler vklNewSampler(VKLVolume volume);\n```\n\nSampler objects may then be parametrized with traversal parameters.\nAvailable parameters are defined by volumes, and are a subset of the\nvolume parameters. As an example, `filter` can be set on both `vdb`\nvolumes and their sampler objects. The volume parameter is used as the\ndefault for sampler objects. The sampler object parameter provides an\noverride per ray. More detail on parameters can be found in the sections\non volumes. Use `vklCommit()` to commit parameters to the sampler\nobject.\n\n## Sampling\n\nThe scalar API takes a volume and coordinate, and returns a float value.\nThe volume’s background value (by default `VKL_BACKGROUND_UNDEFINED`) is\nreturned for probe points outside the volume. The attribute index\nselects the scalar attribute of interest; not all volumes support\nmultiple attributes. The time value, which must be between 0 and 1,\nspecifies the sampling time. For temporally constant volumes, this value\nhas no effect.\n\nFor the `cpu` device, the scalar sampling API is:\n\n``` cpp\nfloat vklComputeSample(const VKLSampler *sampler,\n                       const vkl_vec3f *objectCoordinates,\n                       unsigned int attributeIndex,\n                       float time);\n```\n\nwhile on the `gpu` device, it is:\n\n``` cpp\nfloat vklComputeSample(const VKLSampler *sampler,\n                       const vkl_vec3f *objectCoordinates,\n                       unsigned int attributeIndex,\n                       float time,\n                       const VKLFeatureFlags featureFlags);\n```\n\nNote that the `gpu` sampling API introduces an additional `featureFlags`\nargument. These provided “feature flags” allow Open VKL to prune\nunnecessary code during just-in-time (JIT) compilation on GPU, providing\npotentially significant performance gains. See section ‘Feature flag\nusage on GPU’ for details.\n\n### Vector-wide and Stream-wide Sampling (CPU device only)\n\nOn the `cpu` device, vector-wide and stream-wide sampling APIs are also\nprovided.\n\nVector versions allow sampling at 4, 8, or 16 positions at once.\nDepending on the machine type and Open VKL device implementation, these\ncan give greater performance. An active lane mask `valid` is passed in\nas an array of integers; set 0 for lanes to be ignored, -1 for active\nlanes. An array of time values corresponding to each object coordinate\nmay be provided; a `NULL` value indicates all times are zero.\n\n``` cpp\nvoid vklComputeSample4(const int *valid,\n                       const VKLSampler *sampler,\n                       const vkl_vvec3f4 *objectCoordinates,\n                       float *samples,\n                       unsigned int attributeIndex,\n                       const float *times);\n\nvoid vklComputeSample8(const int *valid,\n                       const VKLSampler *sampler,\n                       const vkl_vvec3f8 *objectCoordinates,\n                       float *samples,\n                       unsigned int attributeIndex,\n                       const float *times);\n\nvoid vklComputeSample16(const int *valid,\n                        const VKLSampler *sampler,\n                        const vkl_vvec3f16 *objectCoordinates,\n                        float *samples,\n                        unsigned int attributeIndex,\n                        const float *times);\n```\n\nA stream version allows sampling an arbitrary number of positions at\nonce. While the vector version requires coordinates to be provided in a\nstructure-of-arrays layout, the stream version allows coordinates to be\nprovided in an array-of-structures layout. Thus, the stream API can be\nused to avoid reformatting of data by the application. As with the\nvector versions, the stream API can give greater performance than the\nscalar API.\n\n``` cpp\n  void vklComputeSampleN(const VKLSampler *sampler,\n                         unsigned int N,\n                         const vkl_vec3f *objectCoordinates,\n                         float *samples,\n                         unsigned int attributeIndex,\n                         const float *times);\n```\n\nAll of the above sampling APIs can be used, regardless of the device’s\nnative SIMD width.\n\n### Sampling Multiple Attributes\n\nOpen VKL provides additional APIs for sampling multiple scalar\nattributes in a single call through the `vklComputeSampleM*()`\ninterfaces. Beyond convenience, these can give improved performance\nrelative to the single attribute sampling APIs. As with the single\nattribute APIs, sampling time values may be specified; note that these\nare provided per object coordinate only (rather than separately per\nattribute).\n\nA scalar API supports sampling `M` attributes specified by\n`attributeIndices` on a single object space coordinate:\n\nFor the `cpu` device, the scalar sampling API is:\n\n``` cpp\nvoid vklComputeSampleM(const VKLSampler *sampler,\n                       const vkl_vec3f *objectCoordinates,\n                       float *samples,\n                       unsigned int M,\n                       const unsigned int *attributeIndices,\n                       float time);\n```\n\nwhile on the `gpu` device, it is:\n\n``` cpp\nvoid vklComputeSampleM(const VKLSampler *sampler,\n                       const vkl_vec3f *objectCoordinates,\n                       float *samples,\n                       unsigned int M,\n                       const unsigned int *attributeIndices,\n                       float time,\n                       const VKLFeatureFlags featureFlags);\n```\n\nAgain, see section ‘Feature flag usage on GPU’ for details on feature\nflags.\n\n#### Vector-wide and Stream-wide Multi-Attribute Sampling (CPU device only)\n\nOn the `cpu` device, vector-wide and stream-wide sampling APIs are also\nprovided.\n\nVector versions allow sampling at 4, 8, or 16 positions at once across\nthe `M` attributes:\n\n``` cpp\nvoid vklComputeSampleM4(const int *valid,\n                        const VKLSampler *sampler,\n                        const vkl_vvec3f4 *objectCoordinates,\n                        float *samples,\n                        unsigned int M,\n                        const unsigned int *attributeIndices,\n                        const float *times);\n\nvoid vklComputeSampleM8(const int *valid,\n                        const VKLSampler *sampler,\n                        const vkl_vvec3f8 *objectCoordinates,\n                        float *samples,\n                        unsigned int M,\n                        const unsigned int *attributeIndices,\n                        const float *times);\n\nvoid vklComputeSampleM16(const int *valid,\n                         const VKLSampler *sampler,\n                         const vkl_vvec3f16 *objectCoordinates,\n                         float *samples,\n                         unsigned int M,\n                         const unsigned int *attributeIndices,\n                         const float *times);\n```\n\nThe `[4, 8, 16] * M` sampled values are populated in the `samples` array\nin a structure-of-arrays layout, with all values for each attribute\nprovided in sequence. That is, sample values `s_m,n` for the `m`th\nattribute and `n`th object coordinate will be populated as\n\n``` cpp\nsamples = [s_0,0,   s_0,1,   ..., s_0,N-1,\n           s_1,0,   s_1,1,   ..., s_1,N-1,\n           ...,\n           s_M-1,0, s_M-1,1, ..., s_M-1,N-1]\n```\n\nA stream version allows sampling an arbitrary number of positions at\nonce across the `M` attributes. As with single attribute stream\nsampling, the `N` coordinates are provided in an array-of-structures\nlayout.\n\n``` cpp\nvoid vklComputeSampleMN(const VKLSampler *sampler,\n                        unsigned int N,\n                        const vkl_vec3f *objectCoordinates,\n                        float *samples,\n                        unsigned int M,\n                        const unsigned int *attributeIndices,\n                        const float *times);\n```\n\nThe `M * N` sampled values are populated in the `samples` array in an\narray-of-structures layout, with all attribute values for each\ncoordinate provided in sequence as\n\n``` cpp\nsamples = [s_0,0,   s_1,0,   ..., s_M-1,0,\n           s_0,1,   s_1,1,   ..., s_M-1,1,\n           ...,\n           s_0,N-1, s_1,N-1, ..., s_M-1,N-1]\n```\n\nAll of the above sampling APIs can be used, regardless of the device’s\nnative SIMD width.\n\n## Gradients\n\nIn a very similar API to `vklComputeSample`, `vklComputeGradient`\nqueries the value gradient at an object space coordinate. Again, a\nscalar API, now returning a vec3f instead of a float. NaN values are\nreturned for points outside the volume. The time value, which must be\nbetween 0 and 1, specifies the sampling time. For temporally constant\nvolumes, this value has no effect.\n\nFor the `cpu` device, the scalar sampling API is:\n\n``` cpp\nvkl_vec3f vklComputeGradient(const VKLSampler *sampler,\n                             const vkl_vec3f *objectCoordinates,\n                             unsigned int attributeIndex,\n                             float time);\n```\n\nwhile on the `gpu` device, it is:\n\n``` cpp\nvkl_vec3f vklComputeGradient(const VKLSampler *sampler,\n                             const vkl_vec3f *objectCoordinates,\n                             unsigned int attributeIndex,\n                             float time,\n                             const VKLFeatureFlags featureFlags);\n```\n\n### Vector-wide and Stream-wide Gradients (CPU device only)\n\nAs with the sampling APIs, on the `cpu` device vector-wide and\nstream-wide gradient APIs are also provided.\n\nThe vector versions are:\n\n``` cpp\nvoid vklComputeGradient4(const int *valid,\n                         const VKLSampler *sampler,\n                         const vkl_vvec3f4 *objectCoordinates,\n                         vkl_vvec3f4 *gradients,\n                         unsigned int attributeIndex,\n                         const float *times);\n\nvoid vklComputeGradient8(const int *valid,\n                         const VKLSampler *sampler,\n                         const vkl_vvec3f8 *objectCoordinates,\n                         vkl_vvec3f8 *gradients,\n                         unsigned int attributeIndex,\n                         const float *times);\n\nvoid vklComputeGradient16(const int *valid,\n                          const VKLSampler *sampler,\n                          const vkl_vvec3f16 *objectCoordinates,\n                          vkl_vvec3f16 *gradients,\n                          unsigned int attributeIndex,\n                          const float *times);\n```\n\nFinally, a stream version is provided:\n\n``` cpp\nvoid vklComputeGradientN(const VKLSampler *sampler,\n                         unsigned int N,\n                         const vkl_vec3f *objectCoordinates,\n                         vkl_vec3f *gradients,\n                         unsigned int attributeIndex,\n                         const float *times);\n```\n\nAll of the above gradient APIs can be used, regardless of the device’s\nnative SIMD width.\n\n## Iterators\n\nOpen VKL has APIs to search for particular volume values along a ray.\nQueries can be for ranges of volume values (`vklIterateInterval`) or for\nparticular values (`vklIterateHit`).\n\nInterval iterators require a context object to define the sampler and\nparameters related to iteration behavior. An interval iterator context\nis created via\n\n``` cpp\nVKLIntervalIteratorContext vklNewIntervalIteratorContext(VKLSampler sampler);\n```\n\nThe parameters understood by interval iterator contexts are defined in\nthe table below.\n\n| Type            | Name                   | Default       | Description                                                                                                                                                                                                                                                                               |\n|:----------------|:-----------------------|:--------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| int             | attributeIndex         | 0             | Defines the volume attribute of interest.                                                                                                                                 ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frenderkit%2Fopenvkl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frenderkit%2Fopenvkl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frenderkit%2Fopenvkl/lists"}