0

Je suis assez nouveau sur DirectX et Direct2D. J'expérimente avec SharpDx pour décharger le travail sur le matériel plutôt que consommer le CPU pour le rendu constant.Augmentation de la mémoire avec le dessin de bitmap SharpDX

J'ai un pipeline de fondation de médias. J'ai implémenté un moteur de rendu personnalisé. Mon application est en C# et WPF.

Je récupère les pixels bruts de mon pipeline et les envoie vers WritableBitamps qui met à jour un contrôle Image. Apparemment, il y a un problème connu avec le contrôle Image qui tient sur les pinceaux. Mon application peut jeter des exceptions de mémoire à ce problème. Si le cadre d'origine n'est pas grand, le problème n'est pas perceptible. Disons 800x600 vidéo.

Je rencontre d'autres problèmes si une vidéo 1920 par 1080 est en cours de lecture.

J'ai essayé de créer un BitmapSource et de mettre à jour le tampon arrière (pour empêcher la création constante de bits) et cela n'a pas aidé. Dans certains cas, la mémoire se développe comme un fou. A partir de maintenant, je crée de nouveaux bitamps pour chaque dessin. Je sais que c'est une solution temporaire pour les tests.

Alors maintenant, ce que j'expérimente est SharpDx. J'utilise un wrapper appelé D2DControl qui enveloppe un code D3DImage et setup et permet de créer un contrôle WPF que vous pouvez brancher dans votre vue (Similaire à D3DImage D2DControl est dérivé de D3DImage) Je sais que certaines personnes détestent les liens externes mais voici le lien au cas où quelqu'un est intéressé.

https://github.com/dalance/D2dControl/tree/master/D2dControl

Qu'est-ce que cette enveloppe fait est qu'il cache beaucoup de détails. Il expose une méthode Render() qui permet au dessin de se produire.

Voici ce que j'ai. J'ai essayé des variantes de création de nouveaux bitouts sur chaque rendu ou de réutilisation de celui-ci. Sur une image vidéo 1920x1080, la mémoire saute 300mg à la fois jusqu'à ce qu'elle atteigne 1,2 Go et s'arrête.

Je suis mise à l'échelle de la bitmap car le D3DImage ne met pas à l'échelle le bit de bit. Avec les contrôles Image, vous pouvez écrire un fichier bitmap volumineux et l'adapter à la taille de la vue. Avec ce code, l'image est rognée si elle est plus grande que le conteneur. Quoiqu'il en soit, la transformation ne change pas le résultat. L'action de CopyFromMemory et DrawBitamp augmente la mémoire.

Donc, mes questions sont: 1) Est-ce que ce que je fais a du sens? 2) Y a-t-il d'autres choses que je peux faire pour éviter les problèmes de mémoire?

Merci d'avoir pris le temps de lire ceci.

Répondre

1

Je vois que vous essayez de résoudre votre tâche par copie de Unmanaged memory dans le Managed memory et de nouveau dans Unmanaged memory. Tout d'abord, vous obtenez des pixels bruts pour le rendu - ce n'est pas une bonne idée, car le code ne peut pas utiliser DirectX Video Acceleration pour l'accélération du décodage - il décode dans la mémoire de la CPU. Deuxièmement, dans votre code il y a Bitmap backBufferBmp - c'est un objet de mémoire géré et vous ne pouvez pas l'effacer de la mémoire rapide, mais vous pouvez essayer GC.Collect Method(). Troisièmement, dans le processus de rendu des pixels de backBufferBmp dans la copie de la mémoire système dans la mémoire vidéo de WPF. Donc, dans votre solution, il y a beaucoup de goulots d'étranglement.Je peux recommander essayer System.Windows.Interop.D3DImage - il permet de joindre Direct3DSurface9 dans le processus de rendu WPF sans copie de la mémoire, alors vous pouvez utiliser Direct3DSurface9 comme une cible de rendu pour l'utilisation DirectX Video Acceleration. Toutefois, il doit écrire un nouveau moteur de rendu personnalisé pour le pipeline Media Foundation.

