2016-12-15 6 views
1

私はいくつかのチュートリアルを実行してDirectXを学習してきましたが、何か入力するたびにDirectXは機能しません。ここで私は研究の時間後に修正することはできません最新のエラーの例です:デバッグDirectXコード

 //Header.h 
    static HWND hWnd; 
    static IDXGISwapChain* swapChain; 
    static ID3D11Device* dev; 
    static ID3D11DeviceContext* devCon; 
    static ID3D11RenderTargetView* renderTarget; 

    //DirectX.cpp 
    bool InitD3D11(HINSTANCE hInst) 
{ 
    HRESULT hr; 
    DXGI_MODE_DESC bufferDesc; 
    ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC)); 
    bufferDesc.Width = 800; 
    bufferDesc.Height = 600; 
    bufferDesc.RefreshRate.Numerator = 60; 
    bufferDesc.RefreshRate.Denominator = 1; 
    bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 
    bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; 
    bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; 

    DXGI_SWAP_CHAIN_DESC swapChainDesc; 
    ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC)); 
    swapChainDesc.BufferDesc = bufferDesc; 
    swapChainDesc.SampleDesc.Count = 1; 
    swapChainDesc.SampleDesc.Quality = 0; 
    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 
    swapChainDesc.BufferCount = 1; 
    swapChainDesc.OutputWindow = hWnd; 
    swapChainDesc.Windowed = true; 
    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; 

    hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL, D3D11_SDK_VERSION, &swapChainDesc, &swapChain, &dev, NULL, &devCon); 

    ID3D11Texture2D* backBuffer; 
    hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&backBuffer); 
    hr = dev->CreateRenderTargetView(backBuffer, NULL, &renderTarget); 
    backBuffer->Release(); 
    devCon->OMSetRenderTargets(1, &renderTarget, NULL); 
    return true; 
} 
//This is not the full code - I linked directx and lib files and stuff like that. 
//If I copy and paste code from tutorials, everything runs fine 

私はInitD3d11を呼び出すたびに、私はswapChainがNULLポインタであるというエラーを取得します。私は、bufferDescおよび/またはswapChainDescがいくつかの無効なデータを持っていると仮定していますが、コンパイラはエラーを原因とする何か手がかりを私に与えることはできません。誰かがこのようなエラーを追跡し修正する方法を教えてください。ありがとう。

答えて

3

HRESULTの値をチェックしていないので、すべてのエラー処理が欠落しています。 COMプログラミングの場合、Direct3Dを使用しても、でなければならないすべてのメソッドのHRESULTを確認する必要があります。戻り値が無視しても安全な場合は、代わりにvoidを返します。

古い学校のC/C++プログラムでHRESULTの値を確認するには、FAILEDまたはSUCCEEDEDマクロを使用します。多くの場合

hr = D3D11CreateDeviceAndSwapChain(/* ... */ *); 
if (FAILED(hr)) 
    return false; 

、失敗したHRESULTは「フェイルファスト」または致命的なエラーとして扱われます。言い換えれば、呼び出しが失敗した場合、プログラムは処理を続行できません。

他のケースでは、おそらく異なるオプションを使用してエラーから回復する特別なケースの処理があります。詳細な例については、Anatomy of Direct3D 11 Create Deviceを参照してください。レガシーDXUTフレームワークに基づいて古いMicrosoftサンプルで

、エラー処理は、いくつかの追跡や&致命的な終了をトレースをしたVV_RETURNようなマクロで行われました。現代のC++サンプルで

、我々は実際にfast-failシナリオの失敗HRESULT上のC++例外を生成するヘルパーDX::ThrowIfFailedを使用しています。これは、コードをより合理的で読みやすくなります:

DX::ThrowIfFailed(
    D3D11CreateDeviceAndSwapChain(/* ... */ *) 
); 

機能自体は次のように定義されています

#include <exception> 

