Metal Validation flags all read-write textures as invalid

I'm getting "Bad Message 431" trying to access the forums from Chrome, so I'm using Safari instead. This is a thread with a ton of people hitting this problem.

https://developer.apple.com/forums/thread/123657

I tracked it down to a bug in the validation layer. This happens with Apple's own sample code. RG16Unorm and other formats shouldn't be flagged as unsupported on a RDNA1 chip in the 16" MBP.

Please also make are R16Unorm isn't flagged either. The Metal texture loader used in the sample seems to always pick the wrong format for loaded images (RG for a height map png?), with no way to control the format.

This is the feedback assistant post on it. https://feedbackassistant.apple.com/feedback/9540775

Thank you for filing a feedback assistant post (and including the link!). I've been researching this and as long as the device supports MTLReadWriteTextureTier2 (see link for the list of formats), there is a guarantee that the read and write occur in the right order for a read-write texture. Technically, the pixel format R16Uint is supported by the validation layer while R16Unorm is not officially supported. However, the sample works because in the shader, it isn't doing anything fancy. But I'm going to call it undefined behavior because it's not technically on the list; and obviously the validation layer is complaining. However, I've forwarded your feedback assistant to one of our teams so they can take a look and make sure there isn't a regression.

What you can do in the mean time, is use R16Float which is on the official list. We will need to go back and examine the sample because I also noticed that the texture had an alpha channel resulting in a RG16 texture and I think that might cause a problem too.

That's not exactly going to work. Terrain system using R16Unorm for the precision, and it's the only format storable in PNG which only has 8u and 16u. Photoshop has been using 16u for a long time to store color, so I'm a little shocked that it's not exposed on desktop even if the Apple Silicon can't handle it.

R16Float is only 10-bits of precision, and R16Uint doesn't often support filtering. But worst case, the PNG data could be read into R16Uint. The Apple sample code should reflect valid use cases though.

If this is suddenly a per-format query, then Metal needs a call to query whether read-write support is possible on every format. Those docs are helpful, but runtime query is needed. Otherwise, how would an app test that R16Unit is supported and not R16Unorm.

So the first issue with the RG16 vs R16 format for the PNG is because the included PNG file has an alpha channel (though nothing is in it). The MTK Texture Loader will produce a R16 format without an alpha channel, and an RG16 format with an alpha channel. I've tried out using a simple compute kernel to generate an R16 only texture instead of using a blit encoder to copy the texture, which requires that the two formats match. I think the fixes the problem where the texture is RG16 or R16--so that's one change needed for the sample.

However, the main problem of using R16Unorm in the shader is that it might not be supported across every device which supports Tier 2 (which devices exactly, I honestly don't have a clue). But this can also be fixed by using one of the supported texture formats. One alternative is to use a ping-pong design pattern. and another is to manually convert to/from float in your shader kernel. I tried using F32Float which maintains the precision of the incoming 16-bit values and works with Tier1 as well. So this would be the necessary second change for the sample to align with our documentation.

Lastly, since I couldn't definitely find a statement in the Metal Shading Language specification that guarantees that you could alias the memory by using a read-only texture and a write-only texture, and both bound to the same MTLTexture, I'm hesitant to say that we recommend this without reservation. This simple example of a read followed by a write in a very defined pattern in a very simple shader is (IMHO) not likely to be problematic, but it's impossible for me to assure you of that.

We have posted a fix to the sample which corrects the behavior on AMD GPUs and works with the validation layer. It handles RG16 and R16 textures correctly as well. The sample now uses R32 which is a supported Tier1 format. Technically, R16Uint is supported but not R16Unorm. Although the sample worked without the validation layer turned on, it was relying on undefined behavior, so we corrected it to align with our documentation.

Metal Validation flags all read-write textures as invalid
 
 
Q