LPDIRECT3DDEVICE9->CreateDevice(...) is failing

Pages: 12
Okay so I've been following Direct3D tutorials from Chad Vernon and I've gone past the part where he's creating his own OOP framework for it.
I've taken all of this and sort of dumbed it down a bit (or complicated it more XD) but I have a problem as the CreateDevice(...) always fails in runtime (and error messages build in catch this for me)

Common.h
1
2
3
4
5
6
7
8
9
10
11
12
13
#pragma once

#define RELEASE(x) x->Release(); x = NULL;
#define STRINGIFY(x) #x
#define ST(x) STRINGIFY(x)
#define CONCAT(x, y) x##y
#define CAT(x, y) CONCAT(x, y)
#define MSG_ERR(x, file, line) CAT(x, CAT(CAT("\n\nFile: ", file), CAT("\nLine: ", ST(line))))

#define SS_FULLSCREEN (WS_EX_TOPMOST| WS_POPUP)
#define SS_FIXEDSCREEN (WS_OVERLAPPED | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU)
#define SS_BORDERLESS WS_OVERLAPPED
#define SS_WINDOWED WS_OVERLAPPEDWINDOW 



Core_Direct3D.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//receives Common.h
//receives d3d9.h and d3dx9.h (and anything else needed through its header)
bool SB::Core::Direct3D::Initialise(HWND hWnd, bool windowed){
	Windowed = windowed;
	m_hWnd = hWnd;
	if(p_DX)
		RELEASE(p_DX);
	if(p_Device)
		RELEASE(p_Device);
	p_DX = Direct3DCreate9(D3D_SDK_VERSION);
	if(!p_DX){
		MessageBox(NULL, MSG_ERR("Failed: Direct3DCreate9()", __FILE__, __LINE__), "Critical Error!", MB_ICONERROR | MB_OK);
		return false;
	}
	p_DX->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &m_displayMode);
	p_DX->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &m_caps);
	DWORD vertexProcessing = 0;
	if(m_caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT){
		vertexProcessing = D3DDEVCAPS_HWTRANSFORMANDLIGHT;
		if(m_caps.DevCaps & D3DDEVCAPS_PUREDEVICE)
			vertexProcessing |= D3DCREATE_PUREDEVICE;
	}
	else
		vertexProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
	if(!BuildPresentParameters()){
		p_DX->Release();
		p_DX = NULL;
		return false;
	}
	HRESULT hresult = 0;
	//Create the device
	hresult = p_DX->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd, vertexProcessing, &m_PP, &p_Device);
	if(FAILED(hresult)){
		p_DX->Release();
		p_DX = NULL;
		MessageBox(NULL, MSG_ERR("Failed: CreateDevice()", __FILE__, __LINE__), "Critical Error!", MB_ICONERROR | MB_OK);
		return false;
	}
	return true;
}



Main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
	WNDCLASSEX wc;
	ZeroMemory(&wc, sizeof(wc));

	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = (CS_HREDRAW | CS_VREDRAW | CS_OWNDC);
	wc.lpfnWndProc = WinProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	//wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CUNIT));
	//wc.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CUNIT));
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.lpszMenuName = NULL;
	wc.hbrBackground = (HBRUSH)BLACK_BRUSH;//COLOR_WINDOW;
	wc.lpszClassName = WINDOW_TITLE;
	RegisterClassEx(&wc);

	HWND hWnd = CreateWindow(WINDOW_TITLE, WINDOW_TITLE, SCREEN_STYLE, CW_USEDEFAULT, CW_USEDEFAULT, SCREEN_W, SCREEN_H, NULL, NULL, hInstance, NULL);
	if(!hWnd){
		MessageBox(NULL, MSG_ERR("Failed: CreateWindow()", __FILE__, __LINE__ -2), "Critical Error!", MB_ICONERROR | MB_OK);
		return 0;
	}
	{//Use rect as a temp value
		RECT rect = {0, 0, SCREEN_W, SCREEN_H};
		AdjustWindowRect(&rect, GetWindowLong(hWnd, GWL_STYLE), false);
		SetWindowPos(hWnd, 0, 0, 0, rect.right-rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE);
	}
	ShowWindow(hWnd, nCmdShow);

	UpdateWindow(hWnd);
	SB::Core::Engine::Setup(hWnd, !FULLSCREEN);

	MSG msg;
	double seconds;
	while(true){
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
			if(msg.message == WM_QUIT)
				break;
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else if(p_D3D->getDevice()){
			seconds = targetFrames(FRAME_TARGET);
			SB::Core::Engine::TickGame(seconds);
			SB::Core::Engine::Render();
		}
	}
	return 0;
}

