[hud] Support HDR color spaces

Blending is broken if we need to do encoding in the shader, but we
cannot do much about that without changing the rendering process,
so this will have to do for now.
This commit is contained in:
Philip Rebohle 2023-01-16 13:31:02 +01:00 committed by Joshie
parent 0e503ce795
commit 599357721a
4 changed files with 83 additions and 27 deletions

View File

@ -79,7 +79,10 @@ namespace dxvk::hud {
const Rc<DxvkContext>& ctx,
VkSurfaceFormatKHR surfaceFormat,
VkExtent2D surfaceSize) {
bool isSrgb = lookupFormatInfo(surfaceFormat.format)->flags.test(DxvkFormatFlag::ColorSpaceSrgb);
VkColorSpaceKHR colorSpace = surfaceFormat.colorSpace;
if (lookupFormatInfo(surfaceFormat.format)->flags.test(DxvkFormatFlag::ColorSpaceSrgb))
colorSpace = VK_COLOR_SPACE_PASS_THROUGH_EXT;
VkViewport viewport;
viewport.x = 0.0f;
@ -97,7 +100,7 @@ namespace dxvk::hud {
ctx->setRasterizerState(m_rsState);
ctx->setBlendMode(0, m_blendMode);
ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, isSrgb);
ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, colorSpace);
m_renderer.beginFrame(ctx, surfaceSize, m_scale);
}

View File

@ -0,0 +1,68 @@
#define VK_COLOR_SPACE_SRGB_NONLINEAR_KHR (0)
#define VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT (1000104002)
#define VK_COLOR_SPACE_HDR10_ST2084_EXT (1000104008)
#define VK_COLOR_SPACE_PASS_THROUGH_EXT (1000104013)
#define HUD_NITS (203.0f)
const mat3 rec709_to_xyz = mat3(
0.4123908, 0.2126390, 0.0193308,
0.3575843, 0.7151687, 0.1191948,
0.1804808, 0.0721923, 0.9505322);
const mat3 xyz_to_rec2020 = mat3(
1.7166512, -0.6666844, 0.0176399,
-0.3556708, 1.6164812, -0.0427706,
-0.2533663, 0.0157685, 0.9421031);
const mat3 rec709_to_rec2020 = xyz_to_rec2020 * rec709_to_xyz;
// Spec constants must always default to
// zero for DXVK to handle them properly
layout(constant_id = 0) const uint hud_color_space = 0;
vec3 encodeSrgb(vec3 linear) {
bvec3 isLo = lessThanEqual(linear, vec3(0.0031308f));
vec3 loPart = linear * 12.92f;
vec3 hiPart = pow(linear, vec3(5.0f / 12.0f)) * 1.055f - 0.055f;
return mix(hiPart, loPart, isLo);
}
vec3 encodePq(vec3 nits) {
const float c1 = 0.8359375f;
const float c2 = 18.8515625f;
const float c3 = 18.6875f;
const float m1 = 0.1593017578125f;
const float m2 = 78.84375f;
vec3 y = clamp(nits / 10000.0f, vec3(0.0f), vec3(1.0f));
vec3 y_m1 = pow(y, vec3(m1));
vec3 num = c1 + c2 * y_m1;
vec3 den = 1.0f + c3 * y_m1;
return pow(num / den, vec3(m2));
}
vec3 encodeScRgb(vec3 nits) {
return nits / 80.0f;
}
vec3 encodeOutput(vec3 linear) {
switch (hud_color_space) {
default:
return linear;
case VK_COLOR_SPACE_SRGB_NONLINEAR_KHR:
return encodeSrgb(linear);
case VK_COLOR_SPACE_HDR10_ST2084_EXT: {
vec3 rec2020 = rec709_to_rec2020 * linear;
return encodePq(rec2020 * HUD_NITS);
}
case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT:
return encodeScRgb(linear * HUD_NITS);
}
}

View File

@ -1,6 +1,8 @@
#version 450
layout(constant_id = 0) const bool srgbSwapchain = false;
#extension GL_GOOGLE_include_directive : require
#include "hud_frag_common.glsl"
layout(location = 0) in vec2 v_coord;
layout(location = 0) out vec4 o_color;
@ -24,14 +26,6 @@ uniform push_data_t {
vec2 scale;
};
vec3 linearToSrgb(vec3 color) {
bvec3 isLo = lessThanEqual(color, vec3(0.0031308f));
vec3 loPart = color * 12.92f;
vec3 hiPart = pow(color, vec3(5.0f / 12.0f)) * 1.055f - 0.055f;
return mix(hiPart, loPart, isLo);
}
void main() {
float cx = v_coord.x * float(count);
float fx = fract(cx);
@ -53,9 +47,7 @@ void main() {
o_color = mix(
unpackUnorm4x8(p0.color),
unpackUnorm4x8(p1.color), fx);
if (!srgbSwapchain)
o_color.rgb = linearToSrgb(o_color.rgb);
o_color *= alpha;
}
o_color.rgb = encodeOutput(o_color.rgb);
}

View File

@ -1,6 +1,8 @@
#version 450
layout(constant_id = 0) const bool srgbSwapchain = false;
#extension GL_GOOGLE_include_directive : require
#include "hud_frag_common.glsl"
layout(binding = 2) uniform sampler2D s_font;
@ -9,14 +11,6 @@ layout(location = 1) in vec4 v_color;
layout(location = 0) out vec4 o_color;
vec3 linearToSrgb(vec3 color) {
bvec3 isLo = lessThanEqual(color, vec3(0.0031308f));
vec3 loPart = color * 12.92f;
vec3 hiPart = pow(color, vec3(5.0f / 12.0f)) * 1.055f - 0.055f;
return mix(hiPart, loPart, isLo);
}
float sampleAlpha(float alpha_bias, float dist_range) {
float value = textureLod(s_font, v_texcoord, 0).r + alpha_bias - 0.5f;
float dist = value * dot(vec2(dist_range, dist_range), 1.0f / fwidth(v_texcoord.xy));
@ -34,6 +28,5 @@ void main() {
o_color.a = r_alpha_shadow * v_color.a;
o_color.rgb *= o_color.a;
if (!srgbSwapchain)
o_color.rgb = linearToSrgb(o_color.rgb);
o_color.rgb = encodeOutput(o_color.rgb);
}