Search code examples
swiftobjective-ctexturesmetal

How to create custom empty Texture correctly?


I need to create a MTLTexture with my custom data (which is currently filled with 0), in order to do it I use such an implementation

  private func createTexture(frame: UnsafeMutableRawPointer) -> MTLTexture? {
    let width = 2048
    let height = 2048
    
    let textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(
      pixelFormat: MTLPixelFormat.rgba8Unorm,
      width: width,
      height: height,
      mipmapped: false)
    
    textureDescriptor.usage = [.shaderWrite, .shaderRead]
    
    guard let texture: MTLTexture = device?.makeTexture(descriptor: textureDescriptor) else
    {
      logger?.log(severity: .error, msg: "create texture FAILED.")
      return nil
    }
    
    let region = MTLRegion.init(origin: MTLOrigin.init(x: 0, y: 0, z: 0), size: MTLSize.init(width: texture.width, height: texture.height, depth: 4));
    
    //MARK: >>> JUST FOR TEST
    let count = width * height * 4
    let stride = MemoryLayout<CChar>.stride
    let alignment = MemoryLayout<CChar>.alignment
    let byteCount = stride * count
    
    let p = UnsafeMutableRawPointer.allocate(byteCount: byteCount, alignment: alignment)
    let data = p.initializeMemory(as: CChar.self, repeating: 0, count: count)
    //MARK: <<<
      
    texture.replace(region: region, mipmapLevel: 0, withBytes: data, bytesPerRow: width * 4)
    
    return texture
  }

So, here I created a descriptor with 4 channels, then I created a region with depth: 4, then created UnsafeMutableRawPointer filled with data stride * count size, but I get an error in this line

texture.replace(region: region, mipmapLevel: 0, withBytes: data, bytesPerRow: width * 4)

_validateReplaceRegion:155: failed assertion `(origin.z + size.depth)(4) must be <= depth(1).'

what am I doing wrong?


Solution

  • The depth property in the following line is incorrect:

    let region = MTLRegion.init(origin: MTLOrigin.init(x: 0, y: 0, z: 0), size: MTLSize.init(width: texture.width, height: texture.height, depth: 4));
    

    The depth property describes the number of elements in the z dimension. For 2D texture it should be 1.