diff --git a/cmuratori/hero/code/code475.hmml b/cmuratori/hero/code/code475.hmml new file mode 100644 index 0000000..9bb91a0 --- /dev/null +++ b/cmuratori/hero/code/code475.hmml @@ -0,0 +1,72 @@ +[video member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Abstracting the Renderer Interface" vod_platform=youtube id=EguT5zni4J4 annotator=Miblo] +[0:02][Recap and set the stage for the day][:speech] +[0:49][Walk through our test RenderLoop() with a view to streamlining the :camera and fog code, and cleaning up the drawing calls in PushSimpleScene()][:api :rendering :research] +[3:34][Our framerate problems incurred by the :lighting][:performance :rendering :research] +[6:12][Crank up the grass sprite count in PushSimpleScene()][:rendering] +[7:53][:Run the game and step in the RenderLoop() to see that we are using 184 bytes of our 64 megabyte-capacity PushBuffer][:memory :performance :rendering] +[9:15][Reduce the PushBuffer size to 1 megabyte][:memory :rendering] +[10:09][Consider simplifying the PushBuffer out of the renderer :API][:memory :rendering] +[16:26][Change open_gl to no longer be initialised as a global variable, but locally by Win32InitOpenGL()][:api] +[28:49][Introduce platform_renderer to generalise our renderer and decouple it from the OpenGL :API] +[35:04][Introduce GetWhiteBitmap(), and continue the :API decoupling, renaming DefaultRenderCommands() to BeginFrame() and OpenGLRenderCommands() to EndFrame()] +[41:38][Set up implement platform_renderer dispatching][:api :speech] +[42:49][Change LoadBMP() to call AddOp() and take a renderer_texture_queue and renderer_texture rather than call QueueTextureOp() and take a platform_renderer][:api] +[46:50][Introduce AllocateTextureQueue() and ProcessTextureQueue() for RenderLoop() to call][:api :memory] +[50:17][Implement AllocateTextureQueue(), setting it up to use the platform :memory allocation call][:api :"platform layer"] +[52:23][Remove AllocateTextureQueue() in favour of making RenderLoop() call InitTextureQueue(), allocating :memory in that call using Win32AllocateMemory()][:api :"platform layer"] +[55:19][Respecify InitTextureQueue() to take MemorySize, and itself compute the possible TextureOpCount to fit in that :memory][:api] +[58:09][Rename MaxVertexCount to MaxQuadCountPerFrame in RenderLoop(), leaving the possibility open for the platform to specially allocate the :memory][:api] +[1:00:15][Reorder RenderLoop() slightly][:api] +[1:01:11][Make Win32InitOpenGL() allocate our open_gl, adding PushBufferMemory and textured_vertex and renderer_texture arrays to this struct][:api :memory] +[1:08:09][Demo C++ inheritance to abstract the renderer][:api :language] +[1:11:38][Abstract out the renderer dispatch with an enum in platform_renderer, for newly introduced Win32AllocateRenderer(), ProcessTextureQueue(), BeginFrame() and EndFrame() to switch on][:api] +[1:27:33][Introduce OpenGLBeginFrame(), adding WindowWidth and WindowHeight to game_render_commands, and stubbing out the various API-specific functions][:api] +[1:38:54][:Run the Renderer Test and check out our :memory usage, to see that we have reserved 1.5 gigabytes][:performance] +[1:41:20][Step through RenderLoop() to determine that EndFrame() allocates this :memory][:performance :run] +[1:44:19][Step through OpenGLEndFrame() into OpenGLChangeToSetting() to see that the first CreateFramebuffer() call reserves 300 megabytes][:memory :performance :run] +[1:46:33][Step in to CreateFramebuffer() to see that the glFramebufferTexture2D() call reserves 200 megabytes, and investigate whether this is reasonable][:memory :performance :run] +[1:51:17][:Run the game and consider our high :memory usage][:performance] +[1:53:29][Temporarily disable multisampling in OpenGLInit()][:rendering] +[1:53:49][:Run the game to see that it now only reserves 312 megabytes][:memory :performance] +[1:54:09][Re-enable multisampling in OpenGLInit() and reduce the grass sprite count in PushSimpleScene()][:rendering] +[1:54:51][:Run the game, and compare the edge :rendering with and without multisampling] +[1:58:03][Disable pixelisation in OpenGLInit()][:rendering] +[1:58:32][:Run the game and consider that enabled pixelisation to be a bug][:rendering] +[1:58:53][Switch [~hero Handmade Hero] over to our abstracted renderer interface[ref + site=MSDN + page="wglGetCurrentDC function" + url=https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-wglgetcurrentdc]][:api :memory :rendering] +[2:12:51][:Run both the Renderer Test and game successfully][:api] +[2:13:28][Refresh our memories as to how the mouse position is handled][:"input handling" :research] +[2:15:24][Prevent DEBUGEnd() from calling ClipSpaceFromPixelSpace() to map the mouse coordinates][:"debug system" :"input handling"] +[2:16:01][:Run the game to find that the clicking doesn't work][:"debug system" :"input handling"] +[2:16:20][Introduce ClampBinormalMapToRange() for WinMainCRTStartup() to clamp the mouse coordinates to -1 to 1 space][:"debug system" :"input handling"] +[2:19:03][:Run the game to find that the mouse works again, but that the rotation and scaling controls are broken][:camera :"debug system" :"input handling"] +[2:19:31][Tweak the :camera rotation and zooming multipliers in UpdateAndRenderWorld()][:"input handling" :programming :run] +[2:21:22][Change the Mouse coordinates in game_input to be one v3 called ClipSpaceMouseP][:"input handling"] +[2:23:21][:Run the game to see that all is working, except for the positions of the :"debug system" menus] +[2:24:34][Reflect on our renderer :API][:research] +[2:25:47][Make OpenGLChangeToSettings() responsible for setting VSync using a newly introduced PlatformOpenGLSetVSync()][:api :rendering] +[2:29:58][:Run the game and the Renderer Test to gauge the VSync][:rendering] +[2:31:34][:Run the Renderer Test in -Od to see that we do request that VSync is disabled][:rendering] +[2:32:20][Q&A][:speech] +[2:32:47][Reflect again on our cleaner renderer :API][:research] +[2:33:45][@ivereadthesequel][Q: Don't know if you've answered this before, but why do you make all of your functions internal? Some in chat were saying that doesn't seem to make sense in a unity build, but I'm just wondering for your general case][:language] +[2:36:51][@vateferfout][Q: Not important, but I think that in your LoadBMP() function you're still declaring a renderer_texture result] +[2:37:29][@rationalcoder][Q: Is there something about your render passes that prohibits hybrid AA techniques, like MSAA 4X plus conservative FXAA? MSAA 16X is way overkill][:rendering] +[2:40:33][Reduce MaxMultiSampleCount in OpenGLInit()][:rendering] +[2:41:00][:Run the game to gauge our multisampling quality][:rendering] +[2:43:50][@uplinkcoder][Q: Could you take a look at 'Typo in win32_render_test.cpp'[ref + site=HandmadeHero/cpp/Issues + page="Typo in win32_render_test.cpp" + url=https://github.com/HandmadeHero/cpp/issues/76]] +[2:44:06][Fix typo in PushSimpleScene()][:"procedural generation"] +[2:45:16][@Rounin][Q: The plants look worse with 8-bit][:rendering] +[2:46:03][@centhusiast][Q: Have we used the malloc from CRT or have we always used Windows alloc? Is it okay to use the malloc in the game?][:memory] +[2:47:39][@ivereadthesequel][Q: On "internal": sorry, I was just wondering on a more fundamental level. I only knew it makes that function only accessible from that translation unit (I may have this wrong), and I wanted to know what it did for you in general, not just in response to the unity build part. Or is that really all it does?][:language] +[2:51:34][We're all good[ref + site="Handmade Hero" + url=https://handmadehero.org/][ref + site="Molly Rocket's Site Nexus" + url=https://mollyrocket.com/nexus]][:speech] +[/video]