2009-04-30 10 views
7

나는 바둑판 식으로 배열 할 수있는 타일 그래픽을 표시하는 WPF 컨트롤 (FrameworkElement에서 상속)을 만들었습니다. 각 타일은 24bpp에서 256x256 픽셀입니다. OnRender를 재정의했습니다. 여기서 모든 새 타일을 (BitmapFrame으로)로드 한 다음 drawingContext.DrawImage를 사용하여 보이는 모든 타일을 그립니다.BitmapSource를 사용한 WPF 렌더링 성능

이제는 렌더링주기 당 새로운 타일이 여러 개있을 때마다 프레임 속도가 약 1 초 동안 60fps에서 0으로 떨어집니다. 이는 이미지로드 (밀리 초 단위로 소요) 또는 DrawImage (일부 중간 렌더링 데이터 구조 만 채우기 때문에 시간이 전혀 필요 없음)로 인해 발생하지는 않습니다.

내 생각에 렌더 스레드 자체가 새로운 BitmapSource 인스턴스 (즉, 이미 캐싱되지 않은 인스턴스)가 20 개 이상 (~ 20 개)이 될 때마다 렌더링 스레드 자체가 울립니다. 그것은 내부 DirectX 호환 형식으로 변환하는 데 많은 시간을 소비하거나 캐싱 문제 일 수 있습니다. 비디오 RAM이 부족할 수는 없습니다. Perforator는 60MB 이하의 최고점을 보여 주며, 256MB가 있습니다. 또한, Perforator는 모든 렌더 타겟이 하드웨어 가속화되어 있으므로 그렇게 할 수 없다고 말합니다.

통찰력을 얻으실 수 있습니다! 사전

다니엘

에서

감사

@RandomEngy :
BitmapScalingMode.LowQuality 문제가 조금 감소하지만, 그것을 제거하지 않았다. 이미 의도 한 해상도로 타일을로드하고 있습니다. 또한 최신 드라이버 인 그래픽 드라이버가 될 수 없습니다 (Nvidia).
스케일링에 많은 시간이 걸린다는 사실에 조금 놀랐습니다. 내가 이해할 수있는 방식으로 비트 맵 (크기에 관계없이)은 Direct3D 텍스처로로드 된 다음 하드웨어 스케일링됩니다. 사실 비트 맵이 처음 렌더링 된 후에는 더 이상 고정하지 않고도 회전 및 크기를 변경할 수 있습니다.

답변

3

수많은 이미지가있는 것은 아닙니다. 하나의 큰 이미지만으로는 이미지가로드 될 때까지 렌더링을 멈추기에 충분하며 이미지 크기가 수천 개에서 시작될 때 상당히 눈에. 수 있습니다.

아마 렌더 스레드라는 데 동의합니다. 테스트를 수행했으며 UI 지연 시간 동안 렌더링 지연이 완전히 캐시 된 BitmapImage를 표시하려고 시도하는 동안 UI 스레드가 여전히 메시지를 전달하고있었습니다.

추측 한 것처럼 이미지에서 일종의 변환 또는 준비 작업을 수행해야합니다. 내 응용 프로그램에서 "렌더링"하지만 이미지를 숨기고, 그것을 보여줄 필요가있을 때 그것을 드러내기로 이것을 완화하려고했습니다. 그러나 어쨌든 렌더링이 멈 추면 이상적이지 않습니다.

(편집)

일부 후속 : 나는 지연을 일으키는 것을 발견 MS WPF 별칭에 대한 논의 후. 내 Server 2008 컴퓨터에서는 새로운 WDDM 드라이버 모델을 지원하지 않는 오래된 비디오 드라이버와 이미지 크기 조정을위한 지연이 결합되었습니다.

원본 이미지 크기가 표시 크기와 다른 경우 이미지가 나타나기 전에 렌더링 스레드가 지연됩니다. 기본적으로 이미지는 최고 품질로 설정되지만 RenderOptions.SetBitmapScalingMode(uiImage, BitmapScalingMode.LowQuality);을 호출하여 렌더링의 배율 옵션을 변경할 수 있습니다. 일단 그렇게하면 이미지를 표시하기 전에 신비한 얼기가 사라졌습니다. 다른 방법으로, 스케일링의 품질 저하가 마음에 들지 않으면 DecodePixelWidth/Height를 표시 할 크기와 동일한 BitmapImage를로드하는 것입니다. 그런 다음 BitmapImage를 백그라운드 스레드에로드하면 표시가 지연되지 않아야합니다.

0

또한 시도해보십시오. 이미지가 나를 위해 더 나은 일을 확장 렌더링했다 때까지 기다리고, "A"채널 색상의 거대한 양을 사용하는 경우

/* 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 **** 

나는 성능 몇 가지 문제가 있었다.

또한 타일 그래픽을 사용한다고 말했습니까?

일반적으로 TileBrush을 사용하여 FrameworkElement에서 브러시로 설정하면됩니다. 동적으로 움직이거나 새로 추가하는 경우 브러시를 생성 한 다음 수동으로 이동하여 브러시를 개체에 적용 할 수 있습니다. 가능한 경우 고정하십시오. 또한 VisualBitmapScalingMode는 모든 Visual의 속성입니다.