Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

CrescentFresh

Member Since 12 Mar 2006
Offline Last Active Mar 26 2013 02:32 PM
-----

Topics I've Started

Recover full screen device, procedurally from other process.

26 February 2013 - 03:38 PM

I have a multi-monitor, multi-full screen dx9 device setup that need to work hand-in-hand with another process. This other process can make the dx9 app minimize so it can take the active foreground window... and when it's done, it signals the dx9 app (via local telnet) to recover itself and become active again. 

 

My finished product needs to accomplish this procedurally, as in I cannot use any input devices to either alt-tab or click the dx9 app in taskbar with mouse. When I try to do it procedurally, the different recovery code I've tried has managed to create two different outcomes.

 

  • The dx9 app does maximize, and recovers... but when I click the screen, if any windows are behind the game it immediately loses focus, as if the dx9 app is only rendering overtop the other windows but not actually there.
  • Or, the game comes back up, but shows only a white screen and the device is reports 'D3DERR_DEVICELOST', and never makes it to 'D3DERR_DEVICENOTRESET'... but if you actually click the screen it receives the input properly and plays the game.

 

I'm almost certain I'm freeing all the dx resources that I need to be, and that it's got to be some sort of focus issue.

 

I'm also aware that AllowSetForegroundWindow(), needs to present in the other process to be able to give up focus, and it is being called.

 

The dx9 app is a fairly large engine, so posting the code is a concise matter will be difficult, below is the general idea of things:

 

 All code is from dx9 app:

//
// A message comes in whether to minimize/maximize
if(m_bMinimize)
{
    LOG("minimize!");
    ShowWindow(deviceRef.GetWnd(), SW_MINIMIZE);//SW_HIDE);
}
else
{
    LOG("MAXIMIZE!");
    ShowWindow(deviceRef.GetWnd(), SW_SHOWNORMAL);
    SetForegroundWindow(deviceRef.GetWnd());
}

 

The below function CheckDevice() is called at the beginning of the render thread loop. It returns whether or not the device is okay.

// Returns true if it's okay to render
bool LtGRenderThread::CheckDevice()
{
    if(m_bLostDevice)
    {
        int j = 0;
	for(j = 0; j < m_iNumDevices; j++) //for(int j = m_iNumDevices-1; j >= 0; --j)
	{
	    HRESULT result = m_pDevices[j].m_pD3DDevice->TestCooperativeLevel();
	    if(FAILED(result))
	    {
	        if(D3DERR_DEVICENOTRESET == result)
		{
		    HRESULT result2 = m_pDevices[j].m_pD3DDevice->Reset(&m_pDevices[j].m_tPresentParams);

		    if(FAILED(result2))
		    {
			LOGF("Device %i: reset failed: %u", LOG_NORMAL, j, result2);			                                              }
		    else
		    {
			LOGF("Device %i: Reset successful...", LOG_NORMAL, j);
		    }
		}
                    break;
		
            }
	    else
	        LOGF("DEVICE %i has recovered!", LOG_TODO, j);
	}

	if(j == m_iNumDevices)
	{
	    LOG("Reloading all vRAM...");

	    for(j = 0; j < m_iNumDevices; j++)
	    {
	        m_pDevices[j].OnResetDevice();
	    }
	
	    // Tell Update thread that we need to reset the device
	    m_MsgManRef.MarkFlag(MSGMAN_ResetDevice);

	    m_bLostDevice = false;
        }
    }
    else
    {
	for(int j = 0; j < m_iNumDevices; j++)
	{
            HRESULT result = m_pDevices[j].m_pD3DDevice->TestCooperativeLevel();
	    if(FAILED(result) || m_pDevices[j].IsForceReset())
	    {
		LOG("A device has been lost! (Or forced to reset)");

		m_bLostDevice = true;
				
		// Clear out all DX resources
		for(int i = 0; i < m_iNumDevices; i++)
		    m_pDevices[i].OnLostDevice();

		m_MsgManRef.MarkFlag(MSGMAN_LostDevice);

	        break;
	    }
        }
    }
	
    return !m_bLostDevice;
}

 

 

I'm pretty sure no one is going to respond to this mess. But I'll just try to be hopeful that someone has some experience in doing something similar to this. Thanks for reading.


Multithreaded renderer (with multiple devices)

18 December 2012 - 01:20 PM

I have a directx 9 application that needs to run on a Windows XP (embedded) machine with two monitors.

My first iteration of the renderer was a single IDirect3DDevice9 object and then I IDirect3DDevice9::CreateAdditionalSwapChain() per "screen", which rendered out multiple 'windows' positioned and sized to simulate full screen.

This worked well, however I'd get lots of screen tearing since I used D3DPRESENT_INTERVAL_IMMEDIATE within the presentation parameters because I don't want to stall the updates waiting for vBlank. Also, I assume that with only one device querying one adapter, I'd not be able to safely assume the vBlank period for both monitors, only the 'main' monitor.

So this lead me to re-writing the renderer to use multiple devices (one for each monitor), and each device has its own adapter for its respective monitor. For my purposes, this is working just as well as the additional swap chains method, however I'm back to the same issue of tearing since the alternative is stalling the main thread twice for both vBlank's, which leads to unacceptable framerate jittering.

 
If I were to put forth the incredible amount of effort of rewriting my engine to be a multi-threaded renderer, will this solve my screen tearing issue? More specifically, am I able to create a thread for each device and render/present them independently? If I must keep all DX API calls on the same thread (which I believe is the case), will stalling multiple times waiting for vBlank still allow me to achieve a 60hz FPS?

-or-

Is there an easier way to know when to invoke IDirect3DSwapChain9::Present() without D3DPRESENT_INTERVAL_DEFAULT and on a single thread?

I've tried polling IDirect3DSwapChain9::GetRasterStatus() to manually present an already rendered backbuffer in the vBlank period (per device/monitor), but that doesn't seem to be accurate enough as I still get tearing.

PARTNERS