Trouble resolving dependency properly

Started by
3 comments, last by Ripiz 11 years, 6 months ago
Hello,

firstly little background. I've seen a lot posts "Write games on engines" and I don't need this type of stuff here. I'm just trying to separate engine and game early on instead of having a lot of hardcoded things later on. This is where I encountered a problem. I'm trying to wrap DirectX into a bit more friendly classes, but they need DirectX Device and I can't think of a decent way of passing device to these objects. Roughly my code looks like this:


class VertexShader {
ID3D11VertexShader *shdr;

void Create(void *bytecode, uint32 size); // requires ID3D11Device or DXWrapper;
};

class DXWrapper {
ID3D11Device *dvc;
ID3D11DeviceContext *dvcc;
};

class Engine {
DXWrapper DXW;
};

// this is how I use VertexShader class:
class SkinnedRenderer {
VertexShader vrtShader;

SkinnedRenderer() {
auto bytecode = ResourceManager.Get("skinned_vs.cso");
vrtShader.Create(bytecode.data(), bytecode.size());
}
};


I managed to think of 2 possible solutions (workarounds?) but I'm not satisfied with either of them.

  1. Pass D3D Device as argument in VertexShader::Create() call, but I feel it's a bit messy doing it all the time.
  2. Make Engine or DXWrapper class's instance static/global, allowing global access, but I'm trying to avoid such dependency, as code re-useability decreases.


Anyone have any ideas how can I resolve this issue, or solution #1 is the right way?

Thank you in advance.
Advertisement
I'm not a graphics programmer (yet), but aren't vertex buffers dependent on the device you create them from? If this is the case, then #1 makes sense assuming you mean DXWrapper& and not ID3D11Device*. However, if this isn't an option, why not pass an intermediate class, which hides the device being used to create the vertex buffers from the interface? Something like the following:


class VertexBufferContext {
public:
VertexBuffer create( ... );

private:
DXWrapper& context;
};
It's VertexShader, not VertexBuffer, but doesn't matter, wrappers look almost identical.
Yes, it does depend on device.

I would still have to initialize VertexBufferContext somewhere, most likely on the DXWrapper, such class method probably would be better on DXWrapper itself, rather than dummy class with single method. However, assignment operator displeases me:


class DXWrapper {
public:
VertexShader CreateVertexShader(...);
};

class SkinnedRenderer {
VertexShader vrtShader;

SkinnedRenderer(DXWrapper &DXW) {
auto bytecode = ResourceManager.Get("skinned_vs.cso");

// this assigment feels little bit fishy and a bit wrong
vrtShader = DXW.CreateVertexShader(bytecode.data(), bytecode.size());
}
};


And before someone suggests using pointer: this class also has purpose of destroying resources on it's own destruction, solves issue of missing Release() calls and some redundant typing.
I recently came across this design problem myself and found that creating a factory responsible for the creation of game assets (shaders, textures, etc.) was a good way to go. The factory ends up maintaining the ID3D11Device creation/destruction, and you can add methods for whatever resources you need with whatever arguments you need. It's no different than the original interface for ID3D11Device really, but it ends up doing away with some creation options you don't think you'll need.


class ResourceManager {
public:
Mesh* createMesh(const char* file);
Texture* createTexture(const char* file);
VShader* createVertexShader(const char* file);
PShader* createPixelShader(const char* file);
private:
ID3D11Device* m_device;
ID3D11DeviceContext* m_context;
};
Thank you both for reply. It seems some kind of factory might be the a good choice in this case.

This topic is closed to new replies.

Advertisement