llvmpipe/draw: Fix texture sampling in geometry shaders
authorZack Rusin <zackr@vmware.com>
Wed, 27 Mar 2013 00:53:27 +0000 (17:53 -0700)
committerZack Rusin <zackr@vmware.com>
Wed, 27 Mar 2013 10:53:02 +0000 (03:53 -0700)
We weren't correctly propagating the samplers and sampler views
when they were related to geometry shaders.

Signed-off-by: Zack Rusin <zackr@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: José Fonseca <jfonseca@vmware.com>
src/gallium/auxiliary/draw/draw_context.c
src/gallium/auxiliary/draw/draw_llvm.c
src/gallium/auxiliary/draw/draw_llvm.h
src/gallium/drivers/llvmpipe/lp_context.c
src/gallium/drivers/llvmpipe/lp_context.h
src/gallium/drivers/llvmpipe/lp_draw_arrays.c
src/gallium/drivers/llvmpipe/lp_state.h
src/gallium/drivers/llvmpipe/lp_state_sampler.c

index d64b82b026193be8ac085f316c67519a4e18ce2e..ceb74df7f1292ea107826fb557329c9776db0315 100644 (file)
@@ -792,8 +792,8 @@ draw_set_samplers(struct draw_context *draw,
    draw->num_samplers[shader_stage] = num;
 
 #ifdef HAVE_LLVM
-   if (draw->llvm && shader_stage == PIPE_SHADER_VERTEX)
-      draw_llvm_set_sampler_state(draw);
+   if (draw->llvm)
+      draw_llvm_set_sampler_state(draw, shader_stage);
 #endif
 }
 
index 9ab3a9f874857d815bce1f9ffe642f093a281d20..3ce48d802c73fd5076fb0f84a136183b55c9c0db 100644 (file)
@@ -241,7 +241,7 @@ create_gs_jit_context_type(struct gallivm_state *gallivm,
    LLVMTargetDataRef target = gallivm->target;
    LLVMTypeRef float_type = LLVMFloatTypeInContext(gallivm->context);
    LLVMTypeRef int_type = LLVMInt32TypeInContext(gallivm->context);
-   LLVMTypeRef elem_types[8];
+   LLVMTypeRef elem_types[DRAW_GS_JIT_CTX_NUM_FIELDS];
    LLVMTypeRef context_type;
 
    elem_types[0] = LLVMArrayType(LLVMPointerType(float_type, 0), /* constants */
@@ -249,17 +249,17 @@ create_gs_jit_context_type(struct gallivm_state *gallivm,
    elem_types[1] = LLVMPointerType(LLVMArrayType(LLVMArrayType(float_type, 4),
                                                  DRAW_TOTAL_CLIP_PLANES), 0);
    elem_types[2] = LLVMPointerType(float_type, 0); /* viewport */
-   
-   elem_types[3] = LLVMPointerType(LLVMPointerType(int_type, 0), 0);
-   elem_types[4] = LLVMPointerType(LLVMVectorType(int_type,
-                                                  vector_length), 0);
-   elem_types[5] = LLVMPointerType(LLVMVectorType(int_type,
-                                                  vector_length), 0);
 
-   elem_types[6] = LLVMArrayType(texture_type,
+   elem_types[3] = LLVMArrayType(texture_type,
                                  PIPE_MAX_SHADER_SAMPLER_VIEWS); /* textures */
-   elem_types[7] = LLVMArrayType(sampler_type,
+   elem_types[4] = LLVMArrayType(sampler_type,
                                  PIPE_MAX_SAMPLERS); /* samplers */
+   
+   elem_types[5] = LLVMPointerType(LLVMPointerType(int_type, 0), 0);
+   elem_types[6] = LLVMPointerType(LLVMVectorType(int_type,
+                                                  vector_length), 0);
+   elem_types[7] = LLVMPointerType(LLVMVectorType(int_type,
+                                                  vector_length), 0);
 
    context_type = LLVMStructTypeInContext(gallivm->context, elem_types,
                                           Elements(elem_types), 0);
@@ -270,23 +270,26 @@ create_gs_jit_context_type(struct gallivm_state *gallivm,
 #endif
 
    LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, constants,
-                          target, context_type, 0);
+                          target, context_type, DRAW_GS_JIT_CTX_CONSTANTS);
    LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, planes,
-                          target, context_type, 1);
+                          target, context_type, DRAW_GS_JIT_CTX_PLANES);
    LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, viewport,
-                          target, context_type, 2);
-   LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, prim_lengths,
-                          target, context_type, 3);
-   LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, emitted_vertices,
-                          target, context_type, 4);
-   LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, emitted_prims,
-                          target, context_type, 5);
+                          target, context_type, DRAW_GS_JIT_CTX_VIEWPORT);
    LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, textures,
                           target, context_type,
                           DRAW_GS_JIT_CTX_TEXTURES);
    LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, samplers,
                           target, context_type,
                           DRAW_GS_JIT_CTX_SAMPLERS);
