Sign in to follow this  
mozie

DX9 texture memory question

Recommended Posts

My current project loads a mesh with D3DXCreateMeshFromFile, multiple times, assigning different x,y,z and rotation values to each. It also gets the texture if there is one specified in the .x mesh. My case is a simple one, but I think it applys to a larger scale if I don't address it eventualy. If the same texture is loaded with the above method, does it get stored multiple times in memory, and accessed seperatly? I suspect it does, but I wouldnt be suprised if it is smarter than that.

Share this post


Link to post
Share on other sites
I am working on the assumption that the D3DX routines are not that smart. Not exactly surefire advice, but since nobody else has commented...

Share this post


Link to post
Share on other sites
Do you mean multiple meshes using the same texture, or lots of the same meshes? I assume you mean the second...

There are techniques called texture pooling and batching you could use to make sure you are not chewing up the entire video RAM. Try googling for tutorials on these, as I'm sure I couldn't explain them very well...

Share this post


Link to post
Share on other sites
Yeah, it does get stored multiple times in memory. You can avoid this by having a sort of texture manager or something. A very simple way would be to use an


std::map<std::string, IDirect3DTexture9*> texturemap;


Then before loading a texture check the map to see if it's already loaded. If it isnt, then load the texture and store a pointer in the map. If it is, then just use the pointer that is already in the map.

You should remember to IDirect3DTexture9::AddRef whenever a texture is loaded so that when one releases it, the original dosent actually get released.

This is of course a very simple way to do this, there are faster and more efficient techniques, but I leave that to you to figure out and invent. That's where teh fun is...

Share this post


Link to post
Share on other sites
Thank's for the replys!

I guess the question I posted made me rethink my design, basicly assuming that DX will know that I have loaded the same file 7, or even 70 times isn't good in itself.

Quote:
Original post by IFooBar
Yeah, it does get stored multiple times in memory. You can avoid this by having a sort of texture manager or something. A very simple way would be to use an


std::map<std::string, IDirect3DTexture9*> texturemap;


Then before loading a texture check the map to see if it's already loaded. If it isnt, then load the texture and store a pointer in the map. If it is, then just use the pointer that is already in the map.


This is what I'm starting work to impliment. I did a bunch of reading at flipcode, about good program structure. I have decided that my current index method for my object manager, to say the least you could call it bad.

I really dont understand std::map namespace, I have never looked it up, and just decided to invent my own way in the meantime. I think I am going to make a class to hold information about the objects location, rotation, movement vectors, etc. Also it would contain pointers to its data members, like the loaded mesh and testure location in memory. Right now this is implimented with a struct. My object manager class has a public pointer, and it also sets a global pointer so other classes can access the index.

Here is my nasty index struct, incase anyone was interisted.


typedef struct strObjectIndex
{
DWORD ref; // objects ref number
ObjectType type; // enumerated type for object
DWORD flags; // flags on this object
DWORD dwNumMaterials; // materials in mesh
char filename[128]; // filename of mesh if exists
LPD3DXMESH pMesh; // pointer to mesh in memory
D3DMATERIAL9* pMeshMaterials; // a pointer to our mesh material structure
LPDIRECT3DTEXTURE9* pMeshTextures; // ' ' textures ' '
D3DXVECTOR3 internal; // objects internal space origin
D3DXMATRIX matT; // transformation
D3DXMATRIX matS; // scalar
D3DXMATRIX matX; // rotation X axis
D3DXMATRIX matY; // rotation Y axis
D3DXMATRIX matZ; // rotation Z axis
FLOAT rotX; // store current rotation X
FLOAT rotY; // store current rotation Y
FLOAT rotZ; // store current rotation Z
D3DXVECTOR3 direction; // unit vector for objects movement direction
FLOAT scalar; // our velocity
DWORD dwNumFaces;
DWORD dwNumIndices;
DWORD dwNumVertices;
FLOAT radius;
}ObjectIndex, *pObjectIndex;



Quote:

You should remember to IDirect3DTexture9::AddRef whenever a texture is loaded so that when one releases it, the original dosent actually get released.

You mean I need to AddRef for every object that wants to use the texture, even though it is only 'loaded' once?
And then I guess just remove the ref when the object is destroyed? Or maintain a ref count equal to the refs getting drawn on the screen at this time, because they are the only ones that really need to use it at the time of render?

Quote:

This is of course a very simple way to do this, there are faster and more efficient techniques, but I leave that to you to figure out and invent. That's where teh fun is...


What about loading the mesh into memory still in its file format, I can't think of a way to pass a memory address as a file, and I have never though to try directly. Would it just be better to load the VB&IB into memory, and use DrawIndexedPrimitave insted of DrawSubset. I understand this is more work, but this is my first venture into any kind of scene management method, and I dont really think that a call to DrawSubset for every object, texture, and alpha is going to play out well in the long run.

For now, I'm just going to try to make a functional class. My camera class came out well (I think), and works with only minor adjustments to the code that was accessing it as a struct! :)

Share this post


Link to post
Share on other sites
Quote:
You mean I need to AddRef for every object that wants to use the texture, even though it is only 'loaded' once?


Yeah. It's so that you can safely release the texture per object without worrying about the texture memory being erased before all objects are done with it. I think maybe a little code will explain it better:


texutre* texmanager::load(filename) {
if( texture_from_file(filename) == not_loaded )
tex = load_texture(filename);

tex->AddRef();
return tex;
}

// some other code
void somefunction() {
texture* t = texmanager::load("myfile");

// Now even if the texture manager deleted its own texture
// at this very time, *this* function will still have a valid
// texture pointer because the ref count was incremented before
// the texture pointer was passed to it.
texmanager::destroy();

// use texture safely...

// Release texture to decrement the ref count and if your the
// last to release this texture then it gets deleted.
t->Release();


Quote:
Would it just be better to load the VB&IB into memory, and use DrawIndexedPrimitave insted of DrawSubset. I understand this is more work, but this is my first venture into any kind of scene management method, and I dont really think that a call to DrawSubset for every object, texture, and alpha is going to play out well in the long run.


That will make batching easier. Batching as in pushing as many vertices that share the same property out to the graphics card in one go. So usually it is a good idea. Generally, IMO, the ID3DXMesh object is good for mesh manipulation (optimizing messhes, welding vertices, lod stuff), but it's not really that efficient at drawing the meshes.

Share this post


Link to post
Share on other sites
I'm just learning DX programming, but it seems to me you would just load the mesh once but have DX render it in multiple positions as needed and keep track of the various instances with separate objects that have pointers to the actual mesh instances.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this