From 1b541bdd3707140da40e59d430ca80f13b897dc4 Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Mon, 20 Nov 2023 14:07:34 -0700 Subject: [PATCH] Avoid floating point exceptions in rendering code There were some places in the rendering code where floating point exceptions (FPE) could happen under certain circumstances. Often we do not care about invalid floating point operation in rendering as they often occur in degenerate cases that don't contribute anyway. However, simulations that might include VTK-m might turn on FPE to check their own operations. In such cases, we don't want errant rendering arithmetic causing an exception and bringing down the whole code. Thus, we turn on FPE in some of our test platforms and avoid such operations in general. --- docs/changelog/avoid-rendering-fpe.md | 10 ++++++++++ vtkm/rendering/Wireframer.h | 4 +++- vtkm/rendering/raytracing/GlyphIntersector.cxx | 6 +++++- 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 docs/changelog/avoid-rendering-fpe.md diff --git a/docs/changelog/avoid-rendering-fpe.md b/docs/changelog/avoid-rendering-fpe.md new file mode 100644 index 000000000..1cfa5e7d2 --- /dev/null +++ b/docs/changelog/avoid-rendering-fpe.md @@ -0,0 +1,10 @@ +# Avoid floating point exceptions in rendering code + +There were some places in the rendering code where floating point +exceptions (FPE) could happen under certain circumstances. Often we do not +care about invalid floating point operation in rendering as they often +occur in degenerate cases that don't contribute anyway. However, +simulations that might include VTK-m might turn on FPE to check their own +operations. In such cases, we don't want errant rendering arithmetic +causing an exception and bringing down the whole code. Thus, we turn on FPE +in some of our test platforms and avoid such operations in general. diff --git a/vtkm/rendering/Wireframer.h b/vtkm/rendering/Wireframer.h index 44a633a36..0e7879653 100644 --- a/vtkm/rendering/Wireframer.h +++ b/vtkm/rendering/Wireframer.h @@ -234,7 +234,9 @@ public: vtkm::Float32 dx = x2 - x1; vtkm::Float32 dy = y2 - y1; - vtkm::Float32 gradient = (dx == 0.0) ? 1.0f : (dy / dx); + if (dx == 0.0) + dx = vtkm::Epsilon32(); // Avoid FPE + vtkm::Float32 gradient = dy / dx; vtkm::Float32 xEnd = vtkm::Round(x1); vtkm::Float32 yEnd = y1 + gradient * (xEnd - x1); diff --git a/vtkm/rendering/raytracing/GlyphIntersector.cxx b/vtkm/rendering/raytracing/GlyphIntersector.cxx index b097d82ec..67ad2b90b 100644 --- a/vtkm/rendering/raytracing/GlyphIntersector.cxx +++ b/vtkm/rendering/raytracing/GlyphIntersector.cxx @@ -418,7 +418,11 @@ public: normal[0] = (vtkm::Abs(vtkm::Abs(lp[0]) - 1.0f) <= eps) ? lp[0] : 0.0f; normal[1] = (vtkm::Abs(vtkm::Abs(lp[1]) - 1.0f) <= eps) ? lp[1] : 0.0f; normal[2] = (vtkm::Abs(vtkm::Abs(lp[2]) - 1.0f) <= eps) ? lp[2] : 0.0f; - vtkm::Normalize(normal); + Precision magSquared = vtkm::MagnitudeSquared(normal); + if (magSquared > eps) + { + normal = vtkm::RSqrt(magSquared) * normal; + } // Flip normal if it is pointing the wrong way if (vtkm::Dot(normal, rayDir) > 0.0f)