+   LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, prim_lengths,
+                          target, context_type,
+                          DRAW_GS_JIT_CTX_PRIM_LENGTHS);
+   LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, emitted_vertices,
+                          target, context_type,
+                          DRAW_GS_JIT_CTX_EMITTED_VERTICES);
+   LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, emitted_prims,
+                          target, context_type,
+                          DRAW_GS_JIT_CTX_EMITTED_PRIMS);
    LP_CHECK_STRUCT_SIZE(struct draw_gs_jit_context,
                         target, context_type);
 
@@ -1721,33 +1724,36 @@ draw_llvm_set_mapped_texture(struct draw_context *draw,
 
 
 void
-draw_llvm_set_sampler_state(struct draw_context *draw)
+draw_llvm_set_sampler_state(struct draw_context *draw, 
+                            unsigned shader_type)
 {
    unsigned i;
 
-   for (i = 0; i < draw->num_samplers[PIPE_SHADER_VERTEX]; i++) {
-      struct draw_jit_sampler *jit_sam = &draw->llvm->jit_context.samplers[i];
-
-      if (draw->samplers[i]) {
-         const struct pipe_sampler_state *s
-            = draw->samplers[PIPE_SHADER_VERTEX][i];
-         jit_sam->min_lod = s->min_lod;
-         jit_sam->max_lod = s->max_lod;
-         jit_sam->lod_bias = s->lod_bias;
-         COPY_4V(jit_sam->border_color, s->border_color.f);
+   if (shader_type == PIPE_SHADER_VERTEX) {
+      for (i = 0; i < draw->num_samplers[PIPE_SHADER_VERTEX]; i++) {
+         struct draw_jit_sampler *jit_sam = &draw->llvm->jit_context.samplers[i];
+
+         if (draw->samplers[i]) {
+            const struct pipe_sampler_state *s
+               = draw->samplers[PIPE_SHADER_VERTEX][i];
+            jit_sam->min_lod = s->min_lod;
+            jit_sam->max_lod = s->max_lod;
+            jit_sam->lod_bias = s->lod_bias;
+            COPY_4V(jit_sam->border_color, s->border_color.f);
+         }
       }
-   }
-
-   for (i = 0; i < draw->num_samplers[PIPE_SHADER_GEOMETRY]; i++) {
-      struct draw_jit_sampler *jit_sam = &draw->llvm->gs_jit_context.samplers[i];
-
-      if (draw->samplers[i]) {
-         const struct pipe_sampler_state *s
-            = draw->samplers[PIPE_SHADER_GEOMETRY][i];
-         jit_sam->min_lod = s->min_lod;
-         jit_sam->max_lod = s->max_lod;
-         jit_sam->lod_bias = s->lod_bias;
-         COPY_4V(jit_sam->border_color, s->border_color.f);
+   } else if (shader_type == PIPE_SHADER_GEOMETRY) {
+      for (i = 0; i < draw->num_samplers[PIPE_SHADER_GEOMETRY]; i++) {
+         struct draw_jit_sampler *jit_sam = &draw->llvm->gs_jit_context.samplers[i];
+
+         if (draw->samplers[i]) {
+            const struct pipe_sampler_state *s
+               = draw->samplers[PIPE_SHADER_GEOMETRY][i];
+            jit_sam->min_lod = s->min_lod;
+            jit_sam->max_lod = s->max_lod;
+            jit_sam->lod_bias = s->lod_bias;
+            COPY_4V(jit_sam->border_color, s->border_color.f);
+         }
       }
    }
 }
@@ -1951,6 +1957,8 @@ draw_gs_llvm_generate(struct draw_llvm *llvm,
                      &llvm->draw->gs.geometry_shader->info,
                      &gs_iface);
 
+   sampler->destroy(sampler);
+
    lp_build_mask_end(&mask);
 
    LLVMBuildRet(builder, lp_build_zero(gallivm, lp_type_uint(32)));
index fc0d2bd4bf1ef96fbab676acfb43ce33d17e537b..84ee601e59dff5f442dec3fdc03669d6d275b33d 100644 (file)
@@ -186,35 +186,40 @@ struct draw_gs_jit_context
    float (*planes) [DRAW_TOTAL_CLIP_PLANES][4];
    float *viewport;
 
+   /* There two need to be exactly at DRAW_JIT_CTX_TEXTURES and
+    * DRAW_JIT_CTX_SAMPLERS positions in the struct */
+   struct draw_jit_texture textures[PIPE_MAX_SHADER_SAMPLER_VIEWS];
+   struct draw_jit_sampler samplers[PIPE_MAX_SAMPLERS];
+   
    int **prim_lengths;
    int *emitted_vertices;
    int *emitted_prims;
-
-   struct draw_jit_texture textures[PIPE_MAX_SHADER_SAMPLER_VIEWS];
-   struct draw_jit_sampler samplers[PIPE_MAX_SAMPLERS];
 };
 
+enum {
+   DRAW_GS_JIT_CTX_CONSTANTS = 0,
+   DRAW_GS_JIT_CTX_PLANES = 1,
+   DRAW_GS_JIT_CTX_VIEWPORT = 2,
+   /* Textures and samples are reserved for DRAW_JIT_CTX_TEXTURES
+    * and DRAW_JIT_CTX_SAMPLERS, because they both need
+    * to be at exactly the same locations as they are in the
+    * VS ctx structure for sampling to work. */
+   DRAW_GS_JIT_CTX_TEXTURES = DRAW_JIT_CTX_TEXTURES,
+   DRAW_GS_JIT_CTX_SAMPLERS = DRAW_JIT_CTX_SAMPLERS,
+   DRAW_GS_JIT_CTX_PRIM_LENGTHS = 5,
+   DRAW_GS_JIT_CTX_EMITTED_VERTICES = 6,
+   DRAW_GS_JIT_CTX_EMITTED_PRIMS = 7,
+   DRAW_GS_JIT_CTX_NUM_FIELDS = 8
+};
 
 #define draw_gs_jit_context_constants(_gallivm, _ptr) \
-   lp_build_struct_get_ptr(_gallivm, _ptr, 0, "constants")
+   lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_GS_JIT_CTX_CONSTANTS, "constants")
 
 #define draw_gs_jit_context_planes(_gallivm, _ptr) \
-   lp_build_struct_get(_gallivm, _ptr, 1, "planes")
+   lp_build_struct_get(_gallivm, _ptr, DRAW_GS_JIT_CTX_PLANES, "planes")
 
 #define draw_gs_jit_context_viewport(_gallivm, _ptr) \
-   lp_build_struct_get(_gallivm, _ptr, 2, "viewport")
-
-#define draw_gs_jit_prim_lengths(_gallivm, _ptr) \
-   lp_build_struct_get(_gallivm, _ptr, 3, "prim_lengths")
-
-#define draw_gs_jit_emitted_vertices(_gallivm, _ptr) \
-   lp_build_struct_get(_gallivm, _ptr, 4, "emitted_vertices")
-
-#define draw_gs_jit_emitted_prims(_gallivm, _ptr) \
-   lp_build_struct_get(_gallivm, _ptr, 5, "emitted_prims")
-
-#define DRAW_GS_JIT_CTX_TEXTURES 6
-#define DRAW_GS_JIT_CTX_SAMPLERS 7
+   lp_build_struct_get(_gallivm, _ptr, DRAW_GS_JIT_CTX_VIEWPORT, "viewport")
 
 #define draw_gs_jit_context_textures(_gallivm, _ptr) \
    lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_GS_JIT_CTX_TEXTURES, "textures")
@@ -222,6 +227,15 @@ struct draw_gs_jit_context
 #define draw_gs_jit_context_samplers(_gallivm, _ptr) \
    lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_GS_JIT_CTX_SAMPLERS, "samplers")
 
