From f2aaa9ce00ffe7310bddcd5e884f34afb741f460 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Thu, 6 Nov 2025 07:23:53 +0000 Subject: [PATCH] dri,gallium: Add support for RGB[A]16_UNORM display formats. These are useful for displaying very high color precision images with more than 10 bpc color depth, and also more precision than what fp16 can do on a standard dynamic range (SDR) display, where fp16 for values in the unorm 0.0 - 1.0 range is about equivalent to at most ~11 bpc linear color depth. This is especially useful for and aimed at scientific applications, e.g., neuroscience and other bio-medical research cases. At least current generation AMD gpu's released during the last 10 years and supported by amdgpu-kms + atomic modesetting do allow for scanout of such 16 bpc framebuffers and of up to 12 bpc output to suitable HDMI or DisplayPort high precision displays. We gate the format behind a new driconf option 'allow_rgb16_configs', which defaults to true, but allows to disable the formats if any issues should arise. Most regular applications won't need the high display precision of these new 16 bpc 64 bpp formats which have higher memory and bandwidth requirements, and therefore a potential undesired performance impact for regular apps. Followup per-platform enablement commits will use the EGL_EXT_config_select_group extension to put these 16 bpc unorm formats into a lower priority config select group 1, so they don't get preferably chosen by default by eglChooseConfig(), but must be explicitely requested by client applications which really need the high color precision of these 64 bpp formats and are happy to pay the potential performance impact. Thanks to Adam Jackson for pointing me to the EGL_EXT_config_select_group extension. If the format would be put into the default config select group 0, a simple EGL eglChooseConfig() call would end up choosing these formats, which is not what such regular apps would want. Tested to not cause any change on native X11/EGL and X11/GLX, which only supports at most 30 bpc / 32 bpp formats. Followup commits will enable these formats for the EGL/Wayland backend, and on the EGL/DRM backend. Signed-off-by: Mario Kleiner Reviewed-by: Adam Jackson Part-of: --- .../auxiliary/pipe-loader/driinfo_gallium.h | 1 + src/gallium/frontends/dri/dri_screen.c | 14 ++++++++++++++ src/mesa/state_tracker/st_manager.c | 1 + src/util/driconf.h | 4 ++++ 4 files changed, 20 insertions(+) diff --git a/src/gallium/auxiliary/pipe-loader/driinfo_gallium.h b/src/gallium/auxiliary/pipe-loader/driinfo_gallium.h index 561a51d94c1..7c2c39a20af 100644 --- a/src/gallium/auxiliary/pipe-loader/driinfo_gallium.h +++ b/src/gallium/auxiliary/pipe-loader/driinfo_gallium.h @@ -69,5 +69,6 @@ DRI_CONF_SECTION_MISCELLANEOUS DRI_CONF_VS_POSITION_ALWAYS_INVARIANT(false) DRI_CONF_VS_POSITION_ALWAYS_PRECISE(false) DRI_CONF_ALLOW_RGB10_CONFIGS(true) + DRI_CONF_ALLOW_RGB16_CONFIGS(true) DRI_CONF_FORCE_INTEGER_TEX_NEAREST(false) DRI_CONF_SECTION_END diff --git a/src/gallium/frontends/dri/dri_screen.c b/src/gallium/frontends/dri/dri_screen.c index fed8c6b5ac1..d158b0002c8 100644 --- a/src/gallium/frontends/dri/dri_screen.c +++ b/src/gallium/frontends/dri/dri_screen.c @@ -324,6 +324,8 @@ dri_fill_in_modes(struct dri_screen *screen) PIPE_FORMAT_B5G6R5_UNORM, PIPE_FORMAT_R16G16B16A16_FLOAT, PIPE_FORMAT_R16G16B16X16_FLOAT, + PIPE_FORMAT_R16G16B16A16_UNORM, + PIPE_FORMAT_R16G16B16X16_UNORM, PIPE_FORMAT_RGBA8888_UNORM, PIPE_FORMAT_RGBX8888_UNORM, PIPE_FORMAT_RGBA8888_SRGB, @@ -341,6 +343,7 @@ dri_fill_in_modes(struct dri_screen *screen) bool mixed_color_depth; bool allow_rgba_ordering; bool allow_rgb10; + bool allow_rgb16; bool allow_fp16; static const bool db_modes[] = { false, true }; @@ -350,6 +353,7 @@ dri_fill_in_modes(struct dri_screen *screen) allow_rgba_ordering = dri_loader_get_cap(screen, DRI_LOADER_CAP_RGBA_ORDERING); allow_rgb10 = driQueryOptionb(&screen->dev->option_cache, "allow_rgb10_configs"); + allow_rgb16 = driQueryOptionb(&screen->dev->option_cache, "allow_rgb16_configs"); allow_fp16 = dri_loader_get_cap(screen, DRI_LOADER_CAP_FP16); #define HAS_ZS(fmt) \ @@ -405,6 +409,16 @@ dri_fill_in_modes(struct dri_screen *screen) UTIL_FORMAT_COLORSPACE_RGB, 2) == 10) continue; + /* Block RGB[A]16_UNORM formats, if forbidden by config */ + if (!allow_rgb16 && !util_format_is_float(pipe_formats[f]) && + util_format_get_component_bits(pipe_formats[f], + UTIL_FORMAT_COLORSPACE_RGB, 0) == 16 && + util_format_get_component_bits(pipe_formats[f], + UTIL_FORMAT_COLORSPACE_RGB, 1) == 16 && + util_format_get_component_bits(pipe_formats[f], + UTIL_FORMAT_COLORSPACE_RGB, 2) == 16) + continue; + if (!allow_fp16 && util_format_is_float(pipe_formats[f])) continue; diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c index 8180788d249..71f2ae2c1de 100644 --- a/src/mesa/state_tracker/st_manager.c +++ b/src/mesa/state_tracker/st_manager.c @@ -416,6 +416,7 @@ st_new_renderbuffer_fb(enum pipe_format format, unsigned samples, bool sw) case PIPE_FORMAT_R16G16B16A16_UNORM: rb->InternalFormat = GL_RGBA16; break; + case PIPE_FORMAT_R16G16B16X16_UNORM: case PIPE_FORMAT_R16G16B16_UNORM: rb->InternalFormat = GL_RGB16; break; diff --git a/src/util/driconf.h b/src/util/driconf.h index e42ae4d455f..22e25be2dc3 100644 --- a/src/util/driconf.h +++ b/src/util/driconf.h @@ -515,6 +515,10 @@ DRI_CONF_OPT_B(allow_rgb10_configs, def, \ "Allow exposure of visuals and fbconfigs with rgb10a2 formats") +#define DRI_CONF_ALLOW_RGB16_CONFIGS(def) \ + DRI_CONF_OPT_B(allow_rgb16_configs, def, \ + "Allow exposure of visuals and fbconfigs with rgb16 and rgba16 formats") + #define DRI_CONF_ALLOW_RGB565_CONFIGS(def) \ DRI_CONF_OPT_B(allow_rgb565_configs, def, \ "Allow exposure of visuals and fbconfigs with rgb565 formats")