Donc, il n'y a pas magic ligne de code pour résoudre votre problème - vous devez réécrire votre code à partir du zéro.

Cordialement.

P.S. vous pouvez trouver exemple d'utilisation de System.Windows.Interop.D3DImage par liaison - WPFViewerEVRDisplay

+0

Merci pour les informations détaillées! J'ai regardé ton projet. Tout d'abord, bon travail! Donc voici ce que je vois avec D2DControl. L'API utilise une surface Texture2D et se connecte à D3DImage en interne. La surface n'est pas exposée, donc le backbuffer ne peut pas être touché directement. En regardant la base de code SharpDX, il semble que l'objet Bitamp utilise un pointeur natif pour la mémoire pour les pixels. Je ne suis pas fan de GC.Collect. Il est très cher si repeatdly appelé. Nous avions de l'ancien code dans notre API, qui avait un appel GC.Collect toutes les 2ms et le fait de le supprimer rendait le code 10 fois plus rapide. – KevinSP

+0

L'objet Bitamp n'est pas un System.Drawing.Bitamp. C'est un SharpDX défini qui est censé être soutenu par le matériel. Au moins c'est ce que je pense. Je dois le confirmer – KevinSP

+0

Salut, je voudrais vous signaler que 'SharpDX.Direct2D1.Bitmap' a BEAUCOUP de surcharge' CopyFromMemory' fonction. Par exemple 'public void CopyFromMemory (octet [] mémoire, int pitch)'; et 'public void CopyFromMemory (pointeur IntPtr, int pitch);' - prend d'abord la mémoire gérée C#, et une autre prend le pointeur sur la mémoire non gérée. De votre code 'backBufferBmp.CopyFromMemory (sampleData.Pixels, sampleData.Stride);' il ressemble à 'sampleData.Pixels' est' byte [] '- c'est de la mémoire gérée.S'il s'agit d'un vrai 'byte []' - alors vous avez un processus de copie - 'Unmanaged memory' ->' Managed memory' -> 'Unmanaged memory'. –

0

Mise à jour:

Merci beaucoup pour @Evgeny Pereguda réponses détaillées. Cela m'a aidé à réaliser certaines des pensées que je dominais. J'ai pris la route de l'emballage des interfaces Direct3D9 en Cli/C++.

Dans son projet exemple, il a utilisé ComImport pour insérer le côté Direct3D9 en C#. Cela nécessite quelques connaissances concernant les DLL elle-même.

Par la documentation COM côté C#, vous ne pouvez pas tirer partiellement sur une interface. C'est soit tout ou juste la classe Guida et le nom. Dans le cas de Direct3D9, il y a beaucoup de fonctions et essayer de les définir toutes (puisque j'utilise très probablement une méthode hors de toute la classe) est une surcharge. Sa méthode utilise la réflexion pour extraire la méthode basée sur l'adresse de la méthode à partir de la DLL, ce qui nécessite de coder en dur l'adresse de la méthode. J'ai opté pour corriger un emballage pour les classes Direct3D9 dont j'avais besoin en utilisant les fichiers d'en-tête et D3D9.lib puisque je suis un peu sélecteur de choses sur les choses de codage dur.

J'ai créé un contrôle utilisateur complet qui peut être branché à nos applications.

Merci pour les conseils sur les problèmes de mémoire. Le meilleur chemin était d'utiliser de la mémoire non gérée et je ne savais pas que j'utilisais géré. La commutation qui a aidé à augmenter les performances et la mémoire gérée par beaucoup.

SharpDx est bon, mais beaucoup de détails sont cachés et j'aimerais avoir plus de contrôle.

A partir de maintenant, j'écris des pixels non gérés à mon pipeline et la mémoire fonctionne correctement.