Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vulkan color space is different when rendering to swap chain (sRGB) #4842

Open
valaphee opened this issue Dec 6, 2023 · 12 comments
Open

Vulkan color space is different when rendering to swap chain (sRGB) #4842

valaphee opened this issue Dec 6, 2023 · 12 comments
Labels
api: vulkan Issues with Vulkan type: bug Something isn't working

Comments

@valaphee
Copy link
Contributor

valaphee commented Dec 6, 2023

Description
When comparing the cube and water example for different back-ends on window (screenshots even of Vulkan seems to be fine which is weird). The colors are noticeable different.

The colors on Vulkan are darker compared to the screenshots and GL, DX12.

Repro steps
Run the cube or water example with WGPU_BACKEND=dx12 and with WGPU_BACKEND=vulkan

Expected vs observed behavior
Darker colors compared to the baseline and other back-ends window output.

Extra materials
DX12/OpenGL (AMD RX 6900 XT, Win 10/11, No HDR), Vulkan/OpenGL (AMD RX 6900 XT, Linux, No HDR) (expected?):
Screenshot 2023-12-14 163957
Vulkan (AMD RX 6900 XT, Win 11, No HDR):
Screenshot 2023-12-14 164014
Vulkan (Nvidia RTX 3070, Win 10, No HDR):
Unbenannt

wgpu-info.json

Platform

@valaphee valaphee changed the title Vulkan clear color uses a different color space Vulkan color space is different when rendering to swap chain Dec 7, 2023
@valaphee valaphee changed the title Vulkan color space is different when rendering to swap chain Vulkan color space is different when rendering to swap chain (sRGB) Dec 7, 2023
@valaphee
Copy link
Contributor Author

valaphee commented Dec 7, 2023

Might be related to #1646 and #3449, but probably not. As the format seems correct and it also looks right in RenderDoc, but Vulkan seems to do some gamma correction on its own.

@teoxoy teoxoy added type: bug Something isn't working api: vulkan Issues with Vulkan labels Dec 11, 2023
@teoxoy
Copy link
Member

teoxoy commented Dec 11, 2023

@cwfitzgerald any ideas why this is happening?

@cwfitzgerald
Copy link
Member

cwfitzgerald commented Dec 12, 2023

This looks like a tale of different primaries. When outputting SDR, what the output of compositing isn't sRGB. It's your monitor's color space.

What looks like it's happening is that DX12 is outputting sRGB color (by converting the sRGB into the monitor's color space), whereas vulkan is just yeeting the colors into the monitor and hoping for the best.

In short, I'm not sure there's much we can do about this.

@valaphee
Copy link
Contributor Author

valaphee commented Dec 14, 2023

Updated the images, I guess the color channel issue is not related to the linear/non-linear color space issue, but interestingly at least the color space is correct on Nvidia. (But I guess its most likely really a vendor issue)

On Linux Vulkan works perfectly fine.

What's the reason why DX12 is not the default on Windows?

@MarijnS95
Copy link
Contributor

What looks like it's happening is that DX12 is outputting sRGB color (by converting the sRGB into the monitor's color space), whereas vulkan is just yeeting the colors into the monitor and hoping for the best.

Theoretically both Vulkan and Dx12 should set/communicate to DWM what the color space of the output swapchain is, and DWM will appropriately convert it:

https://learn.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range

Then it's up to the SDR->HDR settings in Windows to map the brightness, which is expected to behave the same.

(In our renderer, which does not utilize WGPU, and we disable automatic sRGB conversion by using _UNORM textures, the color output in Vulkan and Dx12 is the same, on a 6800 XT)

Maybe useful to make sure that:

@MarijnS95
Copy link
Contributor

On Linux Vulkan works perfectly fine.

What compositor do you use on Linux that has HDR support?

@valaphee
Copy link
Contributor Author

valaphee commented Jan 1, 2024

X11, and Wayland, on two different machines, one with an AMD iGPU and the other one had a Nvidia dGPU and an Intel iGPU, and both worked fine with both compositors, no HDR enabled (nor supported).

The surface descriptor is also quite similar for both platforms.

@Elabajaba
Copy link
Contributor

Windows 11 (23H2) AMD 6800xt (23.11.2 drivers) no hdr I get identical colours with both vulkan and dx12. (also the background colour on the cube example is blue for me by default, not green?)

@valaphee
Copy link
Contributor Author

valaphee commented Jan 15, 2024

Forget to mention, the default is majority blue, but I changed it to pure green to compare the color values of the screenshots.

Tested with latest commit, but that's odd, I'm using the latest 23.12.1 drivers, HDR is disabled, also tried different display options. (color depth 8/10 bpc, limited/full rgb)

Would be interesting if someone with an RX 6900XT could test.

@valaphee
Copy link
Contributor Author

valaphee commented Jan 17, 2024

Did some further testing, because I was wondering why wgpu doesn't use HDR by default, and found that the first supported format is used by default.

And when using Rgba16Float with Vulkan the image looks like the expected one, same with DX12, but with OpenGL the color space is wrong.

@valaphee
Copy link
Contributor Author

valaphee commented Apr 3, 2024

Updated the issue because on Linux there is a similar problem involving OpenGL (non-es) where the ES variant results in the same image as Vulkan, but OpenGL (non-es) looks the same as Vulkan on Windows 11

@valaphee
Copy link
Contributor Author

valaphee commented Apr 24, 2024

pub fn map_vk_surface_formats(sf: vk::SurfaceFormatKHR) -> Option<wgt::TextureFormat> {
    use ash::vk::Format as F;
    use wgt::TextureFormat as Tf;
    // List we care about pulled from https://vulkan.gpuinfo.org/listsurfaceformats.php
    Some(match sf.color_space {
        vk::ColorSpaceKHR::SRGB_NONLINEAR => match sf.format {
            F::B8G8R8A8_UNORM => Tf::Bgra8Unorm,
            F::B8G8R8A8_SRGB => Tf::Bgra8UnormSrgb,
            F::R8G8B8A8_SNORM => Tf::Rgba8Snorm,
            F::R8G8B8A8_UNORM => Tf::Rgba8Unorm,
            F::R8G8B8A8_SRGB => Tf::Rgba8UnormSrgb,
            _ => return None,
        },
        vk::ColorSpaceKHR::EXTENDED_SRGB_LINEAR_EXT => match sf.format {
            F::R16G16B16A16_SFLOAT => Tf::Rgba16Float,
            F::R16G16B16A16_SNORM => Tf::Rgba16Snorm,
            F::R16G16B16A16_UNORM => Tf::Rgba16Unorm,
            F::A2B10G10R10_UNORM_PACK32 => Tf::Rgb10a2Unorm,
            _ => return None,
        },
        _ => return None,
    })
}

this is also not ideal, as A2B10G10R10_UNORM_PACK32 can be both, nonlinear and linear, and I guess this is also true for all other formats.

But this check is hardcoded

let color_space = if config.format == wgt::TextureFormat::Rgba16Float {
            // Enable wide color gamut mode
            // Vulkan swapchain for Android only supports DISPLAY_P3_NONLINEAR_EXT and EXTENDED_SRGB_LINEAR_EXT
            vk::ColorSpaceKHR::EXTENDED_SRGB_LINEAR_EXT
        } else {
            vk::ColorSpaceKHR::SRGB_NONLINEAR
        };

and doesn't match up with above

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: vulkan Issues with Vulkan type: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants