washed out/overexposed output with macvk + gpu-next
mpv Information
mpv v0.40.0-357-g17a3ac4cf-dirty Copyright © 2000-2025 mpv/MPlayer/mplayer2 projects
built on Oct 4 2025 18:54:12
libplacebo version: v7.356.0 (v7.351.0-80-g76c7076c)
FFmpeg version: 8.0
FFmpeg library versions:
libavcodec 62.11.100
libavdevice 62.1.100
libavfilter 11.4.100
libavformat 62.3.100
libavutil 60.8.100
libswresample 6.1.100
libswscale 9.1.100
Other Information
- macOS version: 15.6.1
- Source of mpv: master build
- Latest known working version: N/A
- Issue started after the following happened: update of libplacebo to master
Reproduction Steps
any video with mpv --no-config
Expected Behavior
same output as current nightly build with libplacebo 7.351
Actual Behavior
output is washed out/overexposed. behavior with --no-config
top left with libplacebo 7.351 (expcted)
top right with libplacebo master (slightly overexposed)
bottom left libplacebo master + --target-trc=bt.1886 --target-prim=bt.709 (overexposed)
bottom right libplacebo master + --target-trc=bt.1886 --target-prim=bt.709 --target-colorspace-hint=yes (slightly overexposed)
smaller window on the right vo=libmpv (same output as top left)
same as above just with my current config (without no-config)
Log File
with no-config:
log libplacebo 7.351 (working): placebo-7.351.log
log libplacebo master (broken): placebo-master.log
without no-config:
log libplacebo 7.351 (working): placebo-7.351.log
log libplacebo master (broken): placebo-master.log
Sample Files
No response
I carefully read all instruction and confirm that I did the following:
- [x] I tested with the latest mpv version to validate that the issue is not already fixed.
- [x] I provided all required information including system and mpv version.
- [x] I produced the log file with the exact same set of files, parameters, and conditions used in "Reproduction Steps", with the addition of
--log-file=output.txt. - [x] I produced the log file while the behaviors described in "Actual Behavior" were actively observed.
- [x] I attached the full, untruncated log file.
- [x] I attached the backtrace in the case of a crash.
following without no-config, the issue starts with following commit on libplacebo https://github.com/haasn/libplacebo/commit/f09e25d8abe34d633f882111d3c4c6f7347ddf06
top left libplacebo 7.351 (working)
top right libplacebo https://github.com/haasn/libplacebo/commit/46ae6c97800511c0eee9d8e37ddefa2ecabf59b0 (working commit before the mentioned above)
bottom left libplacebo https://github.com/haasn/libplacebo/commit/f09e25d8abe34d633f882111d3c4c6f7347ddf06 (broken commit mentioned above)
bttom right libplacebo https://code.videolan.org/videolan/libplacebo/-/merge_requests/751 (slightly different output than the working one)
using --target-colorspace-hint=yes on libplacebo master produced a similar result than with top left libplacebo 7.351 (slightly less exposed/more saturated)
Thank you so much for this report. I never seen so complete format selection in Vulkan colorspaces.
I see 10+6 different images / configuration, but only 4 logs, anyway, let's focus on what we have.
I wanted to post detailed reply, but there are two small bugs in format selection, that shadows the main issue. It's like onion, it has layers... So before proceeding, could you retest with https://github.com/mpv-player/mpv/pull/16877 and https://code.videolan.org/videolan/libplacebo/-/merge_requests/752 ?
This way we will have little bit better behavior in surface format selection and can focus on the other issue.
top right with libplacebo master (slightly overexposed)
This looks correct. libplacebo coverts to linear using inverse of bt.1886. While the surface format selection is bit wrong, because without hint, this shouldn't happen, so let's retest first so we don't discuss unrelated issues.
I see 10+6 different images / configuration, but only 4 logs, anyway, let's focus on what we have.
sorry if you would have liked them too. i didn't provide them for several reasons, i didn't want to overload the issue with even more information (hence why i provided only a log of the basic problem case and the previous behaviour for comparison), the logs without no-config were only provided because of the gamma2.2 remark on irc, all the other cases were more like a "i tried this already but it didn't work (completely)", and i wanted to tackle one problem after another step by step (basically what you already said with the onion).
on a side note since i just noticed it. some of the screenshots above (the ones with >=4 windows on them) were size optimised because they reached the upload limit of github. this unfortunately also stripped the colour profile attached. so not all screenshots are comparable between each other. i will compress the screenshots as jpg from now on.
anyway here we go, everything with no-config for now:
mpv master + libplacebo 1 commit before broken one (top left https://github.com/haasn/libplacebo/commit/46ae6c97800511c0eee9d8e37ddefa2ecabf59b0): master-placebo-okay.log mpv master + libplacebo 7.351 (top right): master-placebo-7.351.log mpv master + libplacebo master (bottom left): master-placebo-master.log mpv #16877 + libplacebo #752 (bottom right): 16877-placebo-752.log
both at the top look identical, both at the bottom look identical besides the text rendering (stats a bit darker). comparing top to bottom, still the same washed out difference.
for completeness sake, same as above but without no-config:
mpv master + libplacebo 1 commit before broken one (top left): master-placebo-okay.log mpv master + libplacebo 7.351 (top right): master-placebo-7.351.log mpv master + libplacebo master (bottom left): master-placebo-master.log mpv https://github.com/mpv-player/mpv/pull/16877 + libplacebo #752 (bottom right): 16877-placebo-752.log
the complete overexposure is gone with both those fixes, but it still looks bit more washed out than before (same/similar as above).
both at the top look identical, both at the bottom look identical besides the text rendering (stats a bit darker). comparing top to bottom, still the same washed out difference.
mpv master + libplacebo 1 commit before broken one (top left https://github.com/haasn/libplacebo/commit/46ae6c97800511c0eee9d8e37ddefa2ecabf59b0): master-placebo-okay.log
Previously, the status quo was that BT.1886 (SDR) was sent to an sRGB-configured swapchain. We recently changed this behavior to instead follow the swapchain configuration. This is the main concern at the moment. It alters the visual appearance but is technically more correct. Although in some cases it may still be wrong. I’ll try to summarize as concisely as possible (for more detail, see https://github.com/mpv-player/mpv/issues/16791).
mpv/libplacebo assumes that SDR content is intended for display on a BT.1886 display. At the same time, the default output target is sRGB. These are not equivalent. To handle this, the inverse of BT.1886 is applied first, followed by sRGB. This ensures that video appears as if it were shown on a BT.1886 display, with contrast adjusted according to the --target-contrast option.
There are two major assumptions here (explicitly stated, though historically not widely followed):
-
BT.709 content implies BT.1886 transfer. The problem is that some videos are not actually mastered for BT.1886, especially screen recordings. These are often tagged as BT.709 but are in practice sRGB. This can be corrected with
--vf=format=gamma=srgbor with autoprofiles. -
The target display is assumed to be sRGB. This can be controlled using the
target-trcoption.
(note if target and source trc is the same, mpv will not convert gamma)
In general, this change is the correct approach, since we configure and send sRGB to the compositor. The compositor then knows how to linearize the signal and apply the proper display transfer. If we don’t do this (as before), the compositor may apply an incorrect conversion—for example, treating an sRGB TRC as if it were BT.1886.
Historically, without color management, an sRGB swapchain was assumed to be passed through directly. This assumption is no longer valid, particularly when targeting HDR displays. There is also some disagreement on Wayland's side about what "sRGB" actually means: they argue it should be encoded as gamma 2.2, while Vulkan continues to treat it as sRGB.
In short, I believe current status is correct. While may not be the most pragmatic thing, I don't see how to "hack" it to workaround badly tagged sources. Historically when everything was SDR, the strategy was "don't care" and just ignore any differences between transfers, and as SDR is display referred, it get displayed in one way or another. The tricky part now is that we may need to convert to say PQ, in which case we need to know source transfer exactly to emulate the nits it would produce.
mpv master + libplacebo 7.351 (top right): master-placebo-7.351.log
there is not difference, to 1st. It's the same picture.
mpv master + libplacebo master (bottom left): master-placebo-master.log
master/master is slightly broken (without patches), because it would pick linear transfer, even if hint is disabled. But good thing that you confirmed that it looks the same as 4th, because this means that linear output is working correctly.
mpv https://github.com/mpv-player/mpv/pull/16877 + libplacebo #752 (bottom right): 16877-placebo-752.log
Looks correct, bt.1886 is converted to sRGB, which is default output without colorspace hint.
I should have mention before, default is --target-colorspace-hint=auto in which case hint is enabled only if target_csp() callback is enabled. Else we just fallback to sRGB.
Could you try with --target-colorspace-hint=yes? It should pick VK_COLOR_SPACE_BT709_NONLINEAR_EXT and output bt.1886 without conversion on mpv side. (curious how macOS implements bt.1886)
for completeness sake, same as above but without no-config:
User side ICC profiles are inherently not compatible with color management done in system. Depending how you created ICC profile, you may have included correction to conversion done in system. How it works is platform specific.
You apply ICC profile in mpv, but then your compositor may apply the same or similar ICC profile before outputting to the display. So in order to make it work you should manually configure swapchain to consistent values that work for your ICC profile.
I wanted to use VK_COLOR_SPACE_PASS_THROUGH_EXT for ICC profiles, but there is disagreement about this from Wayland guys https://github.com/haasn/libplacebo/issues/324
I think we should somehow plug option to use VK_COLOR_SPACE_PASS_THROUGH_EXT still.
I wanted to use
VK_COLOR_SPACE_PASS_THROUGH_EXTfor ICC profiles, but there is disagreement about this from Wayland guys haasn/libplacebo#324
I like https://code.videolan.org/videolan/libplacebo/-/merge_requests/717 for this reason, rather than blanket disabling PASS_THROUGH on all platforms.
... In short, I believe current status is correct. While may not be the most pragmatic thing, I don't see how to "hack" it to workaround badly tagged sources. Historically when everything was SDR, the strategy was "don't care" and just ignore any differences between transfers, and as SDR is display referred, it get displayed in one way or another. The tricky part now is that we may need to convert to say PQ, in which case we need to know source transfer exactly to emulate the nits it would produce.
since the complete overexposure is fixed (my main issue) i don't really have an issue here any more. since it is a deliberate change of behaviour from the previous one, i probably wouldn't notice the difference without comparing side by side and it's pretty 'minuscule'.
Could you try with
--target-colorspace-hint=yes? It should pickVK_COLOR_SPACE_BT709_NONLINEAR_EXTand output bt.1886 without conversion on mpv side. (curious how macOS implements bt.1886)
yes, seems to be the case.
master-placebo-master.log
User side ICC profiles are inherently not compatible with color management done in system. Depending how you created ICC profile, you may have included correction to conversion done in system. How it works is platform specific.
You apply ICC profile in mpv, but then your compositor may apply the same or similar ICC profile before outputting to the display. So in order to make it work you should manually configure swapchain to consistent values that work for your ICC profile.
maybe we are talking past each other and sorry if i am misunderstanding something.
i only use my ICC profile with target-colorspace-hint=no and i also made sure that the colorspace set on the layer (via moltenvk) was either nil or the icc profile itself. both would mean noop in terms of color transformation on the OS color management side. that was the old behaviour and i believe the right one.
tested with master again, now it picks kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1 (https://developer.apple.com/documentation/coregraphics/cgcolorspace/srgb https://github.com/KhronosGroup/MoltenVK/blob/main/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm#L518-L521), which is wrong i would say.
I wanted to use VK_COLOR_SPACE_PASS_THROUGH_EXT for ICC profiles, but there is disagreement about this from Wayland guys https://github.com/haasn/libplacebo/issues/324
I think we should somehow plug option to use VK_COLOR_SPACE_PASS_THROUGH_EXT still.
yeah, i believe VK_COLOR_SPACE_PASS_THROUGH_EXT would be the right behaviour in this case on macOS+moltenvk too, see https://github.com/KhronosGroup/MoltenVK/blob/main/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm#L562-L565.
I wanted to use
VK_COLOR_SPACE_PASS_THROUGH_EXTfor ICC profiles, but there is disagreement about this from Wayland guys haasn/libplacebo#324I think we should somehow plug option to use
VK_COLOR_SPACE_PASS_THROUGH_EXTstill.
@kasper93 From MoltenVK code, I think on macOS VK_COLOR_SPACE_PASS_THROUGH_EXT basically behaves the same as Wayland, it just doesn't mark any colorspace metadata to the surface, and this should mean that's also using sRGB actually.
@kasper93 Also do you think it's related to the issue we discussed here? https://github.com/mpv-player/mpv/pull/16915#issuecomment-3427162984
@Akemi can you try target-colorspace-hint=yes target-contrast=10000?
This is my test result, use newest code with both PR merged, left is target-contrast=auto, and right is target-contrast=10000:
@Akemi can you try
target-colorspace-hint=yes target-contrast=10000?
This is my test result, use newest code with both PR merged, left is
target-contrast=auto, and right istarget-contrast=10000:
It's not related. linear output is not used on macOS.
yeah, i believe VK_COLOR_SPACE_PASS_THROUGH_EXT would be the right behaviour in this case on macOS+moltenvk too
I think this is the remaining item in this issue? Not sure how we want to handle this?
yeah, i believe VK_COLOR_SPACE_PASS_THROUGH_EXT would be the right behaviour in this case on macOS+moltenvk too
I think this is the remaining item in this issue? Not sure how we want to handle this?
Let's just drop it. That's undefined behavior, though looks similar to Wayland implementation.
I think this is the remaining item in this issue? Not sure how we want to handle this?
yes, as far as i am aware for now.