Skip to content

Implement support for triangulated volumes in simphony#333

Open
ggalgoczi wants to merge 2 commits into
mainfrom
triangulated-volumes
Open

Implement support for triangulated volumes in simphony#333
ggalgoczi wants to merge 2 commits into
mainfrom
triangulated-volumes

Conversation

@ggalgoczi
Copy link
Copy Markdown
Contributor

Summary

Adds OptiX builtin triangle-BVH support to the physics simulation pipeline so volumes flagged via stree__force_triangulate_solid=<lv_name> traverse as triangle GAS instances instead of analytic CSG, mixed inside the same IAS as the analytic CSG GAS.

The TriMesh HitGroupData layout (Binding.h), the triangle build input (sysrap/SOPTIX_BuildInput_Mesh.h), the mesh-side SOPTIX_MeshGroup plumbing and the __closesthit__ch triangle branch were already in place. This PR adds the pipeline + SBT wiring that was missing to actually exercise them.

Changes

feat(csgoptix) commit:

  • CSGOptiX/PIP.cc: enable OPTIX_PRIMITIVE_TYPE_FLAGS_TRIANGLE alongside
    _CUSTOM in usesPrimitiveTypeFlags; create a second hitgroup program
    group hitgroup_pg_tri with entryFunctionNameIS = nullptr (OptiX 9 forbids
    an IS program on a triangle hitgroup); add it to optixPipelineCreate and
    optixUtilAccumulateStackSizes.
  • CSGOptiX/PIP.h: declare hitgroup_pg_tri alongside the analytic PG.
  • CSGOptiX/SBT.cc::createHitgroup: pack each SBT record header with the PG
    matching its GAS kind _ hitgroup_pg_tri when foundry->isSolidTrimesh(gas_idx),
    hitgroup_pg otherwise _ instead of a single PG for all records.

test(ci) commit:

  • tests/test_triangulated.sh: runs GPURaytrace on the existing
    opticks_raindrop.gdml twice _ once analytic, once with
    stree__force_triangulate_solid=G4_WATER_solid _ and asserts the
    Opticks: NumHits: counts are bit-identical. A G4Box triangulates to
    12 flat triangles that coincide with the analytic surface, so strict
    equality is the right check.
  • .github/workflows/build-pull-request.yaml: invoke the new test next
    to test_GPURaytrace.sh.

Behaviour for runs that don't trigger triangulation

Functionally equivalent to upstream main:

  • hitgroup_pg_tri is created but unreferenced (no triangle GAS exists).
  • SBT::createHitgroup falls back to hitgroup_pg for every record.
  • Slight optixUtilComputeStackSizes overhead from the extra PG, negligible.
  • Raindrop regression: 12664 hits in both branches, matches existing tolerance.

Mixed analytic + triangulated

Supported. The CI test itself runs a mixed scene (analytic Pb/AIR/VACUUM + triangulated WATER) in a single IAS. The constraint inherited from the existing CSG bookkeeping is that within a single compound CSGSolid all CSGPrim layers must be either all analytic or all triangulated (see comment at SBT.cc:1021). Across different LVs / GAS indices, mixing works.

Validation

Beyond the CI test, manually validated on a deformed raindrop where G4Box solids were replaced with G4Sphere:

solid rotation steps num triangles hit deficit vs analytic
Box (G4_WATER) n/a 12 bit-identical, 5/5 seeds
Sphere (G4_WATER) 24 (default) 528 +0.255% (5/5 seeds, ~3_ each)
Sphere (G4_WATER) 48 2208 +0.105%
Sphere (G4_WATER) 200 39600 +0.0086%

Deficit scales as 1/N_ as expected from the inscribed-polyhedron error. N=34 was an outlier (+0.405%) _ G4PolyhedronSphere with prime-factor rotation counts produces non-smooth meshes; multiples of 24 stay on the clean 1/N_ curve.

GPU Simulation time: measured around gx->simulate() + cudaDeviceSynchronize in src/GPURaytrace.h. On a single warm-run measurement at N=200 with 6.08M photons (RTX 4090), triangle BVH was ~10% faster than the analytic CSG-sphere path _ RT cores beat the custom __intersection__is software intersect for the simple sphere; the gap likely flips back to ana for deep CSG trees.

How to enable

export stree__force_triangulate_solid=lv_name_A,lv_name_B
or

export stree__force_triangulate_solid='filepath:$HOME/.opticks/GEOM/${GEOM}_meshname_stree__force_triangulate_solid.txt'

Names are post-StripTail (no 0x_ suffix). Must be set before the G4_Opticks geometry conversion. With no envvar, behaviour matches main.

ggalgoczi added 2 commits May 15, 2026 20:59
Adds the wiring needed so triangulated solids (forced via
`stree__force_triangulate_solid`) traverse the OptiX builtin triangle
BVH inside the same IAS as the analytic CSG GAS.

* PIP.cc: enable `OPTIX_PRIMITIVE_TYPE_FLAGS_TRIANGLE` alongside
  `_CUSTOM` in `usesPrimitiveTypeFlags`; create a second hitgroup
  program group `hitgroup_pg_tri` with `entryFunctionNameIS = nullptr`
  (OptiX 9 requires no IS program for triangle hitgroups). Both PGs are
  passed to `optixPipelineCreate` and accumulated in `configureStack`.
* PIP.h: declare `hitgroup_pg_tri` alongside the existing analytic PG.
* SBT.cc: `createHitgroup` now packs each record header with the PG
  matching its GAS kind (`hitgroup_pg_tri` when `isSolidTrimesh(gas_idx)`,
  `hitgroup_pg` otherwise) instead of using a single PG for all records.

The TriMesh HitGroupData layout (`Binding.h`), the triangle build input
(`SOPTIX_BuildInput_Mesh`), and the `__closesthit__ch` triangle branch
already existed; this commit fills in the pipeline + SBT side so they
are actually exercised on a physics launch.
Add a CI test that reuses the existing GPURaytrace binary on
tests/geom/opticks_raindrop.gdml. Runs once with the default analytic
CSG path and once with `stree__force_triangulate_solid=G4_WATER_solid`,
asserting bit-identical Opticks NumHits.

A G4Box triangulates to 12 flat triangles that exactly coincide with
the analytic surface (validated across multiple seeds), so a strict
equality check is appropriate: any divergence indicates a regression
in the triangulated-GAS pipeline wiring (PIP primitive flags, second
hitgroup PG, or SBT per-record header packing).

Hooked into .github/workflows/build-pull-request.yaml next to the
existing test_GPURaytrace.sh invocation.
@ggalgoczi ggalgoczi self-assigned this May 15, 2026
@ggalgoczi ggalgoczi added the enhancement New feature or request label May 15, 2026
@ggalgoczi ggalgoczi requested a review from plexoos May 15, 2026 21:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant