[video output=day594 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Switching from Center-Radius to Min-Max" vod_platform=youtube id=TzoW0CjmPl8 annotator=Miblo]
[0:03][Plug the Meow the Infinite printed comic Kickstarter[ref
    site=Kickstarter
    page="Meow the Infinite: Book One"
    url=https://www.kickstarter.com/projects/annarettberg/meow-the-infinite-book-one]][:research]
[0:25][Recap our creation of hhlightprof][:lighting :optimisation :speech]
[1:26][Demo hhlightprof (7.150223 total seconds elapsed)][:lighting :optimisation :run]
[2:31][Describe the two distinct ray casting / box categorisation routines in RayCast()][:lighting :optimisation :research]
[4:46][Describe the lighting_box structure, with the determination to reduce extraneous computations by storing the BoxMin and BoxMax][:"data structure" :lighting :optimisation :research]
[6:50][Replace P and Radius with BoxMin and BoxMax in lighting_box, and begin to propagate this change][:"data structure" :lighting :optimisation]
[7:28][Why compute the BoxMin and BoxMax part way down the :lighting pipeline?][:optimisation :speech]
[8:44][Continue to update the :lighting routines to use BoxMin and BoxMax][:optimisation]
[16:23][:Run hhlightprof to find that the light boxes and boxrefs don't match, because our storage format has changed][:lighting]
[17:02][Enable hhlightprof to transform the old Center-Radius dump to the new Min-Max format][:lighting]
[18:49][hhlightprof total seconds elapsed (with the same results as earlier): 6.702761][:lighting :optimisation :run]
[19:21][Make a note to remove the dump transform from hhlightprof][:lighting]
[19:47][Reflect on our data storage / computation improvement][:lighting :optimisation :research]
[20:34][Further RayCast() optimisations][:lighting :optimisation :research]
[22:17][Further RayCast() optimisations: 1) How do we want to store our tree?][:"data structure" :lighting :optimisation :research]
[22:40][Further RayCast() optimisations: 2) What does our tree want to look like (e.g. k-d tree)?][:"data structure" :lighting :optimisation :research]
[23:11][Further RayCast() optimisations: 3) Do we want the ray casting and the box categorisation in the same loop?][:lighting :optimisation :research]
[23:59][Determine to investigate the efficiency of our information streaming][:lighting :optimisation :research]
[24:54][Separate the ray casting and box categorisation loops in RayCast()][:lighting :optimisation]
[26:17][Augment lighting_work with a lighting_box_pack ScratchSpace array][:"data structure" :lighting :optimisation]
[27:26][Make InternalLightingCore() initialise our new ScratchSpace, and make ProfileRun() in hhlightprof allocate space for it][:lighting :memory :optimisation]
[30:56][:Memory per thread][:research :threading]
[32:59][Make a note to add :memory per thread][:threading]
[33:50][A few words on :memory per thread][:research :threading]
[34:55][:Run hhlightprof with the same results][:lighting :optimisation]
[35:07][Temporarily make RayCast() push lighting boxes onto the ScratchSpace][:lighting :memory :optimisation]
[36:00][:Run hhlightprof with the same results][:lighting :memory :optimisation]
[36:07][Revert RayCast() to push boxes onto the old stack array][:lighting :memory :optimisation]
[36:40][CTAssert() lighting_box_pack][:"data structure"]
[36:59][Make RayCast() do the box pushing and box categorisation in two passes][:lighting :optimisation]
[42:56][:Run hhlightprof with different results][:lighting :optimisation]
[43:14][Scour RayCast() for bugs][:lighting :optimisation :research]
[44:48][Use consistent :language in both loops for accessing lighting_box_pack][:lighting]
[45:05][Continue to scour RayCast() for bugs][:lighting :optimisation :research]
[45:55][Remove the compiled-out code in RayCast()][:lighting :optimisation]
[46:04][Continue to scour RayCast() for bugs][:lighting :optimisation :research]
[46:33][:Run hhlightprof still with different results from originally][:lighting :optimisation]
[47:01][Toggle RayCast() back to the old one-pass code][:lighting :optimisation]
[47:09][:Run hhlightprof with the same results as originally][:lighting :optimisation]
[47:12][Toggle RayCast() to the new two-pass code][:lighting :optimisation]
[47:16][Continue to hunt for inconsistencies between the one-pass and two-pass code in RayCast()][:lighting :optimisation :research]
[48:33][Fix the box pushing loop to only push a box if necessary][:lighting :optimisation]
[49:17][:Run hhlightprof with different results from originally][:lighting :optimisation]
[50:08][Continue to scour RayCast() for bugs][:lighting :optimisation :research]
[51:01][Assert in the box categorisation loop that the previously pushed box is a LeafContainer][:lighting :optimisation]
[51:23][:Run hhlightprof without hitting that assertion][:lighting :optimisation]
[51:29][Continue to scour RayCast() for bugs][:lighting :optimisation :research]
[54:22][@redunlocked][Q: The while(Depth) loop doesn't wrap the second loop][:lighting :optimisation]
[54:56][Continue to scour RayCast() for bugs][:lighting :optimisation :research]
[55:14][Make hhlightprof stream out to files the box leaves and partitions, introducing RECORD_LEAF_BOX() and RECORD_PARTITION_BOX()][:"file io" :lighting :optimisation]
[59:53][:Run hhlightprof][:lighting :optimisation]
[1:00:34][Make hhlightprof only stream out the first run of box leaves and partitions][:"file io" :lighting :optimisation]
[1:00:54][:Run hhlightprof][:lighting :optimisation]
[1:00:59][Rename our box leaves and partitions files to new*][:admin :lighting :optimisation]
[1:01:33][Toggle RayCast() back to the old one-pass code][:lighting :optimisation]
[1:01:44][:Run hhlightprof][:lighting :optimisation]
[1:01:48][Rename our box leaves and partitions files to old*][:admin :lighting :optimisation]
[1:02:02][Try to compare our partitions in Meld][:admin :lighting :optimisation]
[1:03:54][Install Beyond Compare[ref
    site="Scooter Software: Home of Beyond Compare"
    url=http://www.scootersoftware.com/]][:admin]
[1:04:59][Compare our box leaves in Beyond Compare, to see differences][:admin :lighting :optimisation]
[1:06:13][Compare our partitions in Beyond Compare, to see differences][:admin :lighting :optimisation]
[1:07:09][Toggle RayCast() to the new two-pass code][:lighting :optimisation]
[1:07:16][Scour RayCast() for a reason why we're pushing more boxes][:lighting :optimisation :research]
[1:08:17][Consult our box leaves differences in Beyond Compare][:admin :lighting :optimisation]
[1:10:16][Continue to scour RayCast() for a reason why we're pushing more boxes][:lighting :optimisation :research]
[1:10:36][Assert in RayCast() that the partitioning loop does not receive a non-leaf container][:lighting :optimisation]
[1:10:55][Toggle off the box / partition streaming in hhlightprof][:"file io" :lighting :optimisation]
[1:11:54][:Run hhlightprof without hitting that assertion][:lighting :optimisation]
[1:11:57][Puzzle over our bug in RayCast()][:lighting :optimisation :research]
[1:13:01][Make ProfileRun() print out the total input and output boxes][:lighting :optimisation]
[1:14:05][:Run hhlightprof to find a mismatch between the total boxes counts][:lighting :optimisation]
[1:14:28][Consult our box leaves differences in Beyond Compare][:admin :lighting :optimisation]
[1:15:26][Restrict our dumping to one ray's worth of work][:lighting :optimisation]
[1:18:00][:Run hhlightprof][:lighting :optimisation]
[1:18:15][Enable RECORD_RAYCAST_STACK][:lighting :optimisation]
[1:18:24][:Run hhlightprof][:lighting :optimisation]
[1:18:30][Rename our box leaves and partitions files to new*][:admin :lighting :optimisation]
[1:19:05][Toggle RayCast() back to the old one-pass code][:lighting :optimisation]
[1:19:15][:Run hhlightprof][:lighting :optimisation]
[1:19:16][Find our box leaves and partitions dumps to match][:admin :lighting :optimisation]
[1:19:31][Increase our dumping to sixteen rays' worth of work][:lighting :optimisation]
[1:20:13][:Run hhlightprof][:lighting :optimisation]
[1:20:19][Consult our box leaves and partitions files to see partition box indices lower than the input box count][:admin :lighting :optimisation]
[1:22:50][Reacquaint ourselves with SplitBox()][:lighting :optimisation :research]
[1:25:44][Disable RECORD_RAYCAST_STACK][:lighting :optimisation]
[1:25:55][hhlightprof total seconds elapsed: 6.682471][:lighting :optimisation :run]
[1:26:08][Prepare to remove the indirect table-read from SplitBox()][:lighting :optimisation]
[1:28:23][Change SplitBox() to split boxes directly into storage, removing AddBoxReferences() and AddBoxReference()][:lighting :memory :optimisation]
[1:36:38][Update BuildSpatialPartitionForLighting() to use AddBoxStorage() instead of AddBoxReference()][:lighting :memory :optimisation]
[1:37:36][:Run hhlightprof with a high max error / texel][:lighting :optimisation]
[1:38:00][Check all GetBox() calls, and SplitBox() for bugs][:lighting :optimisation :research]
[1:40:28][Fix AddBoxStorage() to correctly store the box index][:lighting :optimisation]
[1:40:45][hhlightprof total seconds elapsed: 6.460956][:lighting :optimisation :run]
[1:41:31][Make a note to remove the BoxRefTable from lighting_solution, removing all mentions of them][:"data structure" :lighting]
[1:42:45][hhlightprof total seconds elapsed: 6.449993][:lighting :optimisation :run]
[1:43:34][Enable RECORD_RAYCAST_STACK][:lighting :optimisation]
[1:43:53][:Run hhlightprof][:lighting :optimisation]
[1:44:02][Consult our box leaves and partitions files to see high partition box indices, as expected, and rename the files to new*][:admin :lighting :optimisation]
[1:44:17][Toggle RayCast() to the new two-pass code][:lighting :optimisation]
[1:44:26][:Run hhlightprof][:lighting :optimisation]
[1:44:31][Rename our box leaves and partitions files to new*, and diff them in Beyond Compare][:admin :lighting :optimisation]
[1:45:26][Make RayCast() record box partition pushes, introducing RECORD_PARTITION_PUSH()][:"file io" :lighting :optimisation]
[1:48:55][Toggle RayCast() back to the old one-pass code][:lighting :optimisation]
[1:49:11][:Run hhlightprof and rename the files to old*][:admin :lighting :optimisation]
[1:49:52][Fix RayCast() to call RECORD_PARTITION_PUSH() in the correct place][:"file io" :lighting :optimisation]
[1:50:08][:Run hhlightprof and see our pushes in the files][:admin :lighting :optimisation]
[1:50:31][Make RECORD_RAYCAST_END() append a newline after each ray][:"file io" :lighting :optimisation]
[1:50:52][:Run hhlightprof, see our rays and rename the files to old*][:admin :lighting :optimisation]
[1:51:18][Toggle RayCast() to the new two-pass code][:lighting :optimisation]
[1:51:34][:Run hhlightprof and rename the files to new*][:admin :lighting :optimisation]
[1:51:43][Diff our partitions files in Beyond Compare, to see different treatment of boxes 1638 and 1844][:admin :lighting :optimisation]
[1:54:17][Set up a breakpoint on box 1638 in RayCast(), and switch the build to -Od][:lighting :optimisation]
[1:55:54][Toggle RayCast() back to the old one-pass code, and comment out the __debugbreak()][:lighting :optimisation]
[1:56:07][:Run hhlightprof and compare these box leaves and partitions with the existing old ones][:admin :lighting :optimisation]
[1:56:26][Reinstate the __debugbreak() in RayCast()][:lighting :optimisation]
[1:56:36][:Run to our __debugbreak() and inspect the values][:lighting :optimisation]
[1:57:43][Determine to check that the leaf count is not larger than our available size][:lighting :optimisation :research]
[1:59:00][Make ProfileRun() save the GlobalMaxWorkStackDepth for RayCast() to assert the LeafCount against, toggling RayCast() back to the old one-pass code][:lighting :optimisation :research]
[2:00:19][Toggle RayCast() back to the old one-pass code][:lighting :optimisation]
[2:00:31][:Run hhlightprof and hit an assertion][:lighting :optimisation]
[2:01:40][Toggle off the __debugbreak() in RayCast()][:lighting :optimisation]
[2:02:07][:Run hhlightprof without hitting our LeafCount assertion][:lighting :optimisation]
[2:02:14][Step through RayCast() to see a consistently low LeafCount][:lighting :optimisation :run]
[2:02:50][Consider ProfileRun() to be allocating enough :memory][:lighting :optimisation :research]
[2:03:29][Remove our LeafCount assertion from RayCast(), and reinstate the __debugbreak() calls on box 1638][:lighting :optimisation]
[2:04:14][:Run to our __debugbreak() and inspect Box 1638][:lighting :optimisation]
[2:04:29][~RemedyBG feature request: Save Watch Window to File][:admin]
[2:04:49][Continue to inspect Box 1638, and save off its Min and Max][:lighting :optimisation :run]
[2:07:27][Realise that our two-loop RayCast() will necessarily test more boxes for partitioning because we pushed more leaves onto the stack][:lighting :optimisation :run]
[2:08:43][Remove the two-pass streaming from RayCast(), because we want to early-out][:lighting :optimisation]
[2:09:01][Plan to go forward with k-d tree, testing the near side before the far side, and early-out if we hit][:lighting :optimisation :research]
[2:09:52][Remove the __debugbreak() calls from RayCast()][:lighting :optimisation]
[2:10:11][Remove the ScratchBuffer from lighting_work][:"data structure" :lighting :optimisation]
[2:11:15][:Run hhlightprof successfully][:lighting :optimisation]
[2:11:24][:Run the game successfully][:lighting :optimisation]
[2:12:01][Q&A][:speech]
[2:12:38][@somebody_took_my_name][Q: Just wanted to let you know we have an IsMemoryEqual() function. Nice debug work today][:memory]
[2:13:48][@xxthebigfoxx][Q: Off-topic, but I noticed your last blog post is dated 2019]
[2:14:45][@x1bzzr][Q: Why is it that software companies increasingly seem to not care about :performance? I've heard you talk about the technical reasons, but I still don't understand why companies would give up on having better software quality than their competitors. Is it because education is bad? Is it because non-performance oriented software is being normalized to the point people don't care about it? Is it because hardware has been compensating for the lack of software performance?]
[2:17:20][@recursivechat][Q: Do you have a git repo for any of your code? Not necessarily [~hero Handmade Hero] code but something small that I could read to see what sort of "patterns" you use to write good code]
[2:19:04][@mattiamanzati][Q: About my question before the stream started, I am looking for a doubly linked list structure, and usually that's done through a structure with a first and last entry pointers, and those have a structure with a next, prev and value pointers. (Let's call this entry_structure.) In order to add an item to the end of the list you need to create a new entry_structure, set the prev pointer to the previous last entry, and UPDATE THE LAST entry_structure in order to have next point to the new last item. Is there any other structure that represents a doubly linked list without this prerequisite?][:"data structure"]
[2:21:02][@xsinxdx][Q: Are there any scalability / usability issues when using enums vs something like a hash table for indexing assets?]
[2:23:10][@buildervanished][Q: Do you know of some sane way of learning a bit of DirectX 11 other than trial and error while scavenging information on MSDN?]
[2:23:20][@mindmark42][Q: How would you recommend writing assembly directly for a function if the complier refuses to optimize it the way you want?][:asm]
[2:24:17][@chronic_quagga][Q: How important is it, in game development and in general, to be concerned with microarchitecture-level optimizations and using metrics from CPU performance counters?][:optimisation]
[2:24:51][@theintrojuicer][Q: How many lines of code are there in the [~hero Handmade Hero] project?]
[2:25:16][34,292 lines of code][:admin]
[2:25:47][@thordura][Q: If you do another programming discussion with [@naysayer88 Jon], do you think it would be valuable do a discussion about entity systems?][:"entity system"]
[2:26:14][@kniffel5][Q: Visual Studio 19 has support for x86 but not x64 assembly. Why's one in it, but the other isn't? Are they so different from each other?][:asm]
[2:27:16][@thordura][Q: I meant like what you guys consider is a good go-to approach to entities][:"entity system"]
[2:28:02][Wonder if we heard back from @mattiamanzati about the doubly linked list question][:"data structure" :research]
[2:29:21][Wander around the orphanage][:run]
[2:29:59][@sagian2005][Q: I think they wanted to know if there is something that acts like a doubly linked list that isn't actually a doubly linked list][:"data structure"]
[2:30:42][Wrap it up with a plug of the Meow the Infinite printed comic Kickstarter[ref
    site=Kickstarter
    page="Meow the Infinite: Book One"
    url=https://www.kickstarter.com/projects/annarettberg/meow-the-infinite-book-one] and the determination to raid [@naysayer88 Jon]'s stream[ref
    site=Twitch
    page=Naysayer88
    url=https://twitch.tv/naysayer88]][:speech]
[/video]
