|
monad
|
|
RaveSteel
At this time I have 380 images from maybe 10 games on my side, nonidea from how many games the files you sent me previously are from.
Unless you have +10000 images I will take all you can send me.
I aim at a very large datset to be representative of different types of graphical styles/games this time.
|
|
2024-09-14 01:54:10
|
|
|
2024-09-14 01:54:16
|
<@167354761270525953> round 2 <https://mega.nz/file/adtFwJDI#iIQY0GmfskdnBc_nUJlK1fRDdoO-m6hG6hnNhCwW9vI>
|
|
|
RaveSteel
|
2024-09-14 01:54:28
|
Nice!
|
|
2024-09-14 02:18:35
|
Waiter, Waiter! More screnshots please
|
|
2024-09-14 02:18:47
|
https://tenor.com/view/waiter-cat-more-kibble-please-gif-13625215935695637260
|
|
2024-09-14 02:19:17
|
I am at 560 screenshots now
|
|
2024-09-15 12:36:13
|
I am at 1300 screenshots from over 80 games btw and currently testing the encodes
|
|
|
monad
|
2024-09-15 12:36:35
|
Sweet.
|
|
|
RaveSteel
|
2024-09-15 12:36:48
|
JXL was so much faster that I had to switch to writing to /tmp
|
|
2024-09-15 12:36:58
|
This made no difference at all for AVIF lol
|
|
2024-09-15 01:05:53
|
Here is the current draft, feel free to criticise
|
|
2024-09-15 01:06:31
|
I will post the encoding results in <#803645746661425173> later
|
|
|
monad
|
2024-09-15 01:32:25
|
As you are including png decode in your measurement, it is not exactly representative of the use case, but this should just mean the fastest jxl has a bit better ratio. Personally, I would be curious about at least proportion of HDR content, even proportion of different art styles, but I would also suggest it doesn't have to be totally scientific if it can convince Valve to run their own testing. They would be best informed about the requirements of the product.
|
|
2024-09-15 06:32:34
|
I'm going to guess a big reason why JXL wouldn't be a priority for Valve is JXL is much harder to share on the web.
|
|
|
RaveSteel
|
|
monad
As you are including png decode in your measurement, it is not exactly representative of the use case, but this should just mean the fastest jxl has a bit better ratio. Personally, I would be curious about at least proportion of HDR content, even proportion of different art styles, but I would also suggest it doesn't have to be totally scientific if it can convince Valve to run their own testing. They would be best informed about the requirements of the product.
|
|
2024-09-15 10:35:34
|
> png decode
I only measured the encoding from PNG to AVIF/JXL, or was this just a typo?
I could split up the images into photographic, pixel art, HDR, but I don't know if that is really needed seeing as the dataset itself has screenshots from so many games that it should be representative. I could add some more pixel art screenshots, but even without them the results speak for themselves I think
|
|
|
monad
I'm going to guess a big reason why JXL wouldn't be a priority for Valve is JXL is much harder to share on the web.
|
|
2024-09-15 10:38:08
|
That is true, but this is one of the main reasons I am doing this: to gain more adoption for JXL (besides the general advantages).
And another point: the current AVIF screenshots gamescope creates cannot be shared over discord either, the main platform of almost any person playing games
|
|
|
monad
|
2024-09-15 11:12:18
|
Normally gamescope would take an image buffer directly from memory and encode it to the target storage format, right? In this test, a png file needs to be decoded first to a buffer in memory, then that is encoded to the target format. But again, If this just gets the format in front of Valve, maybe they will test it properly in their architecture.
|
|
|
RaveSteel
|
2024-09-15 11:13:04
|
Agreed, I have cloned gamescope to try and get it to encode JXL directly, but I am not a programmer
|
|
2024-09-15 11:14:37
|
But still, even with that, it is clear that JXL is much faster than encoding AVIF
|
|
|
monad
|
2024-09-15 11:16:58
|
Yeah, question is always is it _faster enough_, _denser enough_ ... but I think your presentation is pretty good, you did things much better than most would.
|
|
|
RaveSteel
|
2024-09-15 11:17:14
|
Thanks
|
|
|
monad
Yeah, question is always is it _faster enough_, _denser enough_ ... but I think your presentation is pretty good, you did things much better than most would.
|
|
2024-09-15 11:17:40
|
That is the question that remains to be answered by Valve indeed
|
|
2024-09-15 11:17:47
|
But we'll see
|
|
2024-09-15 11:21:17
|
Also I would count it as a win if the default remains AVIF but an option to ouput JXL is added
|
|
|
monad
|
2024-09-15 11:23:00
|
Yes, that would be the best outcome actually, until JXL has support in Chromium.
|
|
|
AccessViolation_
|
2024-09-15 03:34:17
|
Do you have any direct frame buffer captures from console emulators? I imagine screenshots from NES games for example would compress greatly if it's able to utilize the "patches" feature, because those consoles games themselves make heavy use of repeating sprites from a tiny sprite sheet
|
|
2024-09-15 03:35:32
|
This is assuming there are JXL encoders capable of utilizing that, I don't know whether there are actually
|
|
2024-09-15 03:37:48
|
Oh this is about Steam games, I see... Well, many modern games still use sprites in this way to achieve a retro look
|
|
|
RaveSteel
|
|
AccessViolation_
Do you have any direct frame buffer captures from console emulators? I imagine screenshots from NES games for example would compress greatly if it's able to utilize the "patches" feature, because those consoles games themselves make heavy use of repeating sprites from a tiny sprite sheet
|
|
2024-09-15 03:45:33
|
I would happily incoporate this into another comparison, but I don't know of any emulator that supports JXL
|
|
|
AccessViolation_
Oh this is about Steam games, I see... Well, many modern games still use sprites in this way to achieve a retro look
|
|
2024-09-15 03:46:16
|
I have included some "pixel art" games into the dataset, these images often get blown up massively if encoded to AVIF, even compared to PNG
|
|
|
AccessViolation_
|
2024-09-15 03:58:53
|
Ah nice, I'm guessing that's because both PNG and JXL are utilizing palette compression then, as those pixel art games will often have many in-game pixels that are the same color and in the image can be represented as few-bit indices into a color palette.
If `JXL_ENC_FRAME_SETTING_PATCHES` is set to `1`, JXL files should be even smaller as it will create not just palettes of pixels but pallets of groups of pixels as well. For example it would only store one of these tiles that I have highlighted with white lines, and the rest of the tiles would reuse the stored one
|
|
2024-09-15 04:02:39
|
But the patches need to be an exact match, so as soon as the game does funky upscaling with some sort of interpolation that makes that not the case it won't do it at all (in lossless mode)
|
|
|
RaveSteel
|
2024-09-15 04:03:20
|
luckily most pixel art games use nearest upscaling, so it still looks proper
|
|
|
AccessViolation_
|
2024-09-15 04:04:30
|
Ah, that's good
|
|
|
RaveSteel
|
2024-09-15 04:05:31
|
Take a look at this
|
|
2024-09-15 04:05:56
|
Same data, but the avif is almost 10(!) times larger
|
|
|
AccessViolation_
|
2024-09-15 04:07:19
|
Quite the difference indeed
|
|
2024-09-15 04:14:40
|
Unrelated, but now I'm thinking that it might be possible to create a custom encoder specifically for an NES emulator that doesn't even use a frame buffer as the screenshot source, but just directly builds a JXL from sprite data and other relevant information loaded in the emulator's memory. I wonder how small you could get the screenshots
|
|
|
RaveSteel
|
2024-09-15 04:17:26
|
This possibly(?) sounds like something an encoder could be purpose built for. But I wouldn't know, i'm not a programmer
|
|
2024-09-15 04:20:45
|
https://github.com/ValveSoftware/gamescope/issues/1525
|
|
2024-09-15 04:20:58
|
Here the feature request on gamescope's github
|
|
|
jonnyawsom3
|
2024-09-15 06:34:51
|
If it were possible I might've included memory usage too
|
|
2024-09-15 06:35:02
|
(I only just found the thread)
|
|
|
RaveSteel
|
|
If it were possible I might've included memory usage too
|
|
2024-09-15 06:36:27
|
Since I ran 16 encodes in parallel CPU usage was more the issue, but both encodes ran at the maximum possible speed. It took very little RAM, even with 16 parallel encodes
|
|
|
jonnyawsom3
|
|
AccessViolation_
This is assuming there are JXL encoders capable of utilizing that, I don't know whether there are actually
|
|
2024-09-15 06:37:43
|
Currently the patch detection in libjxl is mostly focused on text. Monad made a version that focuses on tiles such as in games, and it does add improvement, but the ideal solution would be directly referencing the sprite sheet in an emulator and essentially rebuilding the scene inside the JXL file. You can also do 2x, 4x and 8x nearest neighbour upsampling in JXL files, so it could be encoded at native resolution and just scaled in metadata instead
|
|
|
AccessViolation_
|
2024-09-15 06:38:24
|
Hehe, that's exactly what I came up with a bit further down
|
|
|
jonnyawsom3
|
|
RaveSteel
Since I ran 16 encodes in parallel CPU usage was more the issue, but both encodes ran at the maximum possible speed. It took very little RAM, even with 16 parallel encodes
|
|
2024-09-15 06:38:26
|
Actually yeah, fair point. I immedeately forgot it was e1, although I know I'd have OOM'd with 16 4K files at once
|
|
|
AccessViolation_
Hehe, that's exactly what I came up with a bit further down
|
|
2024-09-15 06:39:32
|
Natually in the 2 messages I skipped before getting distracted by the github issue Dx
|
|
|
AccessViolation_
|
2024-09-15 06:41:18
|
Does JXL allow you to transform these sprite like flip them? I know the NES has a handful of sprite transformations like these, and I'm wondering how many of them are natively available in JPEG XL. It's not a problem if there's some things JXL can't do, you'd just need to store some redundant data
|
|
2024-09-15 06:42:35
|
It's not something that's likely to appear in real world images *except specifically* screenshots of emulators that can do sprite transformations, so I don't expect much to be possible there
|
|
|
jonnyawsom3
|
2024-09-15 06:46:09
|
> We considered it `Rotation` (also flips, etc) but decided to keep it simple since it adds a bit of implementation complications to do patch blitting in arbitrary orientations and it is already hard enough to detect patches without considering orientations...
|
|
|
AccessViolation_
|
2024-09-15 06:54:20
|
Back on topic - does this version of the encoder used here in lossless mode suffer from some of the file size regressions that have been there since 0.8.X in lossy mode?
|
|
2024-09-15 06:55:24
|
If so, it might be more representative of JPEG XL as a format to go with the decoder on 0.8 as a bug is causing larger file sizes and worse quality in recent versions
|
|
|
RaveSteel
|
|
AccessViolation_
If so, it might be more representative of JPEG XL as a format to go with the decoder on 0.8 as a bug is causing larger file sizes and worse quality in recent versions
|
|
2024-09-15 06:57:48
|
While not comparing across mutiple releases, this graph showed slight improvement since 0.10.1
https://discord.com/channels/794206087879852103/803645746661425173/1284340338143526997
|
|
|
AccessViolation_
|
2024-09-15 07:01:28
|
Oh ok. Yeah I read the issue linked there before ([ Regression in lossy nonphotographic image quality #3530 ](<https://github.com/libjxl/libjxl/issues/3530#issuecomment-2132164263>)) which was about versions up to 0.10 being worse than 0.8 but I guess 0.11 resolved that then, nice (but also that was lossy, idk if lossless was affected)
|
|
2024-09-15 07:03:05
|
How do we expect Valve to react to this feature request?
|
|
2024-09-15 07:04:37
|
I'm guessing at best they'd want JXL support in embedded chromium first to actually be able to display it
|
|
|
RaveSteel
|
2024-09-15 07:07:43
|
If they chose to implement it I'd hope that that an option to chose JXL as an output format for screenshots would be added. AVIF will very likely remain the default for as long as chromium does not support JXL.
|
|
|
monad
|
|
AccessViolation_
Ah nice, I'm guessing that's because both PNG and JXL are utilizing palette compression then, as those pixel art games will often have many in-game pixels that are the same color and in the image can be represented as few-bit indices into a color palette.
If `JXL_ENC_FRAME_SETTING_PATCHES` is set to `1`, JXL files should be even smaller as it will create not just palettes of pixels but pallets of groups of pixels as well. For example it would only store one of these tiles that I have highlighted with white lines, and the rest of the tiles would reuse the stored one
|
|
2024-09-16 12:10:41
|
Current libjxl will not detect patches along those white lines. It may detect patches for the tiny decorations on the floor, which would likely make the file larger than without in this case. libjxl often makes bad decisions on non-text content.
|
|
2024-09-16 12:26:30
|
In any case, it does not try to do patch detection at all when fast speeds are required.
|
|
|
jonnyawsom3
|
2024-09-27 02:44:35
|
I only just realised, but you did the encodes running 16 jobs at once, right? Wouldn't that have messed with the multithreading of the encodes?
|
|
2024-09-27 02:47:26
|
Was wondering why the 4k set was so much slower than the 1080p, since usually larger images scale near-linearly to cores until a certain extent. Took 10x as long for 4x the pixels
|
|
|
RaveSteel
|
|
I only just realised, but you did the encodes running 16 jobs at once, right? Wouldn't that have messed with the multithreading of the encodes?
|
|
2024-09-27 06:48:23
|
It possibly has, the best way to compare would probably have been to encode one image after the other and compare the encoding times for each image.
But even though the 4k encode was *slightly* slower than it would have been (~2 seconds * 2 because of dataset size and * 4 because of pixel amount equals to rougly 16 seconds compared to the 22 seconds real "Encode to RAM" encoding time) it still showed the massive speed increase that is possible with adding support for JXL as an alternative to AVIF
|
|
|
username
|
2024-09-29 06:26:53
|
wouldn't a benefit of JXL compared to AVIF for game screenshots be that JXL can actually fully store 16-bit data while AVIF only goes up to 12-bit. the reason I bring this up is because (at least with DirectX and Windows) games can only really output as 8-bit, 10-bit, and 16-bit (ignoring older games and APIs which can get below 8-bit)
|
|
2024-09-29 06:27:59
|
only really relevant for native HDR games mostly
|
|
2024-09-29 06:40:47
|
https://learn.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range
|
|
2024-09-29 09:55:15
|
<@167354761270525953> <@238552565619359744>
apologies if the pings are unnecessary but I have no clue if Discord properly notifies people of new messages in threads
|
|
|
RaveSteel
|
2024-09-29 09:56:10
|
No worries, I have seen your message. I wanted to answer when I am not on mobile
|
|
|
jonnyawsom3
|
2024-09-29 09:58:11
|
Oh I saw it, but with no HDR display I've got limited experience with it. The closest I can get is taking NVIDIA Ansel photos that output float jxr files with imaginary values
|
|
2024-09-29 10:02:08
|
I don't think I know of any games that output 16bit, but that could just be a limitation of whatever library they're using to save the image
|
|
|
username
|
2024-09-29 10:09:42
|
I know that I can get this game to output as 8-bit or 10-bit or 16-bit by changing around some stuff in the dgVoodoo2 config and can confirm it provides a noticeable bending reduction when I set the internal color formats to a higher bit depth and display it as 10-bit on my 10-bit monitor with the right presentation mode https://store.steampowered.com/app/1304510/SCP_NineTailed_Fox/
|
|
2024-09-29 10:10:25
|
the bending reduction is really noticeable for all the dark areas
|
|
2024-09-29 10:11:28
|
if uh anyone has the proper software and know how for capturing high bit depth screenshots then this might be a good game to test with
|
|
|
jonnyawsom3
|
2024-09-29 10:11:40
|
<:banding:804346788982030337>
|
|
|
RaveSteel
|
|
username
only really relevant for native HDR games mostly
|
|
2024-09-29 12:20:08
|
This is currently only a theoretical advantage, because gamescope will always output a 10 bit AVIF, even though AVIF does support 12 bit indeed, as you mentioned.
I have also found no communication from Valve concerning their choice of AVIF. I strongly assume it is because a speed 10 AVIF is often smaller than a barely compressed PNG. This is pure speculation on my part though, I have not tested whether that is actually the case.
If anyone wants to benchmark encoding between PNG and AVIF, please do share it.
Mayb I'll get around to testing it, but I am much more interested in a possible inclusion of JXL into gamescope.
|
|
|
username
if uh anyone has the proper software and know how for capturing high bit depth screenshots then this might be a good game to test with
|
|
2024-09-29 12:21:18
|
The people over at the "HDR Den" discord seem to often use SKIV, maybe have a look at that. I haven't used it myself and there is no linux release for it, so no idea as to how it works
|
|
|
AccessViolation_
|
2024-10-07 04:45:17
|
I found a game that allowed me to choose between JPEG and PNG for the in-game camera mode, which gives me the normal "screenshot saved" popup from Steam. I guess games are allowed to hook into the screenshot system. Also I found that screenshots taken with the Steam Deck in the Steam UI are JPEG, and I also found some Steam discussions about screenshots being in JPEG by default. Any chance you could clarify in what situation Steam will use lossless AVIF? I don't quite understand
(RE: this issue: [ [Feature request] Add support for JPEG XL screenshots due to greater speed and compression #1525](<https://github.com/ValveSoftware/gamescope/issues/1525>))
<@167354761270525953>
|
|
|
username
|
|
AccessViolation_
I found a game that allowed me to choose between JPEG and PNG for the in-game camera mode, which gives me the normal "screenshot saved" popup from Steam. I guess games are allowed to hook into the screenshot system. Also I found that screenshots taken with the Steam Deck in the Steam UI are JPEG, and I also found some Steam discussions about screenshots being in JPEG by default. Any chance you could clarify in what situation Steam will use lossless AVIF? I don't quite understand
(RE: this issue: [ [Feature request] Add support for JPEG XL screenshots due to greater speed and compression #1525](<https://github.com/ValveSoftware/gamescope/issues/1525>))
<@167354761270525953>
|
|
2024-10-07 04:48:55
|
there is a setting in Steam that makes it so when you take a screenshot it will save both a JPEG and PNG and the PNGs have their own dedicated folder, the option for AVIF just makes it be used in HDR games instead of tone-mapped PNGs
|
|
|
AccessViolation_
|
2024-10-07 04:49:45
|
Ohh I see, thanks
|
|
|
RaveSteel
|
|
username
there is a setting in Steam that makes it so when you take a screenshot it will save both a JPEG and PNG and the PNGs have their own dedicated folder, the option for AVIF just makes it be used in HDR games instead of tone-mapped PNGs
|
|
2024-10-07 05:02:14
|
Do note that I could not get the steam deck to save even HDR games as AVIF on the steamdeck. I tested Doom Eternal, but all screenshots were PNG. Just to be sure I even checked /tmp, but no dice.
|
|
|
AccessViolation_
|
2024-10-07 05:03:01
|
Does the Deck even support HDR?
|
|
|
RaveSteel
|
2024-10-07 05:03:07
|
<@384009621519597581>
gamescope on the desktop will always save screenshots as AVIF if it is executed via `gamescope %command%` in game launhc settings
|
|
|
AccessViolation_
Does the Deck even support HDR?
|
|
2024-10-07 05:03:10
|
Yes
|
|
2024-10-07 05:03:23
|
It even has a dedicated icon for showing that it is displaying HDR
|
|
2024-10-07 05:03:33
|
Only for the steam dekc OLED though
|
|
|
AccessViolation_
|
|
RaveSteel
|
2024-10-07 05:04:55
|
To be aboslutely sure that no AVIF HDR screenshots were recorded i even attached a usb keyboard and pressed super+S, the screenshot keykombo, but this had no efect either
|
|
|
jonnyawsom3
|
|
AccessViolation_
I found a game that allowed me to choose between JPEG and PNG for the in-game camera mode, which gives me the normal "screenshot saved" popup from Steam. I guess games are allowed to hook into the screenshot system. Also I found that screenshots taken with the Steam Deck in the Steam UI are JPEG, and I also found some Steam discussions about screenshots being in JPEG by default. Any chance you could clarify in what situation Steam will use lossless AVIF? I don't quite understand
(RE: this issue: [ [Feature request] Add support for JPEG XL screenshots due to greater speed and compression #1525](<https://github.com/ValveSoftware/gamescope/issues/1525>))
<@167354761270525953>
|
|
2024-10-07 05:12:21
|
Yeah, you can do quite a bit with the hook https://github.com/BOLL7708/SuperScreenShotterVR
|
|
|
AccessViolation_
|
2024-10-07 05:14:24
|
We love integration
|
|
|
jonnyawsom3
|
|
RaveSteel
https://github.com/ValveSoftware/gamescope/issues/1525
|
|
2025-11-13 10:13:56
|
I ended up reading your issue again just now, and thought about our findings from this regression https://github.com/libjxl/libjxl/issues/4447
|
|
2025-11-13 10:14:02
|
I'm assuming you used Clang, so the main regression shouldn't have been present, but the standalone speed could've given it a slight boost too depending on how many threads you were using
|
|
|
RaveSteel
|
2025-11-13 10:19:13
|
No, it was a default cmake build from the arch repos
|
|
2025-11-13 10:19:27
|
and still it was that much faster
|
|
|
jonnyawsom3
|
2025-11-13 10:20:08
|
That means you could've got between 2-12x the performance then
|
|
|
RaveSteel
|
2025-11-13 10:20:35
|
Since I opened that issue I have tested more with 4k and HDR on steam
|
|
2025-11-13 10:20:46
|
HDR AVIFs take seconds to save
|
|
2025-11-13 10:21:16
|
I have vibecoded a very bad implementation of libjxl into gamescope and it was many times faster
|
|
2025-11-13 10:21:41
|
of course nothing I would bring into this discussion on a serious basis, since it was just vibecoded
|
|
|
jonnyawsom3
|
2025-11-13 10:22:15
|
<@274048677851430913> took a shot at integrating simple-lossless JXL into ReShade, works great and thought about making a PR
|
|
|
RaveSteel
|
2025-11-13 10:22:53
|
sounds great!
|
|
2025-11-13 10:23:18
|
another pain point of steams HDR AVIFs is that the PNGs derived from them are not identical to the AVIF
|
|
2025-11-13 10:23:40
|
ssimulacra2 shows around 96 score, whioch is pretty similar, but still not identical
|
|
|
Kampidh
|
|
<@274048677851430913> took a shot at integrating simple-lossless JXL into ReShade, works great and thought about making a PR
|
|
2025-11-13 11:24:37
|
Already tested HDR on both 10 bit and 16 bit (float) surface format and seems to work well, about time now :p
Though I just found out by default reshade HDR PNG implementation always converts that F16 linear sRGB surface into r2020 PQ, while my jxl implementation preserve it (which I do prefer personally)
|
|
|
username
|
|
Kampidh
Already tested HDR on both 10 bit and 16 bit (float) surface format and seems to work well, about time now :p
Though I just found out by default reshade HDR PNG implementation always converts that F16 linear sRGB surface into r2020 PQ, while my jxl implementation preserve it (which I do prefer personally)
|
|
2025-11-13 11:37:10
|
preserving the original space seems preferable IMO especially since JXL is fully color managed.
Also something else but I know that the simple lossless encoder for JXL sadly doesn't support this but it would be cool if the ReShade implementation could save the depth information to the dedicated depth channel that the JXL format supports.
<@794205442175402004> how hard would it be to have the [simple lossless encoder](https://github.com/libjxl/simple-lossless-encoder) support writing to other channels besides RGBA?
|
|
2025-11-13 11:38:22
|
quickly skimming the code it doesn't seem to be setup in a way that would allow writing to other channels easily but idk maybe I'm wrong
|
|
|
jonnyawsom3
|
2025-11-13 11:45:21
|
Well Simple is a cut down version of Fast, which says it supports 4 channels <https://github.com/libjxl/libjxl/tree/main/tools/fast_lossless> but is hardcoded for Alpha <https://github.com/libjxl/libjxl/blob/main/lib/jxl/enc_fast_lossless.cc>
|
|
|
Kampidh
Already tested HDR on both 10 bit and 16 bit (float) surface format and seems to work well, about time now :p
Though I just found out by default reshade HDR PNG implementation always converts that F16 linear sRGB surface into r2020 PQ, while my jxl implementation preserve it (which I do prefer personally)
|
|
2025-11-13 11:49:16
|
And that's something I never considered, with practically all screenshot formats being 10-bit or int, JXL might be the only way to get a truly lossless image from some games (Ignoring JXR because it's support is awful)
|
|
|
Kampidh
|
2025-11-14 12:41:21
|
one test with 16 bit float
|
|
|
jonnyawsom3
|
2025-11-14 01:10:26
|
Ah yes, thank you Irfanview for not doing any color management
|
|
2025-11-14 01:11:10
|
Good photo though, and I might actually use ReShade to get around an FSR bug with NMS' photo mode
|
|
|
Kampidh
|
2025-11-14 01:13:02
|
I usually use tev for viewing HDR images
|
|
|
_wb_
|
|
username
preserving the original space seems preferable IMO especially since JXL is fully color managed.
Also something else but I know that the simple lossless encoder for JXL sadly doesn't support this but it would be cool if the ReShade implementation could save the depth information to the dedicated depth channel that the JXL format supports.
<@794205442175402004> how hard would it be to have the [simple lossless encoder](https://github.com/libjxl/simple-lossless-encoder) support writing to other channels besides RGBA?
|
|
2025-11-14 08:07:06
|
in principle that shouldn't be hard, but part of what makes it fast is that it is hardcoded for taking 1-4 interleaved channels (in uint8 or uint16) as input, so it would need to be extended.
|
|
|
jonnyawsom3
|
|
_wb_
in principle that shouldn't be hard, but part of what makes it fast is that it is hardcoded for taking 1-4 interleaved channels (in uint8 or uint16) as input, so it would need to be extended.
|
|
2025-11-14 08:10:36
|
Games generally don't use the Alpha channel, so in this instance Depth could likely be replace it
|
|
|
username
|
2025-11-14 08:21:50
|
hmm yeah I forgot that alpha isn't relevent for this use-case so would doing that be as simple as just changing what the final channel type is marked as for alpha or no? (non-upstreamable change)
|
|
|
_wb_
|
2025-11-14 08:26:35
|
Yes, actually in general we should probably upstream something like that so it can be used not just for RGBA but also CMYK or RGBD
|
|
|
username
|
|
_wb_
Yes, actually in general we should probably upstream something like that so it can be used not just for RGBA but also CMYK or RGBD
|
|
2025-11-16 07:46:16
|
for the time being does this seem like a correct hack for making the simple lossless encoder use it's input of RGBA to output as a proper RGBD file?
```diff
--- simple_lossless.cc
+++ simple_lossless_depth-hack.cc
@@ -637,32 +637,27 @@
if (frame->bitdepth <= 14) {
output->Write(1, 1); // 16-bit-buffer sufficient
} else {
output->Write(1, 0); // 16-bit-buffer NOT sufficient
}
if (have_alpha) {
output->Write(2, 0b01); // One extra channel
- if (frame->bitdepth == 8) {
- output->Write(1, 1); // ... all_default (ie. 8-bit alpha)
- } else {
output->Write(1, 0); // not d_alpha
- output->Write(2, 0); // type = kAlpha
+ output->Write(2, 1); // type = kDepth
output->Write(1, 0); // not float
if (frame->bitdepth == 10) {
output->Write(2, 0b01); // bit_depth.bits_per_sample = 10
} else if (frame->bitdepth == 12) {
output->Write(2, 0b10); // bit_depth.bits_per_sample = 12
} else {
output->Write(2, 0b11); // 1 + u(6)
output->Write(6, frame->bitdepth - 1);
}
output->Write(2, 0); // dim_shift = 0
output->Write(2, 0); // name_len = 0
- output->Write(1, 0); // alpha_associated = 0
- }
} else {
output->Write(2, 0b00); // No extra channel
}
output->Write(1, 0); // Not XYB
if (frame->nb_chans > 2) {
output->Write(1, 1); // color_encoding.all_default (sRGB)
} else {
```
|
|
|
_wb_
|
2025-11-16 08:49:40
|
Looks ok. You can use jxlinfo to check if it's correctly tagged.
|
|
|
RaveSteel
|
2026-01-09 03:55:14
|
https://github.com/0fbcb238c0/gamescope-jxl/tree/jxl-screenshots-avif-removed
|
|
2026-01-09 03:55:48
|
I did only some rough benchmarking, since it is hard to make direct comparisons as I have to switch the gamescope binaries around
|
|
2026-01-09 03:56:22
|
But, as expected, the JXL capture will always be smaller than the AVIF screenshots
|
|
2026-01-09 03:57:29
|
I tested 4 games, Holocure, Doom Eternal, Deep Rock Galactic and Death Must Die
|
|
2026-01-09 03:58:19
|
Regarding Deep Rock Galactic, which I have used this adapted gamescope in, I already captured 102 images
|
|
2026-01-09 04:01:23
|
The screenshots will on average be around 0.5-1MB smaller than the comparable AVIF image (in Deep Rock Galactic)
This varies per game of course
|
|
2026-01-09 04:08:20
|
For Death Must Die (Pixel art) the difference is more significant.
```
704K gamescope_2026-01-09_16-40-37.jxl - Main Menu
636K gamescope_2026-01-09_16-40-59.jxl - Hub
2,1M gamescope_2026-01-09_16-41-41.avif - Main Menu
2,8M gamescope_2026-01-09_16-41-53.avif - Hub
```
Captured were the main menu and the character in the main hub
|
|
2026-01-09 04:10:59
|
I have two branches in this fork: The one I posted, where I replaced AVIF entirely and a second one, where I plan to make both AVIF and JXL work
|
|
|
AccessViolation_
|
2026-01-09 04:13:23
|
btw, do you normalize them by visual quality? in terms of file size difference
|
|
|
RaveSteel
|
2026-01-09 04:14:08
|
Are you refering to the file size comparison I posted? This can be done with `du -sh`
|
|
2026-01-09 04:14:25
|
In terms of capture all images are lossless
|
|
|
AccessViolation_
|
2026-01-09 04:14:40
|
ahhh gotcha
|
|
2026-01-09 04:14:58
|
I thought they were lossy, that's why I asked
|
|
|
RaveSteel
|
2026-01-09 04:14:59
|
As can be read on my profile: "Give me lossless or give me death" XD
|
|
|
AccessViolation_
|
2026-01-09 04:15:13
|
based
|
|
|
jonnyawsom3
|
|
RaveSteel
I tested 4 games, Holocure, Doom Eternal, Deep Rock Galactic and Death Must Die
|
|
2026-01-09 04:16:28
|
Holocure and Deep Rock my beloved. The latter I was using to test simple-lossless JXL in ReShade
|
|
|
RaveSteel
|
2026-01-09 04:17:08
|
I first thought of trying to include simple lossless, but found normal libjxl to be easier, novice coder and all that
|
|
2026-01-09 04:18:04
|
Also I had some help from ChaGPT, but as far as I can tell by comparing to other projects, nothing too unusual slipped in
|
|
2026-01-09 04:18:18
|
the most complex part was the bitshifting that has to be done for JXL but not for AVIF
|
|
2026-01-09 04:18:45
|
since gamescope uses DRM_FORMAT_XRGB2101010
|
|
2026-01-09 04:20:41
|
Specifically refering to [these lines of code](https://github.com/0fbcb238c0/gamescope-jxl/commit/737a541218557a7f45aa131b3af9fb01d7d76f71#diff-452db373032f99b8c4bd2ed8b40bbd2bab7bed63bf8c51714acc025ea9b6200fR2969)
|
|
|
jonnyawsom3
|
|
RaveSteel
the most complex part was the bitshifting that has to be done for JXL but not for AVIF
|
|
2026-01-09 05:44:49
|
You mean this? And what's it doing, 10-bit to 16-bit?
|
|
|
RaveSteel
|
2026-01-09 06:28:08
|
Yes, via padding as far as I underrstand. I could have likely changed the DRM format to full 16 bit instead, but the filesize would have bloated enormously with little to no benefit
|
|
2026-01-09 06:28:50
|
This is how it looks like if this code is used with AVIF
|
|
2026-01-09 06:29:43
|
If the bits are not padded as shown here, the JXL will appear very dark
|
|
2026-01-09 06:30:30
|
I would show an example, but have deleted the improper JXLs a few weeks before I got it working properly
|
|
2026-01-09 06:44:55
|
I considered adding the JXL parallel runner for threaded encoding, but even single threaded JXL is faster than AVIF
|
|
2026-01-09 06:45:44
|
at least from testing with cjxl, 4 threads could lead to a significant improvement
|
|
2026-01-09 06:45:54
|
after that it drops off a lot
|
|
|
RaveSteel
This is how it looks like if this code is used with AVIF
|
|
2026-01-09 06:49:44
|
Ah, for those who are not on linux, this is how it's supposed to look like
|
|
|
jonnyawsom3
|
|
RaveSteel
If the bits are not padded as shown here, the JXL will appear very dark
|
|
2026-01-09 07:02:04
|
I could be wrong, but I think you can either zero-pad the LSB or use this to directly set it to the 10-bit range https://github.com/libjxl/libjxl/blob/53042ec537712e0df08709524f4df097d42174bc/lib/include/jxl/types.h#L124>
|
|
2026-01-09 07:02:35
|
Based on info in this https://github.com/libjxl/libjxl/issues/1763
|
|
|
RaveSteel
|
2026-01-09 07:04:05
|
Good to know, thanks
Will try this out later
|
|
2026-01-09 07:06:38
|
Wait, IIRC the "always float" part of JXL only applies to lossy, right?
Since the capture here is lossless, the bitdepth is more "rigid", no?
|
|
|
jonnyawsom3
|
2026-01-09 07:08:39
|
Yeah, you'd have to add a separate path if you wanted to allow SDR captures too, but HDR games will only output 10bit usually, so it should be fine
|
|
|
RaveSteel
|
2026-01-09 07:08:57
|
There's a catch here, gamescope always captures in 10 bit, even for SDR
|
|
2026-01-09 07:10:47
|
PNG with DRM_FORMAT_XRGB8888 are in the code, but never used when actually capturing screenshots
|
|
2026-01-09 07:11:12
|
Probably used for the steam gamescope session I'd assume
|
|
|
jonnyawsom3
|
2026-01-09 07:14:21
|
Huh, weird but the JXL can still be set as 10-bit. Decoders can just request 8-bit from libjxl ~~Once it stops outputting Linear for sRGB~~
|
|
|
RaveSteel
|
2026-01-09 07:17:11
|
I thought about this during testing, but decided to try and keep as close as possible to the original AVIF code
|
|
2026-01-09 07:18:09
|
I did set the bitdepth of the JXL encoder to 8 during that, which worked fine
|
|
2026-01-09 07:18:15
|
so maybe it would be possible
|
|
2026-01-09 07:18:37
|
but for 8 bit capture there is a whole block for PNG capture
|
|
2026-01-09 07:19:10
|
the previous AVIF, now JXL encoder, are located entirely within the HDR screenshot function
|
|
|
jonnyawsom3
|
|
RaveSteel
I did set the bitdepth of the JXL encoder to 8 during that, which worked fine
|
|
2026-01-09 07:22:24
|
Wait, so you're padding 10-bit, to 16-bit, then saving to 8-bit?
|
|
|
RaveSteel
|
2026-01-09 07:22:49
|
nono, that was just in testing
|
|
2026-01-09 07:22:55
|
To see if it would work
|
|
|
jonnyawsom3
|
2026-01-09 07:22:56
|
Riight
|
|
|
RaveSteel
I considered adding the JXL parallel runner for threaded encoding, but even single threaded JXL is faster than AVIF
|
|
2026-01-09 07:24:56
|
Effort 1/Fast Lossless lives up to the name. Since you already added full libjxl instead of the cut down encoders, maybe effort 2 with a few threads would be a good fit. Depends on content and resolution though thanks to chunked encoding
|
|
|
RaveSteel
|
2026-01-09 07:30:34
|
I would consider this, but gamescope is kinda problematic with recording screenshots in general. You basically have to mash the keyboard shortcut for screenshotting, because it may not capture one otherwise
|
|
2026-01-09 07:31:34
|
and since that may either result in many screenshots, or only one or two screenshots, it is IMO better to stay with effort 1
|
|
2026-01-09 07:31:44
|
you can simply reencode losslessly afterwards, after all
|
|
2026-01-09 07:32:58
|
Having said that, I will still try it out
|
|
2026-01-09 07:33:12
|
it may just work better
|
|
2026-01-09 08:41:49
|
Alright, that was much better than expected
|
|
2026-01-09 08:42:18
|
Encoding time of a glxgears 1080p window went from around 100ms at effort 1 to 60-70ms
|
|
2026-01-09 08:43:19
|
Before: JXL encode took 102 ms
After: JXL encode took 65 ms
|
|
|
jonnyawsom3
|
2026-01-09 08:44:20
|
Effort 2 on 4 threads?
|
|
|
RaveSteel
|
2026-01-09 08:44:49
|
I used JxlThreadParallelRunnerDefaultNumWorkerThreads, no idea what it defaults too
|
|
2026-01-09 08:45:02
|
effort 2 with threading is as fast as unthreaded effort 1
|
|
|
jonnyawsom3
|
2026-01-09 08:45:32
|
That'll be all threads on the CPU
|
|
|
RaveSteel
|
2026-01-09 08:45:53
|
alright
|
|
2026-01-09 08:46:13
|
well, at least with glxgears, which is mostly a black screen, there is pretty much no improvement in density
|
|
2026-01-09 08:46:23
|
i'll need to test a game
|
|
2026-01-09 09:19:44
|
effort 1 single-threaded
```
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_21-57-44.jxl
JXL encode took 162 ms
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_21-57-52.jxl
JXL encode took 147 ms
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_21-58-10.jxl
JXL encode took 147 ms
```
#### from here on with all cpu threads
effort 1 threaded
```
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_22-00-40.jxl
JXL encode took 96 ms
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_22-00-44.jxl
JXL encode took 85 ms
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_22-00-44.jxl
JXL encode took 83 ms
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_22-00-56.jxl
JXL encode took 89 ms
```
effort 2 threaded
```
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_22-17-47.jxl
JXL encode took 105 ms
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_22-17-51.jxl
JXL encode took 82 ms
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_22-17-51.jxl
JXL encode took 94 ms
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_22-18-04.jxl
JXL encode took 82 ms
```
effort 3 threaded
```
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_22-05-47.jxl
JXL encode took 101 ms
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_22-05-51.jxl
JXL encode took 91 ms
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_22-06-42.jxl
JXL encode took 93 ms
```
effort 7 threaded (lol)
```
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_22-04-08.jxl
JXL encode took 4519 ms
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_22-04-09.jxl
JXL encode took 4395 ms
```
|
|
2026-01-09 09:20:12
|
effort 1 and 2 were pretty much the same in terms of density
|
|
2026-01-09 09:20:48
|
it only starts to make a difference at effort 3
|
|
2026-01-09 09:27:31
|
at 4 cpu threads:
effort 1 and 2 threaded were the same with 4 threads
effort 3 threaded was a bit slower than previously
```
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_22-26-32.jxl
JXL encode took 137 ms
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_22-26-44.jxl
JXL encode took 122 ms
[gamescope] [Info] xwm: Screenshot saved to /tmp/gamescope_2026-01-09_22-26-44.jxl
JXL encode took 123 ms
```
|
|
2026-01-09 09:28:13
|
so at least for my hardware effort 3 is very much viable, but for low power devices effort 1 may be preferable
|
|
2026-01-09 09:28:47
|
especially considering the insignificant difference in density from effort 1 to effort 2
|
|
2026-01-09 09:40:32
|
I tried something rather simple and it worked
|
|
2026-01-09 09:41:20
|
The original AVIF code uses the equivalent of the current JXL code which looks like this
```
color_encoding.primaries =
bHDRScreenshot ? JXL_PRIMARIES_2100 : JXL_PRIMARIES_SRGB;
```
|
|
2026-01-09 09:41:34
|
So I tried setting this same thing for the bitdepth
|
|
2026-01-09 09:41:42
|
``` basic_info.bits_per_sample = bHDRScreenshot ? 10 : 8;```
|
|
2026-01-09 09:41:55
|
and it seems to work
|
|
2026-01-09 09:42:04
|
SDR gets saved as 8 bit and HDR as 10 bit
|
|
2026-01-09 09:43:26
|
Is there anything I am missing which could cause problems with this?
|
|
|
username
|
2026-01-09 09:58:55
|
can't games output as 16 bit?
|
|
2026-01-09 09:59:21
|
actually don't most if not all HDR games output as 16 bit and not 10 bit technically?
|
|
|
RaveSteel
|
2026-01-09 10:00:49
|
Saving as 16 bit would bloat filesizes, and 8 bit screenshots are the default for SDR after all
|
|
2026-01-09 10:01:07
|
But actually no idea about if games output 16 bit
|
|
|
username
|
2026-01-09 10:02:20
|
actually you bringing up SDR being done as 8 bit reminds me that some SDR games actually output as 10 bit
|
|
|
RaveSteel
|
2026-01-09 10:02:36
|
Which would be the default gamescope captures in
|
|
2026-01-09 10:02:55
|
I wonder if I should keep the 10 bit at all times or do 8 bit for SDR capture
|
|
2026-01-09 10:03:20
|
always 10 bit is the default behaviour in gamescope after all
|
|
|
jonnyawsom3
|
|
username
actually don't most if not all HDR games output as 16 bit and not 10 bit technically?
|
|
2026-01-09 10:04:07
|
The display buffer is 10bit, RGBA1010102 to make 32 bits
|
|
|
RaveSteel
|
2026-01-09 10:04:38
|
and gamescope discards alpha, so 30 bits
|
|
|
jonnyawsom3
|
2026-01-09 10:04:38
|
Depends how the game itself handles it
|
|
|
username
|
|
The display buffer is 10bit, RGBA1010102 to make 32 bits
|
|
2026-01-09 10:05:22
|
I don't know how many games actually use this format for HDR. the cases I've seen of this format being used is for 10 bit SDR with RGBA16161616 being used for HDR
|
|
|
RaveSteel
|
2026-01-09 10:05:51
|
can you give an example?
|
|
|
username
|
2026-01-09 10:06:27
|
I think this game maybe? https://store.steampowered.com/app/870780/Control_Ultimate_Edition/
|
|
|
RaveSteel
|
2026-01-09 10:06:53
|
can you test it if you own it?
|
|
2026-01-09 10:07:17
|
does it have an inbuilt screenshot function?
|
|
|
username
|
2026-01-09 10:07:54
|
I don't know if it does. Ill install it for testing but it's gonna take a few hours for me
|
|
2026-01-09 10:08:48
|
also something else that might be an example of https://discord.com/channels/794206087879852103/1284444511375855667/1459307086671511756 is I think modern Unreal engine does the same or a similar thing
|
|
2026-01-09 10:09:30
|
I need to install some tooling/tools to check display swapchains to confirm though
|
|
|
RaveSteel
|
2026-01-09 10:10:56
|
sounds good
|
|
2026-01-09 10:12:31
|
Ah, another point in favor of 10 bit HDR — many viewers, such as mpv, expect HDR content to have 10 bits. the metadata may still be there at higher bitdepths, but it doesn't (always?) recognise it
|
|
2026-01-09 10:13:30
|
The entirety of HDR is weird and everyone is doing their own standards smh
|
|
|
username
|
|
RaveSteel
Ah, another point in favor of 10 bit HDR — many viewers, such as mpv, expect HDR content to have 10 bits. the metadata may still be there at higher bitdepths, but it doesn't (always?) recognise it
|
|
2026-01-09 10:15:34
|
I mean isn't that kinda a problem on the program/viewer if It can't handle different bitdepths? either way with JXL this shouldn't be a problem since libjxl lets you request a desired output bitdepth when decoding so everything should still work fine
|
|
2026-01-09 10:16:22
|
higher bitdepths will get dithered down
|
|
|
RaveSteel
|
2026-01-09 10:16:41
|
true to the first part. the second part only applies to lossy JXLs IIRC? do correct me if I am wrong here
|
|
2026-01-09 10:17:12
|
I pushed a commit with multithreading
|
|
2026-01-09 10:17:39
|
And I included chrono for measuring encoding time
|
|
2026-01-09 10:17:57
|
Will have to do the same for AVIF later, to properly compare encoding times
|
|
|
username
|
2026-01-09 10:18:40
|
|
|
2026-01-09 10:19:15
|
dithering is still done for lossless because the process of viewing a high bitdepth image in a lower bitdepth is a lossy process
|
|
|
RaveSteel
|
|
username
|
|
2026-01-09 10:20:00
|
I think the 16 bit depth is due to this image being captured with reshade. or does reshade always capture the native bitdepth?
|
|
|
username
|
|
RaveSteel
I think the 16 bit depth is due to this image being captured with reshade. or does reshade always capture the native bitdepth?
|
|
2026-01-09 10:21:31
|
ReShade is able to know the format of the output from the game but idk if that is actually being fully taken advantage of or if it's just doing 16 bit if it's not 8 bit
|
|
|
RaveSteel
|
2026-01-09 10:21:55
|
maybe <@274048677851430913> can explain how reshade works here
|
|
|
username
|
2026-01-09 10:27:22
|
is gamescope able to see/know the output swapchain of a game or no? because if not and if what I said about SDR being 10 bit and HDR being 16 bit is true then what would the solution here be? treat SDR as 10 bit and treat HDR as 12 bit or 16 bit?
|
|
2026-01-09 10:27:59
|
might be worth checking to see how much larger 16 bit JXLs actually are
|
|
|
RaveSteel
|
2026-01-09 10:28:16
|
gamescope only defines the output colour format for screenshots by file extension. like so
```
if ( path.extension() == ".jxl" )
drmCaptureFormat = DRM_FORMAT_XRGB2101010;
else if ( path.extension() == ".png" )
drmCaptureFormat = DRM_FORMAT_XRGB8888;
else if ( path.extension() == ".nv12.bin" )
drmCaptureFormat = DRM_FORMAT_NV12;
```
|
|
|
jonnyawsom3
|
|
RaveSteel
I think the 16 bit depth is due to this image being captured with reshade. or does reshade always capture the native bitdepth?
|
|
2026-01-09 10:28:32
|
It's 10-bit expanded to 16-bit IIRC
|
|
|
RaveSteel
|
2026-01-09 10:29:59
|
great
|
|
2026-01-09 10:30:37
|
if this is true then I will likely stay with always 10 bit for screenshots
|
|
2026-01-09 10:30:50
|
but we'll see
|
|
|
username
|
2026-01-09 10:32:55
|
Control is going to take a loooong time to download for me. in the meantime ill try and see if I have any HDR Unreal engine 5 games I can check with
|
|
|
RaveSteel
|
|
jonnyawsom3
|
|
RaveSteel
I think the 16 bit depth is due to this image being captured with reshade. or does reshade always capture the native bitdepth?
|
|
2026-01-09 10:43:46
|
https://saklistudio.com/miniblog/reshade-jpegxl-saga/
> It seems like in HDR PNG they do some color conversion that contributes to that heavy processing, while in JXL I only did buffer conversion (R10G10B10A2 to R16G16B16) without scaling, preserving 10 bit values 0-1023.
|
|
|
RaveSteel
|
2026-01-09 10:44:24
|
alright, so 10 bit it is
|
|
2026-01-09 10:47:20
|
since the PNG on the blog is 8 bit I think I will go with reshade's approach and do 8 bit for SDR and 10 bit for HDR
|
|
|
Kampidh
|
2026-01-09 10:47:22
|
My initial PR was native 10 bit, but then it seems to be changed to 16 bit scaled recently
|
|
|
RaveSteel
|
2026-01-09 10:47:36
|
oh? interesting
|
|
|
Kampidh
|
2026-01-09 10:48:32
|
https://github.com/crosire/reshade/blob/dc4e47ac2dde03f892f0be5ff1d4a241847c71ff/source/runtime.cpp#L5231
|
|
|
RaveSteel
|
2026-01-09 10:49:20
|
any idea why this was changed?
|
|
2026-01-09 10:49:49
|
it seems better to retain the original 10 bits in my opinion
|
|
|
Kampidh
|
2026-01-09 10:54:09
|
Mmm I'm not really sure since it got changed quite a bit since the last time I checked
|
|
|
jonnyawsom3
|
|
Kampidh
Mmm I'm not really sure since it got changed quite a bit since the last time I checked
|
|
2026-01-09 10:55:43
|
Looks like it was this commit https://github.com/crosire/reshade/commit/7303208e58163e58ef59857995abe985bf958fc2
|
|
|
Kampidh
|
2026-01-09 10:56:39
|
Shouldn't be a massive performance hit though since it's just a scaling without color conversion, but I do also prefer native bitdepth x)
|
|
|
RaveSteel
|
|
username
|
2026-01-09 10:56:59
|
yeah having the bitdepth be native is nice
|
|
|
Kampidh
|
2026-01-09 10:57:08
|
Ah yes you beat me to it for sharing the commit link :p
|
|
|
RaveSteel
|
2026-01-09 11:20:28
|
Setting the bitdepth to 8 for SDR doesn't seem to conflict with the bit expansion
|
|
2026-01-09 11:21:04
|
I took a PNG screenshot via steam and a JXL screenshot via gamescope in a game with static elements and both have the same checksum
|
|
2026-01-09 11:21:33
|
So it seems I can simply save SDR screenshots as 8 bit JXLs
|
|
|
username
|
2026-01-09 11:22:04
|
hmm. do you have any Unreal 5 (4 might work as well idk) games to test?
|
|
|
RaveSteel
|
2026-01-09 11:22:33
|
let me check the list of unreal engine games on wikipedia
|
|
2026-01-09 11:23:20
|
Yeah I have one
|
|
2026-01-09 11:23:23
|
let me test
|
|
2026-01-09 11:32:12
|
well, the problem I am encountering is that steam, not gamescope, produces glitchart instead of screenshots
|
|
2026-01-09 11:32:14
|
|
|
2026-01-09 11:34:20
|
it even happens with vanilla gamescope lol
|
|
2026-01-09 11:37:53
|
Seems to be an issue of the steam client with gamescope
|
|
2026-01-09 11:38:24
|
happens in deep rock galactic as well
|
|
2026-01-09 11:39:09
|
the gamescope screenshots work and look as epxtected though
|
|
2026-01-09 11:56:33
|
Testing some more, 8 bit capture for SDR works better than expected. Capturing SDR JXLs with the same checksum as PNG screenshots is repeatable in multiple games, so 8 bit capture is actually bitexact compared to the classic steam screenshotting
|
|
2026-01-10 07:59:38
|
<@184373105588699137> it would theoretically possible to encode scRGB, but doing so would include modifying other parts of gamescope too and I am out of my depth here honestly. gamescope only offers EOTF_PQ and EOTF_Gamma22 so I would have to hack linear in as well. I could use the code i added to encode 16 bit float, but only with gamma it seems
So I will, at this time, keep it simple and stay with 10 bit for PQ and 8 bit for SDR, which is already a departure from the default always 10 bit
|
|
2026-01-10 08:06:37
|
Is there even a game which solely features scRGB as its HDR option?
scRGB is rare as it is already
|
|
2026-01-10 11:43:15
|
Did some benchmarking to compare vanilla gamescope with AVIF to the JXL encoder
Do keep in mind that the JXLs will be even smaller than expected because they are 8 bit while the AVIFs are 10 bit.
But even if both were equal, JXL would still win handily
Effort 1 for all JXLs
Factorio:
```
AVIF:
489 ms
495 ms
482 ms
493 ms
489 ms
Total file size: 28MiB
JXL:
85 ms
88 ms
90 ms
86 ms
84 ms
Total file size: 16MiB
```
Deep Rock Galactic:
```
AVIF:
351 ms
349 ms
306 ms
292 ms
334 ms
Total file size: 19.8MiB
JXL:
90 ms
81 ms
63 ms
63 ms
60 ms
Total file size: 7.9MiB
```
Holocure:
```
AVIF:
277 ms
210 ms
214 ms
199 ms
183 ms
Total file size: 8.6MiB
JXL:
49 ms
45 ms
64 ms
65 ms
61 ms
Total file size: 1.9MiB
```
Doom Eternal
```
AVIF:
267 ms
399 ms
384 ms
309 ms
390 ms
Total file size: 21.5MiB
JXL:
66 ms
80 ms
89 ms
75 ms
87 ms
Total file size: 9.8MiB
```
|
|
|
username
|
2026-01-11 02:44:22
|
always using 8 bit for SDR still feels wrong to me. I remember I was a bit annoyed a few months back because Steam would only capture 8 bit for SDR meanwhile the game itself was outputting 10 bit to my 10 bit monitor
|
|
|
RaveSteel
|
2026-01-11 02:56:31
|
Changing SDR capture to 8 bit was a choice I made. Could always switch back to 10 bit
|
|
2026-01-11 02:57:28
|
I simply assumed that 8 bit would be "better" because it does not really matter for SDR to my understanding
|
|
2026-01-11 02:58:03
|
How did you know that the game put out 10 bit btw?
|
|
2026-01-11 02:58:13
|
And which game was it
|
|
|
username
|
2026-01-11 03:21:37
|
it was this game https://store.steampowered.com/app/1304510/SCP_NineTailed_Fox/ which I went and modified the dgVoodoo2 config for it to set the default texture creation/allocation format to 10 bit and the output framebuffer/swapchain to 10 bit which resulted in noticeably less bending when my monitor was set to 10 bit. the Steam screenshots however where all 8 bit and had noticeable banding
|
|
2026-01-11 03:24:45
|
oh also I only got an hour or so left on the download for [Control](https://store.steampowered.com/app/870780/Control_Ultimate_Edition/) however I don't have SteamOS or anything so all ill be able to do is confirm the output format however I'm pretty sure it's 10 bit since the changelog says so: https://store.steampowered.com/news/app/870780/view/530966340601644728
|
|
2026-01-11 03:24:58
|
> Updated SDR to 10bit (from 8bit), which reduces visible color banding
|
|
|
RaveSteel
|
2026-01-11 09:59:05
|
HM, I Start to See why valve went with simply always capturing 10 bit
|
|
2026-01-11 09:59:35
|
Else it getw complicated fast with all the different bitdepths and formats that are used by games
|
|
|
username
oh also I only got an hour or so left on the download for [Control](https://store.steampowered.com/app/870780/Control_Ultimate_Edition/) however I don't have SteamOS or anything so all ill be able to do is confirm the output format however I'm pretty sure it's 10 bit since the changelog says so: https://store.steampowered.com/news/app/870780/view/530966340601644728
|
|
2026-01-11 11:28:36
|
You mean you are on windows? I would have liked steam+gamescopes output too see which format the game uses
|
|
2026-01-11 11:29:58
|
sadly I don't own the game and can take a look myself
|
|
|
AccessViolation_
|
|
username
> Updated SDR to 10bit (from 8bit), which reduces visible color banding
|
|
2026-01-11 12:59:59
|
this is so based
|
|
2026-01-11 01:00:35
|
this is the first time I personally see something deliberately choosing 10 bit SDR to void color banding
|
|
2026-01-11 01:01:10
|
I finally feel validated in having that discord profile description that complains about color banding
|
|
|
RaveSteel
|
2026-01-11 02:02:58
|
I tested some games
8 Bit SDR
- Holocure
- Doom Eternal
- Factorio (native game, doesn't use vulkan but SDL_PIXELFORMAT_RGB888)
- Deep Rock Galactic Survivor
- Warhammer 40k Spacemarine
- Death Must Die
10 bit SDR
- Deep Rock Galactic
-> actually uses the same color format for both SDR and HDR - VK_FORMAT_A2B10G10R10_UNORM_PACK32
With Terraria it doesn't even show the color format
So there is no uniform way to query color format
especially if it isn't even reported in the first place
|
|
|
Quackdoc
|
|
RaveSteel
Is there even a game which solely features scRGB as its HDR option?
scRGB is rare as it is already
|
|
2026-01-11 02:05:36
|
its fairly common, but I dunno if there are any scrgb only games, I know windows does push it hard
|
|
|
RaveSteel
|
2026-01-11 02:07:51
|
I did manage to capture scRGB I think, but the problem remains with the transfer functions offered by gamescope
|
|
2026-01-11 02:08:40
|
looks very wrong because of this of course
|
|
|
Quackdoc
|
2026-01-11 02:08:55
|
interesting
|
|
|
RaveSteel
|
2026-01-11 02:09:07
|
this is the jxl
|
|
|
Quackdoc
|
2026-01-11 02:09:27
|
can libjxl even recognise scrgb input?
|
|
|
RaveSteel
|
2026-01-11 02:09:49
|
seems so
|
|
2026-01-11 02:09:50
|
|
|
2026-01-11 02:09:54
|
I created this for testing
|
|
2026-01-11 02:10:22
|
16 bit float linear sRGB with red values exceeding 1
|
|
|
Quackdoc
|
2026-01-11 02:10:46
|
I'm at the er today so I can't look at code. but I might be able to take a gander next week
|
|
|
RaveSteel
|
2026-01-11 02:11:10
|
I haven't commited the code because it can't be used without the proper transfer function anyway
|
|
2026-01-11 02:11:41
|
If you want to take a go at hacking in linear EOTF that would be welcome
|
|
|
jonnyawsom3
|
|
RaveSteel
I tested some games
8 Bit SDR
- Holocure
- Doom Eternal
- Factorio (native game, doesn't use vulkan but SDL_PIXELFORMAT_RGB888)
- Deep Rock Galactic Survivor
- Warhammer 40k Spacemarine
- Death Must Die
10 bit SDR
- Deep Rock Galactic
-> actually uses the same color format for both SDR and HDR - VK_FORMAT_A2B10G10R10_UNORM_PACK32
With Terraria it doesn't even show the color format
So there is no uniform way to query color format
especially if it isn't even reported in the first place
|
|
2026-01-11 02:11:45
|
I was just looking into Deep Rock, since I remembered it using a 10bit swapchain in Reshade. Not sure if it actually uses 10bit values in SDR though
|
|
|
RaveSteel
|
2026-01-11 02:12:14
|
I tried to keep it simple and do the original AVIF encoder pretty much 1:1 with JXL, but there are a lot of edge cases I wasn't aware of
|
|
2026-01-11 02:12:36
|
again, I can now very much understand why Valve went with their approach
|
|
|
I was just looking into Deep Rock, since I remembered it using a 10bit swapchain in Reshade. Not sure if it actually uses 10bit values in SDR though
|
|
2026-01-11 02:13:51
|
Good question, maybe something that should be tested properly if anyone finds the time
|
|
|
jonnyawsom3
|
2026-01-11 06:13:56
|
Couldn't find a way to dump the swapchain in ReShade and see if it's using 8bit values in the 10bit swapchain
I did dump the depth buffer though and then tried recompressing the EXR... Interesting...
```cjxl -d 0 "FSD-Win64-Shipping.exe 2026-01-11 16-08-44 191 DepthBuffer.jxl" 12.jxl
JPEG XL encoder v0.12.0 029cec42 [_AVX2_] {Clang 20.1.8}
Encoding [Modular, lossless, effort: 7]
Compressed to 3311.6 kB (28.622 bpp).
1282 x 722, 0.698 MP/s, 16 threads.
cjxl -d 0 "FSD-Win64-Shipping.exe 2026-01-11 16-08-44 191 DepthBuffer.jxl" 12.jxl -e 8
JPEG XL encoder v0.12.0 029cec42 [_AVX2_] {Clang 20.1.8}
Encoding [Modular, lossless, effort: 8]
Compressed to 1041.6 kB (9.003 bpp).
1282 x 722, 0.222 MP/s, 16 threads.```
|
|
|
RaveSteel
|
2026-01-11 08:19:45
|
Using the python lubrary PIL and numpy to check for image data with a 10 bit JXL screenshot from DRG tells me it does only use 8 bits depsite the requested 10 bit color format
```
uint8
0 255
```
This test may not be accurate, I am checking if I can find another method
|
|
2026-01-11 08:21:43
|
Ok, this test is 100% *not* accurate lol
|
|
|
Couldn't find a way to dump the swapchain in ReShade and see if it's using 8bit values in the 10bit swapchain
I did dump the depth buffer though and then tried recompressing the EXR... Interesting...
```cjxl -d 0 "FSD-Win64-Shipping.exe 2026-01-11 16-08-44 191 DepthBuffer.jxl" 12.jxl
JPEG XL encoder v0.12.0 029cec42 [_AVX2_] {Clang 20.1.8}
Encoding [Modular, lossless, effort: 7]
Compressed to 3311.6 kB (28.622 bpp).
1282 x 722, 0.698 MP/s, 16 threads.
cjxl -d 0 "FSD-Win64-Shipping.exe 2026-01-11 16-08-44 191 DepthBuffer.jxl" 12.jxl -e 8
JPEG XL encoder v0.12.0 029cec42 [_AVX2_] {Clang 20.1.8}
Encoding [Modular, lossless, effort: 8]
Compressed to 1041.6 kB (9.003 bpp).
1282 x 722, 0.222 MP/s, 16 threads.```
|
|
2026-01-11 08:37:58
|
Short question since you encoded JXL->JXL
Do you know if it is intentional that libjxl attaches an ICC profile to a JXL in JXL->JXL conversions, even for lossless?
|
|
|
jonnyawsom3
|
|
RaveSteel
Short question since you encoded JXL->JXL
Do you know if it is intentional that libjxl attaches an ICC profile to a JXL in JXL->JXL conversions, even for lossless?
|
|
2026-01-11 08:48:26
|
There's this https://github.com/libjxl/libjxl/pull/2635
|
|
2026-01-11 08:49:12
|
There's a commit at the bottom saying it attaches an ICC for legacy compatibility. libjxl ignores it, png encoding for output uses it (I think)
https://github.com/sboukortt/libjxl/commit/945f7c5a8238fccb2bdb20d734639475fcaae3f1
|
|
|
RaveSteel
|
2026-01-11 08:49:21
|
Hm ,alright
|
|
2026-01-11 08:49:23
|
thanks
|
|
2026-01-11 08:49:46
|
But wait, why not directly create an ICC profile upon first encode?
|
|
2026-01-11 08:49:53
|
if it is for legacy purposes
|
|
2026-01-11 08:50:05
|
No need to wait until a transcode happens
|
|
|
jonnyawsom3
|
|
RaveSteel
Short question since you encoded JXL->JXL
Do you know if it is intentional that libjxl attaches an ICC profile to a JXL in JXL->JXL conversions, even for lossless?
|
|
2026-01-11 08:50:34
|
I've only got 1 build with EXR support due to it not being part of the releases, so I use that one to then get a JXL the other versions can ingest (v0.10 vs 0.11 for floats)
|
|
|
RaveSteel
|
2026-01-11 08:51:42
|
EXR support is pretty useful to have sometimes and since it is enabled by default when building I just keep it
|
|
|
jonnyawsom3
|
2026-01-11 08:54:11
|
~~One day <https://github.com/libjxl/libjxl/issues/3511>~~
|
|
|
RaveSteel
|
2026-01-11 08:55:18
|
EXR support is almost flawless since a while ago, hopefully the remaining roadblocks can be cleared in the future
|
|
2026-01-11 08:55:25
|
After jxl-rs is complete I suppose
|
|
2026-01-11 08:55:53
|
But well, some more work to be done there, jxl-rs is often 10-20 times slower than libjxl on my machine
|
|
|
jonnyawsom3
|
2026-01-11 08:59:14
|
Well, it is singlethreaded
|
|
|
RaveSteel
|
2026-01-11 09:03:49
|
fair point
|
|
2026-01-11 09:39:17
|
I am still not sure if this test is accurate, but using cv2 with python to print values indeed shows a difference between 8 bit screenshots of DRG and 10 bit screenshots
|
|
2026-01-11 09:39:44
|
and while that may be the case, I cannot find any real difference evben with pixel peeping
|
|
2026-01-11 09:40:04
|
but I will trust this test for now, as it put out values that fit the expecation
|
|
2026-01-11 09:42:52
|
Hm, could it be that DRG uses the constantly appearing very subtle noise as a sort of dithering? it is so subtle that it is only really noticable for me if I zoom massively
|
|
|
jonnyawsom3
|
2026-01-11 10:04:11
|
I think it does
|
|
|
RaveSteel
|
2026-01-12 01:15:34
|
I think it may be prudent to always capture 10 bit except for when games declare they are 8 bit
the 16 bit scrgb thingy is much more tedious than expected, so will either be only much later, or not at all
|
|
2026-01-12 01:15:44
|
This is also because the gamescope logic isn't great
|
|
2026-01-12 01:16:29
|
currently the extension of the to-be-written screenshot file is used to decide which DRM format should be used
|
|
2026-01-12 01:17:37
|
it even makes sense, kinda - because some games just do not report a color format. no idea if this could be queried, but this would also be additional work elsewhere
|
|
2026-01-12 01:19:39
|
for now I've started a windows VM and will experiment with how reshade handles jxl screenshots
|
|
|
username
|
|
Kampidh
Shouldn't be a massive performance hit though since it's just a scaling without color conversion, but I do also prefer native bitdepth x)
|
|
2026-01-12 09:57:34
|
might be worth submitting a PR (if you have the time) to bring it back to outputting native bitdepth. because the more I think about it the less desirable it sounds to have games that output at 10 bit (swapchain/framebuffer formats like RGBA1010102) be saved to 16 bit JXLs. It's very possible that the behavior change was unintentional since I wouldn't be surprised if the dev isn't checking the exact bitdepth(s) getting defined in the output files as long as they contain the right data
|
|
2026-01-12 09:59:07
|
I wanted to try reporting it to the ReShade dev but the GitHub repo has the issues section disabled
|
|
|
RaveSteel
|
|
I was just looking into Deep Rock, since I remembered it using a 10bit swapchain in Reshade. Not sure if it actually uses 10bit values in SDR though
|
|
2026-01-12 10:13:50
|
Any specific way you observed This? For me DRG shows "Format 24 (10bpc)" in the reshade statistics
|
|
2026-01-12 10:16:07
|
DRG reshade JXL Screenshots are also 8 bit
|
|
2026-01-12 10:35:58
|
I wonder if reshade properly detects that the game only sends 8 bit data with a 10 bit swapchain? While gamescope only shows the requested color format, which is 10 bit
|
|
|
jonnyawsom3
|
|
RaveSteel
Any specific way you observed This? For me DRG shows "Format 24 (10bpc)" in the reshade statistics
|
|
2026-01-12 02:30:10
|
Yeahh? That is the 10bit swapchain
|
|
|
RaveSteel
I wonder if reshade properly detects that the game only sends 8 bit data with a 10 bit swapchain? While gamescope only shows the requested color format, which is 10 bit
|
|
2026-01-12 02:32:40
|
https://discord.com/channels/794206087879852103/805007255061790730/1435011063354757251
|
|
|
RaveSteel
|
2026-01-12 03:12:45
|
I meant that while the swapchain may be 10 bit, reshade shows the content(?) as 8 bit. So a 10 bit swapchain, but only 8 bits are actually used I guess
|
|
|
https://discord.com/channels/794206087879852103/805007255061790730/1435011063354757251
|
|
2026-01-12 03:14:25
|
There is bug report regarding this on the [steam-for-linux github repo](https://github.com/ValveSoftware/steam-for-linux/issues/11165), but it likely affects the windows version as well, shared codebase and all that
|
|
|
RaveSteel
I meant that while the swapchain may be 10 bit, reshade shows the content(?) as 8 bit. So a 10 bit swapchain, but only 8 bits are actually used I guess
|
|
2026-01-12 03:35:10
|
And I have no idea how to get the true bitdepth of imagedata to decide the bitdepth of the to-be-encoded JXL
|
|
|
Kampidh
|
|
username
might be worth submitting a PR (if you have the time) to bring it back to outputting native bitdepth. because the more I think about it the less desirable it sounds to have games that output at 10 bit (swapchain/framebuffer formats like RGBA1010102) be saved to 16 bit JXLs. It's very possible that the behavior change was unintentional since I wouldn't be surprised if the dev isn't checking the exact bitdepth(s) getting defined in the output files as long as they contain the right data
|
|
2026-01-12 05:57:04
|
Urghh right, I keep thinking how unideal that simple multiplication scaling is..
Seems like the author wants to simplify buffer conversion from 32bpp (rgba1010102) to 48bpp (rgb161616) so that it can be directly used for both PNG (stb) and libjxl input
|
|
|
jonnyawsom3
|
2026-01-12 09:27:44
|
Couldn't they just pad the LSB, then both JXL and PNG can signal 10bit (Via encoder setting and sBIT)
|
|
|
username
|
2026-01-12 11:32:23
|
oh huh yeah I forgot about the `sBIT` PNG chunk
|
|
|
RaveSteel
|
2026-01-14 06:45:57
|
gamescope measures maxCLLNits for HDR, would it be a good idea to set the intensity target of the JXL to that value? There should be no downsides, right?
|
|
2026-01-14 06:46:51
|
So instead of the 10000 nits for PQ it would show i.e. 346 nits
|
|
|
jonnyawsom3
|
|
RaveSteel
There is bug report regarding this on the [steam-for-linux github repo](https://github.com/ValveSoftware/steam-for-linux/issues/11165), but it likely affects the windows version as well, shared codebase and all that
|
|
2026-01-14 06:55:00
|
I left a comment on that with some suggestions
|
|
|
RaveSteel
|
2026-01-14 07:00:02
|
I saw your comments and had a look at the reshade file you linked. would certainly be a good solution for gamescope, but lots of work to implement
|
|
2026-01-17 11:07:46
|
I pixel peeped some comparison screenshots I took of DRG with gamescope and reshade. reshade's a 8bit JXL has visibly more banding than the 10 bit JXLs gamescope produces
|
|
2026-01-17 11:08:10
|
So safe to say that DRG indeed uses 10 bits with SDR for reduced banding
|
|
|
jonnyawsom3
|
2026-01-17 11:09:11
|
Huh, really?
|
|
|
RaveSteel
|
2026-01-17 11:09:58
|
It isn't a massive difference, but visible at high magnification nonetheless
|
|
|
jonnyawsom3
|
2026-01-17 11:10:28
|
I tried to do some comparisons, but without a HDR monitor nothing captures the 10bit swapchain
|
|
|
RaveSteel
|
2026-01-17 11:10:59
|
gamescope now does :)
|
|
2026-01-17 11:11:09
|
Just need to do some polishing and then I can open a PR
|
|
2026-01-17 11:11:48
|
But to be fair, gamescope captured 10 bit even before my changes, just as AVIF, not JXL
|
|
|
jonnyawsom3
|
2026-01-17 11:15:30
|
I know before ReShade was capturing 10-bit, but it displayed as corrupted. Maybe that was just from running a HDR transform on SDR content, and not the bitdepth being incorrect like we thought? <@274048677851430913> would be curious to hear your thoughts, since you fixed the corruped output before
|
|
|
Kampidh
|
2026-01-17 11:27:31
|
Kinda forget already, but yep IIRC it was an output buffer mismatch. And I think the author wants to keep SDR to 8 bit (to have a unified buffer for multiple formats like I said above)
Maybe I can do further experiment, but I don't have DRG to test yet (and I don't think I have other 10bit SDR games on my library)
|
|
|
RaveSteel
|
2026-01-17 11:28:06
|
Have a look at other UE4/UE5 games you own, maybe they behave the same
|
|
|
Kampidh
|
2026-01-18 12:12:25
|
wait I think I found one~
|
|
2026-01-18 01:05:26
|
a quick bodge before bed, seems to be working though :p
|
|
|
jonnyawsom3
|
2026-01-18 01:25:21
|
Did some brightening to compare on my SDR screen, very nice... Now how to get that into ReShade and GameScope...
|
|
2026-01-18 01:26:33
|
|
|
|
Kampidh
|
2026-01-18 09:12:59
|
maybe soon™ alongside reverts for those 'bad' HDR scaling (if I'm not too lazy xD)
*and maybe ideally should bring that for PNG using `sBIT` chunk as well...*
|
|
2026-01-18 04:48:33
|
more examples that show quite a prominent banding on 8bit
|
|
|
jonnyawsom3
|
2026-01-18 05:04:29
|
I did a little test
10-bit JXL is half the size of optimised PNG at effort 1, effort 2 didn't have much effect
8-bit is a tiny bit larger than Oxipng with effort 1, but effort 2 is another 35% smaller (and 5x slower), so might be worth checking for GameScope
|
|
|
RaveSteel
|
2026-01-18 05:07:36
|
I had considered querying the number of CPU cores and switch between efforts depending on that
|
|
2026-01-18 05:07:57
|
For my CPU I can effortlessly encode at effort 3 and still be faster than AVIF
|
|
2026-01-18 05:08:38
|
I have left in effort 1 for now, but maybe something that could be added at a later time
|
|
2026-01-18 05:09:08
|
The binary I compiled for my own usage is effort 3
|
|
2026-01-18 05:10:07
|
But more important IMO would be trying to adapt gamescope to handle colorformats similarly to reshade so that screenshots are saved according the the swapchain bitdepth
|
|
2026-01-18 05:10:59
|
The 10 bit default for JXL isn't bad, since it's still much smaller than AVIF, but I would like to "properly" capture nonetheless
|
|
|
jonnyawsom3
|
2026-01-18 05:22:57
|
We'd need to check both bitdepth and colorspace, then set each independently if we want 'full' captures
|
|
|
RaveSteel
For my CPU I can effortlessly encode at effort 3 and still be faster than AVIF
|
|
2026-01-18 05:24:13
|
3 is weighted only, good for photographic images but by far the slowest to decode
|
|
|
RaveSteel
|
2026-01-18 05:53:28
|
Which effort level do you suggest?
|
|
2026-01-18 06:02:14
|
effort 4 is 7 times slower in encode than effort 3, and not really slower in decode for me
|
|
2026-01-18 06:02:20
|
maybe 5ms difference
|
|
2026-01-18 06:02:29
|
effort 5 is even slower
|
|
2026-01-18 06:02:41
|
which is of course expected
|
|
2026-01-18 06:03:31
|
Effort 5 decodes pretty much as fast as effort 3 on my system
|
|
2026-01-18 06:06:01
|
effort 2 decodes slightly faster, ~5-10ms
|
|
|
jonnyawsom3
|
2026-01-18 06:19:22
|
Everything 3+ uses weighted, 2 is fastest and 1 fastish. Mostly noticeable with 4K images or when scrolling though a folder
|
|
|
RaveSteel
|
2026-01-18 06:21:35
|
At least for me effort 1-3 encode in pretty much the same time, so I can afford the higher effort
|
|
2026-01-18 06:21:42
|
Only a few milliseconds difference
|
|
2026-01-18 06:21:43
|
But since my machine is very fast I chose effort 1 as the equivalent to the encode defined in the AVIF encoder for gamescope
|
|
2026-01-18 06:23:11
|
So it it'll be effort 1 in the PR I will open
|
|
2026-01-18 06:25:50
|
wait
|
|
2026-01-18 06:26:09
|
No idea if it'd make sense
|
|
2026-01-18 06:26:25
|
But I could set the used predictor via JXL_ENC_FRAME_SETTING_MODULAR_PREDICTOR
|
|
|
jonnyawsom3
|
2026-01-18 06:26:51
|
That only works effort 4+
|
|
|
RaveSteel
|
2026-01-18 06:26:57
|
Ah darn
|
|
|
jonnyawsom3
|
|
RaveSteel
effort 2 decodes slightly faster, ~5-10ms
|
|
2026-01-18 06:29:22
|
You did get me to re-test, not sure what changed but now e1 is the fastest to decode, barely
`3840 x 2160, geomean: 24.568 MP/s [23.012, 26.921], 10 reps, 0 threads.`
`3840 x 2160, geomean: 23.507 MP/s [21.416, 24.075], 10 reps, 0 threads.`
`3840 x 2160, geomean: 7.928 MP/s [7.494, 8.058], 10 reps, 0 threads.`
Weighted still drags it's feet though
|
|
2026-01-18 06:36:35
|
But anyway, e1 will still beat the old AVIF, e2 makes sure it beats PNG too
|
|
|
Kampidh
more examples that show quite a prominent banding on 8bit
|
|
2026-01-18 06:40:05
|
I'm trying to think, AVIF doesn't have dithering does it? So even if they did capture 10-bit SDR, it would probably have even more banding on the 8-bit display
|
|
|
RaveSteel
|
2026-01-18 06:52:43
|
For me it looks like this. e3 of course slower, but since I have many cores the decode is barely noticable in comparison
```
1920 x 1080, geomean: 30.429 MP/s [29.40, 31.34], , 10 reps, 0 threads.
1920 x 1080, geomean: 30.547 MP/s [28.98, 31.50], , 10 reps, 0 threads.
1920 x 1080, geomean: 8.038 MP/s [7.13, 8.26], , 10 reps, 0 threads.
```
With all cores
```
1920 x 1080, geomean: 286.227 MP/s [203.60, 314.30], , 10 reps, 32 threads.
1920 x 1080, geomean: 289.143 MP/s [185.43, 308.57], , 10 reps, 32 threads.
1920 x 1080, geomean: 99.722 MP/s [71.61, 107.81], , 10 reps, 32 threads.
```
Of the games I've tested e2 is often only barely smaller than e1
|
|
|
jonnyawsom3
|
2026-01-18 06:53:36
|
10bit or 8bit?
|
|
|
RaveSteel
|
2026-01-18 06:53:40
|
10 bit
|
|
2026-01-18 06:54:30
|
I would love to chose bitdepth depending on the colorspace and colorformat, but that will have to come later
|
|
|
jonnyawsom3
|
2026-01-18 06:55:03
|
Ah right, so you're always encoding as 10bit to cover all cases for now?
|
|
|
RaveSteel
|
2026-01-18 06:55:31
|
yep, same as the already included AVIF encoder
|
|
2026-01-18 06:55:46
|
I tried to be 1:1 wherever possible
|
|
|
jonnyawsom3
|
|
RaveSteel
There is bug report regarding this on the [steam-for-linux github repo](https://github.com/ValveSoftware/steam-for-linux/issues/11165), but it likely affects the windows version as well, shared codebase and all that
|
|
2026-01-18 06:56:22
|
I wonder if that'll happen again given JXL is a bit more forgiving in how it handles bitdepth
|
|
|
RaveSteel
|
2026-01-18 06:56:47
|
We'll see if/when JXL is included directly in steam
|
|
2026-01-18 06:56:54
|
soon™, surely
|
|
2026-01-18 06:57:23
|
I mentioned this before, but capturing AVIF screenshots via steam is incredibly slow, much slower than via gamescope
|
|
2026-01-18 06:57:58
|
Steam and gamescope in general have many issues that haven't been resolved even after months or years of open bug reports
|
|
2026-01-18 06:59:42
|
But we have to work with what we've got
|
|
|
monad
|
|
RaveSteel
The binary I compiled for my own usage is effort 3
|
|
2026-01-18 08:04:58
|
e3 is not usable if you are encoding images characteristic of flat UI or pixel art. the storage size will be massive compared to e1/e2.
|
|
2026-01-18 08:07:26
|
for most games maybe it is not a problem, but for edge cases you'll have poor performance
|
|
|
RaveSteel
|
2026-01-18 08:19:48
|
hm, true
|
|
2026-01-18 08:20:12
|
A test screenshot went from 366KB to 1.7MB with e3
|
|
|
monad
|
2026-01-18 08:23:10
|
imo, if you can't afford e4, but can afford more compute than e1, then e2 is safer for general content
|
|
|
RaveSteel
|
2026-01-18 08:24:23
|
I think e4 would still be fast enough, but slower than AVIF
|
|
2026-01-18 08:24:34
|
And I want to at least beat AVIF in terms of speed
|
|
2026-01-18 08:24:50
|
Density will pretty much always be better, but we know that already
|
|
2026-01-18 08:25:02
|
Alright, e2 it is then
|
|
|
jonnyawsom3
|
2026-01-20 10:35:52
|
Random discovery, print screen on Windows captures the 10bit game buffer, but pasting it most places converts it to 8bit. Making a 16bit Linear Krita canvas and *then* pasting it keeps the full data
|
|
2026-01-20 10:50:04
|
Theoretically, this is a 10bit Linear screenshot, though the values seem a bit weird... (Click/tap to zoom and load the original with color management)
|
|
|
RaveSteel
|
2026-01-20 03:40:49
|
Interesting
|
|
2026-01-20 03:42:38
|
some heavy posterisation it looks like here
|
|
|
Quackdoc
|
|
Theoretically, this is a 10bit Linear screenshot, though the values seem a bit weird... (Click/tap to zoom and load the original with color management)
|
|
2026-01-20 03:50:19
|
10bit linear? rough
|
|
|
jonnyawsom3
|
2026-01-20 04:24:25
|
I tried comparing it to an 8bit capture and they seemed identical, but the '10bit' was definitely a lot darker when pasted into an 8bit canvas, so I'm not sure what was going on
|
|
|
RaveSteel
|
2026-01-21 05:11:59
|
<@794205442175402004> two questions regarding the encoding of JXLs in gamescope
1. gamescope determines the maxCLL of a given frame and wrote that into the HDR AVIF.
Is there any negative to taking that determined maximum in nits and setting it as the intensity target of a lossless to-be-encoded JXL?
2. I am capturing 8 bit but also 10 bit data with JXL_TYPE_UINT16. Are JXL_BIT_DEPTH_FROM_PIXEL_FORMAT and JXL_BIT_DEPTH_FROM_CODESTREAM relevant for encode here? Or do they only/mostly affect decoding of the image?
Thanks in advance
|
|
|
_wb_
|
2026-01-21 06:18:14
|
<@604964375924834314> can probably answer this better than me.
1. I think intensity_target defines the luminance corresponding to maxval (1.0), not the actually-reached-peak. So if you set intensity_target to the maxCLL value, you'll end up making the image darker (e.g. if the image was 1.0 signaled = 10000 nits, and the highest value reached is 3800 nits, then if you set intensity_target to 3800, you get 1.0 signaled = 3800 nits and the whole image becomes darker).
2. I don't remember, is this part of the API not documented?
|
|
|
username
|
2026-01-21 06:19:59
|
it's documented here but a little bit unclear: https://libjxl.readthedocs.io/en/latest/api_common.html#_CPPv415JxlBitDepthType
|
|
|
spider-mario
|
2026-01-21 07:33:39
|
`intensity_target` is supposed to be an upper bound on the actually reached peak (ideally as tight as possible, but that’s not mandatory), and for non-PQ only, doubles as the luminance of 1.0
|
|
2026-01-21 07:35:36
|
(PQ is always interpreted as specified in SMPTE ST 2084)
|
|
2026-01-21 07:40:42
|
(that is,)
|
|
|
RaveSteel
|
2026-01-21 07:41:29
|
Good to know, thank you. In that case it doesn't apply here, because gamescope only determines maxCLL for HDR, which, in gamescope's case, is always PQ
About my second question, because the documentation is indeed a bit unclear:
Does it make a difference if I set it, or is it optional?
I am mainly asking, because I tried both and it didn't seem to make a difference, but maybe I am missing something?
If I were to use it, it would probably have to be JXL_BIT_DEPTH_FROM_CODESTREAM, because the input data is 8 or 10 bit with JXL_TYPE_UINT16
|
|
|
jonnyawsom3
|
|
RaveSteel
Good to know, thank you. In that case it doesn't apply here, because gamescope only determines maxCLL for HDR, which, in gamescope's case, is always PQ
About my second question, because the documentation is indeed a bit unclear:
Does it make a difference if I set it, or is it optional?
I am mainly asking, because I tried both and it didn't seem to make a difference, but maybe I am missing something?
If I were to use it, it would probably have to be JXL_BIT_DEPTH_FROM_CODESTREAM, because the input data is 8 or 10 bit with JXL_TYPE_UINT16
|
|
2026-01-21 10:51:01
|
Maybe this helps https://github.com/libjxl/libjxl/pull/1812
|
|
|
RaveSteel
|
2026-01-22 12:08:56
|
Hm, doesn't seem that setting the depth type like this even has an effect, at least in this case. I get bitexact identical files if all circumstances match
|
|
2026-01-22 12:11:02
|
The documentation says that JXL_BIT_DEPTH_FROM_PIXEL_FORMAT is the default, but maybe the encoder is smart enough to switch if it doesn't match?
|
|
|
jonnyawsom3
|
2026-01-22 12:13:04
|
Or the buffer is already scaled/padded correctly?
|
|
|
RaveSteel
|
2026-01-22 12:13:56
|
I am shifting the data so it fits into the 16 bits of JXL_TYPE_UINT16, but if I don't do that the image is just black or otherwise incorrect
|
|
2026-01-22 12:14:27
|
Of course it is possible, that I am doing something wrong here
|
|
|
_wb_
|
2026-01-22 06:16:17
|
Maybe check how cjxl/djxl are using this, iirc it does have something to do with supporting both msb padding and lsb padding.
|
|
|
RaveSteel
|
2026-01-22 11:33:14
|
If I understood it correctly it is mostly on how a JXL decoder interprets the data. But, seeing as all software that I tried used the default JXL_BIT_DEPTH_FROM_PIXEL_FORMAT (apparently), I will not set the bit depth type and simply retain the bitshift I am currently doing. That seems to be the best solution at this time
|
|
2026-01-22 06:56:26
|
I tested out JXL vs AVIF encoding on an old AMD Ryzen 2200G from 2018.
Just starting DRG was hard, with 30fps and dips in just the main menu with all low settings and FSR set to ultra performance.
JXL absolutely slaughtered AVIF here
|
|
2026-01-22 06:56:42
|
AVIF encode took 2973 ms
AVIF encode took 3516 ms
AVIF encode took 3217 ms
AVIF encode took 2879 ms
AVIF encode took 5015 ms
AVIF encode took 4640 ms
JXL encode took 730 ms
JXL encode took 791 ms
JXL encode took 832 ms
JXL encode took 727 ms
JXL encode took 1105 ms
JXL encode took 995 ms
|
|
|
jonnyawsom3
|
2026-01-22 06:59:42
|
I'm on a Ryzen 1700... I'm guessing you were running with no dedicated GPU?
|
|
|
RaveSteel
|
2026-01-22 06:59:49
|
yep
|
|
2026-01-22 07:01:38
|
this was with effort 2 btw
|
|
2026-01-22 07:01:45
|
could have been even faster at effort 1
|
|
|
username
|
2026-01-22 07:06:35
|
would maybe be good to include these results with the PR.
Actually speaking of, I'm wondering if it would make sense to try and set JXL as the default right off the bat since it does so much better on all metrics. Microsoft is able to get away with making Windows output JXR files for screenshots despite the only web browsers supporting them being unavailable now
|
|
|
RaveSteel
|
2026-01-22 07:07:31
|
I would prefer that, but setting JXL as the secondary option is the safe bet for now I reckon
|
|
2026-01-22 07:07:39
|
Maybe it can be brought up in the PR discussion
|
|
2026-01-22 07:08:03
|
And yes, I will include some of these results
|
|
2026-01-22 07:09:24
|
Also, while not quite an accurate measurement but rather by sight — capturing a JXL screenshot takes about 200MB of RAM. I'll take a look later at roughly how much AVIF uses
|
|
2026-01-22 07:16:46
|
AVIF varies much more than JXL in memory usage. I took around 20 screenshots with some pauses between each.
Sometimes it was around 200MB, same as JXL
|
|
2026-01-22 07:16:56
|
But other times it went up to 500MB
|
|
2026-01-22 07:17:11
|
But it mostly stayed between 200-400MB of memory usage
|
|
2026-01-22 07:18:24
|
I wonder how much these will differ when I will have included 8 bit capture at a later date
|
|
2026-01-22 07:19:16
|
But JXL should have no problem replacing AVIF as well as PNG in gamescope, while also making scRGB capture possible, which AVIF just cannot do
|
|
2026-01-22 07:19:27
|
no idea about nv12.bin though
|
|
2026-01-23 02:43:02
|
I opened the PR
https://github.com/ValveSoftware/gamescope/pull/2068
|
|
|
Quackdoc
|
2026-01-23 02:50:45
|
is it saving lossless or lossy?
|
|
|
RaveSteel
|
2026-01-23 02:51:02
|
lossless
|
|
2026-01-23 02:51:29
|
I didn't even add an option for lossy
|
|
|
Quackdoc
|
2026-01-23 02:52:00
|
perfect
|
|
|
RaveSteel
|
2026-01-23 02:52:35
|
lossless or nothing!
|
|
2026-01-23 02:53:11
|
Sadly the commits aren't squashed, that may be a problem. I did enable the option, so no idea why
|
|
|
Quackdoc
|
2026-01-23 02:53:29
|
commits get squashed when the maintainer merges
|
|
2026-01-23 02:53:37
|
or you manually squash
|
|
|
RaveSteel
|
2026-01-23 02:53:40
|
ah
|
|
2026-01-23 02:53:47
|
my first PR, so no idea
|
|
2026-01-23 02:54:34
|
I wonder how it'll go
|
|
2026-01-23 02:54:38
|
I wrote a wall of text
|
|
|
Quackdoc
|
2026-01-23 02:54:39
|
I usually don't squash myself unless it's asked, or I have a lot of nonsense commits I need to unfuck, but typically it's better to leave it in commits as it's easier to review
|
|
|
RaveSteel
|
2026-01-23 02:54:48
|
Good to know, thanks
|
|