No idea where it leaked.

Started by
11 comments, last by lucky6969b 11 years, 2 months ago

I followed a book actually and plug it into a QT project

Do you find anything unusual?

D3DX: MEMORY LEAKS DETECTED: 159 allocations unfreed (3312 bytes)
D3DX: Set HKLM\Software\Microsoft\Direct3D\D3DXBreakOnAllocId=0x2fd0 to debug

myDX9Widget.h


#pragma once

 
#include "dxwidget.h"



class myDX9Widget :
    public DXWidget
{
public:
    
#ifdef QWIDGET_H
    myDX9Widget( QWidget *parent = 0, Qt::WFlags flags = 0 )
        : DXWidget( parent, flags ), m_pD3D(0), m_pDevice(0)
    {
    }
#else
    myDX9Widget()
        : m_pD3D(0), m_pDevice(0)
    {
    }
#endif

    virtual ~myDX9Widget()
    {
        uninitialize();
    }

    virtual void initCamera()
    {
        m_camera[0].Load(m_pDevice, "Data\\Others\\Demo1.cam");
        m_camera[1].Load(m_pDevice, "Data\\Others\\Demo2.cam");
        m_camera[2].Load(m_pDevice, "Data\\Others\\Demo3.cam");
    }

    virtual void initModels()
    {
        mOperatorMesh.Load(L"Data\\operator.x");

    }
    //-----------------------------------------------------------------------------
    // Name: initialize()
    // Desc: This function will only be called once during the application's
    //       initialization phase. Therefore, it can't contain any resources that
    //       need to be restored every time the Direct3D device is lost or the
    //       window is resized.
    //-----------------------------------------------------------------------------
    HRESULT initialize()
    {
        HRESULT hr = S_OK;

        
        m_pD3D = 0;
        m_pDevice = 0;
        
        m_pVB = NULL;
        m_pIB = NULL;
        m_pVertexShader = NULL;
        m_pConstantTable = NULL;
        m_pVertexDeclaration = NULL;

        m_pD3D = Direct3DCreate9(D3D_SDK_VERSION); //Standard

        D3DCAPS9 Caps;
        m_pD3D->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &Caps );

        DWORD BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;

        // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW
        // then switch to SWVP.
        if( ( Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) == 0 ||
            Caps.VertexShaderVersion < D3DVS_VERSION( 2, 0 ) )
        {
            BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
        }

        ZeroMemory( &m_d3dpp, sizeof(m_d3dpp) );
        m_d3dpp.Windowed = TRUE;
        m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
        m_d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
        m_d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
        m_d3dpp.MultiSampleQuality = 0;
        m_d3dpp.EnableAutoDepthStencil = TRUE;
        m_d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;

        for( int m=0; m<=(int)D3DMULTISAMPLE_4_SAMPLES; m+=2 )
        {
            DWORD QualityBackBuffer = 0;

            hr = m_pD3D->CheckDeviceMultiSampleType( D3DADAPTER_DEFAULT,
                                                     D3DDEVTYPE_HAL,
                                                     m_d3dpp.BackBufferFormat,
                                                     m_d3dpp.Windowed,
                                                     (D3DMULTISAMPLE_TYPE)m,
                                                     &QualityBackBuffer );
            if( FAILED(hr) ) break;
        
            if( QualityBackBuffer>0 )
            {
                m_d3dpp.MultiSampleType = (D3DMULTISAMPLE_TYPE)m;
                m_d3dpp.MultiSampleQuality = QualityBackBuffer-1;
            }
        }

        // Hardware Device
        hr = m_pD3D->CreateDevice(
            D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, winId(),
            BehaviorFlags, &m_d3dpp, &m_pDevice );

        if( FAILED(hr) )
        {
            m_d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
            m_d3dpp.MultiSampleQuality = 0;
            // Reference Rasterizer
            hr = m_pD3D->CreateDevice(
                D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, winId(),
                D3DCREATE_SOFTWARE_VERTEXPROCESSING, &m_d3dpp, &m_pDevice );
        }

        g_pDevice = m_pDevice;

        if (SUCCEEDED(hr))
        {
            hr = restoreDeviceObjects();
        }

        initCamera();
        initModels();
        

        return hr;
    }

    //-----------------------------------------------------------------------------
    // Name: uninitialize()
    // Desc: Releases all previously initialized objects
    //-----------------------------------------------------------------------------
    void uninitialize()
    {

        invalidateDeviceObjects();

        SAFE_RELEASE(m_pDevice);
        SAFE_RELEASE(m_pD3D);
    }

    //-----------------------------------------------------------------------------
    // Name: restoreDeviceObjects()
    // Desc: You are encouraged to develop applications with a single code path to
    //       respond to device loss. This code path is likely to be similar, if not
    //       identical, to the code path taken to initialize the device at startup.
    //-----------------------------------------------------------------------------
    HRESULT    restoreDeviceObjects()
    {
        if( !m_pDevice ) return E_FAIL;

        
        HRESULT hr = S_OK;

        DWORD VERTS_PER_EDGE = 64;
        DWORD dwNumVertices = VERTS_PER_EDGE * VERTS_PER_EDGE;
        DWORD dwNumIndices = 6 * ( VERTS_PER_EDGE - 1 ) * ( VERTS_PER_EDGE - 1 );

        // Create and initialize index buffer
        WORD* pIndices;
        V_RETURN( m_pDevice->CreateIndexBuffer( dwNumIndices * sizeof( WORD ),
                                                 0, D3DFMT_INDEX16,
                                                 D3DPOOL_DEFAULT, &m_pIB, NULL ) );
        V_RETURN( m_pIB->Lock( 0, 0, ( void** )&pIndices, 0 ) );

        DWORD y;
        for( y = 1; y < VERTS_PER_EDGE; y++ )
        {
            for( DWORD x = 1; x < VERTS_PER_EDGE; x++ )
            {
                *pIndices++ = ( WORD )( ( y - 1 ) * VERTS_PER_EDGE + ( x - 1 ) );
                *pIndices++ = ( WORD )( ( y - 0 ) * VERTS_PER_EDGE + ( x - 1 ) );
                *pIndices++ = ( WORD )( ( y - 1 ) * VERTS_PER_EDGE + ( x - 0 ) );

                *pIndices++ = ( WORD )( ( y - 1 ) * VERTS_PER_EDGE + ( x - 0 ) );
                *pIndices++ = ( WORD )( ( y - 0 ) * VERTS_PER_EDGE + ( x - 1 ) );
                *pIndices++ = ( WORD )( ( y - 0 ) * VERTS_PER_EDGE + ( x - 0 ) );
            }
        }
        V_RETURN( m_pIB->Unlock() );

        // Create and initialize vertex buffer
        V_RETURN( m_pDevice->CreateVertexBuffer( dwNumVertices * sizeof( D3DXVECTOR2 ), 0, 0,
                                                  D3DPOOL_DEFAULT, &m_pVB, NULL ) );

        D3DXVECTOR2* pVertices;
        V_RETURN( m_pVB->Lock( 0, 0, ( void** )&pVertices, 0 ) );
        for( y = 0; y < VERTS_PER_EDGE; y++ )
        {
            for( DWORD x = 0; x < VERTS_PER_EDGE; x++ )
            {
                *pVertices++ = D3DXVECTOR2( ( ( float )x / ( float )( VERTS_PER_EDGE - 1 ) - 0.5f ) * D3DX_PI,
                                            ( ( float )y / ( float )( VERTS_PER_EDGE - 1 ) - 0.5f ) * D3DX_PI );
            }
        }
        V_RETURN( hr = m_pVB->Unlock() );


        LPD3DXBUFFER pCode;
        D3DVERTEXELEMENT9 decl[] =
        {
            { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
            D3DDECL_END()
        };
        V_RETURN( m_pDevice->CreateVertexDeclaration( decl, &m_pVertexDeclaration ) );

        DWORD dwShaderFlags = 0;
#ifdef DEBUG_VS
        dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
    #endif
#ifdef DEBUG_PS
        dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
#endif
        V_RETURN( D3DXCompileShaderFromFile( L"HLSLwithoutFX.vsh", NULL, NULL, "Ripple",
                                             "vs_2_0", dwShaderFlags, &pCode,
                                             NULL, &m_pConstantTable ) );
        hr = m_pDevice->CreateVertexShader( ( DWORD* )pCode->GetBufferPointer(), &m_pVertexShader );
        pCode->Release();
        if( FAILED( hr ) )
            return hr;

        m_pDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
        m_pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
        m_pDevice->SetRenderState( D3DRS_MULTISAMPLEANTIALIAS, TRUE );
        
        return S_OK;
    }

    //-----------------------------------------------------------------------------
    // Name: invalidateDeviceObjects()
    // Desc: If the lost device can be restored, the application prepares the
    //       device by destroying all video-memory resources and any
    //       swap chains. This is typically accomplished by using the SAFE_RELEASE
    //       macro.
    //-----------------------------------------------------------------------------
    HRESULT invalidateDeviceObjects()
    {
        if( !m_pDevice ) return E_FAIL;
        
        
        SAFE_RELEASE( m_pVertexShader );
        SAFE_RELEASE( m_pConstantTable );
        SAFE_RELEASE( m_pVertexDeclaration );
        SAFE_RELEASE( m_pIB );
        SAFE_RELEASE( m_pVB );
        

        return S_OK;
    }

    //-----------------------------------------------------------------------------
    // Name: render()
    // Desc: Draws the scene
    //-----------------------------------------------------------------------------
    virtual HRESULT    render()
    {
        
        if( !m_pDevice ) return E_FAIL;

        HRESULT hr = S_OK;

        clearScene( D3DXCOLOR( 0.0f, 0.25f, 0.25f, 0.55f ), 1.0f, 0 );

        DWORD VERTS_PER_EDGE = 64;
        DWORD dwNumVertices = VERTS_PER_EDGE * VERTS_PER_EDGE;
        DWORD dwNumIndices = 6 * ( VERTS_PER_EDGE - 1 ) * ( VERTS_PER_EDGE - 1 );

        if( SUCCEEDED(beginScene()) )
        {
            D3DXMATRIXA16 mWorldViewProj = D3DXMATRIXA16((float*)&ViewMatrix()) * D3DXMATRIXA16((float*)&ProjMatrix());
            // DX10 spec only guarantees Sincos function from -100 * Pi to 100 * Pi
            float fBoundedTime = (float) m_fTime - (floor( (float) m_fTime / (2.0f * D3DX_PI)) * 2.0f * D3DX_PI);

            m_pConstantTable->SetMatrix( m_pDevice, "mWorldViewProj", &mWorldViewProj );
            m_pConstantTable->SetFloat( m_pDevice, "fTime", fBoundedTime );

            m_pDevice->SetVertexDeclaration( m_pVertexDeclaration );
            m_pDevice->SetVertexShader( m_pVertexShader );
            m_pDevice->SetStreamSource( 0, m_pVB, 0, sizeof( D3DXVECTOR2 ) );
            m_pDevice->SetIndices( m_pIB );
            m_pDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, dwNumVertices, 0, dwNumIndices / 3 );

            endScene();
        }

        hr = present();
        m_lastRendered = m_fTime;
        

        return S_OK;
    }

    //-----------------------------------------------------------------------------
    // Name: clearScene()
    // Desc: Clear the render target and depth stencil
    //-----------------------------------------------------------------------------
    void    clearScene( D3DXCOLOR ClearColor, float Z, DWORD Stencil )
    {
        m_pDevice->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, (DWORD)ClearColor, Z, Stencil );
    }

    //-----------------------------------------------------------------------------
    // Name: clearRenderTarget()
    // Desc: Clear the render target
    //-----------------------------------------------------------------------------
    void    clearRenderTarget( D3DXCOLOR ClearColor )
    {
        m_pDevice->Clear( 0, 0, D3DCLEAR_TARGET,(DWORD)ClearColor, 1.0f, 0 );
    }

    //-----------------------------------------------------------------------------
    // Name: clearScene()
    // Desc: Clear the render target
    //-----------------------------------------------------------------------------
    void    clearDepthStencil( float Z, DWORD Stencil )
    {
        m_pDevice->Clear( 0, 0, D3DCLEAR_TARGET, 0, Z, Stencil );
    }

    //-----------------------------------------------------------------------------
    // Name: beginScene()
    // Desc: Begin the scene
    //-----------------------------------------------------------------------------
    HRESULT    beginScene()
    {
        return m_pDevice->BeginScene();
    }

    //-----------------------------------------------------------------------------
    // Name: endScene()
    // Desc: End the scene
    //-----------------------------------------------------------------------------
    HRESULT    endScene()
    {
        return m_pDevice->EndScene();
    }

    //-----------------------------------------------------------------------------
    // Name: present()
    // Desc: Present the backbuffer contents to the display
    //-----------------------------------------------------------------------------
    HRESULT    present()
    {

        HRESULT hr;

        
        hr = m_pDevice->Present( 0, 0, 0, 0 );

        // The following code refer to "Direct3D (DirectX 9.0) Code Samples Page6: Lost Device Recovery".
        // URL: http://www.codesampler.com/dx9src.htm

        //
        // If Present fails with D3DERR_DEVICELOST the application needs to be
        // notified so it cleanup resources and reset the device.
        //

        if( D3DERR_DEVICELOST == hr )
        {
            // Yield some CPU time to other processes
            Sleep( 100 ); // 100 milliseconds

            //
            // Test the cooperative level to see if it's okay to render.
            // The application can determine what to do on encountering a lost
            // device by querying the return value of the TestCooperativeLevel
            // method.
            //

            if( FAILED( hr = m_pDevice->TestCooperativeLevel() ) )
            {
                // The device has been lost but cannot be reset at this time.
                // Therefore, rendering is not possible and we'll have to return
                // and try again at a later time.
                if( hr == D3DERR_DEVICELOST )
                    return hr;

                // The device has been lost but it can be reset at this time.
                if( hr == D3DERR_DEVICENOTRESET )
                {
                    //
                    // If the device can be restored, the application prepares the
                    // device by destroying all video-memory resources and any
                    // swap chains.
                    //

                    invalidateDeviceObjects();

                    //
                    // Then, the application calls the Reset method.
                    //
                    // Reset is the only method that has an effect when a device
                    // is lost, and is the only method by which an application can
                    // change the device from a lost to an operational state.
                    // Reset will fail unless the application releases all
                    // resources that are allocated in D3DPOOL_DEFAULT, including
                    // those created by the IDirect3DDevice9::CreateRenderTarget
                    // and IDirect3DDevice9::CreateDepthStencilSurface methods.
                    //

                    hr = m_pDevice->Reset( &m_d3dpp );

                    if( FAILED( hr ) )
                        return hr;

                    //
                    // Finally, a lost device must re-create resources (including  
                    // video memory resources) after it has been reset.
                    //

                    restoreDeviceObjects();
                }
            }
        }
        

        return hr;
    }

    virtual void    paintEvent(QPaintEvent *e)
    {
        Q_UNUSED(e);
        render();
    }

    void    onResize( UINT nWidth, UINT nHeight )
    {
        HRESULT hr = S_OK;

        if( !m_pDevice ) return;

        
        m_d3dpp.BackBufferWidth = nWidth;
        m_d3dpp.BackBufferHeight = nHeight;

        invalidateDeviceObjects();

        hr = m_pDevice->Reset(&m_d3dpp);

        restoreDeviceObjects();
        
        // Camera ---------------------------------------------------

        setAspect( width() / (float)height() );
        

        render();
    }

