Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Problemas Al Recuperar El Device En Direct3d

Iniciado por [EX3], 21 de Diciembre de 2004, 04:02:19 AM

« anterior - próximo »

[EX3]

 Wenas. Pues despues de meter mano al TLSA Engine durante unos cuantos meses he decidido hacer una pausa y volver a la dx_lib32 para erradicar algunos bugs y modificar y añadir algunas funciones mas a la libreria.

En el apartado grafico el mayor problema que tengo es cuando ejecuto un programa con dx_lib32 a pantalla completa y este pierde Device de Direct3D cuando pierde el foco la ventana del programa. Tengo aplicado este codigo para recuperar el Device pero me provoca un error grave de windows y me cierra la aplicacion:

Select Case Device.TestCooperativeLevel
       Case D3DERR_DEVICENOTRESET
           'Resetea el Device:
           Call Device.Reset(D3DWindow) -> Esta linea es la que provoca el error.
           Exit Function
           
       Case Is <> D3D_OK
           'No es posible renderizar:
           Exit Function

End Select

Llevo meses intentando corregir este error y ya no se me ocurre ke mas hacer. Que es lo que falla? Como haceis vosotros para recuperar el Device en vuestros programas?

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

Haddd

 Creo que tienes que invalidar primero todo lo que sea referente al device. En los ejemplos de DX hay mucho código así.


_Grey

 Como dice Haddd.Mas claramente tienes que cargarte los vertexbuffer, indexbuffers, texturas... etc.... Resetear el Device y crearlos de nuevo. (segun como los crearas puedes ahorrarte ese trabajo). pero en general se puede decir que hes una faena....

