Jump to content
  • Advertisement
Sign in to follow this  
thk123

DX11 [DirectX] Beginning DX Learning - SwapChain::Present crashes program and driver

This topic is 2843 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, I am just starting out with Direct X 11. I have been following these tutorials but I am stuck at the first lesson with actual rendering (drawing a triangle). Specifically, my program crashes when I reach the present line. Actually, it doesn't crash but my computer freezes up, then the screen goes blank, then comes back on with a message saying my display driver has crashed and my program doesn't do anything more. I have updated my drivers and my graphics card is running Direct X 11. Heres the code

#include <Windows.h>
#include <WindowsX.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>

#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "d3dx11.lib")
#pragma comment (lib, "d3dx10.lib")

#define ScreenWidth 800
#define ScreenHeight 600

IDXGISwapChain *swapChain;
ID3D11Device *device;
ID3D11DeviceContext *devcon;
ID3D11RenderTargetView *backBuffer;

ID3D11VertexShader *mVertexShader;
ID3D11PixelShader *mPixelShader;

ID3D11Buffer *mVideoBuffer;
ID3D11InputLayout *mInputLayout;

struct Vertex
{
float x, y, z;
D3DXCOLOR Color;
};


void Init3D(HWND windowHandle);
void RenderFrame();
void Clean3D();
void InitGraphics();
void InitPipeline();

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
//MessageBox(NULL, "Hello world","My Window", MB_OK);
HWND windowHandle;
WNDCLASSEX windowClass;

ZeroMemory(&windowClass, sizeof(WNDCLASSEX));

windowClass.cbSize = sizeof(WNDCLASSEX);
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = WindowProc;
windowClass.hInstance = hInstance;
windowClass.hCursor = LoadCursor(NULL,IDC_ARROW);
//windowClass.hbrBackground = (HBRUSH)COLOR_WINDOW;
windowClass.lpszClassName = "WindowClass1";

RegisterClassEx(&windowClass);

RECT desiredSize = {0,0,500,400};
AdjustWindowRect(&desiredSize,WS_OVERLAPPEDWINDOW, FALSE);

windowHandle = CreateWindowEx(NULL,"WindowClass1","TK Program", WS_OVERLAPPEDWINDOW,0,0,ScreenWidth,ScreenHeight,NULL, NULL, hInstance, NULL);

ShowWindow(windowHandle, nCmdShow);

Init3D(windowHandle);

MSG msg = {0};

while(true)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);

if(msg.message == WM_QUIT)
{
break;
}

//do some game related stuff
}
RenderFrame();
}
Clean3D();
return msg.wParam;
}

LRESULT CALLBACK WindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;

}break;
}

return DefWindowProc (hWnd, message,wParam,lParam);
}

void Init3D(HWND windowHandle)
{
DXGI_SWAP_CHAIN_DESC swapChainDescription;
ZeroMemory(&swapChainDescription, sizeof(DXGI_SWAP_CHAIN_DESC));

swapChainDescription.BufferCount = 1;
swapChainDescription.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDescription.BufferDesc.Width = ScreenWidth;
swapChainDescription.BufferDesc.Height = ScreenHeight;
swapChainDescription.OutputWindow = windowHandle;
swapChainDescription.SampleDesc.Count = 4;
swapChainDescription.Windowed = true;
swapChainDescription.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

D3D11CreateDeviceAndSwapChain(NULL,D3D_DRIVER_TYPE_HARDWARE,NULL,NULL,NULL,NULL, D3D11_SDK_VERSION,&swapChainDescription, &swapChain,&device,NULL,&devcon);

ID3D11Texture2D *pBackBuffer = NULL;
swapChain->GetBuffer(0,__uuidof(ID3D11Texture2D),(LPVOID*)&pBackBuffer);
device->CreateRenderTargetView(pBackBuffer, NULL, &backBuffer);
pBackBuffer->Release();

devcon->OMSetRenderTargets(1, &backBuffer,NULL);

D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));

viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = ScreenWidth;
viewport.Height = ScreenHeight;

devcon->RSSetViewports(1,&viewport);

InitGraphics();
InitPipeline();
}

