Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/actions/setup-cuda/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

name: Setup CUDA Toolkit
description: Install CUDA Toolkit (cudart + nvcc) via NVIDIA's apt repository.
Architecture-aware (x86_64 / sbsa) so it works on both ubuntu-22.04 and
ubuntu-22.04-arm runners. Replaces the Jimver/cuda-toolkit action, which
hardcodes /x86_64/ in the repo URL and fails on ARM runners.

inputs:
cuda-version:
description: 'CUDA major-minor version (e.g. "12-4" for 12.4)'
required: false
default: '12-4'

runs:
using: composite
steps:
- name: Install CUDA toolkit (apt)
shell: bash
run: |
set -euo pipefail
ARCH=$(dpkg --print-architecture)
case "$ARCH" in
amd64) CUDA_ARCH=x86_64 ;;
arm64) CUDA_ARCH=sbsa ;;
*) echo "setup-cuda: unsupported arch '$ARCH'" >&2; exit 1 ;;
esac
REPO_URL="https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/${CUDA_ARCH}"
TMPDIR=$(mktemp -d)
wget -q -O "${TMPDIR}/cuda-keyring.deb" "${REPO_URL}/cuda-keyring_1.1-1_all.deb"
sudo dpkg -i "${TMPDIR}/cuda-keyring.deb"
rm -rf "${TMPDIR}"
sudo apt-get update -y
sudo apt-get install -y --no-install-recommends \
cuda-nvcc-${{ inputs.cuda-version }} \
cuda-cudart-dev-${{ inputs.cuda-version }}
# Expose to subsequent steps. CMake's find_package(CUDAToolkit)
# picks up CUDA_PATH or finds nvcc via PATH.
CUDA_VERSION_DOTTED="$(echo '${{ inputs.cuda-version }}' | tr '-' '.')"
echo "CUDA_PATH=/usr/local/cuda-${CUDA_VERSION_DOTTED}" >> "$GITHUB_ENV"
echo "/usr/local/cuda-${CUDA_VERSION_DOTTED}/bin" >> "$GITHUB_PATH"
19 changes: 17 additions & 2 deletions .github/workflows/build-ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,21 @@ jobs:
- name: Install Apt dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake libx11-dev clang-format-14 ccache libvulkan-dev
sudo apt-get install -y build-essential cmake libx11-dev clang-format-14 ccache libvulkan-dev glslang-tools

- name: Install patchelf (Release only)
if: ${{ matrix.build_type == 'Release' }}
run: |
sudo apt-get update
sudo apt-get install -y patchelf

# CUDA toolkit needed at link time for viz_core (device_image
# links libcudart). The wheel itself excludes libcuda.so.1 via
# auditwheel; runtime CUDA is the consumer's responsibility.
# Custom action handles both x86_64 and ARM64 (sbsa) repos.
- name: Install CUDA toolkit
uses: ./.github/actions/setup-cuda

- name: Setup CloudXR SDK
id: cloudxr-sdk
uses: ./.github/actions/setup-cloudxr-sdk
Expand Down Expand Up @@ -196,6 +204,10 @@ jobs:
tar -xzvf viz-tests.tar.gz -C viz-tests
chmod +x viz-tests/viz_*_tests

# No CUDA Toolkit install on the GPU runner — viz_core static-links
# libcudart_static, so the binaries only need the NVIDIA driver
# (libcuda.so.1) which the runner already has.

- name: Run viz [gpu] tests
run: |
set -euo pipefail
Expand Down Expand Up @@ -262,7 +274,10 @@ jobs:
- name: Install Apt dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake libx11-dev clang-format-14 ccache libvulkan-dev
sudo apt-get install -y build-essential cmake libx11-dev clang-format-14 ccache libvulkan-dev glslang-tools

- name: Install CUDA toolkit
uses: ./.github/actions/setup-cuda

- name: Cache ccache
uses: actions/cache@v5
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/build-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,18 @@ jobs:
version: 1.3.290.0
cache: true

# CUDA Toolkit needed at link time for viz_core (device_image links
# cudart). Jimver action works correctly on Windows (the arm64
# /x86_64/ hardcoding bug is Linux-only); runs NVIDIA's silent
# network installer and sets CUDA_PATH so find_package(CUDAToolkit)
# locates the install.
- name: Install CUDA Toolkit
uses: Jimver/cuda-toolkit@v0.2.19
with:
cuda: '12.4.0'
method: 'network'
sub-packages: '["nvcc", "cudart"]'

