ID3DXAllocateHierarchy - Memory Leaks

Started by
15 comments, last by John_Idol 16 years, 4 months ago
I implement it but I don't call Create/DestroyMeshContainer, 'cause as for Create/DestroyFrame, they are callbacks. I checked and the code is being executed.

these are the functions I am using (from a demo which web address you can find on top-post):

struct D3DXMESHCONTAINER_EXTENDED: public D3DXMESHCONTAINER{/* The base D3DXMESHCONTAINER has a pMaterials member which is a D3DXMATERIAL structure that contains a texture filename and material data. It is easier to ignore this and instead store the data in arrays of textures and materials in this extended structure:*/IDirect3DTexture9**  exTextures;		// Array of texture pointers  D3DMATERIAL9*        exMaterials;		// Array of materials                                // Skinned mesh variablesID3DXMesh*     exSkinMesh;			// The skin meshD3DXMATRIX* exBoneOffsets;			// The bone matrix Offsets, one per boneD3DXMATRIX**		 exFrameCombinedMatrixPointer;	// Array of frame matrix pointers};HRESULT CMeshHierarchy::CreateMeshContainer( THIS_    LPCSTR Name,    CONST D3DXMESHDATA *pMeshData,    CONST D3DXMATERIAL *pMaterials,    CONST D3DXEFFECTINSTANCE *pEffectInstances,    DWORD NumMaterials,    CONST DWORD *pAdjacency,    LPD3DXSKININFO pSkinInfo,    LPD3DXMESHCONTAINER* ppNewMeshContainer){    // Create a mesh container structure to fill and initilaise to zero values// I use an extended version of the structure (D3DXMESHCONTAINER_EXTENDED)D3DXMESHCONTAINER_EXTENDED *newMeshContainer=new    D3DXMESHCONTAINER_EXTENDED;ZeroMemory(newMeshContainer, sizeof(D3DXMESHCONTAINER_EXTENDED));// initialise return pointer before proceeding*ppNewMeshContainer = NULL;// The mesh name (may be null) needs copying overnewMeshContainer->Name=CUtilities::DuplicateCharString(Name);// The mesh type (D3DXMESHTYPE_MESH, D3DXMESHTYPE_PMESH or D3DXMESHTYPE_PATCHMESH)	if (pMeshData->Type!=D3DXMESHTYPE_MESH)	{	// This does not handle mesh types other than the standard	DestroyMeshContainer(newMeshContainer);	return E_FAIL;	}newMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;	// Adjacency data - holds information about adjacency, required by ID3DMESH DWORD dwFaces = pMeshData->pMesh->GetNumFaces();newMeshContainer->pAdjacency = new DWORD[dwFaces*3];memcpy(newMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * dwFaces*3);	// Get the Direct3D device, luckily this is held in the mesh itselfLPDIRECT3DDEVICE9 pd3dDevice = NULL;pMeshData->pMesh->GetDevice(&pd3dDevice);// Make a copy of the mesh data that is passed in to our mesh containerD3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE];if (FAILED(pMeshData->pMesh->GetDeclaration(Declaration)))	return E_FAIL;pMeshData->pMesh->CloneMesh(D3DXMESH_MANAGED,               		Declaration, pd3dDevice, 		&newMeshContainer->MeshData.pMesh);// Create material and texture arrays. I always want to have at least onenewMeshContainer->NumMaterials= max(NumMaterials,1);newMeshContainer->exMaterials= new D3DMATERIAL9[newMeshContainer->NumMaterials];newMeshContainer->exTextures= new LPDIRECT3DTEXTURE9[newMeshContainer->NumMaterials];ZeroMemory(newMeshContainer->exTextures,sizeof(LPDIRECT3DTEXTURE9)* newMeshContainer->NumMaterials);if (NumMaterials>0){	// Load all the textures and copy the materials over			for(DWORD i = 0; i < NumMaterials; ++i)	{	newMeshContainer->exTextures = NULL;		newMeshContainer->exMaterials=pMaterials.MatD3D;        if(pMaterials.pTextureFilename)	{           // Note: the texture filename in the mesh container is an LPSTR (char  *) but this           // demo uses UNICODE so convert to LPWSTR (WCHAR*) required by D3DXCreateTextureFromFileW	   WCHAR wszTexName[MAX_PATH];	   CUtilities::FillWideStringFromCharString(pMaterials.pTextureFilename,wszTexName,MAX_PATH);	    // Use the D3DX function to create the texturer	    if(FAILED(D3DXCreateTextureFromFile(pd3dDevice,   wszTexName,&newMeshContainer->exTextures)))	    {	    newMeshContainer->exTextures = NULL;	    }	}	}}else    // make a default material in the case where the mesh did not come with one    {		ZeroMemory(&newMeshContainer->exMaterials[0], sizeof( D3DMATERIAL9 ) );        newMeshContainer->exMaterials[0].Diffuse.r = 0.5f;        newMeshContainer->exMaterials[0].Diffuse.g = 0.5f;        newMeshContainer->exMaterials[0].Diffuse.b = 0.5f;        newMeshContainer->exMaterials[0].Specular = newMeshContainer->exMaterials[0].Diffuse;	newMeshContainer->exTextures[0]=NULL;    }	// If there is skin data associated with the mesh copy it over	if (pSkinInfo)	{		// save off the SkinInfo	    newMeshContainer->pSkinInfo = pSkinInfo;	    pSkinInfo->AddRef();	    // Need an array of offset matrices to move the vertices from the figure space to the bone's space	    UINT numBones = pSkinInfo->GetNumBones();	    newMeshContainer->exBoneOffsets = new D3DXMATRIX[numBones];		// Create the arrays for the bones and the frame matricesnewMeshContainer->exFrameCombinedMatrixPointer = new D3DXMATRIX*[numBones];	    // get each of the bone offset matrices so that we don't need to get them later	    for (UINT i = 0; i < numBones; i++)	        newMeshContainer->exBoneOffsets = *(newMeshContainer->pSkinInfo->GetBoneOffsetMatrix(i));/* Note: in the Microsoft samples a GenerateSkinnedMesh function is called here in order to prepare the skinned mesh data for optimial hardware acceleration. As mentioned in the notes this sample does not do hardware skinning but instead uses software skinning*/	}	else		{		// No skin info so null all the pointers		newMeshContainer->pSkinInfo = NULL;		newMeshContainer->exBoneOffsets = NULL;		newMeshContainer->exSkinMesh = NULL;		newMeshContainer->exFrameCombinedMatrixPointer = NULL;	}	// When we got the device we caused an internal reference count to be incremented	// So we now need to release it	SAFE_RELEASE(pd3dDevice);	// The mesh may contain a reference to an effect file	if (pEffectInstances)	{		if (pEffectInstances->pEffectFilename)		{			OutputDebugString(L"This .x file references an effect file. Effect files are not handled by this demo");		}	}		// Set the output mesh container to our newly created one	*ppNewMeshContainer = newMeshContainer;    	return S_OK;}HRESULT CMeshHierarchy::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase){// Convert to our extended type. OK as we know for sure it is:D3DXMESHCONTAINER_EXTENDED* pMeshContainer=(D3DXMESHCONTAINER_EXTENDED*)pMeshContainerBase;		// name	SAFE_DELETE_ARRAY(pMeshContainer->Name)	// material array	SAFE_DELETE_ARRAY(pMeshContainer->exMaterials)	// release the textures before deleting the array	if(pMeshContainer->exTextures)	{		for(UINT i = 0; i < pMeshContainer->NumMaterials; ++i)			SAFE_RELEASE(pMeshContainer->exTextures);	}	// texture array	SAFE_DELETE_ARRAY(pMeshContainer->exTextures)	// adjacency data	SAFE_DELETE_ARRAY(pMeshContainer->pAdjacency) 		// bone parts	SAFE_DELETE_ARRAY(pMeshContainer->exBoneOffsets)		// frame matrices	SAFE_DELETE_ARRAY(pMeshContainer->exFrameCombinedMatrixPointer)		// release skin mesh	SAFE_RELEASE(pMeshContainer->exSkinMesh)		// release the main mesh	SAFE_RELEASE(pMeshContainer->MeshData.pMesh)		// release skin information	SAFE_RELEASE(pMeshContainer->pSkinInfo)		// finally delete the mesh container itself	SAFE_DELETE(pMeshContainer);    return S_OK;}


If no-one will read all this code... I won't blame them :-)
Advertisement
Sorry for those never-ending comment lines...
Hi there, I use this code mostly unchanged and my demos seem to work and close ok. (But I also used the same thing to learn from too, so mm??????..)

Are you sure there is a memory leaks. try not using it and just load a basic mesh and see if the errors still there.
I tought it was something I changed, but then I tried to pay attention at the demo project (unchanged) output and I was getting the memory leaks as well (with both the default bouncy-thing and the skeleton one).
So I set the breakalloc and when it stopped the last call on the callstack was LoadHierarchyFromX. All of this wit the April SDK.
Now doing the same thing with the November SDK I am getting a different result, when breakalloc breaks the execution it says me the there's no source code available for the current location and shows me disassembly code, and the call stack is different. No idea about what I should do, this is the current call stack:

------->ntdll.dll!7c901230() 	//breaks on this line 	d3d9d.dll!00f4ed3d() 	 	d3d9d.dll!00f4e4cb() 	 	d3d9d.dll!00f4e59b() 	 	d3d9d.dll!00f4e440() 	 	d3d9d.dll!00f64963() 	 	d3d9d.dll!00f4af3f() 	 	d3d9d.dll!00f8dd57() 	 	d3d9d.dll!00f4e440() 	 	d3d9d.dll!00fbe7b7() 	 	d3d9d.dll!00fc85ba() 	 	d3d9d.dll!00fc84b7() 	 	d3d9d.dll!0118a46b() 	 	d3d9d.dll!00fcad2c() 	 	D3DX9d_36.dll!0067589b() 	 	d3d9d.dll!00fbb852() 	 	d3d9d.dll!00fbbe81() 	 	d3d9d.dll!00fbbe44() 	 	d3d9d.dll!00fc89ee() 	 	D3DX9d_36.dll!00676567() 	



[Edited by - John_Idol on November 29, 2007 6:11:28 AM]
it would be good if someone would reply....
is it or is it not got a problem???????? or is it just a debug thing...
Quote:Original post by ankhd
it would be good if someone would reply....
is it or is it not got a problem???????? or is it just a debug thing...


Thanks ;-)

Have you been using the same demo?
Can you try and see if you get memory leaks with the original demo? (on VS2003)
Some new Info:

the breakAllocId changes if I change the Default .X file to be loaded, no matter what how many models how load after. Obviously the number of unfreeed bytes increases if I load more models. This makes me think the break allocId is registered just the first time, and something goes wrong every time I load an .X. No Memory leaks at all if I load models without animation.

With some of the models I am Actually able to BreakOnAllocId and the debbuger kicks in on this line of my implementation of CMeshHierarchy::CreateMeshContainer:


// When we got the device we caused an internal reference count to be incremented
// So we now need to release it
SAFE_RELEASE(pd3dDevice);

This topic is closed to new replies.

Advertisement