Sign in to follow this  
Endar

CreateDevice error on other comps

Recommended Posts

I'm attempting to run a demo that I've written on other computers, but it doesn't seem to want to run. Apparently, CreateDevice returns "Invalid Call" (using DXGetErrorDescription), but the same executable works fine on the comp I developed it with. So it seems that one of the parameters was invalid for the particular computer. I am creating the device to use the primary display adapter (D3DADAPTER_DEFAULT), with hardware rasterization (D3DDEVTYPE_HAL) and with hardware vertex processing. I've tried it on two computers, a laptop (winXP, I think) and a desktop (win2000), and they both come up with the same error. I tried creating the device with software vertex processing on the laptop (not the desktop), and it returned that it was unavailable. The app was compiled with the October 2006 version of the SDK, and I also ran the re-distributable packages for both DX (Feb 2007) and VC++ 8 on the machines, and it doesn't come up with any errors of libraries not loaded, so it doesn't appear to be a dependency problem. Link to a zipped version of the app (compiled in release build). Could someone help me understand what is happening? More importantly, could you tell me if it actually runs? P.S. If the game does run, turn the volume down before playing (no sound in the menu, but check option menu for volume control). The sound effects can be very loud at 100% volume. Keys are arrows and space for shoot.

Share this post


Link to post
Share on other sites
Can we see the code where you set up your present parameters? Are you calling the various validation functions like IDirect3D9::CheckDeviceFormat and IDirect3D9::CheckDepthStencilMatch? If not, you need to in order to find out if the formats you want to use can actually be used on the target hardware.

What graphics card and OS are you running, and what card and OS are on the machines you've tested? Would it be possible to install the SDK and debug rumtimes on one of the target machines to capture the debug output? That'll get D3D to tell you why the call is failing (Although using the validation functions will tell you that anyway).

Share this post


Link to post
Share on other sites
It ran on my machine, but I have the Directx SDK. It will be hard for anybody to help you without seeing any code, but here are my guesses anyway. The machines you're testing the demo on use 24-bit color depth for display, and don't support 32-bits... I've seen a lot of those. Direct3D, afaik, doesn't support 24-bpp display modes, so you will have to use 16bpp for your backbuffer format and also switch to fullscreen. OR: you're using a depth/stencil format which is not available.

At any rate, check this out:
http://www.geocities.com/adelamro2004/files/D3DSettings.zip
This is a program which displays a settings dialog before it initializes the device, and it takes into account the capabilities of the underlying hardware (source included). I wrote it for an article that never saw the sunlight. I hope this helps.
-Love & Peace!

Share this post


Link to post
Share on other sites
At the moment, it doesn't need to be elegant, it just needs to work on most computers.

This is what I've got so far:

// get a pointer to something (don't know what), that we can use to create the d3d9 device
IDirect3D9* temp = Direct3DCreate9( D3D_SDK_VERSION );

if( !temp ){
util::LogManager::log( boost::format("%1%: Call to 'Direct3DCreate9' failed.") % __FUNCTION__,
util::MSGTYPE_ERROR);
return false;
}

D3DPRESENT_PARAMETERS d3dpp;
// set the parameters for the D3D9 device
ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS) );
d3dpp.Windowed = !settings.fullscreen; // set if the d3d instance is windowed or fullscreen
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

// if we're running DX fullscreen
if( settings.fullscreen ){
// we're trying to run in fullscreen, so we have to set the proper resolution
d3dpp.BackBufferHeight = (unsigned int) settings.screen_size.height;
d3dpp.BackBufferWidth = (unsigned int) settings.screen_size.width;

// set the back buffer format
//d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferFormat = D3DFMT_X1R5G5B5;
}
// else if we're running windowed
else{
// if we set either (or both) to 0, DX will use the size of the window
d3dpp.BackBufferHeight = 0;
d3dpp.BackBufferWidth = 0;

// set the format of the back buffer to unknown because in windowed mode, it doesn't matter
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
}

