Skip to content

Refactor Gaussian splatting ops and extract utility functions#596

Merged
fwilliams merged 1 commit into
mainfrom
pr2/dissolve-gsplat
Apr 17, 2026
Merged

Refactor Gaussian splatting ops and extract utility functions#596
fwilliams merged 1 commit into
mainfrom
pr2/dissolve-gsplat

Conversation

@fwilliams

@fwilliams fwilliams commented Apr 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR is primarily code migration and renaming for consistency. It introduces no functional changes and removes some code duplication.

What is included:

  • Renames 21 Gaussian splatting operator file pairs in ops/gsplat/ with descriptive names (e.g. GaussianProjectionForward -> ProjectGaussiansAnalyticForward, GaussianRasterizeForward -> RasterizeScreenSpaceGaussiansForward)
  • Extracts shared CUDA utilities into utils/cuda/ (BinSearch, CubWrapper, Prefetch, WarpReduce, Alignment, CopyCoords, OpType) and utils/cuda/math/ (AffineTransform, Rotation)
  • Extracts Gaussian-specific utilities into utils/gsplat/ (Gaussian2D, GaussianCameraAccessorCopy, GaussianCameras, GaussianMath, GaussianRasterize, GaussianRasterizeFromWorld, GaussianRasterizeOptionalInputs)
  • Removes the template dispatch pattern (dispatchFoo<DeviceTag>) from op headers in favor of plain functions with internal device dispatch
  • Deletes dead gsplat files: GaussianUtils.cpp/.h/.cuh, GaussianVectorTypes, GaussianMacros, GaussianRenderSettings, GaussianRigidTransform, GaussianCameraMatrixUtils, GaussianWarpUtils
  • Renames GaussianSplatBinding.cpp -> GaussianSplatOps.cpp
  • Updates all include paths in bindings, viewer, PLY I/O, and 16 C++ test files
  • Removes OpType struct in favor of PyTorch's built-in at::opmath_type
  • Removes GSPLAT_PRAGMA_UNROLL struct in favor of #pragma unroll

Part of #590 (PR 2: refactor gsplat directory).

Test plan

  • C++ build succeeds
  • C++ gtests: 39/41 pass (2 pre-existing flaky failures unrelated to this change: GaussianRasterizeForwardMaskedEdgeTile.NoDeadlock deadlock timeout, PredGatherIGemmTest CUDA launch failure)
  • Python unit tests (cd tests && pytest unit -v)
  • CI passes

@fwilliams fwilliams requested a review from a team as a code owner April 10, 2026 23:20
@fwilliams fwilliams enabled auto-merge (squash) April 11, 2026 00:22
Comment thread src/fvdb/detail/utils/cuda/Prefetch.h
Comment thread src/fvdb/detail/utils/cuda/OpType.cuh Outdated
Comment thread src/fvdb/detail/ops/gsplat/EvaluateSphericalHarmonicsBackward.cu
Comment thread src/fvdb/detail/utils/cuda/CubWrapper.cuh Outdated
@fwilliams fwilliams force-pushed the pr2/dissolve-gsplat branch 2 times, most recently from c2ba2a6 to 56fd532 Compare April 13, 2026 17:53
@matthewdcong

Copy link
Copy Markdown
Contributor

I think we also have some Python function naming leaking into the C++ side. For example, dispatch_rasterize_screen_space_gaussians_bwd in RasterizeScreenSpaceGaussiansBackward.cu. Unless that's intentional?

@fwilliams

Copy link
Copy Markdown
Collaborator Author

I think we also have some Python function naming leaking into the C++ side. For example, dispatch_rasterize_screen_space_gaussians_bwd in RasterizeScreenSpaceGaussiansBackward.cu. Unless that's intentional?

It's intentional. I'm trying to have the operator names and the binding names align. rasterize_screen_space_gaussians is more precise and constrasts against rasterize_world_space_gaussians.

@matthewdcong

Copy link
Copy Markdown
Contributor

I think we also have some Python function naming leaking into the C++ side. For example, dispatch_rasterize_screen_space_gaussians_bwd in RasterizeScreenSpaceGaussiansBackward.cu. Unless that's intentional?

It's intentional. I'm trying to have the operator names and the binding names align. rasterize_screen_space_gaussians is more precise and constrasts against rasterize_world_space_gaussians.

Sorry I mean the conventions -- In the C++ code, it should be named rasterizeScreenSpaceGaussians in order to match with the rest of the code.

@harrism

harrism commented Apr 13, 2026

