-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from syjdev/task/add_AVCaptureSession
add CaptureSession & make a demo view
- Loading branch information
Showing
13 changed files
with
424 additions
and
138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 0 additions & 24 deletions
24
BlurDiscriminator-iOS/BlurDiscriminator-iOS/Base.lproj/Main.storyboard
This file was deleted.
Oops, something went wrong.
98 changes: 98 additions & 0 deletions
98
BlurDiscriminator-iOS/BlurDiscriminator-iOS/BlurDiscriminator/BlurDiscriminator.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// | ||
// BlurDiscriminator.swift | ||
// BlurDiscriminator-iOS | ||
// | ||
// Created by syjdev on 2021/01/23. | ||
// | ||
|
||
import Metal | ||
import MetalPerformanceShaders | ||
import MetalKit | ||
|
||
|
||
class BlurDiscriminator { | ||
|
||
let mtlDevice: MTLDevice | ||
let library: MTLLibrary | ||
var commandQueue: MTLCommandQueue? | ||
let computePipelineState: MTLComputePipelineState | ||
|
||
init() throws { | ||
guard let mtlDevice = MTLCreateSystemDefaultDevice() else { | ||
throw BlurDiscriminatorError.mtlDeviceWasCorrupted | ||
} | ||
|
||
guard MPSSupportsMTLDevice(mtlDevice) else { | ||
throw BlurDiscriminatorError.unsupportedDevice | ||
} | ||
|
||
self.mtlDevice = mtlDevice | ||
self.commandQueue = self.mtlDevice.makeCommandQueue() | ||
|
||
do { | ||
self.library = try self.mtlDevice.makeLibrary(source: shaderFunction, options: nil) | ||
} catch { | ||
throw error | ||
} | ||
|
||
guard let kernelFunction = self.library.makeFunction(name: "changeToGrayscale") else { | ||
throw BlurDiscriminatorError.unsupportedDevice | ||
} | ||
|
||
self.computePipelineState = try self.mtlDevice.makeComputePipelineState(function: kernelFunction) | ||
} | ||
|
||
func calculateGrayscaledPixelVariance(cgImage: CGImage) -> Result<Float, Error> { | ||
if self.commandQueue == nil { | ||
self.commandQueue = self.mtlDevice.makeCommandQueue() | ||
} | ||
|
||
guard let commandQueue = self.commandQueue, | ||
let commandBuffer = commandQueue.makeCommandBuffer(), | ||
let commandEncoder = commandBuffer.makeComputeCommandEncoder() | ||
else { | ||
return .failure(BlurDiscriminatorError.commandWasCorrupted) | ||
} | ||
|
||
let textureLoader = MTKTextureLoader(device: self.mtlDevice) | ||
let texture: MTLTexture | ||
do { | ||
texture = try textureLoader.newTexture(cgImage: cgImage, options: nil) | ||
} catch { | ||
return .failure(BlurDiscriminatorError.failedToMakeTexture) | ||
} | ||
|
||
let imageDescriptor = MPSImageDescriptor(channelFormat: .float32, width: cgImage.width, height: cgImage.height, featureChannels: 1) | ||
let inputImage = MPSImage(texture: texture, featureChannels: 3) | ||
let grayscaledImage = MPSTemporaryImage(commandBuffer: commandBuffer, imageDescriptor: imageDescriptor) | ||
|
||
commandEncoder.setComputePipelineState(self.computePipelineState) | ||
commandEncoder.setTexture(inputImage.texture, index: 0) | ||
commandEncoder.setTexture(grayscaledImage.texture, index: 1) | ||
|
||
commandEncoder.dispatchThreadgroups(texture: texture, computePipelineState: self.computePipelineState) | ||
commandEncoder.endEncoding() | ||
|
||
let laplacian = MPSImageLaplacian(device: self.mtlDevice) | ||
let laplacianImage = MPSTemporaryImage(commandBuffer: commandBuffer, imageDescriptor: imageDescriptor) | ||
laplacian.encode(commandBuffer: commandBuffer, sourceImage: grayscaledImage, destinationImage: laplacianImage) | ||
|
||
let imageStatisticsMeanAndVariance = MPSImageStatisticsMeanAndVariance(device: self.mtlDevice) | ||
let varianceDescriptor = MPSImageDescriptor(channelFormat: .float32, width: 2, height: 1, featureChannels: 1) | ||
let statisticsImage = MPSImage(device: self.mtlDevice, imageDescriptor: varianceDescriptor) | ||
imageStatisticsMeanAndVariance.encode(commandBuffer: commandBuffer, sourceImage: laplacianImage, destinationImage: statisticsImage) | ||
|
||
commandBuffer.commit() | ||
commandBuffer.waitUntilCompleted() | ||
|
||
var variance: Float = 0 | ||
statisticsImage.texture.getBytes( | ||
&variance, | ||
bytesPerRow: statisticsImage.texture.width * MemoryLayout<Float>.size, | ||
from: MTLRegionMake2D(1, 0, 1, 1), | ||
mipmapLevel: 0 | ||
) | ||
|
||
return .success(variance) | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
BlurDiscriminator-iOS/BlurDiscriminator-iOS/BlurDiscriminator/BlurDiscriminatorError.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// | ||
// BlurDiscriminatorError.swift | ||
// BlurDiscriminator-iOS | ||
// | ||
// Created by syjdev on 2021/01/23. | ||
// | ||
|
||
import Foundation | ||
|
||
enum BlurDiscriminatorError: Error { | ||
case mtlDeviceWasCorrupted | ||
case unsupportedDevice | ||
case shaderFunctionWasCorrupted | ||
case commandWasCorrupted | ||
case failedToMakeTexture | ||
} |
27 changes: 27 additions & 0 deletions
27
...rDiscriminator-iOS/BlurDiscriminator/MTLComputeCommandEncoder+encodeThreadgroupSize.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// | ||
// MTLComputeCommandEncoder+encodeThreadgroupSize.swift | ||
// BlurDiscriminator-iOS | ||
// | ||
// Created by syjdev on 2021/01/23. | ||
// | ||
|
||
import Metal | ||
|
||
|
||
extension MTLComputeCommandEncoder { | ||
/// calculate a suitable threadgroups, then call dispatchThreadgroups. | ||
/// | ||
/// You can see a apple's guide, "https://developer.apple.com/documentation/metal/calculating_threadgroup_and_grid_sizes" | ||
/// | ||
func dispatchThreadgroups(texture: MTLTexture, computePipelineState: MTLComputePipelineState) { | ||
let width = computePipelineState.threadExecutionWidth | ||
let height = computePipelineState.maxTotalThreadsPerThreadgroup / width | ||
let threadsPerThreadgroup = MTLSizeMake(width, height, 1) | ||
|
||
let threadgroupsPerGrid = MTLSize(width: (texture.width + width - 1) / width, | ||
height: (texture.height + height - 1) / height, | ||
depth: 1) | ||
|
||
self.dispatchThreadgroups(threadgroupsPerGrid, threadsPerThreadgroup: threadsPerThreadgroup) | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
BlurDiscriminator-iOS/BlurDiscriminator-iOS/BlurDiscriminator/ShaderFunctions.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// | ||
// ShaderFunctions.swift | ||
// BlurDiscriminator-iOS | ||
// | ||
// Created by syjdev on 2021/01/23. | ||
// | ||
|
||
import Foundation | ||
|
||
|
||
internal let shaderFunction = """ | ||
using namespace metal; | ||
constant float3 rgbDegree = float3(0.3333, 0.3333, 0.3333); | ||
kernel void changeToGrayscale(texture2d<float, access::read> input [[ texture(0) ]], | ||
texture2d<float, access::write> output [[ texture(1) ]], | ||
uint2 gid [[ thread_position_in_grid ]]) | ||
{ | ||
if((gid.x < output.get_width()) && (gid.y < output.get_height())) | ||
{ | ||
float4 pixel = input.read(gid); | ||
float grayscaledRgb = dot(pixel.rgb, rgbDegree); | ||
float4 grayscaledPixel = float4(grayscaledRgb, grayscaledRgb, grayscaledRgb, 1.0) * 255.0; | ||
output.write(grayscaledPixel, gid); | ||
} | ||
} | ||
""" |
Oops, something went wrong.