# NKSR's wheels expired, so the install is now a CUDA compile

> A CVPR 2023 Highlight research release from NVIDIA's Toronto AI lab that reconstructs 3D implicit surfaces from sparse, noisy point clouds by fitting compactly supported neural kernels. The paper claims state of the art on object, indoor and outdoor benchmarks. The practical picture in 2026 is a repository with no releases, no downloadable wheel, a requirements file that pins two different torch versions in two different index lines, and two different licences for the code and the model.

**nv-tlabs/NKSR** — [CVPR 2023 Highlight] Neural Kernel Surface Reconstruction

- Repository: https://github.com/nv-tlabs/NKSR
- Website: https://research.nvidia.com/labs/toronto-ai/NKSR
- Stars: 998 · Forks: 72
- Language: Cuda
- License: NOASSERTION
- Published: 2026-09-16 · Updated: 2026-09-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/nv-tlabs-nksr

## The pre-built wheels expired, which is why the CUDA source is in the repository

The most useful line in the whole README is dated 2025-09-08. Due to the expiration of the pre-built wheels, the full CUDA code was uploaded so that users can compile it themselves, and the replacement wheel is compatible with PyTorch 2.7.0 and CUDA 12.8.

That reframes what this repository is. It is not a package you can add to a requirements file and get a working module; it is a source tree with a build step, and the older binaries that made it look otherwise are gone. The news list has only three entries in total, the wheel expiry, a community tutorial from June 2023 on turning an iPhone scan into a mesh, and the original code release on 2023-06-08.

There is also no GitHub release history at all, and the default branch is called public rather than main. If you are arriving from a paper citation, there is no version to pin to; there is a commit.

The install sequence reflects the compile requirement. You clone, create a conda environment from the provided file, install the requirements, and then build the package itself with build isolation disabled, because the extension has to compile against the torch you already installed rather than a torch the build system fetches on its own.

## One requirements file pinning torch 2.7.0 and asking for torch 2.8.0 wheels

The setup prose says the latest Python and PyTorch are recommended, and then the requirements file pins both:

```
--extra-index-url https://download.pytorch.org/whl/cu128
torch==2.7.0+cu128
torchvision

-f https://data.pyg.org/whl/torch-2.8.0+cu128.html
torch-scatter
```

Torch is pinned to 2.7.0 with the CUDA 12.8 build. The scatter extension, which the sparse kernels need, is fetched from a find-links index built for torch 2.8.0 with CUDA 12.8. Those two lines ask for different torch versions in the same install, and a user following the file literally will either get no matching scatter wheel or an unexpected torch upgrade.

The same file also installs the ninja build tool as a Python dependency, pulls GitPython, and adds pyntcloud and plyfile for point cloud input and output. One entry is a leftover from further upstream: python-pycg, a compilation graph library, which is not something a surface reconstruction runtime would call.

The version guidance in the prose and the version pins in the file are simply different documents, and the file is the one that decides what you get.

## The source and the kitchen-sink model are under two different licences

The licence situation has three layers and they do not agree.

The repository's own licence metadata records nothing identifiable, so the platform reports it as unknown. The README's licence section says the work is made available under the NVIDIA Source Code License, and points at a file called LICENSE.txt rather than LICENSE. The copyright line is NVIDIA Corporation and affiliates, 2023.

Then there is the model. The kitchen-sink model, the one the quick example is meant to use, is stated to be released under CC-BY-SA 4.0, which is a share-alike content licence rather than a proprietary source licence.

So a repository whose metadata cannot classify its terms contains source under one named licence and a downloadable model artifact under a different one, with the file named so that automated tooling will not find it. Business and licensing enquiries are routed to an NVIDIA research licensing form rather than to a maintainer.

Which terms reach a given artefact is worth confirming before this goes into anything commercial, because the two documents in play grant very different rights and neither one tells you how they interact when the model output is redistributed.

## The usage snippet calls two things it never imports

The quick example is five lines of real API and two lines that do not run:

