DX9 texture memory question

Started by
5 comments, last by waterwizard 19 years, 5 months ago
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.
Advertisement
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...
Sean Henley [C++ Tutor]Rensselaer Polytechnic Institute
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...
[size=2]aliak.net
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! :)
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.
[size=2]aliak.net
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