• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Soul Reaver

[DirectX 9] Mesh gone after device reset

17 posts in this topic

Hi, I've a probably easy-to-solve problem but it seems really strange to me. After a device reset my mesh is not being rendered anymore. Here is my code:
Mesh::Mesh(D3DDevice* device, std::string folder , std::string file, bool optimize)
{
	_device = device;

	ID3DXBuffer *mtrlBuffer, *adjBuffer;
	D3DXLoadMeshFromX((folder + file).c_str(), D3DXMESH_MANAGED,
					  _device, &adjBuffer, &mtrlBuffer, 0,
					  &_numFaces, &_mesh);

	D3DXMATERIAL* mtrl = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer();

	for(uint i = 0; i < _numFaces; i++)
	{
		_material.push_back(mtrl[i].MatD3D);

		if(mtrl[i].pTextureFilename != 0)
		{
			D3DTexture* tex;
			std::string f = folder + mtrl[i].pTextureFilename;
			D3DXCreateTextureFromFileEx(_device, f.c_str(), 0,      
                                                    0, 0, 0,
						    D3DFMT_UNKNOWN,  
                                                    D3DPOOL_MANAGED, 
                                                    D3DX_DEFAULT,
						    D3DX_DEFAULT, 0, NULL, 
                                                    NULL, &tex);
			_texture.push_back(tex);
		}
		else
			_texture.push_back(0);
	}

	mtrlBuffer->Release();

	if(optimize)
	{
		_mesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT |
                                       D3DXMESHOPT_COMPACT |
  				       D3DXMESHOPT_VERTEXCACHE,
				       (DWORD*)adjBuffer->GetBufferPointer(),
				       0, 0, 0);
	}

	adjBuffer->Release();
}

void Mesh::render()
{
	for(uint i = 0; i < _numFaces; i++)
	{
		_device->SetMaterial(&_material[i]);
		_device->SetTexture(0, _texture[i]);
		HRESULT hr = _mesh->DrawSubset(i);
		if(FAILED(hr))
			MessageBox(NULL, DXGetErrorString(hr), "", MB_OK);
	}
}


The things that are strange to me are that -the mesh is in the managed pool -the texture pointers are not 0 -the DrawSubset() function doesn't fail -the output of direct3d9 looks fine Any ideas what I'm doing wrong? Thanks in advance
0

Share this post


Link to post
Share on other sites
Have you tried enabling the debug runtimes to see if they give you any warnings? Also, have you tried looking at a frame in PIX to see what's going on?
0

Share this post


Link to post
Share on other sites
Quote:
Original post by MJP
Have you tried enabling the debug runtimes to see if they give you any warnings? Also, have you tried looking at a frame in PIX to see what's going on?


The D3D9 debug runtime is enabled but I see no unusual output as I said before.

I found out that the mesh isn't gone completely. It just renders only 1 triangle which is black. I couldn't see it at first because backface culling is enabled.

I don't really know what to do with the results of PIX since I have never used it before.

0

Share this post


Link to post
Share on other sites
Do you use the same ResetDevice() function when you reset as you do when you initially create the device? If the mesh renders correctly just after you create the device and mesh, it sounds like you set different parameters from your initial device creation when you reset the device. Check all your present params, lighting params, render states, etc., to ensure they're the same when you both create and reset the device.
0

Share this post


Link to post
Share on other sites
Thanks for you help,

it was in fact because I didn't reset the renderstates and lights.
I thought these options wouldn't be affected when the device is lost.
0

Share this post


Link to post
Share on other sites
Quote:
Original post by Soul Reaver
Thanks for you help,

it was in fact because I didn't reset the renderstates and lights.
I thought these options wouldn't be affected when the device is lost.
When the device is reset, it's reset to the same state it was in when the device was created - so ALL device state is reset.
0

Share this post


Link to post
Share on other sites
Glad you found the problem. I use the same ResetDevice() routine following both creation and reset to ensure things stay the same. You might try that.
0

Share this post


Link to post
Share on other sites
Sorry for the bump but what code do you use for restoring the meshes/lights after the App regains focus?

Do you cycle through each Mesh object or something?

Edit: I though I had to readress textures and materials.

Fix: I made a new function to set all render states which is called at startup and after device gets focus
0

Share this post


Link to post
Share on other sites
[quote name='Tispe' timestamp='1298991930' post='4780561']
Sorry for the bump but what code do you use for restoring the meshes/lights after the App regains focus?

Do you cycle through each Mesh object or something?
[/quote]
Not sure what you mean by "restore." In any case, what you do in response to WM_SETFOCUS depends on what you do in response to WM_KILLFOCUS.

If you're having a problem, you should describe it.
0

Share this post


Link to post
Share on other sites
As an aside, you shouldn't be performing lost device handling in response to WM_ messages. It will only end in tears.

To quote from the SDK:
[quote]By design, the full set of scenarios that can cause a device to become lost is not specified. Some typical examples include loss of focus, such as when the user presses ALT+TAB or when a system dialog is initialized. Devices can also be lost due to a power management event, or when another application assumes full-screen operation.[/quote]
In other words, you aren't capturing all events that can cause a device to become lost, and the time will come when it bites you. Check the HRESULT of your IDirect3DDevice9::Present (or IDirect3DSwapChain9::Present) call for D3DERR_DEVICELOST instead.
0

Share this post


Link to post
Share on other sites
[quote name='mhagain' timestamp='1298999230' post='4780590']
As an aside, you shouldn't be performing lost device handling in response to WM_ messages. It will only end in tears.

To quote from the SDK:
[quote]By design, the full set of scenarios that can cause a device to become lost is not specified. Some typical examples include loss of focus, such as when the user presses ALT+TAB or when a system dialog is initialized. Devices can also be lost due to a power management event, or when another application assumes full-screen operation.[/quote]
In other words, you aren't capturing all events that can cause a device to become lost, and the time will come when it bites you. Check the HRESULT of your IDirect3DDevice9::Present (or IDirect3DSwapChain9::Present) call for D3DERR_DEVICELOST instead.
[/quote]

hmm, I tried this:

[code]
if(d3ddev->Present(NULL, NULL, NULL, NULL) != D3D_OK)
ResetDevice();
[/code]

ResetDevice() is the same function called when WM_ACTIVATEAPP is recieved. But the screen is blank after I ALT-TAB out and back in.I have to remove the whole WM_ messages routine to make it work.

Do I need to stop rendering when the app no longer has focus? Seems to me Present() will be ran in the background and I "reset" the device 60 times/sec while the app is minimized
0

Share this post


Link to post
Share on other sites
In general, you would be better off [i]not[/i] performing any device/rendering functions in response to window messages.

I would suggest you call ResetDevice() at only [b]one[/b] location in your code (other than in your CreateDevice() routine), probably in your run loop after you call dev->TestCooperativeLevel, and the result of TestCooperativeLevel indicates that's the appropriate action to take.

With regard to what you tried: if dev->Present fails, ResetDevice() may not be the proper thing to do. The failure may not be a result of the device needing to be reset.

With regard to gaining/losing focus, it's possible to have your application run in background if there's an overriding reason. However, it would be probably be better to pause your app when it loses focus. That's an indication that the user (for the moment) isn't interested in your window.
0

Share this post


Link to post
Share on other sites
[quote name='Tispe' timestamp='1299000226' post='4780597']
hmm, I tried this:

[code]
if(d3ddev->Present(NULL, NULL, NULL, NULL) != D3D_OK)
ResetDevice();
[/code]

ResetDevice() is the same function called when WM_ACTIVATEAPP is recieved. But the screen is blank after I ALT-TAB out and back in.I have to remove the whole WM_ messages routine to make it work.

Do I need to stop rendering when the app no longer has focus? Seems to me Present() will be ran in the background and I "reset" the device 60 times/sec while the app is minimized
[/quote]

Try something like this instead:
[code]hr = d3ddev->Present (NULL, NULL, NULL, NULL);
if (hr == D3DERR_DEVICELOST)
{
while (1)
{
hr = d3ddev->TestCooperativeLevel ();
switch (hr)
{
case D3D_OK:
// device is no longer lost and reset has completed successfully; recover resources here
return; // note: this assumes that this test is the last thing in the function it's being called from
case D3DERR_DEVICELOST:
// device is still lost; can't do anything so do nothing
break;
case D3DERR_DEVICENOTRESET:
// device is ready to be reset; Release resources here and then Reset it
// (be sure to test the hr from your Reset call too!)
break;
default:
// something bad happened! quit the program.
break;
}
Sleep (5); // yield some CPU
}
}[/code]
0

Share this post


