ios – Metal is premultiplying texture alpha between fragment attachment & fragment shader arg— why?

[ad_1]

I’m convinced that Metal is alpha-premultiplying my texture at some point between the attachment commandEncoder.setFragmentTexture(…, index: 0) and the fragment shader’s arguments (texture2d<float> texture [[texture(0)]],). The Xcode Metal Frame Capture seems to confirm this:

Inspecting the draw… command’s fragment texture binding:

Fragment binding in Xcode's frame debugger

shows this is clearly a non-alpha-premultiplied image (which I know to be true of the CGImage it comes from— it’s pulled from the network and is loaded manually with texture.replace(…, withBytes: …), not MTKTextureLoader):

Inspecting with Pre-Multiplied Alpha enabled; too light on the semi-transparent edges to be correct:
Inspecting with Pre-Multiplied Alpha enabled; too light on the semi-transparent edges to be correct
Inspecting with Pre-Multiplied Alpha enabled; correct imagery:
Inspecting with Pre-Multiplied Alpha enabled; correct imagery

However, when debugging the same texel as returned by the dataTexture.sample(dataTextureSampler, in.dataTextureCoordinate) call in the fragment shader (using the 0 texture fragment binding), the pixels are now clearly alpha-premultiplied:

Inspecting with Pre-Multiplied Alpha enabled; correct imagery:
Inspecting with Pre-Multiplied Alpha enabled; correct imagery
Inspecting with Pre-Multiplied Alpha disabled; too dark on the semi-transparent edges to be correct:
Inspecting with Pre-Multiplied Alpha disabled; too dark on the semi-transparent edges to be correct


So why is Metal doing this? Is this documented anywhere? (I’ve scoured the Metal Shading Language Specification Version 3.1 to no avail.) Is this configurable somehow? (There’s a hint to the purpose of this by the argument name of dataTexture— I really would like to keep the literal values in the texture unless I say otherwise.)

Blending is being done with RGB: add, one, oneMinusSourceAlpha; A: add, one, oneMinusSourceAlpha; as is customary for pre-multiplied alpha blending (though I’m pretty sure that’s not relevant here since we’re looking at fragment inputs, not blended outputs).

Using Xcode 15.0.1 with an iPad Pro 11″ 2021 iPad13,6 running iPadOS 17.1; and also Xcode 15.1 beta 2 with an iPhone 14 Pro iPhone15,2 running iOS 17.2 beta 2.

[ad_2]

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top