neraulgraphics 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- neraulgraphics-0.4.0/.github/workflows/release.yml +141 -0
- neraulgraphics-0.4.0/.gitignore +34 -0
- neraulgraphics-0.4.0/CHANGELOG.md +104 -0
- neraulgraphics-0.4.0/CMakeLists.txt +214 -0
- neraulgraphics-0.4.0/LICENSE +202 -0
- neraulgraphics-0.4.0/Makefile +36 -0
- neraulgraphics-0.4.0/PKG-INFO +167 -0
- neraulgraphics-0.4.0/README.md +135 -0
- neraulgraphics-0.4.0/RELEASING.md +85 -0
- neraulgraphics-0.4.0/cmake/neraulgraphicsConfig.cmake.in +15 -0
- neraulgraphics-0.4.0/cmake/version.h.in +12 -0
- neraulgraphics-0.4.0/docs/guide.md +334 -0
- neraulgraphics-0.4.0/docs/portability.md +73 -0
- neraulgraphics-0.4.0/docs/screenshot.png +0 -0
- neraulgraphics-0.4.0/examples/mujoco_humanoid.py +34 -0
- neraulgraphics-0.4.0/examples/newton_shapes.py +58 -0
- neraulgraphics-0.4.0/examples/view_model.py +49 -0
- neraulgraphics-0.4.0/include/neraulgraphics/mesh.h +82 -0
- neraulgraphics-0.4.0/include/neraulgraphics/renderer.h +145 -0
- neraulgraphics-0.4.0/include/neraulgraphics/scene.h +82 -0
- neraulgraphics-0.4.0/pyproject.toml +113 -0
- neraulgraphics-0.4.0/python/bindings.cpp +447 -0
- neraulgraphics-0.4.0/python/neraulgraphics/__init__.py +82 -0
- neraulgraphics-0.4.0/python/neraulgraphics/_adapter.py +131 -0
- neraulgraphics-0.4.0/python/neraulgraphics/loaders.py +503 -0
- neraulgraphics-0.4.0/python/neraulgraphics/mujoco.py +152 -0
- neraulgraphics-0.4.0/python/neraulgraphics/newton.py +177 -0
- neraulgraphics-0.4.0/python/neraulgraphics/py.typed +0 -0
- neraulgraphics-0.4.0/python/neraulgraphics/shapes.py +164 -0
- neraulgraphics-0.4.0/src/.gitkeep +0 -0
- neraulgraphics-0.4.0/src/backend.h +59 -0
- neraulgraphics-0.4.0/src/backend_api.h +91 -0
- neraulgraphics-0.4.0/src/bvh.cpp +205 -0
- neraulgraphics-0.4.0/src/bvh.h +67 -0
- neraulgraphics-0.4.0/src/cpu_backend.cpp +209 -0
- neraulgraphics-0.4.0/src/cuda_backend.cu +258 -0
- neraulgraphics-0.4.0/src/cuda_backend_stub.cpp +14 -0
- neraulgraphics-0.4.0/src/device_scene.h +89 -0
- neraulgraphics-0.4.0/src/geom.h +84 -0
- neraulgraphics-0.4.0/src/geom_dev.h +182 -0
- neraulgraphics-0.4.0/src/instances.cpp +47 -0
- neraulgraphics-0.4.0/src/instances.h +48 -0
- neraulgraphics-0.4.0/src/main.cpp +284 -0
- neraulgraphics-0.4.0/src/mesh.cpp +97 -0
- neraulgraphics-0.4.0/src/mesh_build.cpp +197 -0
- neraulgraphics-0.4.0/src/mesh_build.h +50 -0
- neraulgraphics-0.4.0/src/mesh_dev.h +254 -0
- neraulgraphics-0.4.0/src/render_core.h +217 -0
- neraulgraphics-0.4.0/src/renderer.cpp +193 -0
- neraulgraphics-0.4.0/tests/test_adapters.py +289 -0
- neraulgraphics-0.4.0/tests/test_loaders.py +294 -0
- neraulgraphics-0.4.0/tests/test_python.py +330 -0
- neraulgraphics-0.4.0/tests/test_renderer.cpp +769 -0
- neraulgraphics-0.4.0/tests/test_shapes.py +71 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
# Pushing a tag vX.Y.Z builds the source archive and wheels, then publishes them as the
|
|
4
|
+
# GitHub Release for that tag, and to PyPI if that has been switched on (see RELEASING.md).
|
|
5
|
+
# Running it by hand (Actions > release > Run workflow) builds the same files without
|
|
6
|
+
# publishing anything, as a dry run.
|
|
7
|
+
#
|
|
8
|
+
# Wheels: Linux x86_64 carries the CUDA backend (and uses the CPU on a machine with no GPU);
|
|
9
|
+
# macOS, Windows and Linux aarch64 are CPU-only.
|
|
10
|
+
#
|
|
11
|
+
# See RELEASING.md for the steps around it.
|
|
12
|
+
|
|
13
|
+
on:
|
|
14
|
+
push:
|
|
15
|
+
tags: ["v*.*.*"]
|
|
16
|
+
workflow_dispatch:
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
# Refuses to release unless the tag, CMakeLists.txt and CHANGELOG.md agree.
|
|
23
|
+
check-version:
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
outputs:
|
|
26
|
+
version: ${{ steps.version.outputs.version }}
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v7
|
|
29
|
+
|
|
30
|
+
- id: version
|
|
31
|
+
run: |
|
|
32
|
+
version=$(sed -nE 's/^project\(neraulgraphics VERSION ([0-9]+\.[0-9]+\.[0-9]+).*/\1/p' CMakeLists.txt)
|
|
33
|
+
if [ -z "$version" ]; then
|
|
34
|
+
echo "::error::no version found in CMakeLists.txt"
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
38
|
+
|
|
39
|
+
if [ "$GITHUB_REF_TYPE" = "tag" ] && [ "$GITHUB_REF_NAME" != "v$version" ]; then
|
|
40
|
+
echo "::error::tag $GITHUB_REF_NAME does not match version $version in CMakeLists.txt"
|
|
41
|
+
exit 1
|
|
42
|
+
fi
|
|
43
|
+
if ! grep -q "^## \[$version\]" CHANGELOG.md; then
|
|
44
|
+
echo "::error::CHANGELOG.md has no '## [$version]' section"
|
|
45
|
+
exit 1
|
|
46
|
+
fi
|
|
47
|
+
echo "version $version"
|
|
48
|
+
|
|
49
|
+
sdist:
|
|
50
|
+
needs: check-version
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/checkout@v7
|
|
54
|
+
- run: pipx run build --sdist
|
|
55
|
+
- uses: actions/upload-artifact@v7
|
|
56
|
+
with:
|
|
57
|
+
name: sdist
|
|
58
|
+
path: dist/*.tar.gz
|
|
59
|
+
|
|
60
|
+
# Settings live in [tool.cibuildwheel] in pyproject.toml, shared with local builds.
|
|
61
|
+
# Linux x86_64, with the CUDA backend.
|
|
62
|
+
wheels:
|
|
63
|
+
needs: check-version
|
|
64
|
+
runs-on: ubuntu-latest
|
|
65
|
+
steps:
|
|
66
|
+
- uses: actions/checkout@v7
|
|
67
|
+
- uses: pypa/cibuildwheel@v4.3.5
|
|
68
|
+
with:
|
|
69
|
+
output-dir: wheelhouse
|
|
70
|
+
- uses: actions/upload-artifact@v7
|
|
71
|
+
with:
|
|
72
|
+
name: wheels-linux-cuda
|
|
73
|
+
path: wheelhouse/*.whl
|
|
74
|
+
|
|
75
|
+
# Everything without CUDA: the build finds no CUDA compiler and builds the CPU backend only.
|
|
76
|
+
wheels-cpu:
|
|
77
|
+
needs: check-version
|
|
78
|
+
strategy:
|
|
79
|
+
fail-fast: false
|
|
80
|
+
matrix:
|
|
81
|
+
include:
|
|
82
|
+
- { name: macos-arm64, os: macos-latest }
|
|
83
|
+
- { name: windows-amd64, os: windows-latest }
|
|
84
|
+
- { name: linux-aarch64, os: ubuntu-24.04-arm, archs: aarch64 }
|
|
85
|
+
runs-on: ${{ matrix.os }}
|
|
86
|
+
steps:
|
|
87
|
+
- uses: actions/checkout@v7
|
|
88
|
+
- uses: pypa/cibuildwheel@v4.3.5
|
|
89
|
+
env:
|
|
90
|
+
CIBW_ARCHS_LINUX: ${{ matrix.archs }}
|
|
91
|
+
with:
|
|
92
|
+
output-dir: wheelhouse
|
|
93
|
+
- uses: actions/upload-artifact@v7
|
|
94
|
+
with:
|
|
95
|
+
name: wheels-${{ matrix.name }}
|
|
96
|
+
path: wheelhouse/*.whl
|
|
97
|
+
|
|
98
|
+
publish:
|
|
99
|
+
if: github.ref_type == 'tag'
|
|
100
|
+
needs: [check-version, sdist, wheels, wheels-cpu]
|
|
101
|
+
runs-on: ubuntu-latest
|
|
102
|
+
permissions:
|
|
103
|
+
contents: write
|
|
104
|
+
steps:
|
|
105
|
+
- uses: actions/checkout@v7
|
|
106
|
+
|
|
107
|
+
- uses: actions/download-artifact@v8
|
|
108
|
+
with:
|
|
109
|
+
path: dist
|
|
110
|
+
merge-multiple: true
|
|
111
|
+
|
|
112
|
+
- name: Create the release
|
|
113
|
+
env:
|
|
114
|
+
GH_TOKEN: ${{ github.token }}
|
|
115
|
+
VERSION: ${{ needs.check-version.outputs.version }}
|
|
116
|
+
run: |
|
|
117
|
+
# The release notes are this version's section of CHANGELOG.md.
|
|
118
|
+
awk -v v="$VERSION" '
|
|
119
|
+
$0 ~ "^## \\[" v "\\]" { found = 1; next }
|
|
120
|
+
found && /^## \[/ { exit }
|
|
121
|
+
found { print }
|
|
122
|
+
' CHANGELOG.md > notes.md
|
|
123
|
+
gh release create "$GITHUB_REF_NAME" dist/* \
|
|
124
|
+
--title "neraulgraphics $VERSION" \
|
|
125
|
+
--notes-file notes.md
|
|
126
|
+
|
|
127
|
+
# PyPI, by trusted publishing: no token is stored here. It does nothing until the repository
|
|
128
|
+
# variable PUBLISH_TO_PYPI is set to true, after the one-time setup on pypi.org in RELEASING.md.
|
|
129
|
+
pypi:
|
|
130
|
+
if: github.ref_type == 'tag' && vars.PUBLISH_TO_PYPI == 'true'
|
|
131
|
+
needs: [check-version, sdist, wheels, wheels-cpu, publish]
|
|
132
|
+
runs-on: ubuntu-latest
|
|
133
|
+
environment: pypi
|
|
134
|
+
permissions:
|
|
135
|
+
id-token: write
|
|
136
|
+
steps:
|
|
137
|
+
- uses: actions/download-artifact@v8
|
|
138
|
+
with:
|
|
139
|
+
path: dist
|
|
140
|
+
merge-multiple: true
|
|
141
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Allowlist: ignore everything in this subproject by default...
|
|
2
|
+
*
|
|
3
|
+
|
|
4
|
+
# ...but keep descending into directories, so the rules below can reach inside
|
|
5
|
+
# them. Without this, git never looks inside src/ and the !/src/** below can
|
|
6
|
+
# never match.
|
|
7
|
+
!*/
|
|
8
|
+
|
|
9
|
+
# ...and un-ignore only what defines the project.
|
|
10
|
+
!/.gitignore
|
|
11
|
+
!/LICENSE
|
|
12
|
+
!/CMakeLists.txt
|
|
13
|
+
!/Makefile
|
|
14
|
+
!/src/**
|
|
15
|
+
!/include/**
|
|
16
|
+
!/cmake/**
|
|
17
|
+
!/python/**
|
|
18
|
+
!/tests/**
|
|
19
|
+
!/examples/**
|
|
20
|
+
!/.github/**
|
|
21
|
+
!/pyproject.toml
|
|
22
|
+
!/README.md
|
|
23
|
+
!/CHANGELOG.md
|
|
24
|
+
!/RELEASING.md
|
|
25
|
+
!/docs/**
|
|
26
|
+
|
|
27
|
+
# Build trees: re-ignored as whole directories so git doesn't walk them at all.
|
|
28
|
+
/build/
|
|
29
|
+
/cmake-build-*/
|
|
30
|
+
/dist/
|
|
31
|
+
/wheelhouse/
|
|
32
|
+
/.idea/
|
|
33
|
+
__pycache__/
|
|
34
|
+
*.egg-info/
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Each release has a section here. The release workflow refuses to publish a version
|
|
4
|
+
without one, and uses the section as the release notes.
|
|
5
|
+
|
|
6
|
+
Versions follow [semantic versioning](https://semver.org). Before 1.0, a minor
|
|
7
|
+
version (0.x.0) may change the API.
|
|
8
|
+
|
|
9
|
+
## [0.4.0]
|
|
10
|
+
|
|
11
|
+
Newton and MuJoCo adapters, model loading, textures, and a CPU backend so it runs on any machine.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- A CPU backend. The renderer runs on every core of the machine when there is no NVIDIA GPU,
|
|
15
|
+
drawing the same picture as the GPU (the two run the same rendering code). `Renderer` takes
|
|
16
|
+
`device="auto" | "cuda" | "cpu"` (C++: `Device`), `Renderer.device` says which was chosen, and
|
|
17
|
+
`cuda_available()` says whether a GPU is usable. `NERAULGRAPHICS_DEVICE=cpu` overrides `auto`;
|
|
18
|
+
`NERAULGRAPHICS_THREADS` sets the CPU thread count. A machine with no GPU used to raise
|
|
19
|
+
`CudaError`; it now falls back to the CPU.
|
|
20
|
+
- CUDA is optional at build time (`-DNERAULGRAPHICS_CUDA=AUTO|ON|OFF`; AUTO uses it if a CUDA
|
|
21
|
+
compiler is found). Without it the library needs only a C++17 compiler and depends on no CUDA
|
|
22
|
+
library or driver.
|
|
23
|
+
- Wheels for macOS (Apple Silicon), Windows and Linux aarch64, CPU-only, alongside the Linux x86_64
|
|
24
|
+
CUDA wheels. The release workflow can publish to PyPI by trusted publishing, once enabled.
|
|
25
|
+
- `docs/portability.md`: what runs where, and how other GPUs could be supported.
|
|
26
|
+
- `neraulgraphics.newton.NewtonRenderer` and `neraulgraphics.mujoco.MuJoCoRenderer`:
|
|
27
|
+
render a Newton or MuJoCo simulation. Shapes become mesh instances once; each
|
|
28
|
+
`render(state)` only moves them. Sphere, box, capsule, cylinder, cone, ellipsoid,
|
|
29
|
+
plane and mesh shapes, with colours from the model.
|
|
30
|
+
- `neraulgraphics.shapes`: capsule, cylinder, cone, plane and sphere generators, and the
|
|
31
|
+
pose math (`pose_matrices`, `compose_poses`) the adapters use.
|
|
32
|
+
- `examples/` with Newton, MuJoCo and model-viewing scripts, and `mujoco` and `images` extras.
|
|
33
|
+
- Smooth shading and textures. `Mesh` takes optional per-vertex `normals` and `uvs`; a new
|
|
34
|
+
`Texture` (RGBA8, sRGB, bilinear filtered, repeating) can be put on an `Instance` with its
|
|
35
|
+
`texture` index, and multiplies into the material's diffuse colour. `Renderer` takes `textures`.
|
|
36
|
+
- `neraulgraphics.load`, `load_gltf` and `load_obj`: glTF 2.0 (`.gltf` and `.glb`) and
|
|
37
|
+
Wavefront OBJ with materials, colour textures, vertex normals and node transforms, returning a
|
|
38
|
+
`LoadedScene` whose `.renderer()` frames the model and lights it.
|
|
39
|
+
- `Renderer.ambient` (C++: `set_ambient`): light reaching every surface regardless of the lights,
|
|
40
|
+
so faces turned from every light are not black. Defaults to 0; the adapters and loaders
|
|
41
|
+
default to 0.2.
|
|
42
|
+
- Simulator planes draw as a checkerboard ground.
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
- `make_camera` computes in double precision on the CPU, so a camera is identical on both backends.
|
|
46
|
+
- Python wheel tests now render for real on build machines, on the CPU backend.
|
|
47
|
+
|
|
48
|
+
### Known limits
|
|
49
|
+
- Textures are not mip-mapped, so distant fine patterns grain until samples accumulate.
|
|
50
|
+
- The CPU backend is roughly 40 to 100 times slower than a recent GPU (at 1280x720 a 16-core CPU takes 17 to 41 ms for 138k-triangle models).
|
|
51
|
+
- glTF: no animation or skinning (bind pose is drawn), normal maps, transparency or Draco.
|
|
52
|
+
|
|
53
|
+
## [0.3.0]
|
|
54
|
+
|
|
55
|
+
Triangle meshes and dynamic scenes.
|
|
56
|
+
|
|
57
|
+
### Added
|
|
58
|
+
- Apache-2.0 license.
|
|
59
|
+
- Triangle meshes. `Mesh` is geometry, built into a BVH once; `Instance` places a
|
|
60
|
+
mesh with its own `Transform` and `Material`. The number of instances is not
|
|
61
|
+
capped, unlike spheres. Pass them to `Renderer(..., meshes, instances)`.
|
|
62
|
+
- `Renderer::set_instance_transforms()` (Python: an `(N, 3, 4)` array or a list of
|
|
63
|
+
`Transform`) moves instances without touching the meshes. The tree over
|
|
64
|
+
instances is refitted in place and rebuilt only when it has loosened too far.
|
|
65
|
+
- `make_transform` (position, `(x, y, z, w)` quaternion, scale), `make_box` and
|
|
66
|
+
`make_icosphere`, in C++ and Python.
|
|
67
|
+
- `make raytracer` builds the viewer and links it as `./raytracer`; `make run`
|
|
68
|
+
and `make test` do the obvious. The viewer takes `--instances N` to spawn
|
|
69
|
+
spinning shapes.
|
|
70
|
+
|
|
71
|
+
### Known limits
|
|
72
|
+
- Triangles are shaded flat, with no vertex normals or textures.
|
|
73
|
+
- Updating instances runs on the CPU: about 9 ms for 10,000 and 90 ms for 100,000.
|
|
74
|
+
- Ray-triangle tests are not watertight along an exact shared edge.
|
|
75
|
+
|
|
76
|
+
## [0.2.0]
|
|
77
|
+
|
|
78
|
+
The renderer is now a package you can call from Python or C++.
|
|
79
|
+
|
|
80
|
+
### Added
|
|
81
|
+
- Python package: `pip install`, then `import neraulgraphics`. `Renderer.render()`
|
|
82
|
+
returns a `(height, width, 3)` uint8 numpy array. Vectors are plain tuples,
|
|
83
|
+
lists or numpy arrays. Bad input raises `ValueError`; CUDA failures raise
|
|
84
|
+
`neraulgraphics.CudaError`. Type stubs included.
|
|
85
|
+
- Linux wheels for Python 3.10 and later that need only the NVIDIA driver, not
|
|
86
|
+
the CUDA toolkit, built for every GPU generation from Turing to Blackwell.
|
|
87
|
+
- `neraulgraphics/version.h`, generated from the version in `CMakeLists.txt`.
|
|
88
|
+
- C++ tests, run with `ctest`.
|
|
89
|
+
|
|
90
|
+
### Changed
|
|
91
|
+
- Renamed everything to `neraulgraphics`: `find_package(neraulgraphics)`, the
|
|
92
|
+
`neraulgraphics::core` target, `#include <neraulgraphics/renderer.h>` and
|
|
93
|
+
`namespace neraulgraphics`. The viewer is now `neraulgraphics-viewer`.
|
|
94
|
+
- The public headers no longer include any CUDA header. Vectors are
|
|
95
|
+
`neraulgraphics::Vec3`, and `make_camera` is computed inside the library, so
|
|
96
|
+
cameras no longer depend on the caller's floating point flags.
|
|
97
|
+
- The `Renderer` floor argument is optional; the default is no floor.
|
|
98
|
+
|
|
99
|
+
## [0.1.0]
|
|
100
|
+
|
|
101
|
+
- The renderer as a library: a `gpu::Renderer` class that owns its device
|
|
102
|
+
memory, reports errors as exceptions, and rejects bad input before it reaches
|
|
103
|
+
the GPU.
|
|
104
|
+
- CMake install and `find_package(raytracer)` support.
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.28)
|
|
2
|
+
|
|
3
|
+
# Must precede project(): with no build type CMake adds no -O flag and GCC defaults to -O0.
|
|
4
|
+
# Only when built on its own; a project that pulls this one in keeps its own build type.
|
|
5
|
+
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR AND NOT CMAKE_BUILD_TYPE
|
|
6
|
+
AND NOT CMAKE_CONFIGURATION_TYPES)
|
|
7
|
+
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build Type" FORCE)
|
|
8
|
+
endif()
|
|
9
|
+
|
|
10
|
+
# 120 = compute capability 12.0 (RTX 50-series). "native" works on CUDA 12.6+.
|
|
11
|
+
# A default only: set before project(), which would otherwise cache its own (75
|
|
12
|
+
# with CUDA 13), so -DCMAKE_CUDA_ARCHITECTURES=... on the command line still wins.
|
|
13
|
+
# A build directory configured before this file existed may hold that 75; reset
|
|
14
|
+
# its cache once (CLion: Tools > CMake > Reset Cache and Reload Project).
|
|
15
|
+
# A pip install from source defaults to "native", the GPU of the machine building it.
|
|
16
|
+
if (NOT DEFINED CMAKE_CUDA_ARCHITECTURES)
|
|
17
|
+
if (DEFINED SKBUILD)
|
|
18
|
+
set(CMAKE_CUDA_ARCHITECTURES native CACHE STRING "CUDA architectures to compile for")
|
|
19
|
+
else()
|
|
20
|
+
set(CMAKE_CUDA_ARCHITECTURES 120 CACHE STRING "CUDA architectures to compile for")
|
|
21
|
+
endif()
|
|
22
|
+
endif()
|
|
23
|
+
|
|
24
|
+
# The one place the version is written. version.h, the find_package version file,
|
|
25
|
+
# the Python package metadata and neraulgraphics.__version__ all read it from here.
|
|
26
|
+
project(neraulgraphics VERSION 0.4.0 LANGUAGES CXX)
|
|
27
|
+
|
|
28
|
+
# CUDA is optional. Without it the library still builds and renders, on the CPU, with nothing but a
|
|
29
|
+
# C++17 compiler. AUTO uses CUDA when a CUDA compiler is found; ON requires it; OFF skips it.
|
|
30
|
+
set(NERAULGRAPHICS_CUDA AUTO CACHE STRING "Build the CUDA (NVIDIA GPU) backend: AUTO, ON or OFF")
|
|
31
|
+
set_property(CACHE NERAULGRAPHICS_CUDA PROPERTY STRINGS AUTO ON OFF)
|
|
32
|
+
set(NERAULGRAPHICS_WITH_CUDA OFF)
|
|
33
|
+
if (NERAULGRAPHICS_CUDA STREQUAL "ON")
|
|
34
|
+
enable_language(CUDA)
|
|
35
|
+
set(NERAULGRAPHICS_WITH_CUDA ON)
|
|
36
|
+
elseif (NERAULGRAPHICS_CUDA STREQUAL "AUTO")
|
|
37
|
+
include(CheckLanguage)
|
|
38
|
+
check_language(CUDA)
|
|
39
|
+
if (CMAKE_CUDA_COMPILER)
|
|
40
|
+
enable_language(CUDA)
|
|
41
|
+
set(NERAULGRAPHICS_WITH_CUDA ON)
|
|
42
|
+
endif()
|
|
43
|
+
endif()
|
|
44
|
+
message(STATUS "neraulgraphics: CUDA backend ${NERAULGRAPHICS_WITH_CUDA}; the CPU backend is always built")
|
|
45
|
+
|
|
46
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
47
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
48
|
+
set(CMAKE_CUDA_STANDARD 17)
|
|
49
|
+
set(CMAKE_CUDA_STANDARD_REQUIRED ON)
|
|
50
|
+
|
|
51
|
+
# On by default only when this is the top-level project, so a project that uses
|
|
52
|
+
# the library through add_subdirectory or FetchContent never needs SDL2.
|
|
53
|
+
option(NERAULGRAPHICS_BUILD_VIEWER "Build the interactive SDL2 viewer" ${PROJECT_IS_TOP_LEVEL})
|
|
54
|
+
option(NERAULGRAPHICS_BUILD_TESTS "Build the C++ tests (run with ctest)" ${PROJECT_IS_TOP_LEVEL})
|
|
55
|
+
option(NERAULGRAPHICS_INSTALL "Generate install rules and the find_package config" ${PROJECT_IS_TOP_LEVEL})
|
|
56
|
+
option(NERAULGRAPHICS_BUILD_PYTHON "Build the Python module (pip install . sets this)" OFF)
|
|
57
|
+
|
|
58
|
+
# Shared links libcudart.so, which the machine running the program must have.
|
|
59
|
+
# Static bakes the runtime in and needs only the NVIDIA driver, which is what lets
|
|
60
|
+
# a Python wheel run on a machine without the CUDA toolkit.
|
|
61
|
+
set(NERAULGRAPHICS_CUDA_RUNTIME Shared CACHE STRING "How to link the CUDA runtime: Shared or Static")
|
|
62
|
+
set_property(CACHE NERAULGRAPHICS_CUDA_RUNTIME PROPERTY STRINGS Shared Static)
|
|
63
|
+
|
|
64
|
+
find_package(Threads REQUIRED)
|
|
65
|
+
if (NERAULGRAPHICS_WITH_CUDA)
|
|
66
|
+
find_package(CUDAToolkit REQUIRED)
|
|
67
|
+
endif()
|
|
68
|
+
|
|
69
|
+
# ---------------------------------------------------------------- library --
|
|
70
|
+
|
|
71
|
+
# The renderer on its own: no window, no SDL. Consumers link neraulgraphics::core.
|
|
72
|
+
add_library(neraulgraphics_core STATIC
|
|
73
|
+
src/renderer.cpp
|
|
74
|
+
src/cpu_backend.cpp
|
|
75
|
+
src/instances.cpp
|
|
76
|
+
src/bvh.cpp
|
|
77
|
+
src/mesh.cpp
|
|
78
|
+
src/mesh_build.cpp)
|
|
79
|
+
if (NERAULGRAPHICS_WITH_CUDA)
|
|
80
|
+
target_sources(neraulgraphics_core PRIVATE src/cuda_backend.cu)
|
|
81
|
+
else()
|
|
82
|
+
target_sources(neraulgraphics_core PRIVATE src/cuda_backend_stub.cpp)
|
|
83
|
+
endif()
|
|
84
|
+
add_library(neraulgraphics::core ALIAS neraulgraphics_core)
|
|
85
|
+
|
|
86
|
+
configure_file(cmake/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/neraulgraphics/version.h
|
|
87
|
+
@ONLY)
|
|
88
|
+
|
|
89
|
+
# The public headers. BASE_DIRS makes these the include path, both here and once
|
|
90
|
+
# installed, so every consumer writes #include <neraulgraphics/renderer.h>.
|
|
91
|
+
# Everything in src/ (the BVH, the rendering core, the backends) stays private to the library.
|
|
92
|
+
target_sources(neraulgraphics_core PUBLIC
|
|
93
|
+
FILE_SET HEADERS
|
|
94
|
+
BASE_DIRS include ${CMAKE_CURRENT_BINARY_DIR}/include
|
|
95
|
+
FILES
|
|
96
|
+
include/neraulgraphics/mesh.h
|
|
97
|
+
include/neraulgraphics/renderer.h
|
|
98
|
+
include/neraulgraphics/scene.h
|
|
99
|
+
${CMAKE_CURRENT_BINARY_DIR}/include/neraulgraphics/version.h)
|
|
100
|
+
|
|
101
|
+
target_include_directories(neraulgraphics_core PRIVATE src)
|
|
102
|
+
|
|
103
|
+
# PRIVATE: the public headers need nothing from CUDA or threads. A static library still
|
|
104
|
+
# carries them to whoever links it, as link-only dependencies.
|
|
105
|
+
target_link_libraries(neraulgraphics_core PRIVATE Threads::Threads)
|
|
106
|
+
if (NERAULGRAPHICS_WITH_CUDA)
|
|
107
|
+
if (NERAULGRAPHICS_CUDA_RUNTIME STREQUAL "Static")
|
|
108
|
+
target_link_libraries(neraulgraphics_core PRIVATE CUDA::cudart_static)
|
|
109
|
+
else()
|
|
110
|
+
target_link_libraries(neraulgraphics_core PRIVATE CUDA::cudart)
|
|
111
|
+
endif()
|
|
112
|
+
endif()
|
|
113
|
+
target_compile_features(neraulgraphics_core PUBLIC cxx_std_17)
|
|
114
|
+
|
|
115
|
+
# Position-independent so the library can be linked into a shared object, such as
|
|
116
|
+
# the Python extension module.
|
|
117
|
+
set_target_properties(neraulgraphics_core PROPERTIES
|
|
118
|
+
POSITION_INDEPENDENT_CODE ON
|
|
119
|
+
EXPORT_NAME core)
|
|
120
|
+
|
|
121
|
+
target_compile_options(neraulgraphics_core PRIVATE
|
|
122
|
+
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:CUDA>>:-use_fast_math>
|
|
123
|
+
# Prints registers per thread and spill counts; a nonzero stack frame means
|
|
124
|
+
# something fell out to local memory.
|
|
125
|
+
$<$<COMPILE_LANGUAGE:CUDA>:-Xptxas=-v>)
|
|
126
|
+
|
|
127
|
+
# ----------------------------------------------------------------- viewer --
|
|
128
|
+
|
|
129
|
+
if (NERAULGRAPHICS_BUILD_VIEWER)
|
|
130
|
+
find_package(SDL2 REQUIRED)
|
|
131
|
+
|
|
132
|
+
# Links the library exactly the way an outside project would.
|
|
133
|
+
add_executable(neraulgraphics-viewer src/main.cpp)
|
|
134
|
+
target_link_libraries(neraulgraphics-viewer PRIVATE neraulgraphics::core SDL2::SDL2)
|
|
135
|
+
|
|
136
|
+
# The COMPILE_LANGUAGE guard is required: nvcc rejects -march=native and -ffast-math.
|
|
137
|
+
# -ffast-math lets the compiler assume NaN never occurs, which is why the
|
|
138
|
+
# renderer's input checks live in render_gpu.cu, not in anything built here.
|
|
139
|
+
target_compile_options(neraulgraphics-viewer PRIVATE
|
|
140
|
+
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:CXX>>:-march=native -ffast-math>)
|
|
141
|
+
endif()
|
|
142
|
+
|
|
143
|
+
# ------------------------------------------------------------------ tests --
|
|
144
|
+
|
|
145
|
+
if (NERAULGRAPHICS_BUILD_TESTS)
|
|
146
|
+
enable_testing()
|
|
147
|
+
# Plain C++ built with -ffast-math, like the viewer: the checks must survive it.
|
|
148
|
+
add_executable(neraulgraphics-tests tests/test_renderer.cpp)
|
|
149
|
+
target_link_libraries(neraulgraphics-tests PRIVATE neraulgraphics::core)
|
|
150
|
+
# The BVH builder is library-private, but its tests want it directly.
|
|
151
|
+
target_include_directories(neraulgraphics-tests PRIVATE src)
|
|
152
|
+
target_compile_options(neraulgraphics-tests PRIVATE
|
|
153
|
+
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:CXX>>:-ffast-math>)
|
|
154
|
+
add_test(NAME renderer COMMAND neraulgraphics-tests)
|
|
155
|
+
endif()
|
|
156
|
+
|
|
157
|
+
# ----------------------------------------------------------------- python --
|
|
158
|
+
|
|
159
|
+
if (NERAULGRAPHICS_BUILD_PYTHON)
|
|
160
|
+
find_package(Python 3.10 REQUIRED COMPONENTS Interpreter Development.Module
|
|
161
|
+
OPTIONAL_COMPONENTS Development.SABIModule)
|
|
162
|
+
execute_process(COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir
|
|
163
|
+
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE nanobind_ROOT)
|
|
164
|
+
find_package(nanobind CONFIG REQUIRED)
|
|
165
|
+
|
|
166
|
+
# STABLE_ABI: on Python 3.12+ one build serves every later version too.
|
|
167
|
+
nanobind_add_module(_core STABLE_ABI NB_STATIC python/bindings.cpp)
|
|
168
|
+
# __version__ comes from the generated version.h, like everything else.
|
|
169
|
+
target_link_libraries(_core PRIVATE neraulgraphics::core)
|
|
170
|
+
install(TARGETS _core LIBRARY DESTINATION neraulgraphics)
|
|
171
|
+
|
|
172
|
+
# Type stubs, so editors can autocomplete and type-check against the module.
|
|
173
|
+
nanobind_add_stub(_core_stub
|
|
174
|
+
MODULE _core
|
|
175
|
+
OUTPUT _core.pyi
|
|
176
|
+
PYTHON_PATH $<TARGET_FILE_DIR:_core>
|
|
177
|
+
DEPENDS _core)
|
|
178
|
+
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/_core.pyi DESTINATION neraulgraphics)
|
|
179
|
+
endif()
|
|
180
|
+
|
|
181
|
+
# ---------------------------------------------------------------- install --
|
|
182
|
+
|
|
183
|
+
if (NERAULGRAPHICS_INSTALL)
|
|
184
|
+
include(GNUInstallDirs)
|
|
185
|
+
include(CMakePackageConfigHelpers)
|
|
186
|
+
|
|
187
|
+
set(NERAULGRAPHICS_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/neraulgraphics)
|
|
188
|
+
|
|
189
|
+
install(TARGETS neraulgraphics_core
|
|
190
|
+
EXPORT neraulgraphicsTargets
|
|
191
|
+
FILE_SET HEADERS)
|
|
192
|
+
|
|
193
|
+
# Writes the imported target neraulgraphics::core that find_package hands back.
|
|
194
|
+
install(EXPORT neraulgraphicsTargets
|
|
195
|
+
NAMESPACE neraulgraphics::
|
|
196
|
+
DESTINATION ${NERAULGRAPHICS_CMAKE_DIR})
|
|
197
|
+
|
|
198
|
+
configure_package_config_file(cmake/neraulgraphicsConfig.cmake.in
|
|
199
|
+
${CMAKE_CURRENT_BINARY_DIR}/neraulgraphicsConfig.cmake
|
|
200
|
+
INSTALL_DESTINATION ${NERAULGRAPHICS_CMAKE_DIR})
|
|
201
|
+
|
|
202
|
+
# Before 1.0 a minor version may change the API, so only the same minor matches.
|
|
203
|
+
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/neraulgraphicsConfigVersion.cmake
|
|
204
|
+
COMPATIBILITY SameMinorVersion)
|
|
205
|
+
|
|
206
|
+
install(FILES
|
|
207
|
+
${CMAKE_CURRENT_BINARY_DIR}/neraulgraphicsConfig.cmake
|
|
208
|
+
${CMAKE_CURRENT_BINARY_DIR}/neraulgraphicsConfigVersion.cmake
|
|
209
|
+
DESTINATION ${NERAULGRAPHICS_CMAKE_DIR})
|
|
210
|
+
|
|
211
|
+
if (NERAULGRAPHICS_BUILD_VIEWER)
|
|
212
|
+
install(TARGETS neraulgraphics-viewer RUNTIME)
|
|
213
|
+
endif()
|
|
214
|
+
endif()
|