Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm developing a game. The game architecture is very modular. I have a "Graphics Engine", which uses either a Direct3D or OpenGL renderer. However the user does not have access to the renderers directly. Instead the "Graphics Engine" class is used, which uses a renderer interface.

I also have a resource management system. As for now, the renderers are respoinsible for allocating and releasing video memory. That couples my design in a bad way, since the "Graphics Engine" has undesirable logic for transferring resources between the RAM and the VideoRam through sending signals to the "Renderer". I want the resource management system to be responsible for allocating video memory.

I want to decouple the "Renderer" and "Graphics Engine" classes as much as possible, and make the renderer only responsible for rendering. Is there a way to obtain a universal pointer to a Video RAM buffer, and use it to render with both renderers?

My problem is basically that I can only obtain OpenGL or Direct3D handles, which can be used only from the relevant API. And the "Graphics Engine" should not know which renderer it uses.

share|improve this question
    
isnt kinda like using a render target in xna, i guess there's no reason you can't wrap that up somehow in your own "API" –  Wardy Aug 17 '13 at 17:30
    
Are you not basically describing what most game engines do though? I personally use unity, at no point do i go near any DX or OpenGL API I simply declare game objects and add a renderer component to them, behind all that unity figures out the actual calls needed and its platform independent so whats your angle? –  Wardy Aug 17 '13 at 17:32
    
i guess you will have to code interfaces for the user to interact with and implement the neccesary functions once for each API. I don´t think there is a way of interacting with videocard in an API Independent way. –  Luis W Aug 17 '13 at 17:35

1 Answer 1

up vote 2 down vote accepted

This is just basic abstraction. Write an API-neutral interface for buffers, textures, and so on. Either use dynamic polymorphism (abstract interfaces with virtual functions) for these or compile-time static polymophism (a shared header with some ifdefs and then link different implementations whether you're compiling for a D3D-primary platforms or a GL-only platform). A simple, very incomplete draft of doing this would be:

// implement this interface for each graphics API you support
class IBuffer {
public:
  ~IBuffer() {}

  virtual size_t GetByteWidth() const = 0;
  virtual void UpdateData(const void* data, size_t width, size_t offset = 0) = 0;
  virtual void* Map() = 0;
  virtual void Unmap() = 0;
};

// implement this interface for each graphics API you support
class IGraphicsDevice {
public:
  virtual std::shared_ptr<IBuffer> CreateBuffer(size_t size) = 0;
};

// creates a device as appropriate
enum class EGraphicsType { Default, Direct3D, OpenGL, OpenGLES };
shared_ptr<IGraphicsDevice> GraphicsDeviceFactory(EGraphicsType type) {
  switch (type) {
  case EGraphicsType::Default:
#if defined(HAS_DIRECT3D)
  case EGraphicsType::Direct3D:
    return std::make_shared<GraphicsDeviceDirect3D>();
#endif
#if defined(HAS_OPENGL)
  case EGraphicsType::OpenGL:
    return std::make_shared<GraphicsDeviceOpenGL>();
#endif
#if defined(HAS_OPENGLES)
  case EGraphicsType::OpenGLES:
    return std::make_shared<GraphicsDeviceOpenGLES>();
#endif
  default:
    ASSERT(!"Unsupported graphics device");
    return nullptr;
  }
}

For static polymorphism, get rid of the virtual calls, directly embed the ID3DWhatever* values or GLint values wrapped in an #if defined(USE_FOO) to select which implementation to use, and make a variety of .cpp files for each platform and either only link the ones you need or wrap their contents in more macro conditionals. For some of the last-gen consoles the static polymorphism approach could have a substantial impact on performance as their CPUs weren't as good at efficiently handling virtual table indirections, though on the PC and likely the next-gen consoles this shouldn't be much of a problem. I don't have any information on mobile platforms regarding this.

share|improve this answer
    
As an addendum, I don't think it's quite common to call the compile-time technique mentioned "static polymorphism" but I don't know any other terminology that more accurately describes it. Primary point is that you can do it all at compile-time with no virtual function calls. You can use the PIMPL pattern to keep system dependencies out of your headers if you want, too, or just use void* and a lot of casting since both the D3D COM interface pointers and the GLint handles will fit in a void* on every architecture that matters to game development. –  Sean Middleditch Aug 18 '13 at 19:23

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.