Today we're announcing a brand new library that will be replacing FNA's graphics subsystem, called FNA3D:
What is FNA3D?
FNA3D is a pure C99 library that provides an XNA4-like graphics API, which can be rendered with one of many available graphics backends, including backends for OpenGL (2.1, ES3) and Metal (EDIT: Now D3D11 as well!). In addition to providing significant performance improvements to FNA's existing graphics implementation, it is significantly easier to add new backends and is now completely decoupled from FNA itself, meaning all the years of work that have been put into FNA's rendering speed and reliability can now be used by other projects!
You can find the full README here.
Way back in 2014, when FNA was officially becoming its own library (vs. just a platform fork of MonoGame), one of the first major from-scratch rewrites I did was for the renderer. The result was "OpenGLDevice", which isolated all the API calls throughout the library into a single, easy-to-manage file. This eventually evolved into "IGLDevice", which allowed for multiple implementations in a single binary, meaning we could have various graphics backends without compromising FNA's single-assembly portability feature. This was recently used to develop FNA's new Metal implementation for macOS/iOS/tvOS!
Over the years, a frequent question that has come up is how backends with more specific needs would be plugged into IGLDevice. Direct3D is typically accessed in C# via SharpDX, which I didn't want to include as a dependency, and console graphics APIs would have required special private branches, which goes against the single-assembly portability rule and gives FNA users a significantly greater maintenance burden. My answer to all these questions was usually "we'll just make a native DLL for those backends when they show up," with me secretly knowing that such a backend would never actually materialize anyway. Because, you know, it's not like I was going to do it, and FNA didn't have that many contributors back then.
Except now we do have major contributors, most notably Caleb Cornett, who actually have more of an interest in these targets than me, a guy that just cares about Linux and desktop versions. As both a learning experiment and a test of how usable IGLDevice really was, Caleb started work on a D3D11Device that was all contained in a native C++ DLL, which was accessed via DllImports in FNA. This actually kind of worked! The problem is that managing both the native pointers as well as all the C# interfaces was really painful, to the point where I, the author of IGLDevice in the first place, wanted all the C# crap to get out of the way so we could just use the pointers by themselves. It made me wonder what it'd be like to move all the existing OpenGL stuff to a C library as well, since I happen to prefer C anyway...
With that, the prototyping of an all-C99 IGLDevice implementation began. Just 26 days later, we had a fully-complete port of every FNA graphics backend with the IGLDevice totally replaced with this new DLL. Despite being super-bleeding-edge, it is an absolute dream to work with compared to the old C# code! That's probably the reason that this got done so quickly; not only do we have every existing backend ported already, but two new backends are already in development, now that adding new code no longer requires working with C# craziness just to get started.
When can I start using FNA3D?
This is about 60,000 lines of changes, so while we're very confident in FNA3D's quality in the early stages, it is still early, so we're calling this the "beta" phase: All the features from IGLDevice are present and the library works on Linux, Windows, macOS, iOS, tvOS, Xbox, Switch, and Stadia, but we're still hunting for possible bugs introduced by the port, and we're also still locking in the final public API. Our intention is to freeze the ABI and complete the transition from IGLDevice to FNA3D for FNA 20.09, to be released on September 1, 2020. If you're interested in helping test, read on!
How can I help test FNA3D?
If you're using FNA right now, you can follow this guide to get started with moving to the new graphics system, and you can ignore the entire next section.
If you're developing a non-FNA project and want to try FNA3D, you should really read the next section first.
Should I be using FNA3D?
If you're looking for an experience identical to Microsoft.Xna.Framework.Graphics, this is for you! If you're looking for a generic graphics library, you will probably be very unhappy with FNA3D.
FNA3D is taking a very different approach compared to FAudio, FNA's library for audio support. FAudio was, from the very beginning, developed with every intention of it being used in lots of different projects, from games using XAudio2 to other reimplementation projects like Wine. FAudio has a very broad appeal, so we have to accommodate the needs of many different kinds of projects in addition to FNA.
For FNA3D, we're taking the exact opposite approach: If your project doesn't have the exact same needs as FNA, too bad, we don't care. This is not a graphics library like DXVK, where they have the immense burden of having to work with thousands of applications where maybe like 0.1% of them actually have valid data and call streams. If you write code that's not valid and it doesn't work, now or later, that's your problem, not ours. Don't like our shader system? Tough, you can write a new one if you need it that badly, and by the way, it can't affect FNA's performance or reliability. FNA is one of FAudio's priorities, while FNA is FNA3D's only priority. Match your code with FNA's or go use something else. It may seem harsh, but the main reason FNA's renderer is as good as it is has a lot to do with keeping an aggressively strict specification, with virtually no concern for how other projects write their graphics systems.
If you're still interested in trying FNA3D after all that, simply
git clone --recursive git://github.com/FNA-XNA/FNA3D.git
... and follow the README! The headers are in the 'include/' folder, and are fully documented.
The FNA Discord
As always, you can find the community at our Discord server! The #development channel has been very active, and you can use #help if you need any assistance with FNA3D.
I'm happy to announce that I am now in the GitHub Sponsors program! This means that anyone with a GitHub account can now subscribe to a monthly payment system that will allow me to continue my work maintaining the numerous FOSS game development projects that I maintain, including FNA and FAudio.
You can find my sponsorship profile here.
If you're on the fence about this, I'll give you quite the incentive: Microsoft is skipping all payment processing fees, so in addition to taking extra money out of Microsoft's pocket (which I think my audience will take some joy in...), everything you pledge will go directly to me. A slight change of pace from Patreon's usual scams, hm?
I've been very vocal about the poor state of the crowdfunding ecosystem, and I think the GitHub Sponsors program is very much what we've all been looking for. I think you'll agree, and I hope you'll pledge what you can!
Want a Linux game?
I'm now officially back to working on Linux games full-time! I have my own hit list as always, but I'm always looking for more projects! Now's a really good time to hit me up while it's on my mind. Don't forget, whether you're an indie developer or an independent developer, there's a good chance I can accommodate your needs!
Turn a minimal Fedora installation into a SteamOS box!
1. Write Fedora Workstation NetInstall ISO to a USB drive 2. Boot USB image, install Minimal configuration with standard partition layout matching SteamOS' 3. Set root password, create a user called 'steam', set a password for it 4. Reboot, log in as root 5. A whole bunch of commands: dnf group install hardware-support dnf install Xorg xorg-x11-drv-evdev libglvnd-egl vulkan-loader.x86_64 vulkan-loader.i686 lightdm flatpak NetworkManager-wifi kernel-modules-extra bluez dnf config-manager --add-repo=https://negativo17.org/repos/fedora-steam.repo dnf install steam steamos-compositor steamos-modeswitch-inhibitor.x86_64 steamos-modeswitch-inhibitor.i686 setsebool -P allow_execheap 1 systemctl enable sshd.service systemctl enable lightdm.service systemctl set-default graphical.target 6. Edit /etc/lightdm/lightdm.conf: pam-service=lightdm-autologin pam-autologin-service=lightdm-autologin user-session=steamos autologin-user=steam autologin-session=steamos 7. Create /var/lib/AccountsService/users/steam: [User] Session=steamos XSession=steamos Icon=/home/steam/.face SystemAccount=false 8. Reboot, should work now! 9. Additional steps for NVIDIA users: dnf config-manager --add-repo=https://negativo17.org/repos/fedora-nvidia.repo dnf install kernel-devel dkms-nvidia nvidia-driver-libs.x86_64 nvidia-driver-libs.i686 reboot # Should be using the NVIDIA driver now!
Want to replicate my build machine? Grab CentOS 7 and have a look...
# Update base install before doing anything else yum update # Add EPEL yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm # Add SCL yum install centos-release-scl # All the base build tools! yum install bzip2 bzip2-devel clang cmake cmake3 gcc-c++ git hg \ libcxx-devel libstdc++-static libuuid-devel libxml2-devel llvm-devel \ lzma-sdk-devel openssl-devel patch svn yum-utils yum-plugin-copr # SDL2 dependencies yum-builddep SDL2 # Coprs for MinGW as well as LLVM 8, needed to build osxcross yum copr enable mlampe/devtoolset-8 yum copr enable mlampe/llvm-toolset-8.0 yum copr enable alonid/mingw-epel7 yum install devtoolset-8 llvm-toolset-8.0 mingw32-* mingw64-* # CMake3 by default alternatives --install /usr/local/bin/cmake cmake /usr/bin/cmake 10 \ --slave /usr/local/bin/ctest ctest /usr/bin/ctest \ --slave /usr/local/bin/cpack cpack /usr/bin/cpack \ --slave /usr/local/bin/ccmake ccmake /usr/bin/ccmake \ --family cmake alternatives --install /usr/local/bin/cmake cmake /usr/bin/cmake3 20 \ --slave /usr/local/bin/ctest ctest /usr/bin/ctest3 \ --slave /usr/local/bin/cpack cpack /usr/bin/cpack3 \ --slave /usr/local/bin/ccmake ccmake /usr/bin/ccmake3 \ --family cmake # Also: # Modify unistd.h to change __block to anything but __block # The CMake config provided by SDL2-mingw is terrible, delete the block # that starts with "if(NOT TARGET SDL2::SDL2)". # Be prepared to pass -std=gnu99 manually. A LOT. # To enter Mac building mode (and to build osxcross itself): # scl enable llvm-toolset-8.0 bash
Wait, a "plan"?
Well, this is a .plan file, so here's my TODO. Expect nothing from it, ever.
In Progress FNA3D Vulkan Star-Twine Codename ThinkingWithShaders Codename MishyMashyPlatformSmashy Celeste Stadia Launch They Bleed Pixels Switch Launch Waiting Room Streets of Rage 4 - Port's been done for a while, QA isn't ready yet Panzer Paladin - Waiting on an external thing Anodyne 1, TFoL, VVVVVV 2.3 - Look at these after FNA3D's out Rhys - Someone has to remove the XNA relinker FNA Tutorial - Leaving this alone for a bit SDL_GetAudioDeviceSpec - Oh god I don't even know dude Codename FullCircle - Need some backend access first... Codename CityVessel - Not even finished yet, whatever Codename SpinnyTokelau - Assessment coming up in... uhh... ScoreRush PC - Graphics, AppAdmin, strings for PC settings, blah blah blah 64-bit Panic - Waveform repo :/ - Gotta rebuild all MojoSetup packages (F you Canonical)