Merge branch 'gallium-userbuf'
authorMarek Olšák <maraeo@gmail.com>
Fri, 11 May 2012 14:38:13 +0000 (16:38 +0200)
committerMarek Olšák <maraeo@gmail.com>
Fri, 11 May 2012 14:38:13 +0000 (16:38 +0200)
Conflicts:
src/gallium/docs/source/screen.rst
src/gallium/drivers/nv50/nv50_state.c
src/gallium/include/pipe/p_defines.h
src/mesa/state_tracker/st_draw.c

20 files changed:
1  2 
src/gallium/docs/source/screen.rst
src/gallium/drivers/llvmpipe/lp_state_fs.c
src/gallium/drivers/nouveau/nouveau_buffer.c
src/gallium/drivers/nv50/nv50_screen.c
src/gallium/drivers/nv50/nv50_state.c
src/gallium/drivers/r600/evergreen_state.c
src/gallium/drivers/r600/r600_pipe.h
src/gallium/drivers/r600/r600_state.c
src/gallium/drivers/r600/r600_state_common.c
src/gallium/drivers/radeonsi/evergreen_state.c
src/gallium/drivers/radeonsi/r600_state_common.c
src/gallium/drivers/radeonsi/radeonsi_pipe.h
src/gallium/drivers/svga/svga_screen.c
src/gallium/include/pipe/p_context.h
src/gallium/include/pipe/p_defines.h
src/gallium/include/pipe/p_state.h
src/mesa/state_tracker/st_context.c
src/mesa/state_tracker/st_context.h
src/mesa/state_tracker/st_draw.c
src/mesa/state_tracker/st_draw_feedback.c

index d912dc6d81d15a0e2b8fb609b670807f44d30739,f6c6f3fd119e69580f10037d308b4f3ef2008f64..ff63ce83beab003853ebf4622e5198012f396918
@@@ -110,8 -110,15 +110,17 @@@ The integer capabilities
  * ``PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY``: This CAP describes
    a hw limitation.  If true, pipe_vertex_element::src_offset must always be
    aligned to 4.  If false, there are no restrictions on src_offset.
 +* ``PIPE_CAP_COMPUTE``: Whether the implementation supports the
 +  compute entry points defined in pipe_context and pipe_screen.
+ * ``PIPE_CAP_USER_INDEX_BUFFERS``: Whether user index buffers are supported.
+   If not, the state tracker must upload all indices which are not in hw
+   resources.
+ * ``PIPE_CAP_USER_CONSTANT_BUFFERS``: Whether user constant buffers are
+   supported. If not, the state tracker must upload constants which are not in hw
+   resources.
+ * ``PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT``: Describes the required
+   alignment of pipe_constant_buffer::buffer_offset.
  
  
  .. _pipe_capf:
@@@ -185,33 -192,8 +194,33 @@@ to be 0
    If unsupported, only float opcodes are supported.
  * ``PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS``: THe maximum number of texture
    samplers.
 +* ``PIPE_SHADER_CAP_PREFERRED_IR``: Preferred representation of the
 +  program.  It should be one of the ``pipe_shader_ir`` enum values.
  
  
 +.. _pipe_compute_cap:
 +
 +PIPE_COMPUTE_CAP_*
 +^^^^^^^^^^^^^^^^^^
 +
 +Compute-specific capabilities. They can be queried using
 +pipe_screen::get_compute_param.
 +
 +* ``PIPE_COMPUTE_CAP_GRID_DIMENSION``: Number of supported dimensions
 +  for grid and block coordinates.  Value type: ``uint64_t``.
 +* ``PIPE_COMPUTE_CAP_MAX_GRID_SIZE``: Maximum grid size in block
 +  units.  Value type: ``uint64_t []``.
 +* ``PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE``: Maximum block size in thread
 +  units.  Value type: ``uint64_t []``.
 +* ``PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE``: Maximum size of the GLOBAL
 +  resource.  Value type: ``uint64_t``.
 +* ``PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE``: Maximum size of the LOCAL
 +  resource.  Value type: ``uint64_t``.
 +* ``PIPE_COMPUTE_CAP_MAX_PRIVATE_SIZE``: Maximum size of the PRIVATE
 +  resource.  Value type: ``uint64_t``.
 +* ``PIPE_COMPUTE_CAP_MAX_INPUT_SIZE``: Maximum size of the INPUT
 +  resource.  Value type: ``uint64_t``.
 +
  .. _pipe_bind:
  
  PIPE_BIND_*
@@@ -249,12 -231,6 +258,12 @@@ resources might be created and handled 
  * ``PIPE_BIND_SCANOUT``: A front color buffer or scanout buffer.
  * ``PIPE_BIND_SHARED``: A sharable buffer that can be given to another
    process.
 +* ``PIPE_BIND_GLOBAL``: A buffer that can be mapped into the global
 +  address space of a compute program.
 +* ``PIPE_BIND_SHADER_RESOURCE``: A buffer or texture that can be
 +  bound to the graphics pipeline as a shader resource.
 +* ``PIPE_BIND_COMPUTE_RESOURCE``: A buffer or texture that can be
 +  bound to the compute program as a shader resource.
  
  .. _pipe_usage:
  
index 582c6db15d50d486a683a451cf6cb60c9544dc43,ec94190649c36cfeb14967cabe5b8bb63f8cf5af..2d2391e908c5ec98e2d876245ffec6734a710c04
@@@ -924,7 -924,6 +924,7 @@@ generate_variant(struct llvmpipe_contex
                   const struct lp_fragment_shader_variant_key *key)
  {
     struct lp_fragment_shader_variant *variant;
 +   const struct util_format_description *cbuf0_format_desc;
     boolean fullcolormask;
  
     variant = CALLOC_STRUCT(lp_fragment_shader_variant);
      */
     fullcolormask = FALSE;
     if (key->nr_cbufs == 1) {
 -      const struct util_format_description *format_desc;
 -      format_desc = util_format_description(key->cbuf_format[0]);
 -      if ((~key->blend.rt[0].colormask &
 -           util_format_colormask(format_desc)) == 0) {
 -         fullcolormask = TRUE;
 -      }
 +      cbuf0_format_desc = util_format_description(key->cbuf_format[0]);
 +      fullcolormask = util_format_colormask_full(cbuf0_format_desc, key->blend.rt[0].colormask);
     }
  
     variant->opaque =
@@@ -1166,11 -1169,21 +1166,21 @@@ llvmpipe_delete_fs_state(struct pipe_co
  static void
  llvmpipe_set_constant_buffer(struct pipe_context *pipe,
                               uint shader, uint index,
-                              struct pipe_resource *constants)
+                              struct pipe_constant_buffer *cb)
  {
     struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
-    unsigned size = constants ? constants->width0 : 0;
-    const void *data = constants ? llvmpipe_resource_data(constants) : NULL;
+    struct pipe_resource *constants = cb ? cb->buffer : NULL;
+    unsigned size;
+    const void *data;
+    if (cb && cb->user_buffer) {
+       constants = llvmpipe_user_buffer_create(pipe->screen, cb->user_buffer,
+                                               cb->buffer_size,
+                                               PIPE_BIND_CONSTANT_BUFFER);
+    }
+    size = constants ? constants->width0 : 0;
+    data = constants ? llvmpipe_resource_data(constants) : NULL;
  
     assert(shader < PIPE_SHADER_TYPES);
     assert(index < PIPE_MAX_CONSTANT_BUFFERS);
     }
  
     llvmpipe->dirty |= LP_NEW_CONSTANTS;
+    if (cb && cb->user_buffer) {
+       pipe_resource_reference(&constants, NULL);
+    }
  }
  
  