- name: Configure CMake
# Note:
# sccache does not work with VSBuild, so we use Ninja generator here.
Expand Down
18 changes: 14 additions & 4 deletions deps/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,24 @@ machine and are located via `find_package`.
- **Min version**: 1.2 (Televiz checks `VK_API_VERSION_1_2` at device select time).
- **License**: Apache 2.0 (loader); per-vendor for ICD drivers.

### CUDA Toolkit (optional, used by examples)
### CUDA Toolkit
- **Locator**: `find_package(CUDAToolkit REQUIRED)`
- **Required by**: `examples/camera_streamer/` only today; `viz` adds CUDA
dependency once CUDA-Vulkan interop lands; CI must have CUDA installed for
GPU test runner to exercise these paths.
- **Required by**: `viz/core/` (`CudaTexture`, `DeviceImage` link to
`CUDA::cudart`) when `BUILD_VIZ=ON`; also `examples/camera_streamer/`.
- **Min version**: 12.0
- **CI**: installed via `Jimver/cuda-toolkit@v0.2.x` action with
`nvcc` + `cudart` sub-packages.
- **License**: NVIDIA EULA

### glslangValidator (shader compiler)
- **Locator**: `find_program(GLSLANG_VALIDATOR glslangValidator REQUIRED)`
- **Required by**: `viz/shaders/` to compile `.vert` / `.frag` GLSL
into SPIR-V at build time.
- **Linux**: `apt-get install glslang-tools`
- **Windows**: ships with the LunarG Vulkan SDK
- **macOS**: `brew install glslang`
- **License**: BSD-3 / Khronos

## Third-Party Dependencies

### OpenXR SDK
Expand Down
36 changes: 30 additions & 6 deletions src/viz/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,19 @@ sibling `<sub-module>_tests/` directory:

- **`viz/core/`** — foundational types + Vulkan/CUDA infrastructure.
Library: `viz_core`. Today: `VkContext`, `VizBuffer`, `Pose3D`, `Fov`,
`Resolution`, `ViewInfo`, `PixelFormat`, `RenderTarget`, `FrameSync`.
Future: `cuda_texture`. Math types (`glm::vec3`, `glm::quat`,
`Resolution`, `ViewInfo`, `PixelFormat`, `RenderTarget`, `FrameSync`,
`HostImage`, `DeviceImage`. `HostImage` / `DeviceImage` are the
symmetric pair of owning 2D pixel buffers (CPU bytes vs CUDA-Vulkan
interop) — both expose `VizBuffer view()` so generic helpers branch
on `VizBuffer::space`. Math types (`glm::vec3`, `glm::quat`,
`glm::mat4`) come from GLM 1.0.1 (FetchContent in
`deps/third_party/`); use `glm::value_ptr(mat)` to get a raw `float*`
for Vulkan / CUDA upload (POD-equivalent layout, no copy).
CUDA-Vulkan interop requires CUDA Toolkit at link time
(`CUDAToolkit::cudart`). `VkContext::init()` matches the current
CUDA device to the chosen Vulkan physical device by UUID — every
viz_core type can assume CUDA and Vulkan are talking to the same
GPU without re-doing the match.
- **`viz/layers/`** — `LayerBase` and concrete layers (`QuadLayer`, etc.).
Library: `viz_layers` (INTERFACE / header-only today; promoted to
STATIC when the first concrete layer ships). Depends on `viz_core`.
Expand All @@ -39,11 +47,18 @@ sibling `<sub-module>_tests/` directory:
frame loop, type conversion). Library: `viz_xr`. **Optional** behind
`BUILD_VIZ_XR`. Depends on `viz_core` + OpenXR.
- **`viz/python/`** — pybind11 module `_viz`, exposed as `isaacteleop.viz`.
- **`viz/shaders/`** — GLSL → SPIR-V at build time.
- **`viz/shaders/`** — GLSL → SPIR-V at build time. Library: `viz_shaders`
(INTERFACE — exposes generated headers `viz/shaders/<name>.spv.h`,
each containing an `inline constexpr alignas(uint32_t) unsigned char`
byte array + a `Size` constant). Compilation runs `glslangValidator`
(system-installed; CI gets `glslang-tools` apt package). Add new
shader programs by dropping `<name>.vert` / `<name>.frag` in
`viz/shaders/cpp/` and calling `compile_shader(<name>.vert kVarName)`
in the local CMakeLists.

