Skip to content

Commit

Permalink
simd: have a "structure of arrays" layout for all spheres data, chang…
Browse files Browse the repository at this point in the history
…e HitSphere -> HitSpheres

- PC 171 -> 184 Mray/s
- Mac 42.6 -> 48.1 Mray/s
  • Loading branch information
aras-p committed Apr 10, 2018
1 parent bcfca46 commit b4ef99d
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 41 deletions.
62 changes: 37 additions & 25 deletions Cpp/Source/Maths.cpp
Expand Up @@ -47,34 +47,46 @@ float3 RandomUnitVector(uint32_t& state)
}


bool HitSphere(const Ray& r, const Sphere& s, float tMin, float tMax, Hit& outHit)
int HitSpheres(const Ray& r, const SpheresSoA& spheres, float tMin, float tMax, Hit& outHit)
{
assert(s.invRadius == 1.0f/s.radius);
AssertUnit(r.dir);
float3 oc = r.orig - s.center;
float b = dot(oc, r.dir);
float c = dot(oc, oc) - s.radius*s.radius;
float discr = b*b - c;
if (discr > 0)
Hit tmpHit;
int id = -1;
float closest = tMax;
for (int i = 0; i < spheres.count; ++i)
{
float discrSq = sqrtf(discr);

float t = (-b - discrSq);
if (t < tMax && t > tMin)
float ocX = r.orig.getX() - spheres.centerX[i];
float ocY = r.orig.getY() - spheres.centerY[i];
float ocZ = r.orig.getZ() - spheres.centerZ[i];
float b = ocX * r.dir.getX() + ocY * r.dir.getY() + ocZ * r.dir.getZ();
float c = ocX * ocX + ocY * ocY + ocZ * ocZ - spheres.radius[i] * spheres.radius[i];
float discr = b * b - c;
if (discr > 0)
{
outHit.pos = r.pointAt(t);
outHit.normal = (outHit.pos - s.center) * s.invRadius;
outHit.t = t;
return true;
}
t = (-b + discrSq);
if (t < tMax && t > tMin)
{
outHit.pos = r.pointAt(t);
outHit.normal = (outHit.pos - s.center) * s.invRadius;
outHit.t = t;
return true;
float discrSq = sqrtf(discr);

float t = (-b - discrSq);
if (t > tMin && t < tMax && t < closest)
{
id = i;
closest = t;
tmpHit.pos = r.pointAt(t);
tmpHit.normal = (tmpHit.pos - float3(spheres.centerX[i], spheres.centerY[i], spheres.centerZ[i])) * spheres.invRadius[i];
tmpHit.t = t;
}
else
{
t = (-b + discrSq);
if (t > tMin && t < tMax && t < closest)
{
id = i;
closest = t;
tmpHit.pos = r.pointAt(t);
tmpHit.normal = (tmpHit.pos - float3(spheres.centerX[i], spheres.centerY[i], spheres.centerZ[i])) * spheres.invRadius[i];
tmpHit.t = t;
}
}
}
}
return false;
outHit = tmpHit;
return id;
}
32 changes: 31 additions & 1 deletion Cpp/Source/Maths.h
Expand Up @@ -222,7 +222,37 @@ struct Sphere
};


bool HitSphere(const Ray& r, const Sphere& s, float tMin, float tMax, Hit& outHit);
// data for all spheres in a "structure of arrays" layout
struct SpheresSoA
{
SpheresSoA(int c)
: count(c)
{
centerX = new float[c];
centerY = new float[c];
centerZ = new float[c];
radius = new float[c];
invRadius = new float[c];
}
~SpheresSoA()
{
delete[] centerX;
delete[] centerY;
delete[] centerZ;
delete[] radius;
delete[] invRadius;
}

float* centerX;
float* centerY;
float* centerZ;
float* radius;
float* invRadius;
int count;
};


int HitSpheres(const Ray& r, const SpheresSoA& spheres, float tMin, float tMax, Hit& outHit);

float RandomFloat01(uint32_t& state);
float3 RandomInUnitDisk(uint32_t& state);
Expand Down
28 changes: 13 additions & 15 deletions Cpp/Source/Test.cpp
Expand Up @@ -19,6 +19,8 @@ static Sphere s_Spheres[] =
};
const int kSphereCount = sizeof(s_Spheres) / sizeof(s_Spheres[0]);

static SpheresSoA s_SpheresSoA(kSphereCount);

struct Material
{
enum Type { Lambert, Metal, Dielectric };
Expand Down Expand Up @@ -51,20 +53,8 @@ const int kMaxDepth = 10;

bool HitWorld(const Ray& r, float tMin, float tMax, Hit& outHit, int& outID)
{
Hit tmpHit;
bool anything = false;
float closest = tMax;
for (int i = 0; i < kSphereCount; ++i)
{
if (HitSphere(r, s_Spheres[i], tMin, closest, tmpHit))
{
anything = true;
closest = tmpHit.t;
outHit = tmpHit;
outID = i;
}
}
return anything;
outID = HitSpheres(r, s_SpheresSoA, tMin, tMax, outHit);
return outID != -1;
}


Expand Down Expand Up @@ -295,7 +285,15 @@ void UpdateTest(float time, int frameCount, int screenWidth, int screenHeight)
#endif

for (int i = 0; i < kSphereCount; ++i)
s_Spheres[i].UpdateDerivedData();
{
Sphere& s = s_Spheres[i];
s.UpdateDerivedData();
s_SpheresSoA.centerX[i] = s.center.getX();
s_SpheresSoA.centerY[i] = s.center.getY();
s_SpheresSoA.centerZ[i] = s.center.getZ();
s_SpheresSoA.radius[i] = s.radius;
s_SpheresSoA.invRadius[i] = s.invRadius;
}

s_Cam = Camera(lookfrom, lookat, float3(0, 1, 0), 60, float(screenWidth) / float(screenHeight), aperture, distToFocus);
}
Expand Down

0 comments on commit b4ef99d

Please sign in to comment.