index f6629901c155b139c5c1892b7856d11aef88df1f,ff199debd7445238efb8ae863acf3b884ba2f8b8..936e2bf246ace722d4faf2117e5117785de02fb9
@@@ -398,7 -398,6 +398,6 @@@ nouveau_user_buffer_create(struct pipe_
     buffer->base.width0 = bytes;
     buffer->base.height0 = 1;
     buffer->base.depth0 = 1;
-    buffer->base.user_ptr = ptr;
  
     buffer->data = ptr;
     buffer->status = NOUVEAU_BUFFER_STATUS_USER_MEMORY;
@@@ -524,10 -523,8 +523,10 @@@ nouveau_scratch_runout_release(struct n
  {
     if (!nv->scratch.nr_runout)
        return;
 -   while (nv->scratch.nr_runout--)
 +   do {
 +      --nv->scratch.nr_runout;
        nouveau_bo_ref(NULL, &nv->scratch.runout[nv->scratch.nr_runout]);
 +   } while (nv->scratch.nr_runout);
  
     FREE(nv->scratch.runout);
     nv->scratch.end = 0;
index b341ade695e6c3b8cc2ace76961da2a78a7d45f0,a6dfbedf299a6c6f031b0caf5b641847876c689c..c96e028b2a2677fcc2126459ace0f45920c487d5
@@@ -73,8 -73,6 +73,8 @@@ nv50_screen_is_format_supported(struct 
  static int
  nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
  {
 +   const uint16_t class_3d = nouveau_screen(pscreen)->class_3d;
 +
     switch (param) {
     case PIPE_CAP_MAX_COMBINED_SAMPLERS:
        return 64;
@@@ -84,8 -82,8 +84,8 @@@
        return 12;
     case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
        return 14;
 -   case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: /* shader support missing */
 -      return 0;
 +   case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
 +      return 512;
     case PIPE_CAP_MIN_TEXEL_OFFSET:
        return -8;
     case PIPE_CAP_MAX_TEXEL_OFFSET:
@@@ -97,6 -95,7 +97,6 @@@
     case PIPE_CAP_ANISOTROPIC_FILTER:
     case PIPE_CAP_SCALED_RESOLVE:
        return 1;
 -   case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
     case PIPE_CAP_SEAMLESS_CUBE_MAP:
        return nv50_screen(pscreen)->tesla->oclass >= NVA0_3D_CLASS;
     case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
     case PIPE_CAP_OCCLUSION_QUERY:
        return 1;
     case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
 -      return 0;
 +      return 4;
     case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
 -      return 128;
     case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
 -      return 32;
 +      return 64;
 +   case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
 +      return (class_3d >= NVA0_3D_CLASS) ? 1 : 0;
     case PIPE_CAP_BLEND_EQUATION_SEPARATE:
     case PIPE_CAP_INDEP_BLEND_ENABLE:
        return 1;
        return 1;
     case PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS:
     case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
-       return 0; /* state trackers will know better */
     case PIPE_CAP_USER_VERTEX_BUFFERS:
+    case PIPE_CAP_USER_INDEX_BUFFERS:
+       return 0; /* state trackers will know better */
+    case PIPE_CAP_USER_CONSTANT_BUFFERS:
        return 1;
+    case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
+       return 256;
     case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
     case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
     case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
index 5e32b2717fd80f9f964cebb280f0b2e2ad54f2af,a17540a1492032db7e00db222043e8c089c41f20..7f840e2b42e1ef45f633b121167d4e3cdd37a9b5
@@@ -680,9 -680,6 +680,9 @@@ nv50_sp_state_create(struct pipe_contex
     prog->type = type;
     prog->pipe.tokens = tgsi_dup_tokens(cso->tokens);
  
 +   if (cso->stream_output.num_outputs)
 +      prog->pipe.stream_output = cso->stream_output;
 +
     return (void *)prog;
  }
  
@@@ -747,9 -744,16 +747,16 @@@ nv50_gp_state_bind(struct pipe_context 
  
  static void
  nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
-                          struct pipe_resource *res)
+                          struct pipe_constant_buffer *cb)
  {
     struct nv50_context *nv50 = nv50_context(pipe);
+    struct pipe_resource *res = cb ? cb->buffer : NULL;
+    if (cb && cb->user_buffer) {
+       res = nouveau_user_buffer_create(pipe->screen, cb->user_buffer,
+                                        cb->buffer_size,
+                                        PIPE_BIND_CONSTANT_BUFFER);
+    }
  
     pipe_resource_reference(&nv50->constbuf[shader][index], res);
  
     nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_CB(shader, index));
  
     nv50->dirty |= NV50_NEW_CONSTBUF;
+    if (cb && cb->user_buffer) {
+       pipe_resource_reference(&res, NULL);
+    }
  }
  
  /* =============================================================================
@@@ -912,90 -920,6 +923,90 @@@ nv50_vertex_state_bind(struct pipe_cont
     nv50->dirty |= NV50_NEW_VERTEX;
  }
  
 +static struct pipe_stream_output_target *
 +nv50_so_target_create(struct pipe_context *pipe,
 +                      struct pipe_resource *res,
 +                      unsigned offset, unsigned size)
 +{
 +   struct nv50_so_target *targ = MALLOC_STRUCT(nv50_so_target);
 +   if (!targ)
 +      return NULL;
 +
 +   if (nouveau_context(pipe)->screen->class_3d >= NVA0_3D_CLASS) {
 +      targ->pq = pipe->create_query(pipe,
 +                                    NVA0_QUERY_STREAM_OUTPUT_BUFFER_OFFSET);
 +      if (!targ->pq) {
 +         FREE(targ);
 +         return NULL;
 +      }
 +   } else {
 +      targ->pq = NULL;
 +   }
 +   targ->clean = TRUE;
 +
 +   targ->pipe.buffer_size = size;
 +   targ->pipe.buffer_offset = offset;
 +   targ->pipe.context = pipe;
 +   targ->pipe.buffer = NULL;
 +   pipe_resource_reference(&targ->pipe.buffer, res);
 +   pipe_reference_init(&targ->pipe.reference, 1);
 +
 +   return &targ->pipe;
 +}
 +
 +static void
 +nv50_so_target_destroy(struct pipe_context *pipe,
 +                       struct pipe_stream_output_target *ptarg)
 +{
 +   struct nv50_so_target *targ = nv50_so_target(ptarg);
 +   if (targ->pq)
 +      pipe->destroy_query(pipe, targ->pq);
 +   FREE(targ);
 +}
 +
 +static void
 +nv50_set_stream_output_targets(struct pipe_context *pipe,
 +                               unsigned num_targets,
 +                               struct pipe_stream_output_target **targets,
 +                               unsigned append_mask)
 +{
 +   struct nv50_context *nv50 = nv50_context(pipe);
 +   unsigned i;
 +   boolean serialize = TRUE;
 +   const boolean can_resume = nv50->screen->base.class_3d >= NVA0_3D_CLASS;
 +
 +   assert(num_targets <= 4);
 +
 +   for (i = 0; i < num_targets; ++i) {
 +      const boolean changed = nv50->so_target[i] != targets[i];
 +      if (!changed && (append_mask & (1 << i)))
 +         continue;
 +      nv50->so_targets_dirty |= 1 << i;
 +
 +      if (can_resume && changed && nv50->so_target[i]) {
 +         nva0_so_target_save_offset(pipe, nv50->so_target[i], i, serialize);
 +         serialize = FALSE;
 +      }
 +
 +      if (targets[i] && !(append_mask & (1 << i)))
 +         nv50_so_target(targets[i])->clean = TRUE;
 +
 +      pipe_so_target_reference(&nv50->so_target[i], targets[i]);
 +   }
 +   for (; i < nv50->num_so_targets; ++i) {
 +      if (can_resume && nv50->so_target[i]) {
 +         nva0_so_target_save_offset(pipe, nv50->so_target[i], i, serialize);
 +         serialize = FALSE;
 +      }
 +      pipe_so_target_reference(&nv50->so_target[i], NULL);
 +      nv50->so_targets_dirty |= 1 << i;
 +   }
 +   nv50->num_so_targets = num_targets;
 +
 +   if (nv50->so_targets_dirty)
 +      nv50->dirty |= NV50_NEW_STRMOUT;
 +}
 +
  void
  nv50_init_state_functions(struct nv50_context *nv50)
  {
  
     pipe->set_vertex_buffers = nv50_set_vertex_buffers;
     pipe->set_index_buffer = nv50_set_index_buffer;
 -}
  
-    pipe->redefine_user_buffer = u_default_redefine_user_buffer;
 +   pipe->create_stream_output_target = nv50_so_target_create;
 +   pipe->stream_output_target_destroy = nv50_so_target_destroy;
 +   pipe->set_stream_output_targets = nv50_set_stream_output_targets;
 +}
index 82313ea60319ae4636589b06b1f68224bfe8923b,517121dc28808baf420dc569ca0a0b7913162bab..81aedb5c0ac21cb25b7cdcfba000609012eb6b54
@@@ -796,11 -796,11 +796,11 @@@ static void *evergreen_create_dsa_state
                alpha_test_control |= S_028410_ALPHA_TEST_ENABLE(1);
                alpha_ref = fui(state->alpha.ref_value);
        }
 +      dsa->sx_alpha_test_control = alpha_test_control & 0xff;
        dsa->alpha_ref = alpha_ref;
  
        /* misc */
        db_render_control = 0;
 -      r600_pipe_state_add_reg(rstate, R_028410_SX_ALPHA_TEST_CONTROL, alpha_test_control);
        r600_pipe_state_add_reg(rstate, R_028800_DB_DEPTH_CONTROL, db_depth_control);
        r600_pipe_state_add_reg(rstate, R_028000_DB_RENDER_CONTROL, db_render_control);
        return rstate;
@@@ -1177,7 -1177,7 +1177,7 @@@ static void evergreen_set_clip_state(st
  {
        struct r600_context *rctx = (struct r600_context *)ctx;
        struct r600_pipe_state *rstate = CALLOC_STRUCT(r600_pipe_state);
-       struct pipe_resource *cbuf;
+       struct pipe_constant_buffer cb;
  
        if (rstate == NULL)
                return;
        rctx->states[R600_PIPE_STATE_CLIP] = rstate;
        r600_context_pipe_state_set(rctx, rstate);
  
-       cbuf = pipe_user_buffer_create(ctx->screen,
-                                    state->ucp,
-                                    4*4*8, /* 8*4 floats */
-                                    PIPE_BIND_CONSTANT_BUFFER);
-       r600_set_constant_buffer(ctx, PIPE_SHADER_VERTEX, 1, cbuf);
-       pipe_resource_reference(&cbuf, NULL);
+       cb.buffer = NULL;
+       cb.user_buffer = state->ucp;
+       cb.buffer_offset = 0;
+       cb.buffer_size = 4*4*8;
+       r600_set_constant_buffer(ctx, PIPE_SHADER_VERTEX, 1, &cb);
+       pipe_resource_reference(&cb.buffer, NULL);
  }
  
  static void evergreen_set_polygon_stipple(struct pipe_context *ctx,
@@@ -1428,11 -1428,6 +1428,11 @@@ static void evergreen_cb(struct r600_co
                blend_bypass = 1;
        }
  
 +      if (ntype == V_028C70_NUMBER_UINT || ntype == V_028C70_NUMBER_SINT)
 +              rctx->sx_alpha_test_control |= S_028410_ALPHA_TEST_BYPASS(1);
 +      else
 +              rctx->sx_alpha_test_control &= C_028410_ALPHA_TEST_BYPASS;
 +
        color_info |= S_028C70_FORMAT(format) |
                S_028C70_COMP_SWAP(swap) |
                S_028C70_BLEND_CLAMP(blend_clamp) |
@@@ -1767,7 -1762,7 +1767,7 @@@ static void evergreen_emit_constant_buf
        uint32_t dirty_mask = state->dirty_mask;
  
        while (dirty_mask) {
-               struct r600_constant_buffer *cb;
+               struct pipe_constant_buffer *cb;
                struct r600_resource *rbuffer;
                uint64_t va;
                unsigned buffer_index = ffs(dirty_mask) - 1;
@@@ -1871,7 -1866,6 +1871,6 @@@ void evergreen_init_state_functions(str
        rctx->context.set_vertex_sampler_views = evergreen_set_vs_sampler_view;
        rctx->context.set_viewport_state = evergreen_set_viewport_state;
        rctx->context.sampler_view_destroy = r600_sampler_view_destroy;
-       rctx->context.redefine_user_buffer = u_default_redefine_user_buffer;
        rctx->context.texture_barrier = r600_texture_barrier;
        rctx->context.create_stream_output_target = r600_create_so_target;
        rctx->context.stream_output_target_destroy = r600_so_target_destroy;
index 3a5f5509b62bbaeac565e0d6117130557ba24def,63fc27564d7454e510934588361e88fd4eb75ebc..db455f021ad9951e92b35cddff8f8c6650284328
@@@ -161,7 -161,6 +161,7 @@@ struct r600_pipe_dsa 
        ubyte                           valuemask[2];
        ubyte                           writemask[2];
        bool                            is_flush;
 +      unsigned                        sx_alpha_test_control;
  };
  
  struct r600_vertex_element
@@@ -228,17 -227,10 +228,10 @@@ struct r600_stencil_re
        ubyte writemask[2];
  };
  
- struct r600_constant_buffer
- {
-       struct pipe_resource            *buffer;
-       unsigned                        buffer_offset;
-       unsigned                        buffer_size;
- };
  struct r600_constbuf_state
  {
        struct r600_atom                atom;
-       struct r600_constant_buffer     cb[PIPE_MAX_CONSTANT_BUFFERS];
+       struct pipe_constant_buffer     cb[PIPE_MAX_CONSTANT_BUFFERS];
        uint32_t                        enabled_mask;
        uint32_t                        dirty_mask;
  };
@@@ -258,7 -250,6 +251,7 @@@ struct r600_context 
        struct pipe_framebuffer_state   framebuffer;
        unsigned                        cb_target_mask;
        unsigned                        fb_cb_shader_mask;
 +      unsigned                        sx_alpha_test_control;
        unsigned                        cb_shader_mask;
        unsigned                        cb_color_control;
        unsigned                        pa_sc_line_stipple;
@@@ -498,7 -489,7 +491,7 @@@ void r600_delete_ps_shader(struct pipe_
  void r600_delete_vs_shader(struct pipe_context *ctx, void *state);
  void r600_constant_buffers_dirty(struct r600_context *rctx, struct r600_constbuf_state *state);
  void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
-                             struct pipe_resource *buffer);
+                             struct pipe_constant_buffer *cb);
  struct pipe_stream_output_target *
  r600_create_so_target(struct pipe_context *ctx,
                      struct pipe_resource *buffer,
index 2ad57b27f1057ef3a548dc3d23d6c512781c12fe,3a83b613e587889b18f3ac31d04ad06c73fca178..acf59f80bf49cf80affe97dc000158c64d0df0cd
@@@ -805,9 -805,9 +805,9 @@@ static void *r600_create_dsa_state(stru
                alpha_test_control |= S_028410_ALPHA_TEST_ENABLE(1);
                alpha_ref = fui(state->alpha.ref_value);
        }
 +      dsa->sx_alpha_test_control = alpha_test_control & 0xff;
        dsa->alpha_ref = alpha_ref;
  
 -      r600_pipe_state_add_reg(rstate, R_028410_SX_ALPHA_TEST_CONTROL, alpha_test_control);
        r600_pipe_state_add_reg(rstate, R_028800_DB_DEPTH_CONTROL, db_depth_control);
        return rstate;
  }
@@@ -1260,7 -1260,7 +1260,7 @@@ static void r600_set_clip_state(struct 
  {
        struct r600_context *rctx = (struct r600_context *)ctx;
        struct r600_pipe_state *rstate = CALLOC_STRUCT(r600_pipe_state);
-       struct pipe_resource * cbuf;
+       struct pipe_constant_buffer cb;
  
        if (rstate == NULL)
                return;
        rctx->states[R600_PIPE_STATE_CLIP] = rstate;
        r600_context_pipe_state_set(rctx, rstate);
  
-       cbuf = pipe_user_buffer_create(ctx->screen,
-                                    state->ucp,
-                                    4*4*8, /* 8*4 floats */
-                                    PIPE_BIND_CONSTANT_BUFFER);
-       r600_set_constant_buffer(ctx, PIPE_SHADER_VERTEX, 1, cbuf);
-       pipe_resource_reference(&cbuf, NULL);
+       cb.buffer = NULL;
+       cb.user_buffer = state->ucp;
+       cb.buffer_offset = 0;
+       cb.buffer_size = 4*4*8;
+       r600_set_constant_buffer(ctx, PIPE_SHADER_VERTEX, 1, &cb);
+       pipe_resource_reference(&cb.buffer, NULL);
  }
  
  static void r600_set_polygon_stipple(struct pipe_context *ctx,
@@@ -1466,11 -1466,6 +1466,11 @@@ static void r600_cb(struct r600_contex
                blend_bypass = 1;
        }
  
 +      if (ntype == V_0280A0_NUMBER_UINT || ntype == V_0280A0_NUMBER_SINT)
 +              rctx->sx_alpha_test_control |= S_028410_ALPHA_TEST_BYPASS(1);
 +      else
 +              rctx->sx_alpha_test_control &= C_028410_ALPHA_TEST_BYPASS;
 +
        color_info |= S_0280A0_FORMAT(format) |
                S_0280A0_COMP_SWAP(swap) |
                S_0280A0_BLEND_BYPASS(blend_bypass) |
@@@ -1738,7 -1733,7 +1738,7 @@@ static void r600_emit_constant_buffers(
        uint32_t dirty_mask = state->dirty_mask;
  
        while (dirty_mask) {
-               struct r600_constant_buffer *cb;
+               struct pipe_constant_buffer *cb;
                struct r600_resource *rbuffer;
                unsigned offset;
                unsigned buffer_index = ffs(dirty_mask) - 1;
@@@ -1835,7 -1830,6 +1835,6 @@@ void r600_init_state_functions(struct r
        rctx->context.set_vertex_sampler_views = r600_set_vs_sampler_views;
        rctx->context.set_viewport_state = r600_set_viewport_state;
        rctx->context.sampler_view_destroy = r600_sampler_view_destroy;
-       rctx->context.redefine_user_buffer = u_default_redefine_user_buffer;
        rctx->context.texture_barrier = r600_texture_barrier;
        rctx->context.create_stream_output_target = r600_create_so_target;
        rctx->context.stream_output_target_destroy = r600_so_target_destroy;
index a817831fd8251422ac04d5b3c58c199a7acaf5b8,ccae7d91d43863075b963830f9fa6cee65633e01..d47383558d9b23b8dcd173f311ec0bbf027e786a
@@@ -244,8 -244,6 +244,8 @@@ void r600_bind_dsa_state(struct pipe_co
                return;
        rstate = &dsa->rstate;
        rctx->states[rstate->id] = rstate;
 +      rctx->sx_alpha_test_control &= ~0xff;
 +      rctx->sx_alpha_test_control |= dsa->sx_alpha_test_control;
        rctx->alpha_ref = dsa->alpha_ref;
        rctx->alpha_ref_dirty = true;
        r600_context_pipe_state_set(rctx, rstate);
@@@ -532,12 -530,12 +532,12 @@@ void r600_constant_buffers_dirty(struc
  }
  
  void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
-                             struct pipe_resource *buffer)
+                             struct pipe_constant_buffer *input)
  {
        struct r600_context *rctx = (struct r600_context *)ctx;
        struct r600_constbuf_state *state;
-       struct r600_constant_buffer *cb;
-       uint8_t *ptr;
+       struct pipe_constant_buffer *cb;
+       const uint8_t *ptr;
  
        switch (shader) {
        case PIPE_SHADER_VERTEX:
        /* Note that the state tracker can unbind constant buffers by
         * passing NULL here.
         */
-       if (unlikely(!buffer)) {
+       if (unlikely(!input)) {
                state->enabled_mask &= ~(1 << index);
                state->dirty_mask &= ~(1 << index);
                pipe_resource_reference(&state->cb[index].buffer, NULL);
        }
  
        cb = &state->cb[index];
-       cb->buffer_size = buffer->width0;
+       cb->buffer_size = input->buffer_size;
  
-       ptr = buffer->user_ptr;
+       ptr = input->user_buffer;
  
        if (ptr) {
                /* Upload the user buffer. */
                if (R600_BIG_ENDIAN) {
                        uint32_t *tmpPtr;
-                       unsigned i, size = buffer->width0;
+                       unsigned i, size = input->buffer_size;
  
                        if (!(tmpPtr = malloc(size))) {
                                R600_ERR("Failed to allocate BE swap buffer.\n");
                        u_upload_data(rctx->uploader, 0, size, tmpPtr, &cb->buffer_offset, &cb->buffer);
                        free(tmpPtr);
                } else {
-                       u_upload_data(rctx->uploader, 0, buffer->width0, ptr, &cb->buffer_offset, &cb->buffer);
+                       u_upload_data(rctx->uploader, 0, input->buffer_size, ptr, &cb->buffer_offset, &cb->buffer);
                }
        } else {
                /* Setup the hw buffer. */
-               cb->buffer_offset = 0;
-               pipe_resource_reference(&cb->buffer, buffer);
+               cb->buffer_offset = input->buffer_offset;
+               pipe_resource_reference(&cb->buffer, input->buffer);
        }
  
        state->enabled_mask |= 1 << index;
@@@ -753,7 -751,6 +753,6 @@@ void r600_draw_vbo(struct pipe_context 
        uint8_t *ptr;
  
        if ((!info.count && (info.indexed || !info.count_from_stream_output)) ||
-           (info.indexed && !rctx->index_buffer.buffer) ||
            !r600_conv_pipe_prim(info.mode, &prim)) {
                assert(0);
                return;
        if (info.indexed) {
                /* Initialize the index buffer struct. */
                pipe_resource_reference(&ib.buffer, rctx->index_buffer.buffer);
+               ib.user_buffer = rctx->index_buffer.user_buffer;
                ib.index_size = rctx->index_buffer.index_size;
                ib.offset = rctx->index_buffer.offset + info.start * ib.index_size;
  
                /* Translate or upload, if needed. */
                r600_translate_index_buffer(rctx, &ib, info.count);
  
-               ptr = ib.buffer->user_ptr;
-               if (ptr) {
+               ptr = (uint8_t*)ib.user_buffer;
+               if (!ib.buffer && ptr) {
                        u_upload_data(rctx->uploader, 0, info.count * ib.index_size,
                                      ptr, &ib.offset, &ib.buffer);
                }
                r600_pipe_state_add_reg(&rctx->vgt, R_02823C_CB_SHADER_MASK, 0);
                r600_pipe_state_add_reg(&rctx->vgt, R_028408_VGT_INDX_OFFSET, info.index_bias);
                r600_pipe_state_add_reg(&rctx->vgt, R_02840C_VGT_MULTI_PRIM_IB_RESET_INDX, info.restart_index);
 +              r600_pipe_state_add_reg(&rctx->vgt, R_028410_SX_ALPHA_TEST_CONTROL, 0);
                r600_pipe_state_add_reg(&rctx->vgt, R_028A94_VGT_MULTI_PRIM_IB_RESET_EN, info.primitive_restart);
                r600_pipe_state_add_reg(&rctx->vgt, R_03CFF4_SQ_VTX_START_INST_LOC, info.start_instance);
                r600_pipe_state_add_reg(&rctx->vgt, R_028A0C_PA_SC_LINE_STIPPLE, 0);
        r600_pipe_state_mod_reg(&rctx->vgt, rctx->cb_shader_mask);
        r600_pipe_state_mod_reg(&rctx->vgt, info.index_bias);
        r600_pipe_state_mod_reg(&rctx->vgt, info.restart_index);
 +      r600_pipe_state_mod_reg(&rctx->vgt, rctx->sx_alpha_test_control);
        r600_pipe_state_mod_reg(&rctx->vgt, info.primitive_restart);
        r600_pipe_state_mod_reg(&rctx->vgt, info.start_instance);
  
index 6d345b0679f212de3607a4c2be569d48704a3a6a,75d6cadc6cccab60284f20fd2751ae92d0e8f629..b094248fee181ff2d3bc0ebaf72200558fb98af8
@@@ -1166,6 -1166,24 +1166,6 @@@ static void si_delete_sampler_state(str
        free(state);
  }
  
 -static unsigned si_map_swizzle(unsigned swizzle)
 -{
 -      switch (swizzle) {
 -      case UTIL_FORMAT_SWIZZLE_Y:
 -              return V_008F1C_SQ_SEL_Y;
 -      case UTIL_FORMAT_SWIZZLE_Z:
 -              return V_008F1C_SQ_SEL_Z;
 -      case UTIL_FORMAT_SWIZZLE_W:
 -              return V_008F1C_SQ_SEL_W;
 -      case UTIL_FORMAT_SWIZZLE_0:
 -              return V_008F1C_SQ_SEL_0;
 -      case UTIL_FORMAT_SWIZZLE_1:
 -              return V_008F1C_SQ_SEL_1;
 -      default: /* UTIL_FORMAT_SWIZZLE_X */
 -              return V_008F1C_SQ_SEL_X;
 -      }
 -}
 -
  static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_context *ctx,
                                                        struct pipe_resource *texture,
                                                        const struct pipe_sampler_view *state)
  
        va = r600_resource_va(ctx->screen, texture);
        view->state[0] = (va + tmp->offset[0]) >> 8;
 -      view->state[1] = ((va + tmp->offset[0]) >> 40) & 0xff;
 -      view->state[1] |= (S_008F14_DATA_FORMAT(format) |
 -                         S_008F14_NUM_FORMAT(num_format));
 +      view->state[1] = (S_008F14_BASE_ADDRESS_HI((va + tmp->offset[0]) >> 40) |
 +                        S_008F14_DATA_FORMAT(format) |
 +                        S_008F14_NUM_FORMAT(num_format));
        view->state[2] = (S_008F18_WIDTH(texture->width0 - 1) |
                          S_008F18_HEIGHT(height - 1));
        view->state[3] = (S_008F1C_DST_SEL_X(si_map_swizzle(swizzle[0])) |
@@@ -1807,7 -1825,6 +1807,6 @@@ void cayman_init_state_functions(struc
        rctx->context.set_vertex_sampler_views = evergreen_set_vs_sampler_view;
        rctx->context.set_viewport_state = evergreen_set_viewport_state;
        rctx->context.sampler_view_destroy = r600_sampler_view_destroy;
-       rctx->context.redefine_user_buffer = u_default_redefine_user_buffer;
        rctx->context.texture_barrier = r600_texture_barrier;
        rctx->context.create_stream_output_target = r600_create_so_target;
        rctx->context.stream_output_target_destroy = r600_so_target_destroy;
@@@ -2070,9 -2087,9 +2069,9 @@@ void si_pipe_shader_vs(struct pipe_cont
        r600_pipe_state_add_reg(rstate,
                                R_02870C_SPI_SHADER_POS_FORMAT,
                                S_02870C_POS0_EXPORT_FORMAT(V_02870C_SPI_SHADER_4COMP) |
 -                              S_02870C_POS1_EXPORT_FORMAT(V_02870C_SPI_SHADER_4COMP) |
 -                              S_02870C_POS2_EXPORT_FORMAT(V_02870C_SPI_SHADER_4COMP) |
 -                              S_02870C_POS3_EXPORT_FORMAT(V_02870C_SPI_SHADER_4COMP),
 +                              S_02870C_POS1_EXPORT_FORMAT(V_02870C_SPI_SHADER_NONE) |
 +                              S_02870C_POS2_EXPORT_FORMAT(V_02870C_SPI_SHADER_NONE) |
 +                              S_02870C_POS3_EXPORT_FORMAT(V_02870C_SPI_SHADER_NONE),
                                NULL, 0);
  
        va = r600_resource_va(ctx->screen, (void *)shader->bo);
index 416c89048e6d70d53c51a9aca830fdb12612eb5c,53a34ef519c55146464165506b481b501cea9fa3..06eb96b9ee84c05c56c332f49bf63422d790463a
@@@ -424,10 -424,10 +424,10 @@@ static void r600_update_alpha_ref(struc
  }
  
  void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
-                             struct pipe_resource *buffer)
+                             struct pipe_constant_buffer *cb)
  {
        struct r600_context *rctx = (struct r600_context *)ctx;
-       struct r600_resource *rbuffer = r600_resource(buffer);
+       struct r600_resource *rbuffer = cb ? r600_resource(cb->buffer) : NULL;
        struct r600_pipe_state *rstate;
        uint64_t va_offset;
        uint32_t offset;
        /* Note that the state tracker can unbind constant buffers by
         * passing NULL here.
         */
-       if (buffer == NULL) {
+       if (cb == NULL) {
                return;
        }
  
        r600_inval_shader_cache(rctx);
  
-       r600_upload_const_buffer(rctx, &rbuffer, &offset);
+       if (cb->user_buffer)
+               r600_upload_const_buffer(rctx, &rbuffer, cb->user_buffer, cb->buffer_size, &offset);
+       else
+               offset = 0;
        va_offset = r600_resource_va(ctx->screen, (void*)rbuffer);
        va_offset += offset;
        //va_offset >>= 8;
  
        r600_context_pipe_state_set(rctx, rstate);
  
-       if (buffer != &rbuffer->b.b)
+       if (cb->buffer != &rbuffer->b.b)
                pipe_resource_reference((struct pipe_resource**)&rbuffer, NULL);
  }
  
@@@ -625,15 -628,12 +628,15 @@@ static void r600_vertex_buffer_update(s
                ptr[0] = va & 0xFFFFFFFF;
                ptr[1] = (S_008F04_BASE_ADDRESS_HI(va >> 32) |
                          S_008F04_STRIDE(vertex_buffer->stride));
 -              ptr[2] = (vertex_buffer->buffer->width0 - offset) / vertex_buffer->stride;
 -              /* XXX: Hardcoding RGBA */
 -              ptr[3] = (S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) |
 -                        S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) |
 -                        S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) |
 -                        S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) |
 +              if (vertex_buffer->stride > 0)
 +                      ptr[2] = ((vertex_buffer->buffer->width0 - offset) /
 +                                vertex_buffer->stride);
 +              else
 +                      ptr[2] = vertex_buffer->buffer->width0 - offset;
 +              ptr[3] = (S_008F0C_DST_SEL_X(si_map_swizzle(desc->swizzle[0])) |
 +                        S_008F0C_DST_SEL_Y(si_map_swizzle(desc->swizzle[1])) |
 +                        S_008F0C_DST_SEL_Z(si_map_swizzle(desc->swizzle[2])) |
 +                        S_008F0C_DST_SEL_W(si_map_swizzle(desc->swizzle[3])) |
                          S_008F0C_NUM_FORMAT(num_format) |
                          S_008F0C_DATA_FORMAT(data_format));
  
@@@ -734,7 -734,7 +737,7 @@@ void r600_draw_vbo(struct pipe_context 
                /* Translate or upload, if needed. */
                r600_translate_index_buffer(rctx, &ib, info.count);
  
-               if (ib.buffer->user_ptr) {
+               if (ib.user_buffer) {
                        r600_upload_index_buffer(rctx, &ib, info.count);
                }
  
index 3077f068017146a8effaba2f56a54ae54e3531ab,ab30892d51a31238922f32d20332ff22c8e79717..bba4cf2369142ddcf39904643051ee02096cc3c6
@@@ -37,7 -37,6 +37,7 @@@
  #include "r600.h"
  #include "radeonsi_public.h"
  #include "r600_resource.h"
 +#include "sid.h"
  
  #define R600_MAX_CONST_BUFFERS 1
  #define R600_MAX_CONST_BUFFER_SIZE 4096
@@@ -443,7 -442,7 +443,7 @@@ void r600_bind_vs_shader(struct pipe_co
  void r600_delete_ps_shader(struct pipe_context *ctx, void *state);
  void r600_delete_vs_shader(struct pipe_context *ctx, void *state);
  void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
-                             struct pipe_resource *buffer);
+                             struct pipe_constant_buffer *cb);
  struct pipe_stream_output_target *
  r600_create_so_target(struct pipe_context *ctx,
                      struct pipe_resource *buffer,
@@@ -468,24 -467,6 +468,24 @@@ static INLINE uint32_t S_FIXED(float va
  }
  #define ALIGN_DIVUP(x, y) (((x) + (y) - 1) / (y))
  
 +static INLINE unsigned si_map_swizzle(unsigned swizzle)
 +{
 +      switch (swizzle) {
 +      case UTIL_FORMAT_SWIZZLE_Y:
 +              return V_008F0C_SQ_SEL_Y;
 +      case UTIL_FORMAT_SWIZZLE_Z:
 +              return V_008F0C_SQ_SEL_Z;
 +      case UTIL_FORMAT_SWIZZLE_W:
 +              return V_008F0C_SQ_SEL_W;
 +      case UTIL_FORMAT_SWIZZLE_0:
 +              return V_008F0C_SQ_SEL_0;
 +      case UTIL_FORMAT_SWIZZLE_1:
 +              return V_008F0C_SQ_SEL_1;
 +      default: /* UTIL_FORMAT_SWIZZLE_X */
 +              return V_008F0C_SQ_SEL_X;
 +      }
 +}
 +
  static inline unsigned r600_tex_aniso_filter(unsigned filter)
  {
        if (filter <= 1)   return 0;
index 5a8434a04dc5c4b20733cb48d8aa8adb88f55178,ac2d35e5ea4a529f3232a9004fd3f476331d2bf0..64ec658b80e632c45a761a8570cf62953e906fa5
@@@ -161,7 -161,12 +161,12 @@@ svga_get_param(struct pipe_screen *scre
     case PIPE_CAP_TEXTURE_SWIZZLE:
        return 1;
     case PIPE_CAP_USER_VERTEX_BUFFERS:
+    case PIPE_CAP_USER_INDEX_BUFFERS:
+       return 0;
+    case PIPE_CAP_USER_CONSTANT_BUFFERS:
        return 1;
+    case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
+       return 16;
  
     case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
        {
     case PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS:
     case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
     case PIPE_CAP_GLSL_FEATURE_LEVEL:
 +   case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
 +   case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
        return 0;
 +   case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
 +      return 1;
  
     default:
        debug_printf("Unexpected PIPE_CAP_ query %u\n", param);
index 0951e70f48197554198274163a76c11f4281861c,7709177444f5db177fc125c29a9efafc3df98e5d..f59e388123292a9d9f80064011e8af3b56e62467
@@@ -41,6 -41,7 +41,7 @@@ struct pipe_blend_color
  struct pipe_blend_state;
  struct pipe_box;
  struct pipe_clip_state;
+ struct pipe_constant_buffer;
  struct pipe_depth_stencil_alpha_state;
  struct pipe_draw_info;
  struct pipe_fence_handle;
@@@ -63,7 -64,6 +64,7 @@@ struct pipe_vertex_element
  struct pipe_video_buffer;
  struct pipe_video_decoder;
  struct pipe_viewport_state;
 +struct pipe_compute_state;
  union pipe_color_union;
  union pipe_query_result;
  
@@@ -142,10 -142,6 +143,10 @@@ struct pipe_context 
     void   (*bind_geometry_sampler_states)(struct pipe_context *,
                                            unsigned num_samplers,
                                            void **samplers);
 +   void   (*bind_compute_sampler_states)(struct pipe_context *,
 +                                         unsigned start_slot,
 +                                         unsigned num_samplers,
 +                                         void **samplers);
     void   (*delete_sampler_state)(struct pipe_context *, void *);
  
     void * (*create_rasterizer_state)(struct pipe_context *,
  
     void (*set_constant_buffer)( struct pipe_context *,
                                  uint shader, uint index,
-                                 struct pipe_resource *buf );
+                                 struct pipe_constant_buffer *buf );
  
     void (*set_framebuffer_state)( struct pipe_context *,
                                    const struct pipe_framebuffer_state * );
                                        unsigned num_views,
                                        struct pipe_sampler_view **);
  
 +   void (*set_compute_sampler_views)(struct pipe_context *,
 +                                     unsigned start_slot, unsigned num_views,
 +                                     struct pipe_sampler_view **);
 +
 +   /**
 +    * Bind an array of shader resources that will be used by the
 +    * graphics pipeline.  Any resources that were previously bound to
 +    * the specified range will be unbound after this call.
 +    *
 +    * \param first      first resource to bind.
 +    * \param count      number of consecutive resources to bind.
 +    * \param resources  array of pointers to the resources to bind, it
 +    *                   should contain at least \a count elements
 +    *                   unless it's NULL, in which case no new
 +    *                   resources will be bound.
 +    */
 +   void (*set_shader_resources)(struct pipe_context *,
 +                                unsigned start, unsigned count,
 +                                struct pipe_surface **resources);
 +
     void (*set_vertex_buffers)( struct pipe_context *,
                                 unsigned num_buffers,
                                 const struct pipe_vertex_buffer * );
                                    unsigned stride,
                                    unsigned layer_stride);
  
-    /* Notify a driver that a content of a user buffer has been changed.
-     * The changed range is [offset, offset+size-1].
-     * The new width0 of the buffer is offset+size. */
-    void (*redefine_user_buffer)(struct pipe_context *,
-                                 struct pipe_resource *,
-                                 unsigned offset,
-                                 unsigned size);
     /**
      * Flush any pending framebuffer writes and invalidate texture caches.
      */
      */
     struct pipe_video_buffer *(*create_video_buffer)( struct pipe_context *context,
                                                       const struct pipe_video_buffer *templat );
 +
 +   /**
 +    * Compute kernel execution
 +    */
 +   /*@{*/
 +   /**
 +    * Define the compute program and parameters to be used by
 +    * pipe_context::launch_grid.
 +    */
 +   void *(*create_compute_state)(struct pipe_context *context,
 +                               const struct pipe_compute_state *);
 +   void (*bind_compute_state)(struct pipe_context *, void *);
 +   void (*delete_compute_state)(struct pipe_context *, void *);
 +
 +   /**
 +    * Bind an array of shader resources that will be used by the
 +    * compute program.  Any resources that were previously bound to
 +    * the specified range will be unbound after this call.
 +    *
 +    * \param first      first resource to bind.
 +    * \param count      number of consecutive resources to bind.
 +    * \param resources  array of pointers to the resources to bind, it
 +    *                   should contain at least \a count elements
 +    *                   unless it's NULL, in which case no new
 +    *                   resources will be bound.
 +    */
 +   void (*set_compute_resources)(struct pipe_context *,
 +                                 unsigned start, unsigned count,
 +                                 struct pipe_surface **resources);
 +
 +   /**
 +    * Bind an array of buffers to be mapped into the address space of
 +    * the GLOBAL resource.  Any buffers that were previously bound
 +    * between [first, first + count - 1] are unbound after this call.
 +    *
 +    * \param first      first buffer to map.
 +    * \param count      number of consecutive buffers to map.
 +    * \param resources  array of pointers to the buffers to map, it
 +    *                   should contain at least \a count elements
 +    *                   unless it's NULL, in which case no new
 +    *                   resources will be bound.
 +    * \param handles    array of pointers to the memory locations that
 +    *                   will be filled with the respective base
 +    *                   addresses each buffer will be mapped to.  It
 +    *                   should contain at least \a count elements,
 +    *                   unless \a resources is NULL in which case \a
 +    *                   handles should be NULL as well.
 +    *
 +    * Note that the driver isn't required to make any guarantees about
 +    * the contents of the \a handles array being valid anytime except
 +    * during the subsequent calls to pipe_context::launch_grid.  This
 +    * means that the only sensible location handles[i] may point to is
 +    * somewhere within the INPUT buffer itself.  This is so to
 +    * accommodate implementations that lack virtual memory but
 +    * nevertheless migrate buffers on the fly, leading to resource
 +    * base addresses that change on each kernel invocation or are
 +    * unknown to the pipe driver.
 +    */
 +   void (*set_global_binding)(struct pipe_context *context,
 +                              unsigned first, unsigned count,
 +                              struct pipe_resource **resources,
 +                              uint32_t **handles);
 +
 +   /**
 +    * Launch the compute kernel starting from instruction \a pc of the
 +    * currently bound compute program.
 +    *
 +    * \a grid_layout and \a block_layout are arrays of size \a
 +    * PIPE_COMPUTE_CAP_GRID_DIMENSION that determine the layout of the
 +    * grid (in block units) and working block (in thread units) to be
 +    * used, respectively.
 +    *
 +    * \a input will be used to initialize the INPUT resource, and it
 +    * should point to a buffer of at least
 +    * pipe_compute_state::req_input_mem bytes.
 +    */
 +   void (*launch_grid)(struct pipe_context *context,
 +                       const uint *block_layout, const uint *grid_layout,
 +                       uint32_t pc, const void *input);
 +   /*@}*/
  };
  
  
index edcca23746b33b87299306370dafb4dc83fe1834,398cb98248c02557db642088ce3d1d939c16ff9e..1e05cc4caeee8f9eea5e1fff69922c73f8d5492b
@@@ -304,9 -304,6 +304,9 @@@ enum pipe_transfer_usage 
  #define PIPE_BIND_STREAM_OUTPUT        (1 << 11) /* set_stream_output_buffers */
  #define PIPE_BIND_CURSOR               (1 << 16) /* mouse cursor */
  #define PIPE_BIND_CUSTOM               (1 << 17) /* state-tracker/winsys usages */
 +#define PIPE_BIND_GLOBAL               (1 << 18) /* set_global_binding */
 +#define PIPE_BIND_SHADER_RESOURCE      (1 << 19) /* set_shader_resources */
 +#define PIPE_BIND_COMPUTE_RESOURCE     (1 << 20) /* set_compute_resources */
  
  /* The first two flags above were previously part of the amorphous
   * TEXTURE_USAGE, most of which are now descriptions of the ways a
  #define PIPE_SHADER_VERTEX   0
  #define PIPE_SHADER_FRAGMENT 1
  #define PIPE_SHADER_GEOMETRY 2
 -#define PIPE_SHADER_TYPES    3
 +#define PIPE_SHADER_COMPUTE  3
 +#define PIPE_SHADER_TYPES    4
  
  
  /**
@@@ -481,7 -477,9 +481,10 @@@ enum pipe_cap 
     PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY = 65,
     PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY = 66,
     PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY = 67,
-    PIPE_CAP_COMPUTE = 68
 -   PIPE_CAP_USER_INDEX_BUFFERS = 68,
 -   PIPE_CAP_USER_CONSTANT_BUFFERS = 69,
 -   PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT = 70
++   PIPE_CAP_COMPUTE = 68,
++   PIPE_CAP_USER_INDEX_BUFFERS = 69,
++   PIPE_CAP_USER_CONSTANT_BUFFERS = 70,
++   PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT = 71
  };
  
  /**
@@@ -524,32 -522,9 +527,32 @@@ enum pipe_shader_ca
     PIPE_SHADER_CAP_INDIRECT_CONST_ADDR = 15,
     PIPE_SHADER_CAP_SUBROUTINES = 16, /* BGNSUB, ENDSUB, CAL, RET */
     PIPE_SHADER_CAP_INTEGERS = 17,
 -   PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS = 18
 +   PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS = 18,
 +   PIPE_SHADER_CAP_PREFERRED_IR = 19
  };
  
 +/**
 + * Shader intermediate representation.
 + */
 +enum pipe_shader_ir
 +{
 +   PIPE_SHADER_IR_TGSI
 +};
 +
 +/**
 + * Compute-specific implementation capability.  They can be queried
 + * using pipe_screen::get_compute_param.
 + */
 +enum pipe_compute_cap
 +{
 +   PIPE_COMPUTE_CAP_GRID_DIMENSION,
 +   PIPE_COMPUTE_CAP_MAX_GRID_SIZE,
 +   PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE,
 +   PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE,
 +   PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE,
 +   PIPE_COMPUTE_CAP_MAX_PRIVATE_SIZE,
 +   PIPE_COMPUTE_CAP_MAX_INPUT_SIZE
 +};
  
  /**
   * Composite query types
index 02cd1fdfafb39a990317370fb6f29483605d73ec,3bc35bc77ce68b365aeff5cebfa80ab19e545389..51a956d95329e2f705ee14345706ac6839eaff53
@@@ -62,7 -62,6 +62,7 @@@ extern "C" 
  #define PIPE_MAX_GEOMETRY_SAMPLERS  16
  #define PIPE_MAX_SHADER_INPUTS    32
  #define PIPE_MAX_SHADER_OUTPUTS   32
 +#define PIPE_MAX_SHADER_SAMPLER_VIEWS 32
  #define PIPE_MAX_SHADER_RESOURCES 32
  #define PIPE_MAX_TEXTURE_LEVELS   16
  #define PIPE_MAX_SO_BUFFERS        4
@@@ -338,7 -337,6 +338,7 @@@ struct pipe_surfac
     unsigned height;              /**< logical height in pixels */
  
     unsigned usage;               /**< bitmask of PIPE_BIND_x */
 +   unsigned writable:1;          /**< writable shader resource */
  
     union {
        struct {
@@@ -417,9 -415,6 +417,6 @@@ struct pipe_resourc
  
     unsigned bind;            /**< bitmask of PIPE_BIND_x */
     unsigned flags;           /**< bitmask of PIPE_RESOURCE_FLAG_x */
-    /* XXX this is only temporary and will be removed once it's not needed */
-    uint8_t *user_ptr;        /**< user buffer pointer */
  };
  
  
@@@ -449,6 -444,19 +446,19 @@@ struct pipe_vertex_buffe
     unsigned stride;    /**< stride to same attrib in next vertex, in bytes */
     unsigned buffer_offset;  /**< offset to start of data in buffer, in bytes */
     struct pipe_resource *buffer;  /**< the actual buffer */
+    const void *user_buffer;  /**< pointer to a user buffer if buffer == NULL */
+ };
+ /**
+  * A constant buffer.  A subrange of an existing buffer can be set
+  * as a constant buffer.
+  */
+ struct pipe_constant_buffer {
+    struct pipe_resource *buffer; /**< the actual buffer */
+    unsigned buffer_offset; /**< offset to start of data in buffer, in bytes */
+    unsigned buffer_size;   /**< how much data can be read in shader */
+    const void *user_buffer;  /**< pointer to a user buffer if buffer == NULL */
  };
  
  
@@@ -507,6 -515,7 +517,7 @@@ struct pipe_index_buffe
     unsigned index_size;  /**< size of an index, in bytes */
     unsigned offset;  /**< offset to start of data in buffer, in bytes */
     struct pipe_resource *buffer; /**< the actual buffer */
+    const void *user_buffer;  /**< pointer to a user buffer if buffer == NULL */
  };
  
  
@@@ -582,13 -591,6 +593,13 @@@ struct pipe_resolve_inf
     unsigned mask; /**< PIPE_MASK_RGBA, Z, S or ZS */
  };
  
 +struct pipe_compute_state
 +{
 +   const void *prog; /**< Compute program to be executed. */
 +   unsigned req_local_mem; /**< Required size of the LOCAL resource. */
 +   unsigned req_private_mem; /**< Required size of the PRIVATE resource. */
 +   unsigned req_input_mem; /**< Required size of the INPUT resource. */
 +};
  
  #ifdef __cplusplus
  }
index ce7dbb3f39a198cdd3472cd5ce0475fe8c18c470,93f4216f34eca2b33b3a8cf972da8c0616c68ff5..b44976525398c62c9d101baa22c47f14cd3ed965
@@@ -65,7 -65,6 +65,6 @@@
  #include "util/u_inlines.h"
  #include "util/u_upload_mgr.h"
  #include "cso_cache/cso_context.h"
- #include "util/u_vbuf.h"
  
  
  DEBUG_GET_ONCE_BOOL_OPTION(mesa_mvp_dp4, "MESA_MVP_DP4", FALSE)
@@@ -112,32 -111,12 +111,12 @@@ st_get_msaa(void
  }
  
  
- static void st_init_vbuf(struct st_context *st)
- {
-    struct u_vbuf_caps caps;
-    u_vbuf_get_caps(st->pipe->screen, &caps);
-    /* Create u_vbuf if there is anything unsupported. */
-    if (!caps.buffer_offset_unaligned ||
-        !caps.buffer_stride_unaligned ||
-        !caps.velem_src_offset_unaligned ||
-        !caps.format_fixed32 ||
-        !caps.format_float16 ||
-        !caps.format_float64 ||
-        !caps.format_norm32 ||
-        !caps.format_scaled32 ||
-        !caps.user_vertex_buffers) {
-       /* XXX user vertex buffers are always uploaded regardless of the CAP. */
-       st->vbuf = u_vbuf_create(st->pipe, &caps);
-       cso_install_vbuf(st->cso_context, st->vbuf);
-    }
- }
  
  
  static struct st_context *
  st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe )
  {
+    struct pipe_screen *screen = pipe->screen;
     uint i;
     struct st_context *st = ST_CALLOC_STRUCT( st_context );
     
     st->dirty.st = ~0;
  
     st->uploader = u_upload_create(st->pipe, 65536, 4, PIPE_BIND_VERTEX_BUFFER);
+    if (!screen->get_param(screen, PIPE_CAP_USER_INDEX_BUFFERS)) {
+       st->indexbuf_uploader = u_upload_create(st->pipe, 128 * 1024, 4,
+                                               PIPE_BIND_INDEX_BUFFER);
+    }
+    if (!screen->get_param(screen, PIPE_CAP_USER_CONSTANT_BUFFERS)) {
+       unsigned alignment =
+          screen->get_param(screen, PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT);
+       st->constbuf_uploader = u_upload_create(pipe, 128 * 1024, alignment,
+                                               PIPE_BIND_CONSTANT_BUFFER);
+    }
     st->cso_context = cso_create_context(pipe);
  
-    st_init_vbuf(st);
     st_init_atoms( st );
     st_init_bitmap(st);
     st_init_clear(st);
     return st;
  }
  
 +static void st_init_driver_flags(struct gl_driver_flags *f)
 +{
 +   f->NewArray = ST_NEW_VERTEX_ARRAYS;
 +}
  
  struct st_context *st_create_context(gl_api api, struct pipe_context *pipe,
                                       const struct gl_config *visual,
        return NULL;
     }
  
 +   st_init_driver_flags(&ctx->DriverFlags);
 +
     /* XXX: need a capability bit in gallium to query if the pipe
      * driver prefers DP4 or MUL/MAD for vertex transformation.
      */
@@@ -254,11 -240,6 +246,6 @@@ static void st_destroy_context_priv( st
     st_destroy_drawpix(st);
     st_destroy_drawtex(st);
  
-    /* Unreference any user vertex buffers. */
-    for (i = 0; i < st->num_user_attribs; i++) {
-       pipe_resource_reference(&st->user_attrib[i].buffer, NULL);
-    }
     for (i = 0; i < Elements(st->state.sampler_views); i++) {
        pipe_sampler_view_reference(&st->state.sampler_views[i], NULL);
     }
     }
  
     u_upload_destroy(st->uploader);
+    if (st->indexbuf_uploader) {
+       u_upload_destroy(st->indexbuf_uploader);
+    }
+    if (st->constbuf_uploader) {
+       u_upload_destroy(st->constbuf_uploader);
+    }
     free( st );
  }
  
  void st_destroy_context( struct st_context *st )
  {
     struct pipe_context *pipe = st->pipe;
-    struct u_vbuf *vbuf = st->vbuf;
     struct cso_context *cso = st->cso_context;
     struct gl_context *ctx = st->ctx;
     GLuint i;
     st_destroy_context_priv(st);
     st = NULL;
  
-    if (vbuf)
-       u_vbuf_destroy(vbuf);
     cso_destroy_context(cso);
  
     pipe->destroy( pipe );
index 4786ed22fe9696c33df4a7f853b2fd4e74bcac73,49b8316842ee2b6452f7c57726825c305da009c1..00a405b69f9828dda9c2e368e54d90a05e5ef7cf
@@@ -41,7 -41,6 +41,6 @@@ struct gen_mipmap_state
  struct st_context;
  struct st_fragment_program;
  struct u_upload_mgr;
- struct u_vbuf;
  
  
  #define ST_NEW_MESA                    (1 << 0) /* Mesa state has changed */
@@@ -50,7 -49,6 +49,7 @@@
  #define ST_NEW_FRAMEBUFFER             (1 << 3)
  #define ST_NEW_EDGEFLAGS_DATA          (1 << 4)
  #define ST_NEW_GEOMETRY_PROGRAM        (1 << 5)
 +#define ST_NEW_VERTEX_ARRAYS           (1 << 6)
  
  
  struct st_state_flags {
@@@ -74,8 -72,7 +73,7 @@@ struct st_contex
  
     struct pipe_context *pipe;
  
-    struct u_upload_mgr *uploader;
-    struct u_vbuf *vbuf;
+    struct u_upload_mgr *uploader, *indexbuf_uploader, *constbuf_uploader;
  
     struct draw_context *draw;  /**< For selection/feedback/rastpos only */
     struct draw_stage *feedback_stage;  /**< For GL_FEEDBACK rendermode */
     int force_msaa;
     void *winsys_drawable_handle;
  
-    /* User vertex buffers. */
-    struct {
-       struct pipe_resource *buffer;
-       /** Element size */
-       GLuint element_size;
-       /** Attribute stride */
-       GLsizei stride;
-    } user_attrib[PIPE_MAX_ATTRIBS];
-    unsigned num_user_attribs;
     /* Active render condition. */
     struct pipe_query *render_condition;
     unsigned condition_mode;
index 42dc3757615744da3c92cb0134ef0a90ef7dd903,ab2290f2c9da747c87eb7f1b2a46852b9a5fb283..a8c20f45acda0f58e9a20347a5a85b84eefb2058
@@@ -61,6 -61,7 +61,7 @@@
  #include "util/u_format.h"
  #include "util/u_prim.h"
  #include "util/u_draw_quad.h"
+ #include "util/u_upload_mgr.h"
  #include "draw/draw_context.h"
  #include "cso_cache/cso_context.h"
  
@@@ -402,18 -403,12 +403,12 @@@ setup_interleaved_attribs(struct gl_con
                            const struct st_vp_variant *vpv,
                            const struct gl_client_array **arrays,
                            struct pipe_vertex_buffer *vbuffer,
-                           struct pipe_vertex_element velements[],
-                           unsigned max_index,
-                           unsigned num_instances)
+                           struct pipe_vertex_element velements[])
  {
-    struct st_context *st = st_context(ctx);
-    struct pipe_context *pipe = st->pipe;
     GLuint attr;
     const GLubyte *low_addr = NULL;
     GLboolean usingVBO;      /* all arrays in a VBO? */
     struct gl_buffer_object *bufobj;
-    GLuint user_buffer_size = 0;
-    GLuint vertex_size = 0;  /* bytes per vertex, in bytes */
     GLsizei stride;
  
     /* Find the lowest address of the arrays we're drawing,
                                                           array->Normalized,
                                                           array->Integer);
        assert(velements[attr].src_format);
-       if (!usingVBO) {
-          /* how many bytes referenced by this attribute array? */
-          uint divisor = array->InstanceDivisor;
-          uint last_index = divisor ? num_instances / divisor : max_index;
-          uint bytes = src_offset + stride * last_index + element_size;
-          user_buffer_size = MAX2(user_buffer_size, bytes);
-          /* update vertex size */
-          vertex_size = MAX2(vertex_size, src_offset + element_size);
-       }
     }
  
     /*
     if (vpv->num_inputs == 0) {
        /* just defensive coding here */
        vbuffer->buffer = NULL;
+       vbuffer->user_buffer = NULL;
        vbuffer->buffer_offset = 0;
        vbuffer->stride = 0;
-       st->num_user_attribs = 0;
     }
     else if (usingVBO) {
        /* all interleaved arrays in a VBO */
           return GL_FALSE;
        }
  
-       vbuffer->buffer = NULL;
-       pipe_resource_reference(&vbuffer->buffer, stobj->buffer);
+       vbuffer->buffer = stobj->buffer;
+       vbuffer->user_buffer = NULL;
        vbuffer->buffer_offset = pointer_to_offset(low_addr);
        vbuffer->stride = stride;
-       st->num_user_attribs = 0;
     }
     else {
        /* all interleaved arrays in user memory */
-       vbuffer->buffer = pipe_user_buffer_create(pipe->screen,
-                                                 (void*) low_addr,
-                                                 user_buffer_size,
-                                                 PIPE_BIND_VERTEX_BUFFER);
+       vbuffer->buffer = NULL;
+       vbuffer->user_buffer = low_addr;
        vbuffer->buffer_offset = 0;
        vbuffer->stride = stride;
-       /* Track user vertex buffers. */
-       pipe_resource_reference(&st->user_attrib[0].buffer, vbuffer->buffer);
-       st->user_attrib[0].element_size = vertex_size;
-       st->user_attrib[0].stride = stride;
-       st->num_user_attribs = 1;
     }
  
     return GL_TRUE;
@@@ -536,22 -510,17 +510,17 @@@ setup_non_interleaved_attribs(struct gl
                                const struct st_vp_variant *vpv,
                                const struct gl_client_array **arrays,
                                struct pipe_vertex_buffer vbuffer[],
-                               struct pipe_vertex_element velements[],
-                               unsigned max_index,
-                               unsigned num_instances)
+                               struct pipe_vertex_element velements[])
  {
-    struct st_context *st = st_context(ctx);
-    struct pipe_context *pipe = st->pipe;
     GLuint attr;
  
     for (attr = 0; attr < vpv->num_inputs; attr++) {
        const GLuint mesaAttr = vp->index_to_input[attr];
        const struct gl_client_array *array = arrays[mesaAttr];
        struct gl_buffer_object *bufobj = array->BufferObj;
-       GLuint element_size = array->_ElementSize;
        GLsizei stride = array->StrideB;
  
-       assert(element_size == array->Size * _mesa_sizeof_type(array->Type));
+       assert(array->_ElementSize == array->Size * _mesa_sizeof_type(array->Type));
  
        if (_mesa_is_bufferobj(bufobj)) {
           /* Attribute data is in a VBO.
              return GL_FALSE;
           }
  
-          vbuffer[attr].buffer = NULL;
-          pipe_resource_reference(&vbuffer[attr].buffer, stobj->buffer);
+          vbuffer[attr].buffer = stobj->buffer;
+          vbuffer[attr].user_buffer = NULL;
           vbuffer[attr].buffer_offset = pointer_to_offset(array->Ptr);
        }
        else {
           /* wrap user data */
-          uint bytes;
           void *ptr;
  
           if (array->Ptr) {
-             uint divisor = array->InstanceDivisor;
-             uint last_index = divisor ? num_instances / divisor : max_index;
-             bytes = stride * last_index + element_size;
              ptr = (void *) array->Ptr;
           }
           else {
              /* no array, use ctx->Current.Attrib[] value */
-             bytes = element_size = sizeof(ctx->Current.Attrib[0]);
              ptr = (void *) ctx->Current.Attrib[mesaAttr];
              stride = 0;
           }
  
           assert(ptr);
-          assert(bytes);
-          vbuffer[attr].buffer =
-             pipe_user_buffer_create(pipe->screen, ptr, bytes,
-                                     PIPE_BIND_VERTEX_BUFFER);
  
+          vbuffer[attr].buffer = NULL;
+          vbuffer[attr].user_buffer = ptr;
           vbuffer[attr].buffer_offset = 0;
-          /* Track user vertex buffers. */
-          pipe_resource_reference(&st->user_attrib[attr].buffer, vbuffer[attr].buffer);
-          st->user_attrib[attr].element_size = element_size;
-          st->user_attrib[attr].stride = stride;
-          st->num_user_attribs = MAX2(st->num_user_attribs, attr + 1);
-          if (!vbuffer[attr].buffer) {
-             /* probably ran out of memory */
-             return GL_FALSE;
-          }
        }
  
        /* common-case setup */
  
  
  static void
- setup_index_buffer(struct gl_context *ctx,
+ setup_index_buffer(struct st_context *st,
                     const struct _mesa_index_buffer *ib,
                     struct pipe_index_buffer *ibuffer)
  {
-    struct st_context *st = st_context(ctx);
-    struct pipe_context *pipe = st->pipe;
+    struct gl_buffer_object *bufobj = ib->obj;
  
-    memset(ibuffer, 0, sizeof(*ibuffer));
-    if (ib) {
-       struct gl_buffer_object *bufobj = ib->obj;
-       ibuffer->index_size = vbo_sizeof_ib_type(ib->type);
+    ibuffer->index_size = vbo_sizeof_ib_type(ib->type);
  
-       /* get/create the index buffer object */
-       if (_mesa_is_bufferobj(bufobj)) {
-          /* elements/indexes are in a real VBO */
-          struct st_buffer_object *stobj = st_buffer_object(bufobj);
-          pipe_resource_reference(&ibuffer->buffer, stobj->buffer);
-          ibuffer->offset = pointer_to_offset(ib->ptr);
-       }
-       else {
-          /* element/indicies are in user space memory */
-          ibuffer->buffer =
-             pipe_user_buffer_create(pipe->screen, (void *) ib->ptr,
-                                     ib->count * ibuffer->index_size,
-                                     PIPE_BIND_INDEX_BUFFER);
-       }
+    /* get/create the index buffer object */
+    if (_mesa_is_bufferobj(bufobj)) {
+       /* indices are in a real VBO */
+       ibuffer->buffer = st_buffer_object(bufobj)->buffer;
+       ibuffer->offset = pointer_to_offset(ib->ptr);
     }
+    else if (st->indexbuf_uploader) {
+       u_upload_data(st->indexbuf_uploader, 0, ib->count * ibuffer->index_size,
+                     ib->ptr, &ibuffer->offset, &ibuffer->buffer);
+       u_upload_unmap(st->indexbuf_uploader);
+    }
+    else {
+       /* indices are in user space memory */
+       ibuffer->user_buffer = ib->ptr;
+    }
+    cso_set_index_buffer(st->cso_context, ibuffer);
  }
  
  
@@@ -811,10 -756,10 +756,10 @@@ handle_fallback_primitive_restart(struc
     unsigned num_sub_prims;
  
     assert(info.indexed);
-    assert(ibuffer->buffer);
+    assert(ibuffer->buffer || ibuffer->user_buffer);
     assert(ib);
  
-    if (!ibuffer->buffer || !ib)
+    if (!ibuffer->buffer || !ibuffer->user_buffer || !ib)
        return;
  
     info.primitive_restart = FALSE;
@@@ -894,9 -839,7 +839,7 @@@ translate_prim(const struct gl_context 
   */
  static GLboolean
  st_validate_varrays(struct gl_context *ctx,
-                     const struct gl_client_array **arrays,
-                     unsigned max_index,
-                     unsigned num_instances)
+                     const struct gl_client_array **arrays)
  {
     struct st_context *st = st_context(ctx);
     const struct st_vertex_program *vp;
     struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
     struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
     unsigned num_vbuffers, num_velements;
-    GLuint attr;
-    unsigned i;
  
     /* must get these after state validation! */
     vp = st->vp;
  
     memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs);
  
-    /* Unreference any user vertex buffers. */
-    for (i = 0; i < st->num_user_attribs; i++) {
-       pipe_resource_reference(&st->user_attrib[i].buffer, NULL);
-    }
-    st->num_user_attribs = 0;
     /*
      * Setup the vbuffer[] and velements[] arrays.
      */
     if (is_interleaved_arrays(vp, vpv, arrays)) {
-       if (!setup_interleaved_attribs(ctx, vp, vpv, arrays, vbuffer, velements,
-                                      max_index, num_instances)) {
+       if (!setup_interleaved_attribs(ctx, vp, vpv, arrays, vbuffer,
+                                      velements)) {
           return GL_FALSE;
        }
  
     }
     else {
        if (!setup_non_interleaved_attribs(ctx, vp, vpv, arrays,
-                                          vbuffer, velements, max_index,
-                                          num_instances)) {
+                                          vbuffer, velements)) {
           return GL_FALSE;
        }
  
     cso_set_vertex_buffers(st->cso_context, num_vbuffers, vbuffer);
     cso_set_vertex_elements(st->cso_context, num_velements, velements);
  
-    /* unreference buffers (frees wrapped user-space buffer objects)
-     * This is OK, because the pipe driver should reference buffers by itself
-     * in set_vertex_buffers. */
-    for (attr = 0; attr < num_vbuffers; attr++) {
-       pipe_resource_reference(&vbuffer[attr].buffer, NULL);
-       assert(!vbuffer[attr].buffer);
-    }
     return GL_TRUE;
  }
  
   */
  void
  st_draw_vbo(struct gl_context *ctx,
 -            const struct gl_client_array **arrays,
              const struct _mesa_prim *prims,
              GLuint nr_prims,
              const struct _mesa_index_buffer *ib,
  {
     struct st_context *st = st_context(ctx);
     struct pipe_context *pipe = st->pipe;
-    struct pipe_index_buffer ibuffer;
+    struct pipe_index_buffer ibuffer = {0};
     struct pipe_draw_info info;
-    unsigned i, num_instances = 1;
-    unsigned max_index_plus_base;
 +   const struct gl_client_array **arrays = ctx->Array._DrawArrays;
 -   GLboolean new_array =
 -      st->dirty.st &&
 -      (st->dirty.mesa & (_NEW_ARRAY | _NEW_PROGRAM | _NEW_BUFFER_OBJECT)) != 0;
+    unsigned i;
 +   GLboolean new_array;
  
     /* Mesa core state should have been validated already */
     assert(ctx->NewState == 0x0);
  
-    if (ib) {
-       int max_base_vertex = 0;
-       /* Gallium probably doesn't want this in some cases. */
-       if (!index_bounds_valid)
-          if (!all_varyings_in_vbos(arrays))
-             vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index,
-                                    nr_prims);
-       for (i = 0; i < nr_prims; i++) {
-          num_instances = MAX2(num_instances, prims[i].num_instances);
-          max_base_vertex = MAX2(max_base_vertex, prims[i].basevertex);
-       }
-       /* Compute the sum of max_index and max_base_vertex.  That's the value
-        * we need to use when creating buffers.
-        */
-       if (max_index == ~0)
-          max_index_plus_base = max_index;
-       else
-          max_index_plus_base = max_index + max_base_vertex;
-    }
-    else {
-       /* Get min/max index for non-indexed drawing. */
-       min_index = ~0;
-       max_index = 0;
-       for (i = 0; i < nr_prims; i++) {
-          min_index = MIN2(min_index, prims[i].start);
-          max_index = MAX2(max_index, prims[i].start + prims[i].count - 1);
-          num_instances = MAX2(num_instances, prims[i].num_instances);
-       }
-       /* The base vertex offset only applies to indexed drawing */
-       max_index_plus_base = max_index;
-    }
 +   /* Get Mesa driver state. */
 +   st->dirty.st |= ctx->NewDriverState;
 +   ctx->NewDriverState = 0;
 +
 +   new_array =
 +      (st->dirty.st & (ST_NEW_VERTEX_ARRAYS | ST_NEW_VERTEX_PROGRAM)) ||
 +      (st->dirty.mesa & (_NEW_PROGRAM | _NEW_BUFFER_OBJECT)) != 0;
 +
     /* Validate state. */
     if (st->dirty.st) {
        GLboolean vertDataEdgeFlags;
        st_validate_state(st);
  
        if (new_array) {
-          if (!st_validate_varrays(ctx, arrays, max_index_plus_base,
-                                   num_instances)) {
+          if (!st_validate_varrays(ctx, arrays)) {
              /* probably out of memory, no-op the draw call */
              return;
           }
  #endif
     }
  
-    /* Notify the driver that the content of user buffers may have been
-     * changed. */
-    assert(max_index >= min_index);
-    if (!new_array && st->num_user_attribs) {
-       for (i = 0; i < st->num_user_attribs; i++) {
-          if (st->user_attrib[i].buffer) {
-             unsigned element_size = st->user_attrib[i].element_size;
-             unsigned stride = st->user_attrib[i].stride;
-             unsigned min_offset = min_index * stride;
-             unsigned max_offset = max_index_plus_base * stride + element_size;
-             assert(max_offset > min_offset);
-             pipe->redefine_user_buffer(pipe, st->user_attrib[i].buffer,
-                                        min_offset,
-                                        max_offset - min_offset);
-          }
-       }
-    }
-    setup_index_buffer(ctx, ib, &ibuffer);
-    cso_set_index_buffer(st->cso_context, &ibuffer);
     util_draw_init_info(&info);
     if (ib) {
+       /* Get index bounds for user buffers. */
+       if (!index_bounds_valid)
+          if (!all_varyings_in_vbos(arrays))
+             vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index,
+                                    nr_prims);
+       setup_index_buffer(st, ib, &ibuffer);
        info.indexed = TRUE;
        if (min_index != ~0 && max_index != ~0) {
           info.min_index = min_index;
        info.primitive_restart = ctx->Array.PrimitiveRestart;
        info.restart_index = ctx->Array.RestartIndex;
     }
-    /* Set info.count_from_stream_output. */
-    if (tfb_vertcount) {
-       st_transform_feedback_draw_init(tfb_vertcount, &info);
+    else {
+       /* Transform feedback drawing is always non-indexed. */
+       /* Set info.count_from_stream_output. */
+       if (tfb_vertcount) {
+          st_transform_feedback_draw_init(tfb_vertcount, &info);
+       }
     }
  
     /* do actual drawing */
           cso_draw_vbo(st->cso_context, &info);
     }
  
-    pipe_resource_reference(&ibuffer.buffer, NULL);
+    if (ib && st->indexbuf_uploader && !_mesa_is_bufferobj(ib->obj)) {
+       pipe_resource_reference(&ibuffer.buffer, NULL);
+    }
  }
  
  
index 257618aa992fc6272e93ad6f04c47fe4eeb3bc47,ee19898b3ea1b1f907c997203912af8306087c1b..4209fb214f8c659a4f2943d188f541f1ee207e05
@@@ -91,6 -91,7 +91,6 @@@ set_feedback_vertex_format(struct gl_co
   */
  void
  st_feedback_draw_vbo(struct gl_context *ctx,
 -                     const struct gl_client_array **arrays,
                       const struct _mesa_prim *prims,
                       GLuint nr_prims,
                       const struct _mesa_index_buffer *ib,
     struct pipe_vertex_buffer vbuffers[PIPE_MAX_SHADER_INPUTS];
     struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
     struct pipe_index_buffer ibuffer;
-    struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
+    struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {NULL};
     struct pipe_transfer *ib_transfer = NULL;
 +   const struct gl_client_array **arrays = ctx->Array._DrawArrays;
     GLuint attr, i;
     const GLubyte *low_addr = NULL;
     const void *mapped_indices = NULL;
           assert(stobj->buffer);
  
           vbuffers[attr].buffer = NULL;
+          vbuffers[attr].user_buffer = NULL;
           pipe_resource_reference(&vbuffers[attr].buffer, stobj->buffer);
           vbuffers[attr].buffer_offset = pointer_to_offset(low_addr);
           velements[attr].src_offset = arrays[mesaAttr]->Ptr - low_addr;
+          /* map the attrib buffer */
+          map = pipe_buffer_map(pipe, vbuffers[attr].buffer,
+                                PIPE_TRANSFER_READ,
+                                &vb_transfer[attr]);
+          draw_set_mapped_vertex_buffer(draw, attr, map);
        }
        else {
-          /* attribute data is in user-space memory, not a VBO */
-          uint bytes = (arrays[mesaAttr]->Size
-                        * _mesa_sizeof_type(arrays[mesaAttr]->Type)
-                        * (max_index + 1));
-          /* wrap user data */
-          vbuffers[attr].buffer
-             = pipe_user_buffer_create(pipe->screen, (void *) arrays[mesaAttr]->Ptr,
-                                       bytes,
-                                     PIPE_BIND_VERTEX_BUFFER);
+          vbuffers[attr].buffer = NULL;
+          vbuffers[attr].user_buffer = arrays[mesaAttr]->Ptr;
           vbuffers[attr].buffer_offset = 0;
           velements[attr].src_offset = 0;
+          draw_set_mapped_vertex_buffer(draw, attr, vbuffers[attr].user_buffer);
        }
  
        /* common-case setup */
  #if 0
        draw_set_vertex_buffer(draw, attr, &vbuffer[attr]);
  #endif
-       /* map the attrib buffer */
-       map = pipe_buffer_map(pipe, vbuffers[attr].buffer,
-                             PIPE_TRANSFER_READ,
-                           &vb_transfer[attr]);
-       draw_set_mapped_vertex_buffer(draw, attr, map);
     }
  
     draw_set_vertex_buffers(draw, vp->num_inputs, vbuffers);
  
   out_unref_vertex:
     for (attr = 0; attr < vp->num_inputs; attr++) {
-       pipe_buffer_unmap(pipe, vb_transfer[attr]);
+       if (vb_transfer[attr])
+          pipe_buffer_unmap(pipe, vb_transfer[attr]);
        draw_set_mapped_vertex_buffer(draw, attr, NULL);
        pipe_resource_reference(&vbuffers[attr].buffer, NULL);
     }