swars icon indicating copy to clipboard operation
swars copied to clipboard

refactoring: GPU acceleration in bflibrary

Open mefistotelis opened this issue 2 years ago • 0 comments

That was always highly requested feature, for all Bullfrog games.

Personal approach:

I really like the special style of pre-GPU rendered 3D games; each of them looked really unique, especially compared to the first accelerated games. For contrast, the 3D pipelines using old Glide, and first version of OpenGL and DirectX were very static - no shaders, no stylization, just provide polygons and textures and that's it. Each of these games looked the same, being at high contrast with the variety of software-rendered games, which often used non-standardized approaches to 3D, and surprising optimizations.

Now that same look changed over time, as more modern versions of OGL and DirectX were introduced. The pipeline became very dynamic, allowing to inject custom code (shaders) at each step of the scene generation and rasterization. Now, every style that was used in the past, can be reproduced by crafting a proper set of shaders.

For me, the original approach - where the style was a necessity due to hardware restrictions rather than creative decision - still has a value. I like looking at it as a series of tough engineering decisions, and I wouldn't like that transformed into just a touch of artistic vanity. So, I don't really need any hardware-accelerated Bullfrog game.

Another approach is from the legal perspective. Mods for Bullfrog games require the original game to play, which provides one argument against copyright litigation. Another is that all the mods are free and with no financial reward to developers. But that may not be enough in case the copyright owners plans to remake the game - since they often cannot offer much more than modernized graphics, having graphical improvement mod for an old game is a risk for their new release.

Still, people do ask for that. So here is how we'd go with making it happen.

Game loop:

The Bullfrog games do everything in a loop within one thread:

  • read inputs
  • update game world
  • apply changes due to inputs
  • draw the game screen
  • repeat

So the first thing that needs an update in each game it to divide that - draw the game in a separate thread. This of course is not as easy as creating a new thread and calling draw function there - because there is no single draw function. So to achieve that, first all calls need to be separated from reading inputs and updating the world - that will require storing some additional information from some functions, to be later used by the drawing functions. When reading the world state for the purpose of drawing is separated from reading that state for the purpose of world update, then locks have to be added, so that drawing thread won't read something in the middle of an update. Then, when this is ready, the drawing can be finally moved to a separate thread.

BfLibrary interfaces:

The Bullfrog Library interface does not provide a level of abstraction to support both hardware and software rendering. It assumes the screen is a memory mapped area, and work buffer is also a part of the system memory and accessible for direct writes.

So a new interface would have to be created, working at appropriate level of the API. There would be a different format of draw list for the accelerated output, and the HUD and menus would have to be drawn using draw list as well - currently these elements are often drawn directly during their state update.

mefistotelis avatar Jun 20 '22 17:06 mefistotelis