LRESULT CALLBACK WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
	switch(msg){
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_PAINT:
		ValidateRect(hWnd, 0);
		return 0;
	case WM_SIZE:
		if(wParam == SIZE_MINIMIZED)
			SB::Core::Engine::active = false;
		else{
			SB::Core::Engine::active = true;
			SCREEN_W = LOWORD(lParam);
			SCREEN_H = HIWORD(lParam);
			if(SB::Core::Engine::D3D.getDevice())
				SB::Core::Engine::D3D.Reset();
		}
        //Other cases and defaults and stuffs
        }
    return 0; //(Actually returns the Def_shiz(...)
}


The only thing I know for certain is that for some reason CreateDevice() is returning <0 (I will try and get the value returned and will post incase it's of any help).
Last edited on
Okays... I've found out that the value returned by CreateDevice() is always
-2005530516

Although I still have no idea what this means
Last edited on
If the
CreateDevice()
method succeeds, then the return value is D3D_OK.

I would suggest that, in your Core_Direct3D.cpp file, change the
FAILED()
macro on line 33 around a bit. Try comparing the
hresult
with the following error codes to narrow down your problem.

1
2
3
4
5
6
7
8
9
if(hresult == D3DERR_DEVICELOST) {
	/**/
}else if(hresult == D3DERR_INVALIDCALL) {
	/**/
}else if(hresult == D3DERR_NOTAVAILABLE) {
	/**/
}else if(hresult == D3DERR_OUTOFVIDEOMEMORY) {
	/**/
}


*EDIT* Googling:
direct3d createdevice "-2005530516"
brings up a lot of results. Try your luck there.
Last edited on
Okay, I will update my result as soon as I can... I just noticed that my code doesn't actually show how the Initialise function is called... It's called from SB::Core::Engine::Setup along with some prerequisites and safety procedures.
That's just to clarify.
That error it means D3DERR_INVALIDCALL.
Okays, thanks for finding that one out before I had chance to...
So any ideas how I rectify this? (And yeah I'm just gonna take a look down MSDN now that I have that code)

EDIT: I can't find anything relevant to my situation so far, lots of people say they get this error when forgetting to initialise the D3DPRESENT_PARAMETERS but this is done in my BuildPresentParameters(), and it is checked to make sure it's successful...

I've tried running my little app in debug mode and got the following response:
First-chance exception at 0x00F75046 in MAIN.exe: 0xC0000005: Access violation reading location 0x00000188.

If there is a handler for this exception, the program may be safely continued.


So I'm imagining there's nothing wrong with the actual Direct3D aspect of this programming, just my careless placement of members..?
Last edited on
Does the debug only show one error at a time until something is fixed because this is the only error I can see and it's got pretty much nothing to do with CreateDevice().

My error comes from here:
1
2
3
SB::Core::Direct3D::getDevice(){
    return p_Device; //Error here!
}


But the catch what I've put in my program is getting CreateDevice() as failing, nothing to do with the getDevice().

I usually don't try and ask much and I try figure it out myself but I'm really confused here
Last edited on
I don't think it's the cause of your problem, but don't use macros (#define) if you don't know what you're doing.

You have:
#define RELEASE(x) x->Release(); x = NULL;

used like:
1
2
	if(p_DX)
		RELEASE(p_DX);


results in the following expansion:
1
2
3
	if(p_DX)
		p_DX->Release();
	p_DX = NULL;

which is harmless for that particular use case, but it isn't what one expects and could be problematic elsewhere.

An inline function would probably be more appropriate in C++.
Oh indeed, thanks for that... Wonder if somewhere this is setting something to null that is needed in the create device?
I noticed something, might be nothing.

D3DERR_INVALIDCALL : The method call is invalid. For example, a method's parameter may not be a valid pointer.

HRESULT CreateDevice(
  [in]           UINT Adapter,
  [in]           D3DDEVTYPE DeviceType,
  [in]           HWND hFocusWindow,
  [in]           DWORD BehaviorFlags,
  [in, out]      D3DPRESENT_PARAMETERS *pPresentationParameters,
  [out, retval]  IDirect3DDevice9 **ppReturnedDeviceInterface
);


What exactly is p_Device?
Yeah, I thought about that but I have checked everything to do with p_Device, and the m_PP, I have a feeling that the RELEASE macro may be clearing the settings so I need to check that out, p_Device is a pointer to a DIRECT3DDEVICE9 (set to NULL) will point to the device by CreateDevice().

And the D3DPRESENT_PARAMERTERS called m_DD is initialised in BuildPresentParamerters...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
bool SB::Core::Direct3D::BuildPresentParameters(){
	ZeroMemory(&m_PP, sizeof(m_PP));
	D3DFORMAT adapterFormat = (Windowed) ? m_displayMode.Format : D3DFMT_X8R8G8B8;
	if(SUCCEEDED(p_DX->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8)))
		m_PP.AutoDepthStencilFormat = D3DFMT_D24S8;
	else if(SUCCEEDED(p_DX->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8)))
		m_PP.AutoDepthStencilFormat = D3DFMT_D24X8;
	else if(SUCCEEDED(p_DX->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16)))
		m_PP.AutoDepthStencilFormat = D3DFMT_D16;
	else{
		MessageBox(NULL, MSG_ERR("Invalid Depth Format", __FILE__, __LINE__), "Critical Error!", MB_ICONERROR | MB_OK);
		return false;
	}
	m_PP.BackBufferWidth = (Windowed) ? 0 : m_displayMode.Width;
	m_PP.BackBufferHeight = (Windowed) ? 0 : m_displayMode.Height;
	m_PP.BackBufferFormat = adapterFormat;
	m_PP.BackBufferCount = 1;
	m_PP.MultiSampleType = D3DMULTISAMPLE_NONE;
	m_PP.MultiSampleQuality = 0;
	m_PP.SwapEffect = D3DSWAPEFFECT_DISCARD;
	m_PP.hDeviceWindow = m_hWnd;
	m_PP.Windowed = Windowed;
	m_PP.EnableAutoDepthStencil = true;
	m_PP.FullScreen_RefreshRateInHz = (Windowed) ? 0 : m_displayMode.RefreshRate;
	m_PP.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
	return true;
}
Is it a pointer to a DIRECT3DDEVICE9, in other words

