Jump to content

  • Log In with Google      Sign In   
  • Create Account

FREE SOFTWARE GIVEAWAY

We have 4 x Pro Licences (valued at $59 each) for 2d modular animation software Spriter to give away in this Thursday's GDNet Direct email newsletter.


Read more in this forum topic or make sure you're signed up (from the right-hand sidebar on the homepage) and read Thursday's newsletter to get in the running!


[DirectX 9] Mesh gone after device reset


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
17 replies to this topic

#1 Soul Reaver   Members   -  Reputation: 108

Like
0Likes
Like

Posted 21 May 2010 - 02:04 AM

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

Sponsor:

#2 MJP   Moderators   -  Reputation: 11787

Like
0Likes
Like

Posted 21 May 2010 - 07:21 AM

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?

#3 Soul Reaver   Members   -  Reputation: 108

Like
0Likes
Like

Posted 24 May 2010 - 02:19 AM

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.



#4 Buckeye   Crossbones+   -  Reputation: 6381

Like
0Likes
Like

Posted 24 May 2010 - 02:41 AM

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.

#5 Soul Reaver   Members   -  Reputation: 108

Like
0Likes
Like

Posted 24 May 2010 - 03:00 AM

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.

#6 Evil Steve   Members   -  Reputation: 1987

Like
0Likes
Like

Posted 24 May 2010 - 03:04 AM

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.

#7 Buckeye   Crossbones+   -  Reputation: 6381

Like
0Likes
Like

Posted 24 May 2010 - 03:04 AM

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.


#8 Tispe   Members   -  Reputation: 1047

Like
0Likes
Like

Posted 01 March 2011 - 09:05 AM

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

#9 Buckeye   Crossbones+   -  Reputation: 6381

Like
0Likes
Like

Posted 01 March 2011 - 09:26 AM

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?

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.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.


#10 mhagain   Crossbones+   -  Reputation: 8284

Like
0Likes
Like

Posted 01 March 2011 - 11:07 AM

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:

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.

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.

It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.


#11 Tispe   Members   -  Reputation: 1047

Like
0Likes
Like

Posted 01 March 2011 - 11:23 AM

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:

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.

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.


hmm, I tried this:

if(d3ddev->Present(NULL, NULL, NULL, NULL) != D3D_OK)
		ResetDevice();

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

#12 Buckeye   Crossbones+   -  Reputation: 6381

Like
0Likes
Like

Posted 01 March 2011 - 11:57 AM

In general, you would be better off not performing any device/rendering functions in response to window messages.

I would suggest you call ResetDevice() at only one 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.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.


#13 mhagain   Crossbones+   -  Reputation: 8284

Like
0Likes
Like

Posted 01 March 2011 - 12:17 PM

hmm, I tried this:

if(d3ddev->Present(NULL, NULL, NULL, NULL) != D3D_OK)
		ResetDevice();

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


Try something like this instead:
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
	}
}

It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.


#14 Tispe   Members   -  Reputation: 1047

Like
0Likes
Like

Posted 01 March 2011 - 12:58 PM

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.


Now I only reset if its lost

if(d3ddev->Present(NULL, NULL, NULL, NULL) == D3DERR_DEVICELOST)
		ResetDevice();

where ResetDevice():

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();
	}
}

Proper enough?

#15 Buckeye   Crossbones+   -  Reputation: 6381

Like
0Likes
Like

Posted 01 March 2011 - 01:43 PM

Proper enough?

Wow. Actually, no. It appears you're just trying to patch things together.

First - the general principle of checking whether the device is valid after you've gone through updating and rendering, as a personal opinion, is backwards. Testing for a properly setup device should be done before 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.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.


#16 Tispe   Members   -  Reputation: 1047

Like
0Likes
Like

Posted 01 March 2011 - 02:27 PM

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.

#17 Buckeye   Crossbones+   -  Reputation: 6381

Like
0Likes
Like

Posted 01 March 2011 - 02:58 PM

So don't use Present() to check if the device is lost?

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.

Should I TestCooperativeLevel() each time I enter my rendering function and "abort" if there is an error?

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?

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,


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.

I read that you should take care of messages while you try to reset the device.

Sounds like a good idea - but not mixed in with DirectX functions.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.


#18 Tispe   Members   -  Reputation: 1047

Like
0Likes
Like

Posted 03 March 2011 - 01:52 PM

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.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS