Question

I am trying to learn some DirectX API and, for now, I have just a WINAPI window and a simple render function that displays a bitmap over the entire screen. My WINMAIN function:

LPDIRECT3D9 pD3D; // the Direct3D object
LPDIRECT3DDEVICE9 pd3dDevice; // the Direct3D device

// This is winmain, the main entry point for Windows applications
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, 
                    int nCmdShow) {
     hInst = hInstance;
     // Initialize the window
     if (!initWindow(hInstance)) return false;
     // called after creating the window
     if (!initDirect3D()) return false;
     // main message loop:
     MSG msg;
     ZeroMemory( &msg, sizeof( msg ) );
     while( msg.message != WM_QUIT) {
         if( PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) {
             TranslateMessage ( &msg );
             DispatchMessage ( &msg );
         } else {
             render();
         }
     }
     // Release the device and the Direct3D object
     if( pd3dDevice != NULL ) pd3dDevice->Release( );
     if( pD3D != NULL ) pD3D->Release( );
     return (int) msg.wParam;
}

and this is my render function:

void render(void) {
    IDirect3DSurface9* surface;
    pd3dDevice->CreateOffscreenPlainSurface(640, // the width of the surface to create
        480, // the height of the surface to create
        D3DFMT_X8R8G8B8, // the surface format
        D3DPOOL_DEFAULT, // the memory pool to use
        &surface, // holds the resulting surface
        NULL); // reserved
    D3DXLoadSurfaceFromFile(surface, NULL, NULL, L"test.bmp", NULL, D3DX_DEFAULT, 0, NULL);
    // This will hold the back buffer
    IDirect3DSurface9* backbuffer = NULL;
    // Check to make sure you have a valid Direct3D device
    if( NULL == pd3dDevice ) return;// Clear the back buffer to a blue color
    pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0,0,255 ), 1.0f, 0 );
    // Get the back buffer
    pd3dDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer );
    // Copy the offscreen surface to the back buffer
    // Note the use of NULL values for the source and destination RECTs
    // This ensures a copy of the entire surface to the back buffer
    pd3dDevice->StretchRect(surface, NULL, backbuffer, NULL, D3DTEXF_NONE );
    // Present the back buffer contents to the display
    pd3dDevice->Present( NULL, NULL, NULL, NULL );
}

So, the main problem is that when the render function is enabled (uncommented) the memory used by the application goes to 400 - 600 Mb in a second. Now, If I disabled (comment) the line from WinMain, the memory is left in 5 Mb but the processor goes crazy and the application uses about 50% of it. So, it looks like WinMain() uses a lot of processor and render() a lot of memory. Why? What am I forgetting?

Thanks!

Was it helpful?

Solution

pd3dDevice->CreateOffscreenPlainSurface(640, // the width of the surface to create
        480, // the height of the surface to create
        D3DFMT_X8R8G8B8, // the surface format
        D3DPOOL_DEFAULT, // the memory pool to use
        &surface, // holds the resulting surface
        NULL); // reserved
    D3DXLoadSurfaceFromFile(surface, NULL, NULL, L"test.bmp", NULL, D3DX_DEFAULT, 0, NULL);

You're calling this bit of code which creates resources a bazillion times, but you're not releasing it. It's in the render function which must be called at least 60 times a second (and if it lacks the sync with the vertical retrace, it can be called thousands of times a second, creating a huge problem for you). That means you change the pointer to the surface to a new block of surface memory with the same image and lose the address to the old (unreleased). Therefore, it causes a memory leak.

Shift that code into an initialization function of the application, not in the render function. (and make sure you manage it! When you stop using it, call the release function to lower the ref. count of the COM object so the memory can be claimed by the system (available to you, again))

Edit: This also needs to be moved to the init of the app, it's only needed once here

IDirect3DSurface9* backbuffer = NULL;
    // Check to make sure you have a valid Direct3D device
    if( NULL == pd3dDevice ) return;// Clear the back buffer to a blue color
    pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0,0,255 ), 1.0f, 0 );
    // Get the back buffer
    pd3dDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer );
    // Copy the offscreen surface to the back buffer
    // Note the use of NULL values for the source and destination RECTs
    // This ensures a copy of the entire surface to the back buffer
    pd3dDevice->StretchRect(surface, NULL, backbuffer, NULL, D3DTEXF_NONE );
    // Present the back buffer contents to the display

OTHER TIPS

The Processor usage is 50% is mainly due to frequent calling of while loop infinity times.

ex.,

while(TRUE)
{
}

This will check frequently, as you are instruction the processor to concentrate this as the condition is true. if you are using 4 core processor, one of the processor will completely focus to this process, in my case I used 4 cores, thus my cpu usage is 25%. I think you are using 2 core processor.

while(TRUE)
{
Sleep(1);
}

This will resolve your processor problem.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top