2011-05-16 12 views
5

He escrito un motor de renderizado basado en Direct3D 9 en C# usando SlimDX. En un nuevo proyecto, ahora necesito distribuir imágenes de una escena 3D cargada usando un servicio web. El problema es que para poder renderizar algo necesito un dispositivo Direct3d. ¿Hay alguna manera de crear un dispositivo direct3d sin que el usuario inicie sesión en el sistema y el escritorio no esté bloqueado?Renderizar escena 3D en el sistema bloqueado

Si eso no es posible, ¿alguien sabe de alguna solución? Al final, necesito un ejecutable que se pueda ejecutar desde el planificador de tareas usando alguna cuenta de usuario local o un servicio, que periódicamente muestra imágenes de la escena desde ciertos puntos de vista.

El motor se divide en dos partes: el motor en sí y el renderizador. Entonces, si no hay otra manera, entonces también podría implementar un renderizador nuevo usando OpenGL o cualquier otra tecnología que permita renderizar sin tener una forma visible.

Editar:

Lo que tengo hasta ahora es la siguiente:

protected override void OnContinue() { 
     base.OnContinue(); 

     NativeFunctions.SafeWindowStationHandle hwinsta = NativeFunctions.WindowStation.OpenWindowStation(
      "WinSta0", 
      true, 
      NativeFunctions.AccessMask.WINSTA_ALL_ACCESS); 

     if(hwinsta == null || hwinsta.IsClosed || hwinsta.IsInvalid) 
      Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error()); 

     if(NativeFunctions.WindowStation.SetProcessWindowStation(hwinsta.DangerousGetHandle())) { 
      NativeFunctions.SafeDesktopHandle ptrDesktop = NativeFunctions.WindowStation.OpenInputDesktop(
       0, 
       true, 
       NativeFunctions.AccessMask.DESKTOP_CREATEWINDOW); 

      if(ptrDesktop.IsClosed || ptrDesktop.IsInvalid) 
       return; 

      if(!NativeFunctions.WindowStation.SetThreadDesktop(ptrDesktop.DangerousGetHandle())) 
       return; 

      Log log = Logger.Instance.CreateLog("DXService", true, true, false); 

      log.LogMessage("Desktop set, creating D3D-Object.", LOGMESSAGELEVEL.CRITICAL, true); 

      Direct3D direct3D = new Direct3D(); 
      log.LogMessage("Direct3D object created, creating device.", LOGMESSAGELEVEL.CRITICAL, true); 

      if(direct3D.AdapterCount == 0) { 
       log.LogMessage("FATAL: direct3D.AdapterCount == 0"); 
      } 
     } 
    } 

Esto es parte de un servicio de windows mínima. Puse el código importante en la función OnContinue porque es más fácil de depurar que el código de inicio. Le di a estos servicios el derecho de interactuar con el escritorio activo. cuando ejecuto el servicio como una cuenta de sistema local para que funcione el escritorio y la ventana, pero la cantidad de GraphicsAdapters sigue siendo 0, cuando ejecuto el servicio usando una cuenta de usuario dedicada, entonces ni siquiera puedo abrir la WindowStation. ¿Hay algo más que pueda intentar o que estoy haciendo mal? Estoy probando esto en una máquina con Windows 7, mientras estoy conectado ya que de lo contrario la depuración se vuelve muy difícil. ¿Podría ser esto un problema?

Gracias

Respuesta

0

En los días de XP, trabajé en un proyecto que invocó con éxito la representación de hardware de Direct3D desde un servicio en una máquina sin que nadie iniciara sesión en la consola. Me olvidé por completo de los detalles (ingeniosos), pero requirió cierto uso del "Window Station and Desktop Functions" API para conseguir de alguna manera un HWND utilizable. Sin embargo, el OS más nuevo/servidor es completamente diferente con todas las nuevas características de seguridad.

Me sorprendería si OpenGL funcionara mejor que Direct3D en esta área, aunque podría valer la pena intentarlo. Otras cosas que podría considerar:

  • NVidia parece estar desarrollando sus GPGPU/CUDA con servidores sin cabeza en mente. Simplemente funciona. Sin embargo, significa reimplementar por completo tus cosas en una API no gráfica.
  • Microsoft RemoteFX (Server2008R2 y Win7) parece facilitar que las máquinas virtuales tengan acceso a las GPU del servidor. (Perversamente, la opción más fácil podría ser simplemente ejecutar su procesador en una máquina virtual.)
+0

Muchas gracias por la pista a las estaciones de ventana, ¿podría tratar de recordar algunas de las acciones necesarias para que esto funcione, ya que es casi exactamente lo que necesito. Según lo que he leído hasta ahora, necesito ejecutar mi aplicación como un servicio, con privilegios para acceder al escritorio interactivo (agujero de seguridad) y luego, de alguna manera, debería ser capaz de crear un dispositivo válido. ¿Pero cómo? ;) – Gooo

+0

Lo siento, fue hace demasiado tiempo y no estaba realmente involucrado con ese código.Podría haber sido tan simple de obtener el escritorio hwnd para el escritorio utilizado para mostrar la pantalla de inicio de sesión (a través de EnumDesktopWindows?) O podría haber sido más complicado, realmente no lo recuerdo. – timday

0

En el caso de OpenGL usando un contexto pBuffer podría funcionar para obtener la aceleración de GPU en incluso un escritorio bloqueado; sin embargo, esto depende en gran medida del controlador, lo que puede configurar el PBuffer para daños permanentes mientras está bloqueado, por lo que YMMV. Yo le daría una oportunidad.

Cuestiones relacionadas