osx金属不会渲染

时间:2016-02-10 11:52:16

标签: swift macos 3d metal

我跟着this tutorial,从iOS推断到OS X,一切都编译得很好,除了我没有任何渲染(甚至是清晰的颜色)没有任何错误。谁能请一看,告诉我这里我做错了什么?我不能像在教程中那样在iOS上测试这个,因为iOS模拟器还不支持Metal。

我有一个金属渲染的自定义视图。 我没有添加子图层(如教程中所示),因为图层是 nil 。我想我需要以某种方式激活,我不知道如何。

import Cocoa
import Metal
import QuartzCore

class MetalView: NSView {

    var device: MTLDevice!
    var pipelineState: MTLRenderPipelineState!
    var commandQueue: MTLCommandQueue!
    var renderPassDescriptor: MTLRenderPassDescriptor!
    var vertexBuffer: MTLBuffer!

    var drawable: CAMetalDrawable {
        return (layer as! CAMetalLayer).nextDrawable()!
    }

    override func awakeFromNib() {
        // Device
        device = MTLCreateSystemDefaultDevice()

        // Layer
        let metalLayer = CAMetalLayer()
        metalLayer.device = device
        metalLayer.pixelFormat = .BGRA8Unorm
        metalLayer.framebufferOnly = true
        metalLayer.frame = frame
        layer = metalLayer

        // Pipeline State
        let defaultLibrary = device.newDefaultLibrary()
        let fragmentProgram = defaultLibrary!.newFunctionWithName("basic_fragment")
        let vertexProgram = defaultLibrary!.newFunctionWithName("basic_vertex")

        let pipelineStateDescriptor = MTLRenderPipelineDescriptor()
        pipelineStateDescriptor.vertexFunction = vertexProgram
        pipelineStateDescriptor.fragmentFunction = fragmentProgram
        pipelineStateDescriptor.colorAttachments[0].pixelFormat = .BGRA8Unorm

        do
        {
            try pipelineState = device.newRenderPipelineStateWithDescriptor(pipelineStateDescriptor)

        }
        catch let error as NSError {
            NSLog("Failed to create pipeline state, error \(error)")
        }

        // Command Queue
        commandQueue = device.newCommandQueue()

        // Render Pass Descriptor
        renderPassDescriptor = MTLRenderPassDescriptor()
        renderPassDescriptor.colorAttachments[0].texture = drawable.texture
        renderPassDescriptor.colorAttachments[0].loadAction = .Clear
        renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColor(red: 0.75, green: 0.5, blue: 0.0, alpha: 1.0)

        // Vertex Buffer
        let vertexData:[Float] = [
             0.0,  1.0, 0.0,
            -1.0, -1.0, 0.0,
             1.0, -1.0, 0.0
        ]
        vertexBuffer = device.newBufferWithBytes(vertexData, length: vertexData.count * sizeofValue(vertexData[0]), options: MTLResourceOptions())
    }

    override func drawRect(dirtyRect: NSRect) {
        let commandBuffer = commandQueue.commandBuffer()
        let renderEncoder = commandBuffer.renderCommandEncoderWithDescriptor(renderPassDescriptor)
        renderEncoder.setRenderPipelineState(pipelineState)
        renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, atIndex: 0)
        renderEncoder.drawPrimitives(.Triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1)
        renderEncoder.endEncoding()

        commandBuffer.presentDrawable(drawable)
        commandBuffer.commit()
    }

}

我有以下着色器代码:

#include <metal_stdlib>
using namespace metal;

struct VertexIn
{
    packed_float3 position;
};

vertex float4 basic_vertex(
    const device VertexIn* vertex_array [[ buffer(0) ]],
    unsigned int vertex_id [[ vertex_id ]])
{
    return float4(vertex_array[vertex_id].position, 1.0);
}

fragment half4 basic_fragment()
{
    return half4(1.0);
}

1 个答案:

答案 0 :(得分:3)

直接设置视图的layer属性是必要的,但不足以创建所谓的图层托管视图。您可以阅读有关图层托管和图层支持here之间的区别。

您几乎肯定需要图层支持的视图。要执行此操作,请覆盖makeBackingLayer方法,您将在其中创建和配置Metal图层,然后将其返回。然后,在视图的生命周期的早期(理想情况下在其初始化程序中),将wantsLayer属性设置为YES。这足以让您的图层在屏幕上显示。