gpu-next: allow to output in scRGB when outputting HDR
Expected behavior of the wanted feature
as the title suggests :)
I see some potential issues here:
I tried adding that feature myself in the past and realised that libplacebo converts to the target colour space at its earliest convenience. This has the issue that any negative value and possibly any value above 1 gets clipped as scRGB is defined to have 1.0 = 80 nits and having BT.709/sRGB primaries. iirc either libplacebo clips for safety reasons or because any advanced scaling algorithm needs to have it's input range to be 0-1 afaik, or other processing clips to a 0-1 range.
My solution to that was to have the internal colour space be HDR10 until just before the image is presented and then convert to scRGB. Currently there is no consumer display standard that allows for anything wider than HDR10, so this should be fine for now. But I wasn't sure how and where to implement that.
Currently there is also a MR open for libplacebo to add absolute and relative linear transfers which is probably related. Essentially scRGB would need a PL_COLOR_TRC_LINEAR_80_ABS option added or there needs to be a separate option to define what nits 1.0 equals to for a specific "linear absolute transfer".
EDIT:
currently in mpv the scRGB colour space option for d3d11 is defined as linear here: https://github.com/mpv-player/mpv/blob/8469605191c1fb3c9ebf84617a4b2e2bada357fa/video/out/d3d11/context.c#L80 which is not entirely correct. It is also basically unusable and is mentioned to have issues in the manual so it's not really that important imho.
Alternative behavior of the wanted feature
No response
Log File
No response
Sample Files
No response
Essentially scRGB would need a PL_COLOR_TRC_LINEAR_80_ABS option added or there needs to be a separate option to define what nits 1.0 equals to for a specific "linear absolute transfer".
That would be a start. Making libplacebo output valid for scRGB is not that hard, we would need to renormalize in output pass. Internally libplacebo use absolute linear scaling, with min luminance to max luminance range. Though this wouldn't be useful without fixing also gamut mapping, which would clip everything to sRGB primaries, not knowing how to handle extended range.
Generally it's possible to add support, but at the same time not sure if scRGB is that useful over just outputting PQ as is the current status and actually the only transfer function that can output HDR from libplacebo correctly.
currently in mpv the scRGB colour space option for d3d11 is defined as linear here:
This is used only for vo=gpu and it's not correct, it has other issues too.
That would be a start. Making libplacebo output valid for scRGB is not that hard, we would need to renormalize in output pass. Internally libplacebo use absolute linear scaling, with min luminance to max luminance range. Though this wouldn't be useful without fixing also gamut mapping, which would clip everything to sRGB primaries, not knowing how to handle extended range.
The solution I described seems like the easiest to me but libplacebo seems totally not set up for it. Also keeping the full HDR10 range between 0-1 and storing it in fp16 would cause a huge accuracy loss if the transfer is kept linear. It would be needed to be stored in fp32 which is pretty unreasonable imho. Aren't advanced scaling options also somewhat broken if the full HDR10 range is kept in normalised linear? Because the linear differences get too high or too low because the perceptual difference is constant in PQ. I thought gpu and gpu-next keep it non linear because of that reason and linear scaling is disabled.
Generally it's possible to add support, but at the same time not sure if scRGB is that useful over just outputting PQ as is the current status and actually the only transfer function that can output HDR from libplacebo correctly.
I can name a few:
- on Windows you can't get higher bit depth output than 10 bit otherwise, as HDR10 is the only other HDR output format
- 10 bit YCbCr does not map 1:1 into 10 bit RGB, using scRGB would get closer to 1:1 mapping
- if decoding the EL layer from DV ever gets added it would be nice to be able to actually send those 2 extra bits to your display
- following the contrast sensitivity function described by Barten which PQ is based on, a bit depth of 11.5 would be needed, so any content providing a higher bit depth can't actually be sent to your display
- anything wider than the BT.2020 gamut would be automatically covered by scRGB in the future
I know this is specific stuff but I care! 😺
There used be another similar format to scRGB supported by the AMD's Vulkan Windows driver which was dropped when they added their DXGI layered support for Vulkan, which was FORMAT_R16G16B16A16_SFLOAT + COLOR_SPACE_BT2020_LINEAR_EXT, it had 1.0 at 100 nits. What I mean is that there could be potentially other similar output colour spaces that could or can be used to output a higher bit depth than 10. iirc gamescope currently also supports FORMAT_R16G16B16A16_SFLOAT + COLOR_SPACE_HDR10_ST2084_EXT (or used to) which would obviously be a lot easier to support but that format and colour space combination is not available on Windows and scRGB is generally supported everywhere.