From: Marek Olšák Date: Thu, 29 Mar 2012 15:51:50 +0000 (+0200) Subject: gallium: add start_slot parameter to set_vertex_buffers X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e73bf3b805de78299f1a652668ba4e6eab9bac94;p=mesa.git gallium: add start_slot parameter to set_vertex_buffers 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 --- diff --git a/src/gallium/auxiliary/Makefile.sources b/src/gallium/auxiliary/Makefile.sources index 2807c780d2d..6258861f0c8 100644 --- a/src/gallium/auxiliary/Makefile.sources +++ b/src/gallium/auxiliary/Makefile.sources @@ -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 \ diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index db4fa019a35..b3decc58f0e 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -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; } diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h index f49b2b706a4..16158edacc3 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.h +++ b/src/gallium/auxiliary/cso_cache/cso_context.h @@ -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, diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index 48b5db34027..91dd2e1a20a 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.c @@ -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); } diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h index 4a73ec8c37d..30633233fb0 100644 --- a/src/gallium/auxiliary/draw/draw_context.h +++ b/src/gallium/auxiliary/draw/draw_context.h @@ -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, diff --git a/src/gallium/auxiliary/postprocess/pp_run.c b/src/gallium/auxiliary/postprocess/pp_run.c index d2f7aa6dafb..4e6d6750f0b 100644 --- a/src/gallium/auxiliary/postprocess/pp_run.c +++ b/src/gallium/auxiliary/postprocess/pp_run.c @@ -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); } diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c index bf1c392cd41..ab1549e2de6 100644 --- a/src/gallium/auxiliary/util/u_blit.c +++ b/src/gallium/auxiliary/util/u_blit.c @@ -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); } diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index f4ac4aa8685..bb784d6b370 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -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) diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h index c49faaad717..b96e68e9310 100644 --- a/src/gallium/auxiliary/util/u_blitter.h +++ b/src/gallium/auxiliary/util/u_blitter.h @@ -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 diff --git a/src/gallium/auxiliary/util/u_draw_quad.c b/src/gallium/auxiliary/util/u_draw_quad.c index 81c4f107ea9..3fe324afa80 100644 --- a/src/gallium/auxiliary/util/u_draw_quad.c +++ b/src/gallium/auxiliary/util/u_draw_quad.c @@ -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) diff --git a/src/gallium/auxiliary/util/u_draw_quad.h b/src/gallium/auxiliary/util/u_draw_quad.h index 2834a4a8115..cb17f4e4cb2 100644 --- a/src/gallium/auxiliary/util/u_draw_quad.h +++ b/src/gallium/auxiliary/util/u_draw_quad.h @@ -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); diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c index 4d8adb9f355..48ebdb9fa3d 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -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 index 00000000000..ac1edcdbb82 --- /dev/null +++ b/src/gallium/auxiliary/util/u_helpers.c @@ -0,0 +1,90 @@ +/************************************************************************** + * + * Copyright 2012 Marek Olšák + * 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 index 00000000000..09c7116fa6d --- /dev/null +++ b/src/gallium/auxiliary/util/u_helpers.h @@ -0,0 +1,51 @@ +/************************************************************************** + * + * Copyright 2012 Marek Olšák + * 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 diff --git a/src/gallium/auxiliary/util/u_inlines.h b/src/gallium/auxiliary/util/u_inlines.h index 5c6e7eb3234..3d68cf5400e 100644 --- a/src/gallium/auxiliary/util/u_inlines.h +++ b/src/gallium/auxiliary/util/u_inlines.h @@ -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) { diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h index 4047bd9b016..607fbecb02f 100644 --- a/src/gallium/auxiliary/util/u_math.h +++ b/src/gallium/auxiliary/util/u_math.h @@ -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 } diff --git a/src/gallium/auxiliary/util/u_vbuf.c b/src/gallium/auxiliary/util/u_vbuf.c index 1cc83c3dd39..7fb492882f5 100644 --- a/src/gallium/auxiliary/util/u_vbuf.c +++ b/src/gallium/auxiliary/util/u_vbuf.c @@ -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); } diff --git a/src/gallium/auxiliary/util/u_vbuf.h b/src/gallium/auxiliary/util/u_vbuf.h index 59eb59a1190..0f82271649d 100644 --- a/src/gallium/auxiliary/util/u_vbuf.h +++ b/src/gallium/auxiliary/util/u_vbuf.h @@ -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 diff --git a/src/gallium/auxiliary/vl/vl_compositor.c b/src/gallium/auxiliary/vl/vl_compositor.c index 0cb1a9f38ad..7ea13bf593d 100644 --- a/src/gallium/auxiliary/vl/vl_compositor.c +++ b/src/gallium/auxiliary/vl/vl_compositor.c @@ -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); diff --git a/src/gallium/auxiliary/vl/vl_matrix_filter.c b/src/gallium/auxiliary/vl/vl_matrix_filter.c index 333fcc8f813..438bedab226 100644 --- a/src/gallium/auxiliary/vl/vl_matrix_filter.c +++ b/src/gallium/auxiliary/vl/vl_matrix_filter.c @@ -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); diff --git a/src/gallium/auxiliary/vl/vl_median_filter.c b/src/gallium/auxiliary/vl/vl_median_filter.c index 5770ff8258a..dfa280a6d2a 100644 --- a/src/gallium/auxiliary/vl/vl_median_filter.c +++ b/src/gallium/auxiliary/vl/vl_median_filter.c @@ -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); diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c b/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c index 4614c8abd37..eb82b95bb4c 100644 --- a/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c +++ b/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c @@ -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]); diff --git a/src/gallium/drivers/galahad/glhd_context.c b/src/gallium/drivers/galahad/glhd_context.c index 3400a4d213a..ecdfe068f79 100644 --- a/src/gallium/drivers/galahad/glhd_context.c +++ b/src/gallium/drivers/galahad/glhd_context.c @@ -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); } diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c index d96ac7ab938..7fa648fc4d9 100644 --- a/src/gallium/drivers/i915/i915_state.c +++ b/src/gallium/drivers/i915/i915_state.c @@ -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 * diff --git a/src/gallium/drivers/i915/i915_surface.c b/src/gallium/drivers/i915/i915_surface.c index 331d6e230d0..08a6f343922 100644 --- a/src/gallium/drivers/i915/i915_surface.c +++ b/src/gallium/drivers/i915/i915_surface.c @@ -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); diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c index fb2f78764a4..0325b151f83 100644 --- a/src/gallium/drivers/identity/id_context.c +++ b/src/gallium/drivers/identity/id_context.c @@ -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); } diff --git a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c index f37b3ca1cea..3497edf9d1c 100644 --- a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c +++ b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c @@ -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); } diff --git a/src/gallium/drivers/llvmpipe/lp_state_vertex.c b/src/gallium/drivers/llvmpipe/lp_state_vertex.c index 4a74cd7c9d4..7594d028b71 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_vertex.c +++ b/src/gallium/drivers/llvmpipe/lp_state_vertex.c @@ -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); } diff --git a/src/gallium/drivers/llvmpipe/lp_surface.c b/src/gallium/drivers/llvmpipe/lp_surface.c index a4789b4f5c3..e42f4c838e9 100644 --- a/src/gallium/drivers/llvmpipe/lp_surface.c +++ b/src/gallium/drivers/llvmpipe/lp_surface.c @@ -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); diff --git a/src/gallium/drivers/noop/noop_state.c b/src/gallium/drivers/noop/noop_state.c index dbfe35b668c..16ce9b457d9 100644 --- a/src/gallium/drivers/noop/noop_state.c +++ b/src/gallium/drivers/noop/noop_state.c @@ -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) { } diff --git a/src/gallium/drivers/nv30/nv30_draw.c b/src/gallium/drivers/nv30/nv30_draw.c index 46e85362815..51fe4f86ed1 100644 --- a/src/gallium/drivers/nv30/nv30_draw.c +++ b/src/gallium/drivers/nv30/nv30_draw.c @@ -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); } diff --git a/src/gallium/drivers/nv30/nv30_miptree.c b/src/gallium/drivers/nv30/nv30_miptree.c index e89725feb2f..5d941ab771e 100644 --- a/src/gallium/drivers/nv30/nv30_miptree.c +++ b/src/gallium/drivers/nv30/nv30_miptree.c @@ -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); diff --git a/src/gallium/drivers/nv30/nv30_push.c b/src/gallium/drivers/nv30/nv30_push.c index c5867bfa11a..5ec2d462a68 100644 --- a/src/gallium/drivers/nv30/nv30_push.c +++ b/src/gallium/drivers/nv30/nv30_push.c @@ -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); } diff --git a/src/gallium/drivers/nv30/nv30_state.c b/src/gallium/drivers/nv30/nv30_state.c index 046ba723dae..af8bb449fce 100644 --- a/src/gallium/drivers/nv30/nv30_state.c +++ b/src/gallium/drivers/nv30/nv30_state.c @@ -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; } diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c index 2052f914258..819b0a2e2bf 100644 --- a/src/gallium/drivers/nv50/nv50_state.c +++ b/src/gallium/drivers/nv50/nv50_state.c @@ -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); diff --git a/src/gallium/drivers/nvc0/nvc0_state.c b/src/gallium/drivers/nvc0/nvc0_state.c index 1bd54342e81..30011df4dc1 100644 --- a/src/gallium/drivers/nvc0/nvc0_state.c +++ b/src/gallium/drivers/nvc0/nvc0_state.c @@ -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 diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index 96c96c367a2..651ea8529e8 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -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) { diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 198ab73d257..46d7ea1748b 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -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; diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index b43f330af98..85d05bd2ce3 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -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); } } diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c index a19248da3a2..085108d3709 100644 --- a/src/gallium/drivers/r600/r600_blit.c +++ b/src/gallium/drivers/r600/r600_blit.c @@ -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, diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index a4d3e461ef1..3503c3964a6 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -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); } diff --git a/src/gallium/drivers/radeonsi/r600_blit.c b/src/gallium/drivers/radeonsi/r600_blit.c index cea7e128018..30736fcf8a7 100644 --- a/src/gallium/drivers/radeonsi/r600_blit.c +++ b/src/gallium/drivers/radeonsi/r600_blit.c @@ -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); diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index 66f0bd886fe..bd44d732935 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -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, diff --git a/src/gallium/drivers/rbug/rbug_context.c b/src/gallium/drivers/rbug/rbug_context.c index 0b59a0121c2..28f300877cf 100644 --- a/src/gallium/drivers/rbug/rbug_context.c +++ b/src/gallium/drivers/rbug/rbug_context.c @@ -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); diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c index 59226fb9c15..ba9e7817ceb 100644 --- a/src/gallium/drivers/softpipe/sp_draw_arrays.c +++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c @@ -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); } diff --git a/src/gallium/drivers/softpipe/sp_state_vertex.c b/src/gallium/drivers/softpipe/sp_state_vertex.c index 95acecd3be4..2aee700fec2 100644 --- a/src/gallium/drivers/softpipe/sp_state_vertex.c +++ b/src/gallium/drivers/softpipe/sp_state_vertex.c @@ -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); } diff --git a/src/gallium/drivers/softpipe/sp_surface.c b/src/gallium/drivers/softpipe/sp_surface.c index bb143f4cb3a..911c34df1b8 100644 --- a/src/gallium/drivers/softpipe/sp_surface.c +++ b/src/gallium/drivers/softpipe/sp_surface.c @@ -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); diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h index f2f26da1cd5..32671ecafa7 100644 --- a/src/gallium/drivers/svga/svga_context.h +++ b/src/gallium/drivers/svga/svga_context.h @@ -234,8 +234,6 @@ struct svga_state unsigned flag_1d; unsigned flag_srgb; } tex_flags; - - boolean any_user_vertex_buffers; }; struct svga_prescale { diff --git a/src/gallium/drivers/svga/svga_pipe_blit.c b/src/gallium/drivers/svga/svga_pipe_blit.c index 34ac995ef60..a44ed12adf7 100644 --- a/src/gallium/drivers/svga/svga_pipe_blit.c +++ b/src/gallium/drivers/svga/svga_pipe_blit.c @@ -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);*/ diff --git a/src/gallium/drivers/svga/svga_pipe_vertex.c b/src/gallium/drivers/svga/svga_pipe_vertex.c index 58469910732..82bd1b33efe 100644 --- a/src/gallium/drivers/svga/svga_pipe_vertex.c +++ b/src/gallium/drivers/svga/svga_pipe_vertex.c @@ -23,6 +23,7 @@ * **********************************************************/ +#include "util/u_helpers.h" #include "util/u_inlines.h" #include "pipe/p_defines.h" #include "util/u_math.h" @@ -36,32 +37,14 @@ 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; } diff --git a/src/gallium/drivers/svga/svga_swtnl_state.c b/src/gallium/drivers/svga/svga_swtnl_state.c index e9239bafef9..dea3a26b6f2 100644 --- a/src/gallium/drivers/svga/svga_swtnl_state.c +++ b/src/gallium/drivers/svga/svga_swtnl_state.c @@ -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); diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c index a5110bec487..ba1882ea652 100644 --- a/src/gallium/drivers/trace/tr_context.c +++ b/src/gallium/drivers/trace/tr_context.c @@ -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(); diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index 761761da773..88e12b2f318 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -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 * ); diff --git a/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp b/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp index 5d581aa2e3f..54447814c5c 100644 --- a/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp +++ b/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp @@ -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) diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c index de13458e384..9faf54f411d 100644 --- a/src/gallium/state_trackers/vega/renderer.c +++ b/src/gallium/state_trackers/vega/renderer.c @@ -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); diff --git a/src/gallium/tests/graw/fs-fragcoord.c b/src/gallium/tests/graw/fs-fragcoord.c index eac9627e860..fc4e6b6d4e7 100644 --- a/src/gallium/tests/graw/fs-fragcoord.c +++ b/src/gallium/tests/graw/fs-fragcoord.c @@ -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); } diff --git a/src/gallium/tests/graw/fs-frontface.c b/src/gallium/tests/graw/fs-frontface.c index 5f9d8d2d910..b9598f562bb 100644 --- a/src/gallium/tests/graw/fs-frontface.c +++ b/src/gallium/tests/graw/fs-frontface.c @@ -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); } diff --git a/src/gallium/tests/graw/fs-test.c b/src/gallium/tests/graw/fs-test.c index 51be87478f7..9cde75cff25 100644 --- a/src/gallium/tests/graw/fs-test.c +++ b/src/gallium/tests/graw/fs-test.c @@ -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 ) diff --git a/src/gallium/tests/graw/fs-write-z.c b/src/gallium/tests/graw/fs-write-z.c index 0bcecd7436a..a196cbbe54a 100644 --- a/src/gallium/tests/graw/fs-write-z.c +++ b/src/gallium/tests/graw/fs-write-z.c @@ -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); } diff --git a/src/gallium/tests/graw/gs-test.c b/src/gallium/tests/graw/gs-test.c index e9b0829e6ce..c43f54595bf 100644 --- a/src/gallium/tests/graw/gs-test.c +++ b/src/gallium/tests/graw/gs-test.c @@ -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 ) diff --git a/src/gallium/tests/graw/occlusion-query.c b/src/gallium/tests/graw/occlusion-query.c index a4f13cbdae4..d522bce038c 100644 --- a/src/gallium/tests/graw/occlusion-query.c +++ b/src/gallium/tests/graw/occlusion-query.c @@ -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); } diff --git a/src/gallium/tests/graw/quad-sample.c b/src/gallium/tests/graw/quad-sample.c index ca6fe3ec9f2..ab5f299f3e3 100644 --- a/src/gallium/tests/graw/quad-sample.c +++ b/src/gallium/tests/graw/quad-sample.c @@ -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 ) diff --git a/src/gallium/tests/graw/quad-tex.c b/src/gallium/tests/graw/quad-tex.c index 02d78ad1fa8..7eb9104a574 100644 --- a/src/gallium/tests/graw/quad-tex.c +++ b/src/gallium/tests/graw/quad-tex.c @@ -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 ) diff --git a/src/gallium/tests/graw/shader-leak.c b/src/gallium/tests/graw/shader-leak.c index 6100af3192c..be93771f577 100644 --- a/src/gallium/tests/graw/shader-leak.c +++ b/src/gallium/tests/graw/shader-leak.c @@ -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 ) diff --git a/src/gallium/tests/graw/tex-srgb.c b/src/gallium/tests/graw/tex-srgb.c index af3e1c36f15..5442f94f722 100644 --- a/src/gallium/tests/graw/tex-srgb.c +++ b/src/gallium/tests/graw/tex-srgb.c @@ -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 ) diff --git a/src/gallium/tests/graw/tex-swizzle.c b/src/gallium/tests/graw/tex-swizzle.c index 7dc35eb43a3..7807b0b80a2 100644 --- a/src/gallium/tests/graw/tex-swizzle.c +++ b/src/gallium/tests/graw/tex-swizzle.c @@ -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) diff --git a/src/gallium/tests/graw/tri-gs.c b/src/gallium/tests/graw/tri-gs.c index be1f0352029..573bc8a83f4 100644 --- a/src/gallium/tests/graw/tri-gs.c +++ b/src/gallium/tests/graw/tri-gs.c @@ -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 ) diff --git a/src/gallium/tests/graw/tri-instanced.c b/src/gallium/tests/graw/tri-instanced.c index ce81c9c0217..4e3a80b61dd 100644 --- a/src/gallium/tests/graw/tri-instanced.c +++ b/src/gallium/tests/graw/tri-instanced.c @@ -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, diff --git a/src/gallium/tests/graw/tri.c b/src/gallium/tests/graw/tri.c index 7b6507eab11..71dd51afd87 100644 --- a/src/gallium/tests/graw/tri.c +++ b/src/gallium/tests/graw/tri.c @@ -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); } diff --git a/src/gallium/tests/graw/vs-test.c b/src/gallium/tests/graw/vs-test.c index 7fb97d84948..0677f04f28f 100644 --- a/src/gallium/tests/graw/vs-test.c +++ b/src/gallium/tests/graw/vs-test.c @@ -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 ) diff --git a/src/mesa/state_tracker/st_atom_array.c b/src/mesa/state_tracker/st_atom_array.c index ab46f11887e..c96f6dc70c3 100644 --- a/src/mesa/state_tracker/st_atom_array.c +++ b/src/mesa/state_tracker/st_atom_array.c @@ -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); } diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index b024ef0db32..843dc5be337 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -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); diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index 90eb0af4fe0..4aa0bc18ff5 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -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); } diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 642011488cd..ff8a9dc4364 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -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); diff --git a/src/mesa/state_tracker/st_cb_drawtex.c b/src/mesa/state_tracker/st_cb_drawtex.c index e87de44063e..269068da2b0 100644 --- a/src/mesa/state_tracker/st_cb_drawtex.c +++ b/src/mesa/state_tracker/st_cb_drawtex.c @@ -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); } diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index da361d88795..69bd50336ec 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -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; } diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index c85d09cb5cd..2cc52773efb 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -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; diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c index a6c7d0eec85..ae87fb28dbf 100644 --- a/src/mesa/state_tracker/st_draw_feedback.c +++ b/src/mesa/state_tracker/st_draw_feedback.c @@ -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); }