osx 金属不渲染
osx metal doesn't render
我遵循了 this tutorial,从 iOS 推断为 OS X,一切都编译得很好,除了我没有得到任何渲染(甚至是清晰的颜色)没有任何错误.谁能看看并告诉我我在这里做错了什么?我无法像教程中那样在 iOS 上对此进行测试,因为 iOS Simulator 尚不支持 Metal。
我有一个 Metal Rendering 的自定义视图。
我没有添加子层(就像在教程中那样),因为该层是 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);
}
直接设置视图的 layer
属性 是必要的,但不足以创建所谓的 图层托管视图 。您可以阅读层托管和层支持之间的区别 here。
您几乎肯定想要一个 layer-backed 视图。为此,请覆盖 makeBackingLayer
方法,您将在该方法中创建和配置 Metal 层,然后 return 它。然后,在视图生命周期的早期(最好是在其初始化程序中),将 wantsLayer
属性 设置为 YES
。这应该足以让您的图层出现在屏幕上。
我遵循了 this tutorial,从 iOS 推断为 OS X,一切都编译得很好,除了我没有得到任何渲染(甚至是清晰的颜色)没有任何错误.谁能看看并告诉我我在这里做错了什么?我无法像教程中那样在 iOS 上对此进行测试,因为 iOS Simulator 尚不支持 Metal。
我有一个 Metal Rendering 的自定义视图。 我没有添加子层(就像在教程中那样),因为该层是 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);
}
直接设置视图的 layer
属性 是必要的,但不足以创建所谓的 图层托管视图 。您可以阅读层托管和层支持之间的区别 here。
您几乎肯定想要一个 layer-backed 视图。为此,请覆盖 makeBackingLayer
方法,您将在该方法中创建和配置 Metal 层,然后 return 它。然后,在视图生命周期的早期(最好是在其初始化程序中),将 wantsLayer
属性 设置为 YES
。这应该足以让您的图层出现在屏幕上。