namespace DX 
{ 
    inline void ThrowIfFailed(HRESULT hr) 
    { 
     if (FAILED(hr)) 
     { 
      // Set a breakpoint on this line to catch DirectX API errors 
      throw std::exception(); 
     } 
    } 
} 

あなたのプログラムは、デフォルトのVisual Studioテンプレートで、すでにある/EHscしてコンパイルする必要があります。詳細は、this topic pageを参照してください。

上記のコードスニペットから、かなり古い学校のチュートリアルに従っています。 DirectX 11の開発でさえ多くの変更があり、古いチュートリアルのほとんどは混乱の原因となります。 DirectXを初めてお使いになる方は、まずDirectX Tool Kittutorialsをご覧ください。その後、「モダンな」Direct3Dをよりよく理解して古いチュートリアルに戻り、古いものからより関連性の高い情報を抽出することができます。すべてのHRESULTS、あなたがすべき次の事を確認した後

は、出力ウィンドウ内の余分なデバッグ情報を提供してDirect3Dのデバッグ層を有効です。

DWORD createDeviceFlags = 0; 
#ifdef _DEBUG 
    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; 
#endif 

hr = D3D11CreateDeviceAndSwapChain(
    nullptr, D3D_DRIVER_TYPE_HARDWARE, 
    nullptr, createDeviceFlags, nullptr, 
    0, D3D11_SDK_VERSION, 
    &swapChainDesc, &swapChain, &dev, nullptr, &devCon); 

あなたは、私が代わりに古い学校NULLのビジュアルC++ 2010以降でサポートされているC++ 11 nullptrを使用しています注意してください。それはタイプされているからです。バージョンの2つの場所でNULLを使用していましたが、パラメータが実際にはポインタではありませんでした。数字です。

これで、スワップチェーンが作成できない理由を診断するのに役立つ基本的なエラーに関する多くのフィードバックを得ることができます。ウィンドウズモード(bufferDesc.RefreshRate)ではなく、「排他的フルスクリーンモード」でのみ意味のあるいくつかの値を提供しているからです。代わりに、試してみてください。これは={};構文で0に構造体を初期化しますVS 2013やVS 2015上で動作します

DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; 
swapChainDesc.BufferDesc.Width = 800; 
swapChainDesc.BufferDesc.Height = 600; 
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 
swapChainDesc.SampleDesc.Count = 1; 
swapChainDesc.SampleDesc.Quality = 0; 
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 
swapChainDesc.BufferCount = 1; 
swapChainDesc.OutputWindow = hWnd; 
swapChainDesc.Windowed = TRUE; 
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; 

。旧式のコンパイラでは、上の旧式コードのようにZeroMemoryを使用する必要があります。

D3D11_CREATE_DEVICE_DEBUGを使用すると、開発者のみが使用するデバッグデバイスがないシステムでは失敗することに注意してください。デバッグデバイスレイヤの取得場所に関する詳細は、使用しているWindowsのバージョンによって異なります。下部に小さなサマリーテーブルがあるDirect3D SDK Debug Layer Tricksを参照してください。

また、初期化されていない変数の存在下でのデバッグは、大きな苦痛です。初期化されていないポインタは、特に大きな時間を浪費することがあります。

さらに良い
static HWND hWnd = nullptr; 
static IDXGISwapChain* swapChain = nullptr; 
static ID3D11Device* dev = nullptr; 
static ID3D11DeviceContext* devCon = nullptr; 
static ID3D11RenderTargetView* renderTarget = nullptr; 

、代わりにあなたのCOMオブジェクトの生のポインタを使用しての、あなたはMicrosoft::WRL::ComPtrのようなC++スマートポインタを使用する必要があります:あなたは、以下のなかった場合には役立つだろう。詳細はthis topic pageを参照してください。私たちの現代のサンプルはそれを使用しています。これは単なるC++テンプレートなので、WindowsのStore、UWP、およびXbox Oneのアプリケーションだけでなく、従来のWin32デスクトップアプリケーションでも機能します。