2017-07-19 5 views
0

J'essaie d'appliquer les filtres de caméra en direct à travers le métal en utilisant les filtres MPSKernal par défaut donnés par Apple et personnalisés compute Shaders.Fuite de mémoire lorsque j'utilise des shaders de calcul personnalisés dans Metal

En appliquant les filtres personnalisés sur une vue de collection dans une grille avec la combinaison de valeurs par défaut et les fonctions de noyau personnalisées.

Il ressemble à l'application Clips.

enter image description here

Mais ce que je Mémorable est que en utilisant les filtres sur mesure il y a beaucoup de memory leaks par rapport aux fonctions du noyau par défaut données par Apple.

Je ne sais pas quelles erreurs j'ai faites, le cas échéant.

Voici mon shader de calcul personnalisé.

kernel void customFunction1(

         texture2d<float, access::read> inTexture [[texture(0)]], 

         texture2d<float, access::write> outTexture [[texture(1)]], 

         uint2 gid [[thread_position_in_grid]]){ 

const float4 colorAtPixel = inTexture.read(gid); 
const float4 outputColor = float4(colorAtPixel.r, colorAtPixel.g, colorAtPixel.b, 1); 

outTexture.write(outputColor, gid); 

} 

En ce qui concerne ma création de mon pipeline et l'envoi par des groupes de discussion le code va ici

let blur = MPSImageGaussianBlur(device: device, sigma: 0) 

    let threadsPerThreadgroup = MTLSizeMake(4, 4, 1) 
    let threadgroupsPerGrid = MTLSizeMake(destinationTexture.width/threadsPerThreadgroup.width, destinationTexture.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 { 
     let inPlaceTexture = UnsafeMutablePointer<MTLTexture>.allocate(capacity: 1) 
     inPlaceTexture.initialize(to: destinationTexture) 
     blur.encode(commandBuffer: commandBuffer, inPlaceTexture: inPlaceTexture, fallbackCopyAllocator: nil) 
    } 

L'état Pipeline avec la coutume Shader est créé comme ça.

 let defaultLibrary = device.newDefaultLibrary() 

     let kernelFunction = defaultLibrary!.makeFunction(name: name) 

     do { 
      pipelineState = try device.makeComputePipelineState(function: kernelFunction!) 
     } catch { 
      fatalError("Unable to create pipeline state") 
     } 

Et dans l'instrumentation, il montre qu'il ya une fuite dans certains Malloc 16 bytes et méthode [Mtkview draw].

La capture d'écran est illustrée ci-dessous.

enter image description here

Je veux aider à trouver où et comment le problème se produit à partir.

Merci.

Répondre

1

Il n'y a aucune raison d'attribuer explicitement un UnsafeMutablePointer pour stocker le paramètre de texture in-situ. Incidemment, c'est la source de votre fuite: vous allouez le pointeur, puis ne le libérez jamais.

Utilisez une variable locale pour passer la texture à la place:

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

Par ailleurs, vous (éventuellement) va avoir un mauvais moment si vous appelez la méthode encode en place sans fournir une solution de repli allocateur ou vérifiant la valeur de retour. L'encodage sur place échouera dans certaines situations, vous devez donc fournir une fermeture qui alloue une texture appropriée en cas d'échec.

+0

Cela a bien fonctionné. Je vous remercie. Mais pouvez-vous me suggérer comment implémenter l'allocateur de copie de secours. Je l'ai essayé mais il plante @warrenm. –