Module: Mesa
Branch: master
Commit: 6444f5702dcac87c41e9c7af66c1762c7a48f3a0
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=6444f5702dcac87c41e9c7af66c1762c7a48f3a0

Author: Eric Anholt <[email protected]>
Date:   Tue Aug 25 20:58:27 2020 -0700

softpipe: Fix buffer overflows in SSBO atomics.

SSBO atomics are always to the .x channel, but we were doing reads on
.xyzw and writes to whatever the writemask was.

Reviewed-by: Marek Olšák <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3395>

---

 src/gallium/drivers/softpipe/sp_buffer.c | 153 ++++++++++++++-----------------
 1 file changed, 68 insertions(+), 85 deletions(-)

diff --git a/src/gallium/drivers/softpipe/sp_buffer.c 
b/src/gallium/drivers/softpipe/sp_buffer.c
index 585f0875ce6..97e52008a8b 100644
--- a/src/gallium/drivers/softpipe/sp_buffer.c
+++ b/src/gallium/drivers/softpipe/sp_buffer.c
@@ -155,114 +155,97 @@ handle_op_atomic(const struct pipe_shader_buffer *bview,
                  float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
                  float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
 {
-   uint c;
-   unsigned sdata[4];
+   uint c = 0; /* SSBO atomics are always on the .x channel. */
+   unsigned sdata;
 
-   for (c = 0; c < 4; c++) {
-      memcpy(&sdata[c], data_ptr + (c * 4), 4);
-   }
+   memcpy(&sdata, data_ptr + (c * 4), 4);
 
    if (just_read) {
-      for (c = 0; c < 4; c++) {
-         ((uint32_t *)rgba[c])[qi] = sdata[c];
-      }
+      ((uint32_t *)rgba[c])[qi] = sdata;
       return;
    }
 
    switch (opcode) {
-   case TGSI_OPCODE_ATOMUADD:
-      for (c = 0; c < 4; c++) {
-         unsigned temp = sdata[c];
-         sdata[c] += ((uint32_t *)rgba[c])[qi];
-         ((uint32_t *)rgba[c])[qi] = temp;
-      }
+   case TGSI_OPCODE_ATOMUADD: {
+      unsigned temp = sdata;
+      sdata += ((uint32_t *)rgba[c])[qi];
+      ((uint32_t *)rgba[c])[qi] = temp;
       break;
-   case TGSI_OPCODE_ATOMXCHG:
-      for (c = 0; c < 4; c++) {
-         unsigned temp = sdata[c];
-         sdata[c] = ((uint32_t *)rgba[c])[qi];
-         ((uint32_t *)rgba[c])[qi] = temp;
-      }
+   }
+   case TGSI_OPCODE_ATOMXCHG: {
+      unsigned temp = sdata;
+      sdata = ((uint32_t *)rgba[c])[qi];
+      ((uint32_t *)rgba[c])[qi] = temp;
       break;
-   case TGSI_OPCODE_ATOMCAS:
-      for (c = 0; c < 4; c++) {
-         unsigned dst_x = sdata[c];
-         unsigned cmp_x = ((uint32_t *)rgba[c])[qi];
-         unsigned src_x = ((uint32_t *)rgba2[c])[qi];
-         unsigned temp = sdata[c];
-         sdata[c] = (dst_x == cmp_x) ? src_x : dst_x;
-         ((uint32_t *)rgba[c])[qi] = temp;
-      }
+   }
+   case TGSI_OPCODE_ATOMCAS: {
+      unsigned dst_x = sdata;
+      unsigned cmp_x = ((uint32_t *)rgba[c])[qi];
+      unsigned src_x = ((uint32_t *)rgba2[c])[qi];
+      unsigned temp = sdata;
+      sdata = (dst_x == cmp_x) ? src_x : dst_x;
+      ((uint32_t *)rgba[c])[qi] = temp;
       break;
-   case TGSI_OPCODE_ATOMAND:
-      for (c = 0; c < 4; c++) {
-         unsigned temp = sdata[c];
-         sdata[c] &= ((uint32_t *)rgba[c])[qi];
-         ((uint32_t *)rgba[c])[qi] = temp;
-      }
+   }
+   case TGSI_OPCODE_ATOMAND: {
+      unsigned temp = sdata;
+      sdata &= ((uint32_t *)rgba[c])[qi];
+      ((uint32_t *)rgba[c])[qi] = temp;
       break;
-   case TGSI_OPCODE_ATOMOR:
-      for (c = 0; c < 4; c++) {
-         unsigned temp = sdata[c];
-         sdata[c] |= ((uint32_t *)rgba[c])[qi];
-         ((uint32_t *)rgba[c])[qi] = temp;
-      }
+   }
+   case TGSI_OPCODE_ATOMOR: {
+      unsigned temp = sdata;
+      sdata |= ((uint32_t *)rgba[c])[qi];
+      ((uint32_t *)rgba[c])[qi] = temp;
       break;
-   case TGSI_OPCODE_ATOMXOR:
-      for (c = 0; c < 4; c++) {
-         unsigned temp = sdata[c];
-         sdata[c] ^= ((uint32_t *)rgba[c])[qi];
-         ((uint32_t *)rgba[c])[qi] = temp;
-      }
+   }
+   case TGSI_OPCODE_ATOMXOR: {
+      unsigned temp = sdata;
+      sdata ^= ((uint32_t *)rgba[c])[qi];
+      ((uint32_t *)rgba[c])[qi] = temp;
       break;
-   case TGSI_OPCODE_ATOMUMIN:
-      for (c = 0; c < 4; c++) {
-         unsigned dst_x = sdata[c];
-         unsigned src_x = ((uint32_t *)rgba[c])[qi];
-         sdata[c] = MIN2(dst_x, src_x);
-         ((uint32_t *)rgba[c])[qi] = dst_x;
-      }
+   }
+   case TGSI_OPCODE_ATOMUMIN: {
+      unsigned dst_x = sdata;
+      unsigned src_x = ((uint32_t *)rgba[c])[qi];
+      sdata = MIN2(dst_x, src_x);
+      ((uint32_t *)rgba[c])[qi] = dst_x;
       break;
-   case TGSI_OPCODE_ATOMUMAX:
-      for (c = 0; c < 4; c++) {
-         unsigned dst_x = sdata[c];
-         unsigned src_x = ((uint32_t *)rgba[c])[qi];
-         sdata[c] = MAX2(dst_x, src_x);
-         ((uint32_t *)rgba[c])[qi] = dst_x;
-      }
+   }
+   case TGSI_OPCODE_ATOMUMAX: {
+      unsigned dst_x = sdata;
+      unsigned src_x = ((uint32_t *)rgba[c])[qi];
+      sdata = MAX2(dst_x, src_x);
+      ((uint32_t *)rgba[c])[qi] = dst_x;
       break;
-   case TGSI_OPCODE_ATOMIMIN:
-      for (c = 0; c < 4; c++) {
-         int dst_x = sdata[c];
-         int src_x = ((uint32_t *)rgba[c])[qi];
-         sdata[c] = MIN2(dst_x, src_x);
-         ((uint32_t *)rgba[c])[qi] = dst_x;
-      }
+   }
+   case TGSI_OPCODE_ATOMIMIN: {
+      int dst_x = sdata;
+      int src_x = ((uint32_t *)rgba[c])[qi];
+      sdata = MIN2(dst_x, src_x);
+      ((uint32_t *)rgba[c])[qi] = dst_x;
       break;
-   case TGSI_OPCODE_ATOMIMAX:
-      for (c = 0; c < 4; c++) {
-         int dst_x = sdata[c];
-         int src_x = ((uint32_t *)rgba[c])[qi];
-         sdata[c] = MAX2(dst_x, src_x);
-         ((uint32_t *)rgba[c])[qi] = dst_x;
-      }
+   }
+   case TGSI_OPCODE_ATOMIMAX: {
+      int dst_x = sdata;
+      int src_x = ((uint32_t *)rgba[c])[qi];
+      sdata = MAX2(dst_x, src_x);
+      ((uint32_t *)rgba[c])[qi] = dst_x;
       break;
-   case TGSI_OPCODE_ATOMFADD:
-      for (c = 0; c < 4; c++) {
-         float temp = uif(sdata[c]);
-         sdata[c] = fui(temp + rgba[c][qi]);
-         rgba[c][qi] = temp;
-      }
+   }
+   case TGSI_OPCODE_ATOMFADD: {
+      float temp = uif(sdata);
+      sdata = fui(temp + rgba[c][qi]);
+      rgba[c][qi] = temp;
       break;
+   }
    default:
       assert(!"Unexpected TGSI opcode in sp_tgsi_op");
       break;
    }
 
-   for (c = 0; c < 4; c++) {
-      if (writemask & (1 << c)) {
-         memcpy(data_ptr + (c * 4), &sdata[c], 4);
-      }
+   if (writemask & TGSI_WRITEMASK_X) {
+      memcpy(data_ptr + (c * 4), &sdata, 4);
    }
 }
 

_______________________________________________
mesa-commit mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to