gallium: add start_slot parameter to set_vertex_buffers
authorMarek Olšák <maraeo@gmail.com>
Thu, 29 Mar 2012 15:51:50 +0000 (17:51 +0200)
committerMarek Olšák <maraeo@gmail.com>
Tue, 30 Oct 2012 23:55:13 +0000 (00:55 +0100)
This allows updating only a subrange of buffer bindings.

set_vertex_buffers(pipe, start_slot, count, NULL) unbinds buffers in that
range. Binding NULL resources unbinds buffers too (both buffer and user_buffer
must be NULL).

The meta ops are adapted to only save, change, and restore the single slot
they use. The cso_context can save and restore only one vertex buffer slot.
The clients can query which one it is using cso_get_aux_vertex_buffer_slot.
It's currently set to 0. (the Draw module breaks if it's set to non-zero)

It should decrease the CPU overhead when using a lot of meta ops, but
the drivers must be able to treat each vertex buffer slot as a separate
state (only r600g does so at the moment).

I can imagine this also being useful for optimizing some OpenGL use cases.

Reviewed-by: Brian Paul <brianp@vmware.com>
78 files changed:
src/gallium/auxiliary/Makefile.sources
src/gallium/auxiliary/cso_cache/cso_context.c
src/gallium/auxiliary/cso_cache/cso_context.h
src/gallium/auxiliary/draw/draw_context.c
src/gallium/auxiliary/draw/draw_context.h
src/gallium/auxiliary/postprocess/pp_run.c
src/gallium/auxiliary/util/u_blit.c
src/gallium/auxiliary/util/u_blitter.c
src/gallium/auxiliary/util/u_blitter.h
src/gallium/auxiliary/util/u_draw_quad.c
src/gallium/auxiliary/util/u_draw_quad.h
src/gallium/auxiliary/util/u_gen_mipmap.c
src/gallium/auxiliary/util/u_helpers.c [new file with mode: 0644]
src/gallium/auxiliary/util/u_helpers.h [new file with mode: 0644]
src/gallium/auxiliary/util/u_inlines.h
src/gallium/auxiliary/util/u_math.h
src/gallium/auxiliary/util/u_vbuf.c
src/gallium/auxiliary/util/u_vbuf.h
src/gallium/auxiliary/vl/vl_compositor.c
src/gallium/auxiliary/vl/vl_matrix_filter.c
src/gallium/auxiliary/vl/vl_median_filter.c
src/gallium/auxiliary/vl/vl_mpeg12_decoder.c
src/gallium/drivers/galahad/glhd_context.c
src/gallium/drivers/i915/i915_state.c
src/gallium/drivers/i915/i915_surface.c
src/gallium/drivers/identity/id_context.c
src/gallium/drivers/llvmpipe/lp_draw_arrays.c
src/gallium/drivers/llvmpipe/lp_state_vertex.c
src/gallium/drivers/llvmpipe/lp_surface.c
src/gallium/drivers/noop/noop_state.c
src/gallium/drivers/nv30/nv30_draw.c
src/gallium/drivers/nv30/nv30_miptree.c
src/gallium/drivers/nv30/nv30_push.c
src/gallium/drivers/nv30/nv30_state.c
src/gallium/drivers/nv50/nv50_state.c
src/gallium/drivers/nvc0/nvc0_state.c
src/gallium/drivers/r300/r300_blit.c
src/gallium/drivers/r300/r300_render.c
src/gallium/drivers/r300/r300_state.c
src/gallium/drivers/r600/r600_blit.c
src/gallium/drivers/r600/r600_state_common.c
src/gallium/drivers/radeonsi/r600_blit.c
src/gallium/drivers/radeonsi/si_state.c
src/gallium/drivers/rbug/rbug_context.c
src/gallium/drivers/softpipe/sp_draw_arrays.c
src/gallium/drivers/softpipe/sp_state_vertex.c
src/gallium/drivers/softpipe/sp_surface.c
src/gallium/drivers/svga/svga_context.h
src/gallium/drivers/svga/svga_pipe_blit.c
src/gallium/drivers/svga/svga_pipe_vertex.c
src/gallium/drivers/svga/svga_swtnl_state.c
src/gallium/drivers/trace/tr_context.c
src/gallium/include/pipe/p_context.h
src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp
src/gallium/state_trackers/vega/renderer.c
src/gallium/tests/graw/fs-fragcoord.c
src/gallium/tests/graw/fs-frontface.c
src/gallium/tests/graw/fs-test.c
src/gallium/tests/graw/fs-write-z.c
src/gallium/tests/graw/gs-test.c
src/gallium/tests/graw/occlusion-query.c
src/gallium/tests/graw/quad-sample.c
src/gallium/tests/graw/quad-tex.c
src/gallium/tests/graw/shader-leak.c
src/gallium/tests/graw/tex-srgb.c
src/gallium/tests/graw/tex-swizzle.c
src/gallium/tests/graw/tri-gs.c
src/gallium/tests/graw/tri-instanced.c
src/gallium/tests/graw/tri.c
src/gallium/tests/graw/vs-test.c
src/mesa/state_tracker/st_atom_array.c
src/mesa/state_tracker/st_cb_bitmap.c
src/mesa/state_tracker/st_cb_clear.c
src/mesa/state_tracker/st_cb_drawpixels.c
src/mesa/state_tracker/st_cb_drawtex.c
src/mesa/state_tracker/st_context.c
src/mesa/state_tracker/st_context.h
src/mesa/state_tracker/st_draw_feedback.c

index 2807c780d2d3872b3e66af4d9316017aafdbad55..6258861f0c85c245e27e1263bf7c3624fbd6633f 100644 (file)
@@ -115,6 +115,7 @@ C_SOURCES := \
        util/u_handle_table.c \
        util/u_hash.c \
        util/u_hash_table.c \
+       util/u_helpers.c \
        util/u_index_modify.c \
        util/u_keymap.c \
        util/u_linear.c \
index db4fa019a3529a66edd658a2ea74be226c9474b4..b3decc58f0e0ddefac179cf403bccd485fe3e6a2 100644 (file)
@@ -86,11 +86,9 @@ struct cso_context {
 
    struct sampler_info samplers[PIPE_SHADER_TYPES];
 
-   uint nr_vertex_buffers;
-   struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
-
-   uint nr_vertex_buffers_saved;
-   struct pipe_vertex_buffer vertex_buffers_saved[PIPE_MAX_ATTRIBS];
+   struct pipe_vertex_buffer aux_vertex_buffer_current;
+   struct pipe_vertex_buffer aux_vertex_buffer_saved;
+   unsigned aux_vertex_buffer_index;
 
    unsigned nr_so_targets;
    struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_BUFFERS];
@@ -246,7 +244,8 @@ static void cso_init_vbuf(struct cso_context *cso)
        !caps.format_norm32 ||
        !caps.format_scaled32 ||
        !caps.user_vertex_buffers) {
-      cso->vbuf = u_vbuf_create(cso->pipe, &caps);
+      cso->vbuf = u_vbuf_create(cso->pipe, &caps,
+                                cso->aux_vertex_buffer_index);
    }
 }
 
@@ -266,6 +265,8 @@ struct cso_context *cso_create_context( struct pipe_context *pipe )
    ctx->pipe = pipe;
    ctx->sample_mask_saved = ~0;
 
+   ctx->aux_vertex_buffer_index = 0; /* 0 for now */
+
    cso_init_vbuf(ctx);
 
    /* Enable for testing: */
@@ -323,12 +324,8 @@ void cso_release_all( struct cso_context *ctx )
    util_unreference_framebuffer_state(&ctx->fb);
    util_unreference_framebuffer_state(&ctx->fb_saved);
 
