[SOLVED] rendering to texture and device lost

Discussion area about developing or extending OGRE, adding plugins for it or building applications on it. No newbie questions please, use the Help forum for that.
Post Reply
User avatar
bishopnator
Goblin
Posts: 223
Joined: Thu Apr 26, 2007 11:43 am
Location: Slovakia / Switzerland
x 1

[SOLVED] rendering to texture and device lost

Post by bishopnator » Tue Oct 20, 2009 2:14 pm

Hi, I get some crashes in D3D render system during rendering to textures (RenderTarget) if user switch to OS with alt+tab. It seems as bug to me in ogre, but i am not sure ofcourse O:-) because I am using "special" rendering code in my app.
I am rendering my big texture by parts -> ie. 4096x4096 texture (stored in RAM) is rendered by 256x256 pixels multiple times in loop:

Code: Select all

		for(int z=iMinZ; z<=iMaxZ + dz; z++) {
			for(int x=iMinX; x<=iMaxX + dx; x++) {
				BaseBlock* pBlock = m_arBlocks[x + z*m_xBlocksCount];
				if(!pBlock->renderToTexture(pSceneMgr, w, h, iMinX, iMaxX, iMinZ, iMaxZ, pMem, pf, pTexture)) {
					bSuccess = false;
					break;
				}
			}
		}

pMem     - RAM texture
w        - width of pMem
h        - height of pMem
iMinX/iMaxX/iMinZ/iMaxZ - positioning pTexture in pMem
pTexture - RenderTarget (smaller than pMem)
If during this loop user swith to OS, my RenderTarget become invalid due to device lost and Ogre throw exception - I am not sure if I do everything ok, because I render data to texture manually by calling methods from RenderSystem directly:

Code: Select all

		// render all renderabled directly with render system - it'll ignore all custom (user) settings in scene manager
		pRenderSystem->_setViewport(pViewport);
		pRenderSystem->_setViewMatrix(pCamera->getViewMatrix());
		pRenderSystem->_setProjectionMatrix(pCamera->getProjectionMatrix());
		pRenderSystem->clearFrameBuffer(Ogre::FBT_COLOUR|Ogre::FBT_DEPTH, pViewport->getBackgroundColour());
		pRenderSystem->_beginFrame();
		for(Ogre::Renderables::iterator it=arParts.begin(); it!=arParts.end(); ++it) {
			Ogre::Renderable* pRend = *it;
			pRend->getRenderOperation(renderOp);
			const Ogre::MaterialPtr& pMaterial = pRend->getMaterial();
			Ogre::Pass* pPass = pMaterial->getTechnique(0)->getPass(0);
			pRend->getWorldTransforms(&worldTransform);			

			// setup render system
			pRenderSystem->_setWorldMatrix(worldTransform);
			pSceneMgr->_setPass(pPass);

			if(pPass->isProgrammable()) {
				// setup data source
				Ogre::AutoParamDataSource dataSource;
				dataSource.setCurrentViewport(pViewport);
				dataSource.setCurrentRenderTarget(pViewport->getTarget());
				dataSource.setCurrentRenderable(pRend);
				dataSource.setCurrentSceneManager(pSceneMgr);
				dataSource.setWorldMatrices(&worldTransform, 1);
				dataSource.setCurrentCamera(pCamera, false);
				dataSource.setCurrentPass(pPass);
				dataSource.setAmbientLightColour(pSceneMgr->getAmbientLight());
				dataSource.setCurrentLightList(&lightList);
				pPass->_updateAutoParamsNoLights(&dataSource);
				pPass->_updateAutoParamsLightsOnly(&dataSource);

				// NOTE: We MUST bind parameters AFTER updating the autos
				if (pPass->hasVertexProgram())
					pRenderSystem->bindGpuProgramParameters(Ogre::GPT_VERTEX_PROGRAM, pPass->getVertexProgramParameters());

				if (pPass->hasGeometryProgram())
					pRenderSystem->bindGpuProgramParameters(Ogre::GPT_GEOMETRY_PROGRAM, pPass->getGeometryProgramParameters());

				if (pPass->hasFragmentProgram())
					pRenderSystem->bindGpuProgramParameters(Ogre::GPT_FRAGMENT_PROGRAM, pPass->getFragmentProgramParameters());
			}

			// perform rendering
			pRenderSystem->_render(renderOp);
		}
		pRenderSystem->_endFrame();
-> crash is on setting current viewport (first line) - if it is correct, I don't know it is sufficient to check device status before rendering to texture (before setting viewport) - what happens if device become lost during sending renderables to render system?
Last edited by bishopnator on Wed Oct 21, 2009 8:59 pm, edited 1 time in total.
0 x

User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19261
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
Contact:

Re: rendering to texture and device lost

Post by sinbad » Tue Oct 20, 2009 3:28 pm

If you're doing manual rendering like this it would be best to listen in on the device events (RenderSystem::Listener) and pause your own manual rendering commands until the device is restored. Ogre does this itself usually but obviously you're bypassing the protection :)
0 x