[EX3]

 En los ejemplos para VB ninguno hace recuperacion del Device ya que todos son en modo Ventana y los de C++ estuve mirando el codigo y no veo por ningun lado el codigo de recuperacion del Device  :(  Voy a darme otro paseo por Google para ver si encuentro algo. Por cierto, Haddd, vuestro motor no hace recuperacion del Device?

Sobre lo de eliminar cualquier textura, buffer, etc... me extraña un poco por ke en DirectDraw no habia ke hacer nada de eso para recuperar el control del render y este codigo ke he puesto funcionaba tal y como esta en el ejemplo de donde lo saque (ke por cierto no se donde lo tengo :S) El tema es que esto de reiniciar el Device y de recargar las texturas era una supuesta idea "chapucera" ke tuve y mira por donde parece ke no iba muy desencaminado.

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

[EX3]

 Select Case Device.TestCooperativeLevel
       Case D3DERR_DEVICENOTRESET
           'Resetea el Device:
           Call MainFont.OnLostDevice
           Call DxSprite.OnLostDevice
           Call Device.Reset(D3DWindow)
           Call DxSprite.OnResetDevice
           Call MainFont.OnResetDevice
           Exit Function
           
       Case Is <> D3D_OK
           'No es posible renderizar:
           Exit Function
   End Select

Ahora si se resetea el Device, parece ser que tb hay ke resetear componentes como DXSprite o DXFont y si, parece ser que hay que recargar las texturas de nuevo, pero... y que haces con las texturas que has creado en tiempo de ejecucion? Tb hay ke recargar las Superficies (Surfaces)? Esto en DirectDraw era mas sencillo :(

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

Haddd

 Nuestro motor actualmente NO recupera el device. Sin embargo está bastante preparado para ello, puesto que las clases de recuperación están bien localizadas.

La recuperación de devices es una tarea que por desgracia es compleja. Normalmente, al definirle POOL_MANAGED, DX te resuelve él solito esa tarea. En realida lo que hace es mantener una copia en memoria RAM de todo lo que tiene en vídeo. Al Invalidarlo o resetearlo, se va a la ram y copia el valor en vídeo.

Pero eso implica que cualquier cambio se copia también a la RAM. Entonces si tienes una tarjeta de vídeo de 512 MB y utilizas POOL_MANAGED y llenas toda la memoria de vídeo con texturas, que sepas que necesitarás también 512 MB de RAM aproximadamente para poder recuperarlo.

Entonces, para no complicarme la vida y la RAM, opté por que los objetos fueran POOL_DEFAULT. Si se provoca un Reset, pues...¡mala suerte!

[EX3]

 Mis texturas las cargo como POOL_MAGNAGED y aun asi no las visualiza, es mas, creo ke aun con el codigo ke tengo ahora puesto sigue sin resetearse correctamente todo por ke en un programa ke tengo ke solo trabaja con primitivas graficas,  sin texturas ni nada y tampoco se resetea correctamente, solo me conserva la resolucion pero nada mas. No pense que esto llegase a ser tan complejo. De momento lo ke he hecho es hacer que la funcion de renderizado de la dx_lib32 devuelva un valor de retorno especifico si el dispositivo se ha perdido, asi el programador puede optar por reinciar el motor grafico desde 0 pero eske aun asi sigue estando el tema de los graficos creados en tiempo de ejecucion, ke se irian al garete, pero weno, al menos evitamos una salida descontrolada del programa, ke no es poco.

Salu2...

P.D.: Nadie ha implementado recuperacion del Device en su motor? No me puedo creer :(  
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

Helius

 Yo lo implementé en mi juego Helium 3D.

La verdad es que es una chapuza, lo que hace es lo siguiente:

HRESULT Result = m_pDispD3D->Present(NULL, NULL, m_pManager->DaHwnd(), NULL);

while(Result == D3DERR_DEVICELOST)
{
 ResetFin();
 m_pNivel->ResetFin();
 //Keep testing the level until it says we
 //can reset.
 while(Result != D3DERR_DEVICENOTRESET)
 {
  //Give up control to other applications
  Sleep(1000);

  //Pump messages in order to respond to messages
  //that may lead to restoration.
  MSG Message;
  PeekMessage(&Message, 0, 0, 0, PM_REMOVE);
  TranslateMessage(&Message);
  DispatchMessage(&Message);

  //Check to see if things are ready to be reset
  Result = m_pDispD3D->TestCooperativeLevel();
 }

 //Reset the device using the saved parameters
 ResetIni();
 m_pNivel->ResetIni();
}


Al intentar llamar a Present  comprueba si se ha perdido el device, en ese caso destruye todo lo que no se ha creado con POOL_MANAGED (de ahí las llamadas a ResetFin(); y m_pNivel->ResetFin(); ).

Luego espera hasta que el device se recupera y puede ser reseteado, sólo entonces lo resetea (ResetIni(); m_pNivel->ResetIni(); ), es decir, vuelve a incializar el device y todos los recursos que no sean POOL_MANAGED.

Puedes ver el código entero en mi web. Por lo menos al hacerle un ALT+TAB vuelve al juego de nuevo, aunque tarda un poquillo ;)
Geardome Devlog
Tutoriales sobre DirectX 9, Nintendo DS y PSP.

[EX3]

 Helius, mil gracias por tu ayuda! Ya funciona correctamente :lol:

Aun ya resuelto el problema kiero mostrar un metodo en el ke estuve trabajando esta ultima semana y ke casi funcionaba a la perfeccion:
Subrutina ResetarDevice()
//Generamos un subdirectorio en el directorio temporal de windows que tendra como nombre el hWnd de la ventana donde trabaja DirectX.
CrearDirectorioTemporal()

//Guardamos los graficos en memoria en el directorio temporal.
SalvarTexturas()
SalvarSuperficies()

//Cerramos Direct3D:
Terminar()

//Iniciamos Direct3D de nuevo con los parametros anteriormente usados y guardados en una variable:
IniciarDirect3D()

//Volvemos a configurar los RenderStates:
ConfigurarDevice()

//Volvemos a cargar y configurar la fuente de texto anteriormente utilizada:
CargarFuenteDeTexto()

//Volvemos a cargar los graficos en memoria:
CargarTexturas()
CargarSuperficies()

//Eliminamos los archivos y el directorio temporal:
EliminarArchivosTemporales()
EliminarDirectorioTemporal()

Fin Subrutina

El codigo real es muy extenso por eso he puesto el pseudocodigo, para ke al menos veais la idea. Este metodo me funcionaba con todos los ejemplos de la dx_lib32 pero no en el TLSA Engine donde se colgaba todo el rato intentando resetear una vez y otra y otra sin saber la causa. El metodo estaba pensado para que funcionase con varios programas simultaneamente ya ke a veces somos tan brutos (algunos :rolleyes:) de ejecutar dos veces el mismo juego y asi no habria problemas a la hora de resetear los devices ya que los graficos se guardarian en directorios propios de cada aplicacion. Se ke es un pelin chapucilla pero era lo unico ke vi ke podia funcionar.

Lo dicho Helius, muchas gracias ;)

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

Loover

 Entonces, ¿para que  un simple ALT+TAB funcione correctamente es necesario recargar todos los gráficos?  :blink:

No lo entiendo, ¿entonces como es que un ALT+TAB en juegos como el Quake 3 o muchos otros es tán rápido?
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

[EX3]

 Si lo dices por mi ultimo post ten en cuenta que fue una idea que intente implementar antes de que Helius me diese la solucion al problema. Si realizas el reseteo con Direct3D y cargas las texturas y resto de recursos graficos como POOL_MAGNAGED no tienes que volver a recargar dichos recursos, y muy lento no es, al menos a mi me va rapido.

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

Loover

 Bueno el Quake 3 usa OGL, xD. Pero bueno, apliquese lo mismo a cualquier juego que tras un ALT+TAB tarde nada en Direct3d.
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

Loover

 ¿Si las cargo como POOL_MAGNAGED tras perder el device es como sino las cargara sino que las coge de memoria?

¿Cómo solucionaste lo de las texturas que hayan cambiando en tiempo de ejecución?
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.