Mesa (master): gallium/softpipe/draw: support samplers in geometry shaders

Zack Rusin zack at kemper.freedesktop.org
Fri Jun 11 10:36:50 PDT 2010


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

Author: Zack Rusin <zack at kde.org>
Date:   Fri Jun 11 13:31:52 2010 -0400

gallium/softpipe/draw: support samplers in geometry shaders

---

 src/gallium/auxiliary/draw/draw_context.c       |   13 +++-
 src/gallium/auxiliary/draw/draw_context.h       |    1 +
 src/gallium/drivers/softpipe/sp_context.c       |   24 +++++++-
 src/gallium/drivers/softpipe/sp_context.h       |    6 ++
 src/gallium/drivers/softpipe/sp_flush.c         |    3 +
 src/gallium/drivers/softpipe/sp_state.h         |   10 +++
 src/gallium/drivers/softpipe/sp_state_derived.c |   13 ++++
 src/gallium/drivers/softpipe/sp_state_fs.c      |    3 +
 src/gallium/drivers/softpipe/sp_state_sampler.c |   77 +++++++++++++++++++++++
 src/gallium/include/pipe/p_context.h            |    7 ++
 src/gallium/include/pipe/p_state.h              |    1 +
 11 files changed, 153 insertions(+), 5 deletions(-)

diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index 7c77025..dab95e5 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -435,13 +435,18 @@ draw_num_shader_outputs(const struct draw_context *draw)
  */
 void
 draw_texture_samplers(struct draw_context *draw,
+                      uint shader,
                       uint num_samplers,
                       struct tgsi_sampler **samplers)
 {
-   draw->vs.num_samplers = num_samplers;
-   draw->vs.samplers = samplers;
-   draw->gs.num_samplers = num_samplers;
-   draw->gs.samplers = samplers;
+   if (shader == PIPE_SHADER_VERTEX) {
+      draw->vs.num_samplers = num_samplers;
+      draw->vs.samplers = samplers;
+   } else {
+      debug_assert(shader == PIPE_SHADER_GEOMETRY);
+      draw->gs.num_samplers = num_samplers;
+      draw->gs.samplers = samplers;
+   }
 }
 
 
diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h
index 103d653..c0122f2 100644
--- a/src/gallium/auxiliary/draw/draw_context.h
+++ b/src/gallium/auxiliary/draw/draw_context.h
@@ -97,6 +97,7 @@ draw_num_shader_outputs(const struct draw_context *draw);
 
 void
 draw_texture_samplers(struct draw_context *draw,
+                      uint shader_type,
                       uint num_samplers,
                       struct tgsi_sampler **samplers);
 
diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c
index 401a28a..12ef98a 100644
--- a/src/gallium/drivers/softpipe/sp_context.c
+++ b/src/gallium/drivers/softpipe/sp_context.c
@@ -114,6 +114,11 @@ softpipe_destroy( struct pipe_context *pipe )
       pipe_sampler_view_reference(&softpipe->vertex_sampler_views[i], NULL);
    }
 
+   for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) {
+      sp_destroy_tex_tile_cache(softpipe->geometry_tex_cache[i]);
+      pipe_sampler_view_reference(&softpipe->geometry_sampler_views[i], NULL);
+   }
+
    for (i = 0; i < PIPE_SHADER_TYPES; i++) {
       uint j;
 
@@ -174,7 +179,12 @@ softpipe_is_resource_referenced( struct pipe_context *pipe,
           softpipe->vertex_tex_cache[i]->texture == texture)
          return PIPE_REFERENCED_FOR_READ;
    }
-   
+   for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) {
+      if (softpipe->geometry_tex_cache[i] &&
+          softpipe->geometry_tex_cache[i]->texture == texture)
+         return PIPE_REFERENCED_FOR_READ;
+   }
+
    return PIPE_UNREFERENCED;
 }
 
