[video output=day430 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Stratifying and Multithreading the Lighting" vod_platform=youtube id=_S6xFy1Le-g annotator=Miblo]
[0:02][Recap and set the stage for the day continuing with :lighting mods][:rendering :speech]
[0:18][:Lighting mods][:blackboard :rendering]
[1:04]["Stratified sampling" with a few words on random number generation and :"debug visualisation"][:blackboard :lighting :prng :rendering :statistics]
[4:50][:Run the game to see what we see, i.e. no :"debug visualisation" of our ray casting][:lighting :rendering]
[7:33][Introduce PushDebugLine() and a debug_line struct to draw the :lighting rays][:"debug visualisation" :rendering]
[17:10][:Run the game to see our wild rays][:"debug visualisation" :lighting :rendering]
[17:51][Reduce the line thickness in OutputLightingPoints(), and fix the location of their origin in LightingTest()][:lighting :"debug visualisation" :rendering]
[20:37][:Run the game to see our stably located rays][:lighting :"debug visualisation" :rendering]
[21:47][Reduce the near clip plane distance in UpdateAndRenderWorld() if in debug mode][:camera]
[22:13][:Run the game to see our :"debug visualisation"]
[22:44][Raise the ray's origin in LightingTest()][:lighting :"debug visualisation" :rendering]
[23:01][:Run the game and see our :lighting ray :"debug visualisation"][:rendering]
[23:13][Add a keybinding to pause the :lighting ray :"debug visualisation"][:rendering]
[26:24][:Run the game, and pause and inspect our :lighting ray :"debug visualisation"][:rendering]
[30:30][Stratified Hemisphere Sampling][:blackboard :lighting :rendering :statistics]
[35:46][Add XAxis and YAxis to lighting_point for SampleHemisphere() to take and distribute the samples into two halves][:lighting :rendering :statistics]
[41:03][:Run the game to see our distributed :lighting samples][:"debug visualisation" :rendering]
[44:03][Add a SampleTable to lighting_solution for LightingTest() to fill with customised locations][:lighting :rendering :statistics]
[52:47][:Run the game to see no flicker because the rays are not random][:"debug visualisation" :lighting :rendering]
[53:32][Flatten down the midrange rays in LightingTest()][:lighting :rendering :statistics]
[53:56][:Run the game to see our distributed rays][:"debug visualisation" :lighting :rendering :statistics]
[54:56][Add some randomness into SampleHemisphere()][:lighting :prng :rendering :statistics]
[56:29][:Run the game to see our perturbed rays, with flicker][:"debug visualisation" :lighting :rendering :statistics]
[57:20][Add a tweakable Ratio in SampleHemisphere()][:lighting :rendering :statistics]
[57:49][:Run the game and tweak the Ratio, watching the effect on the flicker][:"debug visualisation" :lighting :rendering :statistics]
[59:41][Increase the tUpdate in LightingTest(), to smooth the :lighting over a longer time][:rendering]
[1:00:10][:Run the game to inspect the :lighting, and consider using predictable sampling, smoothed over time][:rendering :statistics]
[1:02:07][Replace the random Series with EntropyCounter in lighting_solution, to predictably seed the random number generator per :lighting sample][:prng :rendering :statistics]
[1:05:16][:Run the game to see the effects of this][:"debug visualisation" :lighting :rendering]
[1:06:13][Make ComputeLightPropagation() correctly pin the EntropyCounter to the :lighting sample][:prng :rendering :statistics]
[1:07:04][:Run the game to see a repetitive pattern in the rays][:"debug visualisation" :lighting :prng :rendering :statistics]
[1:08:27][Make LightingTest() blend the :lighting slower than it takes samples][:prng :rendering :statistics]
[1:10:09][:Run the game to see that this doesn't help us much][:lighting :rendering]
[1:10:54][Enable OutputLightingTextures() to factor in the direction to light][:lighting :rendering]
[1:11:25][:Run the game to see how this affects the :lighting solution][:rendering]
[1:12:27][Prevent LightingTest() from blending the light over time][:lighting :rendering]
[1:13:08][:Run the game to see that this is incredibly noisy][:"debug visualisation" :lighting :rendering]
[1:15:10][Tweak the EntropyCount and tUpdate in LightingTest(), and increase the RayCount][:lighting :rendering]
[1:16:58][:Run the game to see our coverage][:"debug visualisation" :lighting :rendering]
[1:17:36][Increase the Ratio in SampleHemisphere() and set the RayCount to 16 in ComputeLightPropagation()][:lighting :rendering]
[1:18:01][:Run the game to see our more evenly distributed rays, and consider how to proceed][:"debug visualisation" :lighting :rendering]
[1:20:21][Introduce a DoLightingWork() callback to thread the ray casting][:lighting :optimisation :rendering :threading]
[1:28:47][:Run the game to see how this works][:lighting :optimisation :rendering :threading]
[1:29:22][Add a single-thread toggle to ComputeLightPropagation()][:lighting :rendering]
[1:30:17][:Run the game to see that the threaded path has slowed us][:lighting :optimisation :rendering :threading]
[1:30:29][Try making ComputeLightPropagation() loop over fewer samples][:lighting :optimisation :rendering]
[1:31:40][:Run the game to see that we are still slow][:lighting :optimisation :rendering]
[1:32:37][Try toggling SampleHemisphere() back to how it was][:lighting :rendering :statistics]
[1:33:18][:Run the game to determine that this has nothing to do with it][:lighting :rendering]
[1:34:00][Distribute the work across multiple threads again][:lighting :optimisation :rendering :threading]
[1:34:43][:Run the game to see that we do get a little bit faster, but not as much as expected][:lighting :optimisation :rendering :threading]
[1:37:31][Increase the RayCount to 64 and :run the game comparing it in the single- and multithreaded paths][:lighting :optimisation :programming :rendering :threading]
[1:39:21][Add a TIMED_FUNCTION() to LightingTest()][:"debug system" :lighting :rendering]
[1:39:58][:Run the game to see that the heavy load is entirely in ComputeLightPropagation()][:lighting :performance :rendering]
[1:40:40][Comment out all instances of values changing in the solution][:lighting :optimisation :rendering :threading]
[1:42:11][:Run the game to see that this speeds us up, and add back in some of those value changes, noting that we were thrashing the cache][:lighting :performance :rendering :threading]
[1:45:52][Make ComputeLightPropagation() set PointsPerWork to a multiple of 16, for cache-line alignment][:lighting :optimisation :rendering :threading]
[1:50:07][:Run the game to see that we are still speedy][:lighting :optimisation :rendering :threading]
[1:52:08][Q&A][:speech]
[1:52:32][@trevnewt][Q: Can we temporarily turn off / turn down the frame-to-frame color interpolation to see how much the increased sample count stabilizes the solution on its own?][:lighting :rendering]
[1:52:44][Temporarily disable smoothing and tweak the RayCount, sample randomisation and EntropyFrameCount][:lighting :prng :programming :rendering :run :statistics]
[1:56:39][@praet_a51][Q: Can someone explain why to store and pass around OnePastLastSamplePointIndex instead of calculating at the loop part?]
[1:59:29][@vaualbus][Q: Why we not using the atomics when we modify data on the multithread pass?][:optimisation :threading]
[2:00:05][@jamoflaw][Q: Given the restricted number of rays should they be biased towards directions which are "interesting" to us, i.e. not vertically? Just wondering as are we interested in the light values gained from the ceiling compared to that from surfaces which the player can visually see on screen][:lighting :rendering]
[2:01:03][@drzool][Q: Can the raycasts be optimized more?][:lighting :optimisation :rendering]
[2:01:40][@sdanna][Q: Would increasing the size of the SampleTable make sense if we are going to 64 rays?][:lighting :rendering]
[2:02:01][@enyo_enev][Q: Since you only use cubes, depending on the height of the light you may know exactly where to cast since there can be, say, only 4x4 square over you at a certain height? I think it could work even if the light is placed as a "wall" the generated table based on height would be flipped towards the normal?][:lighting :rendering]
[2:02:38][@aquaxv][Q: Less technical question: how are you today?]
[2:03:20][@enyo_enev][Q: Normal of the wall][:lighting :rendering]
[2:05:43][@jamoflaw][Q: Now the :threading is working well, how does it scale with more threads?][:optimisation]
[2:10:14][@staythirsty90][Q: What's the status of using LLVM?]
[2:10:37][@printf_armin][Q: How is the light source stored?][:lighting :memory :rendering]
[2:10:56][@neitchzehrer][Q: No more wrist supports?]
[2:10:59][@nxsy][Q: Use the new calculator!]
[2:12:19][@longboolean][Q: Are there any ways to make it clear in your profiler that you are having these cache issues (concerning threads, and shared :memory) or is this just something you have to look for with trial and error, experience etc?][:profiling :threading]
[2:14:30][@nxsy][Q: In menu, View -> History might help]
[2:15:05][Time to shut down, with a glimpse into the future optimising the :lighting and reducing its variance more intelligently][:optimisation :rendering :speech]
[/video]
