amd/vpelib: FP16 non linear handling

[WHY]
FP16 with non-linear gamma is not a regular format. But to support
multi-pass with FP16 intermediate format, the support needs to be added.

Acked-by: Peyton Lee <peytolee@amd.com>
Signed-off-by: Navid Assadian <Navid.Assadian@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/42033>
This commit is contained in:
Assadian, Navid 2026-05-12 16:56:32 -04:00 committed by Marge Bot
parent bbf7875153
commit e64b5b24df
2 changed files with 42 additions and 30 deletions

View file

@ -2296,9 +2296,6 @@ bool vpe20_check_output_color_space(
if (cs == COLOR_SPACE_UNKNOWN || tf == TRANSFER_FUNC_UNKNOWN)
return false;
if (vpe_is_fp16(format) && tf != TRANSFER_FUNC_LINEAR)
return false;
if ((cs == COLOR_SPACE_CUSTOM) || (tf == TRANSFER_FUNC_CUSTOM))
return false;
@ -2765,6 +2762,12 @@ enum vpe_status vpe20_update_blnd_gamma(struct vpe_priv *vpe_priv,
if (lut3d_enabled) {
vpe_color_build_tm_cs(tm_params, &param->dst_surface, &tm_out_cs);
vpe_color_get_color_space_and_tf(&tm_out_cs, &cs, &tf);
// For HLG final output, use Linear TF to apply scaling without additional curve
if (output_ctx->tf == TRANSFER_FUNC_HLG) {
tf = TRANSFER_FUNC_LINEAR;
}
} else {
can_bypass = true;
}
@ -2802,14 +2805,14 @@ enum vpe_status vpe20_update_output_gamma(struct vpe_priv *vpe_priv,
enum vpe_status status = VPE_STATUS_OK;
struct fixed31_32 y_scale = vpe_fixpt_one;
if (vpe_is_fp16(param->dst_surface.format)) {
y_scale = vpe_fixpt_mul_int(y_scale, CCCS_NORM);
if ((vpe_is_fp16(param->dst_surface.format) == true) &&
(param->dst_surface.cs.tf == VPE_TF_G10)) {
y_scale = vpe_fixpt_mul_int(vpe_fixpt_one, CCCS_NORM);
}
if (!geometric_scaling && vpe_is_HDR(output_ctx->tf))
can_bypass = false;
else
if ((geometric_scaling == true) || (vpe_is_HDR(output_ctx->tf) == false)) {
can_bypass = true;
}
vpe_color_update_regamma_tf(
vpe_priv, output_ctx->tf, vpe_fixpt_one, y_scale, vpe_fixpt_zero, can_bypass, output_tf);

View file

@ -279,17 +279,25 @@ static bool color_update_input_cs(struct vpe_priv *vpe_priv, enum color_space in
static bool can_bypass_degamma(const struct stream_ctx *stream_ctx)
{
if (vpe_is_fp16(stream_ctx->stream.surface_info.format))
return true;
if ((stream_ctx->stream.tm_params.UID != 0) || (stream_ctx->stream.tm_params.enable_3dlut))
return true;
if (stream_ctx->geometric_scaling)
return true;
bool can_bypass = false;
// Linear FP16
if ((vpe_is_fp16(stream_ctx->stream.surface_info.format) == true) &&
(stream_ctx->stream.surface_info.cs.tf == VPE_TF_G10)) {
can_bypass = true;
}
// 3D LUT
if ((stream_ctx->stream.tm_params.UID != 0) || (stream_ctx->stream.tm_params.enable_3dlut)) {
can_bypass = true;
}
// First and intermediate passes of multi-pass VPE
if (stream_ctx->geometric_scaling) {
can_bypass = true;
}
if (stream_ctx->stream.surface_info.format == VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBE) {
return true;
can_bypass = true;
}
return false;
return can_bypass;
}
bool vpe_use_csc_adjust(const struct vpe_color_adjust *adjustments)
@ -1249,25 +1257,28 @@ enum vpe_status vpe_color_update_whitepoint(
const struct vpe_priv *vpe_priv, const struct vpe_build_param *param)
{
struct stream_ctx *stream = vpe_priv->stream_ctx;
const struct output_ctx *output_ctx = &vpe_priv->output_ctx;
const struct vpe_color_space *vpe_cs = &stream->stream.surface_info.cs;
bool output_isHDR = vpe_is_HDR(vpe_priv->output_ctx.tf);
bool input_isHDR = false;
bool is_yCbCr = false;
bool is_g24 = false;
bool is_fp16 = false;
struct stream_ctx *stream = vpe_priv->stream_ctx;
const struct output_ctx *output_ctx = &vpe_priv->output_ctx;
bool output_isHDR = vpe_is_HDR(vpe_priv->output_ctx.tf);
bool input_isHDR = false;
bool is_yCbCr = false;
bool is_g24 = false;
bool is_fp16_linear = false;
bool is_compound = stream->stream.lut_compound.enabled;
for (unsigned int stream_index = 0; stream_index < vpe_priv->num_streams; stream_index++) {
input_isHDR = vpe_is_HDR(stream->tf);
is_yCbCr = stream->is_yuv_input;
is_g24 = (vpe_cs->tf == VPE_TF_G24);
is_fp16 = vpe_is_fp16(stream->stream.surface_info.format);
is_g24 = (stream->stream.surface_info.cs.tf == VPE_TF_G24);
// Only FP16 G10 input has data in [0, CCCS_NORM] range
is_fp16_linear = (vpe_is_fp16(stream->stream.surface_info.format) &&
(stream->stream.surface_info.cs.tf == VPE_TF_G10));
if (is_compound) {
stream->white_point_gain = vpe_fixpt_one;
} else if (!input_isHDR && output_isHDR) {
int sdrWhiteLevel = (is_yCbCr || is_g24) ? SDR_VIDEO_WHITE_POINT : SDR_WHITE_POINT;
stream->white_point_gain = vpe_fixpt_from_fraction(sdrWhiteLevel, 10000);
} else if (input_isHDR && !output_isHDR) {
@ -1280,10 +1291,8 @@ enum vpe_status vpe_color_update_whitepoint(
stream->white_point_gain = vpe_fixpt_one;
}
if (is_fp16) {
stream->white_point_gain = vpe_fixpt_div_int(stream->white_point_gain, CCCS_NORM);
}
if (stream->stream.surface_info.format == VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBE) {
if ((is_fp16_linear == true) ||
(stream->stream.surface_info.format == VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBE)) {
stream->white_point_gain = vpe_fixpt_div_int(stream->white_point_gain, CCCS_NORM);
}