我跟着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);
}
答案 0 :(得分:3)
直接设置视图的layer
属性是必要的,但不足以创建所谓的图层托管视图。您可以阅读有关图层托管和图层支持here之间的区别。
您几乎肯定需要图层支持的视图。要执行此操作,请覆盖makeBackingLayer
方法,您将在其中创建和配置Metal图层,然后将其返回。然后,在视图的生命周期的早期(理想情况下在其初始化程序中),将wantsLayer
属性设置为YES
。这足以让您的图层在屏幕上显示。