From 5b805dda00fa25b48fde4060caf2d8ace3eaf6bd Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Sat, 31 Dec 2022 10:39:38 +0000 Subject: [PATCH] rendervulkan: Framework for configurable SDR on HDR content brightness --- src/rendervulkan.cpp | 17 +++++++++++++++++ src/shaders/blit_push_data.h | 13 +++++++++++++ src/shaders/colorimetry.h | 14 +++++++++----- src/shaders/cs_composite_blit.comp | 10 +--------- src/shaders/cs_composite_blur.comp | 10 +--------- src/shaders/cs_composite_blur_cond.comp | 11 ++--------- src/shaders/cs_composite_rcas.comp | 4 ++++ src/shaders/cs_gaussian_blur_horizontal.comp | 4 ++++ src/shaders/cs_rgb_to_nv12.comp | 2 ++ src/shaders/heatmap.h | 6 ++++-- 10 files changed, 57 insertions(+), 34 deletions(-) create mode 100644 src/shaders/blit_push_data.h diff --git a/src/rendervulkan.cpp b/src/rendervulkan.cpp index f2a0f5d..220a98a 100644 --- a/src/rendervulkan.cpp +++ b/src/rendervulkan.cpp @@ -3085,6 +3085,9 @@ std::shared_ptr vulkan_acquire_screenshot_texture(uint32_t width return nullptr; } +float g_flLinearToNits = 400.0f; +float g_flNitsToLinear = 1.0f / 100.0f; + struct BlitPushData_t { vec2_t scale[k_nMaxLayers]; @@ -3094,6 +3097,9 @@ struct BlitPushData_t uint32_t frameId; uint32_t blurRadius; + float linearToNits; + float nitsToLinear; + explicit BlitPushData_t(const struct FrameInfo_t *frameInfo) { for (int i = 0; i < frameInfo->layerCount; i++) { @@ -3105,6 +3111,9 @@ struct BlitPushData_t borderMask = frameInfo->borderMask(); frameId = s_frameId++; blurRadius = frameInfo->blurRadius ? ( frameInfo->blurRadius * 2 ) - 1 : 0; + + linearToNits = g_flLinearToNits; + nitsToLinear = g_flNitsToLinear; } explicit BlitPushData_t(float blit_scale) { @@ -3113,6 +3122,9 @@ struct BlitPushData_t opacity[0] = 1.0f; borderMask = 0; frameId = s_frameId; + + linearToNits = g_flLinearToNits; + nitsToLinear = g_flNitsToLinear; } }; @@ -3170,6 +3182,9 @@ struct RcasPushData_t uint32_t u_frameId; uint32_t u_c1; + float linearToNits; + float nitsToLinear; + RcasPushData_t(const struct FrameInfo_t *frameInfo, float sharpness) { uvec4_t tmp; @@ -3180,6 +3195,8 @@ struct RcasPushData_t u_borderMask = frameInfo->borderMask() >> 1u; u_frameId = s_frameId++; u_c1 = tmp.x; + linearToNits = g_flLinearToNits; + nitsToLinear = g_flNitsToLinear; for (uint32_t i = 1; i < k_nMaxLayers; i++) { u_scale[i - 1] = frameInfo->layers[i].scale; diff --git a/src/shaders/blit_push_data.h b/src/shaders/blit_push_data.h new file mode 100644 index 0000000..2a60ac4 --- /dev/null +++ b/src/shaders/blit_push_data.h @@ -0,0 +1,13 @@ +layout(push_constant) +uniform layers_t { + vec2 u_scale[VKR_MAX_LAYERS]; + vec2 u_offset[VKR_MAX_LAYERS]; + float u_opacity[VKR_MAX_LAYERS]; + uint u_borderMask; + uint u_frameId; + uint u_blur_radius; + + // hdr + float u_linearToNits; // sdr -> hdr + float u_nitsToLinear; // hdr -> sdr +}; diff --git a/src/shaders/colorimetry.h b/src/shaders/colorimetry.h index 48c06cd..6635803 100644 --- a/src/shaders/colorimetry.h +++ b/src/shaders/colorimetry.h @@ -61,16 +61,20 @@ vec3 pqToNits(vec3 pq) { return 10000.0 * pow(num / den, vec3(oo_m1)); } -// pq -> nits -> linear (nits / 80) -const float c_nitsToLinearLightScale = 80.0f; +// This is apparently defined at 80 nits... +// May want to take liberties with this when displaying +// on SDR though... 100 may be a better fit for most content +// to match typical sRGB mastering. const float c_scRGBLightScale = 80.0f; + +// nits -> linear (nits / scale) vec3 nitsToLinear(vec3 nits) { - // This is typical, but we might want to make this customizable. - return nits / c_nitsToLinearLightScale; + return nits * u_nitsToLinear; } +// linear -> nits (linear * scale) vec3 linearToNits(vec3 linear) { - return linear * c_nitsToLinearLightScale; + return linear * u_linearToNits; } ///////////////////////////// diff --git a/src/shaders/cs_composite_blit.comp b/src/shaders/cs_composite_blit.comp index 8a9d7c0..bb4498f 100644 --- a/src/shaders/cs_composite_blit.comp +++ b/src/shaders/cs_composite_blit.comp @@ -9,15 +9,7 @@ layout( local_size_y = 8, local_size_z = 1) in; -layout(push_constant) -uniform layers_t { - vec2 u_scale[VKR_MAX_LAYERS]; - vec2 u_offset[VKR_MAX_LAYERS]; - float u_opacity[VKR_MAX_LAYERS]; - uint u_borderMask; - uint u_frameId; -}; - +#include "blit_push_data.h" #include "composite.h" vec4 sampleLayer(uint layerIdx, vec2 uv) { diff --git a/src/shaders/cs_composite_blur.comp b/src/shaders/cs_composite_blur.comp index b769dfe..28f699f 100644 --- a/src/shaders/cs_composite_blur.comp +++ b/src/shaders/cs_composite_blur.comp @@ -9,15 +9,7 @@ layout( local_size_y = 8, local_size_z = 1) in; -layout(push_constant) -uniform layers_t { - vec2 u_scale[VKR_MAX_LAYERS]; - vec2 u_offset[VKR_MAX_LAYERS]; - float u_opacity[VKR_MAX_LAYERS]; - uint u_borderMask; - uint u_frameId; - uint u_blur_radius; -}; +#include "blit_push_data.h" #define BLUR_DONT_SCALE 1 #include "composite.h" diff --git a/src/shaders/cs_composite_blur_cond.comp b/src/shaders/cs_composite_blur_cond.comp index 4052edd..b571faf 100644 --- a/src/shaders/cs_composite_blur_cond.comp +++ b/src/shaders/cs_composite_blur_cond.comp @@ -9,15 +9,8 @@ layout( local_size_y = 8, local_size_z = 1) in; -layout(push_constant) -uniform layers_t { - vec2 u_scale[VKR_MAX_LAYERS]; - vec2 u_offset[VKR_MAX_LAYERS]; - float u_opacity[VKR_MAX_LAYERS]; - uint u_borderMask; - uint u_frameId; - uint u_blur_radius; -}; +#include "blit_push_data.h" + #define BLUR_DONT_SCALE 1 #include "composite.h" #include "blur.h" diff --git a/src/shaders/cs_composite_rcas.comp b/src/shaders/cs_composite_rcas.comp index d2c13e8..9c2fe60 100644 --- a/src/shaders/cs_composite_rcas.comp +++ b/src/shaders/cs_composite_rcas.comp @@ -18,6 +18,10 @@ uniform layers_t { uint u_borderMask; uint u_frameId; uint u_c1; + + // hdr + float u_linearToNits; + float u_nitsToLinear; }; #include "composite.h" diff --git a/src/shaders/cs_gaussian_blur_horizontal.comp b/src/shaders/cs_gaussian_blur_horizontal.comp index cb2c3c6..58c1da7 100644 --- a/src/shaders/cs_gaussian_blur_horizontal.comp +++ b/src/shaders/cs_gaussian_blur_horizontal.comp @@ -17,6 +17,10 @@ uniform layers_t { uint u_borderMask; uint u_frameId; uint u_blur_radius; + + // hdr + float u_linearToNits; + float u_nitsToLinear; }; #include "composite.h" diff --git a/src/shaders/cs_rgb_to_nv12.comp b/src/shaders/cs_rgb_to_nv12.comp index 25a68ce..00bc98d 100644 --- a/src/shaders/cs_rgb_to_nv12.comp +++ b/src/shaders/cs_rgb_to_nv12.comp @@ -15,6 +15,8 @@ layout( // UVUVUVUVUVUVUVU... const uint u_frameId = 0; +const float u_linearToNits = 400.0f; +const float u_nitsToLinear = 1.0f / 100.0f; layout(push_constant) uniform layers_t { diff --git a/src/shaders/heatmap.h b/src/shaders/heatmap.h index f9d43c4..8081540 100644 --- a/src/shaders/heatmap.h +++ b/src/shaders/heatmap.h @@ -134,8 +134,10 @@ vec3 hdr_heatmap_lilium_impl(float nits) { vec3 hdr_heatmap(vec3 inputColor, bool in_2020, bool in_nits, bool out_nits) { vec3 xyz; + // If the input is SDR, then just multiply by 100 (typical sRGB mastering) + // don't multiply by our typical SDR scale. if (!in_nits) - inputColor *= c_nitsToLinearLightScale; + inputColor *= 100.0f; if (in_2020) xyz = inputColor * rec2020_to_xyz; @@ -152,7 +154,7 @@ vec3 hdr_heatmap(vec3 inputColor, bool in_2020, bool in_nits, bool out_nits) { outputColor = convert_primaries(outputColor, rec709_to_xyz, xyz_to_rec2020); if (out_nits) - outputColor *= c_nitsToLinearLightScale; + outputColor *= u_linearToNits; return outputColor; }