7

Currently I want to optimize my 3d engine for consoles a bit. More precisely I want to be more cache friendly and align my structures more data oriented, but also want to keep my nice user interface.

For example:

bool Init()
{
  // Create a node
  ISceneNode* pNode = GetSystem()->GetSceneManager()->AddNode("viewerNode");

  // Create a transform component
  ITransform* pTrans = m_pNode->CreateTransform("trans");
  pTrans->SetTranslation(0,1.0f,-4.0f);
  pTrans->SetRotation(0,0,0);

  // Create a camera component
  ICamera* pCam = m_pNode->CreateCamera("cam", pTrans);
  pCam->LookAt(Math::Vec3d(0,0,0));

  // And so on...
}

So the user can work with interface pointers in his code.

BUT
In my engine I currently store pointers to scene nodes.

boost::ptr_vector<SceneNode> m_nodes

So in data oriented design it's good practice to have structs of arrays and not arrays of structs. So my node gets from...

class SceneNode
{
private:
  Math::Vec3d m_pos;
};

std::vector<SceneNode> m_nodes;

to this...

class SceneNodes
{
  std::vector<std::string> m_names;
  std::vector<Math::Vec3d> m_positions;
  // and so on...
};

So I see two problems here if I want to apply DOP. Firstly how could I keep my nice user interface without having the user to work with IDs, indexes and so on?

Secondly how do I handle relocations of properties when some vectors resize without letting users interface pointers point to nirvana?

Currently my idea is to implement a kind of handle_vector from which you get a handle for persistent "pointers":

typedef handle<ISceneNodeData> SceneNodeHandle;
SceneNodeHandle nodeHandle = nodeHandleVector.get_handle(idx);

So when the intern std::vector resizes, it updates its handles. A "handle" stores a pointer to the actual object and the "->" operator is overloaded to achive a nice wrapping. But this approach sounds a bis complicated to me?!

What do you think? How to keep a nice interface, but keep thinks contiguous in memory for better cache usage?

Thanks for any help!

1
  • Data-oriented-programming is in my example the conversion from arrays-of-structs to a struct-of-arrays. The virtual Update() methode gets pulled out of a SceneNode an is then a member of the SceneNodes structure. So I can step linear over my arrays in which I'm interested.
    – VitaminCpp
    Commented Oct 6, 2010 at 17:19

2 Answers 2

5

You will need to use smarter handles than raw pointers. There is no way around it with DOP.

This means:

class SceneNode
{
public:
  std::string const& getName() const { mManager->getSceneName(mId); }
  void setName(std::string const& name) { mManager->setSceneName(mId, name); }

  // similar with other data
private:
  ISceneManager* mManager;
  size_t mId;
};

One very good point though: the user cannot accidently call delete on one of the pointer you returned now. That's why smart handles are always better.

On the other hand: how are you going to deal with the lifetime of the pointee of mManager is another issue :-)

3
  • Yes I also thought in this direction, but it doesn't seem very elegant to me... But I think I will choose such a solution and hide the indexing from the user. In my design all "managers" are global. So a simple assert() in debug mode to ensure we have a valid manager is enought. This is a big drawback of DOP. Thank you!
    – VitaminCpp
    Commented Oct 6, 2010 at 14:12
  • @VitaminCpp: it's not really a drawback, as far as I am concerned, because I always use smart handles anyway when designing an interface. Much easier to evolve, may include reference counting transparently, protects the content and may provide binary compatibility much more easily. Commented Oct 6, 2010 at 14:34
  • Indeed this is a strong argument! Now the hard part is to remodel the scene node itself DOP... :( Thanks a lot!
    – VitaminCpp
    Commented Oct 6, 2010 at 14:46
1

For those interested in a practical example of DOP, have a look at this fantastic presentation from Niklas Frykholm => http://bitsquid.blogspot.com/2010/05/practical-examples-in-data-oriented.html

This helped me to implement my scene graph in a data oriented manner.

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