Multiple graphics backends

Started by
3 comments, last by jpetrie 15 years, 5 months ago
I want to build my game with the potential to change the underlay graphics API, without rewritting game code. Im currently doing this by proving additonal layers between my game code and the graphics API (currently only d3d9) eg

class IGraphics;
class ISprite;

class IGraphics
{
protected:
	unsigned backCol;
public:
	IGraphics(){};
	virtual~IGraphics(){};

	void SetBackgroundColour(unsigned col){backCol = col;}
	virtual void Render(boost::function<void(IGraphics*)>)=0;

	virtual ISprite *CreateSprite(const std::wstring &File)=0;
};

class D3D9 : public IGraphics
{
	bool lost;
	Window *window;
	IDirect3D9             *d3d;
	IDirect3DDevice9       *device;
	IDirect3DVertexBuffer9 *quadVB;
	void GetParams(D3DPRESENT_PARAMETERS *out);
	void D3D9::SetRenderStates();
public:
	D3D9(Window *window);
	virtual ~D3D9();
	IDirect3DDevice9 *GetDevice();
	virtual void Render(boost::function<void(IGraphics*)>);
	virtual ISprite *CreateSprite(const std::wstring &File);

	boost::function<void(IGraphics*)> OnDeviceLost;
	boost::function<void(IGraphics*)> OnDeviceReset;
};

The game then only handles classes such as IGraphics and ISprite within its code for the most part (eg stuff like lost/reset device is a d3d thing I need to handle, but opengl doesnt have anything like that, however for the most part it will be handled within the other classes once im done). The problem thats occured to me however, is that even if I never call any function from a given API, it loads the API's dlls straight off, meaning it will only work for people who support all the backends I used... Is there someway to make it only load/lookfor/need the dlls when I actauly create a D3D9 IGraphics instance and same for openGL and D3D10? So it will work for poeple that dont have D3D10 for example, as long as they chose D3D9/OpenGL in the options?
Advertisement
You can export a function called (say) GetGraphics from each DLL, which returns an IGraphics, then use LoadLibrary and GetProcAddress to find and call that function on-demand.

That way, you'd only be loading your d3d.dll or opengl.dll when it was actually selected.
So your saying break each one into its own dll, and load/unload that as I need, rather than having them all in the main exe?
Yep, that's the standard approach.

Another option would be to mark the depending DLLs as delay-loaded, but that's probably a bit more flakey than just having separate DLLs.
I would also suggest that if you care at all about the quality of this implementation, you immediately halt forward progress and go fix that "current only D3D9" bug. Runtime-swappable rendering subsystems are thorny, and of highly questionable utility and practicality beyond educational experience... if you build one by providing a vague abstraction based only on a single concrete API (e.g., "only D3D9") you'll probably find yourself with heaps of refactoring to do later, once the abstraction is large and unweildy, and you only just are starting to try and build the OpenGL implementation underneath.

This topic is closed to new replies.

Advertisement