llvmpipe: add support for shader buffer binding.
authorDave Airlie <airlied@redhat.com>
Wed, 26 Jun 2019 05:57:30 +0000 (15:57 +1000)
committerDave Airlie <airlied@redhat.com>
Sun, 7 Jul 2019 06:24:12 +0000 (16:24 +1000)
This add support for setting shader buffers and passing them
to draw or binding them to the fragment shader jit.

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
src/gallium/drivers/llvmpipe/lp_context.h
src/gallium/drivers/llvmpipe/lp_setup.c
src/gallium/drivers/llvmpipe/lp_setup.h
src/gallium/drivers/llvmpipe/lp_setup_context.h
src/gallium/drivers/llvmpipe/lp_state.h
src/gallium/drivers/llvmpipe/lp_state_derived.c
src/gallium/drivers/llvmpipe/lp_state_fs.c
src/gallium/drivers/llvmpipe/lp_texture.c

index 7a2f253984280f2b80c731c04f7ab1bd0b445b7f..8127b16261bc99bb78e98d429edd2f66d873b126 100644 (file)
@@ -82,6 +82,8 @@ struct llvmpipe_context {
    struct pipe_viewport_state viewports[PIPE_MAX_VIEWPORTS];
    struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
 
+   struct pipe_shader_buffer ssbos[PIPE_SHADER_TYPES][LP_MAX_TGSI_SHADER_BUFFERS];
+
    unsigned num_samplers[PIPE_SHADER_TYPES];
    unsigned num_sampler_views[PIPE_SHADER_TYPES];
 
index e72e119c8a1b0aaf6bb78776ab9179f83d43bbb6..a3c9960bcafdb08f934cad266a528d2b7b9aa272 100644 (file)
@@ -664,6 +664,26 @@ lp_setup_set_fs_constants(struct lp_setup_context *setup,
    setup->dirty |= LP_SETUP_NEW_CONSTANTS;
 }
 
+void
+lp_setup_set_fs_ssbos(struct lp_setup_context *setup,
+                      unsigned num,
+                      struct pipe_shader_buffer *buffers)
+{
+   unsigned i;
+
+   LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffers);
+
+   assert(num <= ARRAY_SIZE(setup->ssbos));
+
+   for (i = 0; i < num; ++i) {
+      util_copy_shader_buffer(&setup->ssbos[i].current, &buffers[i]);
+   }
+   for (; i < ARRAY_SIZE(setup->ssbos); i++) {
+      util_copy_shader_buffer(&setup->ssbos[i].current, NULL);
+   }
+   setup->dirty |= LP_SETUP_NEW_SSBOS;
+}
+
 
 void
 lp_setup_set_alpha_ref_value( struct lp_setup_context *setup,
@@ -992,6 +1012,11 @@ lp_setup_is_resource_referenced( const struct lp_setup_context *setup,
       }
    }
 
+   for (i = 0; i < ARRAY_SIZE(setup->ssbos); i++) {
+      if (setup->ssbos[i].current.buffer == texture)
+         return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE;
+   }
+
    return LP_UNREFERENCED;
 }
 
@@ -1135,7 +1160,27 @@ try_update_scene_state( struct lp_setup_context *setup )
       }
    }
 
+   if (setup->dirty & LP_SETUP_NEW_SSBOS) {
+      for (i = 0; i < ARRAY_SIZE(setup->ssbos); ++i) {
+         struct pipe_resource *buffer = setup->ssbos[i].current.buffer;
+         const ubyte *current_data = NULL;
+
+         if (!buffer)
+            continue;
+         /* resource buffer */
+         current_data = (ubyte *) llvmpipe_resource_data(buffer);
+         if (current_data) {
+            current_data += setup->ssbos[i].current.buffer_offset;
 
+            setup->fs.current.jit_context.ssbos[i] = (const uint32_t *)current_data;
+            setup->fs.current.jit_context.num_ssbos[i] = setup->ssbos[i].current.buffer_size;
+         } else {
+            setup->fs.current.jit_context.ssbos[i] = NULL;
+            setup->fs.current.jit_context.num_ssbos[i] = 0;
+         }
+         setup->dirty |= LP_SETUP_NEW_FS;
+      }
+   }
    if (setup->dirty & LP_SETUP_NEW_FS) {
       if (!setup->fs.stored ||
           memcmp(setup->fs.stored,
@@ -1287,6 +1332,10 @@ lp_setup_destroy( struct lp_setup_context *setup )
       pipe_resource_reference(&setup->constants[i].current.buffer, NULL);
    }
 
+   for (i = 0; i < ARRAY_SIZE(setup->ssbos); i++) {
+      pipe_resource_reference(&setup->ssbos[i].current.buffer, NULL);
+   }
+
    /* free the scenes in the 'empty' queue */
    for (i = 0; i < ARRAY_SIZE(setup->scenes); i++) {
       struct lp_scene *scene = setup->scenes[i];
index a42df2dc9e020680ef1b130596dfb721b1436e76..7ee50718b66e18f1f644c6a43f29021a99a1af23 100644 (file)
@@ -104,6 +104,11 @@ lp_setup_set_fs_constants(struct lp_setup_context *setup,
                           unsigned num,
                           struct pipe_constant_buffer *buffers);
 
+void
+lp_setup_set_fs_ssbos(struct lp_setup_context *setup,
+                      unsigned num,
+                      struct pipe_shader_buffer *buffers);
+
 void
 lp_setup_set_alpha_ref_value( struct lp_setup_context *setup,
                               float alpha_ref_value );
index 4b55fd922c8fa5d07dd939e7790e19d2f0e5449f..9c8dde5b6ae52cb802d195abce5cb1c76b4734a8 100644 (file)
@@ -49,7 +49,7 @@
 #define LP_SETUP_NEW_BLEND_COLOR 0x04
 #define LP_SETUP_NEW_SCISSOR     0x08
 #define LP_SETUP_NEW_VIEWPORTS   0x10
-
+#define LP_SETUP_NEW_SSBOS       0x20
 
 struct lp_setup_variant;
 
@@ -143,6 +143,11 @@ struct lp_setup_context
       const void *stored_data;
    } constants[LP_MAX_TGSI_CONST_BUFFERS];
 
+   /** fragment shader buffers */
+   struct {
+      struct pipe_shader_buffer current;
+   } ssbos[LP_MAX_TGSI_SHADER_BUFFERS];
+
    struct {
       struct pipe_blend_color current;
       uint8_t *stored;
index f15d70df7d033373e857e637f4f0377e8d85e617..1c3191b983fe21667ee6f5e0a0cf01779bfa4848 100644 (file)
@@ -56,6 +56,7 @@
 #define LP_NEW_GS            0x10000
 #define LP_NEW_SO            0x20000
 #define LP_NEW_SO_BUFFERS    0x40000
+#define LP_NEW_FS_SSBOS      0x80000
 
 
 
index 4bcca9072449ac77496bbb7f7646e7461dab6a3b..f93bc434c644e342097666402597d459ec556266 100644 (file)
@@ -255,6 +255,11 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
                                 ARRAY_SIZE(llvmpipe->constants[PIPE_SHADER_FRAGMENT]),
                                 llvmpipe->constants[PIPE_SHADER_FRAGMENT]);
 
+   if (llvmpipe->dirty & LP_NEW_FS_SSBOS)
+      lp_setup_set_fs_ssbos(llvmpipe->setup,
+                            ARRAY_SIZE(llvmpipe->ssbos[PIPE_SHADER_FRAGMENT]),
+                            llvmpipe->ssbos[PIPE_SHADER_FRAGMENT]);
+
    if (llvmpipe->dirty & (LP_NEW_SAMPLER_VIEW))
       lp_setup_set_fragment_sampler_views(llvmpipe->setup,
                                           llvmpipe->num_sampler_views[PIPE_SHADER_FRAGMENT],
index cf54d034fa57bd98b4467d87d4d295a912c88230..6934c12c243ad74182939dd57bf9851a83032e45 100644 (file)
@@ -3141,6 +3141,34 @@ llvmpipe_set_constant_buffer(struct pipe_context *pipe,
    }
 }
 
+static void
+llvmpipe_set_shader_buffers(struct pipe_context *pipe,
+                            enum pipe_shader_type shader, unsigned start_slot,
+                            unsigned count, const struct pipe_shader_buffer *buffers,
+                            unsigned writable_bitmask)
+{
+   struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+   unsigned i, idx;
+   for (i = start_slot, idx = 0; i < start_slot + count; i++, idx++) {
+      const struct pipe_shader_buffer *buffer = buffers ? &buffers[idx] : NULL;
+
+      util_copy_shader_buffer(&llvmpipe->ssbos[shader][i], buffer);
+
+      if (shader == PIPE_SHADER_VERTEX ||
+          shader == PIPE_SHADER_GEOMETRY) {
+         const unsigned size = buffer ? buffer->buffer_size : 0;
+         const ubyte *data = NULL;
+         if (buffer && buffer->buffer)
+            data = (ubyte *) llvmpipe_resource_data(buffer->buffer);
+         if (data)
+            data += buffer->buffer_offset;
+         draw_set_mapped_shader_buffer(llvmpipe->draw, shader,
+                                       i, data, size);
+      } else if (shader == PIPE_SHADER_FRAGMENT) {
+         llvmpipe->dirty |= LP_NEW_FS_SSBOS;
+      }
+   }
+}
 
 /**
  * Return the blend factor equivalent to a destination alpha of one.
@@ -3484,6 +3512,8 @@ llvmpipe_init_fs_funcs(struct llvmpipe_context *llvmpipe)
    llvmpipe->pipe.delete_fs_state = llvmpipe_delete_fs_state;
 
    llvmpipe->pipe.set_constant_buffer = llvmpipe_set_constant_buffer;
+
+   llvmpipe->pipe.set_shader_buffers = llvmpipe_set_shader_buffers;
 }
 
 
index 89852cc95c3c7df3aaa5ea8ec0e198f784a3abb1..4dc7eb39f8f7606c1d9d5d692f28c0baa59f058e 100644 (file)
@@ -646,7 +646,8 @@ llvmpipe_is_resource_referenced( struct pipe_context *pipe,
    struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
    if (!(presource->bind & (PIPE_BIND_DEPTH_STENCIL |
                             PIPE_BIND_RENDER_TARGET |
-                            PIPE_BIND_SAMPLER_VIEW)))
+                            PIPE_BIND_SAMPLER_VIEW |
+                            PIPE_BIND_SHADER_BUFFER)))
       return LP_UNREFERENCED;
 
    return lp_setup_is_resource_referenced(llvmpipe->setup, presource);