private:
    //! Used to create the D3DDevice
    IDirect3D9*                m_pD3D;

    //! Our rendering device
    IDirect3DDevice9*        m_pDevice;

    //! D3D Device Parameterss
    D3DPRESENT_PARAMETERS    m_d3dpp;

    LPDIRECT3DVERTEXBUFFER9         m_pVB;
    LPDIRECT3DINDEXBUFFER9          m_pIB;
    LPDIRECT3DVERTEXSHADER9         m_pVertexShader;
    LPD3DXCONSTANTTABLE             m_pConstantTable;
    LPDIRECT3DVERTEXDECLARATION9    m_pVertexDeclaration;

    SkinnedMesh mOperatorMesh;

};
 
 

skinnedmesh.h


//////////////////////////////////////////////////////////////////////////
//                    Character Animation with Direct3D                    //
//                           Author: C. Granberg                            //
//                               2008 - 2009                                //
//////////////////////////////////////////////////////////////////////////

#ifndef SKINNED_MESH
#define SKINNED_MESH

#include <windows.h>
#include <d3dx9.h>
#include <string>
#include <vector>

using namespace std;

struct Bone: public D3DXFRAME
{
    D3DXMATRIX CombinedTransformationMatrix;
};

struct BoneMesh: public D3DXMESHCONTAINER
{
    ID3DXMesh* OriginalMesh;
    vector<D3DMATERIAL9> materials;
    vector<IDirect3DTexture9*> textures;

    DWORD NumAttributeGroups;
    D3DXATTRIBUTERANGE* attributeTable;
    D3DXMATRIX** boneMatrixPtrs;
    D3DXMATRIX* boneOffsetMatrices;
    D3DXMATRIX* currentBoneMatrices;
};

class SkinnedMesh
{
    public:
        SkinnedMesh();
        ~SkinnedMesh();
        void Load(const std::wstring& fileName);
        void Render(Bone *bone);

        void SetPose(D3DXMATRIX world);
        void GetAnimations(vector<string> &animations);

        ID3DXAnimationController* GetController();

    private:
        void UpdateMatrices(Bone* bone, D3DXMATRIX *parentMatrix);
        void SetupBoneMatrixPointers(Bone *bone);

        D3DXFRAME *m_pRootBone;
        ID3DXAnimationController *m_pAnimControl;

    
};

#endif

skinnedMesh.cpp


#include "skinnedMesh.h"
#include <fstream>

#pragma warning(disable:4996)

extern IDirect3DDevice9 *g_pDevice;
//extern ID3DXEffect *g_pEffect;
extern ofstream g_debug;

class BoneHierarchyLoader: public ID3DXAllocateHierarchy
{
    public:
        STDMETHOD(CreateFrame)(THIS_ LPCSTR Name, LPD3DXFRAME *ppNewFrame);
        STDMETHOD(CreateMeshContainer)(THIS_ LPCSTR Name, CONST D3DXMESHDATA * pMeshData, CONST D3DXMATERIAL * pMaterials, CONST D3DXEFFECTINSTANCE * pEffectInstances, DWORD NumMaterials, CONST DWORD * pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER * ppNewMeshContainer);
        STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree);
        STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER pMeshContainerBase);
};

