Mesa (main): llvmpipe: fix FB fetch with non 32-bit render target formats

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Nov 17 04:37:25 UTC 2021


Module: Mesa
Branch: main
Commit: ea6eeb70e67dd1ac2c6e232acd71492f5e8fd207
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=ea6eeb70e67dd1ac2c6e232acd71492f5e8fd207

Author: Pavel Asyutchenko <sventeam at yandex.ru>
Date:   Thu Oct  7 21:39:00 2021 +0300

llvmpipe: fix FB fetch with non 32-bit render target formats

Use lp_build_fetch_rgba_soa instead of lp_build_unpack_rgba_soa.
This one was failing most of deqp *framebuffer_fetch* tests.

Signed-off-by: Pavel Asyutchenko <sventeam at yandex.ru>
Reviewed-by: Dave Airlie <airlied at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13252>

---

 src/gallium/drivers/llvmpipe/lp_state_fs.c | 74 +++++++++++++-----------------
 1 file changed, 31 insertions(+), 43 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index 7a01528e36a..f7f89ca2ed9 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -467,7 +467,6 @@ static void fs_fb_fetch(const struct lp_build_fs_iface *iface,
    LLVMValueRef color_ptr = LLVMBuildLoad(builder, LLVMBuildGEP(builder, fs_iface->color_ptr_ptr, &index, 1, ""), "");
    LLVMValueRef stride = LLVMBuildLoad(builder, LLVMBuildGEP(builder, fs_iface->color_stride_ptr, &index, 1, ""), "");
 
-   LLVMValueRef dst[4 * 4];
    enum pipe_format cbuf_format = key->cbuf_format[cbuf];
    const struct util_format_description* out_format_desc = util_format_description(cbuf_format);
    if (out_format_desc->format == PIPE_FORMAT_NONE) {
@@ -475,46 +474,10 @@ static void fs_fb_fetch(const struct lp_build_fs_iface *iface,
       return;
    }
 
-   struct lp_type dst_type;
    unsigned block_size = bld->type.length;
    unsigned block_height = key->resource_1d ? 1 : 2;
    unsigned block_width = block_size / block_height;
 
-   lp_mem_type_from_format_desc(out_format_desc, &dst_type);
-
-   struct lp_type blend_type;
-   memset(&blend_type, 0, sizeof blend_type);
-   blend_type.floating = FALSE; /* values are integers */
-   blend_type.sign = FALSE;     /* values are unsigned */
-   blend_type.norm = TRUE;      /* values are in [0,1] or [-1,1] */
-   blend_type.width = 8;        /* 8-bit ubyte values */
-   blend_type.length = 16;      /* 16 elements per vector */
-
-   uint32_t dst_alignment;
-   /*
-    * Compute the alignment of the destination pointer in bytes
-    * We fetch 1-4 pixels, if the format has pot alignment then those fetches
-    * are always aligned by MIN2(16, fetch_width) except for buffers (not
-    * 1d tex but can't distinguish here) so need to stick with per-pixel
-    * alignment in this case.
-    */
-   if (key->resource_1d) {
-      dst_alignment = (out_format_desc->block.bits + 7)/(out_format_desc->block.width * 8);
-   }
-   else {
-      dst_alignment = dst_type.length * dst_type.width / 8;
-   }
-   /* Force power-of-two alignment by extracting only the least-significant-bit */
-   dst_alignment = 1 << (ffs(dst_alignment) - 1);
-   /*
-    * Resource base and stride pointers are aligned to 16 bytes, so that's
-    * the maximum alignment we can guarantee
-    */
-   dst_alignment = MIN2(16, dst_alignment);
-
-   LLVMTypeRef blend_vec_type = lp_build_vec_type(gallivm, blend_type);
-   color_ptr = LLVMBuildBitCast(builder, color_ptr, LLVMPointerType(blend_vec_type, 0), "");
-
    if (key->multisample) {
       LLVMValueRef sample_stride = LLVMBuildLoad(builder,
                                                  LLVMBuildGEP(builder, fs_iface->color_sample_stride_ptr,
@@ -536,12 +499,36 @@ static void fs_fb_fetch(const struct lp_build_fs_iface *iface,
       }
       y_offset = LLVMBuildMul(builder, counter, lp_build_const_int32(gallivm, 2), "");
    }
-   load_unswizzled_block(gallivm, color_ptr, stride, block_width, block_height, dst, dst_type, block_size, dst_alignment, x_offset, y_offset, true);
 
+   LLVMValueRef offsets[4 * 4];
    for (unsigned i = 0; i < block_size; i++) {
-      dst[i] = LLVMBuildBitCast(builder, dst[i], LLVMInt32TypeInContext(gallivm->context), "");
+      unsigned x = i % block_width;
+      unsigned y = i / block_width;
+
+      if (block_size == 8) {
+         /* remap the raw slots into the fragment shader execution mode. */
+         /* this math took me way too long to work out, I'm sure it's overkill. */
+         x = (i & 1) + ((i >> 2) << 1);
+         if (!key->resource_1d)
+            y = (i & 2) >> 1;
+      }
+
+      LLVMValueRef x_val;
+      if (x_offset) {
+         x_val = LLVMBuildAdd(builder, lp_build_const_int32(gallivm, x), x_offset, "");
+         x_val = LLVMBuildMul(builder, x_val, lp_build_const_int32(gallivm, out_format_desc->block.bits / 8), "");
+      } else {
+         x_val = lp_build_const_int32(gallivm, x * (out_format_desc->block.bits / 8));
+      }
+
+      LLVMValueRef y_val = lp_build_const_int32(gallivm, y);
+      if (y_offset)
+         y_val = LLVMBuildAdd(builder, y_val, y_offset, "");
+      y_val = LLVMBuildMul(builder, y_val, stride, "");
+
+      offsets[i] = LLVMBuildAdd(builder, x_val, y_val, "");
    }
-   LLVMValueRef packed = lp_build_gather_values(gallivm, dst, block_size);
+   LLVMValueRef offset = lp_build_gather_values(gallivm, offsets, block_size);
 
    struct lp_type texel_type = bld->type;
    if (out_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB &&
@@ -553,9 +540,10 @@ static void fs_fb_fetch(const struct lp_build_fs_iface *iface,
          texel_type = lp_type_uint_vec(bld->type.width, bld->type.width * bld->type.length);
       }
    }
-   lp_build_unpack_rgba_soa(gallivm, out_format_desc,
-                            texel_type,
-                            packed, result);
+
+   lp_build_fetch_rgba_soa(gallivm, out_format_desc, texel_type,
+                           true, color_ptr, offset,
+                           NULL, NULL, NULL, result);
 }
 
 /**



More information about the mesa-commit mailing list