Summary:
Fixes the coordinate indexing used by frustum face culling, and keeps the now-live culling from deleting faces that straddle the camera plane.
`face_verts` has shape `[F, 3, 3]`, where the last two dimensions are the vertex and the xyz coordinate. `_get_culled_faces` indexed it as `face_verts[:, axis]`, which picks one whole vertex out of every face rather than one coordinate out of all three vertices, so `verts_clipped.sum(1) == 3` was asking whether a single vertex was outside the plane on all three axes at once. Every other access in the file agrees with the documented layout — `clip_faces` reads z as `face_verts_unclipped[:, :, 2]`. The fix selects the coordinate with `face_verts[:, :, axis]` and reduces with `all(dim=1)`, which states the documented condition directly: a face is culled only when all three of its vertices lie outside the same plane.
Because the old indexing almost never fired, this is the first time frustum culling does real work, and that exposes a second problem. `_get_culled_faces` runs on the unclipped face verts, and `rasterize_meshes` passes `left`/`right`/`top`/`bottom` in NDC while z stays in world space. The perspective divide mirrors vertices behind the camera through the origin, so a triangle straddling the camera plane can have all 3 projected vertices outside the same xy plane while the part of it in front of the camera still crosses the frustum. At fov 90, for instance, the vertices `(-1.1, 0, 1)`, `(100, 0, -1)` and `(100, 0.1, -1)` all project to x < -1, yet the edge from the first to the second passes through x = 0 while still at z > 0. Culled faces are classified as case 2 and dropped outright, before z clipping could have salvaged them, so that triangle would vanish from the render.
xy culling is therefore now applied only to faces lying entirely in front of the clipping plane (`z >= z_clip_value`, or `z > 0` when no clip value is set), and only when `perspective_correct` is set; straddling faces are left to the z clipping step. Orthographic projections keep usable xy coordinates behind the camera and are unaffected, as is culling on the z axis, which uses world coordinates throughout. The `frustum.cull` check also moves out of the per-plane loop into an early return.
For blast radius: `RasterizationSettings.cull_to_frustum` defaults to `False`, but `rasterize_meshes_python` defaults it to `True`.
Fixes https://github.com/facebookresearch/pytorch3d/issues/1936.
Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/2044
Test Plan:
`buck2 test fbcode//vision/fair/pytorch3d:tests`, filtered to the culling and rendering tests (`--regex 'test_render_meshes_clipped|test_render_meshes\b|clip'`): 34 passed, 0 failed, 8 skipped. The skips are the OpenGL-only tests.
Two new unit tests over `_get_culled_faces`:
- `test_cull_faces_uses_coordinate_axis` — for each of the 6 planes, a face whose 3 vertices all lie outside it is culled; and a face intersecting the left plane stays visible for 3 different vertex orders. Fails on the old `face_verts[:, axis]` indexing.
- `test_cull_faces_straddling_perspective_camera` — a face with one vertex in front of the camera and two behind it, all 3 projecting outside the left plane, is not culled under a perspective projection (with and without a `z_clip_value`) but is culled under an orthographic one; and z-axis culling still fires for a face lying entirely behind `znear`. Negative control: with the xy gating disabled and nothing else changed, this test fails on 2 assertions, so it pins the new behaviour rather than restating it.
`arc lint` on `pytorch3d/renderer/mesh/clip.py` and `tests/test_render_meshes_clipped.py`: no issues.
Reviewed By: MichaelRamamonjisoa
Differential Revision: D117200371
Pulled By: bottler
fbshipit-source-id: 99422fc69f4f5725bd82f6af205a0a333a4aef40
Summary:
`TestICP.test_heterogeneous_inputs` has been failing intermittently for a long
time. The seed was already bumped from 4 to 14 in D80625966 for the same
reason, which relocated the failure rather than removing it.
Root cause: the test aligned two independent random point clouds, and with
`estimate_scale=True` that problem is ill-posed. ICP almost always collapses
`X` onto a single point of `Y`, driving `s` to ~1e-16 and the rmse to zero.
That solution fits perfectly, but the rotation of a cloud that has shrunk to a
point is completely unconstrained, so the batched run and the per-cloud runs
each returned an arbitrary, and different, `R`. Over 600 seeds of the old data
~45% of batch elements collapsed, and every element that exceeded the
tolerance was a collapsed one, with `R` the only quantity that disagreed
(`T`, `s` and `Xt` always matched). This is the same non-uniqueness that
`corresponding_points_alignment` warns about with "Excessively low rank of
cross-correlation".
Which seeds tripped over it came down to float32 rounding: the batched path
sums over the zero-weighted padding and the per-cloud path does not, so the
two differ by ~1e-7, and that difference decides which arbitrary rotation
comes out. It therefore moves with GPU model, BLAS version and TF32, which is
why picking a seed was never a fix - forcing TF32 on makes seed 14 fail
immediately.
Fix: build `Y` as a rigidly moved copy of `X` plus a few extra points. The
clouds still have different sizes within a batch and between `X` and `Y`, so
the padding and masking path is exercised exactly as before, but the alignment
now has a well-determined optimum that ICP cannot collapse.
Also loosen `atol` from 1e-5 to 1e-4. That is needed independently of the
collapse: the two runs sum a different number of terms and so round
differently, and the legitimate deviation on `Xt` reaches 1.17e-5, above the
old tolerance. That was a second latent failure waiting to happen.
The test no longer emits the "Excessively low rank of cross-correlation"
warning, which is the collapse disappearing.
___
Differential Revision: D117539518
fbshipit-source-id: 73e3d70a8f7547de7179b71e6a705fc37f4920c7
Summary:
This diff was automatically generated by the Pyre per-target upgrade tool.
It removes `# pyre-fixme` or `pyrefly: ignore` comments that are no longer needed because the underlying type errors have been resolved.
Note that it will also aim to ensure type checking runs cleanly, and will add suppressions to existing type errors.
#pyreupgrade
Differential Revision: D116557086
fbshipit-source-id: 1337613d4fb3ab79bd3a733f3a4c9a499a72f971
Summary:
GitHub issue #2002 (https://github.com/facebookresearch/pytorch3d/issues/2002)
points out that the near-pi branch of `matrix_to_axis_angle(..., fast=True)`
normalizes with `torch.norm(n)`, which reduces over the whole batch. That is
real, and there were two further problems next to it.
`matrix_to_axis_angle(..., fast=True)`:
- The axis was read from row 0 of `(R + I) / 2`, which is `n_x * n`. That is
exactly zero whenever the axis is perpendicular to x, giving `nan` (for
example for an exact rotation by pi about y), and is dominated by rounding
when `abs(n_x)` is small. It is now read from
`R + R^T - 2*cos(angle)*I == 2*(1 - cos(angle))*nnT`, taking the column whose
diagonal entry is largest so that the multiplier is at least `1/sqrt(3)`.
Symmetrizing also makes the identity exact at every angle rather than only at
pi. The sign, which `nnT` does not determine, comes from `omegas`.
- `torch.norm(n)` becomes a per-row `torch.linalg.vector_norm`, which is the
reported bug: with more than one near-pi rotation in a batch, every one of
them was scaled wrongly.
- The branch threshold was `isclose(angle, pi)`. `omegas` is `2*sin(angle)`
times the axis, so the other branch loses relative precision like
`1/(pi - angle)`, and just outside `isclose` the float32 round-trip error
reached 9.6e-4. The threshold is now `pi - 1e-2`, which leaves under 1% of
uniformly random rotations on the more expensive branch.
- The `torch.isclose(angles, 0)` guard on `omegas` is removed. `torch.sinc(0)`
is 1, so a zero angle was never a special case, and `torch.norm` has a zero
rather than `nan` gradient at zero. The guard only zeroed the answer for
angles below its `atol` of 1e-8, returning 0 instead of an exact 1e-9
rotation, and cost 24% at a batch of 100k.
Worst-case float32 round-trip matrix error over random axes, before -> after:
exactly pi `nan` or 2.0 -> 3.6e-07; `pi - 1e-5` 2.0 -> 4.2e-07; `pi - 1e-4`
9.6e-04 -> 3.6e-07. The worst case at any angle is now 9.9e-06, at the branch
boundary, against 4.8e-07 for `fast=False`.
On the choice of `pi - 1e-2`: the new near-pi branch is accurate at any
threshold, so the threshold only decides how much of the batch takes the
slower branch, and the worst case is always the angle just below it. Measured
on one batch of 100k random float32 rotations on CPU, where `fast=False` took
11.4 ms, threshold against fraction of uniformly random rotations selected,
time, and worst-case round-trip error:
- `isclose(angle, pi)`, the previous behaviour: 0.003%, 8.6 ms, 1e-03
- `pi - 1e-3`: 0.1%, 8.9 ms, 9e-05
- `pi - 1e-2`, chosen: 0.7%, 8.9 ms, 1e-05
- `pi - 0.05`: 3.2%, 10.2 ms, 3e-06
- `3.0` radians: 9.0%, 17.6 ms, 9e-07
So `pi - 1e-2` buys two orders of magnitude of accuracy over the old threshold
for no measurable time, and it is the last threshold that is free; at `3.0`
radians `fast=True` would be slower than `fast=False`. The errors are sampled
over random axes, so they move in the last digit between runs.
`axis_angle_to_matrix(..., fast=True)` is Rodrigues' formula rewritten with
`cross_product_matrix^2 == outer_product - angle^2 * I` and
`(1 - cos(angle)) / angle^2 == sinc(angle / (2*pi))^2 / 2`. The first removes a
batched 3x3 matrix multiplication, which `bmm` serves poorly at that size, and
folds the leftover `-angle^2 * I` into the identity term as `cos(angle) * I`;
the second is defined at zero, so the `angles_sqrd == 0` special case goes
away. Values are unchanged to 8.9e-16.
`matrix_to_axis_angle` also used eight separate boolean mask indexes, each of
which re-runs `nonzero` over the whole batch and, on CUDA, synchronizes. The
cheap branch is now evaluated densely and the near-pi minority is selected
with a single `nonzero`.
Evaluating the near-pi branch densely too, which would remove the last
`nonzero` and so every data-dependent shape, was tried and rejected: against
this version it is 1.24x to 1.60x faster on CUDA at batches of 1k to 100k but
0.88x at 1M, and about 2x slower on CPU, and it does not survive
`torch.jit.script` without further work. It is the version to revisit if
export or `torch.compile` friendliness ever matters more than speed.
Speedups, before -> after:
- `matrix_to_axis_angle`: CUDA 1.88x at a batch of 1k, 1.66x at 100k, 1.47x at
1M; CPU 1.26x at 1k, 2.01x at 100k, 1.71x at 1M.
- `axis_angle_to_matrix`: CUDA 1.26x at 1k, 1.81x at 100k, 5.49x at 1M; CPU
unchanged.
Before this change `matrix_to_axis_angle(..., fast=True)` was slower than
`fast=False` on CUDA at a batch of 100k, 0.587 against 0.463 ms, because the
selection synchronized.
Rewriting `axis_angle_to_matrix` to compute all nine entries in one
`torch.stack`, as `quaternion_to_matrix` does, was also tried and is not
faster: 0.96x, 0.74x and 1.10x on CUDA at 1k, 100k and 1M, because the extra
kernel launches cost about what the saved intermediates gain.
Reviewed By: MichaelRamamonjisoa
Differential Revision: D115714860
fbshipit-source-id: cf19695f67bf2e2e6f8719419e9f902d5c58c309
Summary:
Fixes https://github.com/facebookresearch/pytorch3d/issues/1934. Two independent bugs in the CPU backend.
### 1. Degenerate-triangle filter discards valid faces
`marching_cubes_cpu.cpp`, `marching_cubes.py`
`tri.clear()` and `ps.clear()` sit inside the degeneracy check, so the buffers only reset when a triangle is *accepted*. Once a cube's first triangle is degenerate, `ps[0..2]` stay frozen on it, and every subsequent triangle in that cube fails the same stale check and is dropped.
Fixed by gating on `ps.size() == 3` and clearing unconditionally. The old code could only ever drop faces, never emit incorrect ones, so this is strictly additive.
### 2. Edge hash computed in float32
`marching_cubes_utils.h`
`p[v].x/y/z` hold integral coordinates but are stored as `float`, so `x + y*W + z*W*H` evaluates entirely in float32 before truncating to `int`. float32 is exact only to 2²⁴ − 1 = 16,777,215 — and 256³ maxes out at exactly that value. At 512³ the maximum id is 134,217,727, where float32 spacing is 8, so distinct vertices collide on one id and `uniq_edge_id` merges them.
Fixed by widening `W/H/D` to `int64_t` and casting each coordinate before multiplying. Also tightens the stride from `(W + W*H + W*H*D)` to `W*H*D`. Raises the CPU ceiling from 256³ to 1448³.
Scope is the CPU path only. `marching_cubes_naive` was never affected (Python ints are arbitrary-precision), and neither was CUDA: `hashVpair` there computes ids in `uint` rather than `float`, so it has no 2²⁴ cliff, and `MarchingCubes` already rejects volumes above 1024³ before the CUDA kernel runs. The new `TORCH_CHECK` bound and the "~1448³" note in the new comments describe `MarchingCubesCpu` only.
### Verification
Ellipsoid SDF (0.1, 1, 1), `isolevel=0.0`, identical input tensors on both devices.
| Resolution | CUDA V | CUDA F | CPU V | CPU F | Degenerate dropped |
| -- | -- | -- | -- | -- | -- |
| 32³ | 1,664 | 3,324 | 1,664 | 3,324 | 0 |
| 64³ | 7,312 | 14,620 | 7,312 | 14,620 | 0 |
| 128³ | 30,168 | 60,332 | 30,168 | 60,332 | 0 |
| 256³ | 122,448 | 244,892 | 122,448 | 243,996 | 896 |
| 512³ | 491,944 | 983,884 | 491,944 | 976,140 | 7,744 |
Machine: Arch Linux, RTX 4080, Ryzen 7 7800X3D
Vertex counts now match CUDA exactly at every resolution; 512³ previously produced 176,121. The remaining face gap is entirely degenerate geometry — the CUDA mesh at 512³ contains exactly 7,744 zero-area triangles.
### Tests
`test_degenerate_triangle_keeps_later_faces` — a 2×2×2 volume at `isolevel=1` chosen so the cube's four candidate triangles collapse onto its four outside corners: triangles 1 and 4 become degenerate, 2 and 3 stay valid. Pre-fix, the first degeneracy suppresses the rest and the mesh comes back empty; post-fix it is the expected quad. Asserts both `marching_cubes_naive` and the C++ extension.
`test_large_grid_edge_ids` — a 2×2×4,200,000 volume (~67MB, ~0.1s) holding 16 isolated interior points on the highest-id grid row, positioned so grid-point ids straddle 2²⁴. Each point cuts exactly four grid edges, so the 64-vertex expectation is derived geometrically rather than copied from output. Pre-fix, a hash collision merges two edges and one vertex is lost.
All 26 pre-existing tests in `test_marching_cubes.py` pass **unchanged**. That includes `test_cube_no_duplicate_verts` (`isolevel=1`) and `test_sphere` (`isolevel=64`), which both exercise the degenerate path but whose output is identical before and after the fix — so no existing expectation was edited and `sphere_level64.pickle` does not need regenerating.
The imported diff contained no test file. The two tests above were written during import and differ from the tests described in the upstream PR description.
*Analysis and write-up done collaboratively with AI, figures from testing are done on my own machine and have been checked.*
Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/2043
Test Plan:
```
buck2 test fbcode//vision/fair/pytorch3d:tests -- --regex 'test_marching_cubes'
```
`Pass 28. Fail 0.` — 26 pre-existing tests plus the 2 new regression tests.
Reverting all three source hunks to their pre-fix state and re-running the same command: both new tests fail (`test_degenerate_triangle_keeps_later_faces` returns an empty mesh instead of 4 verts / 2 faces; `test_large_grid_edge_ids` returns 31 verts instead of 32) and all 26 pre-existing tests still pass. The new tests are therefore pinned to exactly this change, and the change breaks nothing that was already covered.
Reviewed By: MichaelRamamonjisoa
Differential Revision: D115424433
Pulled By: bottler
fbshipit-source-id: 547a260010b94253f52f3a3c223d4c4fa78a7ee6
Summary:
`expand_args_fields` gated its whole member-processing pass on
`"__annotations__" in some_class.__dict__`. Under PEP 649 that entry is not in the
class dict until something materializes it, so on 3.14 the check was simply False,
no member was processed, and the pass that moves defaultable members to the end of
`__annotations__` never ran. The class then reached
`dataclasses.dataclass(eq=False)` with a defaulted `<name>_class_type` field ahead
of the non-defaulted `<name>` it replaces, which is a hard `TypeError` at class
construction.
`inspect.get_annotations` returns a class's own annotations — not a base's — which
is exactly what the `__dict__` lookup was expressing, and it behaves identically on
3.12. The in-place `del` / re-add on `some_class.__annotations__` further down is
unaffected: attribute access materializes and caches the dict on 3.14, so the
mutations stick and `dataclasses` sees them (verified on both interpreters).
325 canary failures in V58.
Reviewed By: bottler, ambv
Differential Revision: D115343017
fbshipit-source-id: 33f38dfac9f10c46b1f6b0e57f7005c9d7750dfa
Summary:
This diff was automatically generated by the Pyre per-target upgrade tool.
It adds `# pyre-fixme` or `pyrefly: ignore` comments to suppress type errors that will be introduced by an upcoming Pyre or Pyrefly release. These suppressions allow the upgrade to proceed without breaking existing code.
#pyreupgrade
Differential Revision: D113955432
fbshipit-source-id: e586f1f97f2a9256a8da6431ec9c17231788995e
Summary:
Automated migration to enable Pyrefly type checking for `fbcode/vision/fair/pytorch3d`.
- Added `python.set_pyrefly(True)` to PACKAGE file
- Suppressed pre-existing type errors
Pyrefly is Meta's next-generation Python type checker, replacing Pyre.
If you encounter issues, you can revert the PACKAGE change by removing
the `python.set_pyrefly(True)` line.
#pyreupgrade
Differential Revision: D113596106
fbshipit-source-id: a4caffc6c5622ea030fe296c3a64e45fa803f77e
Summary:
`_cot_laplacian_python` used in-place tensor operations (`clamp_`, `/=`,
`+=`) on intermediates that participate in autograd. Once the resulting
sparse Laplacian is used in a backward pass, these in-place mutations
raise a runtime error:
```
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.sparse.FloatTensor [4, 4]], which is output 0 of SparseCooTensorWithDimsAndTensors, is at version 1; expected version 0 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True, check_nan=False).
```
Replace the in-place ops with out-of-place equivalents so gradients can
flow back to the input vertices.
- `clamp_` → `clamp`
- `cot /= 4.0` → `cot = cot / 4.0`
- `L += L.t()` → `L = L + L.t()`
Reviewed By: bottler
Differential Revision: D111896032
fbshipit-source-id: 4c36677487bae5d37a9d81cb791400576f4b2c5f
Summary:
Pillow 10 removed `Image.ANTIALIAS` (the built 10.4.0 wheel raises `AttributeError`). Replace it with `Image.Resampling.LANCZOS`, the documented successor, which is dual-compat across Pillow 9.4.0 / 10.4.0 / 11.3.0 / 12.2.0. This lands cleanly under the current 9.4.0 pin ahead of the fleet pin bump. Pure constant rename, no behavior change.
PyTorch3D is Meta-authored OSS (fbcode is the source of truth); this change is exported to github.com/facebookresearch/pytorch3d, where the `ANTIALIAS` -> `Resampling.LANCZOS` modernization is equally valid.
Part of the Pillow 9.x -> 10.x migration; see `third-party/pypi/pillow/.agents/migrate-9-to-10.md`.
___
Differential Revision: D108493452
fbshipit-source-id: bb1588e9b2057c6cc27a3d6c382faa4b2ac65f7f
Summary:
This diff was automatically generated by the Pyre per-target upgrade tool.
It adds `# pyre-fixme` or `pyrefly: ignore` comments to suppress type errors that will be introduced by an upcoming Pyre or Pyrefly release. These suppressions allow the upgrade to proceed without breaking existing code.
wed - upgrade new suppression fix
#pyreupgrade
Differential Revision: D108188975
fbshipit-source-id: 65fb6fb0dbd6ade15bd8d85da912413eab2e41f9
Summary:
Add explicit dtype checks for input (torch.float32) and edges (torch.int64) in GatherScatter.forward and gather_scatter_python to match C++ TensorAccessor<float,2> and TensorAccessor<int64_t,2> expectations.
Python previously validated ndim, shape, and input dtype in forward but not edges dtype, and gather_scatter_python lacked dtype checks entirely, relying on ATen error from accessor. This makes errors python-friendly and guards C++ accessor before TensorAccessor construction.
___
Differential Revision: D108140422
fbshipit-source-id: ba54e857279a480a02e2c8f27e316f2e23cc6092
Summary:
Automated migration to enable Pyrefly type checking for `fbcode/vision/fair`.
- Added `python.set_pyrefly(True)` to PACKAGE file
- Suppressed pre-existing type errors
Pyrefly is Meta's next-generation Python type checker, replacing Pyre.
If you encounter issues, you can revert the PACKAGE change by removing
the `python.set_pyrefly(True)` line.
#pyreupgrade
Differential Revision: D107142434
fbshipit-source-id: 25929bb3d5a310d00dab11a46c5395df94357feb
Summary:
Enables building pytorch3d's `_C` extension against a ROCm-built PyTorch and running the test suite on AMD GPUs, including the pulsar subrenderer. Verified on AMD Instinct MI250X (gfx90a, warpSize=64), HIP 7.2, PyTorch 2.13.
## Mechanics
`torch.utils.cpp_extension.BuildExtension` auto-hipifies `.cu` sources of a `CUDAExtension` against a HIP-built torch (`cuda_runtime.h → hip/hip_runtime.h`, `cub:: → hipcub::`, `cudaStream_t → hipStream_t`, etc.), so most of the lift is build-system glue and a small number of CUDA intrinsics that don't have HIP equivalents.
- `setup.py`: detect ROCm via `torch.version.hip is not None`; treat `ROCM_HOME` as the GPU-toolkit-root analogue of `CUDA_HOME` (without this, `CUDA_HOME is None` silently demoted the build to a CPU-only `CppExtension`); skip `CUB_HOME`, CUDA-13 visibility flags, and `-ccbin=` on ROCm.
- `pytorch3d/csrc/pulsar/gpu/commands.h`: CUDA's `_rn`-suffixed FP rounding intrinsics (`__fadd_rn`, `__fdiv_rn`, `__fsqrt_rn`, `__fmaf_rn`, `__frcp_rn`) and `__saturatef` have no HIP equivalents — AMD's GPU ISA has no instruction-level rounding-mode override, so they expand to plain operators / `sqrtf` / `fmaf` / `1.0f/x` / `fmaxf(0,fminf(1,x))` on the `USE_ROCM` arm, which are rounding-mode-equivalent (both round-to-nearest-even). The HIP compiler may fuse `a+b*c` into a single-rounding FMA where CUDA's `_rn` would have prevented it; if FMA-fusion drift ever becomes a numerical issue, add `-ffp-contract=off` to pulsar's HIPCC flags. `__powf` is replaced with `powf`. `atomicAdd_block` has no HIP function-name equivalent — the semantic equivalent is `__hip_atomic_fetch_add(ptr, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_WORKGROUP)` (plain HIP `atomicAdd` is device-scope, strictly stronger than block-scope and forces L2-coherent atomics).
- `tests/test_point_mesh_distance.py`: loosen `grad_faces` tolerance in `test_point_face_distance` from `5e-7` to `5e-6` to match the sibling `test_face_point_distance`. The backward kernel uses `atomicAdd` and calls `alertNotDeterministic`; FP add order varies by wavefront width.
- The X_t / camera-R/T equality checks in `test_points_alignment.py` and `test_cameras_alignment.py` are now skipped when `n_points <= dim` (resp. `batch_size <= 3` for camera-center alignment in 3D). Mean-centering renders the SVD rank-deficient in those cases, so the rotation around the degenerate axis is non-unique and different BLAS implementations (rocBLAS RDNA vs CDNA, cuBLAS) pick different valid null-space directions. The center-alignment check still runs and verifies the well-defined part of the transformation.
Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/2039
Test Plan:
All GPU tests pass on both AMD Instinct MI250X (gfx90a, wave64, HIP 7.2) and AMD Radeon Pro W7800 (gfx1100, wave32, HIP 7.2.53211, torch 2.13.0a0).
| Module | Result |
|---|---|
| knn, ball_query, sample_farthest_points, face_areas_normals | all pass |
| rasterize_points, rasterize_meshes, chamfer, packed_to_padded | all pass |
| interpolate_face_attributes, blending, compositing, sample_pdf, mesh_normal_consistency | all pass |
| point_mesh_distance | 9/9 pass (with tolerance fix in this PR) |
| pulsar/test_forward, test_channels, test_depth, test_hands, test_ortho, test_small_spheres | 10 passed (FB_TEST=1) |
| test_render_points pulsar tests, test_camera_conversions::test_pulsar_conversion | 3 passed |
| points_to_volumes, iou_box3d, marching_cubes | 20 failures, all env-only |
The 20 env-only failures are `torch.inverse()` on CPU tensors in test reference paths; this verification host's PyTorch was built with `USE_LAPACK: 0` (only `mkl-static` `.a` archives in the conda env; PyTorch's `FindBLAS` looks for `libmkl_intel_lp64.so`). Unrelated to the port — re-verifying with a LAPACK-linked PyTorch is left to upstream.
Reviewed By: MichaelRamamonjisoa
Differential Revision: D106825690
Pulled By: bottler
fbshipit-source-id: f7a9b6028e6fb555f3b8c0f9792e88b818327166
Summary:
This diff was automatically generated by the Pyre per-target upgrade tool.
It adds `# pyre-fixme` or `pyrefly: ignore` comments to suppress type errors that will be introduced by an upcoming Pyre or Pyrefly release. These suppressions allow the upgrade to proceed without breaking existing code.
Pyrefly Upgrade - f-string fix
#pyreupgrade
Differential Revision: D105268300
fbshipit-source-id: 2f19758e20755944509fe14fc256002c652052a5
Summary:
No one is using these.
(The minify part has been broken for a couple of years, too)
Reviewed By: patricklabatut
Differential Revision: D96977684
fbshipit-source-id: 4708dfd37b14d1930f1370677eb126a61a0d9d3c
Summary: Remove the Support Ukraine banner component and its usage from the PyTorch3D website homepage.
Reviewed By: bottler
Differential Revision: D96559642
fbshipit-source-id: fd716cde7145d5c0105b2d2fb569375395b9b5de
Summary:
Replace boolean indexing and torch.is_grad_enabled() control flow in _sqrt_positive_part with a pure torch.where implementation. The old code used ret[positive_mask] = torch.sqrt(x[positive_mask]) which produces an incorrect ONNX Where/index_put node with mismatched broadcast shapes when the model is exported via torch.onnx.export.
The new implementation substitutes 1.0 for non-positive values before sqrt (avoiding infinite gradient at sqrt(0)) and masks the result back to 0, preserving the zero-subgradient-at-zero property.
Fixes https://github.com/facebookresearch/pytorch3d/issues/2020
Reviewed By: sgrigory
Differential Revision: D94365479
fbshipit-source-id: a1ebe8dc077573f83efc262520b6669159b83ef0
Summary:
Added `atol=1e-4` tolerance parameter to the `assertClose` calls on lines 682 and 683 in the `test_inverse` method of `TestTranslate` class.
This is a retry of D90225548
Reviewed By: sgrigory
Differential Revision: D90682979
fbshipit-source-id: ac13f000174dd9962326296e1c3116d0d39c7751
Summary:
## LLM-generated Summary:
Replaces self.assertTrue(torch.allclose(...)) with self.assertClose(...) throughout fbcode/vision/fair/pytorch3d/tests/test_transforms.py. This standardizes numeric closeness assertions for clearer failures and consistency while preserving tolerances and test behavior.
---
Session: DEV34970678
Reviewed By: shapovalov
Differential Revision: D90251428
fbshipit-source-id: cdae842be82f0ba548802e6977be272134e8508c
Summary:
CUDA 13.0 introduced breaking changes that cause build failures in pytorch3d:
**1. Symbol Visibility Changes (pulsar)**
- NVCC now forces `__global__` functions to have hidden ELF visibility by default
- `__global__` function template stubs now have internal linkage
**Fix:** Added NVCC flags (`--device-entity-has-hidden-visibility=false` and `-static-global-template-stub=false`) for fbcode builds with CUDA 13.0+.
**2. cuCtxCreate API Change (pycuda)**
- CUDA 13.0 changed `cuCtxCreate` from 3 to 4 arguments
- pycuda 2022.2 (current default) uses the old signature and fails to compile
- pycuda 2025.1.2 (D83501913) includes the CUDA 13.0 fix
**Fix:** Added CUDA 13.0 constraint to pycuda alias to auto-select pycuda 2025.1.2.
**NCCL Compatibility Note:**
- Current stable NCCL (2.25) is NOT compatible with CUDA 13.0 (`cudaTypedefs.h` removed)
- NCCL 2.27+ works with CUDA 13.0 and will become stable in early January 2026 (per HPC Comms team)
- Until then, CUDA 13.0 builds require `-c hpc_comms.use_nccl=2.27`
References:
- GitHub issue: https://github.com/facebookresearch/pytorch3d/issues/2011
- NVIDIA blog: https://developer.nvidia.com/blog/cuda-c-compiler-updates-impacting-elf-visibility-and-linkage/
- FBGEMM_GPU fix: D86474263
- pycuda 2025.1.2 buckification: D83501913
Reviewed By: bottler
Differential Revision: D88816596
fbshipit-source-id: 1ba666dab8c0e06d1286b8d5bc5d84cfc55c86e6
Summary: When using `sample_farthest_points` with `lengths`, it throws an error because of the device mismatch between `lengths` and `torch.rand(lengths.size())` on GPU.
Reviewed By: bottler
Differential Revision: D82378997
fbshipit-source-id: 8e929256177d543d1dd1249e8488f70e03e4101f