@@ -225,6 +235,7 @@ softpipe_create_context( struct pipe_screen *screen,
    softpipe->pipe.create_sampler_state = softpipe_create_sampler_state;
    softpipe->pipe.bind_fragment_sampler_states  = softpipe_bind_sampler_states;
    softpipe->pipe.bind_vertex_sampler_states = softpipe_bind_vertex_sampler_states;
+   softpipe->pipe.bind_geometry_sampler_states = softpipe_bind_geometry_sampler_states;
    softpipe->pipe.delete_sampler_state = softpipe_delete_sampler_state;
 
    softpipe->pipe.create_depth_stencil_alpha_state = softpipe_create_depth_stencil_state;
@@ -265,6 +276,7 @@ softpipe_create_context( struct pipe_screen *screen,
    softpipe->pipe.set_scissor_state = softpipe_set_scissor_state;
    softpipe->pipe.set_fragment_sampler_views = softpipe_set_sampler_views;
    softpipe->pipe.set_vertex_sampler_views = softpipe_set_vertex_sampler_views;
+   softpipe->pipe.set_geometry_sampler_views = softpipe_set_geometry_sampler_views;
    softpipe->pipe.create_sampler_view = softpipe_create_sampler_view;
    softpipe->pipe.sampler_view_destroy = softpipe_sampler_view_destroy;
    softpipe->pipe.set_viewport_state = softpipe_set_viewport_state;
@@ -301,6 +313,9 @@ softpipe_create_context( struct pipe_screen *screen,
    for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) {
       softpipe->vertex_tex_cache[i] = sp_create_tex_tile_cache( &softpipe->pipe );
    }
+   for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) {
+      softpipe->geometry_tex_cache[i] = sp_create_tex_tile_cache( &softpipe->pipe );
+   }
 
    softpipe->fs_machine = tgsi_exec_machine_create();
 
@@ -319,10 +334,17 @@ softpipe_create_context( struct pipe_screen *screen,
       goto fail;
 
    draw_texture_samplers(softpipe->draw,
+                         PIPE_SHADER_VERTEX,
                          PIPE_MAX_VERTEX_SAMPLERS,
                          (struct tgsi_sampler **)
                             softpipe->tgsi.vert_samplers_list);
 
+   draw_texture_samplers(softpipe->draw,
+                         PIPE_SHADER_GEOMETRY,
+                         PIPE_MAX_GEOMETRY_SAMPLERS,
+                         (struct tgsi_sampler **)
+                            softpipe->tgsi.geom_samplers_list);
+
    if (debug_get_bool_option( "SP_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 e641a81..53115a8 100644
--- a/src/gallium/drivers/softpipe/sp_context.h
+++ b/src/gallium/drivers/softpipe/sp_context.h
@@ -60,6 +60,7 @@ struct softpipe_context {
    struct pipe_blend_state *blend;
    struct pipe_sampler_state *sampler[PIPE_MAX_SAMPLERS];
    struct pipe_sampler_state *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS];
+   struct pipe_sampler_state *geometry_samplers[PIPE_MAX_GEOMETRY_SAMPLERS];
    struct pipe_depth_stencil_alpha_state *depth_stencil;
    struct pipe_rasterizer_state *rasterizer;
    struct sp_fragment_shader *fs;
@@ -78,6 +79,7 @@ struct softpipe_context {
    struct pipe_scissor_state scissor;
    struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
    struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS];
+   struct pipe_sampler_view *geometry_sampler_views[PIPE_MAX_GEOMETRY_SAMPLERS];
    struct pipe_viewport_state viewport;
    struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
    struct {
@@ -92,6 +94,8 @@ struct softpipe_context {
    unsigned num_sampler_views;
    unsigned num_vertex_samplers;
    unsigned num_vertex_sampler_views;
+   unsigned num_geometry_samplers;
+   unsigned num_geometry_sampler_views;
    unsigned num_vertex_buffers;
 
    unsigned dirty; /**< Mask of SP_NEW_x flags */
@@ -148,6 +152,7 @@ struct softpipe_context {
 
    /** TGSI exec things */
    struct {
+      struct sp_sampler_varient *geom_samplers_list[PIPE_MAX_GEOMETRY_SAMPLERS];
       struct sp_sampler_varient *vert_samplers_list[PIPE_MAX_VERTEX_SAMPLERS];
       struct sp_sampler_varient *frag_samplers_list[PIPE_MAX_SAMPLERS];
    } tgsi;
@@ -169,6 +174,7 @@ struct softpipe_context {
    unsigned tex_timestamp;
    struct softpipe_tex_tile_cache *tex_cache[PIPE_MAX_SAMPLERS];
    struct softpipe_tex_tile_cache *vertex_tex_cache[PIPE_MAX_VERTEX_SAMPLERS];
+   struct softpipe_tex_tile_cache *geometry_tex_cache[PIPE_MAX_GEOMETRY_SAMPLERS];
 
    unsigned use_sse : 1;
    unsigned dump_fs : 1;
diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c
index 5024fc8..4a53ef0 100644
--- a/src/gallium/drivers/softpipe/sp_flush.c
+++ b/src/gallium/drivers/softpipe/sp_flush.c
@@ -56,6 +56,9 @@ softpipe_flush( struct pipe_context *pipe,
       for (i = 0; i < softpipe->num_vertex_sampler_views; i++) {
          sp_flush_tex_tile_cache(softpipe->vertex_tex_cache[i]);
       }
+      for (i = 0; i < softpipe->num_geometry_sampler_views; i++) {
+         sp_flush_tex_tile_cache(softpipe->geometry_tex_cache[i]);
+      }
    }
 
    if (flags & PIPE_FLUSH_SWAPBUFFERS) {
diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h
index d0b73cc..7d6b86d 100644
--- a/src/gallium/drivers/softpipe/sp_state.h
+++ b/src/gallium/drivers/softpipe/sp_state.h
@@ -100,6 +100,7 @@ struct sp_vertex_shader {
 struct sp_geometry_shader {
    struct pipe_shader_state shader;
    struct draw_geometry_shader *draw_data;
+   int max_sampler;
 };
 
 struct sp_velems_state {
@@ -128,6 +129,10 @@ void
 softpipe_bind_vertex_sampler_states(struct pipe_context *,
                                     unsigned num_samplers,
                                     void **samplers);
+void
+softpipe_bind_geometry_sampler_states(struct pipe_context *,
+                                      unsigned num_samplers,
+                                      void **samplers);
 void softpipe_delete_sampler_state(struct pipe_context *, void *);
 
 void *
@@ -195,6 +200,11 @@ softpipe_set_vertex_sampler_views(struct pipe_context *,
                                   unsigned num,
                                   struct pipe_sampler_view **);
 
+void
+softpipe_set_geometry_sampler_views(struct pipe_context *,
+                                    unsigned num,
+                                    struct pipe_sampler_view **);
+
 struct pipe_sampler_view *
 softpipe_create_sampler_view(struct pipe_context *pipe,
                              struct pipe_resource *texture,
diff --git a/src/gallium/drivers/softpipe/sp_state_derived.c b/src/gallium/drivers/softpipe/sp_state_derived.c
index 4c6d490..3ba4d93 100644
--- a/src/gallium/drivers/softpipe/sp_state_derived.c
+++ b/src/gallium/drivers/softpipe/sp_state_derived.c
@@ -225,6 +225,19 @@ update_tgsi_samplers( struct softpipe_context *softpipe )
          }
       }
    }
+
+   for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) {
+      struct softpipe_tex_tile_cache *tc = softpipe->geometry_tex_cache[i];
+
+      if (tc->texture) {
+         struct softpipe_resource *spt = softpipe_resource(tc->texture);
+
+         if (spt->timestamp != tc->timestamp) {
+	    sp_tex_tile_cache_validate_texture(tc);
+            tc->timestamp = spt->timestamp;
+         }
+      }
+   }
 }
 
 
diff --git a/src/gallium/drivers/softpipe/sp_state_fs.c b/src/gallium/drivers/softpipe/sp_state_fs.c
index 2fff80c..3fbf1f2 100644
--- a/src/gallium/drivers/softpipe/sp_state_fs.c
+++ b/src/gallium/drivers/softpipe/sp_state_fs.c
@@ -35,6 +35,7 @@
 #include "util/u_inlines.h"
 #include "draw/draw_context.h"
 #include "draw/draw_vs.h"
+#include "draw/draw_gs.h"
 #include "tgsi/tgsi_dump.h"
 #include "tgsi/tgsi_exec.h"
 #include "tgsi/tgsi_scan.h"
@@ -223,6 +224,8 @@ softpipe_create_gs_state(struct pipe_context *pipe,
    if (state->draw_data == NULL)
       goto fail;
 
+   state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
+
    return state;
 
 fail:
diff --git a/src/gallium/drivers/softpipe/sp_state_sampler.c b/src/gallium/drivers/softpipe/sp_state_sampler.c
index 2692f06..09b0ffc 100644
--- a/src/gallium/drivers/softpipe/sp_state_sampler.c
+++ b/src/gallium/drivers/softpipe/sp_state_sampler.c
@@ -121,6 +121,33 @@ softpipe_bind_vertex_sampler_states(struct pipe_context *pipe,
    softpipe->dirty |= SP_NEW_SAMPLER;
 }
 
+void
+softpipe_bind_geometry_sampler_states(struct pipe_context *pipe,
+                                      unsigned num_samplers,
+                                      void **samplers)
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+   unsigned i;
+
+   assert(num_samplers <= PIPE_MAX_GEOMETRY_SAMPLERS);
+
+   /* Check for no-op */
+   if (num_samplers == softpipe->num_geometry_samplers &&
+       !memcmp(softpipe->geometry_samplers, samplers, num_samplers * sizeof(void *)))
+      return;
+
+   draw_flush(softpipe->draw);
+
+   for (i = 0; i < num_samplers; ++i)
+      softpipe->geometry_samplers[i] = samplers[i];
+   for (i = num_samplers; i < PIPE_MAX_GEOMETRY_SAMPLERS; ++i)
+      softpipe->geometry_samplers[i] = NULL;
+
+   softpipe->num_geometry_samplers = num_samplers;
+
+   softpipe->dirty |= SP_NEW_SAMPLER;
+}
+
 
 struct pipe_sampler_view *
 softpipe_create_sampler_view(struct pipe_context *pipe,
@@ -210,6 +237,36 @@ softpipe_set_vertex_sampler_views(struct pipe_context *pipe,
    softpipe->dirty |= SP_NEW_TEXTURE;
 }
 
+void
+softpipe_set_geometry_sampler_views(struct pipe_context *pipe,
+                                    unsigned num,
+                                    struct pipe_sampler_view **views)
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+   uint i;
+
+   assert(num <= PIPE_MAX_GEOMETRY_SAMPLERS);
+
+   /* Check for no-op */
+   if (num == softpipe->num_geometry_sampler_views &&
+       !memcmp(softpipe->geometry_sampler_views, views, num * sizeof(struct pipe_sampler_view *))) {
+      return;
+   }
+
+   draw_flush(softpipe->draw);
+
+   for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) {
+      struct pipe_sampler_view *view = i < num ? views[i] : NULL;
+
+      pipe_sampler_view_reference(&softpipe->geometry_sampler_views[i], view);
+      sp_tex_tile_cache_set_sampler_view(softpipe->geometry_tex_cache[i], view);
+   }
+
+   softpipe->num_geometry_sampler_views = num;
+
+   softpipe->dirty |= SP_NEW_TEXTURE;
+}
+
 
 /**
  * Find/create an sp_sampler_varient object for sampling the given texture,
@@ -293,6 +350,26 @@ softpipe_reset_sampler_varients(struct softpipe_context *softpipe)
       }
    }
 
+   for (i = 0; i <= softpipe->gs->max_sampler; i++) {
+      if (softpipe->geometry_samplers[i]) {
+         struct pipe_resource *texture = NULL;
+
+         if (softpipe->geometry_sampler_views[i]) {
+            texture = softpipe->geometry_sampler_views[i]->texture;
+         }
+
+         softpipe->tgsi.geom_samplers_list[i] =
+            get_sampler_varient( i,
+                                 sp_sampler(softpipe->geometry_samplers[i]),
+                                 texture,
+                                 TGSI_PROCESSOR_GEOMETRY );
+
+         sp_sampler_varient_bind_texture( softpipe->tgsi.geom_samplers_list[i],
+                                          softpipe->geometry_tex_cache[i],
+                                          texture );
+      }
+   }
+
    for (i = 0; i <= softpipe->fs->info.file_max[TGSI_FILE_SAMPLER]; i++) {
       if (softpipe->sampler[i]) {
          struct pipe_resource *texture = NULL;
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index 72afad6..7ec3d63 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -158,6 +158,9 @@ struct pipe_context {
    void   (*bind_vertex_sampler_states)(struct pipe_context *,
                                         unsigned num_samplers,
                                         void **samplers);
+   void   (*bind_geometry_sampler_states)(struct pipe_context *,
+                                          unsigned num_samplers,
+                                          void **samplers);
    void   (*delete_sampler_state)(struct pipe_context *, void *);
 
    void * (*create_rasterizer_state)(struct pipe_context *,
@@ -238,6 +241,10 @@ struct pipe_context {
                                     unsigned num_views,
                                     struct pipe_sampler_view **);
 
+   void (*set_geometry_sampler_views)(struct pipe_context *,
+                                      unsigned num_views,
+                                      struct pipe_sampler_view **);
+
    void (*set_vertex_buffers)( struct pipe_context *,
                                unsigned num_buffers,
                                const struct pipe_vertex_buffer * );
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
index 5ed1cca..6231f06 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -60,6 +60,7 @@ extern "C" {
 #define PIPE_MAX_CONSTANT_BUFFERS 32
 #define PIPE_MAX_SAMPLERS         16
 #define PIPE_MAX_VERTEX_SAMPLERS  16
+#define PIPE_MAX_GEOMETRY_SAMPLERS  16
 #define PIPE_MAX_SHADER_INPUTS    16
 #define PIPE_MAX_SHADER_OUTPUTS   16
 #define PIPE_MAX_TEXTURE_LEVELS   16



More information about the mesa-commit mailing list