【问题标题】:MTKView - Draw on to Two Views at OnceMTKView - 一次绘制两个视图
【发布时间】:2019-01-22 11:55:19
【问题描述】:

我得到了什么

我正在关注 Apple 示例代码 AVCamPhotoFilter 以在 MTKView 上显示相机源。

我想做什么

除了上面的MTKView,我还需要显示第二个MTKView。但是,第二个将显示与第一个完全相同的内容。所以我不想重复代码并做两次工作。

当前绘制方法

override func draw(_ rect: CGRect) {
        var pixelBuffer: CVPixelBuffer?
        var mirroring = false
        var rotation: Rotation = .rotate0Degrees

        syncQueue.sync {
            pixelBuffer = internalPixelBuffer
            mirroring = internalMirroring
            rotation = internalRotation
        }

        guard let drawable = currentDrawable,
            let currentRenderPassDescriptor = currentRenderPassDescriptor,
            let previewPixelBuffer = pixelBuffer else {
                return
        }

        // Create a Metal texture from the image buffer
        let width = CVPixelBufferGetWidth(previewPixelBuffer)
        let height = CVPixelBufferGetHeight(previewPixelBuffer)

        if textureCache == nil {
            createTextureCache()
        }
        var cvTextureOut: CVMetalTexture?
        CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
                                                  textureCache!,
                                                  previewPixelBuffer,
                                                  nil,
                                                  .bgra8Unorm,
                                                  width,
                                                  height,
                                                  0,
                                                  &cvTextureOut)
        guard let cvTexture = cvTextureOut, let texture = CVMetalTextureGetTexture(cvTexture) else {
                print("Failed to create preview texture")

                CVMetalTextureCacheFlush(textureCache!, 0)
                return
        }

        if texture.width != textureWidth ||
            texture.height != textureHeight ||
            self.bounds != internalBounds ||
            mirroring != textureMirroring ||
            rotation != textureRotation {
            setupTransform(width: texture.width, height: texture.height, mirroring: mirroring, rotation: rotation)
        }

        // Set up command buffer and encoder
        guard let commandQueue = commandQueue else {
            print("Failed to create Metal command queue")
            CVMetalTextureCacheFlush(textureCache!, 0)
            return
        }

        guard let commandBuffer = commandQueue.makeCommandBuffer() else {
            print("Failed to create Metal command buffer")
            CVMetalTextureCacheFlush(textureCache!, 0)
            return
        }

        guard let commandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: currentRenderPassDescriptor) else {
            print("Failed to create Metal command encoder")
            CVMetalTextureCacheFlush(textureCache!, 0)
            return
        }

        commandEncoder.label = "Preview display"
        commandEncoder.setRenderPipelineState(renderPipelineState!)
        commandEncoder.setVertexBuffer(vertexCoordBuffer, offset: 0, index: 0)
        commandEncoder.setVertexBuffer(textCoordBuffer, offset: 0, index: 1)
        commandEncoder.setFragmentTexture(texture, index: 0)
        commandEncoder.setFragmentSamplerState(sampler, index: 0)
        commandEncoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4)
        commandEncoder.endEncoding()

        commandBuffer.present(drawable) // Draw to the screen
        commandBuffer.commit()
    }

问题

有没有一种方法可以简单地将纹理传递给第二个MTKView 并在不做两次工作的情况下进行绘制?

【问题讨论】:

    标签: ios swift xcode metal metal-performance-shaders


    【解决方案1】:

    如果将第一个MTKViewframebufferOnly 属性设置为false,则可以提交从其可绘制纹理读取的命令。然后,您可以使用 blit 命令编码器从第一个可绘制对象的纹理复制到第二个(如果它们兼容)。否则,您可以将四边形绘制到第二个可绘制对象的纹理上,并将第一个可绘制对象的纹理作为四边形纹理的来源。

    就个人而言,我认为我希望所有渲染都转到您自己创建的纹理(而不是任何可绘制的纹理)。然后,将其复制/绘制到两个可绘制纹理。

    在任何情况下,如果您需要两个视图完美同步更新,您应该将两个视图的 presentsWithTransaction 设置为 true,同步等待(使用 -waitUntilScheduled)等待(至少)执行复制/绘制到可绘制纹理,然后直接在两个可绘制对象上调用-present。 (也就是说,不要在命令缓冲区上使用-presentDrawable:。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-10
      • 2014-08-13
      • 1970-01-01
      • 2019-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多