Skip to content

Commit

Permalink
Merge pull request #8 from EgorBo/minor-cs-fixes
Browse files Browse the repository at this point in the history
C# perf improvements: aggressive inlining, ref-returns.
On my Mac .NETCore: 17.5 -> 20.1 Mray/s
  • Loading branch information
aras-p committed Apr 15, 2018
2 parents 1763fcf + 43d241d commit f0452ca
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 22 deletions.
5 changes: 4 additions & 1 deletion Cs/Maths.cs
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;

public struct float3
{
Expand Down Expand Up @@ -67,6 +68,7 @@ static uint XorShift32(ref uint state)
return x;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float RandomFloat01(ref uint state)
{
return (XorShift32(ref state) & 0xFFFFFF) / 16777216.0f;
Expand Down Expand Up @@ -135,7 +137,8 @@ public struct Sphere
public Sphere(float3 center_, float radius_) { center = center_; radius = radius_; invRadius = 1.0f / radius_; }
public void UpdateDerivedData() { invRadius = 1.0f / radius; }

public bool HitSphere(Ray r, float tMin, float tMax, ref Hit outHit)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool HitSphere(ref Ray r, float tMin, float tMax, ref Hit outHit)
{
Debug.Assert(invRadius == 1.0f / radius);
Debug.Assert(r.dir.IsNormalized);
Expand Down
2 changes: 1 addition & 1 deletion Cs/Program.cs
Expand Up @@ -62,7 +62,7 @@ static void Main(string[] args)
static uint LinearToSRGB(float x)
{
x = Math.Max(x, 0.0f);
x = Math.Max(1.055f * (float)Math.Pow(x, 0.416666667f) - 0.055f, 0.0f);
x = Math.Max(1.055f * (float)MathF.Pow(x, 0.416666667f) - 0.055f, 0.0f);
uint u = Math.Min((uint)(x * 255.9f), 255u);
return u;
}
Expand Down
48 changes: 28 additions & 20 deletions Cs/Test.cs
Expand Up @@ -3,12 +3,13 @@
#define DO_LIGHT_SAMPLING
#define DO_THREADED

using System;
using System;
using System.Diagnostics;
using static float3;
using static MathUtil;
using System.Threading.Tasks;
using System.Threading;
using System.Runtime.CompilerServices;

struct Material
{
Expand All @@ -27,10 +28,10 @@ public Material(Type t, float3 a, float3 e, float r, float i)

class Test
{
const int DO_SAMPLES_PER_PIXEL = 4;
const int DO_SAMPLES_PER_PIXEL = 4;
const float DO_ANIMATE_SMOOTHING = 0.5f;




Sphere[] s_Spheres = {
new Sphere(new float3(0,-100.5f,-1), 100),
new Sphere(new float3(2,0,-1), 0.5f),
Expand Down Expand Up @@ -60,14 +61,14 @@ class Test
const int kMaxDepth = 10;


bool HitWorld(Ray r, float tMin, float tMax, ref Hit outHit, ref int outID)
bool HitWorld(ref Ray r, float tMin, float tMax, ref Hit outHit, ref int outID)
{
Hit tmpHit = default(Hit);
bool anything = false;
float closest = tMax;
for (int i = 0; i < s_Spheres.Length; ++i)
{
if (s_Spheres[i].HitSphere(r, tMin, closest, ref tmpHit))
if (s_Spheres[i].HitSphere(ref r, tMin, closest, ref tmpHit))
{
anything = true;
closest = tmpHit.t;
Expand All @@ -78,7 +79,7 @@ bool HitWorld(Ray r, float tMin, float tMax, ref Hit outHit, ref int outID)
return anything;
}

bool Scatter(Material mat, Ray r_in, Hit rec, out float3 attenuation, out Ray scattered, out float3 outLightE, ref int inoutRayCount, ref uint state)
bool Scatter(ref Material mat, ref Ray r_in, Hit rec, out float3 attenuation, out Ray scattered, out float3 outLightE, ref int inoutRayCount, ref uint state)
{
outLightE = new float3(0, 0, 0);
if (mat.type == Material.Type.Lambert)
Expand All @@ -92,7 +93,8 @@ bool Scatter(Material mat, Ray r_in, Hit rec, out float3 attenuation, out Ray sc
#if DO_LIGHT_SAMPLING
for (int i = 0; i < s_Spheres.Length; ++i)
{
if (!s_SphereMats[i].HasEmission)
ref Material sphereMat = ref s_SphereMats[i];
if (!sphereMat.HasEmission)
continue; // skip non-emissive
//@TODO if (&mat == &smat)
// continue; // skip self
Expand All @@ -116,14 +118,15 @@ bool Scatter(Material mat, Ray r_in, Hit rec, out float3 attenuation, out Ray sc
Hit lightHit = default(Hit);
int hitID = 0;
++inoutRayCount;
if (HitWorld(new Ray(rec.pos, l), kMinT, kMaxT, ref lightHit, ref hitID) && hitID == i)
var ray = new Ray(rec.pos, l);
if (HitWorld(ref ray, kMinT, kMaxT, ref lightHit, ref hitID) && hitID == i)
{
float omega = 2 * PI * (1 - cosAMax);

float3 rdir = r_in.dir;
Debug.Assert(rdir.IsNormalized);
float3 nl = Dot(rec.normal, rdir) < 0 ? rec.normal : -rec.normal;
outLightE += (mat.albedo * s_SphereMats[i].emissive) * (MathF.Max(0.0f, Dot(l, nl)) * omega / PI);
outLightE += (mat.albedo * sphereMat.emissive) * (MathF.Max(0.0f, Dot(l, nl)) * omega / PI);
}
}
#endif
Expand Down Expand Up @@ -183,25 +186,26 @@ bool Scatter(Material mat, Ray r_in, Hit rec, out float3 attenuation, out Ray sc
return true;
}

float3 Trace(Ray r, int depth, ref int inoutRayCount, ref uint state, bool doMaterialE = true)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
float3 Trace(ref Ray r, int depth, ref int inoutRayCount, ref uint state, bool doMaterialE = true)
{
Hit rec = default(Hit);
int id = 0;
++inoutRayCount;
if (HitWorld(r, kMinT, kMaxT, ref rec, ref id))
if (HitWorld(ref r, kMinT, kMaxT, ref rec, ref id))
{
Ray scattered;
float3 attenuation;
float3 lightE;
var mat = s_SphereMats[id];
ref Material mat = ref s_SphereMats[id];
var matE = mat.emissive;
if (depth < kMaxDepth && Scatter(mat, r, rec, out attenuation, out scattered, out lightE, ref inoutRayCount, ref state))
if (depth < kMaxDepth && Scatter(ref mat, ref r, rec, out attenuation, out scattered, out lightE, ref inoutRayCount, ref state))
{
#if DO_LIGHT_SAMPLING
if (!doMaterialE) matE = new float3(0, 0, 0);
doMaterialE = (mat.type != Material.Type.Lambert);
#endif
return matE + lightE + attenuation * Trace(scattered, depth + 1, ref inoutRayCount, ref state, doMaterialE);
return matE + lightE + attenuation * Trace(ref scattered, depth + 1, ref inoutRayCount, ref state, doMaterialE);
}
else
{
Expand Down Expand Up @@ -238,15 +242,19 @@ int TraceRowJob(int y, int screenWidth, int screenHeight, int frameCount, float[
float u = (x + RandomFloat01(ref state)) * invWidth;
float v = (y + RandomFloat01(ref state)) * invHeight;
Ray r = cam.GetRay(u, v, ref state);
col += Trace(r, 0, ref rayCount, ref state);
col += Trace(ref r, 0, ref rayCount, ref state);
}
col *= 1.0f / (float)DO_SAMPLES_PER_PIXEL;

float3 prev = new float3(backbuffer[backbufferIdx + 0], backbuffer[backbufferIdx + 1], backbuffer[backbufferIdx + 2]);
ref float bb1 = ref backbuffer[backbufferIdx + 0];
ref float bb2 = ref backbuffer[backbufferIdx + 1];
ref float bb3 = ref backbuffer[backbufferIdx + 2];

float3 prev = new float3(bb1, bb2, bb3);
col = prev * lerpFac + col * (1 - lerpFac);
backbuffer[backbufferIdx + 0] = col.x;
backbuffer[backbufferIdx + 1] = col.y;
backbuffer[backbufferIdx + 2] = col.z;
bb1 = col.x;
bb2 = col.y;
bb3 = col.z;
backbufferIdx += 4;
}
}
Expand Down

0 comments on commit f0452ca

Please sign in to comment.