diff options
author | Jeroen Bakker <jeroen@blender.org> | 2022-10-12 09:47:12 +0300 |
---|---|---|
committer | Philipp Oeser <info@graphics-engineer.com> | 2022-10-26 11:48:47 +0300 |
commit | 0386737097716870236d5e480f8ae1ec13e0b7a7 (patch) | |
tree | aa4b192ca1499d388415712468f41e6409738f71 | |
parent | f9c6e0c814b673c31be162e8dbd9ac7c1bc7c5d8 (diff) |
ImageEngine: Clamp image data to fit half float range.
When image data exceeds half float ranges values are set to +/-
infinity that could lead to artifacts later on in the pipeline.
Color management for example.
This patch adds a utility function `IMB_gpu_clamp_half_float`
that clamps full float values to fit within the range of
half floats.
This fixes T98575 and T101601.
-rw-r--r-- | source/blender/draw/engines/image/image_drawing_mode.hh | 2 | ||||
-rw-r--r-- | source/blender/imbuf/IMB_imbuf.h | 7 | ||||
-rw-r--r-- | source/blender/imbuf/intern/util_gpu.c | 16 |
3 files changed, 25 insertions, 0 deletions
diff --git a/source/blender/draw/engines/image/image_drawing_mode.hh b/source/blender/draw/engines/image/image_drawing_mode.hh index a1cd110e1d8..eb14ad6455a 100644 --- a/source/blender/draw/engines/image/image_drawing_mode.hh +++ b/source/blender/draw/engines/image/image_drawing_mode.hh @@ -335,6 +335,7 @@ template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD offset++; } } + IMB_gpu_clamp_half_float(&extracted_buffer); GPU_texture_update_sub(texture, GPU_DATA_FLOAT, @@ -391,6 +392,7 @@ template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD } BKE_image_release_ibuf(image, tile_buffer, lock); } + IMB_gpu_clamp_half_float(&texture_buffer); GPU_texture_update(info.texture, GPU_DATA_FLOAT, texture_buffer.rect_float); imb_freerectImbuf_all(&texture_buffer); } diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 99d931e7035..4e440bf3bdd 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -938,6 +938,13 @@ struct GPUTexture *IMB_create_gpu_texture(const char *name, bool use_high_bitdepth, bool use_premult); /** + * Ensures that values stored in the float rect can safely loaded into half float gpu textures. + * + * Does nothing when given image_buffer doesn't contain a float rect. + */ +void IMB_gpu_clamp_half_float(struct ImBuf *image_buffer); + +/** * The `ibuf` is only here to detect the storage type. The produced texture will have undefined * content. It will need to be populated by using #IMB_update_gpu_texture_sub(). */ diff --git a/source/blender/imbuf/intern/util_gpu.c b/source/blender/imbuf/intern/util_gpu.c index 5feb0ceb515..8afa0c4e079 100644 --- a/source/blender/imbuf/intern/util_gpu.c +++ b/source/blender/imbuf/intern/util_gpu.c @@ -290,3 +290,19 @@ GPUTexture *IMB_create_gpu_texture(const char *name, return tex; } + +void IMB_gpu_clamp_half_float(ImBuf *image_buffer) +{ + const float half_min = -65504; + const float half_max = 65504; + if (!image_buffer->rect_float) { + return; + } + + int rect_float_len = image_buffer->x * image_buffer->y * + (image_buffer->channels == 0 ? 4 : image_buffer->channels); + + for (int i = 0; i < rect_float_len; i++) { + image_buffer->rect_float[i] = clamp_f(image_buffer->rect_float[i], half_min, half_max); + } +} |