mirror of
https://github.com/facebookresearch/pytorch3d.git
synced 2025-08-02 20:02:49 +08:00
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
This commit is contained in:
parent
cb170ac024
commit
860b742a02
@ -28,7 +28,7 @@ struct Pixel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
__device__ bool operator<(const Pixel& a, const Pixel& b) {
|
__device__ bool operator<(const Pixel& a, const Pixel& b) {
|
||||||
return a.z < b.z;
|
return a.z < b.z || (a.z == b.z && a.idx < b.idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the xyz coordinates of the three vertices for the face given by the
|
// Get the xyz coordinates of the three vertices for the face given by the
|
||||||
|
@ -117,13 +117,6 @@ struct IsNeighbor {
|
|||||||
int neighbor_idx;
|
int neighbor_idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function to sort based on the z distance in the top K queue
|
|
||||||
bool SortTopKByZdist(
|
|
||||||
std::tuple<float, int, float, float, float, float> a,
|
|
||||||
std::tuple<float, int, float, float, float, float> b) {
|
|
||||||
return std::get<0>(a) < std::get<0>(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::tuple<torch::Tensor, torch::Tensor, torch::Tensor, torch::Tensor>
|
std::tuple<torch::Tensor, torch::Tensor, torch::Tensor, torch::Tensor>
|
||||||
RasterizeMeshesNaiveCpu(
|
RasterizeMeshesNaiveCpu(
|
||||||
const torch::Tensor& face_verts,
|
const torch::Tensor& face_verts,
|
||||||
@ -310,7 +303,7 @@ RasterizeMeshesNaiveCpu(
|
|||||||
|
|
||||||
// Sort the deque inplace based on the z distance
|
// Sort the deque inplace based on the z distance
|
||||||
// to mimic using a priority queue.
|
// to mimic using a priority queue.
|
||||||
std::sort(q.begin(), q.end(), SortTopKByZdist);
|
std::sort(q.begin(), q.end());
|
||||||
if (static_cast<int>(q.size()) > K) {
|
if (static_cast<int>(q.size()) > K) {
|
||||||
// remove the last value
|
// remove the last value
|
||||||
q.pop_back();
|
q.pop_back();
|
||||||
|
@ -1151,6 +1151,28 @@ class TestRasterizeMeshes(TestCaseMixin, unittest.TestCase):
|
|||||||
bin_faces_same = (bin_faces.squeeze() == bin_faces_expected).all()
|
bin_faces_same = (bin_faces.squeeze() == bin_faces_expected).all()
|
||||||
self.assertTrue(bin_faces_same.item() == 1)
|
self.assertTrue(bin_faces_same.item() == 1)
|
||||||
|
|
||||||
|
def test_order_of_ties(self):
|
||||||
|
# Tied faces are rasterized in index order
|
||||||
|
# We rasterize a mesh with many faces.
|
||||||
|
device = torch.device("cuda:0")
|
||||||
|
verts = -5 * torch.eye(3, dtype=torch.float32, device=device)[None]
|
||||||
|
faces = torch.arange(3, device=device, dtype=torch.int64).expand(1, 100, 3)
|
||||||
|
mesh = Meshes(verts=verts, faces=faces)
|
||||||
|
|
||||||
|
R, T = look_at_view_transform(2.7, 0.0, 0.0)
|
||||||
|
cameras = FoVPerspectiveCameras(device=device, R=R, T=T)
|
||||||
|
|
||||||
|
raster_settings = RasterizationSettings(
|
||||||
|
image_size=28, faces_per_pixel=100, bin_size=0
|
||||||
|
)
|
||||||
|
rasterizer = MeshRasterizer(raster_settings=raster_settings)
|
||||||
|
|
||||||
|
out = rasterizer(mesh, cameras=cameras)
|
||||||
|
self.assertClose(
|
||||||
|
out.pix_to_face[0, 14:, :14],
|
||||||
|
torch.arange(100, device=device).expand(14, 14, 100),
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def rasterize_meshes_python_with_init(
|
def rasterize_meshes_python_with_init(
|
||||||
num_meshes: int,
|
num_meshes: int,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user