New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Client-side MetalFX upscaling for image quality enhancement. #97
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall it looks great, my main concern is with the color accuracy on the YUV conversion, since I spent a lot of time getting that right for the existing pipeline. Also want to make sure it works correctly with HDR/BT.2020 inputs.
} | ||
|
||
|
||
func convertRGBA16FloatToRGBA8Unorm(device: MTLDevice, commandQueue: MTLCommandQueue, sourceTexture: MTLTexture) -> MTLTexture? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason we can't keep the textures in RGB16? The drawable framebuffer is RGBA16Float so ideally we'd like to keep it so that HDR still works
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually wait, is this only for the PNG? If that's the case, then it's fine.
|
||
// Simple YUV to RGB conversion | ||
float3 rgb; | ||
rgb.r = y + 1.402 * uv.y; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should use the same YUV conversion matrix as the YUV fragment shaders, otherwise it will have different colors between HDR (BT.2020) and SDR (BT.709)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May or may not want to also do NonlinearToLinearRGB
and EncodingNonlinearToLinearRGB
here too? Not sure if the MetalFX upscaler cares about the images being a bit over-bright.
|
||
float3 rgb_uncorrect = in_tex_rgb.sample(colorSampler, sampleCoord).rgb; | ||
|
||
const float DIV12 = 1. / 12.92; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs rebasing to use NonlinearToLinearRGB
and EncodingNonlinearToLinearRGB
now
desc.outputHeight = Int(Float(inputHeight)*scaling) | ||
desc.colorTextureFormat = pixelFormat | ||
desc.outputTextureFormat = pixelFormat | ||
desc.colorProcessingMode = .perceptual |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the YUV conversion shader is changed to use NonlinearToLinearRGB
and EncodingNonlinearToLinearRGB
, change this to .hdr
or .linear
Basically these code is generated by ChatGPT, I’ll carefully check them. |
This enables MetalFX for ALVR-visionos.
With a toggle to control if use MetalFX and upscaling factor selection, and also debug option to save raw image and upscaled image.
To use MetalFX, we need to convert YUV420 to RGB first.
UI
Comparsions:
Top: raw
Bottom: Upscaled
Known issue:
The R and B channel of saved image is opposite, but it's ok for debugging seeing these images.
Honestly, due to the bandwidth limitation of apple, metalfx does not change a lot currently.