Chapter 8 showed me how to load a texture but I wanted to build a new texture from scratch. To keep it really easy (I thought), I’d build a tiny 5x5 2D texture with pixel format .a8Unorm which I think means that each pixel has a single 8-bit chanel (greyscale).
My data is a [UInt8] with a single white spot in the centre of a black background which I load into a MTLBuffer.
let device = MTLCreateSystemDefaultDevice()!
let commandQueue = device.makeCommandQueue()!
let commandBuffer = commandQueue.makeCommandBuffer()!
let matrixIn: [UInt8] = [
0,0,0,0,0,
0,0,0,0,0,
0,0,1,0,0,
0,0,0,0,0,
0,0,0,0,0
]
var bufferIn = device.makeBuffer(bytes: matrixIn,
length: 25,
options: .storageModeShared)!
When I examine this buffer, it is as expected:
var matrixOut = [UInt8]()
var start = bufferIn.contents()
.bindMemory(to: UInt8.self, capacity: 25)
var bufferPointer = UnsafeBufferPointer(start: start, count: 25)
bufferPointer.map { matrixOut += [$0] }
for r in 0..<5 {
print("|", terminator: " ")
for c in 0..<5 {
print(matrixOut[r * 5 + c], terminator: " ")
}
print("|")
}
/*
| 0 0 0 0 0 |
| 0 0 0 0 0 |
| 0 0 1 0 0 |
| 0 0 0 0 0 |
| 0 0 0 0 0 |
*/
Now I try to make a texture with it:
let textureDesc = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .a8Unorm,
width: 5,
height: 5,
mipmapped: false)
textureDesc.storageMode = .shared
textureDesc.usage = [.shaderRead, .renderTarget]
let textureIn = device.makeTexture(descriptor: textureDesc)!
// Fill textureIn
var bytesPerRow = MemoryLayout<UInt8>.stride * 5
var region = MTLRegion(origin: MTLOrigin(x: 0, y: 0, z: 0), size: MTLSize(width: 5, height: 5, depth: 1))
textureIn.replace(region: region, mipmapLevel: 0, withBytes: bufferIn.contents(), bytesPerRow: bytesPerRow)
but when I examine textureIn.buffer!.contents(), I find that it’s nil so replace has failed to load my data.
start = textureIn.buffer!.contents()
.bindMemory(to: UInt8.self, capacity: 25)
//Unexpectedly found nil while unwrapping an Optional value. Playground execution failed:
bufferPointer = UnsafeBufferPointer(start: start, count: 25)
bufferPointer.map { matrixOut += [$0] }
for r in 0..<5 {
print("|", terminator: " ")
for c in 0..<5 {
print(matrixOut[r * 5 + c], terminator: " ")
}
print("|")
}
Any idea what I missed?
textureIn.replace(…) seems to be the problem
[Incidentally, my plan was to subject this texture to a load of different MPS kernels and so see your Image Processing example in chapter 30 at work.]