radv: fix color conversions for normalized uint/sint formats
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Tue, 5 Mar 2019 17:17:13 +0000 (18:17 +0100)
committerSamuel Pitoiset <samuel.pitoiset@gmail.com>
Thu, 2 May 2019 07:24:05 +0000 (09:24 +0200)
The hardware actually rounds before conversion. This now matches
what values are used when performing fast clears vs slow clears.

This fixes a rendering issue with Far Cry 3&4. This also fixes
a bunch of CTS tests that use a 8-bit UNORM format (only when
the 512*512 image size hint is manually disabled).

Cc: "19.0" "19.1" <mesa-stable@lists.freedesktop.org>
Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
src/amd/vulkan/radv_formats.c

index bee1c57e610fe4096b7db1b241e74325cf5dd30f..5af172c8e7fe31e994c4b7a64e0b5b21916b888a 100644 (file)
@@ -1032,10 +1032,22 @@ bool radv_format_pack_clear_color(VkFormat format,
                                assert(channel->size == 8);
 
                                v = util_format_linear_float_to_srgb_8unorm(value->float32[c]);
-                       } else if (channel->type == VK_FORMAT_TYPE_UNSIGNED) {
-                               v = MAX2(MIN2(value->float32[c], 1.0f), 0.0f) * ((1ULL << channel->size) - 1);
-                       } else  {
-                               v = MAX2(MIN2(value->float32[c], 1.0f), -1.0f) * ((1ULL << (channel->size - 1)) - 1);
+                       } else {
+                               float f = MIN2(value->float32[c], 1.0f);
+
+                               if (channel->type == VK_FORMAT_TYPE_UNSIGNED) {
+                                       f = MAX2(f, 0.0f) * ((1ULL << channel->size) - 1);
+                               } else {
+                                       f = MAX2(f, -1.0f) * ((1ULL << (channel->size - 1)) - 1);
+                               }
+
+                               /* The hardware rounds before conversion. */
+                               if (f > 0)
+                                       f += 0.5f;
+                               else
+                                       f -= 0.5f;
+
+                               v = (uint64_t)f;
                        }
                } else if (channel->type == VK_FORMAT_TYPE_FLOAT) {
                        if (channel->size == 32) {