Copy link
Copy Markdown
Contributor
  • Moves 21 Gaussian op file pairs from ops/gsplat/ into ops/ with descriptive names (e.g. GaussianProjectionForward -> ProjectGaussiansAnalyticForward, GaussianRasterizeForward -> RasterizeScreenSpaceGaussiansForward)

If we move all 3DGS ops into the top-level ops directory, it would be helpful to start all 3DGS files with a common prefix. Previously we had "Gaussian".

@fwilliams

Copy link
Copy Markdown
Collaborator Author
  • Moves 21 Gaussian op file pairs from ops/gsplat/ into ops/ with descriptive names (e.g. GaussianProjectionForward -> ProjectGaussiansAnalyticForward, GaussianRasterizeForward -> RasterizeScreenSpaceGaussiansForward)

If we move all 3DGS ops into the top-level ops directory, it would be helpful to start all 3DGS files with a common prefix. Previously we had "Gaussian".

They are standalone ops now with a consistent naming that matches their python counterpart names. e.g. rasterize_screen_space_gaussians_fwd matches RasterizeScreenSpaceGaussiansForward.

I'd push back a bit on adding Gaussian as a prefix to each op file here since we don't do this for e.g. JaggedTensor or GridBatch (its SampleGridTrilinear not GridBatchSampleGridTrilinear). My medium term goal is to have the names of files and operators match from the _fvdb_cpp layer down to the ops directory. The gsplat directory was large with a lot common utilities that got moved out. Now its slimmed down to about 20 ops.

What are your thoughts?

@swahtz

swahtz commented Apr 13, 2026

Copy link
Copy Markdown
Contributor
  • Moves 21 Gaussian op file pairs from ops/gsplat/ into ops/ with descriptive names (e.g. GaussianProjectionForward -> ProjectGaussiansAnalyticForward, GaussianRasterizeForward -> RasterizeScreenSpaceGaussiansForward)

If we move all 3DGS ops into the top-level ops directory, it would be helpful to start all 3DGS files with a common prefix. Previously we had "Gaussian".

Why do we want to move the Gaussian-related ops out of ops/gsplat (or whatever ops subdirectory name we might want)? From a purely code organization standpoint I find it beneficial to have all the interdependent Gaussian-related ops together. What's the benefit of moving them?

@fwilliams

fwilliams commented Apr 13, 2026

Copy link
Copy Markdown
Collaborator Author
  • Moves 21 Gaussian op file pairs from ops/gsplat/ into ops/ with descriptive names (e.g. GaussianProjectionForward -> ProjectGaussiansAnalyticForward, GaussianRasterizeForward -> RasterizeScreenSpaceGaussiansForward)

If we move all 3DGS ops into the top-level ops directory, it would be helpful to start all 3DGS files with a common prefix. Previously we had "Gaussian".

Why do we want to move the Gaussian-related ops out of ops/gsplat (or whatever ops subdirectory name we might want)? From a purely code organization standpoint I find it beneficial to have all the interdependent Gaussian-related ops together. What's the benefit of moving them?

For the same reason we haven't split up GridBatch and all the JaggedTensor ops into their own folders. If we do this, we can segment out different ops into different directories based on their type but I think its not always a clean mapping. E.g. here spherical harmonics evaluation is a generic operator that we happen to use a lot in conjunction with Gaussian splatting.

We can certainly try and group .cu/.h pairs into folders for code organization purposes but I wonder if we shouldn't do this all in one go.

Personally, I prefer to have all the ops be in one big folder but I don't feel that strongly one way or another. If we're going to partition op files, I prefer to do it consistently.

@swahtz

swahtz commented Apr 13, 2026

Copy link
Copy Markdown
Contributor
  • Moves 21 Gaussian op file pairs from ops/gsplat/ into ops/ with descriptive names (e.g. GaussianProjectionForward -> ProjectGaussiansAnalyticForward, GaussianRasterizeForward -> RasterizeScreenSpaceGaussiansForward)

If we move all 3DGS ops into the top-level ops directory, it would be helpful to start all 3DGS files with a common prefix. Previously we had "Gaussian".

Why do we want to move the Gaussian-related ops out of ops/gsplat (or whatever ops subdirectory name we might want)? From a purely code organization standpoint I find it beneficial to have all the interdependent Gaussian-related ops together. What's the benefit of moving them?

For the same reason we haven't split up GridBatch and all the JaggedTensor ops into their own folders. If we do this, we can segment out different ops into different directories based on their type but I think its not always a clean mapping. E.g. here spherical harmonics evaluation is a generic operator that we happen to use a lot in conjunction with Gaussian splatting.

We can certainly try and group .cu/.h pairs into folders for code organization purposes but I wonder if we shouldn't do this all in one go.