HRESULT BoneHierarchyLoader::CreateFrame(LPCSTR Name, LPD3DXFRAME *ppNewFrame)
{
    Bone *newBone = new Bone;
    memset(newBone, 0, sizeof(Bone));

    //Copy name
    if(Name != NULL)
    {
        newBone->Name = new char[strlen(Name)+1];
        strcpy(newBone->Name, Name);
    }

    //Set the transformation matrices
    D3DXMatrixIdentity(&newBone->TransformationMatrix);
    D3DXMatrixIdentity(&newBone->CombinedTransformationMatrix);

    //Return the new bone...
    *ppNewFrame = (D3DXFRAME*)newBone;

    return S_OK;
}

HRESULT BoneHierarchyLoader::CreateMeshContainer(LPCSTR Name,
                                            CONST D3DXMESHDATA *pMeshData,
                                            CONST D3DXMATERIAL *pMaterials,
                                            CONST D3DXEFFECTINSTANCE *pEffectInstances,
                                            DWORD NumMaterials,
                                            CONST DWORD *pAdjacency,
                                            LPD3DXSKININFO pSkinInfo,
                                            LPD3DXMESHCONTAINER *ppNewMeshContainer)
{
    
    //Create new Bone Mesh
    BoneMesh *boneMesh = new BoneMesh;
    memset(boneMesh, 0, sizeof(BoneMesh));

    //Get mesh data
    boneMesh->OriginalMesh = pMeshData->pMesh;
    boneMesh->MeshData.pMesh = pMeshData->pMesh;
    boneMesh->MeshData.Type = pMeshData->Type;
    pMeshData->pMesh->AddRef();        //Add Reference so that the mesh isnt deallocated
    IDirect3DDevice9 *pDevice = NULL;    
    pMeshData->pMesh->GetDevice(&pDevice);    //Get g_pDevice ptr from mesh

    
    //Copy materials and load textures (just like with a static mesh)
    for(int i=0;i<(int)NumMaterials;i++)
    {
        D3DXMATERIAL mtrl;
        memcpy(&mtrl, &pMaterials[i], sizeof(D3DXMATERIAL));
        boneMesh->materials.push_back(mtrl.MatD3D);
        IDirect3DTexture9* newTexture = NULL;

        if(mtrl.pTextureFilename != NULL)
        {
            char textureFname[200];
            strcpy(textureFname, "resources/meshes/");
            strcat(textureFname, mtrl.pTextureFilename);

            //Load texture
            D3DXCreateTextureFromFileA(pDevice, textureFname, &newTexture);
        }

        boneMesh->textures.push_back(newTexture);
    }

    if(pSkinInfo != NULL)
    {
        //Get Skin Info
        boneMesh->pSkinInfo = pSkinInfo;
        pSkinInfo->AddRef();    //Add reference so that the SkinInfo isnt deallocated
        
        DWORD maxVertInfluences = 0;
        DWORD numBoneComboEntries = 0;
        ID3DXBuffer* boneComboTable = 0;

        pSkinInfo->ConvertToIndexedBlendedMesh(pMeshData->pMesh,
                                                D3DXMESH_MANAGED | D3DXMESH_WRITEONLY,  
                                                30,
                                                0, // ignore adjacency in
                                                0, // ignore adjacency out
                                                0, // ignore face remap
                                                0, // ignore vertex remap
                                                &maxVertInfluences,
                                                &numBoneComboEntries,
                                                &boneComboTable,
                                                &boneMesh->MeshData.pMesh);

        if(boneComboTable != NULL)
            boneComboTable->Release();

        //Get Attribute Table
        boneMesh->MeshData.pMesh->GetAttributeTable(NULL, &boneMesh->NumAttributeGroups);
        boneMesh->attributeTable = new D3DXATTRIBUTERANGE[boneMesh->NumAttributeGroups];
        boneMesh->MeshData.pMesh->GetAttributeTable(boneMesh->attributeTable, NULL);

        //Create bone offset and current matrices
        int NumBones = pSkinInfo->GetNumBones();
        boneMesh->boneOffsetMatrices = new D3DXMATRIX[NumBones];        
        boneMesh->currentBoneMatrices = new D3DXMATRIX[NumBones];

        //Get bone offset matrices
        for(int i=0;i < NumBones;i++)
            boneMesh->boneOffsetMatrices[i] = *(boneMesh->pSkinInfo->GetBoneOffsetMatrix(i));
    }

    //Set ppNewMeshContainer to the newly created boneMesh container
    *ppNewMeshContainer = boneMesh;
    
    return S_OK;
}

