2009-04-30 13 views
7

He creado un control de WPF (que hereda de FrameworkElement) que muestra un gráfico de baldosas que pueden ser criticada. Cada mosaico es de 256x256 píxeles a 24 ppp. He anulado OnRender. Allí, cargué cualquier nuevo mosaico (como BitmapFrame), luego dibujé todos los mosaicos visibles usando drawingContext.DrawImage.WPF render rendimiento con BitmapSource

Ahora, cada vez hay más de un puñado de nuevas tejas por rendir ciclo, la tasa de fotogramas de 60 fps cae a cero durante un segundo. Esto no es causado por la carga de las imágenes (que toma en el orden de milisegundos), ni por DrawImage (que no requiere tiempo, ya que simplemente llena una estructura de datos de renderización intermedia).

Mi conjetura es que el hilo se hacen en sí ahoga cada vez que se pone un gran número (~ 20) de los nuevos casos BitmapSource (es decir, los que ya no se había almacenado en caché). O pasa mucho tiempo convirtiéndolos a algún formato interno compatible con DirectX o puede ser un problema de almacenamiento en caché. No puede quedarse sin RAM de video; Perforator muestra picos por debajo de 60 MB, tengo 256 MB. Además, Perforator dice que todos los objetivos de render son acelerados por hardware, por lo que tampoco puede serlo.

Cualquier ideas serán bienvenidos!

Gracias de antemano

Daniel

@RandomEngy:
BitmapScalingMode.LowQuality reducido el problema un poco, pero no deshacerse de él. Ya estoy cargando mosaicos con la resolución deseada. Y no puede ser el controlador de gráficos, que está actualizado (Nvidia).
Estoy un poco sorprendido de saber que el escalado lleva tanto tiempo. De la forma en que lo entendí, un mapa de bits (independientemente de su tamaño) solo se carga como una textura Direct3D y luego se escala en hardware. De hecho, una vez que el mapa de bits se ha renderizado por primera vez, puedo cambiar su rotación y escala sin ningún otro congelamiento.

Respuesta

3

No es solo con una gran cantidad de imágenes. Solo una imagen grande es suficiente para mantener la representación hasta que se haya cargado, y eso puede ser bastante notorio cuando las dimensiones de la imagen comienzan a elevarse por miles.

Estoy de acuerdo con usted en que probablemente sea el hilo de renderizado: hice una prueba y el hilo de la interfaz de usuario todavía estaba felizmente enviando mensajes mientras se producía este retraso de intentar mostrar un mapa de bits completamente precapturado.

Se debe estar haciendo algún tipo de conversión o de preparación en la imagen, como si estuviera especulando. Intenté mitigar esto en mi aplicación "renderizando" pero ocultando la imagen y luego revelándola cuando tengo que mostrarla. Sin embargo, esto es menos que ideal porque las congelaciones de renderización suceden de todos modos.

(Editar)

Algunos de seguimiento: Después de una discusión sobre el alias MS WPF encontré lo que estaba causando los retrasos. En mi máquina Server 2008, era una combinación de controladores de video antiguos que no admiten el nuevo modelo de controlador WDDM y un retraso para redimensionar la imagen.

Si el tamaño de la imagen de origen es diferente del tamaño de la pantalla, que retrasará el hilo rendir ante la imagen aparece. De forma predeterminada, una imagen se establece en la calidad más alta, pero puede cambiar las opciones de escala para la representación llamando al RenderOptions.SetBitmapScalingMode(uiImage, BitmapScalingMode.LowQuality);. Una vez que hice eso, el misterioso congelamiento antes de mostrar una imagen desapareció. Una alternativa, si no le gusta la caída de calidad en la escala, es cargar BitmapImage con DecodePixelWidth/Height igual al tamaño en el que se mostrará. Luego, si carga BitmapImage en una cadena de fondo, no debe demorar su visualización.

0

Pruebe también estos;

/* ivis is declared in XAML <Image x:Name="iVis" UseLayoutRounding="True" SnapsToDevicePixels="True" /> */ 

iVis.Stretch = Stretch.None; 
RenderOptions.SetBitmapScalingMode(iVis, BitmapScalingMode.NearestNeighbor); 
RenderOptions.SetEdgeMode(iVis, EdgeMode.Aliased); 
VisualBitmapScalingMode = BitmapScalingMode.NearestNeighbor; 
iVis.Source = **** your bitmap source **** 

que estaba teniendo algunos problemas con el rendimiento al utilizar una gran cantidad de "A" canal de color de, esperar hasta después de que la imagen había prestado a escala funcionó mucho mejor para mí.

Además, como dijiste usando un gráfico de mosaico?

Normalmente utilizará TileBrush para establecer simplemente como el Pincel en su FrameworkElement. Si los está animando o agregando nuevos dinámicamente, puede generar sus pinceles y aplicarlos a su objeto a medida que avanza manualmente, asegúrese de congelarlos si puede. Además, VisualBitmapScalingMode es una propiedad de cualquier Visual.

Cuestiones relacionadas