// check that the device format is valid for the machine
HRESULT result;
IDirect3DDevice9* d3d9_device = NULL;
if( FAILED(result=temp->CheckDeviceFormat(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
D3DFMT_X8R8G8B8,
0,
D3DRTYPE_SURFACE,
D3DFMT_X8R8G8B8
) ) )
{
// get a string describing the error that occured
std::string str_result = getDirect3DError(result);

util::LogManager::log( boost::format("%1%: D3D9 Device Format Check failed for reason: \"%2%\"") % __FUNCTION__ %
str_result, util::MSGTYPE_ERROR );
return false;
}
// create the device
else if( FAILED( result=temp->CreateDevice(
D3DADAPTER_DEFAULT, // use the primary display adapter (primary monitor)
D3DDEVTYPE_HAL, // hardware rasteriztion
window_handle, // the window handle
// set hardware or software vertex processing
settings.hardware_vertex_processing ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, // the settings for d3d9
&d3d9_device ) ) )
{
// get a string describing the error that occured
std::string str_result = getDirect3DError(result);

util::LogManager::log( boost::format("%1%: D3D9 Device creation failed for reason: \"%2%\"") % __FUNCTION__ %
str_result, util::MSGTYPE_ERROR );
return false;
}// if FAILED( temp->CreateDevice(......) )






How do I specify a 16bpp back buffer? Am I doing it right, because when I attempt to run in fullscreen, my app crashes and has a cry because the back buffer format is wrong. I can run it in X8R8G8B8 without a problem. Well, without a problem with the app running.

I quite intelligently decided, when I was writing it, to run my app windowed, at 800x800, and from what you guys have told me, that's not always going to be possible. If I run it fullscreen, it's going to need to be one of the native resolutions, right? Which would be 800x600. Because this was only a demo, I have specified the size and position of everything in screen coordinates. So, if I have to run in 800x600, everything messes up and I get to spend hours changing it all.

Fun, fun.

Edit:: Okay, I'm now using D3DFMT_R5G6B5 for a 16bpp back buffer format, and at least on my comp (the dev comp) it seems to be working. My problem at the moment is that with the most recent build, the device format check seems to be failing, and I'm not sure why.

I also just changed the two D3DFMT_X8R8G8B8 into D3DFMT_R5G6B5, but it didn't do anything helpful. It still works on the dev comp, but not on the laptop.

[Edited by - Endar on March 19, 2007 7:03:25 PM]

Share this post


Link to post
Share on other sites
I don't understand, you're saying you can run it without a problem with X8R8G8B8? If so, where is the problem then? Anyway, I'd pick up one of the "Direct3D initialization" samples (which are plenty on the net) and continuously tweak and test until I find what's causing the problem. But here are more guesses :)

1. You're possibly not adjusting the window size such that 800x800 is the size of the client rectangle, not the entire window (tip: check the platform SDK function AdjustWindowRect()). If you create the window to be 800x800, the client rect (and thus the back buffer) will possibly have a non-power of two width or height, which is typically not supported.

2. To test using 16bpp for the back buffer, use D3DFMT_R5G6B5, not D3DFMT_X1R5G5B5 (which I suspect is never supported for use with the back buffer).

3. A comment in your code says:
// set the format of the back buffer to unknown because in windowed mode, it doesn't matter
Well it does matter. Like I said, 24bpp formats (which are possibly being used for the desktop display... this is quite common in laptops) are not supported for use with the back buffer.

4. This is wild, but who knows... Try setting the presentation interval member of the presentation parameters structure to D3DPRESENT_INTERVAL_ONE - it's guaranteed to be supported on all cards, but D3DPRESENT_INTERVAL_IMMEDIATE (which is maybe what D3D uses if you set it to 0) is not.

-Love & Peace!

Share this post


Link to post
Share on other sites
Quote:
Original post by hikikomori-san
I don't understand, you're saying you can run it without a problem with X8R8G8B8? If so, where is the problem then? Anyway, I'd pick up one of the "Direct3D initialization" samples (which are plenty on the net) and continuously tweak and test until I find what's causing the problem. But here are more guesses :)

1. You're possibly not adjusting the window size such that 800x800 is the size of the client rectangle, not the entire window (tip: check the platform SDK function AdjustWindowRect()). If you create the window to be 800x800, the client rect (and thus the back buffer) will possibly have a non-power of two width or height, which is typically not supported.

2. To test using 16bpp for the back buffer, use D3DFMT_R5G6B5, not D3DFMT_X1R5G5B5 (which I suspect is never supported for use with the back buffer).

3. A comment in your code says:
// set the format of the back buffer to unknown because in windowed mode, it doesn't matter
Well it does matter. Like I said, 24bpp formats (which are possibly being used for the desktop display... this is quite common in laptops) are not supported for use with the back buffer.

4. This is wild, but who knows... Try setting the presentation interval member of the presentation parameters structure to D3DPRESENT_INTERVAL_ONE - it's guaranteed to be supported on all cards, but D3DPRESENT_INTERVAL_IMMEDIATE (which is maybe what D3D uses if you set it to 0) is not.

-Love & Peace!


I can run it without problem in X8R8G8B8 on the dev computer, not the one I'm using for testing.

1. I've said "stuff it" for 800x800 for the moment, and I'm attempting to create the window at 800x600, which again, is working on the dev comp, but not the laptop.

3.
Quote:
BackBufferWidth, BackBufferHeight
Width and height of the new swap chain's back buffers, in pixels. If Windowed is FALSE (the presentation is full-screen), these values must equal the width and height of one of the enumerated display modes found through IDirect3D9::EnumAdapterModes. If Windowed is TRUE and either of these values is zero, the corresponding dimension of the client area of the hDeviceWindow (or the focus window, if hDeviceWindow is NULL) is taken.

This is what I meant by "doesn't matter". It says that if it is windowed and I set the width and height to 0, then it uses the whole window.

Share this post


Link to post
Share on other sites
Okay, the laptop keeps saying that the Format check failed.


if( FAILED(result=temp->CheckDeviceFormat(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
D3DFMT_R5G6B5,
0,
D3DRTYPE_SURFACE,
D3DFMT_R5G6B5
) ) )



Okay, I changed from the HAL to the REF device, which apparently is not suitable for any kind of retail application, but it has gotten the laptop past it's issue with the device format.

Share this post


Link to post
Share on other sites
My bad, the back buffer width and height shouldn't be a problem in windowed mode. However, your comment was about the back buffer FORMAT, which DOES matter. Anyway, don't use CheckDeviceFormat, use CheckDeviceType. Also, I'm curious as to whether the "demo" I posted a link to above works well on your laptop. (By mistake, I included unnecessary files with it, but the project file ignores those). Hope this helps.
-Love & Peace!

Share this post


Link to post
Share on other sites
Quote:
Original post by hikikomori-san
My bad, the back buffer width and height shouldn't be a problem in windowed mode. However, your comment was about the back buffer FORMAT, which DOES matter. Anyway, don't use CheckDeviceFormat, use CheckDeviceType. Also, I'm curious as to whether the "demo" I posted a link to above works well on your laptop. (By mistake, I included unnecessary files with it, but the project file ignores those). Hope this helps.
-Love & Peace!


Well, the demo brings up the window and shows me all the details, but even with just the initial settings it brings up, I always get the error "Failed to create the Direct3D rendering device!"

Anyway, I just realised that even though I was checking if the REF device was valid, I was still attempting to create a HAL device. I just changed it on my dev computer, and it is so stupidly slow. It runs at like 0.5 fps. So, if it runs that slow on my dev comp, I'm not bothering trying REF on the laptop.

Also, I installed the DX SDK on the laptop, but I don't know how to get debug information from the DX libraries without running the app in debug mode in the IDE. Is there any other way to get the DX library output?

Edit:: Okay, still nothing. I've changed the call to CheckDeviceType, and now the laptop fails on that, in both fullscreen and windowed.

I'm attempting to call the function with using the primary display adapter (D3DADAPTER_DEFAULT), using the HAL instead of REF, with both the display and back buffer as 16bpp (D3DFMT_R5G6B5), and windowed or not, as appropriate.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Glad all HTML code is parsed from AP posts...

