Skip to content

Commit

Permalink
walk back branchless changes -- processing time is roughly equivalent…
Browse files Browse the repository at this point in the history
… between branched and branchless, and branched is more readable
  • Loading branch information
nyoungbq committed Aug 8, 2024
1 parent 5873abc commit 5cd1e18
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 106 deletions.
136 changes: 72 additions & 64 deletions src/simplnx/Utilities/Math/GeometryMath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,47 +69,54 @@ BoundingBox3Df nx::core::GeometryMath::FindBoundingBoxOfFace(const detail::Geome
Point3Df ll = points[0];
Point3Df ur = points[0];

// Avoid Branch Prediction misses by exclusively doing multiplication operations
// C++ (§4.5/4):
// An r-value of type bool can be converted to an r-value of type int,
// with false becoming zero and true becoming one.
//
// The standard guarantees the same for float
bool swap = points[1][0] < ll[0];
ll[0] = points[1][0] * static_cast<float32>(swap) + ll[0] * static_cast<float32>(!swap);

swap = points[1][1] < ll[1];
ll[1] = points[1][1] * static_cast<float32>(swap) + ll[1] * static_cast<float32>(!swap);

swap = points[1][2] < ll[2];
ll[2] = points[1][2] * static_cast<float32>(swap) + ll[2] * static_cast<float32>(!swap);

swap = points[2][0] < ll[0];
ll[0] = points[2][0] * static_cast<float32>(swap) + ll[0] * static_cast<float32>(!swap);

swap = points[2][1] < ll[1];
ll[1] = points[2][1] * static_cast<float32>(swap) + ll[1] * static_cast<float32>(!swap);

swap = points[2][2] < ll[2];
ll[2] = points[2][2] * static_cast<float32>(swap) + ll[2] * static_cast<float32>(!swap);

swap = points[1][0] > ur[0];
ur[0] = points[1][0] * static_cast<float32>(swap) + ur[0] * static_cast<float32>(!swap);

swap = points[1][1] > ur[1];
ur[1] = points[1][1] * static_cast<float32>(swap) + ur[1] * static_cast<float32>(!swap);

swap = points[1][2] > ur[2];
ur[2] = points[1][2] * static_cast<float32>(swap) + ur[2] * static_cast<float32>(!swap);

swap = points[2][0] > ur[0];
ur[0] = points[2][0] * static_cast<float32>(swap) + ur[0] * static_cast<float32>(!swap);

swap = points[2][1] > ur[1];
ur[1] = points[2][1] * static_cast<float32>(swap) + ur[1] * static_cast<float32>(!swap);

swap = points[2][2] > ur[2];
ur[2] = points[2][2] * static_cast<float32>(swap) + ur[2] * static_cast<float32>(!swap);
if(points[1][0] < ll[0])
{
ll[0] = points[1][0];
}
if(points[1][0] > ur[0])
{
ur[0] = points[1][0];
}
if(points[1][1] < ll[1])
{
ll[1] = points[1][1];
}
if(points[1][1] > ur[1])
{
ur[1] = points[1][1];
}
if(points[1][2] < ll[2])
{
ll[2] = points[1][2];
}
if(points[1][2] > ur[2])
{
ur[2] = points[1][2];
}
if(points[2][0] < ll[0])
{
ll[0] = points[2][0];
}
if(points[2][0] > ur[0])
{
ur[0] = points[2][0];
}
if(points[2][1] < ll[1])
{
ll[1] = points[2][1];
}
if(points[2][1] > ur[1])
{
ur[1] = points[2][1];
}
if(points[2][2] < ll[2])
{
ll[2] = points[2][2];
}
if(points[2][2] > ur[2])
{
ur[2] = points[2][2];
}

return {ll, ur};
}
Expand All @@ -135,29 +142,30 @@ BoundingBox3Df nx::core::GeometryMath::FindBoundingBoxOfFaces(const nx::core::Tr
Point3Df min = bounds.getMinPoint();
Point3Df max = bounds.getMaxPoint();

// Avoid Branch Prediction misses by exclusively doing multiplication operations
// C++ (§4.5/4):
// An r-value of type bool can be converted to an r-value of type int,
// with false becoming zero and true becoming one.
//
// The standard guarantees the same for float
bool swap = min[0] < ll[0];
ll[0] = min[0] * static_cast<float32>(swap) + ll[0] * static_cast<float32>(!swap);

swap = min[1] < ll[1];
ll[1] = min[1] * static_cast<float32>(swap) + ll[1] * static_cast<float32>(!swap);

swap = min[2] < ll[2];
ll[2] = min[2] * static_cast<float32>(swap) + ll[2] * static_cast<float32>(!swap);

swap = max[0] > ur[0];
ur[0] = max[0] * static_cast<float32>(swap) + ur[0] * static_cast<float32>(!swap);

swap = max[1] > ur[1];
ur[1] = max[1] * static_cast<float32>(swap) + ur[1] * static_cast<float32>(!swap);

swap = max[2] > ur[2];
ur[2] = max[2] * static_cast<float32>(swap) + ur[2] * static_cast<float32>(!swap);
if(min[0] < ll[0])
{
ll[0] = min[0];
}
if(min[1] < ll[1])
{
ll[1] = min[1];
}
if(min[2] < ll[2])
{
ll[2] = min[2];
}
if(max[0] > ur[0])
{
ur[0] = max[0];
}
if(max[1] > ur[1])
{
ur[1] = max[1];
}
if(max[2] > ur[2])
{
ur[2] = max[2];
}
}

