3 votes

Comment utiliser un compute shaders personnalisé en utilisant metal et obtenir des performances très fluides ?

J'essaie d'appliquer les filtres de la caméra en direct par le biais de métal en utilisant les paramètres par défaut. MPSKernal filtres donnés par apple et custom compute Shaders .

Dans le compute shader j'ai fait l'encodage inplace avec le MPSImageGaussianBlur. et le code va ici

func encode(to commandBuffer: MTLCommandBuffer, sourceTexture: MTLTexture, destinationTexture: MTLTexture, cropRect: MTLRegion = MTLRegion.init(), offset : CGPoint) {

    let blur = MPSImageGaussianBlur(device: device, sigma: 0)
    blur.clipRect = cropRect
    blur.offset = MPSOffset(x: Int(offset.x), y: Int(offset.y), z: 0)

    let threadsPerThreadgroup = MTLSizeMake(4, 4, 1)
    let threadgroupsPerGrid = MTLSizeMake(sourceTexture.width / threadsPerThreadgroup.width, sourceTexture.height / threadsPerThreadgroup.height, 1)

    let commandEncoder = commandBuffer.makeComputeCommandEncoder()
    commandEncoder.setComputePipelineState(pipelineState!)
    commandEncoder.setTexture(sourceTexture, at: 0)
    commandEncoder.setTexture(destinationTexture, at: 1)

    commandEncoder.dispatchThreadgroups(threadgroupsPerGrid, threadsPerThreadgroup: threadsPerThreadgroup)

    commandEncoder.endEncoding()

    autoreleasepool {
        var inPlaceTexture = destinationTexture
        blur.encode(commandBuffer: commandBuffer, inPlaceTexture: &inPlaceTexture, fallbackCopyAllocator: nil)
    }
}

Mais parfois, la texture en place a tendance à échouer et finit par créer un effet de saccade sur l'écran.

Donc, si quelqu'un peut me suggérer la solution sans utiliser la texture in situ ou comment utiliser la fonction fallbackCopyAllocator ou en utilisant le compute shaders d'une manière différente, ce serait vraiment utile.

2voto

Satoshi Nakajima Points 111

J'ai fait suffisamment de codage dans ce domaine (application de shaders de calcul au flux vidéo provenant de la caméra), et le problème le plus courant que vous rencontrez est celui de la "réutilisation du tampon de pixels".

La texture métallique que vous créez à partir du tampon d'échantillonnage est sauvegardée dans un tampon de pixels, qui est géré par la session vidéo, et peut être réutilisée pour les images vidéo suivantes, à moins que vous ne conserviez la référence au tampon d'échantillonnage (conserver la référence à la texture métallique n'est pas suffisant).

N'hésitez pas à jeter un coup d'oeil à mon code à l'adresse suivante https://github.com/snakajima/vs-metal qui applique différents shaders de calcul à un flux vidéo en direct.

La méthode VSContext:set() prend le paramètre optionnel sampleBuffer en plus du paramètre texture, et conserve la référence au sampleBuffer jusqu'à ce que le calcul du shader soit terminé (dans la méthode VSRuntime:encode()).

0voto

Ian Ollmann Points 141

La méthode d'opération en place peut s'avérer difficile à mettre en œuvre, en fonction de ce que fait le filtre sous-jacent. S'il s'agit d'un filtre à passage unique pour certains paramètres, alors vous finirez par ne plus avoir de place pour ces cas.

Depuis que cette méthode a été ajoutée, MPS a ajouté un MTLHeap sous-jacent pour gérer la mémoire de manière un peu plus transparente pour vous. Si votre MPSImage n'a pas besoin d'être visualisée par le CPU et n'existe que pour une courte période de temps sur le GPU, il est recommandé d'utiliser une MPSTemporaryImage à la place. Lorsque le readCount atteint 0, le backing store sera recyclé dans le tas du MPS et rendu disponible pour d'autres MPSTemporaryImages et d'autres ressources temporaires utilisées en aval. De même, le backing store n'est alloué à partir du tas que lorsque cela est absolument nécessaire (par exemple, lorsque la texture est écrite ou que .texture est appelé).

L'utilisation d'images temporaires devrait permettre de réduire considérablement l'utilisation de la mémoire. Par exemple, dans un graphe de réseau neuronal Inception v3, qui comporte plus d'une centaine de passes, le tas a pu réduire automatiquement le graphe à seulement quatre allocations.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X