金属似乎将 bgra8Unorm 解释为 rgba 颜色

Metal seems to interpret bgra8Unorm as an rgba color

在 Apple Metal 应用程序中,我正在尝试编辑纹理内容。纹理使用 bgra8Unorm 像素格式,创建方式如下:

fileprivate var texture: MTLTexture!
private var buffer: MTLBuffer!
    
private var width: Int!
private var height: Int!

...

buffer = device.makeBuffer(length: width * height * 4, options: .storageModeManaged)
        
let textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .bgra8Unorm, width: width, height: height, mipmapped: false)
texture = buffer.makeTexture(descriptor: textureDescriptor, offset: 0, bytesPerRow: width * 4)

我将像素颜色设置如下:

func setPixel(x: Int, y: Int, color: NSColor) {
    let ptr = buffer.contents().bindMemory(to: UInt32.self, capacity: buffer.length / 4)

    var b: CGFloat = 0
    var g: CGFloat = 0
    var r: CGFloat = 0
    var a: CGFloat = 0
    color.getRed(&r, green: &g, blue: &b, alpha: &a)
        
    let index = y * width + x
    ptr[index] = (UInt32(b * 255) << 24) | (UInt32(g * 255) << 16) | (UInt32(r * 255) << 8) | UInt32(a * 255)
    buffer.didModifyRange(index..<(index + 1))
}

主像素格式也设置为bgra8Unorm继承MTKView:

init() {
        super.init(frame: .zero, device: MTLCreateSystemDefaultDevice())
        colorPixelFormat = .bgra8Unorm
        clearColor = MTLClearColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0)
}

片段着色器根本没有做任何有趣的事情:

fragment float4 basic_fragment(
                              VertexOut inVert [[ stage_in ]],
                              texture2d<float> tex2D [[ texture(0) ]],
                              sampler sampler2D [[ sampler(0) ]]
                              ) {
    return tex2D.sample(sampler2D, inVert.tex);
}

然而,当我调用所有这些来将像素的颜色设置为 NSColor.orange 时,它似乎是蓝色的。

运行 调试器并捕获 GPU 帧,我可以看到缓冲区中的值为 8388607,看起来像最大值 AlphaRed 和几乎达到最大值 Green。但不知何故,金属似乎将这种颜色解释为 rgba 格式,尽管我将所有内容都设置为 bgra

我是不是做错了什么?

Am I doing something wrong?

bgra表示内存中依次出现bgra4个分量。 所以,在小端 UInt32 中,b 应该是 LS 字节,a 应该是 MS 字节。

请试试这个:

    ptr[index] = (UInt32(a * 255) << 24) | (UInt32(r * 255) << 16) | (UInt32(g * 255) << 8) | UInt32(b * 255)