From 604fcdb1db36d8bad0ada101d17c2d45e7510017 Mon Sep 17 00:00:00 2001 From: llyyr Date: Mon, 6 Oct 2025 08:10:49 +0530 Subject: [PATCH] render/vulkan: clip negative values before applying transfer function Not all eotf or eotf inverse are well defined for values outside the intended domain, so just ignore it and clamp it away. An alternative solution would be to use sign preserving pow here (i.e. sign(x) * pow(abs(x), p)), however I'm not sure that makes sense or is defined anywhere. Negative values here are likely a result of colors being outside the gamut range, so clipping them to 0 is more correct than mirroring from 0. --- render/vulkan/shaders/output.frag | 3 +++ render/vulkan/shaders/texture.frag | 3 +++ 2 files changed, 6 insertions(+) diff --git a/render/vulkan/shaders/output.frag b/render/vulkan/shaders/output.frag index b9cfcaaa2..5b952fcff 100644 --- a/render/vulkan/shaders/output.frag +++ b/render/vulkan/shaders/output.frag @@ -72,6 +72,9 @@ void main() { rgb = mat3(data.matrix) * rgb; + if (OUTPUT_TRANSFORM != OUTPUT_TRANSFORM_IDENTITY) { + rgb = max(rgb, vec3(0)); + } if (OUTPUT_TRANSFORM == OUTPUT_TRANSFORM_LUT_3D) { // Apply 3D LUT vec3 pos = data.lut_3d_offset + rgb * data.lut_3d_scale; diff --git a/render/vulkan/shaders/texture.frag b/render/vulkan/shaders/texture.frag index b7b78b19a..57d2d049c 100644 --- a/render/vulkan/shaders/texture.frag +++ b/render/vulkan/shaders/texture.frag @@ -66,6 +66,9 @@ void main() { rgb = in_color.rgb / alpha; } + if (TEXTURE_TRANSFORM != TEXTURE_TRANSFORM_IDENTITY) { + rgb = max(rgb, vec3(0)); + } if (TEXTURE_TRANSFORM == TEXTURE_TRANSFORM_SRGB) { rgb = srgb_color_to_linear(rgb); } else if (TEXTURE_TRANSFORM == TEXTURE_TRANSFORM_ST2084_PQ) {