Passer un pointeur à chaque fonction augmente la taille de la pile de 4 octets par ajout (si on oublie un instant les possibles optimisations du compilo, dans le cas où tu ne fais que forward le pointeur par exemple), je suis pas certain que ce soit un gros problème, mais imo dans ce genre de cas avoir un singleton fait plus de sense.
Je suis en train de faire un renderer 3D pour les asset de Wow (ça se voit sur mes précédents posts ici, non?

), et de mon côté j'ai tout simplement choisi de stocker
GxContext (l'équivalent de ton
SDL_Renderer*) dans toutes les classes qui décrivent de la géométrie ou des sources de lumière.
Ça n'empêche pas
GxContext d'être unique: son cycle de vie est contrôlé par le programme. Si j'ai besoin de plusieurs surfaces de rendu, je définis de nouvelles textures pour le depth stencil, etc, et je dessine dedans.
Du coup à mon sens, avoir un singleton ici est la chose la plus logique à faire; et dans la foulée, je forcerai sa création au démarrage du programme. Je réalise que ce n'est pas ce que j'ai fait, mais mon programme ne sert pas qu'à visualiser de la géométrie, c'est aussi un outil pour le datamining, et le rendu 3D n'est qu'un bonus

Petite note: DirectX n'apprécie pas qu'on envoie des commandes depuis plusieurs threads (à juste titre); je ne connais pas le positionnement d'OpenGL et/ou de la SDL à ce sujet mais quand tu commenceras à devoir toucher au threading, garde ça en mémoire

(Je ne sais même pas si c'est autorisé d'avoir plusieurs pipelines de rendu, quelle que soit l'API utilisée; j'ai toujours recyclé un unique pipeline ...)
Fork?