From 5e79c41752c2738632c3c6fc9f748277b0bd5beb Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 22 Oct 2026 12:56:20 +0900 Subject: [PATCH] renderer: add pl_render_params.high_bit_depth_fbos find_fbo_format() tops out at 16-bit floating point FBOs, so any render that goes through an intermediate - which a planar target always does - holds no more than half float precision, whatever the source and target formats are. A 32-bit float source rendered into gbrpf32 planes comes out as half floats in a float container, and 12 and 16-bit integer targets lose codes near the top of the range (a half has 11 bits of mantissa). The new parameter makes find_fbo_format() try 32-bit float formats first, falling back to the usual list when the GPU has none. It is off by default: it doubles the memory traffic of every intermediate pass, which a display render has no use for. --- meson.build | 1 + src/include/libplacebo/renderer.h | 8 ++++++++ src/options.c | 1 + src/renderer.c | 6 ++++++ 4 files changed, 16 insertions(+) diff --git a/meson.build b/meson.build index fcfae38e..afaf06da 100644 --- a/meson.build +++ b/meson.build @@ -12,6 +12,7 @@ project('libplacebo', ['c', 'cpp'], 7, # API version { + '378': 'add pl_render_params.high_bit_depth_fbos', '377': 'VK_KHR_internally_synchronized_queues is used only on request', '376': 'add pl_color_repr_decode_ex, pl_color_decode_args.primaries and pl_shader_encode_color_ex', '375': 'change pl_source_frame and pl_frame_mix members from float to double', diff --git a/src/include/libplacebo/renderer.h b/src/include/libplacebo/renderer.h index ff0d6a8f..58a08040 100644 --- a/src/include/libplacebo/renderer.h +++ b/src/include/libplacebo/renderer.h @@ -340,6 +340,14 @@ struct pl_render_params { // disabling linear scaling and sigmoidization. bool force_low_bit_depth_fbos; + // Prefer 32-bit floating point FBOs over the default 16-bit ones, falling + // back to those if the GPU has no suitable 32-bit format. Doubles the + // memory traffic of every intermediate pass; meant for renders where the + // intermediate precision matters, e.g. writing 32-bit float or 16-bit + // integer planar targets losslessly. Ignored if + // `force_low_bit_depth_fbos` is set. + bool high_bit_depth_fbos; + // If this is true, all shaders will be generated as "dynamic" shaders, // with any compile-time constants being replaced by runtime-adjustable // values. This is generally a performance loss, but has the advantage of diff --git a/src/options.c b/src/options.c index bffa940c..543a89da 100644 --- a/src/options.c +++ b/src/options.c @@ -1164,6 +1164,7 @@ const struct pl_opt_t pl_option_list[] = { OPT_BOOL("disable_dither_gamma_correction", "Disable gamma-correct dithering", params.disable_dither_gamma_correction), OPT_BOOL("disable_fbos", "Disable FBOs", params.disable_fbos), OPT_BOOL("force_low_bit_depth_fbos", "Force 8-bit FBOs", params.force_low_bit_depth_fbos), + OPT_BOOL("high_bit_depth_fbos", "Prefer 32-bit float FBOs", params.high_bit_depth_fbos), OPT_BOOL("dynamic_constants", "Dynamic constants", params.dynamic_constants), {0}, }; diff --git a/src/renderer.c b/src/renderer.c index 809b2eea..36af5b35 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -398,6 +398,10 @@ static void find_fbo_format(struct pass_state *pass) int depth; enum pl_fmt_caps caps; } configs[] = { + // 32-bit floating point formats, only if requested + {PL_FMT_FLOAT, 32, PL_FMT_CAP_LINEAR}, + {PL_FMT_FLOAT, 32, PL_FMT_CAP_SAMPLEABLE}, + // Prefer floating point formats first {PL_FMT_FLOAT, 16, PL_FMT_CAP_LINEAR}, {PL_FMT_FLOAT, 16, PL_FMT_CAP_SAMPLEABLE}, @@ -417,6 +421,8 @@ static void find_fbo_format(struct pass_state *pass) for (int i = 0; i < PL_ARRAY_SIZE(configs); i++) { if (params->force_low_bit_depth_fbos && configs[i].depth > 8) continue; + if (!params->high_bit_depth_fbos && configs[i].depth > 16) + continue; fmt = pl_find_fmt(rr->gpu, configs[i].type, 4, configs[i].depth, 0, PL_FMT_CAP_RENDERABLE | configs[i].caps); -- 2.55.0