microsoft / DirectXTK

The DirectX Tool Kit (aka DirectXTK) is a collection of helper classes for writing DirectX 11.x code in C++
https://walbourn.github.io/directxtk/
MIT License
2.55k stars 506 forks source link

DirectXTK Sprites Init Crash #23

Closed Tonyx97 closed 8 years ago

Tonyx97 commented 8 years ago

Hello guys! I'm desperated to fix this error. My renderer is DX11 and I've already included all headers and the DirectXTK.lib so the problem is when my program reachs this code in runtime 6a5cf6e1439f7facb5d8b192510daad9.png https://gyazo.com/6a5cf6e1439f7facb5d8b192510daad9

where pSpriteBatch is defined like this: std::unique_ptr<SpriteBatch> pSpriteBatch; This is the DXInitializer:

void DX11Renderer::InitDevice()
{
DXGI_SWAP_CHAIN_DESC scd;

ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
scd.BufferCount = 1;  
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
scd.BufferDesc.Width = ScreenX;
scd.BufferDesc.Height = ScreenY;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd.OutputWindow = DXWindow;
scd.SampleDesc.Count = 4;
scd.Windowed = TRUE;
scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

///DEVICE INIT
D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL, D3D11_SDK_VERSION, &scd, &DX11SwapChain, &DX11Device, NULL, &DX11DeviceContext);

DX11SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&BackBuffer);

DX11Device->CreateRenderTargetView(BackBuffer, NULL, &DX11RenderTargetView);
BackBuffer->Release();

DX11DeviceContext->OMSetRenderTargets(1, &DX11RenderTargetView, NULL);

///VIEWPORT INIT
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));

viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = ScreenX;
viewport.Height = ScreenY;

DX11DeviceContext->RSSetViewports(1, &viewport);

///FONTS INIT
pSpriteBatch.reset(new SpriteBatch(DX11DeviceContext)); // <<-- crash
pPurista12.reset(new SpriteFont(DX11Device, L"font.spritefont"));

///BUFFER INIT
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));

bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = sizeof(VERTEX) * 30;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

DX11Device->CreateBuffer(&bd, NULL, &VertexBuffer);

///BLEND INIT

///SHADER INIT
InitRenderShaders();
}

When it reachs the line it shows me this exception 02589a97c1d19a0e5a02aaae9103ecd1.png https://gyazo.com/02589a97c1d19a0e5a02aaae9103ecd1

and this is the breakpoint details 5aca89f56827d44d5a938b412aef40f9.png https://gyazo.com/5aca89f56827d44d5a938b412aef40f9

To be specific, the code will crash when it reachs this code from the file 'mutex.c': 5a320b954b101b87e97fa7623913ad1a.png https://gyazo.com/5a320b954b101b87e97fa7623913ad1a

Does anybody any idea why this happens? I'm building it as Release in x64 bits. Thanks in advance.

walbourn commented 8 years ago

So there are a lot of places where your code could have gone wrong, but your code is not checking for failed HRESULTs. For example D3D11CreateDeviceAndSwapChain could have failed immediately and you have no indication of that until you crashed later. As such, I suspect your problem is indeed that your DX11DeviceContext is invalid at the time you try to set up your SpriteBatch.

You should either make use of the DX::ThrowIfFailed helper and make your code looks something like:

DX::ThrowIfFailed(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL, D3D11_SDK_VERSION, &scd, &DX11SwapChain, &DX11Device, NULL, &DX11DeviceContext));

Or you should use the FAILED and SUCCEEDED macros directly like:

HRESULT hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL, D3D11_SDK_VERSION, &scd, &DX11SwapChain, &DX11Device, NULL, &DX11DeviceContext);
if (FAILED(hr))
    // error

Note that you should also consider making use of Microsoft::WRL::ComPtr which avoids the need to manually use AddRef and Release calls when working with COM objects.

Microsoft::WRL::ComPtr<ID3D11Texture2D> BackBuffer;
DX::ThrowIfFailed(DX11SwapChain->GetBuffer(0, IID_PPV_ARGS(BackBuffer.GetAddressOf())));
DX11Device->CreateRenderTargetView(BackBuffer.Get(), NULL, &DX11RenderTargetView);

You should take a little time to work through the tutorials and read this topic and this topic in particular.