Skip to content

Commit 860b742

Browse files
bottlerfacebook-github-bot
authored andcommitted
deterministic rasterization
Summary: Attempt to fix #659, an observation that the rasterizer is nondeterministic, by resolving tied faces by picking those with lower index. Reviewed By: nikhilaravi, patricklabatut Differential Revision: D30699039 fbshipit-source-id: 39ed797eb7e9ce7370ae71259ad6b757f9449923
1 parent cb170ac commit 860b742

File tree

3 files changed

+24
-9
lines changed

3 files changed

+24
-9
lines changed

pytorch3d/csrc/rasterize_meshes/rasterize_meshes.cu

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ struct Pixel {
2828
};
2929

3030
__device__ bool operator<(const Pixel& a, const Pixel& b) {
31-
return a.z < b.z;
31+
return a.z < b.z || (a.z == b.z && a.idx < b.idx);
3232
}
3333

3434
// Get the xyz coordinates of the three vertices for the face given by the

pytorch3d/csrc/rasterize_meshes/rasterize_meshes_cpu.cpp

+1-8
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,6 @@ struct IsNeighbor {
117117
int neighbor_idx;
118118
};
119119

120-
// Function to sort based on the z distance in the top K queue
121-
bool SortTopKByZdist(
122-
std::tuple<float, int, float, float, float, float> a,
123-
std::tuple<float, int, float, float, float, float> b) {
124-
return std::get<0>(a) < std::get<0>(b);
125-
}
126-
127120
std::tuple<torch::Tensor, torch::Tensor, torch::Tensor, torch::Tensor>
128121
RasterizeMeshesNaiveCpu(
129122
const torch::Tensor& face_verts,
@@ -310,7 +303,7 @@ RasterizeMeshesNaiveCpu(
310303

311304
// Sort the deque inplace based on the z distance
312305
// to mimic using a priority queue.
313-
std::sort(q.begin(), q.end(), SortTopKByZdist);
306+
std::sort(q.begin(), q.end());
314307
if (static_cast<int>(q.size()) > K) {
315308
// remove the last value
316309
q.pop_back();

tests/test_rasterize_meshes.py

+22
Original file line numberDiff line numberDiff line change
@@ -1151,6 +1151,28 @@ def _test_coarse_rasterize(self, device):
11511151
bin_faces_same = (bin_faces.squeeze() == bin_faces_expected).all()
11521152
self.assertTrue(bin_faces_same.item() == 1)
11531153

1154+
def test_order_of_ties(self):
1155+
# Tied faces are rasterized in index order
1156+
# We rasterize a mesh with many faces.
1157+
device = torch.device("cuda:0")
1158+
verts = -5 * torch.eye(3, dtype=torch.float32, device=device)[None]
1159+
faces = torch.arange(3, device=device, dtype=torch.int64).expand(1, 100, 3)
1160+
mesh = Meshes(verts=verts, faces=faces)
1161+
1162+
R, T = look_at_view_transform(2.7, 0.0, 0.0)
1163+
cameras = FoVPerspectiveCameras(device=device, R=R, T=T)
1164+
1165+
raster_settings = RasterizationSettings(
1166+
image_size=28, faces_per_pixel=100, bin_size=0
1167+
)
1168+
rasterizer = MeshRasterizer(raster_settings=raster_settings)
1169+
1170+
out = rasterizer(mesh, cameras=cameras)
1171+
self.assertClose(
1172+
out.pix_to_face[0, 14:, :14],
1173+
torch.arange(100, device=device).expand(14, 14, 100),
1174+
)
1175+
11541176
@staticmethod
11551177
def rasterize_meshes_python_with_init(
11561178
num_meshes: int,

0 commit comments

Comments
 (0)