Devlog 2024-11-18

This is a regularly-occurring status update. More generally-relevant posts can be found under Features (see Creating a Game and Engine from Scratch for context).

This is the beginning of week 5.

What I have done

  • Build system changes:
    • Include directory search paths are used in the dependency hash so that if they change a file is recompiled
    • The use of standard libraries or platform libraries in compiled files that a target depends on now influences its compiled files include directory search paths
      • This is so that if some downstream target #includes a file that #includes <windows.h>, for example, that it will work as expected (meaning that specifying the static library dependency is enough)
    • Added features to help IntelliSense
      • Include directories and preprocessor defines are now added to VCXPROJ files
      • Compile arguments are now added to VCXPROJ files
        • (It turns out that this is important for IntelliSense for things like detecting what version of C++ is used; without it there are lots of false positive red squiggles when using newer features)
      • Files are now added to VCXPROJ files
        • Currently this is done by specifying a file path, along with an optional type (e.g. for C++ compiling or C++ including) and an optional logical display folder (so that files can be organized in a logical file structure in e.g. Solution Explorer).
        • I mostly like this, but one small annoyance is that for C++ files that get compiled it means that each source CPP file has to be listed twice. For now I have decided that the way it is makes sense (rather than e.g. automatically adding these files to be displayed) but it’s something I will have to keep thinking about as I get more experience.
      • Individual files can now be compiled in Visual Studio
        • This involved both adding a pattern for command lines but also adding the ability to jpmake. Previously I had a command line where a file path could be specified to generate just that file (i.e. it was an output file path), but in order to support the Visual Studio functionality the file path must be an input path.
      • Individual C++ files to compile can now have individual C++ build info, rather than always using the C++ build info of the target
        • This was already supported under the hood in jpmake, but I didn’t have a Lua interface for it
  • A new EmptyWindow application exists
    • All this does is create and display a main window, so it is the most basic application imaginable, but it was still exciting to be working on real code rather than the build system
    • I made a post about it
  • I have added many type traits
    • So far these are just clones of standard library ones that I have needed, but it has been fun to learn more about how some of this template “magic” works
    • I made a post about it
  • I added scope guard classes
  • I added custom implementations of move and forward
    • MakeMovable() and ForwardReference() are macros based on https://www.foonathan.net/2020/09/move-forward/
      • I discovered accidentally (there was some reddit or stack overflow comment about that link I think) that the macro version enforces actual moves with no copying fallback, which is something that I have wanted but wasn’t sure if or how it was implementable. After figuring out why the macro had this difference (related to const vs. non-const rvalue references) I have also added a MakeMovableIfPossible() in case I ever want it, which just does the same thing that std::move() does.
  • I added volatile load and store functions, with relaxed, acquire, or release memory ordering
  • I added the ability to allocate and free memory from the operating system
    • (It is also possible to reserve and commit memory in steps if the operating system supports it. This is something I use in jpmake, but don’t currently anticipate using in the game engine itself.)
  • I made array view and memory view classes
    • These don’t have all of the functionality that I would like, but they are a good start of a fundamental building block
    • The cMemoryView class can have a view of both const and mutable memory, and allows slices to be made for partitioning memory
  • I have added memory arena and allocator classes
    • This is just a starting point, but I do have a monotonic allocator and am able to partition and then logically allocate memory from the operating system
    • I have New()/Delete() functions for working with typed memory and Allocate()/Free() functions for working with untyped memory, all of which require an arena
      • The goal is to allocate a single big block of operating system memory when the application starts and then only work with that for the lifetime of the application by partitioning that into smaller sections and using hierarchical arenas to allocate in a controlled way (“controlled” both in terms of lifetimes and cache friendliness).
  • I have set up the machinery for creating a graphics “engine” and created a D3D12 device
    • The application lets the graphics library create a graphics engine, passing in itself and a block of memory from the operating system that is budgeted for graphics. The graphics engine stores a reference to the application who created it and returns a pointer to itself that the application can refer to. This is my attempt at dependency injection while still allowing easy access to different systems.
    • The graphics engine will have a platform-specific context, and so far I am just creating a D3D12 device to store in it as a proof of concept to show that I am able to access the platform-specific D3D functionality and allocate and store things with the new memory system.

Next Steps

  • Use D3D12 to clear the main window to some arbitrary color
  • Implement the top part of the window as one clear color and the bottom part of the window as a different clear color using ideas discussed at https://blurbusters.com/blur-busters-lagless-raster-follower-algorithm-for-emulator-developers/
    • This isn’t how I intend my engine to run (I will use VSync), but ever since reading about it I have wanted to try and do it to make sure I understood the timing involved, and I think getting this to work would show that I have the fundamentals in place before implementing how I really want my renderer to work.

Leave a Reply

Your email address will not be published. Required fields are marked *