MetalBasicTessellation.playground/Contents.swift
/* |
Copyright (C) 2016 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
Playground version of MetalBasicTessellation. |
*/ |
import Cocoa |
import Metal |
import MetalKit |
import PlaygroundSupport |
// Setup Metal |
let device = MTLCreateSystemDefaultDevice()! |
let commandQueue = device.makeCommandQueue() |
let mtkView = MTKView(frame: CGRect(x: 0, y: 0, width: 512, height: 512), device: device) |
var library: MTLLibrary? |
do { |
let path = Bundle.main.path(forResource: "TessellationFunctions", ofType: "metal") |
let source = try String(contentsOfFile: path!, encoding: .utf8) |
library = try device.makeLibrary(source: source, options: nil) |
} catch let error as NSError { |
print("library error: " + error.description) |
} |
// Setup Compute Pipeline |
let kernelFunction = library?.makeFunction(name: "tessellation_kernel_triangle") |
var computePipeline: MTLComputePipelineState? |
do { |
computePipeline = try device.makeComputePipelineState(function: kernelFunction!) |
} catch let error as NSError { |
print("compute pipeline error: " + error.description) |
} |
// Setup Vertex Descriptor |
let vertexDescriptor = MTLVertexDescriptor() |
vertexDescriptor.attributes[0].format = .float4; |
vertexDescriptor.attributes[0].offset = 0; |
vertexDescriptor.attributes[0].bufferIndex = 0; |
vertexDescriptor.layouts[0].stepFunction = .perPatchControlPoint; |
vertexDescriptor.layouts[0].stepRate = 1; |
vertexDescriptor.layouts[0].stride = 4*MemoryLayout<Float>.size; |
// Setup Render Pipeline |
let renderPipelineDescriptor = MTLRenderPipelineDescriptor() |
renderPipelineDescriptor.vertexDescriptor = vertexDescriptor |
renderPipelineDescriptor.colorAttachments[0].pixelFormat = mtkView.colorPixelFormat |
renderPipelineDescriptor.fragmentFunction = library?.makeFunction(name: "tessellation_fragment") |
renderPipelineDescriptor.isTessellationFactorScaleEnabled = false |
renderPipelineDescriptor.tessellationFactorFormat = .half |
renderPipelineDescriptor.tessellationControlPointIndexType = .none |
renderPipelineDescriptor.tessellationFactorStepFunction = .constant |
renderPipelineDescriptor.tessellationOutputWindingOrder = .clockwise |
renderPipelineDescriptor.tessellationPartitionMode = .fractionalEven |
renderPipelineDescriptor.maxTessellationFactor = 64; |
renderPipelineDescriptor.vertexFunction = library?.makeFunction(name: "tessellation_vertex_triangle") |
var renderPipeline: MTLRenderPipelineState? |
do { |
renderPipeline = try device.makeRenderPipelineState(descriptor: renderPipelineDescriptor) |
} catch let error as NSError { |
print("render pipeline error: " + error.description) |
} |
// Setup Buffers |
let tessellationFactorsBuffer = device.makeBuffer(length: 256, options: MTLResourceOptions.storageModePrivate) |
let controlPointPositions: [Float] = [ |
-0.8, -0.8, 0.0, 1.0, // lower-left |
0.0, 0.8, 0.0, 1.0, // upper-middle |
0.8, -0.8, 0.0, 1.0, // lower-right |
] |
let controlPointsBuffer = device.makeBuffer(bytes: controlPointPositions, length:256 , options: []) |
// Tessellation Pass |
let commandBuffer = commandQueue.makeCommandBuffer() |
let computeCommandEncoder = commandBuffer.makeComputeCommandEncoder() |
computeCommandEncoder.setComputePipelineState(computePipeline!) |
let edgeFactor: [Float] = [16.0] |
let insideFactor: [Float] = [8.0] |
computeCommandEncoder.setBytes(edgeFactor, length: MemoryLayout<Float>.size, at: 0) |
computeCommandEncoder.setBytes(insideFactor, length: MemoryLayout<Float>.size, at: 1) |
computeCommandEncoder.setBuffer(tessellationFactorsBuffer, offset: 0, at: 2) |
computeCommandEncoder.dispatchThreadgroups(MTLSizeMake(1, 1, 1), threadsPerThreadgroup: MTLSizeMake(1, 1, 1)) |
computeCommandEncoder.endEncoding() |
let renderPassDescriptor = mtkView.currentRenderPassDescriptor |
let renderCommandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor!) |
renderCommandEncoder.setRenderPipelineState(renderPipeline!) |
renderCommandEncoder.setVertexBuffer(controlPointsBuffer, offset: 0, at: 0) |
renderCommandEncoder.setTriangleFillMode(.lines) |
renderCommandEncoder.setTessellationFactorBuffer(tessellationFactorsBuffer, offset: 0, instanceStride: 0) |
renderCommandEncoder.drawPatches(numberOfPatchControlPoints: 3, patchStart: 0, patchCount: 1, patchIndexBuffer: nil, patchIndexBufferOffset: 0, instanceCount: 1, baseInstance: 0) |
renderCommandEncoder.endEncoding() |
commandBuffer.present(mtkView.currentDrawable!) |
commandBuffer.commit() |
commandBuffer.waitUntilCompleted() |
// Display Tessellated Content |
PlaygroundPage.current.liveView = mtkView |
Copyright © 2016 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2016-09-13