HRESULT BoneHierarchyLoader::DestroyFrame(LPD3DXFRAME pFrameToFree)
{
    if(pFrameToFree)
    {
        //Free name
        if(pFrameToFree->Name != NULL)
            delete [] pFrameToFree->Name;

        //Free bone
        delete pFrameToFree;
    }
    pFrameToFree = NULL;

    return S_OK;
}

HRESULT BoneHierarchyLoader::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase)
{
    BoneMesh *boneMesh = (BoneMesh*)pMeshContainerBase;

    //Release textures
    int numTextures = (int)boneMesh->textures.size();

    for(int i=0;i < numTextures;i++)
        if(boneMesh->textures[i] != NULL)
            boneMesh->textures[i]->Release();

    //Release mesh data
    if(boneMesh->MeshData.pMesh)boneMesh->MeshData.pMesh->Release();
    if(boneMesh->pSkinInfo)boneMesh->pSkinInfo->Release();
    if(boneMesh->OriginalMesh)boneMesh->OriginalMesh->Release();
    delete boneMesh;

    return S_OK;
}


//////////////////////////////////////////////////////////////////////////////////////////////////
//                                    SKINNED MESH                                                //
//////////////////////////////////////////////////////////////////////////////////////////////////

struct VERTEX{
    VERTEX();
    VERTEX(D3DXVECTOR3 pos, D3DCOLOR col){position = pos; color = col;}
    D3DXVECTOR3 position;
    D3DCOLOR color;
    static const DWORD FVF;
};

const DWORD VERTEX::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;

SkinnedMesh::SkinnedMesh()
{
    m_pRootBone = NULL;
    m_pAnimControl = NULL;
}

SkinnedMesh::~SkinnedMesh()
{
    //BoneHierarchyLoader boneHierarchy;
    ///boneHierarchy.DestroyFrame(m_pRootBone);
    BoneHierarchyLoader alloc;
    D3DXFrameDestroy(m_pRootBone, &alloc);
    if(m_pAnimControl)m_pAnimControl->Release();
}

void SkinnedMesh::Load(const std::wstring& fileName)
{
    BoneHierarchyLoader boneHierarchy;

    

    D3DXLoadMeshHierarchyFromX(fileName.c_str(), D3DXMESH_MANAGED,
                               g_pDevice, &boneHierarchy,
                               NULL, &m_pRootBone, &m_pAnimControl);

    SetupBoneMatrixPointers((Bone*)m_pRootBone);

    //Update all the bones
    D3DXMATRIX i;
    D3DXMatrixIdentity(&i);
    UpdateMatrices((Bone*)m_pRootBone, &i);
}

void SkinnedMesh::UpdateMatrices(Bone* bone, D3DXMATRIX *parentMatrix)
{
    if(bone == NULL)return;

    D3DXMatrixMultiply(&bone->CombinedTransformationMatrix,
                       &bone->TransformationMatrix,
                       parentMatrix);

    if(bone->pFrameSibling)UpdateMatrices((Bone*)bone->pFrameSibling, parentMatrix);
    if(bone->pFrameFirstChild)UpdateMatrices((Bone*)bone->pFrameFirstChild, &bone->CombinedTransformationMatrix);
}