Link to post
Share on other sites
[quote name='Buckeye' timestamp='1299002222' post='4780606']
With regard to what you tried: if dev->Present fails, ResetDevice() may not be the proper thing to do. The failure may not be a result of the device needing to be reset.
[/quote]

Now I only reset if its lost

[code]
if(d3ddev->Present(NULL, NULL, NULL, NULL) == D3DERR_DEVICELOST)
ResetDevice();
[/code]

where ResetDevice():

[code]
void ResetDevice()
{
if(d3ddev)
{
MSG msg;
while(d3ddev->TestCooperativeLevel() != D3DERR_DEVICENOTRESET)
{
//WaitMessage();
PeekMessage( &msg, NULL, 0, 0, PM_REMOVE );
TranslateMessage(&msg);
DispatchMessage(&msg);
Sleep(5);
}

if(FAILED(d3dspt->OnLostDevice()))
ErrorMessage(L"The d3dspt->OnLostDevice function failed");
if(FAILED(dxfont->OnLostDevice()))
ErrorMessage(L"The dxfont->OnLostDevice function failed");

if(FAILED(d3ddev->Reset(&d3dpp)))
ErrorMessage(L"The d3ddev->Reset function failed");

if(FAILED(d3dspt->OnResetDevice()))
ErrorMessage(L"The d3dspt->OnResetDevice function failed");
if(FAILED(dxfont->OnResetDevice()))
ErrorMessage(L"The dxfont->OnResetDevice function failed");
DeviceSettings();
}
}
[/code]

Proper enough?
0

Share this post


Link to post
Share on other sites
[quote]Proper enough?[/quote]
Wow. Actually, no. It appears you're just trying to patch things together.

First - the general principle of checking whether the device is valid [i]after[/i] you've gone through updating and rendering, as a personal opinion, is backwards. Testing for a properly setup device should be done [i]before[/i] it's needed for updating/creating objects/rendering/etc.

Second - I would suggest you separate windows messaging and DirecxtX processing to the greatest degree possible.

Take a look at the general arrangement of message processing, device status testing, updating, etc., in some of the SDK examples. Examing the flow Microsoft takes sounds like your best bet.
0

Share this post


Link to post
Share on other sites
So don't use Present() to check if the device is lost? Should I TestCooperativeLevel() each time I enter my rendering function and "abort" if there is an error?

In response to windows messaging, I do have the outer layer of the main loop seperate from DX stuff. This function however is just a secondary message handler for when the device is lost, I read that you should take care of messages while you try to reset the device.
0

Share this post


Link to post
Share on other sites
[quote name='Tispe' timestamp='1299011225' post='4780660']
So don't use Present() to check if the device is lost?[/quote]
I wouldn't check for a specific error, no. I would use the FAILED macro to check it, if I needed to use the device before I call TestCooperativeLevel the next time, or, if for some other reason, I needed to know that the buffer had been successfully presented before continuing.

[quote]Should I TestCooperativeLevel() each time I enter my rendering function and "abort" if there is an error?[/quote]
First, TestCooperativeLevel doesn't return an "error" code, per se. It provides information about the status of the device. Some of the conditions indicated are actually to be expected.

Second, why even enter the rendering function if there's a problem?

[quote]In response to windows messaging, I do have the outer layer of the main loop seperate from DX stuff. This function however is just a secondary message handler for when the device is lost,[/quote]

Have you reviewed the general flow in some of the SDK examples as suggested? Look at EmptyProject, for instance. It sounds like you need a structured approach to your loop and you could probably do worse than follow the same flow shown in an SDK example.

[quote]I read that you should take care of messages while you try to reset the device.[/quote]
Sounds like a good idea - but not mixed in with DirectX functions.
0

Share this post


Link to post
Share on other sites
To be honest I have not used DXUT before. The concept of CALLBACKS are still strange to me. I read up on it and understand that you provide a pointer to a function as argument to another function. I get the basics but when looking at the EmptyProject.cpp code it is stange why you need to "Set the callback functions" when you can just have prototypes and call the functions as I need them.

You talk about the "flow" of a typical SDK example, but reading the forums it is said that using DXUT for a release is not used much, if at all. So I need my own structute and I have one. DXUT and CALLBACKS as I understand it is just a generalisation that can be replaced by simple functions and their prototypes.

I want to alt-tab, toggle fullscreen or change resolution mid-game so I want to call a function to do that, it should be simple. How my loop is built should be irrelevant. We can discuss later how we can optimize it.
0

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  
Followers 0