2017-07-20 3 views
3

Im essayant d'appliquer les filtres de caméra en direct à travers le métal en utilisant les filtres par défaut MPSKernal donnés par Apple et la coutume compute Shaders.Comment utiliser un shader de calcul personnalisé en utilisant du métal et obtenir une performance très lisse?

Dans shader Compute 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 inplace ont tendance à échouer et finalement il crée un effet de secousse sur l'écran.

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

+0

Pourquoi vous codant pour la 'blur' que vous appelez _after_' endEncoding() 'sur le codeur de commande? –

+0

@MatthijsHollemans j'ai utilisé encodeur de commande pour coder l'état du pipeline au GPU un langage compréhensible. Ceci est fait en créant le ** MTLLibrary ** et en créant une fonction, puis en créant un état de pipeline à encoder vers le ** encodeur de commande **. Et le but de l'encodeur de commande est de définir l'état du processus (dans ce cas, coder le shader de calcul vers le GPU). Une fois l'encodage terminé, dites au GPU qu'il est prêt à l'encoder sur le GPU. Merci. En attente de suggestions –

+0

Mon mauvais, j'ai mal interprété votre code. –

Répondre

1

Je l'ai fait assez de codage dans ce domaine (application informatique shaders à flux vidéo de la caméra), et le problème le plus courant que vous rencontrez est le problème « réutilisation tampon pixel ». La texture de métal que vous créez à partir du tampon d'échantillon est sauvegardée dans un tampon de pixels, géré par la session vidéo, et peut être réutilisé pour les trames vidéo suivantes, sauf si vous conservez la référence au tampon d'échantillon (conservation la référence à la texture métallique n'est pas suffisante).

N'hésitez pas à jeter un coup d'oeil à mon code au https://github.com/snakajima/vs-metal, qui applique différents shaders informatiques à un flux vidéo en direct. VSContext: La méthode set() prend le paramètre optionnel sampleBuffer en plus du paramètre de texture, et conserve la référence à sampleBuffer jusqu'à ce que le calcul du shader de calcul soit terminé (dans la méthode VSRuntime: encoder()).

+0

C'était assez d'information pour faire ce que je dois faire. Merci pour l'information. Je mettrai à jour sur ceci une fois que je l'intègre et le teste dans mon application. –