应用计算着色器后将MTKTexture渲染到MTKView时出现问题(比例尺,纵横比不正确)

时间:2019-05-30 09:03:48

标签: ios swift image-processing metal metalkit

我正在尝试使用计算金属着色器处理来自摄像机的视频帧并将其显示给用户。问题在于显示修改后的框架。输出中包含处理过的帧的堆叠副本,其中某些副本被剪切,并且无法完全填满屏幕。

P.S我对iOS和金属都是陌生的

到目前为止,我已经确定了控制该变量的变量: 1.启动的线程组数 2. MTKView的可绘制尺寸 3.在金属着色器中采样ID

我玩这些游戏都没有好结果。

下面是代码和我的输出

设置MTKView的功能

func initMetalView() {

        metalView = MTKView(frame: view.frame, device: metalDevice)

        metalView.delegate = self
        metalView.framebufferOnly = false
        metalView.colorPixelFormat = .bgra8Unorm
        metalView.autoResizeDrawable = false
        metalView.drawableSize = CGSize(width: 1920, height: 1080)
        metalView.layer.transform = CATransform3DMakeRotation(CGFloat(Float.pi),0.0,1.0,0.0)

        view.insertSubview(metalView, at: 0)

    }

用于将CMSampleBuffer转换为MTLTexture的AVCaptureVideoDataOutputSampleBufferDelegate

extension ViewController: AVCaptureVideoDataOutputSampleBufferDelegate {

    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {

        // sample buffer -> image buffer -> CoreVideo metal texture -> MTL texture

        guard let cvImageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
            else { fatalError("can't get image buffer") }

        var textureCache: CVMetalTextureCache?

        guard CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, metalDevice, nil, &textureCache) == kCVReturnSuccess else { fatalError("cant create texture cache") }

        let width = CVPixelBufferGetWidth(cvImageBuffer)
        let height = CVPixelBufferGetHeight(cvImageBuffer)

        var imageTexture: CVMetalTexture?
        let result = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, textureCache!, cvImageBuffer, nil, MTLPixelFormat.bgra8Unorm, width, height, 0, &imageTexture)

        guard let unwrappedImageTexture = imageTexture,
            result == kCVReturnSuccess
            else { fatalError("failed to create texture from image") }

        inputTexture = CVMetalTextureGetTexture(unwrappedImageTexture)

    }
}

MTKViewDelegate用于在inputTexture上应用着色器,并显示outputTexturemetalView

extension ViewController: MTKViewDelegate {

    func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {

    }

    func draw(in view: MTKView) {

        guard let inputTexture = inputTexture,
            let commandQueue = commandQueue,
            let commandBuffer = commandQueue.makeCommandBuffer(),
            let encoder = commandBuffer.makeComputeCommandEncoder(),
            let pipelineState = pipelineState
        else { return }

        encoder.setComputePipelineState(pipelineState)

        encoder.setTextures([metalView.currentDrawable!.texture, inputTexture], range: 0..<2)

        encoder.dispatchThreadgroups(MTLSizeMake(inputTexture.width/16, inputTexture.height/16, 1), threadsPerThreadgroup: threadsPerBlock)
        // inputTexture w:1920, h:1080

        encoder.endEncoding()

        commandBuffer.present(metalView.currentDrawable!)
        commandBuffer.commit()

    }
}

金属计算着色器

#include <metal_stdlib>
using namespace metal;

kernel void blacky (texture2d<float, access::write> outTexture [[texture(0)]],
                   texture2d<float, access::read> inTexture [[texture(1)]],
                   uint2 id [[thread_position_in_grid]]) {

    uint2 flipped_id = uint2(id.y, id.x);
    float3 val = inTexture.read(flipped_id).rgb;
    float g = (val.r + val.g + val.b)/3.0;
    float4 out = float4(g, g, g, 1);
    outTexture.write(out.rgba, id);

}

您可以在此处查看当前输出:https://i.imgur.com/hVDox3U

0 个答案:

没有答案