Bonjour,

Je suis surpris par la forte consommation CPU de DirectX dans WPF. Environ 30% pour un scène mise à jour 30 fois par seconde sur Windows XP (sachant que le PC de test est plus puissant que le PC qui recevra l'application...).

J'utilise une DLL codée en C++ avec Directx9 et j'affiche le rendu dans WPF à l'aide d'un D3DImage. J'ai repris le code d'exemple de Microsoft que l'on trouve ici : http://msdn.microsoft.com/en-us/library/cc656785.aspx

Dans la fonction de rendu, je limite le rafraichissement pour respirer un peu (sinon, les événements souris sont asphyxiés !). C'est une limitation grossière, mais une mesure du nombre de FPS dans le code Directx me donne 30 images/seconde. J’arrangerai ça plus tard .

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 
        private long _PreviousFrameTime = 0;
        void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            RenderingEventArgs args = (RenderingEventArgs)e;
 
            // Control FPS
            long elapsedTicks = DateTime.Now.Ticks - _PreviousFrameTime;
            TimeSpan elapsedSpan = new TimeSpan(elapsedTicks);
 
            if (elapsedSpan.TotalMilliseconds < 1000d / 40d)
               return;
 
            // It's possible for Rendering to call back twice in the same frame 
            // so only render when we haven't already rendered in this frame.
            if (d3dimg.IsFrontBufferAvailable && _lastRender != args.RenderingTime)
            {
                IntPtr pSurface;
                HRESULT.Check(GetBackBufferNoRef(out pSurface));
                if (pSurface != IntPtr.Zero)
                {
                    d3dimg.Lock();
                    // Repeatedly calling SetBackBuffer with the same IntPtr is 
                    // a no-op. There is no performance penalty.
                    d3dimg.SetBackBuffer(D3DResourceType.IDirect3DSurface9, pSurface);
                    HRESULT.Check(Render());
                    d3dimg.AddDirtyRect(new Int32Rect(0, 0, d3dimg.PixelWidth, d3dimg.PixelHeight));
                    d3dimg.Unlock();
 
                    _lastRender = args.RenderingTime;
                }
            }
            _PreviousFrameTime = DateTime.Now.Ticks;
     }
L'outil Visual profiler me dit qu'il passe 20% dans l' "UCE process queue". Je ne sais pas trop ce que c'est, mais quand je commente AddDirtyRect(), l'occupation CPU tend vers 0 (ne pas faire le new à chaque cycle ne change strictement rien).

Qu'en pensez-vous ?

EDIT: Question subsidiaire : sur un PC équipé d'un XP SP3, le d3dimg.IsFrontBufferAvailable passe à true deux fois, puis reste à false indéfiniment. Du coup l'application reste ouverte, mais la scène ne s'affiche pas...

Je n'ai pas de Visual Studio sur ce PC, donc j'ai des difficultés à déboguer...

Avez-vous une idée sur ce qui pourrait se passer ?