+#define draw_gs_jit_prim_lengths(_gallivm, _ptr) \
+   lp_build_struct_get(_gallivm, _ptr, DRAW_GS_JIT_CTX_PRIM_LENGTHS, "prim_lengths")
+
+#define draw_gs_jit_emitted_vertices(_gallivm, _ptr) \
+   lp_build_struct_get(_gallivm, _ptr, DRAW_GS_JIT_CTX_EMITTED_VERTICES, "emitted_vertices")
+
+#define draw_gs_jit_emitted_prims(_gallivm, _ptr) \
+   lp_build_struct_get(_gallivm, _ptr, DRAW_GS_JIT_CTX_EMITTED_PRIMS, "emitted_prims")
+
 
 
 typedef int
@@ -478,7 +492,7 @@ draw_llvm_sampler_soa_create(const struct draw_sampler_static_state *static_stat
                              LLVMValueRef context_ptr);
 
 void
-draw_llvm_set_sampler_state(struct draw_context *draw);
+draw_llvm_set_sampler_state(struct draw_context *draw, unsigned shader_stage);
 
 void
 draw_llvm_set_mapped_texture(struct draw_context *draw,
index 25b1cd063196dbb2b3b7c6804d9ff19ccaa084bf..fa675eab7e1ad5969ca1800b3d7a34a38d0e01e2 100644 (file)
@@ -81,6 +81,10 @@ static void llvmpipe_destroy( struct pipe_context *pipe )
       pipe_sampler_view_reference(&llvmpipe->sampler_views[PIPE_SHADER_VERTEX][i], NULL);
    }
 
