added compute

This commit is contained in:
Marius Horga 2019-02-01 18:39:33 -06:00
parent 12c2fec09b
commit e0a1827db0
9 changed files with 95 additions and 0 deletions

View File

@ -35,3 +35,4 @@ Repository to accompany the following blog posts:
- [Working with Particles in Metal part 3](http://metalkit.org/2017/11/30/working-with-particles-in-metal-part-3.html)
- [Metal By Tutorials book!](http://metalkit.org/2018/05/29/metal-by-tutorials-book.html)
- [Raytracing with Metal](http://metalkit.org/2018/07/14/raytracing-with-metal.html)
- [Introduction to compute using Metal](http://metalkit.org/2019/01/31/intro-to-metal-compute.html)

View File

@ -0,0 +1,9 @@
import MetalKit
import PlaygroundSupport
let frame = NSRect(x: 0, y: 0, width: 800, height: 500)
let delegate = Renderer()
let view = MTKView(frame: frame, device: delegate.device)
view.delegate = delegate
PlaygroundPage.current.liveView = view

View File

@ -0,0 +1,11 @@
#include <metal_stdlib>
using namespace metal;
kernel void compute(texture2d<float, access::read> input [[texture(0)]],
texture2d<float, access::write> output [[texture(1)]],
uint2 id [[thread_position_in_grid]]) {
uint2 index = uint2((id.x / 5) * 5, (id.y / 5) * 5);
float4 color = input.read(index);
output.write(color, id);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 729 KiB

View File

@ -0,0 +1,57 @@
import MetalKit
public class Renderer: NSObject, MTKViewDelegate {
public var device: MTLDevice!
var queue: MTLCommandQueue!
var pipelineState: MTLComputePipelineState!
var image: MTLTexture!
override public init() {
super.init()
initializeMetal()
}
func initializeMetal() {
device = MTLCreateSystemDefaultDevice()
queue = device.makeCommandQueue()
let textureLoader = MTKTextureLoader(device: device)
let url = Bundle.main.url(forResource: "nature", withExtension: "jpg")!
guard let file = Bundle.main.path(forResource: "Shaders", ofType: "metal") else { return }
do {
let source = try String(contentsOfFile: file, encoding: String.Encoding.utf8)
let library = try device.makeLibrary(source: source, options: nil)
guard let function = library.makeFunction(name: "compute") else { return }
pipelineState = try device.makeComputePipelineState(function: function)
image = try textureLoader.newTexture(URL: url, options: [:])
} catch let error {
print(error.localizedDescription)
}
}
public func draw(in view: MTKView) {
guard let commandBuffer = queue.makeCommandBuffer(),
let commandEncoder = commandBuffer.makeComputeCommandEncoder(),
let drawable = view.currentDrawable else {
return
}
commandEncoder.setComputePipelineState(pipelineState)
commandEncoder.setTexture(image, index: 0)
commandEncoder.setTexture(drawable.texture, index: 1)
var width = pipelineState.threadExecutionWidth
var height = pipelineState.maxTotalThreadsPerThreadgroup / width
let threadsPerGroup = MTLSizeMake(width, height, 1)
width = Int(view.drawableSize.width)
height = Int(view.drawableSize.height)
let threadsPerGrid = MTLSizeMake(width, height, 1)
commandEncoder.dispatchThreads(threadsPerGrid, threadsPerThreadgroup: threadsPerGroup)
commandEncoder.endEncoding()
commandBuffer.present(drawable)
commandBuffer.commit()
}
public func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {}
}

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='6.0' target-platform='macos' executeOnSourceChanges='false'/>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>