Ios 有没有一种方法可以计算金属纹理在分配前使用了多少内存?

Ios 有没有一种方法可以计算金属纹理在分配前使用了多少内存?,ios,swift,metal,Ios,Swift,Metal,出于内存管理的目的,我需要知道金属纹理需要多少内存。 我知道我需要对缓冲区进行页面对齐以估计大小,但由于某些原因,我的估计不正确 考虑以下伪代码: import Darwin import Metal import MetalKit import UIKit func estimate(width: Int, height: Int) -> Int { let pageSize = Int(getpagesize()) let unalignedSize = width

出于内存管理的目的,我需要知道金属纹理需要多少内存。 我知道我需要对缓冲区进行页面对齐以估计大小,但由于某些原因,我的估计不正确

考虑以下伪代码:

import Darwin
import Metal
import MetalKit
import UIKit

func estimate(width: Int, height: Int) -> Int {
    let pageSize = Int(getpagesize())
    let unalignedSize = width * height * 4 // let's assume 32bits ARGB texture

    return ((unalignedSize + pageSize - 1) / pageSize) * pageSize
}

func actually(width: Int, height: Int) -> Int {
    let l = MTKTextureLoader(device: MTLCreateSystemDefaultDevice()!)
    let options : [MTKTextureLoader.Option : NSObject] = [
        MTKTextureLoader.Option.allocateMipmaps : NSNumber(booleanLiteral: false),
        MTKTextureLoader.Option.generateMipmaps : NSNumber(booleanLiteral: false),
        MTKTextureLoader.Option.textureUsage    : NSNumber(value: MTLTextureUsage.shaderRead.rawValue),
        MTKTextureLoader.Option.SRGB            : NSNumber(booleanLiteral: false)
    ]
    let t = try! l.newTexture(cgImage: generateMonochromeImage(color: .blue, size: CGSize(width: width, height: height)), options: options)

    return t.allocatedSize
}

func generateMonochromeImage(color: UIColor, size: CGSize) -> CGImage {
    let rect = CGRect(origin: .zero, size: size)
    UIGraphicsBeginImageContextWithOptions(rect.size, false, 1.0)
    color.setFill()
    UIRectFill(rect)
    let image = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()

    return image.cgImage!
}



estimate(width: 414, height: 512) //-> 851968
actually(width: 414, height: 512) //-> 917504
estimate(width: 363, height: 512) //-> 753664
actually(width: 363, height: 512) //-> 786432
正如你所看到的,估计是错误的


是否有一种方法可以预测/计算MTLTexture将分配多少?

至少有一个问题是行字节对齐a.k.a.bytesPerRow。对于硬件来说,访问与某些二次幂对齐的行更有效。所以,这就是数据在内部存储的方式

从您的数字来看,纹理似乎每行使用256字节。因此,一行宽414像素,每像素4字节,需要1656字节。但这不是256的倍数。因此,这些行将被填充到下一个256的倍数,即1792。乘以512行等于917504


但是,正如Idoogy在评论中提到的,这在所有硬件中都是不可预测的。

至少有一个问题是行字节对齐(也称为bytesPerRow)。对于硬件来说,访问与某些二次幂对齐的行更有效。所以,这就是数据在内部存储的方式

从您的数字来看,纹理似乎每行使用256字节。因此,一行宽414像素,每像素4字节,需要1656字节。但这不是256的倍数。因此,这些行将被填充到下一个256的倍数,即1792。乘以512行等于917504


但是,正如Idoogy在评论中提到的,这在所有硬件中都是不可预测的。

由于设备特定的考虑,我怀疑答案是“否”。例如,一些设备将在内存中平铺图像,而另一些设备将对图像进行压缩或进行某种跨步处理,以使硬件更容易处理像素。如果您在其他设备Mac GPU或甚至其他代iOS GPU上运行测试,您可能会看到不同的实际数字。出于设备特定的考虑,我怀疑答案是“否”。例如,一些设备将在内存中平铺图像,而另一些设备将对图像进行压缩或进行某种跨步处理,以使硬件更容易处理像素。如果您在其他设备Mac GPU或其他代iOS GPU上运行测试,您可能会看到不同的实际数据。我运行了一些测试,大小似乎很难预测。。。正如@IDoology所建议的,结果取决于平台。在A12X和A13上,您需要为这些示例添加一页。建议的256字节对齐行启发式方法并不适用于所有维度。可能只需要2^28就可以测试每个设备的每个置换,但在lut中进行利用似乎并不实际。此外,它似乎与MTLDevice.minimumlineartexturereallignment for:无关,它在我测试的每个设备上返回64。所以我想我必须适应不准确的估计…我做了一些测试,尺寸似乎很难预测。。。正如@IDoology所建议的,结果取决于平台。在A12X和A13上,您需要为这些示例添加一页。建议的256字节对齐行启发式方法并不适用于所有维度。可能只需要2^28就可以测试每个设备的每个置换,但在lut中进行利用似乎并不实际。此外,它似乎与MTLDevice.minimumlineartexturereallignment for:无关,它在我测试的每个设备上返回64。所以我想我不得不接受不准确的估计。。。