DIRECT3DDEVICE9* device = NULL;

or

DIRECT3DDEVICE9 device = NULL;

Because it smells like an already-typedef'd pointer to something else.

EDIT* You mean m_PP, not m_DD?

EDIT AGAIN* Incase you haven't seen this already, here's a snippet from MSDN describing the D3DPRESENT_PARAMETERS structure which might be of interest:

MultiSampleQuality
Type: DWORD
Quality level. The valid range is between zero and one less than the level returned by pQualityLevels used by CheckDeviceMultiSampleType. Passing a larger value returns the error D3DERR_INVALIDCALL. Paired values of render targets or of depth stencil surfaces and D3DMULTISAMPLE_TYPE must match.
Last edited on
Yea I did mean m_PP sorry, and also it says the valid range is between zero and its max... The value I've set is just zero, I expect it means inclusively?

By the way I double checked the value returned by CreateDevice and it is definitely D3DERR_INVALIDCALL, I still can't figure out why though, all my variables are initialised and any pointer/references are to valid candidates.

And LPDIRECT3DDEVICE9 is defined as IDirect3DDevice9*
CreateWindow() needs an IDirect3DDevice9** which is used via reference.
Last edited on
*Nudge*
:(
This is tricky business, see.
I'll give this one more galant research effort, but I really have no clue.
Thank you very much for the attempted help, I shall upload all my relevant code files into a dropbox folder shortly if you could wait for that. This is isolated from the rest of the project so it's not too large to filter through but I've been through the source code countless times myself and still can't find the problem.
Sure, I'll be monitoring this thread.
Hey, I managed to find my direct3d settings and switch it to debug mode rather than release... Now running the F5 debug on visual studio I get this message:
[output]Invalid BehaviourFlags parameter. ValidateCreateDevice failed.[output]

This is the value called vertexProcessing, now I just need to find out what is wrong with it!

Outputting the value allows me to see that vertexProcessing is setup for a hardware and pure device, which I don't think my machine is capable of but it's definitely present in dev caps.
Last edited on
You could try explicitly setting vertexProcessing in core_direct3d.cpp to one of the following values, just to see what happens:

D3DCREATE_SOFTWARE_VERTEXPROCESSING
D3DCREATE_HARDWARE_VERTEXPROCESSING
D3DCREATE_MIXED_VERTEXPROCESSING


*EDIT* I did some snooping, and maybe it's because your graphic card is outdated(?)

1.)Run > dxDiag.exe

2.)Select Display tab

3.)What does it say under Drivers>DDI version?
Last edited on
I don't even have a graphics card which is why I was expecting it to return as software processing (I have a laptop with an Intel chipset)
I also tried explicitly declaring the hardware processing but it ONLY works on its own, if pure device or the transform and light is also added then create device still fails.

I'm just worried incase I need these properties in future (although I have no idea what they do cos I've forgot)

EDIT: I don't believe this is of any use now since I've found the source of the problem but since I said I'd upload it, here is my project.
https://www.dropbox.com/sh/6y8pq0lkkrsn3au/Hl3Rise83v
Last edited on
Pages: 12