Native CUDA mesh SDF backend + prebuilt CUDA wheels (0.0.2)#1
Merged
Conversation
Replace the SlangTorch mesh_sdf module with a native CUDA extension (torch.utils.cpp_extension), mirroring the maxwell FDTD CUDA backend. This removes the intermittent SlangTorch load failures on non-UTF-8 Windows consoles and ships prebuilt per-platform wheels so installs never invoke nvcc/MSVC. - geometry/cuda/: six mesh SDF kernels (brute/BVH unsigned distance, distance+winding, BVH ray-parity sign, and hand-derived backward gradients) plus a pybind extension and a JIT/packaged-prebuilt loader. - mesh_sdf.py: load the native module instead of Slang; keep the Torch-native fallback when CUDA/toolchain is unavailable. - Packaging: hatch build hook marks the wheel platform-specific and ships prebuilt/*.pyd plus the CUDA sources; publish workflow builds a CUDA wheel matrix (ubuntu-22.04 + windows-2022, py3.10-3.12) and sdist. - Bump version to 0.0.2.
There was a problem hiding this comment.
Pull request overview
This PR replaces the SlangTorch-based mesh SDF implementation with a native PyTorch CUDA extension (via torch.utils.cpp_extension), adds infrastructure for shipping/loading prebuilt CUDA binaries in wheels, and expands geometry/material utilities (including new polygon-extrusion primitives).
Changes:
- Replaced the Slang mesh SDF backend with a native CUDA extension + Python loader/fallback path.
- Added new polygon-based primitives (
PolySlab,ComplexPolySlab) with signed-distance + mesh export support (where applicable) and accompanying tests. - Updated packaging/build automation to include CUDA sources + prebuilt binaries in wheels and to build/publish a CUDA wheel matrix.
Reviewed changes
Copilot reviewed 17 out of 18 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| witwin/core/mesh_sdf.slang | Removes the old Slang kernel implementation (now superseded by the native CUDA extension). |
| witwin/core/material.py | Adds DifferentiableMaterial and helper coercion utilities for differentiable material parameters. |
| witwin/core/geometry/primitives.py | Adds polygon-loop signed distance helpers and new extruded polygon primitives (PolySlab, ComplexPolySlab). |
| witwin/core/geometry/mesh_sdf.py | Switches mesh SDF dispatch from SlangTorch to the native CUDA extension with caching + Torch fallback. |
| witwin/core/geometry/cuda/mesh_sdf_kernels.cu | Implements the native CUDA kernels (forward + analytic backward) for mesh SDF queries. |
| witwin/core/geometry/cuda/extension.cpp | Defines the PyBind entry points for the CUDA extension. |
| witwin/core/geometry/cuda/build.py | Adds a JIT + packaged-prebuilt loader/build wrapper (including Windows toolchain probing). |
| witwin/core/geometry/cuda/backend.py | Provides a SlangTorch-compatible “module-like” kernel launcher shim over the compiled extension. |
| witwin/core/geometry/cuda/init.py | Exposes the native CUDA backend entry points from the package. |
| witwin/core/geometry/init.py | Exports PolySlab / ComplexPolySlab and includes them in the Geometry union. |
| witwin/core/init.py | Re-exports DifferentiableMaterial at the top-level witwin.core API. |
| tests/test_geometry_smoke.py | Adds smoke coverage for PolySlab construction/to-mesh/to-mask. |
| tests/test_geometry_sdf.py | Adds signed-distance and gradient tests covering polygon slab primitives; updates CUDA SDF skip logic to the native backend. |
| scripts/build_mesh_sdf_cuda_prebuilt.py | Adds a helper script to build and stage a prebuilt extension into cuda/prebuilt/. |
| pyproject.toml | Bumps version to 0.0.2 and configures wheel artifacts + custom hatch hook. |
| hatch_build.py | Marks wheels as non-pure/infer-tagged when a prebuilt extension is present. |
| .gitignore | Ignores prebuilt native extension binaries under witwin/core/geometry/cuda/prebuilt/. |
| .github/workflows/publish-witwin.yml | Adds a CUDA wheel build matrix (Linux/Windows, Py3.10–3.12), sdist build, and release-gated publish flow. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+23
to
+44
| def _coerce_differentiable_scalar(value: Any, *, name: str) -> Any: | ||
| try: | ||
| return float(value) | ||
| except (TypeError, ValueError): | ||
| return value | ||
|
|
||
|
|
||
| def _coerce_differentiable_nonnegative(value: Any, *, name: str) -> Any: | ||
| try: | ||
| scalar = float(value) | ||
| except (TypeError, ValueError): | ||
| return value | ||
| if scalar < 0.0: | ||
| raise ValueError(f"{name} must be >= 0.") | ||
| return scalar | ||
|
|
||
|
|
||
| def _is_numeric_close(value: Any, target: float) -> bool: | ||
| try: | ||
| return bool(np.isclose(float(value), target)) | ||
| except (TypeError, ValueError): | ||
| return False |
Comment on lines
+179
to
+191
| if resolved_frequency == 0.0: | ||
| if not _is_numeric_close(self.sigma_e, 0.0): | ||
| try: | ||
| scalar_sigma = float(self.sigma_e) | ||
| except (TypeError, ValueError): | ||
| scalar_sigma = None | ||
| if scalar_sigma is not None: | ||
| raise ValueError("Conductive materials require frequency > 0.") | ||
| return FrequencyMaterialSample( | ||
| eps_r=self.eps_r, | ||
| mu_r=self.mu_r, | ||
| sigma_e=self.sigma_e, | ||
| ) |
Comment on lines
+193
to
+204
| try: | ||
| eps_r = complex( | ||
| float(self.eps_r), | ||
| -float(self.sigma_e) / (2.0 * np.pi * resolved_frequency * VACUUM_PERMITTIVITY), | ||
| ) | ||
| mu_r = float(self.mu_r) | ||
| sigma_e = float(self.sigma_e) | ||
| except (TypeError, ValueError): | ||
| eps_r = self.eps_r | ||
| mu_r = self.mu_r | ||
| sigma_e = self.sigma_e | ||
| return FrequencyMaterialSample( |
| @@ -3,6 +3,7 @@ | |||
| __version__ = "0.0.1" | |||
Comment on lines
+237
to
+256
| const float N = vdot(a, vcross(b, c)); | ||
| const float D = la * lb * lc + ab * lc + bc * la + ca * lb; | ||
| const float scale = 2.0f * grad_output / fmaxf(N * N + D * D, eps); | ||
|
|
||
| // dN/dA = b x c, dN/dB = c x a, dN/dC = a x b. | ||
| const float3 dN_da = vcross(b, c); | ||
| const float3 dN_db = vcross(c, a); | ||
| const float3 dN_dc = vcross(a, b); | ||
| const float3 a_hat = vscale(a, 1.0f / la); | ||
| const float3 b_hat = vscale(b, 1.0f / lb); | ||
| const float3 c_hat = vscale(c, 1.0f / lc); | ||
| // dD/dA = (lb*lc + b.c) a_hat + lc*b + lb*c, and cyclic variants. | ||
| const float3 dD_da = vadd(vadd(vscale(a_hat, lb * lc + bc), vscale(b, lc)), vscale(c, lb)); | ||
| const float3 dD_db = vadd(vadd(vscale(b_hat, la * lc + ca), vscale(a, lc)), vscale(c, la)); | ||
| const float3 dD_dc = vadd(vadd(vscale(c_hat, la * lb + ab), vscale(b, la)), vscale(a, lb)); | ||
|
|
||
| // d(atan2(N, D)) = (D dN - N dD) / (N^2 + D^2); grad = scale * that. | ||
| const float3 gA = vscale(vsub(vscale(dN_da, D), vscale(dD_da, N)), scale); | ||
| const float3 gB = vscale(vsub(vscale(dN_db, D), vscale(dD_db, N)), scale); | ||
| const float3 gC = vscale(vsub(vscale(dN_dc, D), vscale(dD_dc, N)), scale); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replace the SlangTorch mesh_sdf module with a native CUDA extension
(torch.utils.cpp_extension), mirroring the maxwell FDTD CUDA backend.
Removes intermittent SlangTorch load failures on non-UTF-8 Windows
consoles and ships prebuilt per-platform wheels so installs never
invoke nvcc/MSVC.
distance+winding, BVH ray-parity sign, hand-derived backward
gradients) + pybind extension + JIT/packaged-prebuilt loader.
prebuilt/*.pyd + CUDA sources; publish workflow builds a CUDA wheel
matrix (ubuntu-22.04 + windows-2022, py3.10-3.12) + sdist.
CI: all 6 CUDA wheel builds + sdist green on the branch; each build
smoke-loads the packaged prebuilt without compiling.
🤖 Generated with Claude Code