void InitPipeline()
{
ID3D10Blob *vertexShader, *pixelShader;
D3DX11CompileFromFile("Shaders.hlsl",0,0,"VShader","vs_5_0",0,0,0,&vertexShader,0,0);
D3DX11CompileFromFile("Shaders.hlsl",0,0,"PShader","ps_5_0",0,0,0,&pixelShader,0,0);

device->CreateVertexShader(vertexShader->GetBufferPointer(),vertexShader->GetBufferSize(),NULL,&mVertexShader);
device->CreatePixelShader(pixelShader->GetBufferPointer(),pixelShader->GetBufferSize(),NULL,&mPixelShader);

devcon->VSSetShader(mVertexShader,0,0);
devcon->PSSetShader(mPixelShader,0,0);

D3D11_INPUT_ELEMENT_DESC inputElementDesc[] =
{
{"POSITION",0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA,0},
{"COLOR",0,DXGI_FORMAT_R32G32B32_FLOAT, 0,12,D3D11_INPUT_PER_VERTEX_DATA,0},
};

device->CreateInputLayout(inputElementDesc,2,vertexShader->GetBufferPointer(),vertexShader->GetBufferSize(),&mInputLayout);
devcon->IASetInputLayout(mInputLayout);
}

void InitGraphics()
{
Vertex OurVertices[] = {{0.0f, 0.5f, 0.0f, D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f)},
{0.45f, -0.5, 0.0f, D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f)},
{-0.45f, -0.5f, 0.0f, D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f)},
{0.7f,0.6f,0.3f,D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f)}
};
D3D11_BUFFER_DESC bufferDescription;
ZeroMemory(&bufferDescription,sizeof(D3D11_BUFFER_DESC));

bufferDescription.Usage = D3D11_USAGE_DYNAMIC;
bufferDescription.ByteWidth = 3 * sizeof(Vertex);
bufferDescription.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

device->CreateBuffer(&bufferDescription,NULL,&mVideoBuffer);

D3D11_MAPPED_SUBRESOURCE mappedSubResource;
devcon->Map(mVideoBuffer,NULL,D3D11_MAP_WRITE_DISCARD,NULL, &mappedSubResource);
memcpy(mappedSubResource.pData,OurVertices,sizeof(OurVertices));
devcon->Unmap(mVideoBuffer,NULL);
}

void RenderFrame()
{
devcon->ClearRenderTargetView(backBuffer, D3DXCOLOR(0.0f,0.2f,0.4f,1.0f));

UINT stride = sizeof(Vertex);
UINT offset = 0;
devcon->IASetVertexBuffers(0,1,&mVideoBuffer,&stride,&offset);
devcon->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
devcon->Draw(3,0);

swapChain->Present(0,0);
}

void Clean3D()
{
swapChain->SetFullscreenState(false,NULL);

mPixelShader->Release();
mVertexShader->Release();
swapChain->Release();
backBuffer->Release();
device->Release();
devcon->Release();
}

Share this post


Link to post
Share on other sites
Advertisement
Use the flag D3D11_CREATE_DEVICE_DEBUG for the flags in D3D11CreateDeviceAndSwapChain, and then run with the debugger. You should get debug output if anything is wrong. Overall your code is unsafe as you don't seem to be checking any return values at all. D3D11 functions usually return a HRESULT value which will tell you if they failed.

Share this post


Link to post
Share on other sites

Use the flag D3D11_CREATE_DEVICE_DEBUG for the flags in D3D11CreateDeviceAndSwapChain, and then run with the debugger. You should get debug output if anything is wrong. Overall your code is unsafe as you don't seem to be checking any return values at all. D3D11 functions usually return a HRESULT value which will tell you if they failed.


Ok so I put in HRESULT results in front of all the methods that return HRESULT and the problem appear to be with the shader creation which returns "E_INVALIDARG". If I'm honest, the shader part was something the tutorial glossed over. What I did to incorporate the shader was add a file called "Shaders.hlsl" in to the source folder of the solution containing:

struct VOut
{
float4 position : SV_POSITION;
float4 color : COLOR;
};

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
VOut output;

output.position = position;
output.color = color;

return output;
}


float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
return color;
}


The shader loading code is:

