Renderizar escena 3D en sistema bloqueado

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 mediante un servicio web. El problema es que para renderizar cualquier cosa, necesito un dispositivo Direct3d. ¿Hay alguna forma de crear un dispositivo direct3d sin que un usuario haya iniciado sesión en el sistema y el escritorio no esté bloqueado?

Si eso no es posible, ¿alguien conoce 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 muestre 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 forma, también podría implementar un nuevo renderizador usando opengl o cualquier otra tecnología que permita renderizar sin tener una forma visible.

Edit:

Lo que tengo hasta ahora es esto:

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 mínimo de WindowsService. 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 a interactuar con el escritorio activo. cuando ejecuto el servicio como una cuenta de sistema local, el escritorio y la estación de ventana funcionan, pero el número de GraphicsAdapters sigue siendo 0, cuando ejecuto el servicio con una cuenta de usuario dedicada, ni siquiera puedo abrir WindowStation. ¿Hay algo más que pueda probar o que estoy haciendo mal? Estoy probando esto en una máquina con Windows 7, mientras estoy conectado, ya que la depuración se vuelve muy difícil de lo contrario. ¿Podría ser esto un problema?

Muchas Gracias

preguntado el 16 de mayo de 11 a las 17:05

2 Respuestas

En los días de XP, trabajé en un proyecto que invocó con éxito la representación de hardware Direct3D desde un servicio en una máquina sin nadie conectado a la consola. Olvidé por completo los (ingeniosos) detalles, pero requirió algún uso de la API "Window Station y funciones de escritorio" para conseguir de alguna manera un HWND utilizable. Sin embargo, es probable que el sistema operativo más nuevo / servidor sea completamente diferente de todos modos con todas las nuevas cosas de seguridad.

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

  • NVidia parece estar desarrollando mucho su material GPGPU / CUDA con servidores sin cabeza en mente. Simplemente funciona. Sin embargo, significa reimplementar completamente sus cosas en una API sin gráficos.
  • Microsoft RemoteFX (Server2008R2 y Win7) parece facilitar que las máquinas virtuales obtengan acceso a las GPU del servidor. (Perversamente, su opción más fácil podría ser ejecutar su renderizador en una máquina virtual).

contestado el 17 de mayo de 11 a las 01:05

Muchas gracias por la sugerencia de Window Stations, ¿podría intentar recordar algunas de las acciones necesarias para que esto funcione, ya que esto es casi exactamente lo que necesito? Por 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 poder crear un dispositivo válido. ¿Pero cómo? ;) - Goooool

Lo siento, fue hace demasiado tiempo y no estaba realmente involucrado con ese fragmento de código. Podría haber sido tan simple obtener el hwnd de escritorio 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 puedo recordar. - timday

En el caso de OpenGL, el uso de un contexto PBuffer podría funcionar para obtener aceleración de GPU incluso en un escritorio bloqueado; sin embargo, esto depende en gran medida del controlador, que puede configurar el PBuffer para que se dañe permanentemente mientras está bloqueado, por lo que YMMV. Le daría una oportunidad.

contestado el 16 de mayo de 11 a las 22:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.