v3dv: limit software integer RT clamp to rgb10a2

We can use the HW integer clamp feature, which clamps automatically
to the render target type. This works for all integer formats but
rgb10a2, which has a 16-bit type.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c
index 821aff2..60865cc 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -1080,7 +1080,8 @@
 
    *rt_bpp = iview->internal_bpp;
    *rt_type = iview->internal_type;
-   *rt_clamp = V3D_RENDER_TARGET_CLAMP_NONE;
+   *rt_clamp =vk_format_is_int(iview->vk_format) ?
+      V3D_RENDER_TARGET_CLAMP_INT : V3D_RENDER_TARGET_CLAMP_NONE;
 }
 
 static void
diff --git a/src/broadcom/vulkan/v3dv_meta_copy.c b/src/broadcom/vulkan/v3dv_meta_copy.c
index b5c630f..65806b6 100644
--- a/src/broadcom/vulkan/v3dv_meta_copy.c
+++ b/src/broadcom/vulkan/v3dv_meta_copy.c
@@ -1942,6 +1942,20 @@
    return true;
 }
 
+static bool
+format_needs_software_int_clamp(VkFormat format)
+{
+   switch (format) {
+      case VK_FORMAT_A2R10G10B10_UINT_PACK32:
+      case VK_FORMAT_A2R10G10B10_SINT_PACK32:
+      case VK_FORMAT_A2B10G10R10_UINT_PACK32:
+      case VK_FORMAT_A2B10G10R10_SINT_PACK32:
+         return true;
+      default:
+         return false;
+   };
+}
+
 static void
 get_blit_pipeline_cache_key(VkImageAspectFlags aspect,
                            VkFormat dst_format,
@@ -1955,7 +1969,17 @@
    *p = dst_format;
    p++;
 
-   *p = vk_format_is_int(dst_format) ? src_format : 0;
+   /* Generally, when blitting from a larger format to a smaller format
+    * the hardware takes care of clamping the source to the RT range.
+    * Specifically, for integer formats, this is done by using
+    * V3D_RENDER_TARGET_CLAMP_INT in the render target setup, however, this
+    * clamps to the bit-size of the render type, and some formats, such as
+    * rgb10a2_uint have a 16-bit type, so it won't do what we need and we
+    * require to clamp in software. In these cases, we need to amend the blit
+    * shader with clamp code that depends on both the src and dst formats, so
+    * we need the src format to be part of the key.
+    */
+   *p = format_needs_software_int_clamp(dst_format) ? src_format : 0;
    p++;
 
    *p = aspect;
@@ -2266,11 +2290,13 @@
 
    /* For integer textures, if the bit-size of the destination is too small to
     * hold source value, Vulkan (CTS) expects the implementation to clamp to the
-    * maximum value the destination can hold, however, the hardware doesn't do
-    * this and instead it just takes the souce bits that fit into the
-    * destination. Fix that by clamping manually.
+    * maximum value the destination can hold. The hardware can clamp to the
+    * render target type, which usually matches the component bit-size, but
+    * there are some cases that won't match, such as rgb10a2, which has a 16-bit
+    * render target type, so in these cases we need to clamp manually.
     */
-   if (is_int_blit) {
+   if (format_needs_software_int_clamp(dst_format)) {
+      assert(is_int_blit);
       enum pipe_format src_pformat = vk_format_to_pipe_format(src_format);
       enum pipe_format dst_pformat = vk_format_to_pipe_format(dst_format);