void SkinnedMesh::Render(Bone *bone)
{
    /*
    if(bone == NULL)bone = (Bone*)m_pRootBone;

    //If there is a mesh to render...
    if(bone->pMeshContainer != NULL)
    {
        BoneMesh *boneMesh = (BoneMesh*)bone->pMeshContainer;

        if (boneMesh->pSkinInfo != NULL)
        {        
            // set up bone transforms
            int numBones = boneMesh->pSkinInfo->GetNumBones();
            for(int i=0;i < numBones;i++)
            {
                D3DXMatrixMultiply(&boneMesh->currentBoneMatrices[i],
                                   &boneMesh->boneOffsetMatrices[i],
                                   boneMesh->boneMatrixPtrs[i]);
            }

            D3DXMATRIX view, proj, identity;                
            g_pEffect->SetMatrixArray("FinalTransforms", boneMesh->currentBoneMatrices, boneMesh->pSkinInfo->GetNumBones());
            D3DXMatrixIdentity(&identity);

            //Render the mesh
            for(int i=0;i < (int)boneMesh->NumAttributeGroups;i++)
            {
                int mtrlIndex = boneMesh->attributeTable[i].AttribId;
                m_pDevice->SetMaterial(&(boneMesh->materials[mtrlIndex]));
                m_pDevice->SetTexture(0, boneMesh->textures[mtrlIndex]);
                g_pEffect->SetMatrix("matW", &identity);

                g_pEffect->SetTexture("texDiffuse", boneMesh->textures[mtrlIndex]);
                D3DXHANDLE hTech = g_pEffect->GetTechniqueByName("Skinning");
                g_pEffect->SetTechnique(hTech);
                g_pEffect->Begin(NULL, NULL);
                g_pEffect->BeginPass(0);

                boneMesh->MeshData.pMesh->DrawSubset(mtrlIndex);

                g_pEffect->EndPass();
                g_pEffect->End();
            }
        }
        else
        {
            //Normal Static Mesh
            g_pEffect->SetMatrix("matW", &bone->CombinedTransformationMatrix);

            D3DXHANDLE hTech = g_pEffect->GetTechniqueByName("Lighting");
            g_pEffect->SetTechnique(hTech);

            //Render the mesh
            int numMaterials = (int)boneMesh->materials.size();

            for(int i=0;i < numMaterials;i++)
            {
                m_pDevice->SetMaterial(&boneMesh->materials[i]);
                g_pEffect->SetTexture("texDiffuse", boneMesh->textures[i]);

                g_pEffect->Begin(NULL, NULL);
                g_pEffect->BeginPass(0);

                boneMesh->OriginalMesh->DrawSubset(i);

                g_pEffect->EndPass();
                g_pEffect->End();
            }
        }
    }
    */
    if(bone->pFrameSibling != NULL)Render((Bone*)bone->pFrameSibling);
    if(bone->pFrameFirstChild != NULL)Render((Bone*)bone->pFrameFirstChild);
}

void SkinnedMesh::SetupBoneMatrixPointers(Bone *bone)
{
    if(bone->pMeshContainer != NULL)
    {
        BoneMesh *boneMesh = (BoneMesh*)bone->pMeshContainer;

        if(boneMesh->pSkinInfo != NULL)
        {
            int NumBones = boneMesh->pSkinInfo->GetNumBones();
            boneMesh->boneMatrixPtrs = new D3DXMATRIX*[NumBones];

            for(int i=0;i < NumBones;i++)
            {
                Bone *b = (Bone*)D3DXFrameFind(m_pRootBone, boneMesh->pSkinInfo->GetBoneName(i));
                if(b != NULL)boneMesh->boneMatrixPtrs[i] = &b->CombinedTransformationMatrix;
                else boneMesh->boneMatrixPtrs[i] = NULL;
            }
        }
    }

    if(bone->pFrameSibling != NULL)SetupBoneMatrixPointers((Bone*)bone->pFrameSibling);
    if(bone->pFrameFirstChild != NULL)SetupBoneMatrixPointers((Bone*)bone->pFrameFirstChild);
}

void SkinnedMesh::SetPose(D3DXMATRIX world)
{
    UpdateMatrices((Bone*)m_pRootBone, &world);
}

void SkinnedMesh::GetAnimations(vector<string> &animations)
{
    ID3DXAnimationSet *anim = NULL;

    for(int i=0;i<(int)m_pAnimControl->GetMaxNumAnimationSets();i++)
    {
        anim = NULL;
        m_pAnimControl->GetAnimationSet(i, &anim);

        if(anim != NULL)
        {
            animations.push_back(anim->GetName());
            anim->Release();
        }
    }
}

ID3DXAnimationController* SkinnedMesh::GetController()
{
    ID3DXAnimationController* newAnimController = NULL;

    if(m_pAnimControl != NULL)
    {
        m_pAnimControl->CloneAnimationController(m_pAnimControl->GetMaxNumAnimationOutputs(),
                                                 m_pAnimControl->GetMaxNumAnimationSets(),
                                                 m_pAnimControl->GetMaxNumTracks(),
                                                 m_pAnimControl->GetMaxNumEvents(),
                                                 &newAnimController);
    }

    return newAnimController;
}

Advertisement

Visual Leak Detector, use it....

The memory management in that code looks extremely suspect. What's wrong with using delete?

Have you already tried this :

D3DX: Set HKLM\Software\Microsoft\Direct3D\D3DXBreakOnAllocId=0x2fd0 to debug

to receive more informations ?

When does your SkinnedMesh destructor run? It seems obvious that you've got a D3D resource leak rather than just a regular memory leak (so a regular memory leak detector will be no use whatsoever to you), so if your SkinnedMesh destructor is running after you Release the rest of your D3D objects, this can happen.

