DX9 texture memory question
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.
I am working on the assumption that the D3DX routines are not that smart. Not exactly surefire advice, but since nobody else has commented...
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...
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...
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
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...
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...
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.
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.
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?
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! :)
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 anstd::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! :)
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 codevoid 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.
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.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement