[Mesa-dev] [PATCH 4/4] softpipe: add SSBO/shader atomics support.

Dave Airlie airlied at gmail.com
Mon Apr 11 03:20:22 UTC 2016


From: Dave Airlie <airlied at redhat.com>

This adds support for the features requires for ARB_shader_storage_buffer_object
and ARB_shader_atomic_counters, ARB_shader_atomic_counter_ops.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 docs/GL3.txt                                    |   8 +-
 docs/relnotes/11.3.0.html                       |   4 +-
 src/gallium/auxiliary/tgsi/tgsi_exec.h          |   3 +-
 src/gallium/drivers/softpipe/Makefile.sources   |   1 +
 src/gallium/drivers/softpipe/sp_buffer.c        | 376 ++++++++++++++++++++++++
 src/gallium/drivers/softpipe/sp_buffer.h        |  37 +++
 src/gallium/drivers/softpipe/sp_context.c       |  15 +
 src/gallium/drivers/softpipe/sp_context.h       |   2 +
 src/gallium/drivers/softpipe/sp_fs_exec.c       |   5 +-
 src/gallium/drivers/softpipe/sp_screen.c        |   3 +-
 src/gallium/drivers/softpipe/sp_state.h         |   4 +-
 src/gallium/drivers/softpipe/sp_state_derived.c |   3 +-
 src/gallium/drivers/softpipe/sp_state_image.c   |  28 ++
 13 files changed, 478 insertions(+), 11 deletions(-)
 create mode 100644 src/gallium/drivers/softpipe/sp_buffer.c
 create mode 100644 src/gallium/drivers/softpipe/sp_buffer.h

diff --git a/docs/GL3.txt b/docs/GL3.txt
index e6bb752..0d65673 100644
--- a/docs/GL3.txt
+++ b/docs/GL3.txt
@@ -150,7 +150,7 @@ GL 4.2, GLSL 4.20:
 
   GL_ARB_texture_compression_bptc                       DONE (i965, nvc0, r600, radeonsi)
   GL_ARB_compressed_texture_pixel_storage               DONE (all drivers)
-  GL_ARB_shader_atomic_counters                         DONE (i965, nvc0)
+  GL_ARB_shader_atomic_counters                         DONE (i965, nvc0, softpipe)
   GL_ARB_texture_storage                                DONE (all drivers)
   GL_ARB_transform_feedback_instanced                   DONE (i965, nv50, nvc0, r600, radeonsi, llvmpipe, softpipe)
   GL_ARB_base_instance                                  DONE (i965, nv50, nvc0, r600, radeonsi, llvmpipe, softpipe)
@@ -179,7 +179,7 @@ GL 4.3, GLSL 4.30:
   GL_ARB_program_interface_query                        DONE (all drivers)
   GL_ARB_robust_buffer_access_behavior                  not started
   GL_ARB_shader_image_size                              DONE (i965, radeonsi, softpipe)
-  GL_ARB_shader_storage_buffer_object                   DONE (i965, nvc0)
+  GL_ARB_shader_storage_buffer_object                   DONE (i965, nvc0, softpipe)
   GL_ARB_stencil_texturing                              DONE (i965/gen8+, nv50, nvc0, r600, radeonsi, llvmpipe, softpipe)
   GL_ARB_texture_buffer_range                           DONE (nv50, nvc0, i965, r600, radeonsi, llvmpipe)
   GL_ARB_texture_query_levels                           DONE (all drivers that support GLSL 1.30)
@@ -230,10 +230,10 @@ GLES3.1, GLSL ES 3.1
   GL_ARB_explicit_uniform_location                      DONE (all drivers that support GLSL)
   GL_ARB_framebuffer_no_attachments                     DONE (i965, nvc0, r600, radeonsi)
   GL_ARB_program_interface_query                        DONE (all drivers)
-  GL_ARB_shader_atomic_counters                         DONE (i965, nvc0)
+  GL_ARB_shader_atomic_counters                         DONE (i965, nvc0, softpipe)
   GL_ARB_shader_image_load_store                        DONE (i965, softpipe)
   GL_ARB_shader_image_size                              DONE (i965, softpipe)
-  GL_ARB_shader_storage_buffer_object                   DONE (i965, nvc0)
+  GL_ARB_shader_storage_buffer_object                   DONE (i965, nvc0, softpipe)
   GL_ARB_shading_language_packing                       DONE (all drivers)
   GL_ARB_separate_shader_objects                        DONE (all drivers)
   GL_ARB_stencil_texturing                              DONE (i965/gen8+, nv50, nvc0, r600, radeonsi, llvmpipe, softpipe)
diff --git a/docs/relnotes/11.3.0.html b/docs/relnotes/11.3.0.html
index 97c83a3..8cdbc92 100644
--- a/docs/relnotes/11.3.0.html
+++ b/docs/relnotes/11.3.0.html
@@ -46,9 +46,11 @@ Note: some of the new features are only available with certain drivers.
 <ul>
 <li>GL_ARB_framebuffer_no_attachments on nvc0, r600, radeonsi</li>
 <li>GL_ARB_internalformat_query2 on all drivers</li>
-<li>GL_ARB_shader_atomic_counter_ops on nvc0</li>
+<li>GL_ARB_shader_atomic_counters on softpipe</li>
+<li>GL_ARB_shader_atomic_counter_ops on nvc0, softpipe</li>
 <li>GL_ARB_shader_image_load_store on radeonsi, softpipe</li>
 <li>GL_ARB_shader_image_size on radeonsi, softpipe</li>
+<li>GL_ARB_shader_storage_buffer_objects on softpipe</li>
 <li>GL_ATI_fragment_shader on all Gallium drivers</li>
 <li>GL_EXT_base_instance on all drivers that support GL_ARB_base_instance</li>
 <li>GL_OES_draw_buffers_indexed and GL_EXT_draw_buffers_indexed on all drivers that support GL_ARB_draw_buffers_blend</li>
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h
index 257c58f..42fb922 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h
@@ -528,8 +528,9 @@ tgsi_exec_get_shader_param(enum pipe_shader_cap param)
       return 1;
    case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:
    case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:
-   case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
       return 0;
+   case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
+      return PIPE_MAX_SHADER_BUFFERS;
    case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
       return PIPE_MAX_SHADER_IMAGES;
 
diff --git a/src/gallium/drivers/softpipe/Makefile.sources b/src/gallium/drivers/softpipe/Makefile.sources
index efe8846..97e37d7 100644
--- a/src/gallium/drivers/softpipe/Makefile.sources
+++ b/src/gallium/drivers/softpipe/Makefile.sources
@@ -1,4 +1,5 @@
 C_SOURCES := \
+	sp_buffer.c \
 	sp_clear.c \
 	sp_clear.h \
 	sp_context.c \
diff --git a/src/gallium/drivers/softpipe/sp_buffer.c b/src/gallium/drivers/softpipe/sp_buffer.c
new file mode 100644
index 0000000..f9b3e1f
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_buffer.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright 2016 Red Hat.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "sp_context.h"
+#include "sp_buffer.h"
+#include "sp_texture.h"
+
+#include "util/u_format.h"
+
+static bool
+get_dimensions(const struct pipe_shader_buffer *bview,
+               const struct softpipe_resource *spr,
+               unsigned *width)
+{
+   *width = bview->buffer_size;
+   /*
+    * Bounds check the buffer size from the view
+    * and the buffer size from the underlying buffer.
+    */
+   if (*width > spr->base.width0)
+      return false;
+   return true;
+}
+
+/*
+ * Implement the image LOAD operation.
+ */
+static void
+sp_tgsi_load(const struct tgsi_buffer *buffer,
+             const struct tgsi_buffer_params *params,
+             const int s[TGSI_QUAD_SIZE],
+             float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
+{
+   struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer;
+   struct pipe_shader_buffer *bview;
+   struct softpipe_resource *spr;
+   unsigned width;
+   int c, j;
+   unsigned char *data_ptr;
+   const struct util_format_description *format_desc = util_format_description(PIPE_FORMAT_R32_UINT);
+
+   if (params->unit > PIPE_MAX_SHADER_BUFFERS)
+      goto fail_write_all_zero;
+
+   bview = &sp_buf->sp_bview[params->unit];
+   spr = (struct softpipe_resource *)bview->buffer;
+   if (!spr)
+      goto fail_write_all_zero;
+
+   if (!get_dimensions(bview, spr, &width))
+      return;
+
+   for (j = 0; j < TGSI_QUAD_SIZE; j++) {
+      int s_coord;
+      bool fill_zero = false;
+      uint32_t sdata[4];
+
+      if (!(params->execmask & (1 << j)))
+         fill_zero = true;
+
+      s_coord = s[j];
+      if (s_coord >= width)
+         fill_zero = true;
+
+      if (fill_zero) {
+         for (c = 0; c < 4; c++)
+            rgba[c][j] = 0;
+         continue;
+      }
+      data_ptr = (unsigned char *)spr->data + bview->buffer_offset + s_coord;
+      for (c = 0; c < 4; c++) {
+         format_desc->fetch_rgba_uint(sdata, data_ptr, 0, 0);
+         ((uint32_t *)rgba[c])[j] = sdata[0];
+         data_ptr += 4;
+      }
+   }
+   return;
+fail_write_all_zero:
+   for (j = 0; j < TGSI_QUAD_SIZE; j++) {
+      for (c = 0; c < 4; c++)
+         rgba[c][j] = 0;
+   }
+   return;
+}
+
+/*
+ * Implement the buffer STORE operation.
+ */
+static void
+sp_tgsi_store(const struct tgsi_buffer *buffer,
+              const struct tgsi_buffer_params *params,
+              const int s[TGSI_QUAD_SIZE],
+              float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
+{
+   struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer;
+   struct pipe_shader_buffer *bview;
+   struct softpipe_resource *spr;
+   unsigned width;
+   unsigned char *data_ptr;
+   int j, c;
+   const struct util_format_description *format_desc = util_format_description(PIPE_FORMAT_R32_UINT);
+
+   if (params->unit > PIPE_MAX_SHADER_BUFFERS)
+      return;
+
+   bview = &sp_buf->sp_bview[params->unit];
+   spr = (struct softpipe_resource *)bview->buffer;
+   if (!spr)
+      return;
+
+   if (!get_dimensions(bview, spr, &width))
+      return;
+
+   for (j = 0; j < TGSI_QUAD_SIZE; j++) {
+      int s_coord;
+
+      if (!(params->execmask & (1 << j)))
+         continue;
+
+      s_coord = s[j];
+      if (s_coord >= width)
+         continue;
+
+      data_ptr = (unsigned char *)spr->data + bview->buffer_offset + s_coord;
+
+      for (c = 0; c < 4; c++) {
+         if (params->writemask & (1 << c)) {
+            unsigned temp[4];
+            unsigned char *dptr = data_ptr + (c * 4);
+            temp[0] = ((uint32_t *)rgba[c])[j];
+            format_desc->pack_rgba_uint(dptr, 0, temp, 0, 1, 1);
+         }
+      }
+   }
+}
+
+/*
+ * Implement atomic operations on unsigned integers.
+ */
+static void
+handle_op_uint(const struct pipe_shader_buffer *bview,
+               bool just_read,
+               unsigned char *data_ptr,
+               uint qi,
+               unsigned opcode,
+               unsigned writemask,
+               float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
+               float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
+{
+   uint c;
+   const struct util_format_description *format_desc = util_format_description(PIPE_FORMAT_R32_UINT);
+   unsigned sdata[4];
+
+   for (c = 0; c < 4; c++) {
+      unsigned temp[4];
+      unsigned char *dptr = data_ptr + (c * 4);
+      format_desc->fetch_rgba_uint(temp, dptr, 0, 0);
+      sdata[c] = temp[0];
+   }
+
+   if (just_read) {
+      for (c = 0; c < 4; c++) {
+         ((uint32_t *)rgba[c])[qi] = sdata[c];
+      }
+      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;
+      }
+      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;
+      }
+      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;
+      }
+      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;
+      }
+      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;
+      }
+      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;
+      }
+      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;
+      }
+      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;
+      }
+      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;
+      }
+      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;
+      }
+      break;
+   default:
+      assert(!"Unexpected TGSI opcode in sp_tgsi_op");
+      break;
+   }
+
+   for (c = 0; c < 4; c++) {
+      if (writemask & (1 << c)) {
+         unsigned temp[4];
+         unsigned char *dptr = data_ptr + (c * 4);
+         temp[0] = sdata[c];
+         format_desc->pack_rgba_uint(dptr, 0, temp, 0, 1, 1);
+      }
+   }
+}
+
+/*
+ * Implement atomic buffer operations.
+ */
+static void
+sp_tgsi_op(const struct tgsi_buffer *buffer,
+           const struct tgsi_buffer_params *params,
+           unsigned opcode,
+           const int s[TGSI_QUAD_SIZE],
+           float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
+           float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
+{
+   struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer;
+   struct pipe_shader_buffer *bview;
+   struct softpipe_resource *spr;
+   unsigned width;
+   int j, c;
+   unsigned char *data_ptr;
+
+   if (params->unit > PIPE_MAX_SHADER_BUFFERS)
+      return;
+
+   bview = &sp_buf->sp_bview[params->unit];
+   spr = (struct softpipe_resource *)bview->buffer;
+   if (!spr)
+      goto fail_write_all_zero;
+
+   if (!get_dimensions(bview, spr,
+                       &width))
+      goto fail_write_all_zero;
+
+   for (j = 0; j < TGSI_QUAD_SIZE; j++) {
+      int s_coord;
+      bool just_read = false;
+
+      s_coord = s[j];
+      if (s_coord >= width) {
+         int c;
+         for (c = 0; c < 4; c++) {
+            rgba[c][j] = 0;
+         }
+         continue;
+      }
+
+      /* just readback the value for atomic if execmask isn't set */
+      if (!(params->execmask & (1 << j))) {
+         just_read = true;
+      }
+
+      data_ptr = (unsigned char *)spr->data + bview->buffer_offset + s_coord;
+      /* we should see atomic operations on r32 formats */
+
+      handle_op_uint(bview, just_read, data_ptr, j,
+                     opcode, params->writemask, rgba, rgba2);
+   }
+   return;
+fail_write_all_zero:
+   for (j = 0; j < TGSI_QUAD_SIZE; j++) {
+      for (c = 0; c < 4; c++)
+         rgba[c][j] = 0;
+   }
+   return;
+}
+
+static void
+sp_tgsi_get_dims(const struct tgsi_buffer *buffer,
+                 const struct tgsi_buffer_params *params,
+                 int *dim)
+{
+   struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer;
+   struct pipe_shader_buffer *bview;
+   struct softpipe_resource *spr;
+
+   if (params->unit > PIPE_MAX_SHADER_BUFFERS)
+      return;
+
+   bview = &sp_buf->sp_bview[params->unit];
+   spr = (struct softpipe_resource *)bview->buffer;
+   if (!spr)
+      return;
+
+   *dim = bview->buffer_size;
+}
+
+struct sp_tgsi_buffer *
+sp_create_tgsi_buffer(void)
+{
+   struct sp_tgsi_buffer *buf = CALLOC_STRUCT(sp_tgsi_buffer);
+   if (!buf)
+      return NULL;
+
+   buf->base.load = sp_tgsi_load;
+   buf->base.store = sp_tgsi_store;
+   buf->base.op = sp_tgsi_op;
+   buf->base.get_dims = sp_tgsi_get_dims;
+   return buf;
+};
diff --git a/src/gallium/drivers/softpipe/sp_buffer.h b/src/gallium/drivers/softpipe/sp_buffer.h
new file mode 100644
index 0000000..1822fe7
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_buffer.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 Red Hat.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SP_BUFFER_H
+#define SP_BUFFER_H
+#include "tgsi/tgsi_exec.h"
+
+struct sp_tgsi_buffer
+{
+   struct tgsi_buffer base;
+   struct pipe_shader_buffer sp_bview[PIPE_MAX_SHADER_BUFFERS];
+};
+
+struct sp_tgsi_buffer *
+sp_create_tgsi_buffer(void);
+
+#endif
diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c
index 30b0276..f66fea2 100644
--- a/src/gallium/drivers/softpipe/sp_context.c
+++ b/src/gallium/drivers/softpipe/sp_context.c
@@ -38,6 +38,7 @@
 #include "util/u_pstipple.h"
 #include "util/u_inlines.h"
 #include "tgsi/tgsi_exec.h"
+#include "sp_buffer.h"
 #include "sp_clear.h"
 #include "sp_context.h"
 #include "sp_flush.h"
@@ -203,6 +204,10 @@ softpipe_create_context(struct pipe_screen *screen,
       softpipe->tgsi.image[i] = sp_create_tgsi_image();
    }
 
+   for (i = 0; i < PIPE_SHADER_TYPES; i++) {
+      softpipe->tgsi.buffer[i] = sp_create_tgsi_buffer();
+   }
+
    softpipe->dump_fs = debug_get_bool_option( "SOFTPIPE_DUMP_FS", FALSE );
    softpipe->dump_gs = debug_get_bool_option( "SOFTPIPE_DUMP_GS", FALSE );
 
@@ -288,6 +293,16 @@ softpipe_create_context(struct pipe_screen *screen,
               (struct tgsi_image *)
               softpipe->tgsi.image[PIPE_SHADER_GEOMETRY]);
 
+   draw_buffer(softpipe->draw,
+              PIPE_SHADER_VERTEX,
+              (struct tgsi_buffer *)
+              softpipe->tgsi.buffer[PIPE_SHADER_VERTEX]);
+
+   draw_buffer(softpipe->draw,
+              PIPE_SHADER_GEOMETRY,
+              (struct tgsi_buffer *)
+              softpipe->tgsi.buffer[PIPE_SHADER_GEOMETRY]);
+
    if (debug_get_bool_option( "SOFTPIPE_NO_RAST", FALSE ))
       softpipe->no_rast = TRUE;
 
diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h
index 20a1235..70d00c8 100644
--- a/src/gallium/drivers/softpipe/sp_context.h
+++ b/src/gallium/drivers/softpipe/sp_context.h
@@ -84,6 +84,7 @@ struct softpipe_context {
    struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
 
    struct pipe_image_view images[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_IMAGES];
+   struct pipe_shader_buffer buffers[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS];
    struct pipe_viewport_state viewports[PIPE_MAX_VIEWPORTS];
    struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
    struct pipe_index_buffer index_buffer;
@@ -174,6 +175,7 @@ struct softpipe_context {
    struct {
       struct sp_tgsi_sampler *sampler[PIPE_SHADER_TYPES];
       struct sp_tgsi_image *image[PIPE_SHADER_TYPES];
+      struct sp_tgsi_buffer *buffer[PIPE_SHADER_TYPES];
    } tgsi;
 
    struct tgsi_exec_machine *fs_machine;
diff --git a/src/gallium/drivers/softpipe/sp_fs_exec.c b/src/gallium/drivers/softpipe/sp_fs_exec.c
index 6a5f7ac..155382a 100644
--- a/src/gallium/drivers/softpipe/sp_fs_exec.c
+++ b/src/gallium/drivers/softpipe/sp_fs_exec.c
@@ -63,14 +63,15 @@ static void
 exec_prepare( const struct sp_fragment_shader_variant *var,
               struct tgsi_exec_machine *machine,
               struct tgsi_sampler *sampler,
-              struct tgsi_image *image )
+              struct tgsi_image *image,
+              struct tgsi_buffer *buffer )
 {
    /*
     * Bind tokens/shader to the interpreter's machine state.
     */
    tgsi_exec_machine_bind_shader(machine,
                                  var->tokens,
-                                 sampler, image, NULL);
+                                 sampler, image, buffer);
 }
 
 
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
index 90f29d6..00b414c 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -259,7 +259,6 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
    case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS:
    case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL:
    case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL:
-   case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:
    case PIPE_CAP_INVALIDATE_BUFFER:
    case PIPE_CAP_GENERATE_MIPMAP:
    case PIPE_CAP_STRING_MARKER:
@@ -272,6 +271,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
    case PIPE_CAP_PCI_FUNCTION:
    case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT:
       return 0;
+   case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:
+      return 4;
    }
    /* should only get here on unhandled cases */
    debug_printf("Unexpected PIPE_CAP %d query\n", param);
diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h
index 570bc54..2fc48ab 100644
--- a/src/gallium/drivers/softpipe/sp_state.h
+++ b/src/gallium/drivers/softpipe/sp_state.h
@@ -57,6 +57,7 @@
 
 struct tgsi_sampler;
 struct tgsi_image;
+struct tgsi_buffer;
 struct tgsi_exec_machine;
 struct vertex_info;
 
@@ -83,7 +84,8 @@ struct sp_fragment_shader_variant
    void (*prepare)(const struct sp_fragment_shader_variant *shader,
 		   struct tgsi_exec_machine *machine,
 		   struct tgsi_sampler *sampler,
-		   struct tgsi_image *image);
+		   struct tgsi_image *image,
+		   struct tgsi_buffer *buffer);
 
    unsigned (*run)(const struct sp_fragment_shader_variant *shader,
 		   struct tgsi_exec_machine *machine,
diff --git a/src/gallium/drivers/softpipe/sp_state_derived.c b/src/gallium/drivers/softpipe/sp_state_derived.c
index 65679e7..4ce9d95 100644
--- a/src/gallium/drivers/softpipe/sp_state_derived.c
+++ b/src/gallium/drivers/softpipe/sp_state_derived.c
@@ -344,7 +344,8 @@ update_fragment_shader(struct softpipe_context *softpipe, unsigned prim)
                                     softpipe->fs_machine,
                                     (struct tgsi_sampler *) softpipe->
                                     tgsi.sampler[PIPE_SHADER_FRAGMENT],
-                                    (struct tgsi_image *)softpipe->tgsi.image[PIPE_SHADER_FRAGMENT]);
+                                    (struct tgsi_image *)softpipe->tgsi.image[PIPE_SHADER_FRAGMENT],
+                                    (struct tgsi_buffer *)softpipe->tgsi.buffer[PIPE_SHADER_FRAGMENT]);
    }
    else {
       softpipe->fs_variant = NULL;
diff --git a/src/gallium/drivers/softpipe/sp_state_image.c b/src/gallium/drivers/softpipe/sp_state_image.c
index 8909fa2..5947c93 100644
--- a/src/gallium/drivers/softpipe/sp_state_image.c
+++ b/src/gallium/drivers/softpipe/sp_state_image.c
@@ -24,6 +24,7 @@
 #include "sp_context.h"
 #include "sp_state.h"
 #include "sp_image.h"
+#include "sp_buffer.h"
 
 static void softpipe_set_shader_images(struct pipe_context *pipe,
                                        unsigned shader,
@@ -51,7 +52,34 @@ static void softpipe_set_shader_images(struct pipe_context *pipe,
    }
 }
 
+static void softpipe_set_shader_buffers(struct pipe_context *pipe,
+                                        unsigned shader,
+                                        unsigned start,
+                                        unsigned num,
+                                        struct pipe_shader_buffer *buffers)
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+   unsigned i;
+   assert(shader < PIPE_SHADER_TYPES);
+   assert(start + num <= Elements(softpipe->buffers[shader]));
+
+   /* set the new images */
+   for (i = 0; i < num; i++) {
+      int idx = start + i;
+
+      if (buffers) {
+         pipe_resource_reference(&softpipe->tgsi.buffer[shader]->sp_bview[idx].buffer, buffers[i].buffer);
+         softpipe->tgsi.buffer[shader]->sp_bview[idx] = buffers[i];
+      }
+      else {
+         pipe_resource_reference(&softpipe->tgsi.buffer[shader]->sp_bview[idx].buffer, NULL);
+         memset(&softpipe->tgsi.buffer[shader]->sp_bview[idx], 0, sizeof(struct pipe_shader_buffer));
+      }
+   }
+}
+
 void softpipe_init_image_funcs(struct pipe_context *pipe)
 {
    pipe->set_shader_images = softpipe_set_shader_images;
+   pipe->set_shader_buffers = softpipe_set_shader_buffers;
 }
-- 
2.5.5



More information about the mesa-dev mailing list