Your code is certified as:
http://www.codinghorror.com/blog/images/works-on-my-machine-stamped.png

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
Glad all HTML code is parsed from AP posts...

Your code is certified as:
http://www.codinghorror.com/blog/images/works-on-my-machine-stamped.png


Do you have the DX SDK?

Could you also give me some basic specs so I can get a feel for how new your comp/graphics card is?

Share this post


Link to post
Share on other sites
I do believe that I have found the problem.

I found the "DirectX Caps Viewer", which I assume stands for "capabilities".

The laptop has no graphics hardware (at least none that DX apparently recognises). I am able to run the demo in fullscreen and windowed, if I create a REF device. I also found out the the laptop can run with X8R8G8B8 windowed and fullscreen.

The only problem with a REF device is that it is incredibly slow. But I suppose that if a game/graphics company is running a demo, they're not going to be running it on a laptop with no graphics hardware.

Also, hikikomori, as far as I can see, in your source, I found this little snippet of code:

if( 0 == _strcmpi( g_AdapterInfoVec[uAdapter].adapterIdentifier.Description,
"NVIDIA NVPerfHUD" ) )
{
//g_Log( "Using NVidia PerfHUD." );
DevType = D3DDEVTYPE_REF;
}
else
{
// Not using NVidia PerfHUD..
DevType = D3DDEVTYPE_HAL;
}


It appears that you only use a REF device for a single graphics device. [smile]

I think I found the reason why your app didn't work.

Share this post


Link to post
Share on other sites
Quote:
Original post by Endar
I do believe that I have found the problem.

I found the "DirectX Caps Viewer", which I assume stands for "capabilities".

The laptop has no graphics hardware (at least none that DX apparently recognises). I am able to run the demo in fullscreen and windowed, if I create a REF device. I also found out the the laptop can run with X8R8G8B8 windowed and fullscreen.
If there's no graphics hardware thar DX recognises, that would certainly explain why it doesn't work. Out of interest, can you call IDirect3D9::GetCaps(), or does it fail? I have this problem when trying to use D3D via remote desktop.
Basically, it looks like your laptop doesn't have D3D drivers installed.


Quote:
Original post by Endar
The only problem with a REF device is that it is incredibly slow. But I suppose that if a game/graphics company is running a demo, they're not going to be running it on a laptop with no graphics hardware.

Also, hikikomori, as far as I can see, in your source, I found this little snippet of code:
*** Source Snippet Removed ***
It appears that you only use a REF device for a single graphics device. [smile]

I think I found the reason why your app didn't work.
The REF device is only present on machines with the SDK installed, which is why it's not suitable for deployment. It emulates everything in software, so it's an "ideal" card that supports everything. But because of that, it runs incredibly slowly (It's a software renderer). The only use for it is for testing your code when your card doesn't support something (E.g. pixel shaders), or when you think there might be a driver bug (If HAL and REF give different results, it's probably a driver bug. REF is always right).

As for hikikomori's code, that's slightly different. NVPerfHUD hooks D3D, and requires you to create a REF device. Under the hood, a HAL device is created though. The reason for having to explicitly request a REF device is to prevent people from running NVPerfHUD on applications they didn't write - E.g. Unreal or some other game using D3D. Because apps are never deployed using the REF device (for the reasons I mentioned above), no application should try to create a REF device, meaning you shouldn't be able to run NVPerfHUD on someone elses app.

NVPerfHUD is NVidia's performance analysis tool if you weren't aware.

Finally, you can capture debug output from an app by using tools like DebugView, which will capture all debug output from a program (Including D3D and D3DX debug spew). That should give you some information from D3D telling you why it failed.

Share this post


Link to post
Share on other sites
Could you tell us what color depth the desktop is on? Right-click desktop > Properties.. then choose the settings tab, and see what Color Quality is used. If it's 24bpp, then I think you will not be able to initialize D3D in windowed mode. you will have to set the desktop color depth to 16bpp before running the demo.

If the following code doesn't work, I don't think anything else will.

HRESULT InitD3DDevice()
{
HRESULT hr;

ZeroMemory( &g_D3DPP, sizeof( D3DPRESENT_PARAMETERS ) );

g_D3DPP.Windowed = TRUE;
g_D3DPP.BackBufferFormat = D3DFMT_X8R8G8B8;
g_D3DPP.BackBufferWidth = 0;
g_D3DPP.BackBufferHeight = 0;
g_D3DPP.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_D3DPP.hDeviceWindow = g_hWnd;
g_D3DPP.EnableAutoDepthStencil = FALSE;
g_D3DPP.PresentationInterval = D3DPRESENT_INTERVAL_ONE;

hr = g_pD3D->CreateDevice( 0, D3DDEVTYPE_HAL, g_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&g_D3DPP, &g_pD3DDevice );
if( FAILED( hr ) )
{
OutputDebugString( "Failed to create device using X8R8G8B8, trying R5G6B5" );
g_D3DPP.BackBufferFormat = D3DFMT_R5G6B5;
hr = g_pD3D->CreateDevice( 0, D3DDEVTYPE_HAL, g_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&g_D3DPP, &g_pD3DDevice );
if( FAILED( hr ) )
OutputDebugString( "Failed to create device using R5G6B5... your card is crap!" );
}
if( SUCCEEDED( hr ) )
{
OutputDebugString( "Everything went well" );
g_hrDeviceState = g_pD3DDevice->TestCooperativeLevel();
}
else
g_hrDeviceState = D3DERR_INVALIDDEVICE;
return hr;
}




To test it, replace the InitD3DDevice() from the above demo with this one, and clear the D3DCLEAR_ZBUFFER flag from the Clear() method in OnIdle().
Finally, here is the "mini article" that I was planning on posting somewhere.. it might be helpful. If all fails, save the caps from the caps viewer into a file and post it so we can have a look at it. Hope this helps.
-Love & Peace!

Share this post


Link to post
Share on other sites
If you're looking for a software device solution that will work with all video cards, try using the D3DDEVTYPE_SW. Use this code before you create your device. You'll have to download the software rasterizer from the microsoft website though if you don't have it.

example:
 
// Open up the Direct3D Software Rasterizer and get a pointer to the
// entry point.
if( NULL == ( hRast = LoadLibrary( "C:\\WINDOWS\\System32\\RGB9Rast_1.dll" ) ) &&
NULL == ( hRast = LoadLibrary( "RGB9Rast_1.dll" ) ) )
{
GameError( "Direct3D init failed!\n\n!LoadLibrary:\n"
"Failed to open Direct3D9 RGB software rasterizer." );
return E_FAIL;
}

// Locate the entry point of the software rasterizer
FARPROC Proc = GetProcAddress( hRast, "D3D9GetSWInfo" );

// Register the software renderer so that Direct3D can use it.
if( FAILED( hr = lpD3D->RegisterSoftwareDevice( Proc ) ) )
{
GameError( "Direct3D init failed!\n\nIDirect3D9::RegisterSoftwareDevice:\n"
"Failed to register software driver." );
return hr;
}




and now you can create a Direct3D device using D3DDEVTYPE_SW. Unlike REF, it doesn't support everything like shaders, but it works on everything I've used so far.

Share this post


Link to post
Share on other sites
I'll take a look at the things that you guys suggested, but my main worry was that I'd hand the demo to a game dev studio to look at, and it wouldn't run.

I suppose that fear is mostly baseless (at least in regards to this program) now.

Share this post


Link to post
Share on other sites
Quote:
Original post by Justin Rebuilt
I would hope that any respectable game development studio has the necessary hardware requirements to run your game as it was meant to be.


Hopefully. So I think I won't worry about fullscreen and just leave it windowed and at my original 800x800 window size.

Edit:: I've just posted what I'll most likely be using as the final version of the demo (unless any unforseen bugs pop up) up in the game programming forum.

[Edited by - Endar on March 20, 2007 10:42:40 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this