Sampling 3D Metal Textures on M1

I have a question about texture3d sampling on M1.

I create a 3D texture from 33x33x33 buffer:

Code Block Objective-C
id<MTLTexture> tex = [device newTextureWithDescriptor:texDescriptor];
[tex replaceRegion:MTLRegionMake3D( 0, 0, 0, 33, 33, 33 )
      mipmapLevel:0
            slice:0
        withBytes:GetRawBuffer()
      bytesPerRow:sizeof(vector_float4) * 33
    bytesPerImage:sizeof(vector_float4) * 33 * 33)];

It is then of course passed to my Metal compute kernel and then I sample it:

Code Block metal
float4 apply3DLut(const float4 pixel,
                 const float3 coords,
                  texture3d<float, access::sample> lut) {
    constexpr sampler smp (mag_filter::linear, min_filter::linear);
    float4 out = float4( lut.sample(smp, pixel.rgb) );
    return float4( out.rgb, pixel.a );
}

This code worked fine on Intel, but on M1 the sampling seems to always return 0.0f, no matter where I sample, as if the texture was not created or sampling didn't work.
Answered by BartW in 672588022
All right, so this is what happened:

After setting the texture in the compute encoder and ending the encoding, but before committing the command buffer, I was flagging the texture as purgeable. For some reason Intel did not purge the texture before rendering, while M1 did.

Hi Bart,

This should work. Can you create a request with Feedback Assistant and repost here? If you can attach the app or Xcode project which reproduces the problem, that would be great.

I'm wondering if using a 2D array texture would serve as a replacement for a workaround. You can't do linear sampling between slices as you can with a 3D texture so this may not be straightforward to implement.
Thanks. I'll see about feedback assistant tomorrow, but I'm not sure if I will be able to create a concise project that reproduces that.

What I am utterly confused about is that this code works perfectly fine on Intel and fails on M1. I tried adding Blit synchronize for the texture, thinking that maybe this was the cause, but it didn't do anything. Interestingly, I found out that only for the green channel I get the 0.0f values, for everything else I seem to be getting "nothing" (meaning that when I add or multiply the sample result for r, b or a, it also always comes back as black, while green behaves as if it actually is 0.0f). And the result is always the same, no matter which coordinates I sample.

I'd rather not go to 2D array texture unless there's no other solution. Like you said, it would require changes not only in the shader, but also upstream, that I'd rather avoid.
Accepted Answer
All right, so this is what happened:

After setting the texture in the compute encoder and ending the encoding, but before committing the command buffer, I was flagging the texture as purgeable. For some reason Intel did not purge the texture before rendering, while M1 did.

Sampling 3D Metal Textures on M1
 
 
Q