Metalkit: MTLBuffer и указатели в Swift 3

Я начал с Metalkit, и у меня есть очень простое ядро ​​в качестве тестового примера.

kernel void compute(device float* outData [[ buffer(0) ]])
{
  outData[0] = 234.5;
  outData[3] = 345.6;
}

Эти «вычисленные» данные хранятся в файле MTLBuffer.

var buffer : MTLBuffer?
...
buffer = device.makeBuffer(length: MemoryLayout<Float>.size * 5, options: [])
...
commandBuffer.waitUntilCompleted()

В этот момент ядро ​​записало некоторые тестовые данные в файл MTLBuffer. Вопрос в том, как мне получить доступ к этим данным из моей основной программы?

Я получаю unsafeMutableRawPointer от buffer.contents(). Как мне получить быстрый массив значений, которые я могу использовать везде (отображение на экране, запись в файл и т. д.)?

Эти фрагменты работают в этом очень простом приложении, но я не уверен, что они верны:

let raw = buffer.contents()
let b = raw.bindMemory(to: Float.self, capacity: 5) 
print(b.advanced(by: 3).pointee)

let a = raw.assumingMemoryBound(to: Float.self)
print(a.advanced(by: 3).pointee)


let bufferPointer = UnsafeBufferPointer(start: b, count: 5)
let values = Array(bufferPointer)
print(values)


let value = raw.load(fromByteOffset: MemoryLayout<Float>.size * 3, as: Float.self)
print(value)

И bindMemory, и assumingMemoryBound работают. Хотя assumingMemoryBound предполагает, что базовые байты уже введены, а bindMemory — нет. Я думаю, что один из них должен работать, но не оба. Какой он должен быть и почему?


person user965972    schedule 11.12.2016    source источник


Ответы (1)


Я использую код, представленный ниже, для загрузки в массивы, но я не могу решить, какая версия лучше — моя или ваша.

let count = 16

var array = [Float]()
array.reserveCapacity(count)

    for i in 0..<count {
        array.append(buffer.contents().load(fromByteOffset: MemoryLayout<Float>.size * i, as: Float.self))
    }
person Andreas detests censorship    schedule 19.12.2017
comment
Прошло некоторое время с тех пор, как я посмотрел на это, поэтому я (до сих пор) не знаю, каким должен быть ответ. Сказав это, ваша версия копирует данные байт за байтом. Копирование байтов только для того, чтобы поместить их в другой контейнер, является для меня красным флагом. Действительно ли необходимо делать копию? - person user965972; 22.12.2017
comment
@user965972 user965972 Насколько я знаю, это единственный способ сделать это, но я не смотрел файл UnsafeBufferPointer. Я не очень опытен на низком уровне, но я подумал, что по крайней мере могу дать временное решение. Если я прав, вы можете разделить память между процессором и графическим процессором, поэтому может быть лучший способ загрузки данных из MTLBuffer. - person Andreas detests censorship; 22.12.2017