gallivm,llvmpipe,draw: Support multiple constant buffers.
authorJosé Fonseca <jfonseca@vmware.com>
Tue, 4 Dec 2012 14:52:44 +0000 (14:52 +0000)
committerJosé Fonseca <jfonseca@vmware.com>
Fri, 7 Dec 2012 15:03:07 +0000 (15:03 +0000)
Support 16 (defined in LP_MAX_TGSI_CONST_BUFFERS) as opposed to 32 (as
defined by PIPE_MAX_CONSTANT_BUFFERS) because that would make the jit
context become unnecessarily large.

v2: Bump limit from 4 to 16 to cover ARB_uniform_buffer_object needs,
per Dave Airlie.

Reviewed-by: Brian Paul <brianp@vmware.com>
13 files changed:
src/gallium/auxiliary/draw/draw_llvm.c
src/gallium/auxiliary/draw/draw_llvm.h
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
src/gallium/auxiliary/gallivm/lp_bld_limits.h
src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
src/gallium/drivers/llvmpipe/lp_context.h
src/gallium/drivers/llvmpipe/lp_jit.c
src/gallium/drivers/llvmpipe/lp_jit.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_derived.c
src/gallium/drivers/llvmpipe/lp_state_fs.c

index 6f0e1de7481ace7a22d74c890cea0ac2d8b90417..039db8fce49994b070c9e3399b6905e0664002f7 100644 (file)
@@ -161,8 +161,9 @@ create_jit_context_type(struct gallivm_state *gallivm,
    LLVMTypeRef elem_types[5];
    LLVMTypeRef context_type;
 
-   elem_types[0] = LLVMPointerType(float_type, 0); /* vs_constants */
-   elem_types[1] = LLVMPointerType(float_type, 0); /* gs_constants */
+   elem_types[0] = LLVMArrayType(LLVMPointerType(float_type, 0), /* vs_constants */
+                                 LP_MAX_TGSI_CONST_BUFFERS);
+   elem_types[1] = elem_types[0]; /* gs_constants */
    elem_types[2] = LLVMPointerType(LLVMArrayType(LLVMArrayType(float_type, 4),
                                                  DRAW_TOTAL_CLIP_PLANES), 0);
    elem_types[3] = LLVMPointerType(float_type, 0); /* viewport */
index d7a630eb015e44d62cd44ec90dc501efeb4eebbe..bd11886149d9ed8c351037a51574150f1a1d5f3b 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "draw/draw_vs.h"
 #include "gallivm/lp_bld_sample.h"
+#include "gallivm/lp_bld_limits.h"
 
 #include "pipe/p_context.h"
 #include "util/u_simple_list.h"
@@ -94,8 +95,8 @@ enum {
  */
 struct draw_jit_context
 {
-   const float *vs_constants;
-   const float *gs_constants;
+   const float *vs_constants[LP_MAX_TGSI_CONST_BUFFERS];
+   const float *gs_constants[LP_MAX_TGSI_CONST_BUFFERS];
    float (*planes) [DRAW_TOTAL_CLIP_PLANES][4];
    float *viewport;
 
@@ -104,10 +105,10 @@ struct draw_jit_context
 
 
 #define draw_jit_context_vs_constants(_gallivm, _ptr) \
-   lp_build_struct_get(_gallivm, _ptr, 0, "vs_constants")
+   lp_build_struct_get_ptr(_gallivm, _ptr, 0, "vs_constants")
 
 #define draw_jit_context_gs_constants(_gallivm, _ptr) \
-   lp_build_struct_get(_gallivm, _ptr, 1, "gs_constants")
+   lp_build_struct_get_ptr(_gallivm, _ptr, 1, "gs_constants")
 
 #define draw_jit_context_planes(_gallivm, _ptr) \
    lp_build_struct_get(_gallivm, _ptr, 2, "planes")
index 04b286f0f5b047e0595b5842ed3cd6b2ca070407..507c1586947b7d98941a73adcf53540c4936ad53 100644 (file)
@@ -81,6 +81,8 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
    const unsigned nr = MAX2( shader->base.info.num_inputs,
                              shader->base.info.num_outputs + 1 );
 
+   unsigned i;
+
    fpme->input_prim = in_prim;
    fpme->opt = opt;
 
@@ -138,7 +140,6 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
    }
    else {
       /* Need to create new variant */
-      unsigned i;
 
       /* First check if we've created too many variants.  If so, free
        * 25% of the LRU to avoid using too much memory.
@@ -171,11 +172,14 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
 
    fpme->current_variant = variant;
 
-   /*XXX we only support one constant buffer */
-   fpme->llvm->jit_context.vs_constants =
-      draw->pt.user.vs_constants[0];
-   fpme->llvm->jit_context.gs_constants =
-      draw->pt.user.gs_constants[0];
+   for (i = 0; i < Elements(fpme->llvm->jit_context.vs_constants); ++i) {
+      fpme->llvm->jit_context.vs_constants[i] =
+         draw->pt.user.vs_constants[i];
+   }
+   for (i = 0; i < Elements(fpme->llvm->jit_context.gs_constants); ++i) {
+      fpme->llvm->jit_context.gs_constants[i] =
+         draw->pt.user.gs_constants[i];
+   }
    fpme->llvm->jit_context.planes =
       (float (*) [DRAW_TOTAL_CLIP_PLANES][4]) draw->pt.user.planes[0];
    fpme->llvm->jit_context.viewport =
index 905070e7ae8cd7cda45567445ba74bd2241241e4..30bed1ba31fd293792f69c426075b8d3a7a5def1 100644 (file)
@@ -51,6 +51,9 @@
 
 #define LP_MAX_TGSI_PREDS 16
 
+#define LP_MAX_TGSI_CONST_BUFFERS 16
+
+
 /**
  * Maximum control flow nesting
  *
index cdc784cf0df356d6e87d7fcffc4f3deee85582a5..9caac21fd9bac2d7e5a9eaf13f77e9baf851fd3f 100644 (file)
@@ -63,6 +63,7 @@
 #include "lp_bld_debug.h"
 #include "lp_bld_printf.h"
 #include "lp_bld_sample.h"
+#include "lp_bld_struct.h"
 
 
 static void lp_exec_mask_init(struct lp_exec_mask *mask, struct lp_build_context *bld)
@@ -588,10 +589,22 @@ emit_fetch_constant(
    struct lp_build_context *uint_bld = &bld_base->uint_bld;
    LLVMValueRef indirect_index = NULL;
    struct lp_build_context *bld_fetch = stype_to_fetch(bld_base, stype);
-   
+   unsigned dimension = 0;
+   LLVMValueRef dimension_index;
+   LLVMValueRef consts_ptr;
+
    /* XXX: Handle fetching xyzw components as a vector */
    assert(swizzle != ~0);
 
+   if (reg->Register.Dimension) {
+      assert(!reg->Dimension.Indirect);
+      dimension = reg->Dimension.Index;
+      assert(dimension < LP_MAX_TGSI_CONST_BUFFERS);
+   }
+
+   dimension_index = lp_build_const_int32(gallivm, dimension);
+   consts_ptr = lp_build_array_get(gallivm, bld->consts_ptr, dimension_index);
+
    if (reg->Register.Indirect) {
       indirect_index = get_indirect_index(bld,
                                           reg->Register.File,
@@ -609,7 +622,7 @@ emit_fetch_constant(
       index_vec = lp_build_add(uint_bld, index_vec, swizzle_vec);
 
       /* Gather values from the constant buffer */
-      return build_gather(bld_fetch, bld->consts_ptr, index_vec);
+      return build_gather(bld_fetch, consts_ptr, index_vec);
    }
    else {
       LLVMValueRef index;  /* index into the const buffer */
@@ -617,7 +630,7 @@ emit_fetch_constant(
 
       index = lp_build_const_int32(gallivm, reg->Register.Index*4 + swizzle);
 
-      scalar_ptr = LLVMBuildGEP(builder, bld->consts_ptr,
+      scalar_ptr = LLVMBuildGEP(builder, consts_ptr,
                                    &index, 1, "");
 
       if (stype != TGSI_TYPE_FLOAT && stype != TGSI_TYPE_UNTYPED) {
index 25cdff998c4e484f7e5a60fdbff185a753cb5371..5afa4360aae43438901a018ad361c413c37a1bd3 100644 (file)
@@ -72,7 +72,7 @@ struct llvmpipe_context {
    struct pipe_blend_color blend_color;
    struct pipe_stencil_ref stencil_ref;
    struct pipe_clip_state clip;
-   struct pipe_resource *constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
+   struct pipe_resource *constants[PIPE_SHADER_TYPES][LP_MAX_TGSI_CONST_BUFFERS];
    struct pipe_framebuffer_state framebuffer;
    struct pipe_poly_stipple poly_stipple;
    struct pipe_scissor_state scissor;
index 2667aeb24e6e0145031a552a6d7b4f9fca32c7df..ea7c8054bfa8108712a511a6d0d62722ffdaa946 100644 (file)
@@ -124,7 +124,8 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp)
       LLVMTypeRef elem_types[LP_JIT_CTX_COUNT];
       LLVMTypeRef context_type;
 
-      elem_types[LP_JIT_CTX_CONSTANTS] = LLVMPointerType(LLVMFloatTypeInContext(lc), 0);
+      elem_types[LP_JIT_CTX_CONSTANTS] =
+            LLVMArrayType(LLVMPointerType(LLVMFloatTypeInContext(lc), 0), LP_MAX_TGSI_CONST_BUFFERS);
       elem_types[LP_JIT_CTX_ALPHA_REF] = LLVMFloatTypeInContext(lc);
       elem_types[LP_JIT_CTX_STENCIL_REF_FRONT] =
       elem_types[LP_JIT_CTX_STENCIL_REF_BACK] = LLVMInt32TypeInContext(lc);
index b46990746560a8a1fb34d2cfe879c7fcc7a9d1e5..5dc5bc4c4bf34b2d931737e5e26fd118940aa1f5 100644 (file)
@@ -37,6 +37,7 @@
 
 
 #include "gallivm/lp_bld_struct.h"
+#include "gallivm/lp_bld_limits.h"
 
 #include "pipe/p_state.h"
 #include "lp_texture.h"
@@ -97,7 +98,7 @@ enum {
  */
 struct lp_jit_context
 {
-   const float *constants;
+   const float *constants[LP_MAX_TGSI_CONST_BUFFERS];
 
    float alpha_ref_value;
 
@@ -127,7 +128,7 @@ enum {
 
 
 #define lp_jit_context_constants(_gallivm, _ptr) \
-   lp_build_struct_get(_gallivm, _ptr, LP_JIT_CTX_CONSTANTS, "constants")
+   lp_build_struct_get_ptr(_gallivm, _ptr, LP_JIT_CTX_CONSTANTS, "constants")
 
 #define lp_jit_context_alpha_ref_value(_gallivm, _ptr) \
    lp_build_struct_get(_gallivm, _ptr, LP_JIT_CTX_ALPHA_REF, "alpha_ref_value")
index 0f497afac53c2422d93178961deb8b60ebe5eb34..7d40d8cf6617e3988ed2ddbafbc3e9aa0bee3d79 100644 (file)
@@ -120,11 +120,15 @@ first_point( struct lp_setup_context *setup,
 
 void lp_setup_reset( struct lp_setup_context *setup )
 {
+   unsigned i;
+
    LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
 
    /* Reset derived state */
-   setup->constants.stored_size = 0;
-   setup->constants.stored_data = NULL;
+   for (i = 0; i < Elements(setup->constants); ++i) {
+      setup->constants[i].stored_size = 0;
+      setup->constants[i].stored_data = NULL;
+   }
    setup->fs.stored = NULL;
    setup->dirty = ~0;
 
@@ -549,13 +553,21 @@ lp_setup_set_fs_variant( struct lp_setup_context *setup,
 
 void
 lp_setup_set_fs_constants(struct lp_setup_context *setup,
-                          struct pipe_resource *buffer)
+                          unsigned num,
+                          struct pipe_resource **buffers)
 {
-   LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffer);
+   unsigned i;
+
+   LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffers);
 
-   pipe_resource_reference(&setup->constants.current, buffer);
+   assert(num <= Elements(setup->constants));
 
-   setup->dirty |= LP_SETUP_NEW_CONSTANTS;
+   for (i = 0; i < num; ++i) {
+      if (setup->constants[i].current != buffers[i]) {
+         pipe_resource_reference(&setup->constants[i].current, buffers[i]);
+         setup->dirty |= LP_SETUP_NEW_CONSTANTS;
+      }
+   }
 }
 
 
@@ -820,6 +832,7 @@ try_update_scene_state( struct lp_setup_context *setup )
 {
    boolean new_scene = (setup->fs.stored == NULL);
    struct lp_scene *scene = setup->scene;
+   unsigned i;
 
    assert(scene);
 
@@ -858,42 +871,44 @@ try_update_scene_state( struct lp_setup_context *setup )
       setup->dirty |= LP_SETUP_NEW_FS;
    }
 
-   if(setup->dirty & LP_SETUP_NEW_CONSTANTS) {
-      struct pipe_resource *buffer = setup->constants.current;
+   if (setup->dirty & LP_SETUP_NEW_CONSTANTS) {
+      for (i = 0; i < Elements(setup->constants); ++i) {
+         struct pipe_resource *buffer = setup->constants[i].current;
 
-      if(buffer) {
-         unsigned current_size = buffer->width0;
-         const void *current_data = llvmpipe_resource_data(buffer);
+         if (buffer) {
+            unsigned current_size = buffer->width0;
+            const void *current_data = llvmpipe_resource_data(buffer);
 
-         /* TODO: copy only the actually used constants? */
+            /* TODO: copy only the actually used constants? */
 
-         if(setup->constants.stored_size != current_size ||
-            !setup->constants.stored_data ||
-            memcmp(setup->constants.stored_data,
-                   current_data,
-                   current_size) != 0) {
-            void *stored;
+            if (setup->constants[i].stored_size != current_size ||
+               !setup->constants[i].stored_data ||
+               memcmp(setup->constants[i].stored_data,
+                      current_data,
+                      current_size) != 0) {
+               void *stored;
 
-            stored = lp_scene_alloc(scene, current_size);
-            if (!stored) {
-               assert(!new_scene);
-               return FALSE;
-            }
+               stored = lp_scene_alloc(scene, current_size);
+               if (!stored) {
+                  assert(!new_scene);
+                  return FALSE;
+               }
 
-            memcpy(stored,
-                   current_data,
-                   current_size);
-            setup->constants.stored_size = current_size;
-            setup->constants.stored_data = stored;
+               memcpy(stored,
+                      current_data,
+                      current_size);
+               setup->constants[i].stored_size = current_size;
+               setup->constants[i].stored_data = stored;
+            }
+         }
+         else {
+            setup->constants[i].stored_size = 0;
+            setup->constants[i].stored_data = NULL;
          }
-      }
-      else {
-         setup->constants.stored_size = 0;
-         setup->constants.stored_data = NULL;
-      }
 
-      setup->fs.current.jit_context.constants = setup->constants.stored_data;
-      setup->dirty |= LP_SETUP_NEW_FS;
+         setup->fs.current.jit_context.constants[i] = setup->constants[i].stored_data;
+         setup->dirty |= LP_SETUP_NEW_FS;
+      }
    }
 
 
@@ -904,7 +919,6 @@ try_update_scene_state( struct lp_setup_context *setup )
                  sizeof setup->fs.current) != 0)
       {
          struct lp_rast_state *stored;
-         uint i;
          
          /* The fs state that's been stored in the scene is different from
           * the new, current state.  So allocate a new lp_rast_state object
@@ -1039,7 +1053,9 @@ lp_setup_destroy( struct lp_setup_context *setup )
       pipe_resource_reference(&setup->fs.current_tex[i], NULL);
    }
 
-   pipe_resource_reference(&setup->constants.current, NULL);
+   for (i = 0; i < Elements(setup->constants); i++) {
+      pipe_resource_reference(&setup->constants[i].current, NULL);
+   }
 
    /* free the scenes in the 'empty' queue */
    for (i = 0; i < Elements(setup->scenes); i++) {
index c3dde8040029a982b409fcdbb1244b877c5a2f20..55fbd9be8b829505cddae60f786f57c2adc9b7aa 100644 (file)
@@ -100,7 +100,8 @@ lp_setup_set_fs_variant( struct lp_setup_context *setup,
 
 void
 lp_setup_set_fs_constants(struct lp_setup_context *setup,
-                          struct pipe_resource *buffer);
+                          unsigned num,
+                          struct pipe_resource **buffers);
 
 
 void
index f810700ef296c3fd113b613cb2e52573f0c56457..60809db50a2fa2432db38bc5eb66364a39271819 100644 (file)
@@ -131,7 +131,7 @@ struct lp_setup_context
       struct pipe_resource *current;
       unsigned stored_size;
       const void *stored_data;
-   } constants;
+   } constants[LP_MAX_TGSI_CONST_BUFFERS];
 
    struct {
       struct pipe_blend_color current;
index 3b826de80c97d080eeef92f96ecfea7254d7f0e5..aef222d20f63f1bbffe27e41a2d2e7a7fc346257 100644 (file)
@@ -174,8 +174,9 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
    }
 
    if (llvmpipe->dirty & LP_NEW_CONSTANTS)
-      lp_setup_set_fs_constants(llvmpipe->setup, 
-                                llvmpipe->constants[PIPE_SHADER_FRAGMENT][0]);
+      lp_setup_set_fs_constants(llvmpipe->setup,
+                                Elements(llvmpipe->constants[PIPE_SHADER_FRAGMENT]),
+                                llvmpipe->constants[PIPE_SHADER_FRAGMENT]);
 
    if (llvmpipe->dirty & (LP_NEW_SAMPLER_VIEW))
       lp_setup_set_fragment_sampler_views(llvmpipe->setup,
index f89f9525eeedc61e325ad5b487a29d5702d60289..dced5d25a7fc5583241437745af2270dd1b25365 100644 (file)
@@ -2422,7 +2422,7 @@ llvmpipe_set_constant_buffer(struct pipe_context *pipe,
    data = constants ? llvmpipe_resource_data(constants) : NULL;
 
    assert(shader < PIPE_SHADER_TYPES);
-   assert(index < PIPE_MAX_CONSTANT_BUFFERS);
+   assert(index < Elements(llvmpipe->constants[shader]));
 
    if(llvmpipe->constants[shader][index] == constants)
       return;