Проблемы (неправильный масштаб, соотношение сторон) при рендеринге MTKTexture в MTKView после применения вычислительных шейдеров - PullRequest
0 голосов
/ 30 мая 2019

Я пытаюсь обработать видеокадры с камеры, используя металлические шейдеры, и показать их пользователю.Проблема с отображением модифицированных кадров.Выходные данные содержат сложенные копии обработанного кадра, некоторые из которых обрезаны, и они не заполняют экран полностью.

PS Я новичок как в iOS, так и в металле

Пока что у меня естьопределили переменные, которые управляют этим: 1. Количество запущенных групп потоков 2. Размер рисования MTKView 3. Идентификатор выборки в металлическом шейдере

Я поэкспериментировал с ними без хорошего результата.

Нижекод и мой вывод

Функция, которая устанавливает 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)

    }

AVCaptureVideoDataOutputSampleBufferDelegate, используемый для преобразования CMSampleBuffer в MTLTexture

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 и отображение outputTexture до metalView

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

...