Direct3D - minimiert - Fenster leer



  • Hi!
    Ich bastle gerade ein 2D Spiel (dabei starte ich die Anwendung mit Direct3D im Fullscreen )und soweit funktioniert auch alles, allerdings
    gibt es ein Problem nach dem ich das Fenster mit Alt+Tab minimert habe bzw zum Desktop wechsle UND anschließend wieder in das Spiel springe, dann bleibt das Fenster schwarz und es erscheint nichts mehr von den Texturen...
    Kennt ihr den Grund dafür? - Muss ich alle Bilder erneut in den Speicher laden?
    wenn ja...wieso? Die Bilder werden doch nicht einfach aus dem Speicher entfernt oder?

    MfG Kudlren



  • Doch, die Ressource werden dann manchmal gelöscht. Man kann dann nur noch alles neu laden.
    Den genauen Grund kenn ich nicht, aber ich denke mal, dass eine minimierte Anwendung in dem Zustand keine Ressourcen braucht, und wenn andere Programme Speicher brauchen, werden deine Texturen, Vertex-Buffer... gelöscht.



  • und gibts da eine spezielle WM_??? dafür ?

    hm..ich find es schon seltsam dass alle Bilder gelöscht werden...
    ich werd mal sehen wie ich am Besten alles neulade ohne dass etwas wichtiges überschrieben wird...

    danke jedenfalls für die schnelle antwort!



  • Anscheinend verwendest du Direct3D ohne vorher zu prüfen, ob es überhaupt (noch) in der Lage ist etwas zu tun.

    Hier mal die Renderfunktion von DirectX Utility, damit du sehen kannst was da alles schief laufen kann.

    Deine muss natürlich nicht so komplex sein, aber die ganzen Sicherheitsprüfungen solltest du auf jeden Fall einbauen, es kann jederzeit passieren, dass du Direct3D zurücksetzen musst, weil z. B. der Benutzer die Auflösung geändert hat, oder die Bitrate oder sonstwas während deine Anwendung im Hintergrund schlummert.

    void DXUTRender3DEnvironment()
    {
        HRESULT hr;
    
        IDirect3DDevice9* pd3dDevice = DXUTGetD3DDevice();
        if( NULL == pd3dDevice )
            return;
    
        if( GetDXUTState().GetDeviceLost() || DXUTIsRenderingPaused() || !DXUTIsActive() )
        {
            // Window is minimized or paused so yield CPU time to other processes
            Sleep( 50 ); 
        }
    
        if( GetDXUTState().GetDeviceLost() && !GetDXUTState().GetRenderingPaused() )
        {
            // Test the cooperative level to see if it's okay to render
            if( FAILED( hr = pd3dDevice->TestCooperativeLevel() ) )
            {
                if( D3DERR_DEVICELOST == hr )
                {
                    // The device has been lost but cannot be reset at this time.  
    				// So wait until it can be reset.
                    return;
                }
    
                // If we are windowed, read the desktop format and 
                // ensure that the Direct3D device is using the same format 
                // since the user could have changed the desktop bitdepth 
                if( DXUTIsWindowed() )
                {
                    D3DDISPLAYMODE adapterDesktopDisplayMode;
                    IDirect3D9* pD3D = DXUTGetD3DObject();
                    DXUTDeviceSettings* pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings();
                    pD3D->GetAdapterDisplayMode( pDeviceSettings->AdapterOrdinal, &adapterDesktopDisplayMode );
                    if( pDeviceSettings->AdapterFormat != adapterDesktopDisplayMode.Format )
                    {
                        DXUTMatchOptions matchOptions;
                        matchOptions.eAdapterOrdinal     = DXUTMT_PRESERVE_INPUT;
                        matchOptions.eDeviceType         = DXUTMT_PRESERVE_INPUT;
                        matchOptions.eWindowed           = DXUTMT_PRESERVE_INPUT;
                        matchOptions.eAdapterFormat      = DXUTMT_PRESERVE_INPUT;
                        matchOptions.eVertexProcessing   = DXUTMT_CLOSEST_TO_INPUT;
                        matchOptions.eResolution         = DXUTMT_CLOSEST_TO_INPUT;
                        matchOptions.eBackBufferFormat   = DXUTMT_CLOSEST_TO_INPUT;
                        matchOptions.eBackBufferCount    = DXUTMT_CLOSEST_TO_INPUT;
                        matchOptions.eMultiSample        = DXUTMT_CLOSEST_TO_INPUT;
                        matchOptions.eSwapEffect         = DXUTMT_CLOSEST_TO_INPUT;
                        matchOptions.eDepthFormat        = DXUTMT_CLOSEST_TO_INPUT;
                        matchOptions.eStencilFormat      = DXUTMT_CLOSEST_TO_INPUT;
                        matchOptions.ePresentFlags       = DXUTMT_CLOSEST_TO_INPUT;
                        matchOptions.eRefreshRate        = DXUTMT_CLOSEST_TO_INPUT;
                        matchOptions.ePresentInterval    = DXUTMT_CLOSEST_TO_INPUT;
    
                        DXUTDeviceSettings deviceSettings = DXUTGetDeviceSettings();
                        deviceSettings.AdapterFormat = adapterDesktopDisplayMode.Format;
    
                        hr = DXUTFindValidDeviceSettings( &deviceSettings, &deviceSettings, &matchOptions );
                        if( FAILED(hr) ) // the call will fail if no valid devices were found
                        {
                            DXUTDisplayErrorMessage( DXUTERR_NOCOMPATIBLEDEVICES );
                            DXUTShutdown();
                        }
    
                        // Change to a Direct3D device created from the new device settings.  
                        // If there is an existing device, then either reset or recreate the scene
                        hr = DXUTChangeDevice( &deviceSettings, NULL, false, false );
                        if( FAILED(hr) )  
                        {
                            // If this fails, try to go fullscreen and if this fails also shutdown.
                            if( FAILED(DXUTToggleFullScreen()) )
                                DXUTShutdown();
                        }
    
                        return;
                    }
                }
    
                // Try to reset the device
                if( FAILED( hr = DXUTReset3DEnvironment() ) )
                {
                    if( D3DERR_DEVICELOST == hr )
                    {
                        // The device was lost again, so continue waiting until it can be reset.
                        return;
                    }
                    else if( DXUTERR_RESETTINGDEVICEOBJECTS == hr || 
                             DXUTERR_MEDIANOTFOUND == hr )
                    {
                        DXUTDisplayErrorMessage( hr );
                        DXUTShutdown();
                        return;
                    }
                    else
                    {
                        // Reset failed, but the device wasn't lost so something bad happened, 
                        // so recreate the device to try to recover
                        DXUTDeviceSettings* pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings();
                        if( FAILED( DXUTChangeDevice( pDeviceSettings, NULL, true, false ) ) )
                        {
                            DXUTShutdown();
                            return;
                        }
                    }
                }
            }
    
            GetDXUTState().SetDeviceLost( false );
        }
    
        // Get the app's time, in seconds. Skip rendering if no time elapsed
        double fTime        = DXUTGetGlobalTimer()->GetTime();
        float fElapsedTime  = (float) DXUTGetGlobalTimer()->GetElapsedTime();
    
        // Store the time for the app
        if( GetDXUTState().GetConstantFrameTime() )
        {        
            fElapsedTime = GetDXUTState().GetTimePerFrame();
            fTime     = DXUTGetTime() + fElapsedTime;
        }
    
        GetDXUTState().SetTime( fTime );
        GetDXUTState().SetElapsedTime( fElapsedTime );
    
        // Update the FPS stats
        DXUTUpdateFrameStats();
    
        DXUTHandleTimers();
    
        // Animate the scene by calling the app's frame move callback
        LPDXUTCALLBACKFRAMEMOVE pCallbackFrameMove = GetDXUTState().GetFrameMoveFunc();
        if( pCallbackFrameMove != NULL )
        {
            pCallbackFrameMove( pd3dDevice, fTime, fElapsedTime, GetDXUTState().GetFrameMoveFuncUserContext() );
            pd3dDevice = DXUTGetD3DDevice();
            if( NULL == pd3dDevice ) // Handle DXUTShutdown from inside callback
                return;
        }
    
        if( !GetDXUTState().GetRenderingPaused() )
        {
            // Render the scene by calling the app's render callback
            LPDXUTCALLBACKFRAMERENDER pCallbackFrameRender = GetDXUTState().GetFrameRenderFunc();
            if( pCallbackFrameRender != NULL )
            {
                pCallbackFrameRender( pd3dDevice, fTime, fElapsedTime, GetDXUTState().GetFrameRenderFuncUserContext() );
                pd3dDevice = DXUTGetD3DDevice();
                if( NULL == pd3dDevice ) // Handle DXUTShutdown from inside callback
                    return;
            }
    
    #if defined(DEBUG) | defined(_DEBUG)
            // The back buffer should always match the client rect 
            // if the Direct3D backbuffer covers the entire window
            RECT rcClient;
            GetClientRect( DXUTGetHWND(), &rcClient );
            if( !IsIconic( DXUTGetHWND() ) )
            {
                GetClientRect( DXUTGetHWND(), &rcClient );
                assert( DXUTGetBackBufferSurfaceDesc()->Width == (UINT)rcClient.right );
                assert( DXUTGetBackBufferSurfaceDesc()->Height == (UINT)rcClient.bottom );
            }        
    #endif
    
            // Show the frame on the primary surface.
            hr = pd3dDevice->Present( NULL, NULL, NULL, NULL );
            if( FAILED(hr) )
            {
                if( D3DERR_DEVICELOST == hr )
                {
                    GetDXUTState().SetDeviceLost( true );
                }
                else if( D3DERR_DRIVERINTERNALERROR == hr )
                {
                    // When D3DERR_DRIVERINTERNALERROR is returned from Present(),
                    // the application can do one of the following:
                    // 
                    // - End, with the pop-up window saying that the application cannot continue 
                    //   because of problems in the display adapter and that the user should 
                    //   contact the adapter manufacturer.
                    //
                    // - Attempt to restart by calling IDirect3DDevice9::Reset, which is essentially the same 
                    //   path as recovering from a lost device. If IDirect3DDevice9::Reset fails with 
                    //   D3DERR_DRIVERINTERNALERROR, the application should end immediately with the message 
                    //   that the user should contact the adapter manufacturer.
                    // 
                    // The framework attempts the path of resetting the device
                    // 
                    GetDXUTState().SetDeviceLost( true );
                }
            }
        }
    
        // Update current frame #
        int nFrame = GetDXUTState().GetCurrentFrameNumber();
        nFrame++;
        GetDXUTState().SetCurrentFrameNumber( nFrame );
    
        // Check to see if the app should shutdown due to cmdline
        if( GetDXUTState().GetOverrideQuitAfterFrame() != 0 )
        {
            if( nFrame > GetDXUTState().GetOverrideQuitAfterFrame() )
                DXUTShutdown();
        }
    
        return;
    }
    


  • Hi,

    siehe DirectX SDK Doku unter dem Stichwort "Lost Device". Wenn man alle Resourcen (soweit möglich) im "Managed Pool" anlegt dann muss man diese nicht wiederherstellen. Aber das Device muss man trotzdem resetten.

    Ciao,
    Stefan



  • Erstmal danke für die Antworten...

    @User--:
    Danke für den Codeausschnitt allerdings kann ich mit so ziemlich allen Funktionen/Methoden die dein Code enthält in denen das "DXUT" vorkommt, nichts anfangen....
    GetDXUTState(), etc...
    (Wenn ich es kompiliere bekomme ich für deinen Code 85 Fehler ... Natürlich auch wegen den Unterschiedlichen Variablennamen allerdings auch für alle "DXUT"-Funktionen.....)

    Gibt es keine kürzere Möglichkeit das Device zu reseten?
    Unter "Lost Device" hab ich leider nichts brauchbares gefunden.

    Ja ich lege alles im D3DPOOL_MANAGED an...



  • Dann musst du wohl alles wieder neu erstellen und laden.



  • Dann musst du wohl alles wieder neu erstellen und laden.

    ?
    d.h. ich soll einfach direct3d neuinitialisieren?
    und alle bilder neuladen?

    gibt es nicht einfach eine möglichkeit das device zu reseten?



  • Hi,

    doch gibt es. Dazu müsstest Du Dir allerdings die neueste Doku herunterladen wenn Du in Deiner Version der DOku nichts zum "Lost Device" findest.

    Alle als "managed" erstellten Resources muss man nicht neu laden. Das Device muss man resetten sobald es das wieder zulässt. Schau Dir einfach die möglichen Rückgabewerte von IDirect3DDevice9::Present, IDirect3DDevice9::Reset und IDirect3DDevice9::TestCoopLevel hinsichtlich "Lost Device" an.

    Ciao,
    Stefan



  • Ich habe jetzt ziemlich lang gesucht und auch einiges an Code gefunden allerdings nichts was funktioniert hat...

    Ein BspCode:

    HRESULT hr;
    
          hr=Direct3D.m_lpD3DDevice->TestCooperativeLevel();
    
          if(SUCCEEDED(hr)){
    
    		Direct3D.BeginScene();
    
    	 	Direct3D.DrawText("Test",0,0,D3DCOLOR_XRGB(0,255,0));
    
    		Direct3D.EndScene();
    
    	  }
    
          //Device is lost
          if(hr == D3DERR_DEVICELOST || hr == D3DERR_DEVICENOTRESET){
               //  MessageBox(hWnd,"TEST","TEST",MB_OK);
             Direct3D.m_lpD3DDevice->Reset(&Direct3D.PParams);
    
          }else if(FAILED(hr)){ //Other error
             Direct3D.g_app_done=true;
    
          }
    

    Wenn ich mit Alt+TAB aus dem Fenster springe und dnan wieder hinein ist es leer und zeigt nichts an.
    Ich habe auch ein

    MessageBox(hWnd,"TEST","TEST",MB_OK);
    

    eingebaut um zu prüfen ob überhaupt der if zweig überhaupt erkannt wird...
    und beim Alt+TAB wird die MEssageBox auch ausgegeben...also kann etwas mit dem Reset nicht stimmen....
    Könnt ihr mir helfen?

    MfG Kuldren



  • Ja, dir kann geholfen werden. Du musst es nur so machen, wie in der DX SDK Hilfe beschrieben. f'`8k

    Gruß, TGGC (\-/ returns)



  • Über das Erstellen eines Device gabs einiges aber nicht viel über den Reset....

    int CDirect3D::TestCooperativeLevel(){
    
    	int res;
    
    	HRESULT hrLostDevice = m_lpD3DDevice->TestCooperativeLevel();     
    
        //Do nothing 
        if (hrLostDevice == D3DERR_DEVICELOST) 
            RestoreObject();
        //Reset it 
        else if (hrLostDevice == D3DERR_DEVICENOTRESET) 
            RestoreObject();
    
        //Shut down! 
        else if (hrLostDevice == D3DERR_DRIVERINTERNALERROR) 
    		res= 3;
    
    	return res;
    
    }
    
    void CDirect3D::RestoreObject(){
    
    	  //Resets the device 
     m_lpD3DDevice->Reset(&PParams);
    }
    

    Das hab ich gefunden und in meine CDirect3D Klasse eingebunden..
    allerdings funktioniert es nicht...



  • Hi,

    definiere "funktioniert nicht".

    Zudem nicht vergessen, dass man alle States des Device wieder neu einstellen muss. Insbesondere ist das die Projektionsmatrix, das ambiente Licht, die Lichtquellen, ...

    Ciao,
    Stefan



  • EDIT:
    Hat sich erledigt....habs geschafft!


Log in to reply