【问题标题】:osx metal doesn't renderosx 金属不渲染
【发布时间】:2016-02-10 11:52:15
【问题描述】:

我关注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);
}

【问题讨论】:

  • 对于OS X,您可以将MetalView 设为MTKView 的子类,如果您查看我在mhorga.org 博客上的Metal 教程,这实际上非常简单。
  • 我确实做到了。我有一个 MTKView 的工作示例,我只是想尝试让它在没有它的情况下工作。不过,感谢您的链接!

标签: swift macos 3d metal


【解决方案1】:

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

你几乎肯定想要一个 layer-backed 视图。为此,请覆盖makeBackingLayer 方法,您将在该方法中创建和配置您的金属层,然后将其返回。然后,在视图生命周期的早期(最好在其初始化程序中),将wantsLayer 属性设置为YES。这应该足以让您的图层出现在屏幕上。

【讨论】:

  • 所有这些都是正确的,这也表明除非你用CAMetalLayer 做一些你不能用MTKView 做的事情,否则你最好用后者。
  • @warrenm 非常感谢!这真的很有帮助。我阅读了您提到的文章,结果发现我所要做的就是为我的故事板中的视图启用 CA 层。我玩弄了代码,结果发现我不必重写任何方法,只需向现有层添加一个子层就足够了。
  • 对;切换该复选框足以使视图层支持。我应该提到这一点,但想给你一个超越 IB 的解决方案。
  • 感谢您的投票。如果此答案不适合您,请添加评论或提出新问题。
猜你喜欢
  • 2019-01-01
  • 1970-01-01
  • 2016-03-06
  • 1970-01-01
  • 1970-01-01
  • 2016-03-03
  • 1970-01-01
  • 2022-12-30
  • 2019-03-08
相关资源
最近更新 更多