+   for (i = 0; i < Elements(llvmpipe->sampler_views[0]); i++) {
+      pipe_sampler_view_reference(&llvmpipe->sampler_views[PIPE_SHADER_GEOMETRY][i], NULL);
+   }
+
    for (i = 0; i < Elements(llvmpipe->constants); i++) {
       for (j = 0; j < Elements(llvmpipe->constants[i]); j++) {
          pipe_resource_reference(&llvmpipe->constants[i][j].buffer, NULL);
index 9ccb67bdd1f5cdead2fe8adbdee43be834370e66..6ee7b99f478dc516a9c8c82e0ce43ab392aaabfa 100644 (file)
@@ -82,6 +82,7 @@ struct llvmpipe_context {
    struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
    struct pipe_index_buffer index_buffer;
    struct pipe_resource *mapped_vs_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS];
+   struct pipe_resource *mapped_gs_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS];
 
    unsigned num_samplers[PIPE_SHADER_TYPES];
    unsigned num_sampler_views[PIPE_SHADER_TYPES];
index eaa9ba3b130407f1e38e92151aa556e5ec019957..ae00c49d490b1b138df5a2d93c50f27744ff7409 100644 (file)
@@ -98,6 +98,9 @@ llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
    llvmpipe_prepare_vertex_sampling(lp,
                                     lp->num_sampler_views[PIPE_SHADER_VERTEX],
                                     lp->sampler_views[PIPE_SHADER_VERTEX]);
+   llvmpipe_prepare_geometry_sampling(lp,
+                                      lp->num_sampler_views[PIPE_SHADER_GEOMETRY],
+                                      lp->sampler_views[PIPE_SHADER_GEOMETRY]);
 
    /* draw! */
    draw_vbo(draw, info);
@@ -114,6 +117,7 @@ llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
    draw_set_mapped_so_targets(draw, 0, NULL);
 
    llvmpipe_cleanup_vertex_sampling(lp);
+   llvmpipe_cleanup_geometry_sampling(lp);
 
    /*
     * TODO: Flush only when a user vertex/index buffer is present
index 94a21a0158bdde9ac64ace262419478598c25def..1f27d70415e4c04e6e9852680e719e7b5c87519f 100644 (file)
@@ -141,4 +141,12 @@ void
 llvmpipe_cleanup_vertex_sampling(struct llvmpipe_context *ctx);
 
 
+void
+llvmpipe_prepare_geometry_sampling(struct llvmpipe_context *ctx,
+                                   unsigned num,
+                                   struct pipe_sampler_view **views);
+void
+llvmpipe_cleanup_geometry_sampling(struct llvmpipe_context *ctx);
+
+
 #endif
index 7441973bda2308029809b205a17abc499606eb13..6498d130e0635aeb6d6def3def85af1cbc2e52b9 100644 (file)
@@ -250,14 +250,15 @@ llvmpipe_delete_sampler_state(struct pipe_context *pipe,
 }
 
 
-/**
- * Called during state validation when LP_NEW_SAMPLER_VIEW is set.
- */
-void
-llvmpipe_prepare_vertex_sampling(struct llvmpipe_context *lp,
-                                 unsigned num,
-                                 struct pipe_sampler_view **views)
+static void
+prepare_shader_sampling(
+   struct llvmpipe_context *lp,
+   unsigned num,
+   struct pipe_sampler_view **views,
+   unsigned shader_type,
+   struct pipe_resource *mapped_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS])
 {
+
    unsigned i;
    uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS];
    uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS];
