radv: fix color conversions for normalized uint/sint formats

Submitted by Samuel Pitoiset on March 5, 2019, 5:17 p.m.

Details

Message ID 20190305171713.17098-1-samuel.pitoiset@gmail.com
State Accepted
Commit e03e7c510f571a8867ab7a8604058c075c601a70
Headers show
Series "radv: fix color conversions for normalized uint/sint formats" ( rev: 1 ) in Mesa

Not browsing as part of any series.

Commit Message

Samuel Pitoiset March 5, 2019, 5:17 p.m.
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: 18.3 19.0 <mesa-stable@lists.freedesktop.org>
Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
---
 src/amd/vulkan/radv_formats.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/amd/vulkan/radv_formats.c b/src/amd/vulkan/radv_formats.c
index 0a3ff9ebbd9..9c61e769ebd 100644
--- a/src/amd/vulkan/radv_formats.c
+++ b/src/amd/vulkan/radv_formats.c
@@ -990,10 +990,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) {