```python
import torch
import nksr

bunny_geom = load_bunny_example()

input_xyz = torch.from_numpy(np.asarray(bunny_geom.points)).float().to(device)
input_normal = torch.from_numpy(np.asarray(bunny_geom.normals)).float().to(device)

reconstructor = nksr.Reconstructor(device)
field = reconstructor.reconstruct(input_xyz, input_normal, detail_level=1.0)
mesh = field.extract_dual_mesh(mise_iter=1)
```

It imports torch and nksr. It then calls load_bunny_example, which is defined nowhere in the snippet, and uses np for numpy, which is not imported either. So the first thing a new user has to solve is a missing helper.

The API surface itself is small and readable. You construct a Reconstructor for a device, call reconstruct with the point positions and normals plus a detail level of 1.0, and then extract a dual mesh with one iteration of the mise extractor. No model loading appears in the snippet at all, even though the kitchen-sink model is the thing being offered, which means the connection between the two is left to the usage document.

That document, NKSR-USAGE.md at the repository root, is where the data preparation instructions and the fuller set of examples live, and it is the right next file to open.

## Two of the three benchmark datasets sit in an author's account, and one is a regeneration

Training reproduction is documented properly, down to the logger configuration. You copy the default Zeus yaml to your own file and fill in your wandb account name and where checkpoints and test results should be written. Zeus supports tensorboard and wandb, with wandb recommended.

The datasets are where provenance gets interesting. ShapeNet comes from an S3 bucket in the eu-central-1 region, credited to the Occupancy Networks project, and you are told to place the extracted folder under ../data/shapenet.

Points2Surf and CARLA both come from a Hugging Face account under the name heiwang1997, not from the original dataset authors. And the Points2Surf entry adds a sentence that matters for anyone comparing numbers: the data was regenerated in full with blensor, following the original script, in order to obtain input normals.

So of the three benchmark training sets, one is an upstream dataset used as-is, one is a regeneration by the authors, and one is hosted by the authors. The pre-trained checkpoints for inference come from that same account, fetched by URL inside the test command, so a reproduction run depends on a third-party hosting location for both its weights and two of its datasets.

That is normal practice for a research release and worth stating plainly, because a broken link years from now takes the reproduction with it.

## --tree_depth defaults to 4, and it is the compact-support hierarchy itself

Four training flags are called out as the common ones, and each one changes something structural.

The voxel size flag sets the resolution of the finest level of voxels. The feature flag picks what the encoder sees beyond coordinates: nothing, surface normals as the default, or sensor direction. The tree depth flag sets the depth of the sparse feature hierarchy and defaults to 4. And the experiment name flag only labels the wandb run.

Tree depth is the interesting one, because it is the compactly supported kernel construction made into a number. Compact support is what lets the method use memory-efficient sparse linear solvers and what makes large scenes and out-of-core processing possible at all, so the depth of that hierarchy is the main speed and memory dial in the whole configuration.

Five example training commands are given, one per benchmark configuration: ShapeNet with perfect 1K input, ShapeNet with noisy 3K input, ShapeNet with heavier noise on 3K input, Points2Surf, and CARLA. The naming is slightly uneven, with one configuration called noiser rather than noise, which is the kind of detail that costs a new user a search.

Inference reuses the same config files, adding a checkpoint URL, a disable flag for the unified depth function, and per-dataset include files for the test splits.

## A monkey_patches.py and an overfit.py at the repository root

The root tells you what kind of project this is. There is an assets directory, a configs directory, a dataset directory, examples, an ext directory for the native extension, models, a package directory holding the distribution, and four loose Python files: metrics.py, monkey_patches.py, overfit.py, zeus.py, plus the two entry scripts train.py and test.py and a small tool module.

Two of those loose files are worth naming out loud. A file called monkey_patches.py at the top level means the project modifies the behaviour of libraries it depends on, and a reader has no way to tell which ones without opening it. A file called overfit.py is a debugging tool for collapsing a model onto a single example, which is exactly what you want during development and exactly what you do not want in a production import graph.