Personally, I prefer to have all the ops be in one big folder but I don't feel that strongly one way or another. If we're going to partition op files, I prefer to do it consistently.

But the reality is that there is no functionality that uses the spherical harmonics evaluation operators outside of Gaussian splatting and the arguments to the SH evaluation ops are specific to the Gaussian splatting toolchain (e.g. the means and projected radii arguments). Until there's a reason to move them into a more generic folder, I don't see why we would change that from where they stand today.

@harrism

harrism commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Unless it's a public interface that we want to simplify #include lines for, I prefer to have things more organized rather than one big dump folder.

@fwilliams

Copy link
Copy Markdown
Collaborator Author

Unless it's a public interface that we want to simplify #include lines for, I prefer to have things more organized rather than one big dump folder.

Unless it's a public interface that we want to simplify #include lines for, I prefer to have things more organized rather than one big dump folder.

Sounds good - I moved it into a folder for better organization. Let me know if you guys are happy with the PR otherwise!

@swahtz swahtz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Loving the removal of the templated dispatch functions everywhere. Just a few docs/naming and other improvement comments. Thanks

Comment thread fvdb/__init__.py
Comment thread src/python/GaussianSplatOps.cpp Outdated
Comment thread fvdb/__init__.py
Comment thread src/python/GaussianSplatOps.cpp Outdated
Comment thread src/python/GaussianSplatOps.cpp
Comment thread src/fvdb/detail/utils/cuda/math/AffineTransform.cuh
Comment thread src/fvdb/detail/utils/gsplat/GaussianMath.cuh
Comment thread src/fvdb/detail/utils/gsplat/GaussianMath.cuh
Comment thread src/fvdb/detail/utils/gsplat/GaussianRasterizeFromWorld.cuh
Comment thread src/fvdb/detail/utils/gaussian/GaussianRasterizeOptionalInputs.h Outdated
@matthewdcong

Copy link
Copy Markdown
Contributor

If we're going to keep the splatting operators in a subdirectory, can we just keep the gsplat folder name instead of introducing a new gaussian_splatting folder? It would make the changes easier to follow through the history in the short term, and we can rename it in a straightforward follow up PR.

@fwilliams

Copy link
Copy Markdown
Collaborator Author

Done -- renamed back to gsplat/ in the latest push.

fwilliams added a commit that referenced this pull request Apr 14, 2026
- Add input validation on sh0 shape in evaluate_spherical_harmonics
- Clean up GaussianSplatOps.cpp comments (remove PR-specific notes, empty
  sections, parentheticals, numbered function comments)
- Use empty tensor for shN at degree 0 in GaussianSplat3d._eval_sh to
  avoid holding the full tensor in the autograd graph
- Revert prepare_raster_optional_inputs to camelCase (not Python-bound)
- Add doxygen @param/@return docs to AffineTransform.cuh, GaussianMath.cuh,
  and GaussianRasterizeFromWorld.cuh helpers
- Rename ops/gaussian_splatting/ back to ops/gsplat/ per reviewer request
- Update _fvdb_cpp.pyi stub to match current bindings (add 16 missing
  function stubs, remove 2 stale ones, fix signatures)

Signed-off-by: Francis Williams <francis@fwilliams.info>
Made-with: Cursor
Comment thread src/fvdb/detail/ops/gsplat/FusedSSIM.cu Outdated
Comment thread src/fvdb/detail/ops/gsplat/FusedSSIM.cu Outdated

@matthewdcong matthewdcong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the continued comments. I have some more feedback after checking out your branch and playing around with it.

Comment thread src/fvdb/detail/utils/cuda/Prefetch.h
Comment thread src/fvdb/detail/utils/gsplat/Gaussian2D.cuh
Comment thread src/fvdb/detail/ops/gsplat/FusedSSIM.cu
Comment thread src/fvdb/detail/utils/cuda/Prefetch.h Outdated
Comment thread src/fvdb/detail/utils/cuda/Prefetch.h Outdated

@swahtz swahtz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, thanks for taking on board my notes and explaining the changes.

@matthewdcong

matthewdcong commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Can we update the PR and title description to reflect the latest since it ends up going into the final squashed MR? Also, please add that GSPLAT_PRAGMA_UNROLL has been replaced by #pragma unroll.

@matthewdcong matthewdcong changed the title Dissolve gsplat/ directory: flatten ops and extract utilities Refactor Gaussian splatting ops and extract utility functions Apr 16, 2026
@matthewdcong matthewdcong force-pushed the pr2/dissolve-gsplat branch 3 times, most recently from 9b09c93 to e6f34aa Compare April 16, 2026 17:39
@matthewdcong

Copy link
Copy Markdown
Contributor

Modified the description and title. Lmk if anything is off

