Ralf's profileFun with GPUsBlogLists Tools Help

Blog


    July 02

    NV PerfHUD and Direct3D 10.1

    As nvidia doesn’t have Direct3D 10.1 compatible hardware yet it isn’t a surprise that PerfHUD doesn’t support this updated Version. This includes the case were the Direct3D 10.1 runtime is only used to create a 10.1 techlevel device. Therefore it is necessary to create Direct3D 10.0 devices with the Direct3D 10.0 runtime if you still want to use PerfHUD. This might not a big deal anyway as the same code is required if the application should run on Vista without installed Service Pack.

    But there is another problem. If you use DXGI to enumerate over the adapters and pass them to D3D10CreateDevice1 to check if Direct3D 10.1 is supported you risk an access violation.

    IDXGIAdapter* pAdapter;

    int AdapterID = 0;

     

    while (m_pFactory->EnumAdapters (AdapterID, &pAdapter) == S_OK)

    {

          D3D10_DRIVER_TYPE driverType = D3D10_DRIVER_TYPE_HARDWARE;

     

          DXGI_ADAPTER_DESC Desc;

     

          if (pAdapter->GetDesc (&Desc) == S_OK &&

             (wcscmp(Desc.Description, L"NVIDIA PerfHUD") == 0))

            driverType = D3D10_DRIVER_TYPE_REFERENCE;

     

          ID3D10Device1* pDevice1 = NULL;

     

          //Expect this to crash if run with PerfHUD

          if (D3D10CreateDevice1 (pAdapter,

    driverType,

    NULL,

    0,

    D3D10_FEATURE_LEVEL_10_1,

    D3D10_1_SDK_VERSION,

    &pDevice1) == S_OK)

          {

                pDevice1->Release ();

                OnAdapterSupportD3D10_1 (pAdapter);

          }

     

          ID3D10Device* pDevice = NULL;

     

          if (D3D10CreateDevice  (pAdapter,

    driverType,

    NULL,

    0,

    D3D10_SDK_VERSION,

    &pDevice) == S_OK)

          {

                pDevice->Release ();

                OnAdapterSupportD3D10 (pAdapter);

          }

     

    AdapterID++;

    }

    As PerfHUD hook Direct3D 10 and DXGI the returned adapter interfaces differs from that one that an unhooked DXGI returns. The Direct3D 10.1 runtime assumes that the adapter interfaces are unmodified and therefore doesn’t check them very well.

    An attempt to work around this limitation would be to ignore the PerfHUD adapter when it comes to the Dirtect3D 10.1 test creation.

    IDXGIAdapter* pAdapter;

    int AdapterID = 0;

     

    while (m_pFactory->EnumAdapters (AdapterID, &pAdapter) == S_OK)

    {

          D3D10_DRIVER_TYPE driverType = D3D10_DRIVER_TYPE_HARDWARE;

     

          DXGI_ADAPTER_DESC Desc;

     

          if (pAdapter->GetDesc (&Desc) == S_OK &&

             (wcscmp(Desc.Description, L"NVIDIA PerfHUD") == 0))

          {

            driverType = D3D10_DRIVER_TYPE_REFERENCE;

          }

          else

          {

                ID3D10Device1* pDevice1 = NULL;

     

                if (D3D10CreateDevice1 (pAdapter,

                                       driverType,

                                       NULL,

                                       0,

                                       D3D10_FEATURE_LEVEL_10_1,

                                       D3D10_1_SDK_VERSION,

                                       &pDevice1) == S_OK)

                {

                      pDevice1->Release ();

                      OnAdapterSupportD3D10_1 (pAdapter);

                }

          }

     

          ID3D10Device* pDevice = NULL;

     

          if (D3D10CreateDevice  (pAdapter,

    driverType,

    NULL,

    0,

    D3D10_SDK_VERSION,

    &pDevice) == S_OK)

          {

                pDevice->Release ();

                OnAdapterSupportD3D10 (pAdapter);

          }

     

          AdapterID++;

    }

     

    But this would still crash at the same place. The reason for this is that PerfHUD modifies all adapter interfaces and not only add an additional one. This lead to a working solution

    // Test all adapter once to look for PerfHUD

    bool PerfHUD = false;

     

    int AdapterID = 0;

    IDXGIAdapter* pAdapter;

     

    while (m_pFactory->EnumAdapters (AdapterID, &pAdapter) == S_OK)

    {

          DXGI_ADAPTER_DESC Desc;

     

          if (pAdapter->GetDesc (&Desc) == S_OK &&

             (wcscmp(Desc.Description, L"NVIDIA PerfHUD") == 0))

            PerfHUD = true;

     

          pAdapter->Release();

          AdapterID++;

    }

     

    while (m_pFactory->EnumAdapters (AdapterID, &pAdapter) == S_OK)

    {

          D3D10_DRIVER_TYPE driverType = D3D10_DRIVER_TYPE_HARDWARE;

     

          DXGI_ADAPTER_DESC Desc;

     

          if (pAdapter->GetDesc (&Desc) == S_OK &&

             (wcscmp(Desc.Description, L"NVIDIA PerfHUD") == 0))

          {

                driverType = D3D10_DRIVER_TYPE_REFERENCE;

          }

     

          If (!PerfHUD)

    {

                ID3D10Device1* pDevice1 = NULL;

     

                if (D3D10CreateDevice1 (pAdapter,

                                       driverType,

                                       NULL,

                                       0,

                                       D3D10_FEATURE_LEVEL_10_1,

                                       D3D10_1_SDK_VERSION,

                                       &pDevice1) == S_OK)

                {

                      pDevice1->Release ();

                      OnAdapterSupportD3D10_1 (pAdapter);

                }

          }

     

          ID3D10Device* pDevice = NULL;

     

          if (D3D10CreateDevice  (pAdapter,

    driverType,

    NULL,

    0,

    D3D10_SDK_VERSION,

    &pDevice) == S_OK)

          {

                pDevice->Release ();

                OnAdapterSupportD3D10 (pAdapter);

          }

     

          AdapterID++;

    }

     

    Finnaly don’t forget to remove all PerfHUD code in your release version if you don’t want that others can run your application with PerfHUD.