The examples directory is more revealing about scope. Alongside the simple reconstruction example there are named ones for ScanNet data, for coloured meshes, for Waymo data, a Waymo example that runs on the CPU, one that reconstructs by chunk, and a GIS application. The chunked and CPU variants are the visible ends of the two claims in the abstract, out-of-core processing for scenes too large to hold, and a path that does not need a GPU.

The environment story is repeated in files at the root: the usage document, the Zeus infrastructure document, the conda environment file, and the requirements file.

## The scale claims name one GPU, and the evaluation lives in the paper

The abstract makes three capability claims and one result claim, and they are worth separating.

The capabilities: scale to large scenes through compactly supported kernel functions that allow memory-efficient sparse linear solvers; tolerate noise through a gradient fitting solve; and minimise training requirements, enough to learn from any dataset of dense oriented points and to mix training data of objects and scenes at different scales. It also states that the method reconstructs millions of points in a few seconds and handles very large scenes out of core.

The result claim is state of the art on reconstruction benchmarks of single objects, indoor scenes and outdoor scenes.

The only hardware figure anywhere in the repository is in the testing section: scenes spanning kilometres with millions of points, on an RTX 3090. There is no table of numbers, no comparison against the Neural Kernel Fields baseline it builds on, no timing breakdown, and no memory figure. The evaluation is in the paper, and the repository ships a metrics module rather than any results to look at.

For a project whose headline is a paper result, that is the normal arrangement. It does mean the repository's own claims are the ones to read carefully: three releases of the method are not in this tree, and the news list has not changed since 2025.

## Conclusion

NKSR is a paper release first and a package second, and the right way to approach it is accordingly. If you want the method, read the abstract's three contributions in order, because each one maps to a specific engineering choice you will meet in the code: compact support gives you the sparse solvers and the out-of-core path, gradient fitting is what tolerates noisy input, and the reduced training requirement is why datasets at different scales can be mixed. If you want to run it, budget a compile. There is no wheel, the pre-built ones expired, the install needs build isolation turned off, and the two index lines in the requirements file point at different torch versions, so expect to reconcile them yourself. Before you rely on anything here, settle the licensing question, because the source and the kitchen-sink model are under different terms, and confirm the hardware story, since the only scale figure given names a single consumer GPU.

## FAQ

### How do I install nv-tlabs/NKSR?

There is no working pre-built wheel. In September 2025 the pre-built wheels expired and the full CUDA source was uploaded so users can compile it themselves, with a replacement compatible with PyTorch 2.7.0 and CUDA 12.8. You clone the repository, create the conda environment from environment.yml, install requirements.txt, then build with pip install --no-build-isolation package/.

### What licence is nv-tlabs/NKSR under?

The README names the NVIDIA Source Code License and points at LICENSE.txt, while the repository's own licence metadata records nothing identifiable. Separately, the kitchen-sink model is released under CC-BY-SA 4.0, so the source and the model carry different terms.

### Which torch version does NKSR need?

The requirements file pins torch at 2.7.0 with the CUDA 12.8 build through an extra index URL, but the line that fetches torch-scatter points at a find-links index built for torch 2.8.0 with CUDA 12.8. The prose recommends the latest Python and PyTorch, which does not match either pin.

### How large a scene can nv-tlabs/NKSR reconstruct?

The abstract claims millions of points in a few seconds, with very large scenes handled out of core through compactly supported kernels and sparse solvers. The only hardware named anywhere in the repository is a single RTX 3090, described as reconstructing kilometre-scale scenes with millions of points.

### Where do the NKSR datasets and checkpoints come from?

ShapeNet is fetched from an S3 bucket credited to the Occupancy Networks project. Points2Surf and CARLA are hosted on Hugging Face under the account heiwang1997, and the Points2Surf data was regenerated with blensor following the original script to obtain input normals. Pre-trained checkpoints come from that same account and are passed to the test script as a URL.

## Sources

- [Issues](https://github.com/nv-tlabs/NKSR/issues)
- [nv-tlabs/NKSR on GitHub](https://github.com/nv-tlabs/NKSR)
- [Project website](https://research.nvidia.com/labs/toronto-ai/NKSR)
- [README](https://github.com/nv-tlabs/NKSR/blob/public/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/nv-tlabs-nksr
