Pop Flamingo
Pop Flamingo

Reputation: 2191

Why don't I get the result of this Metal kernel

I am trying to understand how Metal compute shaders work, so I have wrote this code :

class AppDelegate: NSObject, NSApplicationDelegate {


    var number:Float!
    var buffer:MTLBuffer!


    func applicationDidFinishLaunching(aNotification: NSNotification) {
        // Insert code here to initialize your application
        let metalDevice = MTLCreateSystemDefaultDevice()!
        let library = metalDevice.newDefaultLibrary()!
        let commandQueue = metalDevice.newCommandQueue()
        let commandBuffer = commandQueue.commandBuffer()
        let commandEncoder = commandBuffer.computeCommandEncoder()


        let pointlessFunction = library.newFunctionWithName("pointless")!
        let pipelineState = try! metalDevice.newComputePipelineStateWithFunction(pointlessFunction)
        commandEncoder.setComputePipelineState(pipelineState)
        number = 12

        buffer = metalDevice.newBufferWithBytes(&number, length: sizeof(Float), options: MTLResourceOptions.StorageModeShared)
        commandEncoder.setBuffer(buffer, offset: 0, atIndex: 0)


        commandEncoder.endEncoding()

        commandBuffer.commit()
        commandBuffer.waitUntilCompleted()

        let data = NSData(bytesNoCopy: buffer.contents(), length: sizeof(Float), freeWhenDone: false)
        var newResult:Float = 0
        data.getBytes(&newResult, length: sizeof(Float))
        print(newResult)




    }

By making a buffer with StorageModeShared, I want changes made to the Metal buffer reflected in my Swift code, but when I populate my newResult variable, it looks like the buffer is still the same value than at the beginning (12) while it should be 125 :

#include <metal_stdlib>
using namespace metal;



kernel void pointless (device float* outData [[ buffer(0) ]]) {

    *outData = 125.0;
}

What am I doing wrong ?

Upvotes: 3

Views: 272

Answers (1)

user652038
user652038

Reputation:

A kernel function doesn't run unless you dispatch it. I think you're assuming if you have a function, then Metal should run it one time, until you say otherwise, but that won't happen. It will instead not run at all. Add this before endEncoding and you're good to go!

let size = MTLSize(width: 1, height: 1, depth: 1)
commandEncoder.dispatchThreadgroups(size, threadsPerThreadgroup: size)

Upvotes: 1

Related Questions