One way to work around this would be to AddRef your Device in the SkinnedMesh constructor, then Release it in the destructor; this will ensure proper lifetime management for the Device. You may probably also need to do so for your LPDIRECT3D9 too (generally I never use constructor/destructor logic for managing D3D objects as it can be prone to issues such as this, so I can't say anything more here).

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Hi, I have used Visual Leak Detector and removed most of the leaks.

But as mhagain said, the boneMesh is not released.

---------- Block 891 at 0x00CF8870: 8 bytes ----------
Call Stack:
d:\program files (x86)\microsoft visual studio 10.0\vc\include\xmemory (36): PerfectSim.exe!std::_Allocate<std::_Container_proxy> + 0x15 bytes
d:\program files (x86)\microsoft visual studio 10.0\vc\include\xmemory (187): PerfectSim.exe!std::allocator<std::_Container_proxy>::allocate + 0xB bytes
d:\program files (x86)\microsoft visual studio 10.0\vc\include\vector (442): PerfectSim.exe!std::_Vector_val<_D3DMATERIAL9,std::allocator<_D3DMATERIAL9> >::_Vector_val<_D3DMATERIAL9,std::allocator<_D3DMATERIAL9> > + 0xA bytes
d:\program files (x86)\microsoft visual studio 10.0\vc\include\vector (508): PerfectSim.exe!std::vector<_D3DMATERIAL9,std::allocator<_D3DMATERIAL9> >::vector<_D3DMATERIAL9,std::allocator<_D3DMATERIAL9> >
0x00E661A1 (File and line number not available): PerfectSim.exe!BoneMesh::BoneMesh + 0x31 bytes
d:\visual studio projects\perfectsim\perfectsim\skinnedmesh\skinnedmesh.cpp (52): PerfectSim.exe!BoneHierarchyLoader::CreateMeshContainer + 0x24 bytes
0x0F0A1E5D (File and line number not available): d3dx9d_43.dll!D3DXFrameNumNamedMatrices + 0xD3 bytes
0x0F0A1605 (File and line number not available): d3dx9d_43.dll!D3DXCreateKeyframedAnimationSet + 0x55B bytes
0x0F0A20AF (File and line number not available): d3dx9d_43.dll!D3DXFrameNumNamedMatrices + 0x325 bytes
0x0F0A327B (File and line number not available): d3dx9d_43.dll!D3DXFrameNumNamedMatrices + 0x14F1 bytes
0x0F0A3589 (File and line number not available): d3dx9d_43.dll!D3DXFrameNumNamedMatrices + 0x17FF bytes
0x0F0A367B (File and line number not available): d3dx9d_43.dll!D3DXLoadMeshHierarchyFromXW + 0x38 bytes
d:\visual studio projects\perfectsim\perfectsim\skinnedmesh\skinnedmesh.cpp (216): PerfectSim.exe!SkinnedMesh::Load
d:\visual studio projects\perfectsim\perfectsim\mydx9widget.h (39): PerfectSim.exe!myDX9Widget::initModels + 0x26 bytes
d:\visual studio projects\perfectsim\perfectsim\mydx9widget.h (132): PerfectSim.exe!myDX9Widget::initialize
d:\visual studio projects\perfectsim\perfectsim\perfectsim.cpp (26): PerfectSim.exe!PerfectSim::setCanvas
d:\visual studio projects\perfectsim\perfectsim\main.cpp (11): PerfectSim.exe!main + 0x6A bytes
d:\qt\4.8.0\src\winmain\qtmain_win.cpp (131): PerfectSim.exe!WinMain + 0x12 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (547): PerfectSim.exe!__tmainCRTStartup + 0x2C bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (371): PerfectSim.exe!WinMainCRTStartup
0x74C533CA (File and line number not available): kernel32.dll!BaseThreadInitThunk + 0x12 bytes
0x774D9ED2 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x63 bytes
0x774D9EA5 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x36 bytes
Data:
F8 87 CF 00 00 00 00 00 ........ ........


---------- Block 892 at 0x00CF88B8: 8 bytes ----------
Call Stack:
d:\program files (x86)\microsoft visual studio 10.0\vc\include\xmemory (36): PerfectSim.exe!std::_Allocate<std::_Container_proxy> + 0x15 bytes
d:\program files (x86)\microsoft visual studio 10.0\vc\include\xmemory (187): PerfectSim.exe!std::allocator<std::_Container_proxy>::allocate + 0xB bytes
d:\program files (x86)\microsoft visual studio 10.0\vc\include\vector (442): PerfectSim.exe!std::_Vector_val<IDirect3DTexture9 *,std::allocator<IDirect3DTexture9 *> >::_Vector_val<IDirect3DTexture9 *,std::allocator<IDirect3DTexture9 *> > + 0xA bytes
d:\program files (x86)\microsoft visual studio 10.0\vc\include\vector (508): PerfectSim.exe!std::vector<IDirect3DTexture9 *,std::allocator<IDirect3DTexture9 *> >::vector<IDirect3DTexture9 *,std::allocator<IDirect3DTexture9 *> >
0x00E661B3 (File and line number not available): PerfectSim.exe!BoneMesh::BoneMesh + 0x43 bytes
d:\visual studio projects\perfectsim\perfectsim\skinnedmesh\skinnedmesh.cpp (52): PerfectSim.exe!BoneHierarchyLoader::CreateMeshContainer + 0x24 bytes
0x0F0A1E5D (File and line number not available): d3dx9d_43.dll!D3DXFrameNumNamedMatrices + 0xD3 bytes
0x0F0A1605 (File and line number not available): d3dx9d_43.dll!D3DXCreateKeyframedAnimationSet + 0x55B bytes
0x0F0A20AF (File and line number not available): d3dx9d_43.dll!D3DXFrameNumNamedMatrices + 0x325 bytes
0x0F0A327B (File and line number not available): d3dx9d_43.dll!D3DXFrameNumNamedMatrices + 0x14F1 bytes
0x0F0A3589 (File and line number not available): d3dx9d_43.dll!D3DXFrameNumNamedMatrices + 0x17FF bytes
0x0F0A367B (File and line number not available): d3dx9d_43.dll!D3DXLoadMeshHierarchyFromXW + 0x38 bytes
d:\visual studio projects\perfectsim\perfectsim\skinnedmesh\skinnedmesh.cpp (216): PerfectSim.exe!SkinnedMesh::Load
d:\visual studio projects\perfectsim\perfectsim\mydx9widget.h (39): PerfectSim.exe!myDX9Widget::initModels + 0x26 bytes
d:\visual studio projects\perfectsim\perfectsim\mydx9widget.h (132): PerfectSim.exe!myDX9Widget::initialize
d:\visual studio projects\perfectsim\perfectsim\perfectsim.cpp (26): PerfectSim.exe!PerfectSim::setCanvas
d:\visual studio projects\perfectsim\perfectsim\main.cpp (11): PerfectSim.exe!main + 0x6A bytes
d:\qt\4.8.0\src\winmain\qtmain_win.cpp (131): PerfectSim.exe!WinMain + 0x12 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (547): PerfectSim.exe!__tmainCRTStartup + 0x2C bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (371): PerfectSim.exe!WinMainCRTStartup
0x74C533CA (File and line number not available): kernel32.dll!BaseThreadInitThunk + 0x12 bytes
0x774D9ED2 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x63 bytes
0x774D9EA5 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x36 bytes
Data:
0C 88 CF 00 00 00 00 00 ........ ........


Visual Leak Detector detected 2 memory leaks (88 bytes).
Largest number used: 38929 bytes.
Total allocations: 77172 bytes.


HRESULT BoneHierarchyLoader::CreateMeshContainer(LPCSTR Name,
                                            CONST D3DXMESHDATA *pMeshData,
                                            CONST D3DXMATERIAL *pMaterials,
                                            CONST D3DXEFFECTINSTANCE *pEffectInstances,
                                            DWORD NumMaterials,
                                            CONST DWORD *pAdjacency,
                                            LPD3DXSKININFO pSkinInfo,
                                            LPD3DXMESHCONTAINER *ppNewMeshContainer)
{
    
    //Create new Bone Mesh
    BoneMesh *boneMesh = new BoneMesh; <<<<<<<<<<< Leak here
    memset(boneMesh, 0, sizeof(BoneMesh));

HRESULT BoneHierarchyLoader::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase)
{
    BoneMesh *boneMesh = (BoneMesh*)pMeshContainerBase;

    //Release textures
    int numTextures = (int)boneMesh->textures.size();

    for(int i=0;i < numTextures;i++)
        if(boneMesh->textures[i] != NULL)
            boneMesh->textures[i]->Release();

    //Release mesh data
    if(boneMesh->MeshData.pMesh)boneMesh->MeshData.pMesh->Release();
    if(boneMesh->pSkinInfo)boneMesh->pSkinInfo->Release();
    if(boneMesh->OriginalMesh)boneMesh->OriginalMesh->Release();
    delete boneMesh; <<<<<<<<<<<<< I should have deleted it here.

    return S_OK;
}


HRESULT BoneHierarchyLoader::CreateMeshContainer(LPCSTR Name,
                                            CONST D3DXMESHDATA *pMeshData,
                                            CONST D3DXMATERIAL *pMaterials,
                                            CONST D3DXEFFECTINSTANCE *pEffectInstances,
                                            DWORD NumMaterials,
                                            CONST DWORD *pAdjacency,
                                            LPD3DXSKININFO pSkinInfo,
                                            LPD3DXMESHCONTAINER *ppNewMeshContainer)
{
    
    //Create new Bone Mesh
    BoneMesh *boneMesh = new BoneMesh; <<<<<<<<<<< Leak here
    memset(boneMesh, 0, sizeof(BoneMesh));

You probably shouldn't be memsetting your BoneMesh, it's not a POD (Plain Old Data) structure because it contains std::vectors. Who knows what happens if you memset those. Just FYI.

Hi patrrr,

Thanks for your info. But it still doesn't do the trick, the leak seems to deteriorate, growing to ~3000 bytes, after commenting out the line (memset)

Any further advice would be nice.

I wonder what the usages of these messages are.

they are enabled thru direct3d control panel

Direct3D9: :====> ENTER: DLLMAIN(0fa6d9a0): Process Detach 000015b4, tid=00001650
Direct3D9: (INFO) :MemFini!
Direct3D9: (ERROR) :Memory still allocated!  Alloc count = 131
Direct3D9: (ERROR) :Current Process (pid) = 000015b4

How can I track down Alloc count of 131?

Thanks

Jack

You can try this :

http://msdn.microsoft.com/en-us/library/w2fhc9a3(v=vs.80).aspx

At "

Procedure

To set a memory-allocation breakpoint in the Watch window "

But if the allocation number is not the same between each session, it will not help.

Edit : *Sigh* don't forget to copy-paste (v=vs.80).aspx in the URL.

I don't know much about Direct3D stuff, but this AddRef() method seems scary to me. According to MSDN:

Increments the reference count for an interface on an object. This
method should be called for every new copy of a pointer to an interface
on an object.

Doesn't that mean that AddRef() should be called every time you copy a pointer? So this thing here:

boneMesh->OriginalMesh = pMeshData->pMesh;
boneMesh->MeshData.pMesh = pMeshData->pMesh;
boneMesh->MeshData.Type = pMeshData->Type;
pMeshData->pMesh->AddRef(); //Add Reference so that the mesh isnt deallocated

You copied pMesh twice. Shouldn't you be calling AddRef() twice?

It has been confirmed about the leaks, it was because of the material and texture vectors.

Sorry again,

alnite, it still doesn't work.

But I am in doubt, while in the destroyMeshContainer method, the pMeshContainerBase is downcasted to BoneMesh.

That means that extra components in BoneMesh need to be taken care of.

Another thing is the original book has a texture attached with the sample. It was correctly loaded everytime the program runs.

Now I am using a mesh that doesn't have a texture....

Update:

I also find a 8-bytes-short memory allocation....

tried to delete the skinned mesh first, then the device to no avail

Thanks

Jack

This topic is closed to new replies.

Advertisement