Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to draw on MTLTexture in bgra8Unorm pixel format

My code works when I draw on MTLTexture with rgba32Float pixel format, I can take then CVPixelBuffer out of it.

But FlutterTexture requires bgra8Unorm format. I do not want to convert CVPixelBuffer due to performance overhead.

So I'm trying to render on MTLTexture with bgra8Unorm pixel format, but the following fragment shader code won't compile:

fragment vector_uchar4 fragmentShader2(Vertex interpolated [[stage_in]]) {
    return 0xFFFFFFFF;
}

With error: Invalid return type 'vector_uchar4' for fragment function I've tried to replace it with uint type, but it crashes with error:

Fatal error: 'try!' expression unexpectedly raised an error:
Error Domain=AGXMetalA11 Code=3 
"output of type uint is not compatible with a MTLPixelFormatBGRA8Unorm color attachement."
UserInfo={NSLocalizedDescription=output of type uint is not compatible with a MTLPixelFormatBGRA8Unorm color attachement.}

If I use vector_float4 or vector_half4 return type my texture and buffers are empty.

Which return type I have to use for bgra8Unorm pixel format and get non empty image? Is it possible with metal at all?

like image 734
Dima Rostopira Avatar asked Sep 03 '25 05:09

Dima Rostopira


2 Answers

I've found answer on page 30 of Metal Shading Language specification

enter image description here

And finally this code draws image as expected:

fragment float4 fragmentShader2(Vertex interpolated [[stage_in]]) {
    // ...
    rgba8unorm<float4> rgba;
    rgba = float4(color.r, color.g, color.b, 1.0);
    return rgba;
}

If someone can explain what is happening under the hood, I would really like to not waste bounty.

like image 194
Dima Rostopira Avatar answered Sep 05 '25 01:09

Dima Rostopira


It depends on many different factors. In most cases you should use float4 or half4.

All modern apple GPUs that support metal designed to perform calculation on ( 32-bit or 64-bit) floating point data. It's how GPUs works, this means that any read operation calculated by the shader on the Float, Snorm, Unorm formats will be performed on 32-bit or 64-bit floating point, regardless of the original input format. On any writing operation shader performs conversion from 32-bit or 64-bit floating point to target format.
For conversion rules please see Metal Shading Language specification page 217.

Any metal formats that use the Float, Snorm, Unorm suffix are floating-point formats, while Uint and Sint are unsigned and signed integer.

Float - A floating-point value in any of the representations defined by metal.
Unorm - A floating-point value in range [0.0, 1.0].
Snorm - A floating-point value in range [-1.0, 1.0].
Uint - A unsigned integer.
Sint - A signed integer.

like image 33
Hamid Yusifli Avatar answered Sep 05 '25 00:09

Hamid Yusifli



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!