User avatar
bishopnator
Goblin
Posts: 223
Joined: Thu Apr 26, 2007 11:43 am
Location: Slovakia / Switzerland
x 1

Re: rendering to texture and device lost

Post by bishopnator » Tue Oct 20, 2009 10:14 pm

I ofcourse looked into Ogre's sources and I found only one place where device is tested to lost state and then restored -> in D3D9RenderWindow::update method. But during my rendering to texture, main window is not updated (only sometimes if progress bar updates - it cause redraw window contents, but it is not important). I also get another crash which is related to this problem - if device is lost before updating render texture, it immediately returns, but later if I request texture's content (from PixelBuffer), ogre's throws exception. I handle this exception, but I don't know how to wait for restoring device. It happens if I switch to OS before rendering my big texture and I just wait for starting this process - rendering doesn't crash (no render due to lost device), but content of texture is invalid.

Maybe problem is that I run app in fullcreen - if I run app in window and after finishing rendering texture switch to fullscreen, such problems will disapear .. I need this only during app initialization .. but I'll use this as last option O:-)

I think that this problem (with accessing pixel buffer form render texture) will also occur with default rendering sequence without updating main window (texture cannot restore device - only render window).
0 x

User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19261
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
Contact:

Re: rendering to texture and device lost

Post by sinbad » Wed Oct 21, 2009 4:39 pm

In trunk there's lots more checking done, including in D3D9RenderTexture::update.

You will need to have at least one window update to trigger the device restore, as you know. We expose the device lost and device restore events so even if you don't have a regular window update, on receipt of the device lost event you could periodically try to update a render window to see if that triggers the device restore successfully.
0 x

User avatar
bishopnator
Goblin
Posts: 223
Joined: Thu Apr 26, 2007 11:43 am
Location: Slovakia / Switzerland
x 1

Re: rendering to texture and device lost

Post by bishopnator » Wed Oct 21, 2009 8:59 pm

today I solved this with similar solution as you wrote. I have this piece of code at work, but iti is something like this:

Code: Select all

void _checkDevice(Ogre::RenderWindow* pWnd)
{
   if(pWnd == NULL)
     return;
   pWnd->update();
   while(isDeviceLost()) {
      Ogre::WindowEventUtilities::messagePump();
      pWnd->update();
   }   
}
And I have listener for render system's event to set boolean for checking if device is in lost state. It works perfectly -> I check lost device state before rendering and after rendering (because after rendering if I access pixel buffer, it fails with exception). I am not only sure what happens if user switch app to OS during rendering - in DX I read that rendering silently ends with D3DDEVICE_LOST error, but I don't know if ogre excepts in this case or not. If not, than everything is ok, and this solution works perfectly in all cases. Anyway I tries to reproduce crashes in my app, and with using this method (_checkDevice) I was not able to reproduce crash so I suppose it's ok O:-)

Thnx for help ;-)
0 x

KuRi
Goblin
Posts: 242
Joined: Wed Jul 05, 2006 4:19 pm

Re: [SOLVED] rendering to texture and device lost

Post by KuRi » Fri Oct 30, 2009 10:18 am

Hi,

when do you call your _checkDevice method?

Thanks.
0 x

User avatar
bishopnator
Goblin
Posts: 223
Joined: Thu Apr 26, 2007 11:43 am
Location: Slovakia / Switzerland
x 1

Re: [SOLVED] rendering to texture and device lost

Post by bishopnator » Fri Oct 30, 2009 12:22 pm

Hi, as I wrote: before and after rendering, so my rendering loop, which renders terrain parts into texture, looks like that:

Code: Select all

      Ogre::RenderWindow* pWnd = Ogre::Root::getSingleton().getAutoCreatedWindow();
      for(int z=iMinZ; z<=iMaxZ + dz; z++) {
         for(int x=iMinX; x<=iMaxX + dx; x++) {
            BaseBlock* pBlock = m_arBlocks[x + z*m_xBlocksCount];
            _checkDevice(pWnd);
            if(!pBlock->renderToTexture(pSceneMgr, w, h, iMinX, iMaxX, iMinZ, iMaxZ, pMem, pf, pTexture)) {
               bSuccess = false;
               break;
            }
            if(isDeviceLost()) {
               // lost device - we need to wait for device restore and re-render this block again
               x--;
               _checkD3DDevice(pWnd);
            }
         }
      }
This works perfectly for me - I can switch from fullscreen to OS and back without problems. When app is switched to OS, it starts looping in _checkDevice method so rednering is paused.

note: in renderToTexture it is neccessary to handle exceptions or you must be sure that use don't call methods which raises exceptions during lost device state - in my renderToTexture I check lost device state before calling method Ogre::Texture::getBuffer()->blitToMemory(). During lost device state it fires exception because it is not possible to access pixel data from render target.
0 x

Post Reply