Test directories follow the same per-module pattern:
`viz/core_tests/`, `viz/layers_tests/`, `viz/session_tests/`,
`viz/xr_tests/`.
`viz/shaders_tests/`, `viz/xr_tests/`.

`src/viz/CMakeLists.txt` is an **orchestrator only** — it adds the
sub-module sub-directories. Sub-module `CMakeLists.txt` files build the
Expand All @@ -57,8 +72,17 @@ Build paths that ship viz (the wheel CI on Linux + Windows) pass
`-DBUILD_VIZ=ON` explicitly. Lean Dockerfiles
(`examples/teleop_ros2/Dockerfile`) get viz-free builds for free.

When `BUILD_VIZ=ON` you must have Vulkan headers + loader installed:
`libvulkan-dev` on Linux, LunarG SDK on Windows.
When `BUILD_VIZ=ON` the build machine must have:
- **Vulkan headers + loader**: `libvulkan-dev` on Linux, LunarG SDK on
Windows.
- **CUDA Toolkit** (cudart for link, nvcc not strictly required today
but expected to be needed for kernels in M3b+): apt
`nvidia-cuda-toolkit` or the official NVIDIA installer / CI action
(`Jimver/cuda-toolkit`). The wheel excludes `libcuda.so.1` —
consumers supply it via NVIDIA driver.
- **glslangValidator** for shader compilation: `glslang-tools` apt
package on Linux, `brew install glslang` on macOS, ships with the
Vulkan SDK on Windows.

## Code conventions

Expand Down
5 changes: 5 additions & 0 deletions src/viz/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ add_subdirectory(layers)
# layer that drives the per-frame loop and manages the layer registry.
add_subdirectory(session)

# Shaders: GLSL sources compiled to SPIR-V at build time and embedded
# as C arrays. Header-only INTERFACE library viz::shaders.
add_subdirectory(shaders)

# Python bindings (stub today; pybind11 module added later).
if(BUILD_PYTHON_BINDINGS)
add_subdirectory(python)
Expand All @@ -41,4 +45,5 @@ if(BUILD_TESTING)
add_subdirectory(core_tests)
add_subdirectory(layers_tests)
add_subdirectory(session_tests)
add_subdirectory(shaders_tests)
endif()
21 changes: 19 additions & 2 deletions src/viz/core/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,28 @@

cmake_minimum_required(VERSION 3.20)

# Vulkan is required for vk_context.
# Vulkan is always required for vk_context / render_target / etc.
find_package(Vulkan REQUIRED)

# CUDA Toolkit provides the CUDA-Vulkan interop runtime APIs
# (cudaImportExternalMemory, cudaExternalMemoryGetMappedMipmappedArray)
# used by device_image. Required when BUILD_VIZ=ON.
#
# We link CUDA::cudart_static (not CUDA::cudart) so consumers of viz_core
# don't have a runtime libcudart.so.12 dependency:
# - The wheel ships a fully self-contained _viz.so. auditwheel sees no
# libcudart symbols to bundle.
# - viz_*_tests artifacts run on GPU runners that have only the NVIDIA
# driver (libcuda.so.1) installed; static cudart sidesteps the
# "install the toolkit on every runner" problem.
# Tradeoff: ~3 MB binary growth per consumer. Safe because viz_core is
# the only CUDA-using component in this codebase today.
find_package(CUDAToolkit REQUIRED)

# Foundational types and Vulkan/CUDA primitives shared by all viz sub-modules.
# Static lib; consumed in-tree via viz::viz_core.
# Static lib; consumed in-tree via viz::core.
add_library(viz_core STATIC
device_image.cpp
frame_sync.cpp
render_target.cpp
vk_context.cpp
Expand All @@ -30,6 +46,7 @@ target_link_libraries(viz_core
PUBLIC
Vulkan::Vulkan
glm::glm
CUDA::cudart_static
)

# Aliased as viz::core (consumers say viz::core, not viz::viz_core).
Expand Down
Loading
Loading