@@ -282,7 +283,7 @@ llvmpipe_prepare_vertex_sampling(struct llvmpipe_context *lp,
          /* We're referencing the texture's internal data, so save a
           * reference to it.
           */
-         pipe_resource_reference(&lp->mapped_vs_tex[i], tex);
+         pipe_resource_reference(&mapped_tex[i], tex);
 
          if (!lp_tex->dt) {
             /* regular texture - setup array of mipmap level offsets */
@@ -357,7 +358,7 @@ llvmpipe_prepare_vertex_sampling(struct llvmpipe_context *lp,
             assert(addr);
          }
          draw_set_mapped_texture(lp->draw,
-                                 PIPE_SHADER_VERTEX,
+                                 shader_type,
                                  i,
                                  width0, tex->height0, num_layers,
                                  first_level, last_level,
@@ -366,6 +367,19 @@ llvmpipe_prepare_vertex_sampling(struct llvmpipe_context *lp,
       }
    }
 }
+                        
+
+/**
+ * Called during state validation when LP_NEW_SAMPLER_VIEW is set.
+ */
+void
+llvmpipe_prepare_vertex_sampling(struct llvmpipe_context *lp,
+                                 unsigned num,
+                                 struct pipe_sampler_view **views)
+{
+   prepare_shader_sampling(lp, num, views, PIPE_SHADER_VERTEX,
+                           lp->mapped_vs_tex);
+}
 
 void
 llvmpipe_cleanup_vertex_sampling(struct llvmpipe_context *ctx)
@@ -376,6 +390,28 @@ llvmpipe_cleanup_vertex_sampling(struct llvmpipe_context *ctx)
    }
 }
 
+
+/**
+ * Called during state validation when LP_NEW_SAMPLER_VIEW is set.
+ */
+void
+llvmpipe_prepare_geometry_sampling(struct llvmpipe_context *lp,
+                                   unsigned num,
+                                   struct pipe_sampler_view **views)
+{
+   prepare_shader_sampling(lp, num, views, PIPE_SHADER_GEOMETRY,
+                           lp->mapped_gs_tex);
+}
+
+void
+llvmpipe_cleanup_geometry_sampling(struct llvmpipe_context *ctx)
+{
+   unsigned i;
+   for (i = 0; i < Elements(ctx->mapped_gs_tex); i++) {
+      pipe_resource_reference(&ctx->mapped_gs_tex[i], NULL);
+   }
+}
+
 void
 llvmpipe_init_sampler_funcs(struct llvmpipe_context *llvmpipe)
 {