Skip to content

Feature/scm cuda backend - #836

Closed
Auc7us wants to merge 6 commits into
projectchrono:mainfrom
Auc7us:feature/scm-cuda-backend
Closed

Auc7us wants to merge 6 commits into
projectchrono:mainfrom
Auc7us:feature/scm-cuda-backend

Conversation

@Auc7us

@Auc7us Auc7us commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Add a CUDA backend for the SCM GPU path

The SCM GPU ray-cast and contact-force backend is HIP-only, an NVIDIA user needs ROCm
installed to use it. It now builds with either toolchain, and CUDA is what an NVIDIA machine
picks by default. Nothing is removed: HIP on ROCm and HIP through nvcc both still work.

Kernels are single-source. The two .cu files are compiled as CUDA or relabelled
LANGUAGE HIP by chrono_set_gpu_source_language(), the same arrangement Chrono::DEM and
Chrono::FSI::SPH already use. Device syntax is identical between the two languages, so only the
stream type and getLastError sit behind an #if.

Host bridges are duplicated, under terrain/gpu/cuda/ and terrain/gpu/hip/. They are
almost entirely runtime API calls, about thirty symbols, and Chrono has no compatibility layer
for those. Exactly one directory compiles per build; a banner at the top of each file says its
counterpart must be kept in step. Switch to a shim is possible if preferred.

CMake: REQUIRES HIP becomes REQUIRES CUDA_OR_HIP for the SCM GPU feature only.
CHRONO_GPU_BACKEND still selects explicitly; left at AUTO it resolves to CUDA on NVIDIA and
HIP on AMD.

No behavioural change, same kernels, same results. Verified.

Verification

Three toolchains, all clean, no source differences between them:

build compiler result
CUDA nvcc 13.2, RTX 4080 builds, runs
HIP on NVIDIA nvcc via CMAKE_HIP_PLATFORM=nvidia builds, runs
HIP on AMD ROCm 7.2 HIP-clang, gfx942 builds, runs, real gfx942 offload bundles

Benchmarks with the SCM visualization mesh off, 3 runs each, btest_VEH_hmmwvSCM and the Viper
SCM demo:

  • CUDA vs HIP-through-nvcc on the 4080: CUDA 2.5–2.9% faster on HMMWV, parity on Viper.
  • ROCm before vs after the refactor: every delta below the within-branch run-to-run spread.
  • Viper step time, GPU ray cast vs CPU: 5.1x on the 4080, 6.4x on MI300X.
  • Physics matches across vendors: wheel sinkage 0.05482–0.05484, final x −1.1401 to −1.1408 on
    both NVIDIA and AMD.

Auc7us and others added 6 commits September 4, 2026 12:01
Renames the two kernel translation units from .hip.cpp to .cu and removes their
dependence on the HIP runtime, so the same source can be compiled by nvcc or by
hipcc. This is the arrangement Chrono::DEM and Chrono::FSI::SPH already use, and
it reuses their machinery: chrono_set_gpu_source_language() relabels the sources
LANGUAGE HIP when the HIP backend is selected, and .cu is CUDA by default.

The device code needed no changes -- __global__, __shared__, threadIdx and the
<<<>>> launch are spelled identically in both. Only two runtime names appeared in
these files, hipStream_t and hipGetLastError, and they are now selected by a short
conditional at the top of each file. That conditional is not optional: nvcc
implicitly includes <cuda_runtime.h> for a .cu, but HIP-clang provides nothing, so
a .cu with no includes compiles under nvcc and fails under hipcc with threadIdx,
blockIdx and blockDim undeclared.

The host bridges are untouched and remain HIP-only, so CH_ENABLE_VEHICLE_SCM_GPU
still REQUIRES HIP and every existing build behaves exactly as before. They use
around thirty runtime symbols and will be duplicated per backend rather than
routed through a compatibility layer, for which Chrono has no precedent.

Verified on both toolchains:

  SCMRaycastGpuKernels.cu  nvcc -c                                      PASS
  SCMRaycastGpuKernels.cu  hipcc -fsyntax-only --offload-arch=gfx942    PASS
  SCMGpuKernels.cu         nvcc -c                                      PASS
  SCMGpuKernels.cu         hipcc -fsyntax-only --offload-arch=gfx942    PASS

and the full HIP build of Chrono_vehicle links unchanged.
The kernels are already a single source compiled by either toolchain. The host
bridges cannot be: they are almost entirely GPU runtime API calls, about thirty
symbols of allocation, copies, streams and events. Those are duplicated rather
than routed through a compatibility layer, for which Chrono has no precedent.

  terrain/gpu/hip/SCMGpuHost.cpp          moved, unchanged
  terrain/gpu/hip/SCMRaycastGpuHost.cpp   moved, unchanged
  terrain/gpu/cuda/SCMGpuHost.cpp         new
  terrain/gpu/cuda/SCMRaycastGpuHost.cpp  new

Exactly one directory is compiled per build, selected from CHRONO_VEHICLE_SCM_BACKEND.
Each file carries a banner naming its counterpart, because nothing enforces that the
two stay in step -- only one is ever compiled, so a change made to one alone produces
no error anywhere.

The translation is not name-for-name everywhere. hipHostMalloc(p, n) is
cudaHostAlloc(p, n, flags): the flags argument that HIP defaults is mandatory in CUDA,
so a mechanical rename produces a call that fails to compile. Three sites in the
contact-force bridge are affected, all in the pinned staging buffers of the async
double-buffered pipeline.

Also removes a stale #include <hip/hip_runtime.h> from SCMTerrainRaycastGpu.cpp, which
uses no HIP symbol at all. It went unnoticed while the only backend was HIP.

CH_ENABLE_VEHICLE_SCM_GPU now REQUIRES CUDA_OR_HIP, which gives the intended default on
each vendor with no further configuration: an NVIDIA machine resolves AUTO to CUDA
(both backends are candidates and CUDA is first), and an AMD machine resolves it to HIP
on ROCm (the only candidate). HIP over CUDA remains available on NVIDIA for anyone who
wants it, via CHRONO_VEHICLE_SCM_GPU_BACKEND=HIP. The one consequence to be aware of is
that an existing NVIDIA build directory that was using HIP moves to CUDA on reconfigure,
which is the point.

Verified both ways on one machine (RTX 4080, CUDA 13.2, ROCm 7.2 with HIP platform
nvidia):

  AUTO                                  -> CUDA
  CHRONO_VEHICLE_SCM_GPU_BACKEND=HIP    gpu/hip bridges,  HIP_COMPILER,  links HIP
  CHRONO_VEHICLE_SCM_GPU_BACKEND=CUDA   gpu/cuda bridges, CUDA_COMPILER, links CXX

Both produce a Chrono_vehicle carrying the SCM GPU entry points. The AMD leg (gfx942)
is unbuilt here: this container has no ROCm device bitcode, only the front end.
The comment rewrite that came with REQUIRES CUDA_OR_HIP left two phrasings
of the same point about HIP platforms. Keep the one that names the ROCm-only
libraries.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
PR_MESSAGE.md is a scratch note for a different branch that was swept in by
a git add -A. It is not part of the SCM CUDA backend.
Three files claimed FP64 was the validated default, chosen by which HIP
platform the build targets. Neither is true: DesiredRaycastGpuPrecision
returns FP32 unconditionally, overridable only by
SCM_RAYCAST_GPU_PRECISION, and it does so deliberately so the same model
does not diverge between machines. Point at that function instead of
restating its reasoning, and drop the AMD-only framing now that the
kernels also build as CUDA.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Auc7us Auc7us closed this Sep 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant