Tutorial 72: Choosing the Right Rendering Backend
CNA supports four rendering backends. The backend is selected at compile time via a CMake option and compiled into the binary. Runtime switching is not supported.
Backend comparison
| Backend | API coverage | Rendering | Platforms | Best for |
|---|---|---|---|---|
| SDL_RENDERER | 2D-only by design | 2D only | Linux, Windows, Android, Web, macOS | Pure 2D games, CI/CD, maximum compatibility |
| EASYGL | Most mature | 2D + 3D | Linux, Windows, Android (GLES 3.0), Web (WebGL 2) | Most games, broadest GPU support, easiest debug |
| VULKAN | Second-most mature | 2D + 3D | Linux, Windows, Android | Performance-critical games, modern GPUs |
| BGFX | Full parity (Phase 72) | 2D + 3D | Linux, Windows, macOS, Android, Web | Multi-backend portability via a single abstraction |
SDL_RENDERER — 2D only, best compatibility
The SDL_RENDERER backend maps CNA's API onto SDL3's built-in 2D accelerated renderer. It requires no OpenGL or Vulkan driver. SDL3's renderer targets can be hardware-accelerated via the OS compositor (Metal on macOS, D3D11 on Windows, OpenGL on Linux) without the application needing to use those APIs directly.
Limitations: no VertexBuffer, no IndexBuffer, no custom Effect shaders, no BasicEffect 3D rendering, no RenderTarget2D with depth/stencil, no MRT. Any call that requires 3D will throw a NotSupportedException.
Use this backend when: your game is purely 2D, you need to run in a CI environment without a GPU driver, or you are targeting a platform with no OpenGL/Vulkan support.
EASYGL — most mature backend, OpenGL ES 3.0
The EASYGL backend uses the easy-gl library (a sibling repo) to provide an OpenGL ES 3.0 / OpenGL 3.3 core profile implementation. It is CNA's primary, most mature backend, and covers the vast majority of the XNA 4.0 API surface including:
- Full 3D rendering with
VertexBuffer,IndexBuffer,BasicEffect, customEffect RenderTarget2Dwith depth/stencil and MRT (up to 4 targets)- All
BlendState,DepthStencilState,RasterizerStatepresets - GLSL shader support via the Effect system
- Texture formats: Color, HalfVector4, Vector4, Rgba1010102, HdrBlendable
EASYGL is the recommended backend for development and for shipping on Linux, Windows, and Android. RenderDoc attaches cleanly for GPU debugging.
VULKAN — second-most mature, best performance
The VULKAN backend targets Vulkan 1.2 and is CNA's second-most mature backend, with all five stock effects implemented and pixel-tested. It offers lower CPU overhead and better multi-threading opportunities (though CNA does not currently use Vulkan secondary command buffers from worker threads).
The setup cost is higher: you need vulkan-headers and libvulkan-dev, and Vulkan validation layers are recommended during development (see Tutorial 73). Shader code compiles to SPIR-V at build time via glslangValidator or shaderc.
Use VULKAN when: you are targeting modern desktop GPUs, you need the best frame time performance, or you want to future-proof your pipeline — outside of workloads that need custom BlendState modes or working OcclusionQuery.
BGFX — full 2D+3D parity, multi-backend
The BGFX backend wraps the bgfx library, which in turn can target OpenGL, Metal, Direct3D 11/12, or Vulkan depending on the platform. It reached full 2D+3D pixel-verified parity with EasyGL and Vulkan as of this project's Phase 72 — all five stock effects, render targets (MSAA/mip/depth), and all four state classes are real and pixel-tested. Two named gaps remain: custom ShaderEffect source compilation is unsupported (bgfx wants precompiled binary shaders), and OcclusionQuery correctness can't be pixel-verified in this project's CI sandbox. It provides the widest platform reach including macOS (Metal) from a single CMake build.
Decision table
| Situation | Choose |
|---|---|
| Pure 2D game, need web & mobile | SDL_RENDERER or BGFX |
| 3D game, Linux/Windows primary | EASYGL |
| 3D game, best performance, modern hardware | VULKAN |
| Need macOS Metal support | BGFX |
| Development & debugging | EASYGL (best RenderDoc / apitrace support) |
| CI without GPU | SDL_RENDERER (works with software renderer) |
How to set the backend in CMake
Pass -DCNA_GRAPHICS_BACKEND=<NAME> to the CMake configure step. The value is case-sensitive.
// CMakeLists.txt excerpt — backend selection
set(CNA_GRAPHICS_BACKEND "EASYGL" CACHE STRING
"CNA rendering backend: SDL_RENDERER | EASYGL | VULKAN | BGFX")
set_property(CACHE CNA_GRAPHICS_BACKEND PROPERTY STRINGS
SDL_RENDERER EASYGL VULKAN BGFX)
# Validate the choice
if(NOT CNA_GRAPHICS_BACKEND MATCHES "^(SDL_RENDERER|EASYGL|VULKAN|BGFX)$")
message(FATAL_ERROR
"Invalid CNA_GRAPHICS_BACKEND: '${CNA_GRAPHICS_BACKEND}'. "
"Valid values: SDL_RENDERER, EASYGL, VULKAN, BGFX")
endif()
# Each backend adds its own CMake subdirectory
add_subdirectory(src/backends/${CNA_GRAPHICS_BACKEND})
# Expose the selection as a preprocessor define
target_compile_definitions(CNA PUBLIC
CNA_BACKEND_${CNA_GRAPHICS_BACKEND}=1)
To configure and build with the Vulkan backend:
cmake -S . -B build-vulkan -DCNA_GRAPHICS_BACKEND=VULKAN
cmake --build build-vulkan --target CNA CnaTests
Preprocessor defines in game code
You can use the preprocessor defines to include backend-specific code paths in your game:
#if defined(CNA_BACKEND_VULKAN)
// Vulkan-specific: enable Vulkan validation layers at startup
SDL_SetHint(SDL_HINT_VULKAN_DISPLAY, "1");
#elif defined(CNA_BACKEND_EASYGL)
// EasyGL-specific: request a debug context for RenderDoc
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS,
SDL_GL_CONTEXT_DEBUG_FLAG);
#endif
Runtime switching (not supported)
CNA does not support switching the rendering backend at runtime. The backend is compiled into the binary and initialised once during Game::Run(). If you need to support multiple backends from a single executable, build the project twice with different CNA_GRAPHICS_BACKEND settings and ship both binaries (e.g. auto-select based on SDL_GetPlatform() in a launcher shell script).
Alternatively, the BGFX backend selects its underlying API at runtime from the set of backends bgfx was compiled with, which gives some degree of runtime flexibility on platforms where BGFX supports multiple APIs.