@matthewdcong matthewdcong disabled auto-merge April 16, 2026 23:12
fwilliams added a commit that referenced this pull request Apr 16, 2026
This PR is primarily code migration and renaming for consistency. It
introduces no functional changes and removes some code duplication.

What is included:
- Renames 21 Gaussian splatting operator file pairs in `ops/gsplat/`
  with descriptive names (e.g. `GaussianProjectionForward` ->
  `ProjectGaussiansAnalyticForward`, `GaussianRasterizeForward` ->
  `RasterizeScreenSpaceGaussiansForward`)
- Extracts shared CUDA utilities into `utils/cuda/` (BinSearch,
  CubWrapper, Prefetch, WarpReduce, Alignment, CopyCoords, OpType) and
  `utils/cuda/math/` (AffineTransform, Rotation)
- Extracts Gaussian-specific utilities into `utils/gsplat/` (Gaussian2D,
  GaussianCameraAccessorCopy, GaussianCameras, GaussianMath,
  GaussianRasterize, GaussianRasterizeFromWorld,
  GaussianRasterizeOptionalInputs)
- Removes the template dispatch pattern (`dispatchFoo<DeviceTag>`) from
  op headers in favor of plain functions with internal device dispatch
- Deletes dead gsplat files: GaussianUtils.cpp/.h/.cuh,
  GaussianVectorTypes, GaussianMacros, GaussianRenderSettings,
  GaussianRigidTransform, GaussianCameraMatrixUtils, GaussianWarpUtils
- Renames `GaussianSplatBinding.cpp` -> `GaussianSplatOps.cpp`
- Updates all include paths in bindings, viewer, PLY I/O, and 16 C++
  test files
- Removes `OpType` struct in favor of PyTorch's built-in `at::opmath_type`
- Removes `GSPLAT_PRAGMA_UNROLL` struct in favor of `#pragma unroll`

Part of #590 (PR 2: refactor gsplat directory).

Co-authored-by: Matthew Cong <mcong@nvidia.com>
Made-with: Cursor
@fwilliams fwilliams force-pushed the pr2/dissolve-gsplat branch from ffd7623 to 878cf73 Compare April 16, 2026 23:58
This PR is primarily code migration and renaming for consistency. It
introduces no functional changes and removes some code duplication.

What is included:
- Renames 21 Gaussian splatting operator file pairs in `ops/gsplat/`
  with descriptive names (e.g. `GaussianProjectionForward` ->
  `ProjectGaussiansAnalyticForward`, `GaussianRasterizeForward` ->
  `RasterizeScreenSpaceGaussiansForward`)
- Extracts shared CUDA utilities into `utils/cuda/` (BinSearch,
  CubWrapper, Prefetch, WarpReduce, Alignment, CopyCoords, OpType) and
  `utils/cuda/math/` (AffineTransform, Rotation)
- Extracts Gaussian-specific utilities into `utils/gsplat/` (Gaussian2D,
  GaussianCameraAccessorCopy, GaussianCameras, GaussianMath,
  GaussianRasterize, GaussianRasterizeFromWorld,
  GaussianRasterizeOptionalInputs)
- Removes the template dispatch pattern (`dispatchFoo<DeviceTag>`) from
  op headers in favor of plain functions with internal device dispatch
- Deletes dead gsplat files: GaussianUtils.cpp/.h/.cuh,
  GaussianVectorTypes, GaussianMacros, GaussianRenderSettings,
  GaussianRigidTransform, GaussianCameraMatrixUtils, GaussianWarpUtils
- Renames `GaussianSplatBinding.cpp` -> `GaussianSplatOps.cpp`
- Updates all include paths in bindings, viewer, PLY I/O, and 16 C++
  test files
- Removes `OpType` struct in favor of PyTorch's built-in `at::opmath_type`
- Removes `GSPLAT_PRAGMA_UNROLL` struct in favor of `#pragma unroll`

Part of #590 (PR 2: refactor gsplat directory).

Co-authored-by: Matthew Cong <mcong@nvidia.com>
Signed-off-by: Francis Williams <francis@fwilliams.info>
Signed-off-by: Matthew Cong <mcong@nvidia.com>
Made-with: Cursor
@fwilliams fwilliams force-pushed the pr2/dissolve-gsplat branch from 878cf73 to ad90271 Compare April 17, 2026 00:03
@fwilliams fwilliams merged commit 9d1b5d5 into main Apr 17, 2026
38 checks passed
@fwilliams fwilliams deleted the pr2/dissolve-gsplat branch April 17, 2026 00:52
@swahtz swahtz added this to the v0.5 milestone Jun 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.

4 participants