Skip to content

Commit 4c9f0ce

Browse files
wolfpldocornut
authored andcommitted
Add and use SSE-enabled ImRsqrt() in place of 1.0f / ImSqrt(). (#4091)
Squashed 3 commits.
1 parent 84545db commit 4c9f0ce

File tree

3 files changed

+15
-2
lines changed

3 files changed

+15
-2
lines changed

docs/CHANGELOG.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ Other Changes:
6363
- Popups: Added 'OpenPopup(ImGuiID id)' overload to facilitate calling from nested stacks. (#3993, #331) [@zlash]
6464
- Optimization: Disabling some of MSVC most aggressive Debug runtime checks for some simple/low-level functions
6565
(e.g. ImVec2, ImVector) leading to a 10-20% increase of performances with MSVC "default" Debug settings.
66+
- ImDrawList: Add and use SSE-enabled ImRsqrt() in place of 1.0f / ImSqrt(). (#4091) [@wolfpld]
6667
- ImDrawList: Fixed/improved thickness of thick strokes with sharp angles. (#4053, #3366, #2964, #2868, #2518, #2183)
6768
Effectively introduced a regression in 1.67 (Jan 2019), and a fix in 1.70 (Apr 2019) but the fix wasn't actually on
6869
par with original version. Now incorporating the correct revert.

imgui_draw.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, c
694694

695695
// On AddPolyline() and AddConvexPolyFilled() we intentionally avoid using ImVec2 and superfluous function calls to optimize debug/non-inlined builds.
696696
// Those macros expects l-values.
697-
#define IM_NORMALIZE2F_OVER_ZERO(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = 1.0f / ImSqrt(d2); VX *= inv_len; VY *= inv_len; } } while (0)
697+
#define IM_NORMALIZE2F_OVER_ZERO(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = ImRsqrt(d2); VX *= inv_len; VY *= inv_len; } } while (0)
698698
#define IM_FIXNORMAL2F_MAX_INVLEN2 100.0f // 500.0f (see #4053, #3366)
699699
#define IM_FIXNORMAL2F(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.000001f) { float inv_len2 = 1.0f / d2; if (inv_len2 > IM_FIXNORMAL2F_MAX_INVLEN2) inv_len2 = IM_FIXNORMAL2F_MAX_INVLEN2; VX *= inv_len2; VY *= inv_len2; } } while (0)
700700

imgui_internal.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ Index of this file:
5151
#include <math.h> // sqrtf, fabsf, fmodf, powf, floorf, ceilf, cosf, sinf
5252
#include <limits.h> // INT_MIN, INT_MAX
5353

54+
// Enable SSE intrinsics if available
55+
#if defined __SSE__ || defined __x86_64__ || defined _M_X64
56+
#define IMGUI_ENABLE_SSE
57+
#include <immintrin.h>
58+
#endif
59+
5460
// Visual Studio warnings
5561
#ifdef _MSC_VER
5662
#pragma warning (push)
@@ -390,6 +396,12 @@ static inline float ImAbs(float x) { return fabsf(x); }
390396
static inline double ImAbs(double x) { return fabs(x); }
391397
static inline float ImSign(float x) { return (x < 0.0f) ? -1.0f : ((x > 0.0f) ? 1.0f : 0.0f); } // Sign operator - returns -1, 0 or 1 based on sign of argument
392398
static inline double ImSign(double x) { return (x < 0.0) ? -1.0 : ((x > 0.0) ? 1.0 : 0.0); }
399+
#ifdef IMGUI_ENABLE_SSE
400+
static inline float ImRsqrt(float x) { return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(x))); }
401+
#else
402+
static inline float ImRsqrt(float x) { return 1.0f / sqrtf(x); }
403+
#endif
404+
static inline double ImRsqrt(double x) { return 1.0 / sqrt(x); }
393405
#endif
394406
// - ImMin/ImMax/ImClamp/ImLerp/ImSwap are used by widgets which support variety of types: signed/unsigned int/long long float/double
395407
// (Exceptionally using templates here but we could also redefine them for those types)
@@ -410,7 +422,7 @@ static inline ImVec4 ImLerp(const ImVec4& a, const ImVec4& b, float t)
410422
static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; }
411423
static inline float ImLengthSqr(const ImVec2& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y); }
412424
static inline float ImLengthSqr(const ImVec4& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y) + (lhs.z * lhs.z) + (lhs.w * lhs.w); }
413-
static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = (lhs.x * lhs.x) + (lhs.y * lhs.y); if (d > 0.0f) return 1.0f / ImSqrt(d); return fail_value; }
425+
static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = (lhs.x * lhs.x) + (lhs.y * lhs.y); if (d > 0.0f) return ImRsqrt(d); return fail_value; }
414426
static inline float ImFloor(float f) { return (float)(int)(f); }
415427
static inline float ImFloorSigned(float f) { return (float)((f >= 0 || (int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf()
416428
static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); }

0 commit comments

Comments
 (0)