
Writing a Portable CPU/GPU Ray Tracer in C# - mellinoe
https://mellinoe.github.io/graphics/2018/05/19/writing-a-portable-cpu-gpu-ray-tracer-in-c.html
======
IvanK_net
I made a real-time ray-traced game a few years ago, that works in a browser :)
You can increase the resolution, while FPS drops.
[http://powerstones.ivank.net](http://powerstones.ivank.net)

------
Const-me
> You give it regular C# structures and methods, and it automatically converts
> them to HLSL, GLSL SPIR-V, and Metal shaders.

Code introspection is one of the huge strengths of .NET ecosystem.

You can even do it multiple levels of abstraction: bytecode (using e.g.
Mono.Cecil), with built-in reflection API, with built-in expressions API since
.NET 3.5, and apparently this project uses even higher-level approach, Roslyn.

I have never transformed C# code into shaders, when I’m working on something
similar I usually prefer traditional GPU languages like HLSL or CUDA, because
tooling (e.g. visual studio can debug both).

I transformed expressions into NoSQL database queries, worked well. Here’s the
main parts: [https://github.com/Const-
me/EsentSerialize/blob/master/Core/...](https://github.com/Const-
me/EsentSerialize/blob/master/Core/EsentSerialize81/Linq/FilterQuery.cs)

~~~
seanmcdirmid
You can also roll your own expression language using operator overloading and
then plug that into the DLR or HSL, or whatever as needed (I did this in
[https://archive.codeplex.com/?p=bling](https://archive.codeplex.com/?p=bling)).
It doesn’t allow for statements, however, which introspection gives you.

It is much harder in the new UWP, however, where dynamic features (reflection,
introspection, native JIT via the DLR) are no longer guaranteed to be present.

~~~
zamalek
Don't forget that Linq operates over duck-typed extension methods, so you can
also define your own wizardry there.

~~~
seanmcdirmid
Extension methods are important to doing an EDSL in C#. Link syntax is mostly
a dud, however.

~~~
megaman22
Hopefully the weird special-case LINQ syntax will die out soon. The only time
I've found it remotely more helpful than method-chaining is when doing some
nasty joins that I probably shouldn't have been doing in the first place.

------
dahart
Great write-up! Your speedups look like they line up as expected. Would you
happen to know why Aras's look a bit weird, is it the devices he's using? I'm
referring to his Metal timings being more than 10x slower than D3D, and being
almost comparable to C++.

> One of my goals was “use as much of the same code as possible on the CPU and
> GPU”.

Great idea, it's hard to debug GPU code, and super convenient to have
something that you can run & debug on the CPU, then just flip a switch and get
GPU speedups!

> Another obvious limitation is that GPU code cannot recurse.

Yep. I bet this changes relatively soon, since you can sometimes use recursion
in OpenCL & CUDA.

It's a fun exercise in ShaderToy to write a recursive ray tracer. Here's mine:
[https://www.shadertoy.com/view/XllBRf](https://www.shadertoy.com/view/XllBRf)

And here's a much better one:
[https://www.shadertoy.com/view/4scfz4](https://www.shadertoy.com/view/4scfz4)

~~~
aras_p
> I'm referring to his Metal timings being more than 10x slower than D3D

In my case it's the difference in hardware. DX11 results are on GTX 1080 Ti,
whereas Mac are on Iris Pro on 2013 MacBookPro. > 10x performance difference
between these GPUs is entirely expected.

~~~
dahart
Totally makes sense; thanks for the explanation!

------
wolfspider
Always love your work! Going to check this one out right away. Yeah GLES and
readpixel aren’t friends like for instance GPUImage uses the hardware
backbuffer to store it as a workaround:
[https://stackoverflow.com/questions/12813442/cvopenglestextu...](https://stackoverflow.com/questions/12813442/cvopenglestexturecache-
vs-gltexsubimage2d-on-ios)

So it’s device specific to implement the same thing I believe GPUImage uses a
stub for this to apply the same shaders you have in mind.

------
pjmlp
Very interesting reading, we need more article about alternative approaches.

------
ionafgnio
Is there a legitimate reason for D3D12 to exist? It seems like just a locked-
down version of Vulkan to me intended to kill cross-platform gaming (textbook
Microsoft Embrace, Extend, Extinguish). I haven't heard of any advantages in
performance or ease of development. But I'm certainly no expert.

Unrelated note: there's something really funky going with the comparison
between the desktop and the laptop. The desktop is pretty high-end and should
just obliterate that Macbook. It's seriously weird that they're so close. I'm
not sure I trust the results.

~~~
zamalek
> ease of development

Apart from the fact that DirectX 12 predates Vulkan by a substantial margin
(and includes APIs for more than graphics), this is a pretty major reason. The
API itself is only one concern and I can't tell whether it's easier or harder
to use OpenGL (assuming an expert at both) - it's just different. The tooling
surrounding it is a _completely_ different story.

Even during DirectX 9 there was a tool that would show you the state of all
your backbuffers after draw calls[1]. It was extremely spartan, but with such
a simple tool debugging shaders became enormously easier. I'm not sure if
anything exists for OpenGL today. They productized this and more in VS2017[2]
- including _being able to step through shaders in a debugger._ The big draw
to the Windows platform for developers has always been the tooling and
Microsoft knows this.

VS and DirectX aren't going away until people stop regarding them a "just a
text editor" and "just an API" respectively. It would help if people earnestly
competed with what Microsoft is doing, instead of dismissing their products
for no other reason than dogma.

> Microsoft Embrace, Extend, Extinguish

That ended with the exit of Balmer.

[1]: [https://tomtech999.wordpress.com/2011/09/07/debugging-
direct...](https://tomtech999.wordpress.com/2011/09/07/debugging-directx-
applications-with-pix-for-windows/)

[2]: [https://msdn.microsoft.com/en-
us/library/hh315751.aspx](https://msdn.microsoft.com/en-
us/library/hh315751.aspx)

~~~
Const-me
> I'm not sure if anything exists for OpenGL today.

A few years ago Crytek open sourced this:
[https://renderdoc.org/](https://renderdoc.org/)

I’ve mostly used the tool with DX11, but they also support OpenGL, GLES and
Vulkan.