ID3D10Blob *vertexShader, *pixelShader;
D3DX11CompileFromFile("Shaders.hlsl",0,0,"VShader","vs_5_0",0,0,0,&vertexShader,0,0);
D3DX11CompileFromFile("Shaders.hlsl",0,0,"PShader","ps_5_0",0,0,0,&pixelShader,0,0);
LPVOID vertexBufferPointer = vertexShader->GetBufferPointer();
SIZE_T vertexBufferSize = vertexShader->GetBufferSize();
//HRESULT result = device->CreateVertexShader(vertexShader->GetBufferPointer(),vertexShader->GetBufferSize(),NULL,&mVertexShader);
HRESULT result = device->CreateVertexShader(vertexBufferPointer, vertexBufferSize,NULL,&mVertexShader);
result = device->CreatePixelShader(pixelShader->GetBufferPointer(),pixelShader->GetBufferSize(),NULL,&mPixelShader);


Is this where I am going wrong? Also, on a more general note, At each of the HRESULT points, should I be checking that they're ok before continuing? Would hate to be picking up bad practices when I have hardly begun!

Share this post


Link to post
Share on other sites
Yes, generally you want to check as much as possible, or at least methods that are somewhat likely to fail. Compiling shaders is one of those. Does it fail at CreateVertexShader or CreatePixelShader?
If you have a DX11 capable card that is somewhat strange, if D3DX11CompileFromFile succeeds. D3DX11CompileFromFile also returns a HRESULT, and the last parameter can give you compile errors for the shader.

Did you use the debug flag when creating your device?
If you try to call a D3D11 method and have some invalid parameters you will get debug output in the 'Output' window when running with the debugger, which will tell you what's wrong. In VC++, just press F5 to run with the debugger, and make sure to select Debug in the target menu, which should be the default if you didn't change it to Release.

Anyway, to correctly check for errors when compiling the shader, do something like this:

HRESULT hResult;

ID3DBlob *pCompiledCode = NULL;
ID3DBlob *pErrorMsgs = NULL;
hResult = D3DX11CompileFromFile(TEXT("Shaders.hlsl"), NULL, NULL, "VShader", "vs_5_0", 0, 0, NULL, &pCompiledCode, &pErrorMsgs, NULL);
if(FAILED(hResult)) {
MessageBoxA(NULL, (char*)pErrorMsgs->GetBufferPointer(), "D3DX11CompileFromFile failed", MB_OK);
}

ID3D11VertexShader *pVertexShader;
hResult = pDevice->CreateVertexShader(pCompiledCode->GetBufferPointer(), pCompiledCode->GetBufferSize(), NULL, &pVertexShader);
if(FAILED(hResult)) {
asdf; // Add breakpoint here
}

if(pErrorMsgs != NULL)
pErrorMsgs->Release();

pCompiledCode->Release();


Couple that with D3D11_CREATE_DEVICE_DEBUG and you will be able to identify most errors easily.


From what I've heard directxtutorial.com has never been very good at any of this, and skips many things that are important to write safe and stable code. Then again there's not that many D3D11 tutorials I know about.. but you should definitely keep in mind that many functions can fail, and will fail, especially during development when you're changing things around. It's very easy to get a mistake into a shader, and without proper debug output you have no way of knowing which call failed.

Share this post


Link to post
Share on other sites

...
From what I've heard directxtutorial.com has never been very good at any of this, and skips many things that are important to write safe and stable code. Then again there's not that many D3D11 tutorials I know about.. but you should definitely keep in mind that many functions can fail, and will fail, especially during development when you're changing things around. It's very easy to get a mistake into a shader, and without proper debug output you have no way of knowing which call failed.


Thank you so much for you help. The problem was the version number, apparently has to be 4 not 5? Thanks for the heads up about safety, will now make sure pointers point to null and I am actually handling error messages :P

Thanks,

Share this post


Link to post
Share on other sites
If it has to be 4, then that probably means you're running at feature level 10.0. What graphics card do you have?

You can check your feature level with pDevice->GetFeatureLevel(). The following values are valid, and depend on your graphics card:

D3D_FEATURE_LEVEL featureLevel = pDevice->GetFeatureLevel();

D3D_FEATURE_LEVEL_9_1;
D3D_FEATURE_LEVEL_9_2;
D3D_FEATURE_LEVEL_9_3;
D3D_FEATURE_LEVEL_10_0;
D3D_FEATURE_LEVEL_10_1;
D3D_FEATURE_LEVEL_11_0;


Shader version 5.0 only works with feature level 11.0.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!