0 Replies Latest reply on Sep 7, 2010 1:33 PM by amn3sia

    Direct3D process handle leak (sample code included)

    amn3sia

      Intel 945G chipset with latest drivers (6.14.10.4926)

      Windows XP SP3

       

      I have an application that is having a similar problem to the thread I found here:

      http://communities.intel.com/message/95268#95268

       

      The application I have is also for video surveillance, but I'm seeing it with a smaller number of HD resolution cameras (1920x1080). I was able to debug the application and trace the leaks down to some Direct3D calls both when allocating memory and releasing some Direct3D objects as well.

       

      I wrote a quick sample app that I'm able to reproduce the issue on. Basically I just keep creating 1920x1080 swap chains until it fails (typically due to not enough video memory) and you will see that there are 10 process handles created at that point (using SysInternals handle.exe). Then after releasing all the swap chains created there will be 16 process handles. These process handles will remain for the duration of the application even though everything was properly released. Not only does this happen when it runs out of memory and causes the the D3DERR_OUTOFVIDEOMEMORY, but several calls before the out of memory failure you will see process handles getting created that will never be released. For instance, in my case the 6th call to CreateAdditionalSwapChain succeeds but creates a process handle and all additional calls do the same up until the 12th call which fails and creates 5 process handles.

       

       

      Please let me know if there is any additional information I can provide.

       

      Here is the sample code I am able to reproduce the issue with:

       

       

      void PerformDirect3DTest(HWND hWnd)

      {

      HRESULT hr = S_OK;

      CComPtr<IDirect3D9> d3d = NULL;

      CComPtr<IDirect3DDevice9> d3d_device = NULL;

      d3d.Attach(Direct3DCreate9(D3D_SDK_VERSION));

       

      // see what we can do with the graphics hardware before we try to do anything

      D3DCAPS9 dxcaps;

      D3DDEVTYPE devtype = D3DDEVTYPE_HAL;

      DWORD dwFlags = D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE;

      hr = d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, devtype, &dxcaps);

       

      // If device doesn't support HW T&L or doesn't support 1.1 vertex

      // shaders in HW, then switch to SWVP.

      if (((dxcaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0) || (dxcaps.VertexShaderVersion < D3DVS_VERSION(1,1)))

      dwFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;

      else

      dwFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;

       

      // Try to create the D3D device we need

      D3DPRESENT_PARAMETERS d3dParam;

      memset(&d3dParam, 0, sizeof(D3DPRESENT_PARAMETERS));

      d3dParam.Windowed = true;

       

      // since we use an additional swap chain we don't need the default backbuffer to be very big

      d3dParam.BackBufferWidth = 1;

      d3dParam.BackBufferHeight = 1;

      d3dParam.BackBufferCount = 1;

      d3dParam.SwapEffect = D3DSWAPEFFECT_DISCARD;

      d3dParam.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

       

      // this is the window handle of the renderer's video window

      d3dParam.hDeviceWindow = hWnd;

       

      // try to create a device to use based on the type and behaviour we figured out back in the constructor

      hr = d3d->CreateDevice(D3DADAPTER_DEFAULT, devtype, NULL, dwFlags, &d3dParam, &d3d_device);

      if (FAILED(hr))

      return;

       

      // Turn off alpha blending

      if (FAILED(hr = d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE)))

      DXTRACE_ERR(TEXT("DirectX call SetRenderState failed"), hr);

       

      // Set a larger backbuffer size for creating our swap chains

      d3dParam.BackBufferWidth = 1920;

      d3dParam.BackBufferHeight = 1080;

       

      // Create swap chains until we run out of memory

      CComPtr<IDirect3DSwapChain9> *pSwapChains = new CComPtr<IDirect3DSwapChain9>[256];

      for (int i = 0; i < 256; i++)

      {

      // Create a new swap chain to use

      hr = d3d_device->CreateAdditionalSwapChain(&d3dParam, &pSwapChains[i]);

      if (FAILED(hr))

      {

      DXTRACE_ERR(TEXT("DirectX call CreateAdditionalSwapChain failed"), hr);

      break;

      }

      }

       

      // Delete our array of swap chains which will also release them

      delete [] pSwapChains;

      pSwapChains = NULL;

       

      // Not necessary since we're going out of scope, but we'll release anyway

      d3d_device.Release();

      d3d.Release();

      }