-   util_copy_vertex_buffers(ctx->vertex_buffers,
-                            &ctx->nr_vertex_buffers,
-                            NULL, 0);
-   util_copy_vertex_buffers(ctx->vertex_buffers_saved,
-                            &ctx->nr_vertex_buffers_saved,
-                            NULL, 0);
+   pipe_resource_reference(&ctx->aux_vertex_buffer_current.buffer, NULL);
+   pipe_resource_reference(&ctx->aux_vertex_buffer_saved.buffer, NULL);
 
    for (i = 0; i < PIPE_MAX_SO_BUFFERS; i++) {
       pipe_so_target_reference(&ctx->so_targets[i], NULL);
@@ -904,62 +901,71 @@ void cso_restore_vertex_elements(struct cso_context *ctx)
 /* vertex buffers */
 
 void cso_set_vertex_buffers(struct cso_context *ctx,
-                            unsigned count,
+                            unsigned start_slot, unsigned count,
                             const struct pipe_vertex_buffer *buffers)
 {
    struct u_vbuf *vbuf = ctx->vbuf;
 
    if (vbuf) {
-      u_vbuf_set_vertex_buffers(vbuf, count, buffers);
+      u_vbuf_set_vertex_buffers(vbuf, start_slot, count, buffers);
       return;
    }
 
-   if (count != ctx->nr_vertex_buffers ||
-       memcmp(buffers, ctx->vertex_buffers,
-              sizeof(struct pipe_vertex_buffer) * count) != 0) {
-      util_copy_vertex_buffers(ctx->vertex_buffers, &ctx->nr_vertex_buffers,
-                               buffers, count);
-      ctx->pipe->set_vertex_buffers(ctx->pipe, count, buffers);
+   /* Save what's in the auxiliary slot, so that we can save and restore it
+    * for meta ops. */
+   if (start_slot <= ctx->aux_vertex_buffer_index &&
+       start_slot+count > ctx->aux_vertex_buffer_index) {
+      if (buffers) {
+         const struct pipe_vertex_buffer *vb =
+               buffers + (ctx->aux_vertex_buffer_index - start_slot);
+
+         pipe_resource_reference(&ctx->aux_vertex_buffer_current.buffer,
+                                 vb->buffer);
+         memcpy(&ctx->aux_vertex_buffer_current, vb,
+                sizeof(struct pipe_vertex_buffer));
+      }
+      else {
+         pipe_resource_reference(&ctx->aux_vertex_buffer_current.buffer,
+                                 NULL);
+         ctx->aux_vertex_buffer_current.user_buffer = NULL;
+      }
    }
+
+   ctx->pipe->set_vertex_buffers(ctx->pipe, start_slot, count, buffers);
 }
 
-void cso_save_vertex_buffers(struct cso_context *ctx)
+void cso_save_aux_vertex_buffer_slot(struct cso_context *ctx)
 {
    struct u_vbuf *vbuf = ctx->vbuf;
 
    if (vbuf) {
-      u_vbuf_save_vertex_buffers(vbuf);
+      u_vbuf_save_aux_vertex_buffer_slot(vbuf);
       return;
    }
 
-   util_copy_vertex_buffers(ctx->vertex_buffers_saved,
-                            &ctx->nr_vertex_buffers_saved,
-                            ctx->vertex_buffers,
-                            ctx->nr_vertex_buffers);
+   pipe_resource_reference(&ctx->aux_vertex_buffer_saved.buffer,
+                           ctx->aux_vertex_buffer_current.buffer);
+   memcpy(&ctx->aux_vertex_buffer_saved, &ctx->aux_vertex_buffer_current,
+          sizeof(struct pipe_vertex_buffer));
 }
 
-void cso_restore_vertex_buffers(struct cso_context *ctx)
+void cso_restore_aux_vertex_buffer_slot(struct cso_context *ctx)
 {
-   unsigned i;
    struct u_vbuf *vbuf = ctx->vbuf;
 
    if (vbuf) {
-      u_vbuf_restore_vertex_buffers(vbuf);
+      u_vbuf_restore_aux_vertex_buffer_slot(vbuf);
       return;
    }
 
-   util_copy_vertex_buffers(ctx->vertex_buffers,
-                            &ctx->nr_vertex_buffers,
-                            ctx->vertex_buffers_saved,
-                            ctx->nr_vertex_buffers_saved);
-
-   for (i = 0; i < ctx->nr_vertex_buffers_saved; i++) {
-      pipe_resource_reference(&ctx->vertex_buffers_saved[i].buffer, NULL);
-   }
-   ctx->nr_vertex_buffers_saved = 0;
+   cso_set_vertex_buffers(ctx, ctx->aux_vertex_buffer_index, 1,
+                          &ctx->aux_vertex_buffer_saved);
+   pipe_resource_reference(&ctx->aux_vertex_buffer_saved.buffer, NULL);
+}
 
-   ctx->pipe->set_vertex_buffers(ctx->pipe, ctx->nr_vertex_buffers,
-                                 ctx->vertex_buffers);
+unsigned cso_get_aux_vertex_buffer_slot(struct cso_context *ctx)
+{
+   return ctx->aux_vertex_buffer_index;
 }
 
 
index f49b2b706a4ebdd5d577fa74c82d915a83ad3f88..16158edacc33c08639ce046c98a62ee9da524ca0 100644 (file)
@@ -102,10 +102,14 @@ void cso_restore_vertex_elements(struct cso_context *ctx);
 
 
 void cso_set_vertex_buffers(struct cso_context *ctx,
-                            unsigned count,
+                            unsigned start_slot, unsigned count,
                             const struct pipe_vertex_buffer *buffers);
-void cso_save_vertex_buffers(struct cso_context *ctx);
-void cso_restore_vertex_buffers(struct cso_context *ctx);
+
+/* One vertex buffer slot is provided with the save/restore functionality.
+ * cso_context chooses the slot, it can be non-zero. */
+void cso_save_aux_vertex_buffer_slot(struct cso_context *ctx);
+void cso_restore_aux_vertex_buffer_slot(struct cso_context *ctx);
+unsigned cso_get_aux_vertex_buffer_slot(struct cso_context *ctx);
 
 
 void cso_set_stream_outputs(struct cso_context *ctx,
index 48b5db3402716b2764dd1fd465603dbb404ae098..91dd2e1a20aef0a606c172e617ed9fcaec7af942 100644 (file)
@@ -36,6 +36,7 @@
 #include "util/u_math.h"
 #include "util/u_cpu_detect.h"
 #include "util/u_inlines.h"
+#include "util/u_helpers.h"
 #include "draw_context.h"
 #include "draw_vs.h"
 #include "draw_gs.h"
@@ -318,14 +319,14 @@ void draw_set_viewport_state( struct draw_context *draw,
 
 void
 draw_set_vertex_buffers(struct draw_context *draw,
-                        unsigned count,
+                        unsigned start_slot, unsigned count,
                         const struct pipe_vertex_buffer *buffers)
 {
-   assert(count <= PIPE_MAX_ATTRIBS);
+   assert(start_slot + count <= PIPE_MAX_ATTRIBS);
 
-   util_copy_vertex_buffers(draw->pt.vertex_buffer,
-                            &draw->pt.nr_vertex_buffers,
-                            buffers, count);
+   util_set_vertex_buffers_count(draw->pt.vertex_buffer,
+                                 &draw->pt.nr_vertex_buffers,
+                                 buffers, start_slot, count);
 }
 
 
index 4a73ec8c37d6dd5007300cdb3431653aa4e692e5..30633233fb0f13cf91c2534f5c79fc994753da56 100644 (file)
@@ -200,7 +200,7 @@ void draw_delete_geometry_shader(struct draw_context *draw,
  */
 
 void draw_set_vertex_buffers(struct draw_context *draw,
-                             unsigned count,
+                             unsigned start_slot, unsigned count,
                              const struct pipe_vertex_buffer *buffers);
 
 void draw_set_vertex_elements(struct draw_context *draw,
index d2f7aa6dafba27ef2e33dd396103a95e067807fa..4e6d6750f0b69cd296ec1e4319e14cc55715b6ca 100644 (file)
@@ -178,7 +178,7 @@ pp_filter_misc_state(struct program *p)
 void
 pp_filter_draw(struct program *p)
 {
-   util_draw_vertex_buffer(p->pipe, p->cso, p->vbuf, 0,
+   util_draw_vertex_buffer(p->pipe, p->cso, p->vbuf, 0, 0,
                            PIPE_PRIM_QUADS, 4, 2);
    p->pipe->flush(p->pipe, NULL);
 }
index bf1c392cd41a43c4d4fb51564dde4f050a1644cc..ab1549e2de60b8b361e25e41e7a990465b4de048 100644 (file)
@@ -133,7 +133,7 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
    for (i = 0; i < 2; i++) {
       ctx->velem[i].src_offset = i * 4 * sizeof(float);
       ctx->velem[i].instance_divisor = 0;
-      ctx->velem[i].vertex_buffer_index = 0;
+      ctx->velem[i].vertex_buffer_index = cso_get_aux_vertex_buffer_slot(cso);
       ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    }
 
@@ -665,7 +665,7 @@ util_blit_pixels(struct blit_state *ctx,
    cso_save_vertex_shader(ctx->cso);
    cso_save_geometry_shader(ctx->cso);
    cso_save_vertex_elements(ctx->cso);
-   cso_save_vertex_buffers(ctx->cso);
+   cso_save_aux_vertex_buffer_slot(ctx->cso);
 
    /* set misc state we care about */
    if (writemask)
@@ -776,7 +776,9 @@ util_blit_pixels(struct blit_state *ctx,
                                   z);
 
    if (ctx->vbuf) {
-      util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf, offset,
+      util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf,
+                              cso_get_aux_vertex_buffer_slot(ctx->cso),
+                              offset,
                               PIPE_PRIM_TRIANGLE_FAN,
                               4,  /* verts */
                               2); /* attribs/vert */
@@ -795,7 +797,7 @@ util_blit_pixels(struct blit_state *ctx,
    cso_restore_vertex_shader(ctx->cso);
    cso_restore_geometry_shader(ctx->cso);
    cso_restore_vertex_elements(ctx->cso);
-   cso_restore_vertex_buffers(ctx->cso);
+   cso_restore_aux_vertex_buffer_slot(ctx->cso);
    cso_restore_stream_outputs(ctx->cso);
 
    pipe_sampler_view_reference(&sampler_view, NULL);
@@ -869,7 +871,7 @@ util_blit_pixels_tex(struct blit_state *ctx,
    cso_save_vertex_shader(ctx->cso);
    cso_save_geometry_shader(ctx->cso);
    cso_save_vertex_elements(ctx->cso);
-   cso_save_vertex_buffers(ctx->cso);
+   cso_save_aux_vertex_buffer_slot(ctx->cso);
 
    /* set misc state we care about */
    cso_set_blend(ctx->cso, &ctx->blend_write_color);
@@ -923,8 +925,9 @@ util_blit_pixels_tex(struct blit_state *ctx,
                                   s0, t0, s1, t1,
                                   z);
 
-   util_draw_vertex_buffer(ctx->pipe, ctx->cso,
-                           ctx->vbuf, offset,
+   util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf,
+                           cso_get_aux_vertex_buffer_slot(ctx->cso),
+                           offset,
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
                            2); /* attribs/vert */
@@ -942,6 +945,6 @@ util_blit_pixels_tex(struct blit_state *ctx,
    cso_restore_vertex_shader(ctx->cso);
    cso_restore_geometry_shader(ctx->cso);
    cso_restore_vertex_elements(ctx->cso);
-   cso_restore_vertex_buffers(ctx->cso);
+   cso_restore_aux_vertex_buffer_slot(ctx->cso);
    cso_restore_stream_outputs(ctx->cso);
 }
index f4ac4aa868551fa440c749afa9b6640e984f4a45..bb784d6b37021578f95d75f0c07c0f94b1d1f4d2 100644 (file)
@@ -158,7 +158,6 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
    ctx->base.saved_fb_state.nr_cbufs = ~0;
    ctx->base.saved_num_sampler_views = ~0;
    ctx->base.saved_num_sampler_states = ~0;
-   ctx->base.saved_num_vertex_buffers = ~0;
    ctx->base.saved_num_so_targets = ~0;
 
    ctx->has_geometry_shader =
@@ -241,11 +240,14 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
       ctx->rs_discard_state = pipe->create_rasterizer_state(pipe, &rs_state);
    }
 
+   ctx->base.vb_slot = 0; /* 0 for now */
+
    /* vertex elements states */
    memset(&velem[0], 0, sizeof(velem[0]) * 2);
    for (i = 0; i < 2; i++) {
       velem[i].src_offset = i * 4 * sizeof(float);
       velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+      velem[i].vertex_buffer_index = ctx->base.vb_slot;
    }
    ctx->velem_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
 
@@ -253,20 +255,25 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
       memset(&velem[0], 0, sizeof(velem[0]) * 2);
       velem[0].src_offset = 0;
       velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+      velem[0].vertex_buffer_index = ctx->base.vb_slot;
       velem[1].src_offset = 4 * sizeof(float);
       velem[1].src_format = PIPE_FORMAT_R32G32B32A32_SINT;
+      velem[1].vertex_buffer_index = ctx->base.vb_slot;
       ctx->velem_sint_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
 
       memset(&velem[0], 0, sizeof(velem[0]) * 2);
       velem[0].src_offset = 0;
       velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+      velem[0].vertex_buffer_index = ctx->base.vb_slot;
       velem[1].src_offset = 4 * sizeof(float);
       velem[1].src_format = PIPE_FORMAT_R32G32B32A32_UINT;
+      velem[1].vertex_buffer_index = ctx->base.vb_slot;
       ctx->velem_uint_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
    }
 
    if (ctx->has_stream_out) {
       velem[0].src_format = PIPE_FORMAT_R32_UINT;
+      velem[0].vertex_buffer_index = ctx->base.vb_slot;
       ctx->velem_state_readbuf = pipe->create_vertex_elements_state(pipe, 1, &velem[0]);
    }
 
@@ -387,7 +394,6 @@ static void blitter_unset_running_flag(struct blitter_context_priv *ctx)
 
 static void blitter_check_saved_vertex_states(struct blitter_context_priv *ctx)
 {
-   assert(ctx->base.saved_num_vertex_buffers != ~0);
    assert(ctx->base.saved_velem_state != INVALID_PTR);
    assert(ctx->base.saved_vs != INVALID_PTR);
    assert(!ctx->has_geometry_shader || ctx->base.saved_gs != INVALID_PTR);
@@ -400,18 +406,10 @@ static void blitter_restore_vertex_states(struct blitter_context_priv *ctx)
    struct pipe_context *pipe = ctx->base.pipe;
    unsigned i;
 
-   /* Vertex buffers. */
-   pipe->set_vertex_buffers(pipe,
-                            ctx->base.saved_num_vertex_buffers,
-                            ctx->base.saved_vertex_buffers);
-
-   for (i = 0; i < ctx->base.saved_num_vertex_buffers; i++) {
-      if (ctx->base.saved_vertex_buffers[i].buffer) {
-         pipe_resource_reference(&ctx->base.saved_vertex_buffers[i].buffer,
-                                 NULL);
-      }
-   }
-   ctx->base.saved_num_vertex_buffers = ~0;
+   /* Vertex buffer. */
+   pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1,
+                            &ctx->base.saved_vertex_buffer);
+   pipe_resource_reference(&ctx->base.saved_vertex_buffer.buffer, NULL);
 
    /* Vertex elements. */
    pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state);
@@ -935,8 +933,8 @@ static void blitter_draw(struct blitter_context_priv *ctx,
    u_upload_data(ctx->upload, 0, sizeof(ctx->vertices), ctx->vertices,
                  &offset, &buf);
    u_upload_unmap(ctx->upload);
-   util_draw_vertex_buffer(ctx->base.pipe, NULL, buf, offset,
-                           PIPE_PRIM_TRIANGLE_FAN, 4, 2);
+   util_draw_vertex_buffer(ctx->base.pipe, NULL, buf, ctx->base.vb_slot,
+                           offset, PIPE_PRIM_TRIANGLE_FAN, 4, 2);
    pipe_resource_reference(&buf, NULL);
 }
 
@@ -1687,7 +1685,7 @@ void util_blitter_copy_buffer(struct blitter_context *blitter,
    vb.buffer_offset = srcx;
    vb.stride = 4;
 
-   pipe->set_vertex_buffers(pipe, 1, &vb);
+   pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, &vb);
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state_readbuf);
    pipe->bind_vs_state(pipe, ctx->vs_pos_only);
    if (ctx->has_geometry_shader)
index c49faaad717a9cd227d70949cf497d5fbaeb5c0d..b96e68e9310616dc1729b81279a5b643b8ff3292 100644 (file)
@@ -104,8 +104,8 @@ struct blitter_context
    unsigned saved_num_sampler_views;
    struct pipe_sampler_view *saved_sampler_views[PIPE_MAX_SAMPLERS];
 
-   unsigned saved_num_vertex_buffers;
-   struct pipe_vertex_buffer saved_vertex_buffers[PIPE_MAX_ATTRIBS];
+   unsigned vb_slot;
+   struct pipe_vertex_buffer saved_vertex_buffer;
 
    unsigned saved_num_so_targets;
    struct pipe_stream_output_target *saved_so_targets[PIPE_MAX_SO_BUFFERS];
@@ -466,17 +466,13 @@ util_blitter_save_fragment_sampler_views(struct blitter_context *blitter,
 }
 
 static INLINE void
-util_blitter_save_vertex_buffers(struct blitter_context *blitter,
-                                 unsigned num_vertex_buffers,
-                                 struct pipe_vertex_buffer *vertex_buffers)
+util_blitter_save_vertex_buffer_slot(struct blitter_context *blitter,
+                                     struct pipe_vertex_buffer *vertex_buffers)
 {
-   assert(num_vertex_buffers <= Elements(blitter->saved_vertex_buffers));
-
-   blitter->saved_num_vertex_buffers = 0;
-   util_copy_vertex_buffers(blitter->saved_vertex_buffers,
-                            (unsigned*)&blitter->saved_num_vertex_buffers,
-                            vertex_buffers,
-                            num_vertex_buffers);
+   pipe_resource_reference(&blitter->saved_vertex_buffer.buffer,
+                           vertex_buffers[blitter->vb_slot].buffer);
+   memcpy(&blitter->saved_vertex_buffer, &vertex_buffers[blitter->vb_slot],
+          sizeof(struct pipe_vertex_buffer));
 }
 
 static INLINE void
index 81c4f107ea9b4a6a04b0407a2906276fa9c11797..3fe324afa80f230fc50649d0f209c9a1a43bb550 100644 (file)
@@ -42,6 +42,7 @@ void
 util_draw_vertex_buffer(struct pipe_context *pipe,
                         struct cso_context *cso,
                         struct pipe_resource *vbuf,
+                        uint vbuf_slot,
                         uint offset,
                         uint prim_type,
                         uint num_verts,
@@ -60,10 +61,10 @@ util_draw_vertex_buffer(struct pipe_context *pipe,
    /* note: vertex elements already set by caller */
 
    if (cso) {
-      cso_set_vertex_buffers(cso, 1, &vbuffer);
+      cso_set_vertex_buffers(cso, vbuf_slot, 1, &vbuffer);
       cso_draw_arrays(cso, prim_type, 0, num_verts);
    } else {
-      pipe->set_vertex_buffers(pipe, 1, &vbuffer);
+      pipe->set_vertex_buffers(pipe, vbuf_slot, 1, &vbuffer);
       util_draw_arrays(pipe, prim_type, 0, num_verts);
    }
 }
@@ -86,7 +87,7 @@ util_draw_user_vertex_buffer(struct cso_context *cso, void *buffer,
 
    /* note: vertex elements already set by caller */
 
-   cso_set_vertex_buffers(cso, 1, &vbuffer);
+   cso_set_vertex_buffers(cso, 0, 1, &vbuffer);
    cso_draw_arrays(cso, prim_type, 0, num_verts);
 }
 
@@ -97,6 +98,7 @@ util_draw_user_vertex_buffer(struct cso_context *cso, void *buffer,
  */
 void 
 util_draw_texquad(struct pipe_context *pipe, struct cso_context *cso,
+                  uint vbuf_slot,
                   float x0, float y0, float x1, float y1, float z)
 {
    uint numAttribs = 2, i, j;
@@ -145,7 +147,8 @@ util_draw_texquad(struct pipe_context *pipe, struct cso_context *cso,
       goto out;
    pipe_buffer_write(pipe, vbuf, 0, vertexBytes, v);
 
-   util_draw_vertex_buffer(pipe, cso, vbuf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, 2);
+   util_draw_vertex_buffer(pipe, cso, vbuf, vbuf_slot, 0,
+                           PIPE_PRIM_TRIANGLE_FAN, 4, 2);
 
 out:
    if (vbuf)
index 2834a4a81150c3d65709982048397760683aaee4..cb17f4e4cb22ed4e66cd859ffdbf77047210c7ad 100644 (file)
@@ -44,8 +44,9 @@ struct cso_context;
 
 extern void 
 util_draw_vertex_buffer(struct pipe_context *pipe, struct cso_context *cso,
-                        struct pipe_resource *vbuf, uint offset,
-                        uint num_attribs, uint num_verts, uint prim_type);
+                        struct pipe_resource *vbuf, uint vbuf_slot,
+                        uint offset, uint prim_type, uint num_attribs,
+                        uint num_verts);
 
 void
 util_draw_user_vertex_buffer(struct cso_context *cso, void *buffer,
@@ -53,6 +54,7 @@ util_draw_user_vertex_buffer(struct cso_context *cso, void *buffer,
 
 extern void 
 util_draw_texquad(struct pipe_context *pipe, struct cso_context *cso,
+                  uint vbuf_slot,
                   float x0, float y0, float x1, float y1, float z);
 
 
index 4d8adb9f3551726868d207a6089c8e9d39a12312..48ebdb9fa3de4892ea9608209d015d2c19efe1ac 100644 (file)
@@ -1287,7 +1287,7 @@ util_create_gen_mipmap(struct pipe_context *pipe,
    for (i = 0; i < 2; i++) {
       ctx->velem[i].src_offset = i * 4 * sizeof(float);
       ctx->velem[i].instance_divisor = 0;
-      ctx->velem[i].vertex_buffer_index = 0;
+      ctx->velem[i].vertex_buffer_index = cso_get_aux_vertex_buffer_slot(cso);
       ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    }
 
@@ -1565,7 +1565,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
    cso_save_geometry_shader(ctx->cso);
    cso_save_viewport(ctx->cso);
    cso_save_vertex_elements(ctx->cso);
-   cso_save_vertex_buffers(ctx->cso);
+   cso_save_aux_vertex_buffer_slot(ctx->cso);
 
    /* bind our state */
    cso_set_blend(ctx->cso, is_depth ? &ctx->blend_keep_color :
@@ -1673,6 +1673,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
          util_draw_vertex_buffer(ctx->pipe,
                                  ctx->cso,
                                  ctx->vbuf,
+                                 cso_get_aux_vertex_buffer_slot(ctx->cso),
                                  offset,
                                  PIPE_PRIM_TRIANGLE_FAN,
                                  4,  /* verts */
@@ -1697,5 +1698,5 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
    cso_restore_viewport(ctx->cso);
    cso_restore_vertex_elements(ctx->cso);
    cso_restore_stream_outputs(ctx->cso);
-   cso_restore_vertex_buffers(ctx->cso);
+   cso_restore_aux_vertex_buffer_slot(ctx->cso);
 }
diff --git a/src/gallium/auxiliary/util/u_helpers.c b/src/gallium/auxiliary/util/u_helpers.c
new file mode 100644 (file)
index 0000000..ac1edcd
--- /dev/null
@@ -0,0 +1,90 @@
+/**************************************************************************
+ *
+ * Copyright 2012 Marek Olšák <maraeo@gmail.com>
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS AND/OR THEIR SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_helpers.h"
+#include "util/u_inlines.h"
+
+/**
+ * This function is used to copy an array of pipe_vertex_buffer structures,
+ * while properly referencing the pipe_vertex_buffer::buffer member.
+ *
+ * enabled_buffers is updated such that the bits corresponding to the indices
+ * of disabled buffers are set to 0 and the enabled ones are set to 1.
+ *
+ * \sa util_copy_framebuffer_state
+ */
+void util_set_vertex_buffers_mask(struct pipe_vertex_buffer *dst,
+                                  uint32_t *enabled_buffers,
+                                  const struct pipe_vertex_buffer *src,
+                                  unsigned start_slot, unsigned count)
+{
+   unsigned i;
+   uint32_t bitmask = 0;
+
+   dst += start_slot;
+
+   if (src) {
+      for (i = 0; i < count; i++) {
+         if (src[i].buffer || src[i].user_buffer) {
+            bitmask |= 1 << i;
+         }
+         pipe_resource_reference(&dst[i].buffer, src[i].buffer);
+      }
+
+      /* Copy over the other members of pipe_vertex_buffer. */
+      memcpy(dst, src, count * sizeof(struct pipe_vertex_buffer));
+
+      *enabled_buffers &= ~(((1ull << count) - 1) << start_slot);
+      *enabled_buffers |= bitmask << start_slot;
+   }
+   else {
+      /* Unreference the buffers. */
+      for (i = 0; i < count; i++) {
+         pipe_resource_reference(&dst[i].buffer, NULL);
+         dst[i].user_buffer = NULL;
+      }
+
+      *enabled_buffers &= ~(((1ull << count) - 1) << start_slot);
+   }
+}
+
+/**
+ * Same as util_set_vertex_buffers_mask, but it only returns the number
+ * of bound buffers.
+ */
+void util_set_vertex_buffers_count(struct pipe_vertex_buffer *dst,
+                                   unsigned *dst_count,
+                                   const struct pipe_vertex_buffer *src,
+                                   unsigned start_slot, unsigned count)
+{
+   uint32_t enabled_buffers = (1ull << *dst_count) - 1;
+
+   util_set_vertex_buffers_mask(dst, &enabled_buffers, src, start_slot,
+                                count);
+
+   *dst_count = util_last_bit(enabled_buffers);
+}
diff --git a/src/gallium/auxiliary/util/u_helpers.h b/src/gallium/auxiliary/util/u_helpers.h
new file mode 100644 (file)
index 0000000..09c7116
--- /dev/null
@@ -0,0 +1,51 @@
+/**************************************************************************
+ *
+ * Copyright 2012 Marek Olšák <maraeo@gmail.com>
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS AND/OR THEIR SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef U_HELPERS_H
+#define U_HELPERS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "pipe/p_state.h"
+
+void util_set_vertex_buffers_mask(struct pipe_vertex_buffer *dst,
+                                  uint32_t *enabled_buffers,
+                                  const struct pipe_vertex_buffer *src,
+                                  unsigned start_slot, unsigned count);
+
+void util_set_vertex_buffers_count(struct pipe_vertex_buffer *dst,
+                                   unsigned *dst_count,
+                                   const struct pipe_vertex_buffer *src,
+                                   unsigned start_slot, unsigned count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
index 5c6e7eb3234a2bae31142d65215c8c05282b30e8..3d68cf5400e5716e3e9fdf0862d8753a1930fba2 100644 (file)
@@ -449,34 +449,6 @@ static INLINE boolean util_get_offset(
    }
 }
 
-/**
- * This function is used to copy an array of pipe_vertex_buffer structures,
- * while properly referencing the pipe_vertex_buffer::buffer member.
- *
- * \sa util_copy_framebuffer_state
- */
-static INLINE void util_copy_vertex_buffers(struct pipe_vertex_buffer *dst,
-                                            unsigned *dst_count,
-                                            const struct pipe_vertex_buffer *src,
-                                            unsigned src_count)
-{
-   unsigned i;
-
-   /* Reference the buffers of 'src' in 'dst'. */
-   for (i = 0; i < src_count; i++) {
-      pipe_resource_reference(&dst[i].buffer, src[i].buffer);
-   }
-   /* Unreference the rest of the buffers in 'dst'. */
-   for (; i < *dst_count; i++) {
-      pipe_resource_reference(&dst[i].buffer, NULL);
-   }
-
-   /* Update the size of 'dst' and copy over the other members
-    * of pipe_vertex_buffer. */
-   *dst_count = src_count;
-   memcpy(dst, src, src_count * sizeof(struct pipe_vertex_buffer));
-}
-
 static INLINE float
 util_get_min_point_size(const struct pipe_rasterizer_state *state)
 {
index 4047bd9b0162366e084ceb718335baeb2a166860..607fbecb02f5bd7d51dab8efff397e7b7688a99b 100644 (file)
@@ -482,12 +482,16 @@ unsigned ffs( unsigned u )
  */
 static INLINE unsigned util_last_bit(unsigned u)
 {
+#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304)
+   return u == 0 ? 0 : 32 - __builtin_clz(u);
+#else
    unsigned r = 0;
    while (u) {
        r++;
        u >>= 1;
    }
    return r;
+#endif
 }
 
 
index 1cc83c3dd39981da369dd66fc407a013dd7da3fa..7fb492882f514696f53ef660890c98d183be6bc8 100644 (file)
@@ -89,17 +89,17 @@ struct u_vbuf {
    /* This is what was set in set_vertex_buffers.
     * May contain user buffers. */
    struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
-   unsigned nr_vertex_buffers;
+   uint32_t enabled_vb_mask;
 
-   /* Saved vertex buffers. */
-   struct pipe_vertex_buffer vertex_buffer_saved[PIPE_MAX_ATTRIBS];
-   unsigned nr_vertex_buffers_saved;
+   /* Saved vertex buffer. */
+   unsigned aux_vertex_buffer_slot;
+   struct pipe_vertex_buffer aux_vertex_buffer_saved;
 
    /* Vertex buffers for the driver.
-    * There are no user buffers. */
+    * There are usually no user buffers. */
    struct pipe_vertex_buffer real_vertex_buffer[PIPE_MAX_ATTRIBS];
-   unsigned nr_real_vertex_buffers;
-   boolean vertex_buffers_dirty;
+   uint32_t dirty_real_vb_mask; /* which buffers are dirty since the last
+                                   call of set_vertex_buffers */
 
    /* The index buffer. */
    struct pipe_index_buffer index_buffer;
@@ -174,11 +174,12 @@ void u_vbuf_get_caps(struct pipe_screen *screen, struct u_vbuf_caps *caps)
 
 struct u_vbuf *
 u_vbuf_create(struct pipe_context *pipe,
-              struct u_vbuf_caps *caps)
+              struct u_vbuf_caps *caps, unsigned aux_vertex_buffer_index)
 {
    struct u_vbuf *mgr = CALLOC_STRUCT(u_vbuf);
 
    mgr->caps = *caps;
+   mgr->aux_vertex_buffer_slot = aux_vertex_buffer_index;
    mgr->pipe = pipe;
    mgr->cso_cache = cso_cache_create();
    mgr->translate_cache = translate_cache_create();
@@ -239,16 +240,20 @@ void u_vbuf_set_vertex_elements(struct u_vbuf *mgr, unsigned count,
 
 void u_vbuf_destroy(struct u_vbuf *mgr)
 {
+   struct pipe_screen *screen = mgr->pipe->screen;
    unsigned i;
+   unsigned num_vb = screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
+                                              PIPE_SHADER_CAP_MAX_INPUTS);
 
-   mgr->pipe->set_vertex_buffers(mgr->pipe, 0, NULL);
+   mgr->pipe->set_vertex_buffers(mgr->pipe, 0, num_vb, NULL);
 
-   for (i = 0; i < mgr->nr_vertex_buffers; i++) {
+   for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
       pipe_resource_reference(&mgr->vertex_buffer[i].buffer, NULL);
    }
-   for (i = 0; i < mgr->nr_real_vertex_buffers; i++) {
+   for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
       pipe_resource_reference(&mgr->real_vertex_buffer[i].buffer, NULL);
    }
+   pipe_resource_reference(&mgr->aux_vertex_buffer_saved.buffer, NULL);
 
    translate_cache_destroy(mgr->translate_cache);
    u_upload_destroy(mgr->uploader);
@@ -267,39 +272,42 @@ u_vbuf_translate_buffers(struct u_vbuf *mgr, struct translate_key *key,
    struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0};
    struct pipe_resource *out_buffer = NULL;
    uint8_t *out_map;
-   unsigned i, out_offset;
+   unsigned out_offset, mask;
 
    /* Get a translate object. */
    tr = translate_cache_find(mgr->translate_cache, key);
 
    /* Map buffers we want to translate. */
-   for (i = 0; i < mgr->nr_vertex_buffers; i++) {
-      if (vb_mask & (1 << i)) {
-         struct pipe_vertex_buffer *vb = &mgr->vertex_buffer[i];
-         unsigned offset = vb->buffer_offset + vb->stride * start_vertex;
-         uint8_t *map;
+   mask = vb_mask;
+   while (mask) {
+      struct pipe_vertex_buffer *vb;
+      unsigned offset;
+      uint8_t *map;
+      unsigned i = u_bit_scan(&mask);
 
-         if (vb->user_buffer) {
-            map = (uint8_t*)vb->user_buffer + offset;
-         } else {
-            unsigned size = vb->stride ? num_vertices * vb->stride
-                                       : sizeof(double)*4;
+      vb = &mgr->vertex_buffer[i];
+      offset = vb->buffer_offset + vb->stride * start_vertex;
 
-            if (offset+size > vb->buffer->width0) {
-               size = vb->buffer->width0 - offset;
-            }
+      if (vb->user_buffer) {
+         map = (uint8_t*)vb->user_buffer + offset;
+      } else {
+         unsigned size = vb->stride ? num_vertices * vb->stride
+                                    : sizeof(double)*4;
 
-            map = pipe_buffer_map_range(mgr->pipe, vb->buffer, offset, size,
-                                        PIPE_TRANSFER_READ, &vb_transfer[i]);
+         if (offset+size > vb->buffer->width0) {
+            size = vb->buffer->width0 - offset;
          }
 
-         /* Subtract min_index so that indexing with the index buffer works. */
-         if (unroll_indices) {
-            map -= vb->stride * min_index;
-         }
+         map = pipe_buffer_map_range(mgr->pipe, vb->buffer, offset, size,
+                                     PIPE_TRANSFER_READ, &vb_transfer[i]);
+      }
 
-         tr->set_buffer(tr, i, map, vb->stride, ~0);
+      /* Subtract min_index so that indexing with the index buffer works. */
+      if (unroll_indices) {
+         map -= vb->stride * min_index;
       }
+
+      tr->set_buffer(tr, i, map, vb->stride, ~0);
    }
 
    /* Translate. */
@@ -354,7 +362,10 @@ u_vbuf_translate_buffers(struct u_vbuf *mgr, struct translate_key *key,
    }
 
    /* Unmap all buffers. */
-   for (i = 0; i < mgr->nr_vertex_buffers; i++) {
+   mask = vb_mask;
+   while (mask) {
+      unsigned i = u_bit_scan(&mask);
+
       if (vb_transfer[i]) {
          pipe_buffer_unmap(mgr->pipe, vb_transfer[i]);
       }
@@ -379,7 +390,7 @@ u_vbuf_translate_find_free_vb_slots(struct u_vbuf *mgr,
    /* Set the bit for each buffer which is incompatible, or isn't set. */
    uint32_t unused_vb_mask =
       mgr->ve->incompatible_vb_mask_all | mgr->incompatible_vb_mask |
-      ~((1 << mgr->nr_vertex_buffers) - 1);
+      ~mgr->enabled_vb_mask;
 
    memset(fallback_vbs, ~0, sizeof(fallback_vbs));
 
@@ -389,20 +400,21 @@ u_vbuf_translate_find_free_vb_slots(struct u_vbuf *mgr,
          uint32_t index;
 
          if (!unused_vb_mask) {
-            /* fail, reset the number to its original value */
-            mgr->nr_real_vertex_buffers = mgr->nr_vertex_buffers;
             return FALSE;
          }
 
          index = ffs(unused_vb_mask) - 1;
          fallback_vbs[type] = index;
-         if (index >= mgr->nr_real_vertex_buffers) {
-            mgr->nr_real_vertex_buffers = index + 1;
-         }
          /*printf("found slot=%i for type=%i\n", index, type);*/
       }
    }
 
+   for (type = 0; type < VB_NUM; type++) {
+      if (mask[type]) {
+         mgr->dirty_real_vb_mask |= 1 << fallback_vbs[type];
+      }
+   }
+
    memcpy(mgr->fallback_vbs, fallback_vbs, sizeof(fallback_vbs));
    return TRUE;
 }
@@ -568,9 +580,11 @@ static void u_vbuf_translate_end(struct u_vbuf *mgr)
       if (vb != ~0) {
          pipe_resource_reference(&mgr->real_vertex_buffer[vb].buffer, NULL);
          mgr->fallback_vbs[i] = ~0;
+
+         /* This will cause the buffer to be unbound in the driver later. */
+         mgr->dirty_real_vb_mask |= 1 << vb;
       }
    }
-   mgr->nr_real_vertex_buffers = mgr->nr_vertex_buffers;
 }
 
 #define FORMAT_REPLACE(what, withwhat) \
@@ -700,45 +714,77 @@ static void u_vbuf_delete_vertex_elements(struct u_vbuf *mgr, void *cso)
    FREE(ve);
 }
 
-void u_vbuf_set_vertex_buffers(struct u_vbuf *mgr, unsigned count,
+void u_vbuf_set_vertex_buffers(struct u_vbuf *mgr,
+                               unsigned start_slot, unsigned count,
                                const struct pipe_vertex_buffer *bufs)
 {
    unsigned i;
+   /* which buffers are enabled */
+   uint32_t enabled_vb_mask = 0;
+   /* which buffers are in user memory */
+   uint32_t user_vb_mask = 0;
+   /* which buffers are incompatible with the driver */
+   uint32_t incompatible_vb_mask = 0;
+   /* which buffers have a non-zero stride */
+   uint32_t nonzero_stride_vb_mask = 0;
+   uint32_t mask = ~(((1ull << count) - 1) << start_slot);
+
+   /* Zero out the bits we are going to rewrite completely. */
+   mgr->user_vb_mask &= mask;
+   mgr->incompatible_vb_mask &= mask;
+   mgr->nonzero_stride_vb_mask &= mask;
+   mgr->enabled_vb_mask &= mask;
+
+   if (!bufs) {
+      struct pipe_context *pipe = mgr->pipe;
+      /* Unbind. */
+      mgr->dirty_real_vb_mask &= mask;
 
-   mgr->user_vb_mask = 0;
-   mgr->incompatible_vb_mask = 0;
-   mgr->nonzero_stride_vb_mask = 0;
+      for (i = 0; i < count; i++) {
+         unsigned dst_index = start_slot + i;
+
+         pipe_resource_reference(&mgr->vertex_buffer[dst_index].buffer, NULL);
+         pipe_resource_reference(&mgr->real_vertex_buffer[dst_index].buffer,
+                                 NULL);
+      }
+
+      pipe->set_vertex_buffers(pipe, start_slot, count, NULL);
+      return;
+   }
 
    for (i = 0; i < count; i++) {
+      unsigned dst_index = start_slot + i;
       const struct pipe_vertex_buffer *vb = &bufs[i];
-      struct pipe_vertex_buffer *orig_vb = &mgr->vertex_buffer[i];
-      struct pipe_vertex_buffer *real_vb = &mgr->real_vertex_buffer[i];
+      struct pipe_vertex_buffer *orig_vb = &mgr->vertex_buffer[dst_index];
+      struct pipe_vertex_buffer *real_vb = &mgr->real_vertex_buffer[dst_index];
+
+      if (!vb->buffer && !vb->user_buffer) {
+         pipe_resource_reference(&orig_vb->buffer, NULL);
+         pipe_resource_reference(&real_vb->buffer, NULL);
+         real_vb->user_buffer = NULL;
+         continue;
+      }
 
       pipe_resource_reference(&orig_vb->buffer, vb->buffer);
       orig_vb->user_buffer = vb->user_buffer;
 
       real_vb->buffer_offset = orig_vb->buffer_offset = vb->buffer_offset;
       real_vb->stride = orig_vb->stride = vb->stride;
-      real_vb->user_buffer = NULL;
 
       if (vb->stride) {
-         mgr->nonzero_stride_vb_mask |= 1 << i;
-      }
-
-      if (!vb->buffer && !vb->user_buffer) {
-         pipe_resource_reference(&real_vb->buffer, NULL);
-         continue;
+         nonzero_stride_vb_mask |= 1 << dst_index;
       }
+      enabled_vb_mask |= 1 << dst_index;
 
       if ((!mgr->caps.buffer_offset_unaligned && vb->buffer_offset % 4 != 0) ||
           (!mgr->caps.buffer_stride_unaligned && vb->stride % 4 != 0)) {
-         mgr->incompatible_vb_mask |= 1 << i;
+         incompatible_vb_mask |= 1 << dst_index;
          pipe_resource_reference(&real_vb->buffer, NULL);
          continue;
       }
 
       if (!mgr->caps.user_vertex_buffers && vb->user_buffer) {
-         mgr->user_vb_mask |= 1 << i;
+         user_vb_mask |= 1 << dst_index;
          pipe_resource_reference(&real_vb->buffer, NULL);
          continue;
       }
@@ -747,16 +793,14 @@ void u_vbuf_set_vertex_buffers(struct u_vbuf *mgr, unsigned count,
       real_vb->user_buffer = vb->user_buffer;
    }
 
-   for (i = count; i < mgr->nr_vertex_buffers; i++) {
-      pipe_resource_reference(&mgr->vertex_buffer[i].buffer, NULL);
-   }
-   for (i = count; i < mgr->nr_real_vertex_buffers; i++) {
-      pipe_resource_reference(&mgr->real_vertex_buffer[i].buffer, NULL);
-   }
+   mgr->user_vb_mask |= user_vb_mask;
+   mgr->incompatible_vb_mask |= incompatible_vb_mask;
+   mgr->nonzero_stride_vb_mask |= nonzero_stride_vb_mask;
+   mgr->enabled_vb_mask |= enabled_vb_mask;
 
-   mgr->nr_vertex_buffers = count;
-   mgr->nr_real_vertex_buffers = count;
-   mgr->vertex_buffers_dirty = TRUE;
+   /* All changed buffers are marked as dirty, even the NULL ones,
+    * which will cause the NULL buffers to be unbound in the driver later. */
+   mgr->dirty_real_vb_mask |= ~mask;
 }
 
 void u_vbuf_set_index_buffer(struct u_vbuf *mgr,
@@ -782,7 +826,7 @@ u_vbuf_upload_buffers(struct u_vbuf *mgr,
 {
    unsigned i;
    unsigned nr_velems = mgr->ve->count;
-   unsigned nr_vbufs = mgr->nr_vertex_buffers;
+   unsigned nr_vbufs = util_last_bit(mgr->enabled_vb_mask);
    struct pipe_vertex_element *velems =
          mgr->using_translate ? mgr->fallback_velems : mgr->ve->ve;
    unsigned start_offset[PIPE_MAX_ATTRIBS];
@@ -978,6 +1022,19 @@ static void u_vbuf_get_minmax_index(struct pipe_context *pipe,
    }
 }
 
+static void u_vbuf_set_driver_vertex_buffers(struct u_vbuf *mgr)
+{
+   struct pipe_context *pipe = mgr->pipe;
+   unsigned start_slot, count;
+
+   start_slot = ffs(mgr->dirty_real_vb_mask) - 1;
+   count = util_last_bit(mgr->dirty_real_vb_mask >> start_slot);
+
+   pipe->set_vertex_buffers(pipe, start_slot, count,
+                            mgr->real_vertex_buffer + start_slot);
+   mgr->dirty_real_vb_mask = 0;
+}
+
 void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info)
 {
    struct pipe_context *pipe = mgr->pipe;
@@ -990,11 +1047,10 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info)
    if (!mgr->incompatible_vb_mask &&
        !mgr->ve->incompatible_elem_mask &&
        !user_vb_mask) {
+
       /* Set vertex buffers if needed. */
-      if (mgr->vertex_buffers_dirty) {
-         pipe->set_vertex_buffers(pipe, mgr->nr_real_vertex_buffers,
-                                  mgr->real_vertex_buffer);
-         mgr->vertex_buffers_dirty = FALSE;
+      if (mgr->dirty_real_vb_mask) {
+         u_vbuf_set_driver_vertex_buffers(mgr);
       }
 
       pipe->draw_vbo(pipe, info);
@@ -1062,6 +1118,7 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info)
    if (user_vb_mask) {
       u_vbuf_upload_buffers(mgr, start_vertex, num_vertices,
                             info->start_instance, info->instance_count);
+      mgr->dirty_real_vb_mask |= user_vb_mask;
    }
 
    /*
@@ -1086,8 +1143,7 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info)
    */
 
    u_upload_unmap(mgr->uploader);
-   pipe->set_vertex_buffers(pipe, mgr->nr_real_vertex_buffers,
-                            mgr->real_vertex_buffer);
+   u_vbuf_set_driver_vertex_buffers(mgr);
 
    if (unlikely(unroll_indices)) {
       struct pipe_draw_info new_info = *info;
@@ -1105,7 +1161,6 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info)
    if (mgr->using_translate) {
       u_vbuf_translate_end(mgr);
    }
-   mgr->vertex_buffers_dirty = TRUE;
 }
 
 void u_vbuf_save_vertex_elements(struct u_vbuf *mgr)
@@ -1126,22 +1181,18 @@ void u_vbuf_restore_vertex_elements(struct u_vbuf *mgr)
    mgr->ve_saved = NULL;
 }
 
-void u_vbuf_save_vertex_buffers(struct u_vbuf *mgr)
+void u_vbuf_save_aux_vertex_buffer_slot(struct u_vbuf *mgr)
 {
-   util_copy_vertex_buffers(mgr->vertex_buffer_saved,
-                            &mgr->nr_vertex_buffers_saved,
-                            mgr->vertex_buffer,
-                            mgr->nr_vertex_buffers);
+   struct pipe_vertex_buffer *vb =
+         &mgr->vertex_buffer[mgr->aux_vertex_buffer_slot];
+
+   pipe_resource_reference(&mgr->aux_vertex_buffer_saved.buffer, vb->buffer);
+   memcpy(&mgr->aux_vertex_buffer_saved, vb, sizeof(*vb));
 }
 
-void u_vbuf_restore_vertex_buffers(struct u_vbuf *mgr)
+void u_vbuf_restore_aux_vertex_buffer_slot(struct u_vbuf *mgr)
 {
-   unsigned i;
-
-   u_vbuf_set_vertex_buffers(mgr, mgr->nr_vertex_buffers_saved,
-                             mgr->vertex_buffer_saved);
-   for (i = 0; i < mgr->nr_vertex_buffers_saved; i++) {
-      pipe_resource_reference(&mgr->vertex_buffer_saved[i].buffer, NULL);
-   }
-   mgr->nr_vertex_buffers_saved = 0;
+   u_vbuf_set_vertex_buffers(mgr, mgr->aux_vertex_buffer_slot, 1,
+                             &mgr->aux_vertex_buffer_saved);
+   pipe_resource_reference(&mgr->aux_vertex_buffer_saved.buffer, NULL);
 }
index 59eb59a119040398002c2880b38db8b2f2d3a6cf..0f82271649d4ad7111d86b82456bdd390653c1d0 100644 (file)
@@ -64,14 +64,15 @@ void u_vbuf_get_caps(struct pipe_screen *screen, struct u_vbuf_caps *caps);
 
 struct u_vbuf *
 u_vbuf_create(struct pipe_context *pipe,
-              struct u_vbuf_caps *caps);
+              struct u_vbuf_caps *caps, unsigned aux_vertex_buffer_index);
 
 void u_vbuf_destroy(struct u_vbuf *mgr);
 
 /* State and draw functions. */
 void u_vbuf_set_vertex_elements(struct u_vbuf *mgr, unsigned count,
                                 const struct pipe_vertex_element *states);
-void u_vbuf_set_vertex_buffers(struct u_vbuf *mgr, unsigned count,
+void u_vbuf_set_vertex_buffers(struct u_vbuf *mgr,
+                               unsigned start_slot, unsigned count,
                                const struct pipe_vertex_buffer *bufs);
 void u_vbuf_set_index_buffer(struct u_vbuf *mgr,
                              const struct pipe_index_buffer *ib);
@@ -80,7 +81,7 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info);
 /* Save/restore functionality. */
 void u_vbuf_save_vertex_elements(struct u_vbuf *mgr);
 void u_vbuf_restore_vertex_elements(struct u_vbuf *mgr);
-void u_vbuf_save_vertex_buffers(struct u_vbuf *mgr);
-void u_vbuf_restore_vertex_buffers(struct u_vbuf *mgr);
+void u_vbuf_save_aux_vertex_buffer_slot(struct u_vbuf *mgr);
+void u_vbuf_restore_aux_vertex_buffer_slot(struct u_vbuf *mgr);
 
 #endif
index 0cb1a9f38ad30b503ab4c197de4fc659fbf84fb1..7ea13bf593da95aa02a607d37b174af670a33262 100644 (file)
@@ -1013,7 +1013,7 @@ vl_compositor_render(struct vl_compositor_state *s,
    c->pipe->set_scissor_state(c->pipe, &s->scissor);
    c->pipe->set_framebuffer_state(c->pipe, &c->fb_state);
    c->pipe->bind_vs_state(c->pipe, c->vs);
-   c->pipe->set_vertex_buffers(c->pipe, 1, &c->vertex_buf);
+   c->pipe->set_vertex_buffers(c->pipe, 0, 1, &c->vertex_buf);
    c->pipe->bind_vertex_elements_state(c->pipe, c->vertex_elems_state);
    pipe_set_constant_buffer(c->pipe, PIPE_SHADER_FRAGMENT, 0, s->csc_matrix);
    c->pipe->bind_rasterizer_state(c->pipe, c->rast);
index 333fcc8f813506aa7701fbcfb1d2a2991976759b..438bedab226cab9d716b1d1a0bd7b40f65b39e70 100644 (file)
@@ -311,7 +311,7 @@ vl_matrix_filter_render(struct vl_matrix_filter *filter,
    filter->pipe->bind_fs_state(filter->pipe, filter->fs);
    filter->pipe->set_framebuffer_state(filter->pipe, &fb_state);
    filter->pipe->set_viewport_state(filter->pipe, &viewport);
-   filter->pipe->set_vertex_buffers(filter->pipe, 1, &filter->quad);
+   filter->pipe->set_vertex_buffers(filter->pipe, 0, 1, &filter->quad);
    filter->pipe->bind_vertex_elements_state(filter->pipe, filter->ves);
 
    util_draw_arrays(filter->pipe, PIPE_PRIM_QUADS, 0, 4);
index 5770ff8258acf3faa8ee5f57c1fa0d6098717b71..dfa280a6d2a4924b5f3c820a28cf2ec4a137bc17 100644 (file)
@@ -390,7 +390,7 @@ vl_median_filter_render(struct vl_median_filter *filter,
    filter->pipe->bind_fs_state(filter->pipe, filter->fs);
    filter->pipe->set_framebuffer_state(filter->pipe, &fb_state);
    filter->pipe->set_viewport_state(filter->pipe, &viewport);
-   filter->pipe->set_vertex_buffers(filter->pipe, 1, &filter->quad);
+   filter->pipe->set_vertex_buffers(filter->pipe, 0, 1, &filter->quad);
    filter->pipe->bind_vertex_elements_state(filter->pipe, filter->ves);
 
    util_draw_arrays(filter->pipe, PIPE_PRIM_QUADS, 0, 4);
index 4614c8abd37e9cef84bc8a63e54c24e191d41f51..eb82b95bb4c43e460fe2d0d875745ff6094bb789 100644 (file)
@@ -711,7 +711,7 @@ vl_mpeg12_end_frame(struct pipe_video_decoder *decoder,
          if (!ref_frames[j] || !ref_frames[j][i]) continue;
 
          vb[2] = vl_vb_get_mv(&buf->vertex_stream, j);;
-         dec->base.context->set_vertex_buffers(dec->base.context, 3, vb);
+         dec->base.context->set_vertex_buffers(dec->base.context, 0, 3, vb);
 
          vl_mc_render_ref(i ? &dec->mc_c : &dec->mc_y, &buf->mc[i], ref_frames[j][i]);
       }
@@ -722,7 +722,7 @@ vl_mpeg12_end_frame(struct pipe_video_decoder *decoder,
       if (!buf->num_ycbcr_blocks[i]) continue;
 
       vb[1] = vl_vb_get_ycbcr(&buf->vertex_stream, i);
-      dec->base.context->set_vertex_buffers(dec->base.context, 2, vb);
+      dec->base.context->set_vertex_buffers(dec->base.context, 0, 2, vb);
 
       vl_zscan_render(i ? &dec->zscan_c : & dec->zscan_y, &buf->zscan[i] , buf->num_ycbcr_blocks[i]);
 
@@ -741,7 +741,7 @@ vl_mpeg12_end_frame(struct pipe_video_decoder *decoder,
          if (!buf->num_ycbcr_blocks[plane]) continue;
 
          vb[1] = vl_vb_get_ycbcr(&buf->vertex_stream, plane);
-         dec->base.context->set_vertex_buffers(dec->base.context, 2, vb);
+         dec->base.context->set_vertex_buffers(dec->base.context, 0, 2, vb);
 
          if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT)
             vl_idct_prepare_stage2(i ? &dec->idct_c : &dec->idct_y, &buf->idct[plane]);
index 3400a4d213a744e0f6779d2ef625a7d5e7ac28a8..ecdfe068f796b5e89d6b569362293ad8cfa9e1eb 100644 (file)
@@ -621,7 +621,7 @@ galahad_context_set_fragment_sampler_views(struct pipe_context *_pipe,
 
 static void
 galahad_context_set_vertex_buffers(struct pipe_context *_pipe,
-                            unsigned num_buffers,
+                            unsigned start_slot, unsigned num_buffers,
                             const struct pipe_vertex_buffer *_buffers)
 {
    struct galahad_context *glhd_pipe = galahad_context(_pipe);
@@ -638,7 +638,7 @@ galahad_context_set_vertex_buffers(struct pipe_context *_pipe,
    }
 
    pipe->set_vertex_buffers(pipe,
-                            num_buffers,
+                            start_slot, num_buffers,
                             buffers);
 }
 
index d96ac7ab938266381a825da940d5367b96d219b9..7fa648fc4d92e051216958d23fb54f5e1c9249c2 100644 (file)
@@ -30,6 +30,7 @@
 
 
 #include "draw/draw_context.h"
+#include "util/u_helpers.h"
 #include "util/u_inlines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
@@ -926,19 +927,18 @@ static void i915_delete_rasterizer_state(struct pipe_context *pipe,
 }
 
 static void i915_set_vertex_buffers(struct pipe_context *pipe,
-                                    unsigned count,
+                                    unsigned start_slot, unsigned count,
                                     const struct pipe_vertex_buffer *buffers)
 {
    struct i915_context *i915 = i915_context(pipe);
    struct draw_context *draw = i915->draw;
 
-   util_copy_vertex_buffers(i915->vertex_buffers,
-                            &i915->nr_vertex_buffers,
-                            buffers, count);
+   util_set_vertex_buffers_count(i915->vertex_buffers,
+                                 &i915->nr_vertex_buffers,
+                                 buffers, start_slot, count);
 
    /* pass-through to draw module */
-   draw_set_vertex_buffers(draw, count, buffers);
-
+   draw_set_vertex_buffers(draw, start_slot, count, buffers);
 }
 
 static void *
index 331d6e230d0747d540cbc7d2adba3b0325f5830d..08a6f343922dc1410776c525f0ae86226381733a 100644 (file)
@@ -55,7 +55,7 @@ i915_util_blitter_save_states(struct i915_context *i915)
    util_blitter_save_viewport(i915->blitter, &i915->viewport);
    util_blitter_save_scissor(i915->blitter, &i915->scissor);
    util_blitter_save_vertex_elements(i915->blitter, i915->velems);
-   util_blitter_save_vertex_buffers(i915->blitter, i915->nr_vertex_buffers,
+   util_blitter_save_vertex_buffer_slot(i915->blitter,
                                     i915->vertex_buffers);
 
    util_blitter_save_framebuffer(i915->blitter, &i915->framebuffer);
index fb2f78764a44cc721ecfe54ea6065d607d605bb7..0325b151f834c943ddf53897db99bbe10826524c 100644 (file)
@@ -565,7 +565,7 @@ identity_set_vertex_sampler_views(struct pipe_context *_pipe,
 
 static void
 identity_set_vertex_buffers(struct pipe_context *_pipe,
-                            unsigned num_buffers,
+                            unsigned start_slot, unsigned num_buffers,
                             const struct pipe_vertex_buffer *_buffers)
 {
    struct identity_context *id_pipe = identity_context(_pipe);
@@ -582,7 +582,7 @@ identity_set_vertex_buffers(struct pipe_context *_pipe,
    }
 
    pipe->set_vertex_buffers(pipe,
-                            num_buffers,
+                            start_slot, num_buffers,
                             buffers);
 }
 
index f37b3ca1cea3fcf4e776082c8354da0fad37276c..3497edf9d1ce1b767d276e468566d1f970c68f5a 100644 (file)
@@ -68,8 +68,12 @@ llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
     */
    for (i = 0; i < lp->num_vertex_buffers; i++) {
       const void *buf = lp->vertex_buffer[i].user_buffer;
-      if (!buf)
+      if (!buf) {
+         if (!lp->vertex_buffer[i].buffer) {
+            continue;
+         }
          buf = llvmpipe_resource_data(lp->vertex_buffer[i].buffer);
+      }
       draw_set_mapped_vertex_buffer(draw, i, buf);
    }
 
index 4a74cd7c9d41c3cf0bf9d377483d77c3826f1ae6..7594d028b712dd6935d8facf8b1d6166ff7ec9cf 100644 (file)
@@ -33,6 +33,7 @@
 #include "lp_state.h"
 
 #include "draw/draw_context.h"
+#include "util/u_helpers.h"
 #include "util/u_inlines.h"
 #include "util/u_transfer.h"
 
@@ -75,20 +76,20 @@ llvmpipe_delete_vertex_elements_state(struct pipe_context *pipe, void *velems)
 
 static void
 llvmpipe_set_vertex_buffers(struct pipe_context *pipe,
-                            unsigned count,
+                            unsigned start_slot, unsigned count,
                             const struct pipe_vertex_buffer *buffers)
 {
    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
 
    assert(count <= PIPE_MAX_ATTRIBS);
 
-   util_copy_vertex_buffers(llvmpipe->vertex_buffer,
-                            &llvmpipe->num_vertex_buffers,
-                            buffers, count);
+   util_set_vertex_buffers_count(llvmpipe->vertex_buffer,
+                                 &llvmpipe->num_vertex_buffers,
+                                 buffers, start_slot, count);
 
    llvmpipe->dirty |= LP_NEW_VERTEX;
 
-   draw_set_vertex_buffers(llvmpipe->draw, count, buffers);
+   draw_set_vertex_buffers(llvmpipe->draw, start_slot, count, buffers);
 }
 
 
index a4789b4f5c3cfa02e3d0ed734ec127498145c642..e42f4c838e93fb95bdd9bc2272ca479f4f85a376 100644 (file)
@@ -204,8 +204,7 @@ static void lp_blit(struct pipe_context *pipe,
 
    /* XXX turn off occlusion and streamout queries */
 
-   util_blitter_save_vertex_buffers(lp->blitter, lp->num_vertex_buffers,
-                                    lp->vertex_buffer);
+   util_blitter_save_vertex_buffer_slot(lp->blitter, lp->vertex_buffer);
    util_blitter_save_vertex_elements(lp->blitter, (void*)lp->velems);
    util_blitter_save_vertex_shader(lp->blitter, (void*)lp->vs);
    util_blitter_save_geometry_shader(lp->blitter, (void*)lp->gs);
index dbfe35b668c9fcba9bc11834d1e3dd062d119049..16ce9b457d9c605e1a5da47af360dea368412ad9 100644 (file)
@@ -215,8 +215,9 @@ static void noop_set_index_buffer(struct pipe_context *ctx,
 {
 }
 
-static void noop_set_vertex_buffers(struct pipe_context *ctx, unsigned count,
-                                       const struct pipe_vertex_buffer *buffers)
+static void noop_set_vertex_buffers(struct pipe_context *ctx,
+                                   unsigned start_slot, unsigned count,
+                                   const struct pipe_vertex_buffer *buffers)
 {
 }
 
index 46e8536281595413995266e288b5e04ad798f289..51fe4f86ed1126a895948f2538d32467a3729c99 100644 (file)
@@ -379,7 +379,7 @@ nv30_render_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
    if (nv30->draw_dirty & NV30_NEW_CLIP)
       draw_set_clip_state(draw, &nv30->clip);
    if (nv30->draw_dirty & NV30_NEW_ARRAYS) {
-      draw_set_vertex_buffers(draw, nv30->num_vtxbufs, nv30->vtxbuf);
+      draw_set_vertex_buffers(draw, 0, nv30->num_vtxbufs, nv30->vtxbuf);
       draw_set_vertex_elements(draw, nv30->vertex->num_elements, nv30->vertex->pipe);
    }
    if (nv30->draw_dirty & NV30_NEW_FRAGPROG) {
@@ -404,10 +404,14 @@ nv30_render_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
 
    for (i = 0; i < nv30->num_vtxbufs; i++) {
       const void *map = nv30->vtxbuf[i].user_buffer;
-      if (!map)
+      if (!map) {
+         if (!nv30->vtxbuf[i].buffer) {
+            continue;
+         }
          map = pipe_buffer_map(pipe, nv30->vtxbuf[i].buffer,
                                   PIPE_TRANSFER_UNSYNCHRONIZED |
                                   PIPE_TRANSFER_READ, &transfer[i]);
+      }
       draw_set_mapped_vertex_buffer(draw, i, map);
    }
 
index e89725feb2f04ef4c916f7a57c5a34bcfe7e45af..5d941ab771eb88ac9f0093a857491a29bba89cdd 100644 (file)
@@ -193,9 +193,7 @@ nv30_blit(struct pipe_context *pipe,
 
    /* XXX turn off occlusion queries */
 
-   util_blitter_save_vertex_buffers(nv30->blitter,
-                                    nv30->num_vtxbufs,
-                                    nv30->vtxbuf);
+   util_blitter_save_vertex_buffer_slot(nv30->blitter, nv30->vtxbuf);
    util_blitter_save_vertex_elements(nv30->blitter, nv30->vertex);
    util_blitter_save_vertex_shader(nv30->blitter, nv30->vertprog.program);
    util_blitter_save_rasterizer(nv30->blitter, nv30->rast);
index c5867bfa11aee58527dfe0b2601b19e4ee646125..5ec2d462a68da5a1caa8d28173cc0aa056149f25 100644 (file)
@@ -211,6 +211,10 @@ nv30_push_vbo(struct nv30_context *nv30, const struct pipe_draw_info *info)
       struct pipe_vertex_buffer *vb = &nv30->vtxbuf[i];
       struct nv04_resource *res = nv04_resource(vb->buffer);
 
+      if (!vb->buffer && !vb->user_buffer) {
+         continue;
+      }
+
       data = nouveau_resource_map_offset(&nv30->base, res,
                                          vb->buffer_offset, NOUVEAU_BO_RD);
 
@@ -276,8 +280,11 @@ nv30_push_vbo(struct nv30_context *nv30, const struct pipe_draw_info *info)
    if (info->indexed)
       nouveau_resource_unmap(nv04_resource(nv30->idxbuf.buffer));
 
-   for (i = 0; i < nv30->num_vtxbufs; ++i)
-      nouveau_resource_unmap(nv04_resource(nv30->vtxbuf[i].buffer));
+   for (i = 0; i < nv30->num_vtxbufs; ++i) {
+      if (nv30->vtxbuf[i].buffer) {
+         nouveau_resource_unmap(nv04_resource(nv30->vtxbuf[i].buffer));
+      }
+   }
 
    nv30_state_release(nv30);
 }
index 046ba723daee8a308befd65c9b6e415c872c2251..af8bb449fceaa535a3ba722a51ac19b8ce6983b2 100644 (file)
@@ -23,6 +23,7 @@
  *
  */
 
+#include "util/u_helpers.h"
 #include "util/u_inlines.h"
 
 #include "nouveau/nouveau_gldefs.h"
@@ -393,21 +394,15 @@ nv30_set_viewport_state(struct pipe_context *pipe,
 
 static void
 nv30_set_vertex_buffers(struct pipe_context *pipe,
-                        unsigned count,
+                        unsigned start_slot, unsigned count,
                         const struct pipe_vertex_buffer *vb)
 {
     struct nv30_context *nv30 = nv30_context(pipe);
-    unsigned i;
 
     nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXBUF);
 
-    for (i = 0; i < count; ++i)
-       pipe_resource_reference(&nv30->vtxbuf[i].buffer, vb[i].buffer);
-    for (; i < nv30->num_vtxbufs; ++i)
-       pipe_resource_reference(&nv30->vtxbuf[i].buffer, NULL);
-
-    memcpy(nv30->vtxbuf, vb, sizeof(*vb) * count);
-    nv30->num_vtxbufs = count;
+    util_set_vertex_buffers_count(nv30->vtxbuf, &nv30->num_vtxbufs,
+                                  vb, start_slot, count);
 
     nv30->dirty |= NV30_NEW_ARRAYS;
 }
index 2052f914258230b71c48a91e8c9c835d9f3b8163..819b0a2e2bf9ed67158aa096c9d473e5b7b32e7c 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include "pipe/p_defines.h"
+#include "util/u_helpers.h"
 #include "util/u_inlines.h"
 #include "util/u_transfer.h"
 
@@ -883,30 +884,35 @@ nv50_set_viewport_state(struct pipe_context *pipe,
 
 static void
 nv50_set_vertex_buffers(struct pipe_context *pipe,
-                        unsigned count,
+                        unsigned start_slot, unsigned count,
                         const struct pipe_vertex_buffer *vb)
 {
    struct nv50_context *nv50 = nv50_context(pipe);
    unsigned i;
 
-   nv50->vbo_user = nv50->vbo_constant = 0;
+   util_set_vertex_buffers_count(nv50->vtxbuf, &nv50->num_vtxbufs, vb,
+                                 start_slot, count);
+
+   if (!vb) {
+      nv50->vbo_user &= ~(((1ull << count) - 1) << start_slot);
+      nv50->vbo_constant &= ~(((1ull << count) - 1) << start_slot);
+      return;
+   }
 
    for (i = 0; i < count; ++i) {
-      nv50->vtxbuf[i].stride = vb[i].stride;
-      pipe_resource_reference(&nv50->vtxbuf[i].buffer, vb[i].buffer);
+      unsigned dst_index = start_slot + i;
+
       if (!vb[i].buffer && vb[i].user_buffer) {
-         nv50->vtxbuf[i].user_buffer = vb[i].user_buffer;
-         nv50->vbo_user |= 1 << i;
+         nv50->vbo_user |= 1 << dst_index;
          if (!vb[i].stride)
-            nv50->vbo_constant |= 1 << i;
+            nv50->vbo_constant |= 1 << dst_index;
+         else
+            nv50->vbo_constant &= ~(1 << dst_index);
       } else {
-         nv50->vtxbuf[i].buffer_offset = vb[i].buffer_offset;
+         nv50->vbo_user &= ~(1 << dst_index);
+         nv50->vbo_constant &= ~(1 << dst_index);
       }
    }
-   for (; i < nv50->num_vtxbufs; ++i)
-      pipe_resource_reference(&nv50->vtxbuf[i].buffer, NULL);
-
-   nv50->num_vtxbufs = count;
 
    nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_VERTEX);
 
index 1bd54342e810f14a5cb9f58732986c194704abd3..30011df4dc12461616fe7381991706c74ef9a77f 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include "pipe/p_defines.h"
+#include "util/u_helpers.h"
 #include "util/u_inlines.h"
 #include "util/u_transfer.h"
 
@@ -778,59 +779,38 @@ nvc0_set_viewport_state(struct pipe_context *pipe,
 
 static void
 nvc0_set_vertex_buffers(struct pipe_context *pipe,
-                        unsigned count,
+                        unsigned start_slot, unsigned count,
                         const struct pipe_vertex_buffer *vb)
 {
     struct nvc0_context *nvc0 = nvc0_context(pipe);
-    uint32_t constant_vbos = 0;
     unsigned i;
 
-    nvc0->vbo_user = 0;
-
-    if (count != nvc0->num_vtxbufs) {
-       for (i = 0; i < count; ++i) {
-          pipe_resource_reference(&nvc0->vtxbuf[i].buffer, vb[i].buffer);
-          if (vb[i].user_buffer) {
-             nvc0->vbo_user |= 1 << i;
-             nvc0->vtxbuf[i].user_buffer = vb[i].user_buffer;
-             if (!vb[i].stride)
-                constant_vbos |= 1 << i;
-          } else {
-             nvc0->vtxbuf[i].buffer_offset = vb[i].buffer_offset;
-          }
-          nvc0->vtxbuf[i].stride = vb[i].stride;
-       }
-       for (; i < nvc0->num_vtxbufs; ++i)
-          pipe_resource_reference(&nvc0->vtxbuf[i].buffer, NULL);
+    util_set_vertex_buffers_count(nvc0->vtxbuf, &nvc0->num_vtxbufs, vb,
+                                  start_slot, count);
 
-       nvc0->num_vtxbufs = count;
-       nvc0->dirty |= NVC0_NEW_ARRAYS;
-    } else {
-       for (i = 0; i < count; ++i) {
-          if (vb[i].user_buffer) {
-             nvc0->vtxbuf[i].user_buffer = vb[i].user_buffer;
-             nvc0->vbo_user |= 1 << i;
-             if (!vb[i].stride)
-                constant_vbos |= 1 << i;
-             assert(!vb[i].buffer);
-          }
-          if (nvc0->vtxbuf[i].buffer == vb[i].buffer &&
-              nvc0->vtxbuf[i].buffer_offset == vb[i].buffer_offset &&
-              nvc0->vtxbuf[i].stride == vb[i].stride)
-             continue;
-          pipe_resource_reference(&nvc0->vtxbuf[i].buffer, vb[i].buffer);
-          nvc0->vtxbuf[i].buffer_offset = vb[i].buffer_offset;
-          nvc0->vtxbuf[i].stride = vb[i].stride;
-          nvc0->dirty |= NVC0_NEW_ARRAYS;
-       }
+    if (!vb) {
+       nvc0->vbo_user &= ~(((1ull << count) - 1) << start_slot);
+       nvc0->constant_vbos &= ~(((1ull << count) - 1) << start_slot);
+       return;
     }
-    if (constant_vbos != nvc0->constant_vbos) {
-       nvc0->constant_vbos = constant_vbos;
-       nvc0->dirty |= NVC0_NEW_ARRAYS;
+
+    for (i = 0; i < count; ++i) {
+       unsigned dst_index = start_slot + i;
+
+       if (vb[i].user_buffer) {
+          nvc0->vbo_user |= 1 << dst_index;
+          if (!vb[i].stride)
+             nvc0->constant_vbos |= 1 << dst_index;
+          else
+             nvc0->constant_vbos &= ~(1 << dst_index);
+       } else {
+          nvc0->vbo_user &= ~(1 << dst_index);
+          nvc0->constant_vbos &= ~(1 << dst_index);
+       }
     }
 
-    if (nvc0->dirty & NVC0_NEW_ARRAYS)
-       nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_VTX);
+    nvc0->dirty |= NVC0_NEW_ARRAYS;
+    nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_VTX);
 }
 
 static void
index 96c96c367a26901a9af1da56449bf3ccf6f5762a..651ea8529e803c57da629d3470662574ebd420b4 100644 (file)
@@ -66,8 +66,7 @@ static void r300_blitter_begin(struct r300_context* r300, enum r300_blitter_op o
     util_blitter_save_vertex_shader(r300->blitter, r300->vs_state.state);
     util_blitter_save_viewport(r300->blitter, &r300->viewport);
     util_blitter_save_scissor(r300->blitter, r300->scissor_state.state);
-    util_blitter_save_vertex_buffers(r300->blitter, r300->nr_vertex_buffers,
-                                     r300->vertex_buffer);
+    util_blitter_save_vertex_buffer_slot(r300->blitter, r300->vertex_buffer);
     util_blitter_save_vertex_elements(r300->blitter, r300->velems);
 
     if (op & R300_SAVE_FRAMEBUFFER) {
index 198ab73d257aaf221e163bfc36f53d620cdf1531..46d7ea1748b143d3ab0feb259218ca111db03271 100644 (file)
@@ -1191,8 +1191,6 @@ void r300_blitter_draw_rectangle(struct blitter_context *blitter,
     if (r300->skip_rendering)
         return;
 
-    r300->context.set_vertex_buffers(&r300->context, 0, NULL);
-
     if (type == UTIL_BLITTER_ATTRIB_TEXCOORD)
         r300->sprite_coord_enable = 1;
 
index b43f330af98382740781da3479274317211ccd76..85d05bd2ce30fd1d52f537e0f572571fac24fee8 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "util/u_framebuffer.h"
 #include "util/u_half.h"
+#include "util/u_helpers.h"
 #include "util/u_math.h"
 #include "util/u_mm.h"
 #include "util/u_memory.h"
@@ -1626,7 +1627,7 @@ static void r300_set_viewport_state(struct pipe_context* pipe,
 }
 
 static void r300_set_vertex_buffers_hwtcl(struct pipe_context* pipe,
-                                    unsigned count,
+                                    unsigned start_slot, unsigned count,
                                     const struct pipe_vertex_buffer* buffers)
 {
     struct r300_context* r300 = r300_context(pipe);
@@ -1637,31 +1638,31 @@ static void r300_set_vertex_buffers_hwtcl(struct pipe_context* pipe,
         count = 1;
     }
 
-    util_copy_vertex_buffers(r300->vertex_buffer,
-                             &r300->nr_vertex_buffers,
-                             buffers, count);
+    util_set_vertex_buffers_count(r300->vertex_buffer,
+                                  &r300->nr_vertex_buffers,
+                                  buffers, start_slot, count);
 
     r300->vertex_arrays_dirty = TRUE;
 }
 
 static void r300_set_vertex_buffers_swtcl(struct pipe_context* pipe,
-                                    unsigned count,
+                                    unsigned start_slot, unsigned count,
                                     const struct pipe_vertex_buffer* buffers)
 {
     struct r300_context* r300 = r300_context(pipe);
     unsigned i;
 
-    util_copy_vertex_buffers(r300->vertex_buffer,
-                             &r300->nr_vertex_buffers,
-                             buffers, count);
-    draw_set_vertex_buffers(r300->draw, count, buffers);
+    util_set_vertex_buffers_count(r300->vertex_buffer,
+                                  &r300->nr_vertex_buffers,
+                                  buffers, start_slot, count);
+    draw_set_vertex_buffers(r300->draw, start_slot, count, buffers);
 
     for (i = 0; i < count; i++) {
         if (buffers[i].user_buffer) {
-            draw_set_mapped_vertex_buffer(r300->draw, i,
+            draw_set_mapped_vertex_buffer(r300->draw, start_slot + i,
                                           buffers[i].user_buffer);
         } else if (buffers[i].buffer) {
-            draw_set_mapped_vertex_buffer(r300->draw, i,
+            draw_set_mapped_vertex_buffer(r300->draw, start_slot + i,
                 r300_resource(buffers[i].buffer)->malloced_buffer);
         }
     }
index a19248da3a2c4955b8f22b4c4540559964f884c5..085108d37095d03f14c9231161a210258e9ae112 100644 (file)
@@ -55,9 +55,7 @@ static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op
 
        r600_suspend_nontimer_queries(rctx);
 
-       util_blitter_save_vertex_buffers(rctx->blitter,
-                                        util_last_bit(rctx->vertex_buffer_state.enabled_mask),
-                                        rctx->vertex_buffer_state.vb);
+       util_blitter_save_vertex_buffer_slot(rctx->blitter, rctx->vertex_buffer_state.vb);
        util_blitter_save_vertex_elements(rctx->blitter, rctx->vertex_fetch_shader.cso);
        util_blitter_save_vertex_shader(rctx->blitter, rctx->vs_shader);
        util_blitter_save_so_targets(rctx->blitter, rctx->num_so_targets,
index a4d3e461ef15ee7b2a18e537f5d11913552994f5..3503c3964a6b556ba173c61a7bd34d0a47e4b4ac 100644 (file)
@@ -495,41 +495,42 @@ void r600_vertex_buffers_dirty(struct r600_context *rctx)
        }
 }
 
-static void r600_set_vertex_buffers(struct pipe_context *ctx, unsigned count,
-                            const struct pipe_vertex_buffer *input)
+static void r600_set_vertex_buffers(struct pipe_context *ctx,
+                                   unsigned start_slot, unsigned count,
+                                   const struct pipe_vertex_buffer *input)
 {
        struct r600_context *rctx = (struct r600_context *)ctx;
        struct r600_vertexbuf_state *state = &rctx->vertex_buffer_state;
-       struct pipe_vertex_buffer *vb = state->vb;
+       struct pipe_vertex_buffer *vb = state->vb + start_slot;
        unsigned i;
-       /* This sets 1-bit for buffers with index >= count. */
-       uint32_t disable_mask = ~((1ull << count) - 1);
+       uint32_t disable_mask = 0;
        /* These are the new buffers set by this function. */
        uint32_t new_buffer_mask = 0;
 
-       /* Set buffers with index >= count to NULL. */
-       uint32_t remaining_buffers_mask =
-               rctx->vertex_buffer_state.enabled_mask & disable_mask;
-
-       while (remaining_buffers_mask) {
-               i = u_bit_scan(&remaining_buffers_mask);
-               pipe_resource_reference(&vb[i].buffer, NULL);
-       }
-
        /* Set vertex buffers. */
-       for (i = 0; i < count; i++) {
-               if (memcmp(&input[i], &vb[i], sizeof(struct pipe_vertex_buffer))) {
-                       if (input[i].buffer) {
-                               vb[i].stride = input[i].stride;
-                               vb[i].buffer_offset = input[i].buffer_offset;
-                               pipe_resource_reference(&vb[i].buffer, input[i].buffer);
-                               new_buffer_mask |= 1 << i;
-                       } else {
-                               pipe_resource_reference(&vb[i].buffer, NULL);
-                               disable_mask |= 1 << i;
+       if (input) {
+               for (i = 0; i < count; i++) {
+                       if (memcmp(&input[i], &vb[i], sizeof(struct pipe_vertex_buffer))) {
+                               if (input[i].buffer) {
+                                       vb[i].stride = input[i].stride;
+                                       vb[i].buffer_offset = input[i].buffer_offset;
+                                       pipe_resource_reference(&vb[i].buffer, input[i].buffer);
+                                       new_buffer_mask |= 1 << i;
+                               } else {
+                                       pipe_resource_reference(&vb[i].buffer, NULL);
+                                       disable_mask |= 1 << i;
+                               }
                        }
                }
-        }
+       } else {
+               for (i = 0; i < count; i++) {
+                       pipe_resource_reference(&vb[i].buffer, NULL);
+               }
+               disable_mask = ((1ull << count) - 1);
+       }
+
+       disable_mask <<= start_slot;
+       new_buffer_mask <<= start_slot;
 
        rctx->vertex_buffer_state.enabled_mask &= ~disable_mask;
        rctx->vertex_buffer_state.dirty_mask &= rctx->vertex_buffer_state.enabled_mask;
@@ -1371,7 +1372,7 @@ void r600_draw_rectangle(struct blitter_context *blitter,
        }
 
        /* draw */
-       util_draw_vertex_buffer(&rctx->context, NULL, buf, offset,
+       util_draw_vertex_buffer(&rctx->context, NULL, buf, rctx->blitter->vb_slot, offset,
                                R600_PRIM_RECTANGLE_LIST, 3, 2);
        pipe_resource_reference(&buf, NULL);
 }
index cea7e12801850587200dcff20ed69cabe7ad01ae..30736fcf8a73acefac51fe642e53cbab97a0adf7 100644 (file)
@@ -61,9 +61,7 @@ static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op
        if (rctx->queued.named.viewport) {
                util_blitter_save_viewport(rctx->blitter, &rctx->queued.named.viewport->viewport);
        }
-       util_blitter_save_vertex_buffers(rctx->blitter,
-                                        rctx->nr_vertex_buffers,
-                                        rctx->vertex_buffer);
+       util_blitter_save_vertex_buffer_slot(rctx->blitter, rctx->vertex_buffer);
        util_blitter_save_so_targets(rctx->blitter, rctx->num_so_targets,
                                     (struct pipe_stream_output_target**)rctx->so_targets);
 
index 66f0bd886fe330eb1faaa72a33c6a12fa6d54a07..bd44d732935488f9975a8a2a7c85d8d4649f840f 100644 (file)
@@ -27,6 +27,7 @@
 #include "util/u_memory.h"
 #include "util/u_framebuffer.h"
 #include "util/u_blitter.h"
+#include "util/u_helpers.h"
 #include "util/u_math.h"
 #include "util/u_pack_color.h"
 #include "tgsi/tgsi_parse.h"
@@ -2488,12 +2489,12 @@ static void si_delete_vertex_element(struct pipe_context *ctx, void *state)
        FREE(state);
 }
 
-static void si_set_vertex_buffers(struct pipe_context *ctx, unsigned count,
+static void si_set_vertex_buffers(struct pipe_context *ctx, unsigned start_slot, unsigned count,
                                  const struct pipe_vertex_buffer *buffers)
 {
        struct r600_context *rctx = (struct r600_context *)ctx;
 
-       util_copy_vertex_buffers(rctx->vertex_buffer, &rctx->nr_vertex_buffers, buffers, count);
+       util_set_vertex_buffers_count(rctx->vertex_buffer, &rctx->nr_vertex_buffers, buffers, start_slot, count);
 }
 
 static void si_set_index_buffer(struct pipe_context *ctx,
index 0b59a0121c2f5954d7b7cb0160c6c90551ac0052..28f300877cf9cbda4a990d929b118c2290f72945 100644 (file)
@@ -783,7 +783,7 @@ rbug_set_fragment_sampler_views(struct pipe_context *_pipe,
 
 static void
 rbug_set_vertex_buffers(struct pipe_context *_pipe,
-                        unsigned num_buffers,
+                        unsigned start_slot, unsigned num_buffers,
                         const struct pipe_vertex_buffer *_buffers)
 {
    struct rbug_context *rb_pipe = rbug_context(_pipe);
@@ -801,7 +801,7 @@ rbug_set_vertex_buffers(struct pipe_context *_pipe,
       buffers = unwrapped_buffers;
    }
 
-   pipe->set_vertex_buffers(pipe,
+   pipe->set_vertex_buffers(pipe, start_slot,
                             num_buffers,
                             buffers);
 
index 59226fb9c153a944a565f5f2df8eab700575e276..ba9e7817cebad05d716370f6d5363e0949675fa3 100644 (file)
@@ -76,8 +76,12 @@ softpipe_draw_vbo(struct pipe_context *pipe,
    /* Map vertex buffers */
    for (i = 0; i < sp->num_vertex_buffers; i++) {
       const void *buf = sp->vertex_buffer[i].user_buffer;
-      if (!buf)
+      if (!buf) {
+         if (!sp->vertex_buffer[i].buffer) {
+            continue;
+         }
          buf = softpipe_resource(sp->vertex_buffer[i].buffer)->data;
+      }
       draw_set_mapped_vertex_buffer(draw, i, buf);
    }
 
index 95acecd3be4d31ae7e876191b63ba69bd2c39f90..2aee700fec28282ddd568a9e937ce9268193fde8 100644 (file)
@@ -33,6 +33,7 @@
 #include "sp_state.h"
 
 #include "util/u_memory.h"
+#include "util/u_helpers.h"
 #include "util/u_inlines.h"
 #include "util/u_transfer.h"
 #include "draw/draw_context.h"
@@ -79,20 +80,20 @@ softpipe_delete_vertex_elements_state(struct pipe_context *pipe, void *velems)
 
 static void
 softpipe_set_vertex_buffers(struct pipe_context *pipe,
-                            unsigned count,
+                            unsigned start_slot, unsigned count,
                             const struct pipe_vertex_buffer *buffers)
 {
    struct softpipe_context *softpipe = softpipe_context(pipe);
 
    assert(count <= PIPE_MAX_ATTRIBS);
 
-   util_copy_vertex_buffers(softpipe->vertex_buffer,
-                            &softpipe->num_vertex_buffers,
-                            buffers, count);
+   util_set_vertex_buffers_count(softpipe->vertex_buffer,
+                                 &softpipe->num_vertex_buffers,
+                                 buffers, start_slot, count);
 
    softpipe->dirty |= SP_NEW_VERTEX;
 
-   draw_set_vertex_buffers(softpipe->draw, count, buffers);
+   draw_set_vertex_buffers(softpipe->draw, start_slot, count, buffers);
 }
 
 
index bb143f4cb3a82469d3438a05ad5fd5b3bae29254..911c34df1b806a6c994f7121ce232d86220c9d2c 100644 (file)
@@ -56,8 +56,7 @@ static void sp_blit(struct pipe_context *pipe,
 
    /* XXX turn off occlusion and streamout queries */
 
-   util_blitter_save_vertex_buffers(sp->blitter, sp->num_vertex_buffers,
-                                    sp->vertex_buffer);
+   util_blitter_save_vertex_buffer_slot(sp->blitter, sp->vertex_buffer);
    util_blitter_save_vertex_elements(sp->blitter, sp->velems);
    util_blitter_save_vertex_shader(sp->blitter, sp->vs);
    util_blitter_save_geometry_shader(sp->blitter, sp->gs);
index f2f26da1cd53d719c840c4bd83219e38cce0cde5..32671ecafa72a55a364ca4c3f5fa0be48faf6777 100644 (file)
@@ -234,8 +234,6 @@ struct svga_state
       unsigned flag_1d;
       unsigned flag_srgb;
    } tex_flags;
-
-   boolean any_user_vertex_buffers;
 };
 
 struct svga_prescale {
index 34ac995ef60cd529c485f595eb244c5a66ea6f7a..a44ed12adf7a73e769d70b6c24736ff1831d0ee3 100644 (file)
@@ -183,9 +183,7 @@ static void svga_blit(struct pipe_context *pipe,
 
    /* XXX turn off occlusion and streamout queries */
 
-   util_blitter_save_vertex_buffers(svga->blitter,
-                                    svga->curr.num_vertex_buffers,
-                                    svga->curr.vb);
+   util_blitter_save_vertex_buffer_slot(svga->blitter, svga->curr.vb);
    util_blitter_save_vertex_elements(svga->blitter, (void*)svga->curr.velems);
    util_blitter_save_vertex_shader(svga->blitter, svga->curr.vs);
    /*util_blitter_save_geometry_shader(svga->blitter, svga->curr.gs);*/
index 58469910732ea9970bfef84f1c223300cfce790a..82bd1b33efeee241a3496b4c89cbca90f5b3ed7b 100644 (file)
@@ -23,6 +23,7 @@
  *
  **********************************************************/
 
+#include "util/u_helpers.h"
 #include "util/u_inlines.h"
 #include "pipe/p_defines.h"
 #include "util/u_math.h"
 
 
 static void svga_set_vertex_buffers(struct pipe_context *pipe,
-                                    unsigned count,
+                                    unsigned start_slot, unsigned count,
                                     const struct pipe_vertex_buffer *buffers)
 {
    struct svga_context *svga = svga_context(pipe);
-   unsigned i;
-   boolean any_user_buffer = FALSE;
-
-   /* Check for no change */
-   if (count == svga->curr.num_vertex_buffers &&
-       memcmp(svga->curr.vb, buffers, count * sizeof buffers[0]) == 0)
-      return;
-
-   /* Adjust refcounts */
-   for (i = 0; i < count; i++) {
-      pipe_resource_reference(&svga->curr.vb[i].buffer, buffers[i].buffer);
-      if (svga_buffer_is_user_buffer(buffers[i].buffer))
-         any_user_buffer = TRUE;
-   }
-
-   for ( ; i < svga->curr.num_vertex_buffers; i++)
-      pipe_resource_reference(&svga->curr.vb[i].buffer, NULL);
 
-   /* Copy remaining data */
-   memcpy(svga->curr.vb, buffers, count * sizeof buffers[0]);
-   svga->curr.num_vertex_buffers = count;
-   svga->curr.any_user_vertex_buffers = any_user_buffer;
+   util_set_vertex_buffers_count(svga->curr.vb,
+                                 &svga->curr.num_vertex_buffers,
+                                 buffers, start_slot, count);
 
    svga->dirty |= SVGA_NEW_VBUFFER;
 }
index e9239bafef9ae45c0133705f8b4c6568ab1d83bd..dea3a26b6f2c0eb837940b7cd1411f9d4178c4aa 100644 (file)
@@ -98,7 +98,7 @@ update_swtnl_draw( struct svga_context *svga,
                                 svga->curr.fs->draw_shader);
 
    if (dirty & SVGA_NEW_VBUFFER)
-      draw_set_vertex_buffers(svga->swtnl.draw, 
+      draw_set_vertex_buffers(svga->swtnl.draw, 0,
                               svga->curr.num_vertex_buffers, 
                               svga->curr.vb);
 
index a5110bec4870afb9488026461c2c22f3a15a8842..ba1882ea6525e97bef9dc49394c018771db6998f 100644 (file)
@@ -1060,7 +1060,7 @@ trace_context_set_vertex_sampler_views(struct pipe_context *_pipe,
 
 static INLINE void
 trace_context_set_vertex_buffers(struct pipe_context *_pipe,
-                                 unsigned num_buffers,
+                                 unsigned start_slot, unsigned num_buffers,
                                  const struct pipe_vertex_buffer *buffers)
 {
    struct trace_context *tr_ctx = trace_context(_pipe);
@@ -1070,6 +1070,7 @@ trace_context_set_vertex_buffers(struct pipe_context *_pipe,
    trace_dump_call_begin("pipe_context", "set_vertex_buffers");
 
    trace_dump_arg(ptr, pipe);
+   trace_dump_arg(uint, start_slot);
    trace_dump_arg(uint, num_buffers);
 
    trace_dump_arg_begin("buffers");
@@ -1081,10 +1082,10 @@ trace_context_set_vertex_buffers(struct pipe_context *_pipe,
       memcpy(_buffers, buffers, num_buffers * sizeof(*_buffers));
       for (i = 0; i < num_buffers; i++)
          _buffers[i].buffer = trace_resource_unwrap(tr_ctx, buffers[i].buffer);
-      pipe->set_vertex_buffers(pipe, num_buffers, _buffers);
+      pipe->set_vertex_buffers(pipe, start_slot, num_buffers, _buffers);
       FREE(_buffers);
    } else {
-      pipe->set_vertex_buffers(pipe, num_buffers, NULL);
+      pipe->set_vertex_buffers(pipe, start_slot, num_buffers, NULL);
    }
 
    trace_dump_call_end();
index 761761da77354a83be4db75ff92d37392a0b9843..88e12b2f318641e86a5c14c008be73f5e5d4f47b 100644 (file)
@@ -249,6 +249,7 @@ struct pipe_context {
                                 struct pipe_surface **resources);
 
    void (*set_vertex_buffers)( struct pipe_context *,
+                               unsigned start_slot,
                                unsigned num_buffers,
                                const struct pipe_vertex_buffer * );
 
index 5d581aa2e3f6ddf5e00da3ce276477f29b893d96..54447814c5c90b03c195969b8806107d746e4ada 100644 (file)
@@ -842,7 +842,7 @@ struct dxgi_blitter
                pipe->bind_depth_stencil_alpha_state(pipe, zsa);
                pipe->bind_blend_state(pipe, blend);
                pipe->bind_vertex_elements_state(pipe, elements);
-               pipe->set_vertex_buffers(pipe, 1, &vbuf);
+               pipe->set_vertex_buffers(pipe, 0, 1, &vbuf);
                pipe->bind_fs_state(pipe, fs);
                pipe->bind_vs_state(pipe, vs);
                if(pipe->bind_gs_state)
index de13458e3842538971accca0a71c583ac0f050fc..9faf54f411d80a017dbe27e3a9c43c94e06182d6 100644 (file)
@@ -1040,7 +1040,7 @@ void renderer_polygon_stencil(struct renderer *renderer,
 {
    assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
 
-   cso_set_vertex_buffers(renderer->cso, 1, vbuf);
+   cso_set_vertex_buffers(renderer->cso, 0, 1, vbuf);
 
    if (!renderer->u.polygon_stencil.manual_two_sides) {
       cso_draw_arrays(renderer->cso, mode, start, count);
index eac9627e86094bb9ac8049405c2902544e777985..fc4e6b6d4e77dedd91a5bb017b8f56cc94178e7e 100644 (file)
@@ -74,7 +74,7 @@ set_vertices(void)
                                               sizeof(vertices),
                                               vertices);
 
-   info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf);
+   info.ctx->set_vertex_buffers(info.ctx, 0, 1, &vbuf);
 }
 
 
index 5f9d8d2d9106e2cf32c975ac99082d061bfa74bf..b9598f562bbe4ed8e39e221b2d916666a80bb61e 100644 (file)
@@ -96,7 +96,7 @@ set_vertices(void)
                                               sizeof(vertices),
                                               vertices);
 
-   info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf);
+   info.ctx->set_vertex_buffers(info.ctx, 0, 1, &vbuf);
 }
 
 
index 51be87478f771039fe550242cab1e2a61d3467b9..9cde75cff2573caf7d4b172971c9985ab5273616 100644 (file)
@@ -181,7 +181,7 @@ static void set_vertices( void )
                                               sizeof(vertices),
                                               vertices);
 
-   ctx->set_vertex_buffers(ctx, 1, &vbuf);
+   ctx->set_vertex_buffers(ctx, 0, 1, &vbuf);
 }
 
 static void set_vertex_shader( void )
index 0bcecd7436aba96be19f284270fbf603b99953f4..a196cbbe54ab24382acb2f88b242d3d264150427 100644 (file)
@@ -100,7 +100,7 @@ set_vertices(void)
                                               sizeof(vertices),
                                               vertices);
 
-   info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf);
+   info.ctx->set_vertex_buffers(info.ctx, 0, 1, &vbuf);
 }
 
 
index e9b0829e6ceae2afd088d6378fcd1a7428704f41..c43f54595bf39062797725343be6d3ff534cbbbe 100644 (file)
@@ -266,7 +266,7 @@ static void set_vertices( void )
                                                  vertices);
    }
 
-   ctx->set_vertex_buffers(ctx, 1, &vbuf);
+   ctx->set_vertex_buffers(ctx, 0, 1, &vbuf);
 }
 
 static void set_vertex_shader( void )
index a4f13cbdae48ff13aa4b3fd20255367ac25577ee..d522bce038cebef817e16a7ffeced21a92a71949 100644 (file)
@@ -100,7 +100,7 @@ set_vertices(struct vertex *vertices, unsigned bytes)
                                               bytes,
                                               vertices);
 
-   info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf);
+   info.ctx->set_vertex_buffers(info.ctx, 0, 1, &vbuf);
 }
 
 
index ca6fe3ec9f2655372651f5ed35201ab20a52ae11..ab5f299f3e302ceb960fd2b5c620b57248a0ae53 100644 (file)
@@ -107,7 +107,7 @@ static void set_vertices( void )
                                               sizeof(vertices),
                                               vertices);
 
-   ctx->set_vertex_buffers(ctx, 1, &vbuf);
+   ctx->set_vertex_buffers(ctx, 0, 1, &vbuf);
 }
 
 static void set_vertex_shader( void )
index 02d78ad1fa8fbe3fa3c2d416e1801f99f5085dd0..7eb9104a5749f1826f144b6b08c9cde5a0abe022 100644 (file)
@@ -63,7 +63,7 @@ static void set_vertices( void )
                                               sizeof(vertices),
                                               vertices);
 
-   info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf);
+   info.ctx->set_vertex_buffers(info.ctx, 0, 1, &vbuf);
 }
 
 static void set_vertex_shader( void )
index 6100af3192c347be535a5e78907aabbf0de6c4bc..be93771f5772a65c864f955095b5c7ad963cbbea 100644 (file)
@@ -97,7 +97,7 @@ static void set_vertices( void )
                                               sizeof(vertices),
                                               vertices);
 
-   ctx->set_vertex_buffers(ctx, 1, &vbuf);
+   ctx->set_vertex_buffers(ctx, 0, 1, &vbuf);
 }
 
 static void set_vertex_shader( void )
index af3e1c36f15b369778bda787a56f4d500d375820..5442f94f722b6c115504593ce37c9cb1915ce359 100644 (file)
@@ -79,7 +79,7 @@ set_vertices(struct vertex *verts, unsigned num_verts)
                                               num_verts * sizeof(struct vertex),
                                               verts);
 
-   info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf);
+   info.ctx->set_vertex_buffers(info.ctx, 0, 1, &vbuf);
 }
 
 static void set_vertex_shader( void )
index 7dc35eb43a360c26a0e72608e792a4ee6222433c..7807b0b80a290edee535d4d5882b77a8b53bce98 100644 (file)
@@ -61,7 +61,7 @@ static void set_vertices(void)
                                               sizeof(vertices),
                                               vertices);
 
-   info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf);
+   info.ctx->set_vertex_buffers(info.ctx, 0, 1, &vbuf);
 }
 
 static void set_vertex_shader(void)
index be1f0352029505b6f6932874e1ece0a582d4641b..573bc8a83f4b1cfaba3c756cbf285a0eb73048ff 100644 (file)
@@ -98,7 +98,7 @@ static void set_vertices( void )
                                               sizeof(vertices),
                                               vertices);
 
-   ctx->set_vertex_buffers(ctx, 1, &vbuf);
+   ctx->set_vertex_buffers(ctx, 0, 1, &vbuf);
 }
 
 static void set_vertex_shader( void )
index ce81c9c021733fc6089ca16e9aa49bf127ad29f4..4e3a80b61dd3ebd0d4ec64a425e987fdadb8a877 100644 (file)
@@ -150,7 +150,7 @@ static void set_vertices( void )
                                                  sizeof(inst_data),
                                                  inst_data);
 
-   ctx->set_vertex_buffers(ctx, 2, vbuf);
+   ctx->set_vertex_buffers(ctx, 0, 2, vbuf);
 
    /* index data */
    ibuf.buffer = pipe_buffer_create_with_data(ctx,
index 7b6507eab11bfda00fab4caa981d7fe6e8886c22..71dd51afd876edf71afafa75f66af93a2d5727bb 100644 (file)
@@ -62,7 +62,7 @@ static void set_vertices( void )
                                               sizeof(vertices),
                                               vertices);
 
-   info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf);
+   info.ctx->set_vertex_buffers(info.ctx, 0, 1, &vbuf);
 }
 
 
index 7fb97d84948ef0932d724af5dd474c04a599f41d..0677f04f28fa533ade3272507ab1bb6849e69ade 100644 (file)
@@ -180,7 +180,7 @@ static void set_vertices( void )
                                               sizeof(vertices),
                                               vertices);
 
-   ctx->set_vertex_buffers(ctx, 1, &vbuf);
+   ctx->set_vertex_buffers(ctx, 0, 1, &vbuf);
 }
 
 static void set_vertex_shader( void )
index ab46f11887e59d78d7fc74da73f3e2414deaf422..c96f6dc70c3ce20587ed0ce15cc8cbcb61ac9b25 100644 (file)
@@ -574,7 +574,13 @@ static void update_array(struct st_context *st)
       num_velements = vpv->num_inputs;
    }
 
-   cso_set_vertex_buffers(st->cso_context, num_vbuffers, vbuffer);
+   cso_set_vertex_buffers(st->cso_context, 0, num_vbuffers, vbuffer);
+   if (st->last_num_vbuffers > num_vbuffers) {
+      /* Unbind remaining buffers, if any. */
+      cso_set_vertex_buffers(st->cso_context, num_vbuffers,
+                             st->last_num_vbuffers - num_vbuffers, NULL);
+   }
+   st->last_num_vbuffers = num_vbuffers;
    cso_set_vertex_elements(st->cso_context, num_velements, velements);
 }
 
index b024ef0db325482c394db9addc7034ab0d0060f5..843dc5be33715a345155536b0068deda4e0ee690 100644 (file)
@@ -457,7 +457,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    cso_save_vertex_shader(cso);
    cso_save_geometry_shader(cso);
    cso_save_vertex_elements(cso);
-   cso_save_vertex_buffers(cso);
+   cso_save_aux_vertex_buffer_slot(cso);
 
    /* rasterizer state: just scissor */
    st->bitmap.rasterizer.scissor = ctx->Scissor.Enabled;
@@ -526,7 +526,9 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
                            x, y, width, height, z, color, &vbuf, &offset);
 
    if (vbuf) {
-      util_draw_vertex_buffer(pipe, st->cso_context, vbuf, offset,
+      util_draw_vertex_buffer(pipe, st->cso_context, vbuf,
+                              cso_get_aux_vertex_buffer_slot(st->cso_context),
+                              offset,
                               PIPE_PRIM_TRIANGLE_FAN,
                               4,  /* verts */
                               3); /* attribs/vert */
@@ -541,7 +543,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    cso_restore_vertex_shader(cso);
    cso_restore_geometry_shader(cso);
    cso_restore_vertex_elements(cso);
-   cso_restore_vertex_buffers(cso);
+   cso_restore_aux_vertex_buffer_slot(cso);
    cso_restore_stream_outputs(cso);
 
    pipe_resource_reference(&vbuf, NULL);
index 90eb0af4fe071f9f751c6e4f09ec3563d2a140aa..4aa0bc18ff5145676380de1d240a4a6939a6da62 100644 (file)
@@ -176,7 +176,9 @@ draw_quad(struct st_context *st,
    /* draw */
    util_draw_vertex_buffer(pipe,
                            st->cso_context,
-                           vbuf, offset,
+                           vbuf,
+                           cso_get_aux_vertex_buffer_slot(st->cso_context),
+                           offset,
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
                            2); /* attribs/vert */
@@ -225,7 +227,7 @@ clear_with_quad(struct gl_context *ctx,
    cso_save_vertex_shader(st->cso_context);
    cso_save_geometry_shader(st->cso_context);
    cso_save_vertex_elements(st->cso_context);
-   cso_save_vertex_buffers(st->cso_context);
+   cso_save_aux_vertex_buffer_slot(st->cso_context);
 
    /* blend state: RGBA masking */
    {
@@ -325,7 +327,7 @@ clear_with_quad(struct gl_context *ctx,
    cso_restore_vertex_shader(st->cso_context);
    cso_restore_geometry_shader(st->cso_context);
    cso_restore_vertex_elements(st->cso_context);
-   cso_restore_vertex_buffers(st->cso_context);
+   cso_restore_aux_vertex_buffer_slot(st->cso_context);
    cso_restore_stream_outputs(st->cso_context);
 }
 
index 642011488cd40bb8b25fd0638cf5f9f69c1962ec..ff8a9dc43642446ca5e2a346d72b489823d3d23b 100644 (file)
@@ -637,7 +637,9 @@ draw_quad(struct gl_context *ctx, GLfloat x0, GLfloat y0, GLfloat z,
    }
 
    u_upload_unmap(st->uploader);
-   util_draw_vertex_buffer(pipe, st->cso_context, buf, offset,
+   util_draw_vertex_buffer(pipe, st->cso_context, buf,
+                           cso_get_aux_vertex_buffer_slot(st->cso_context),
+                           offset,
                           PIPE_PRIM_QUADS,
                           4,  /* verts */
                           3); /* attribs/vert */
@@ -683,7 +685,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    cso_save_vertex_shader(cso);
    cso_save_geometry_shader(cso);
    cso_save_vertex_elements(cso);
-   cso_save_vertex_buffers(cso);
+   cso_save_aux_vertex_buffer_slot(cso);
    if (write_stencil) {
       cso_save_depth_stencil_alpha(cso);
       cso_save_blend(cso);
@@ -808,7 +810,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    cso_restore_vertex_shader(cso);
    cso_restore_geometry_shader(cso);
    cso_restore_vertex_elements(cso);
-   cso_restore_vertex_buffers(cso);
+   cso_restore_aux_vertex_buffer_slot(cso);
    cso_restore_stream_outputs(cso);
    if (write_stencil) {
       cso_restore_depth_stencil_alpha(cso);
index e87de44063e05d80836417f6493bca3c52d1bcda..269068da2b0a407b92ccccd4ccde093bdc6a1068 100644 (file)
@@ -228,7 +228,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
    cso_save_vertex_shader(cso);
    cso_save_geometry_shader(cso);
    cso_save_vertex_elements(cso);
-   cso_save_vertex_buffers(cso);
+   cso_save_aux_vertex_buffer_slot(cso);
 
    {
       void *vs = lookup_shader(pipe, numAttribs,
@@ -266,6 +266,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
 
 
    util_draw_vertex_buffer(pipe, cso, vbuffer,
+                          cso_get_aux_vertex_buffer_slot(cso),
                            offset,  /* offset */
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
@@ -279,7 +280,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
    cso_restore_vertex_shader(cso);
    cso_restore_geometry_shader(cso);
    cso_restore_vertex_elements(cso);
-   cso_restore_vertex_buffers(cso);
+   cso_restore_aux_vertex_buffer_slot(cso);
    cso_restore_stream_outputs(cso);
 }
 
index da361d887959b503d84edf808d2987f1cce9c0c1..69bd50336ec777716b040470bbf7d85a5db10ca4 100644 (file)
@@ -173,7 +173,8 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe,
       memset(&st->velems_util_draw[i], 0, sizeof(struct pipe_vertex_element));
       st->velems_util_draw[i].src_offset = i * 4 * sizeof(float);
       st->velems_util_draw[i].instance_divisor = 0;
-      st->velems_util_draw[i].vertex_buffer_index = 0;
+      st->velems_util_draw[i].vertex_buffer_index =
+            cso_get_aux_vertex_buffer_slot(st->cso_context);
       st->velems_util_draw[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    }
 
index c85d09cb5cdbed56b1b8c681ee992894efbd2917..2cc52773efba4d19a531f3b7d5bc9732faf0d929 100644 (file)
@@ -188,6 +188,9 @@ struct st_context
    int force_msaa;
    void *winsys_drawable_handle;
 
+   /* The number of vertex buffers from the last call of validate_arrays. */
+   unsigned last_num_vbuffers;
+
    /* Active render condition. */
    struct pipe_query *render_condition;
    unsigned condition_mode;
index a6c7d0eec8530092cb0105039969ed19f7915629..ae87fb28dbfe166a2febf265bea56859116afb22 100644 (file)
@@ -205,7 +205,7 @@ st_feedback_draw_vbo(struct gl_context *ctx,
 #endif
    }
 
-   draw_set_vertex_buffers(draw, vp->num_inputs, vbuffers);
+   draw_set_vertex_buffers(draw, 0, vp->num_inputs, vbuffers);
    draw_set_vertex_elements(draw, vp->num_inputs, velements);
 
    memset(&ibuffer, 0, sizeof(ibuffer));
@@ -264,5 +264,5 @@ st_feedback_draw_vbo(struct gl_context *ctx,
       draw_set_mapped_vertex_buffer(draw, attr, NULL);
       pipe_resource_reference(&vbuffers[attr].buffer, NULL);
    }
-   draw_set_vertex_buffers(draw, 0, NULL);
+   draw_set_vertex_buffers(draw, 0, vp->num_inputs, NULL);
 }