Why int's for outside-engine resource lookups?

Jan 16, 2012 at 10:39 AM
Edited Jan 16, 2012 at 10:41 AM

I have been crawling into this code and come to wonder why resource ID's outside engine scope are ints? In documentation i read that this is to protect internal DX objects from user code and to simplify knowledge requirements, but this also creates some drawbacks in current implementation. For example - what if you would need to destroy some resources at a time, without reloading all of them (very common in games as UI and common graphics files will stay the same, while per-level data will change) ? Currently you cannot remove any particular one resource from arrays (as far as i know) as that would break all other 'references'. Why not make those references as a hash codes and look up into hashtable, not list? Engine internal resource lookups by integer index could also be removed if reference to DX3D11 resource would be a friend class to engine containing protected direct reference to D3D11 object.  You could then also add some other useful stuff to that reference, for example, creation time and/or user-specified group id, to later use that as a tag for disposing related batch of resources. You could then assign, for example, all core resources (back buffer textures etc) index of 0, and per-level resources, say, index 1 and after level is done, just call Renderer->ReleaseByGroup(1) to get rid of per-level resources. Thro simplest way currently to add per-resource release is to change ID calculation from "container.count - 1" to "container.findFirstUnusedIndex()" that would return first index into container array where resource have been released and/or is null.

Coordinator
Jan 16, 2012 at 7:51 PM

Hello Haibane,

Thank you for the interesting post!  You are indeed correct that there is no way to delete resources in the current implementation.  At the time of the initial implementation I was only writing small demos with the engine, and hence didn't need to be very careful in developing a good system for managing lots of references.  Especially since GPU resources are virtual in D3D11, it was never an issue before...  It would still be nice to have a good way to manage the resources, and your suggestions about allowing groups and naming objects are good points.

The reason that I haven't utilized a hash table was simplicity and lookup speed - it doesn't get much faster than an array lookup.  In addition, by using an index for the outside world to reference the resources, it makes it possible to change the implementation very easily - the outside world gets an integer, but they have no idea was the integer value means.  So we can update the implementation without having to worry about changing the types that the users are referencing.

To be honest, I have thought about this exact topic recently after adding the ability to resize texture resources and realizing that I can't get rid of the resources.  I have done some investigation into methods for utilizing a recycled index, similar to what is discussed in this post from the bitsquid guys.  This will be a good little update to make, so thank you for bringing it up.

I am not clear on what you mean with the removal of the internal integer references - can you explain that a little further?  Since the client application refers to the resources by integer, I'm not sure how I could get out of using the same lookup procedure internally as well.  Perhaps a short example would clear it up?

This is a great discussion topic - I'd love to continue this and other discussions, so keep on crawling!

Jan 20, 2012 at 12:11 PM
Edited Jan 20, 2012 at 12:21 PM

Good read on that bitsquid, thanks for pointing that out :)

About that "integer reference removal" - there (probably?) will be a need to replace int with some more sophisticated struct for extension (add unique id to know when reference supplied is old etc) and to avoid code duplication (i see you are doing some experimentation on id like "type = id & 0xFFFF" that i believe would be better encompassed as a function on struct. And as long id stuct does not contain any actual pointer reference, you keep all the benefits of simple data. As looking up a reference from more sophisticated data structure would probably be more cpu-costly, it might be beneficial to use actual pointers when communicating in engine internal components, on the other hand it will make engine code more complicated and that's probably a thing to avoid.

Coordinator
Jan 20, 2012 at 7:03 PM

Ahh - I see now.  Well, I could switch the index to a struct, but I'm not sure if it is really necessary.  Currently I have some helper functions for validating the type and index being within range, and I think moving those methods to the structure would be somewhat more encapsulated.  However, the implementation remains within the renderer class, so the whole system is currently contained anyway.  If I need to add some additional room for extra information, I could always switch to an int64 instead of just a regular integer. 

However, I think your other suggestions have merit.  Currently, I think this is the list of updates that I would like to make to the resource referencing system:

  1. Allow the release of resources.  This will be done by passing the ResourcePtr (or directly the resource ID) to a RendererDX11 method.
  2. Currently there is no way to reference which resource view is tied to which resource.  Each resource view that gets created for a resource should be recorded in the ResourceDX11 class, and then they can also be released when their resource is released.
  3. To facilitate reusing the empty slots in the list, we will add a unique id to the resource index.  As each resource is created, the unique id counter is incremented and used to ensure an old index doesn't reference a new resource (and can assert that to be the case).
  4. When a new resource is created, we simply search the array of pointers to find one that is null.  If there is none, then the array is increased in size by using the *.add(...) method.
  5. The group ID that you mentioned above can easily be added to the ResourceDX11 base class, and then a simple search of the array will turn up all the items with that ID.  The removal shouldn't happen too often, so just a linear search should be fine.
  6. I would also like to add a naming mechanism for the resources, so that there is some way to reference them when debugging (and also usable for PIX too).

I think that should be sufficient to get the system upgraded a little bit.  Let's see if I can make that happen fairly soon :)  Thanks for the suggestions, and I'll be sure to post once the update is performed!

 

Feb 26, 2012 at 10:20 PM

Any update on this? :)

Coordinator
Feb 27, 2012 at 12:20 PM

I am slowly marching towards a solution on this topic.  I am changing the way the resources are indexed, but I am doing it piece by piece rather than a single big set of changes.  It is just taking a long time since I've been away for a couple weeks.  In my current local copy, I have removed the ID information from the resources, and I'm testing things out to ensure that it didn't break anything.

I'll try to keep pushing forward with this and get going a bit further ASAP!  Thanks for the reminder :)

- Jason

Feb 27, 2012 at 6:32 PM

Nice to hear that, keep up the good work! :)