You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: _posts/2025-04-04-neural-gfx-in-an-afternoon.md
+7-7
Original file line number
Diff line number
Diff line change
@@ -47,7 +47,7 @@ Slang makes this entire process much easier, because it can automatically calcul
47
47
48
48
Let’s take a look at what it looks like to do this in the code. I’ll first go through a simplified version of the 2D Gaussian splatting example, so it’s very clear how the mechanism works. You can find this example in the SlangPy repository [here](https://github.com/shader-slang/slangpy/tree/main/examples/simplified-splatting). First, we’ll check out the Python side of things. With SlangPy, this code is pretty succinct.
49
49
50
-
```Python
50
+
```python
51
51
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
52
52
53
53
import slangpy as spy
@@ -146,7 +146,7 @@ for iter in range(iterations):
146
146
147
147
This is the entire Python file for setting up, initializing a set of 2D Gaussian blobs, and kicking off the derivative propagation that calculates the ideal values for all those blob parameters. The setup should be fairly straightforward and explained by the comments, so let’s take a closer look at the “meat” of this file, iterating through our gradient descent.
148
148
149
-
```Python
149
+
```python
150
150
iterations =10000
151
151
foriterinrange(iterations):
152
152
# Back-propagage the unit per-pixel loss with auto-diff.
@@ -164,14 +164,14 @@ What the `module.perPixelLoss.bwds()` call is doing is going into the Slang modu
164
164
165
165
When this call finishes, per_pixel_loss will contain values representing the results of the loss function for each pixel based on the “calculated image” that results from all of our current blob parameters, and blobs will have a gradient associated with each blob, indicating which direction the parameters should move in order to get closer to the target. The input image will be unchanged.
This line calls into a Slang function in our module which provides an [optimized algorithm](https://optimization.cbe.cornell.edu/index.php?title=Adam) for updating our blobs based on the information stored in the blob gradients. It calculates moving averages of these gradients, so that we can update our blob parameters efficiently. You can read more about how Adam works in [the paper](https://arxiv.org/pdf/1412.6980) that introduced it, and you’ll see the implementation in our Slang module in a moment. Don’t worry– it’s less than thirty lines of Slang code!
173
173
174
-
```Python
174
+
```python
175
175
# Every 50 iterations, render the blobs out to a texture, and hand it off to tev
176
176
# so that you can visualize the iteration towards ideal
177
177
ifiter%50==0:
@@ -188,7 +188,7 @@ Ok! Now, for the Slang side of things.
188
188
189
189
There’s a bit more to the Slang code, but let’s first take a look at the functions that we called out to from SlangPy just a moment ago. The workhorse of the module is that `perPixelLoss()` function and its helpers:
190
190
191
-
```Slang
191
+
```hlsl
192
192
// simpleSplatBlobs() is a naive implementation of the computation of color for a pixel.
193
193
// It will iterate over all of the Gaussians for each pixel, to determine their contributions
194
194
// to the pixel color, so this will become prohibitively slow with a very small number of
@@ -272,7 +272,7 @@ You might wonder if iterating over our entire list of Gaussians for each pixel i
272
272
273
273
This set of functions is responsible for calculating all of the output pixels, as well as the difference between those values and our ideal target image, so they’re invoked not just for propagating loss derivatives (the `module.perPixelLoss.bwds` call we made in Python), but also during the rendering of our output texture, via `renderBlobsToTexture`, which looks like this:
274
274
275
-
```Slang
275
+
```hlsl
276
276
void renderBlobsToTexture(
277
277
RWTexture2D<float4> output,
278
278
GradInOutTensor<float, 1> blobsBuffer,
@@ -288,7 +288,7 @@ As you can see, this function just takes the result of `simpleSplatBlobs`, and w
288
288
289
289
The other piece of the equation is the Adam update algorithm:
0 commit comments