return {ll, ur};
Expand Down
102 changes: 60 additions & 42 deletions src/simplnx/Utilities/Math/GeometryMath.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,21 +324,27 @@ char IsPointInTriangle(const nx::core::Point3D<T>& p0, const nx::core::Point3D<T
bool hasNeg = area0 < 0 || area1 < 0 || area2 < 0;
int32 zeroCount = !area0 + !area1 + !area2;

char code = '?';

bool secondaryCond = !zeroCount;
code = secondaryCond * 'F' + !secondaryCond * code;

secondaryCond = zeroCount == 1;
code = secondaryCond * 'E' + !secondaryCond * code;

secondaryCond = zeroCount == 2;
code = secondaryCond * 'V' + !secondaryCond * code;

bool primaryCond = !(hasPos && hasNeg);
code = !primaryCond * '0' + primaryCond * code;
if(!(hasPos && hasNeg))
{
if(zeroCount == 0)
{
return 'F';
}
else if(zeroCount == 1)
{
return 'E';
}
else if(zeroCount == 2)
{
return 'V';
}
else if(zeroCount == 3)
{
return '?';
}
}

return code;
return '0';
}

/**
Expand Down Expand Up @@ -438,21 +444,27 @@ char RayCrossesTriangle(const Ray<T>& ray, const Point3D<T>& p0, const Point3D<T
bool hasNeg = vol0 < 0 || vol1 < 0 || vol2 < 0;
int32 zeroCount = !vol0 + !vol1 + !vol2;

char code = '?';

bool secondaryCond = !zeroCount;
code = secondaryCond * 'f' + !secondaryCond * code;

secondaryCond = zeroCount == 1;
code = secondaryCond * 'e' + !secondaryCond * code;

secondaryCond = zeroCount == 2;
code = secondaryCond * 'v' + !secondaryCond * code;

bool primaryCond = !(hasPos && hasNeg);
code = !primaryCond * '0' + primaryCond * code;
if(!(hasPos && hasNeg))
{
if(zeroCount == 0)
{
return 'f';
}
else if(zeroCount == 1)
{
return 'e';
}
else if(zeroCount == 2)
{
return 'v';
}
else if(zeroCount == 3)
{
return '?';
}
}

return code;
return '0';
}

/**
Expand All @@ -478,21 +490,27 @@ char RayCrossesTriangle(const CachedRay<T>& ray, const Point3D<T>& p0, const Poi
bool hasNeg = vol0 < 0 || vol1 < 0 || vol2 < 0;
int32 zeroCount = !vol0 + !vol1 + !vol2;

char code = '?';

bool secondaryCond = !zeroCount;
code = secondaryCond * 'f' + !secondaryCond * code;

secondaryCond = zeroCount == 1;
code = secondaryCond * 'e' + !secondaryCond * code;

secondaryCond = zeroCount == 2;
code = secondaryCond * 'v' + !secondaryCond * code;

bool primaryCond = !(hasPos && hasNeg);
code = !primaryCond * '0' + primaryCond * code;
if(!(hasPos && hasNeg))
{
if(zeroCount == 0)
{
return 'f';
}
else if(zeroCount == 1)
{
return 'e';
}
else if(zeroCount == 2)
{
return 'v';
}
else if(zeroCount == 3)
{
return '?';
}
}

return code;
return '0';
}

/**
Expand Down

0 comments on commit 5cd1e18

Please sign in to comment.