[Mesa-dev] [PATCH] gallium: allow setting of the internal stream output offset

Zack Rusin zackr at vmware.com
Thu Mar 6 15:47:51 PST 2014


D3D10 allows setting of the internal offset of a buffer, which is
in general only incremented via actual stream output writes. By
allowing setting of the internal offset draw_auto is capable
of rendering from buffers which have not been actually streamed
out to. Our interface didn't allow. This change functionally
shouldn't make any difference to OpenGL where instead of an
append_bitmask you just get a real array where -1 means append
(like in D3D) and 0 means do not append.

Signed-off-by: Zack Rusin <zackr at vmware.com>
---
 src/gallium/auxiliary/cso_cache/cso_context.c | 13 ++++++++-----
 src/gallium/auxiliary/cso_cache/cso_context.h |  2 +-
 src/gallium/auxiliary/draw/draw_pt.c          |  8 +++++---
 src/gallium/auxiliary/hud/hud_context.c       |  2 +-
 src/gallium/auxiliary/postprocess/pp_run.c    |  2 +-
 src/gallium/auxiliary/util/u_blit.c           |  2 +-
 src/gallium/auxiliary/util/u_blitter.c        | 13 +++++++++----
 src/gallium/auxiliary/util/u_gen_mipmap.c     |  2 +-
 src/gallium/docs/source/context.rst           |  9 +++++----
 src/gallium/drivers/galahad/glhd_context.c    |  4 ++--
 src/gallium/drivers/ilo/ilo_state.c           |  8 ++++++--
 src/gallium/drivers/llvmpipe/lp_state_so.c    |  7 ++++---
 src/gallium/drivers/noop/noop_state.c         |  2 +-
 src/gallium/drivers/nouveau/nv50/nv50_state.c |  7 ++++---
 src/gallium/drivers/nouveau/nvc0/nvc0_state.c |  7 ++++---
 src/gallium/drivers/radeon/r600_pipe_common.h |  2 +-
 src/gallium/drivers/radeon/r600_streamout.c   |  5 ++++-
 src/gallium/drivers/radeonsi/si_descriptors.c |  4 ++--
 src/gallium/drivers/softpipe/sp_state_so.c    |  2 +-
 src/gallium/drivers/trace/tr_context.c        |  6 +++---
 src/gallium/include/pipe/p_context.h          |  2 +-
 src/gallium/tools/trace/dump_state.py         |  4 ++--
 src/mesa/state_tracker/st_cb_bitmap.c         |  2 +-
 src/mesa/state_tracker/st_cb_clear.c          |  2 +-
 src/mesa/state_tracker/st_cb_drawpixels.c     |  2 +-
 src/mesa/state_tracker/st_cb_drawtex.c        |  2 +-
 src/mesa/state_tracker/st_cb_xformfb.c        | 20 +++++++++++++-------
 27 files changed, 84 insertions(+), 57 deletions(-)

diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c
index 2dcf01d..9146684 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.c
+++ b/src/gallium/auxiliary/cso_cache/cso_context.c
@@ -332,7 +332,7 @@ void cso_release_all( struct cso_context *ctx )
       ctx->pipe->bind_vertex_elements_state( ctx->pipe, NULL );
 
       if (ctx->pipe->set_stream_output_targets)
-         ctx->pipe->set_stream_output_targets(ctx->pipe, 0, NULL, 0);
+         ctx->pipe->set_stream_output_targets(ctx->pipe, 0, NULL, NULL);
    }
 
    /* free fragment sampler views */
@@ -1241,7 +1241,7 @@ void
 cso_set_stream_outputs(struct cso_context *ctx,
                        unsigned num_targets,
                        struct pipe_stream_output_target **targets,
-                       unsigned append_bitmask)
+                       const unsigned *offsets)
 {
    struct pipe_context *pipe = ctx->pipe;
    uint i;
@@ -1266,7 +1266,7 @@ cso_set_stream_outputs(struct cso_context *ctx,
    }
 
    pipe->set_stream_output_targets(pipe, num_targets, targets,
-                                   append_bitmask);
+                                   offsets);
    ctx->nr_so_targets = num_targets;
 }
 
@@ -1292,6 +1292,7 @@ cso_restore_stream_outputs(struct cso_context *ctx)
 {
    struct pipe_context *pipe = ctx->pipe;
    uint i;
+   unsigned offset[PIPE_MAX_SO_BUFFERS];
 
    if (!ctx->has_streamout) {
       return;
@@ -1302,19 +1303,21 @@ cso_restore_stream_outputs(struct cso_context *ctx)
       return;
    }
 
+   assert(ctx->nr_so_targets_saved <= PIPE_MAX_SO_BUFFERS);
    for (i = 0; i < ctx->nr_so_targets_saved; i++) {
       pipe_so_target_reference(&ctx->so_targets[i], NULL);
       /* move the reference from one pointer to another */
       ctx->so_targets[i] = ctx->so_targets_saved[i];
       ctx->so_targets_saved[i] = NULL;
+      /* -1 means append */
+      offset[i] = (unsigned)-1;
    }
    for (; i < ctx->nr_so_targets; i++) {
       pipe_so_target_reference(&ctx->so_targets[i], NULL);
    }
 
-   /* ~0 means append */
    pipe->set_stream_output_targets(pipe, ctx->nr_so_targets_saved,
-                                   ctx->so_targets, ~0);
+                                   ctx->so_targets, offset);
 
    ctx->nr_so_targets = ctx->nr_so_targets_saved;
    ctx->nr_so_targets_saved = 0;
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h
index 822e2df..1aa9998 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.h
+++ b/src/gallium/auxiliary/cso_cache/cso_context.h
@@ -115,7 +115,7 @@ unsigned cso_get_aux_vertex_buffer_slot(struct cso_context *ctx);
 void cso_set_stream_outputs(struct cso_context *ctx,
                             unsigned num_targets,
                             struct pipe_stream_output_target **targets,
-                            unsigned append_bitmask);
+                            const unsigned *offsets);
 void cso_save_stream_outputs(struct cso_context *ctx);
 void cso_restore_stream_outputs(struct cso_context *ctx);
 
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index e2ff7f9..3236e52 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -431,14 +431,16 @@ draw_pt_arrays_restart(struct draw_context *draw,
  */
 static void
 resolve_draw_info(const struct pipe_draw_info *raw_info,
-                  struct pipe_draw_info *info)
+                  struct pipe_draw_info *info,
+                  struct pipe_vertex_buffer *vertex_buffer)
 {
    memcpy(info, raw_info, sizeof(struct pipe_draw_info));
 
    if (raw_info->count_from_stream_output) {
       struct draw_so_target *target =
          (struct draw_so_target *)info->count_from_stream_output;
-      info->count = target->emitted_vertices;
+      assert(vertex_buffer != NULL);
+      info->count = target->internal_offset / vertex_buffer->stride;
 
       /* Stream output draw can not be indexed */
       debug_assert(!info->indexed);
@@ -467,7 +469,7 @@ draw_vbo(struct draw_context *draw,
     */
    util_fpstate_set_denorms_to_zero(fpstate);
 
-   resolve_draw_info(info, &resolved_info);
+   resolve_draw_info(info, &resolved_info, &(draw->pt.vertex_buffer[0]));
    info = &resolved_info;
 
    assert(info->instance_count > 0);
diff --git a/src/gallium/auxiliary/hud/hud_context.c b/src/gallium/auxiliary/hud/hud_context.c
index 465013c..ccf020b 100644
--- a/src/gallium/auxiliary/hud/hud_context.c
+++ b/src/gallium/auxiliary/hud/hud_context.c
@@ -454,7 +454,7 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex)
    cso_set_depth_stencil_alpha(cso, &hud->dsa);
    cso_set_rasterizer(cso, &hud->rasterizer);
    cso_set_viewport(cso, &viewport);
-   cso_set_stream_outputs(cso, 0, NULL, 0);
+   cso_set_stream_outputs(cso, 0, NULL, NULL);
    cso_set_geometry_shader_handle(cso, NULL);
    cso_set_vertex_shader_handle(cso, hud->vs);
    cso_set_vertex_elements(cso, 2, hud->velems);
diff --git a/src/gallium/auxiliary/postprocess/pp_run.c b/src/gallium/auxiliary/postprocess/pp_run.c
index a4dc75d..7d9330c 100644
--- a/src/gallium/auxiliary/postprocess/pp_run.c
+++ b/src/gallium/auxiliary/postprocess/pp_run.c
@@ -136,7 +136,7 @@ pp_run(struct pp_queue_t *ppq, struct pipe_resource *in,
 
    /* set default state */
    cso_set_sample_mask(cso, ~0);
-   cso_set_stream_outputs(cso, 0, NULL, 0);
+   cso_set_stream_outputs(cso, 0, NULL, NULL);
    cso_set_geometry_shader_handle(cso, NULL);
    cso_set_render_condition(cso, NULL, FALSE, 0);
 
diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c
index dd33eb0..4b25b93 100644
--- a/src/gallium/auxiliary/util/u_blit.c
+++ b/src/gallium/auxiliary/util/u_blit.c
@@ -537,7 +537,7 @@ util_blit_pixels_tex(struct blit_state *ctx,
    cso_set_sample_mask(ctx->cso, ~0);
    cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
    cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
-   cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
+   cso_set_stream_outputs(ctx->cso, 0, NULL, NULL);
 
    /* sampler */
    ctx->sampler.normalized_coords = normalized;
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index 66b511e..1e7f374 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -472,9 +472,12 @@ static void blitter_restore_vertex_states(struct blitter_context_priv *ctx)
 
    /* Stream outputs. */
    if (ctx->has_stream_out) {
+      unsigned offsets[PIPE_MAX_SO_BUFFERS];
+      for (i = 0; i < ctx->base.saved_num_so_targets; i++)
+         offsets[i] = (unsigned)-1;
       pipe->set_stream_output_targets(pipe,
                                       ctx->base.saved_num_so_targets,
-                                      ctx->base.saved_so_targets, ~0);
+                                      ctx->base.saved_so_targets, offsets);
 
       for (i = 0; i < ctx->base.saved_num_so_targets; i++)
          pipe_so_target_reference(&ctx->base.saved_so_targets[i], NULL);
@@ -1013,7 +1016,7 @@ static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx,
    if (ctx->has_geometry_shader)
       pipe->bind_gs_state(pipe, NULL);
    if (ctx->has_stream_out)
-      pipe->set_stream_output_targets(pipe, 0, NULL, 0);
+      pipe->set_stream_output_targets(pipe, 0, NULL, NULL);
 }
 
 static void blitter_draw(struct blitter_context_priv *ctx,
@@ -1806,6 +1809,7 @@ void util_blitter_copy_buffer(struct blitter_context *blitter,
    struct pipe_context *pipe = ctx->base.pipe;
    struct pipe_vertex_buffer vb;
    struct pipe_stream_output_target *so_target;
+   unsigned offsets[PIPE_MAX_SO_BUFFERS] = {0};
 
    if (srcx >= src->width0 ||
        dstx >= dst->width0) {
@@ -1847,7 +1851,7 @@ void util_blitter_copy_buffer(struct blitter_context *blitter,
    pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state);
 
    so_target = pipe->create_stream_output_target(pipe, dst, dstx, size);
-   pipe->set_stream_output_targets(pipe, 1, &so_target, 0);
+   pipe->set_stream_output_targets(pipe, 1, &so_target, offsets);
 
    util_draw_arrays(pipe, PIPE_PRIM_POINTS, 0, size / 4);
 
@@ -1867,6 +1871,7 @@ void util_blitter_clear_buffer(struct blitter_context *blitter,
    struct pipe_context *pipe = ctx->base.pipe;
    struct pipe_vertex_buffer vb = {0};
    struct pipe_stream_output_target *so_target;
+   unsigned offsets[PIPE_MAX_SO_BUFFERS] = {0};
 
    assert(num_channels >= 1);
    assert(num_channels <= 4);
@@ -1906,7 +1911,7 @@ void util_blitter_clear_buffer(struct blitter_context *blitter,
    pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state);
 
    so_target = pipe->create_stream_output_target(pipe, dst, offset, size);
-   pipe->set_stream_output_targets(pipe, 1, &so_target, 0);
+   pipe->set_stream_output_targets(pipe, 1, &so_target, offsets);
 
    util_draw_arrays(pipe, PIPE_PRIM_POINTS, 0, size / 4);
 
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c
index d3401a6..dad3ad2 100644
--- a/src/gallium/auxiliary/util/u_gen_mipmap.c
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.c
@@ -1578,7 +1578,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
    cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
    cso_set_sample_mask(ctx->cso, ~0);
    cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
-   cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
+   cso_set_stream_outputs(ctx->cso, 0, NULL, NULL);
    cso_set_render_condition(ctx->cso, NULL, FALSE, 0);
 
    set_fragment_shader(ctx, type, is_depth);
diff --git a/src/gallium/docs/source/context.rst b/src/gallium/docs/source/context.rst
index 64df0ac..8e14522 100644
--- a/src/gallium/docs/source/context.rst
+++ b/src/gallium/docs/source/context.rst
@@ -182,10 +182,11 @@ discussed above.
   use pipe_so_target_reference instead.
 
 * ``set_stream_output_targets`` binds stream output targets. The parameter
-  append_bitmask is a bitmask, where the i-th bit specifies whether new
-  primitives should be appended to the i-th buffer (writing starts at
-  the internal offset), or whether writing should start at the beginning
-  (the internal offset is effectively set to 0).
+  offset is an array which specifies the internal offset of the buffer. The
+  internal offset is, besides writing, used for reading the data during the
+  draw_auto stage, i.e. it specifies how much data there is in the buffer
+  for the purposes of the draw_auto stage. -1 means the buffer should
+  be appended to, and everything else sets the internal offset.
 
 NOTE: The currently-bound vertex or geometry shader must be compiled with
 the properly-filled-in structure pipe_stream_output_info describing which
diff --git a/src/gallium/drivers/galahad/glhd_context.c b/src/gallium/drivers/galahad/glhd_context.c
index fa743bd..2e61e59 100644
--- a/src/gallium/drivers/galahad/glhd_context.c
+++ b/src/gallium/drivers/galahad/glhd_context.c
@@ -613,12 +613,12 @@ static INLINE void
 galahad_context_set_stream_output_targets(struct pipe_context *_pipe,
                                           unsigned num_targets,
                                           struct pipe_stream_output_target **tgs,
-                                          unsigned append_bitmask)
+                                          const unsigned *offsets)
 {
    struct galahad_context *glhd_pipe = galahad_context(_pipe);
    struct pipe_context *pipe = glhd_pipe->pipe;
 
-   pipe->set_stream_output_targets(pipe, num_targets, tgs, append_bitmask);
+   pipe->set_stream_output_targets(pipe, num_targets, tgs, offsets);
 }
 
 static void
diff --git a/src/gallium/drivers/ilo/ilo_state.c b/src/gallium/drivers/ilo/ilo_state.c
index 43dc347..1b97eaa 100644
--- a/src/gallium/drivers/ilo/ilo_state.c
+++ b/src/gallium/drivers/ilo/ilo_state.c
@@ -856,10 +856,11 @@ static void
 ilo_set_stream_output_targets(struct pipe_context *pipe,
                               unsigned num_targets,
                               struct pipe_stream_output_target **targets,
-                              unsigned append_bitmask)
+                              const unsigned *offset)
 {
    struct ilo_context *ilo = ilo_context(pipe);
    unsigned i;
+   unsigned append_bitmask = 0;
 
    if (!targets)
       num_targets = 0;
@@ -868,8 +869,11 @@ ilo_set_stream_output_targets(struct pipe_context *pipe,
    if (!ilo->so.count && !num_targets)
       return;
 
-   for (i = 0; i < num_targets; i++)
+   for (i = 0; i < num_targets; i++) {
       pipe_so_target_reference(&ilo->so.states[i], targets[i]);
+      if (offset[i] == (unsigned)-1)
+         append_bitmask |= 1 << i;
+   }
 
    for (; i < ilo->so.count; i++)
       pipe_so_target_reference(&ilo->so.states[i], NULL);
diff --git a/src/gallium/drivers/llvmpipe/lp_state_so.c b/src/gallium/drivers/llvmpipe/lp_state_so.c
index fa58f79..b70458b 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_so.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_so.c
@@ -64,16 +64,17 @@ static void
 llvmpipe_set_so_targets(struct pipe_context *pipe,
                         unsigned num_targets,
                         struct pipe_stream_output_target **targets,
-                        unsigned append_bitmask)
+                        const unsigned *offsets)
 {
    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
    int i;
    for (i = 0; i < num_targets; i++) {
+      const boolean append = (offsets[i] == (unsigned)-1);
       pipe_so_target_reference((struct pipe_stream_output_target **)&llvmpipe->so_targets[i], targets[i]);
       /* if we're not appending then lets reset the internal
          data of our so target */
-      if (!(append_bitmask & (1 << i)) && llvmpipe->so_targets[i]) {
-         llvmpipe->so_targets[i]->internal_offset = 0;
+      if (!append && llvmpipe->so_targets[i]) {
+         llvmpipe->so_targets[i]->internal_offset = offsets[i];
          llvmpipe->so_targets[i]->emitted_vertices = 0;
       }
    }
diff --git a/src/gallium/drivers/noop/noop_state.c b/src/gallium/drivers/noop/noop_state.c
index 9c62c27..5cb37b6 100644
--- a/src/gallium/drivers/noop/noop_state.c
+++ b/src/gallium/drivers/noop/noop_state.c
@@ -274,7 +274,7 @@ static void noop_stream_output_target_destroy(struct pipe_context *ctx,
 static void noop_set_stream_output_targets(struct pipe_context *ctx,
                            unsigned num_targets,
                            struct pipe_stream_output_target **targets,
-                           unsigned append_bitmask)
+                           const unsigned *offsets)
 {
 }
 
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_state.c b/src/gallium/drivers/nouveau/nv50/nv50_state.c
index 288ba46..065e10c 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_state.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_state.c
@@ -1051,7 +1051,7 @@ static void
 nv50_set_stream_output_targets(struct pipe_context *pipe,
                                unsigned num_targets,
                                struct pipe_stream_output_target **targets,
-                               unsigned append_mask)
+                               const unsigned *offsets)
 {
    struct nv50_context *nv50 = nv50_context(pipe);
    unsigned i;
@@ -1062,7 +1062,8 @@ nv50_set_stream_output_targets(struct pipe_context *pipe,
 
    for (i = 0; i < num_targets; ++i) {
       const boolean changed = nv50->so_target[i] != targets[i];
-      if (!changed && (append_mask & (1 << i)))
+      const boolean append = (offsets[i] == (unsigned)-1);
+      if (!changed && append)
          continue;
       nv50->so_targets_dirty |= 1 << i;
 
@@ -1071,7 +1072,7 @@ nv50_set_stream_output_targets(struct pipe_context *pipe,
          serialize = FALSE;
       }
 
-      if (targets[i] && !(append_mask & (1 << i)))
+      if (targets[i] && !append)
          nv50_so_target(targets[i])->clean = TRUE;
 
       pipe_so_target_reference(&nv50->so_target[i], targets[i]);
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
index 0213a8e..8fcff01 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
@@ -1027,7 +1027,7 @@ static void
 nvc0_set_transform_feedback_targets(struct pipe_context *pipe,
                                     unsigned num_targets,
                                     struct pipe_stream_output_target **targets,
-                                    unsigned append_mask)
+                                    unsigned *offsets)
 {
    struct nvc0_context *nvc0 = nvc0_context(pipe);
    unsigned i;
@@ -1036,14 +1036,15 @@ nvc0_set_transform_feedback_targets(struct pipe_context *pipe,
    assert(num_targets <= 4);
 
    for (i = 0; i < num_targets; ++i) {
-      if (nvc0->tfbbuf[i] == targets[i] && (append_mask & (1 << i)))
+      boolean append = (offsets[i] == ((unsigned)-1));
+      if (nvc0->tfbbuf[i] == targets[i] && append)
          continue;
       nvc0->tfbbuf_dirty |= 1 << i;
 
       if (nvc0->tfbbuf[i] && nvc0->tfbbuf[i] != targets[i])
          nvc0_so_target_save_offset(pipe, nvc0->tfbbuf[i], i, &serialize);
 
-      if (targets[i] && !(append_mask & (1 << i)))
+      if (targets[i] && !append)
          nvc0_so_target(targets[i])->clean = TRUE;
 
       pipe_so_target_reference(&nvc0->tfbbuf[i], targets[i]);
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
index cf5aa08..b0000a0 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -397,7 +397,7 @@ void r600_streamout_buffers_dirty(struct r600_common_context *rctx);
 void r600_set_streamout_targets(struct pipe_context *ctx,
 				unsigned num_targets,
 				struct pipe_stream_output_target **targets,
-				unsigned append_bitmask);
+				unsigned *offset);
 void r600_emit_streamout_end(struct r600_common_context *rctx);
 void r600_streamout_init(struct r600_common_context *rctx);
 
diff --git a/src/gallium/drivers/radeon/r600_streamout.c b/src/gallium/drivers/radeon/r600_streamout.c
index adc11e0..b6cf858 100644
--- a/src/gallium/drivers/radeon/r600_streamout.c
+++ b/src/gallium/drivers/radeon/r600_streamout.c
@@ -108,10 +108,11 @@ void r600_streamout_buffers_dirty(struct r600_common_context *rctx)
 void r600_set_streamout_targets(struct pipe_context *ctx,
 				unsigned num_targets,
 				struct pipe_stream_output_target **targets,
-				unsigned append_bitmask)
+				const unsigned *offsets)
 {
 	struct r600_common_context *rctx = (struct r600_common_context *)ctx;
 	unsigned i;
+        unsigned append_bitmask = 0;
 
 	/* Stop streamout. */
 	if (rctx->streamout.num_targets && rctx->streamout.begin_emitted) {
@@ -122,6 +123,8 @@ void r600_set_streamout_targets(struct pipe_context *ctx,
 	for (i = 0; i < num_targets; i++) {
 		pipe_so_target_reference((struct pipe_stream_output_target**)&rctx->streamout.targets[i], targets[i]);
 		r600_context_add_resource_size(ctx, targets[i]->buffer);
+		if (offsets[i] == ((unsigned)-1))
+			append_bitmask |=  1 << i;
 	}
 	for (; i < rctx->streamout.num_targets; i++) {
 		pipe_so_target_reference((struct pipe_stream_output_target**)&rctx->streamout.targets[i], NULL);
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index 9b10d01..4925bef 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -605,7 +605,7 @@ void si_set_ring_buffer(struct pipe_context *ctx, uint shader, uint slot,
 static void si_set_streamout_targets(struct pipe_context *ctx,
 				     unsigned num_targets,
 				     struct pipe_stream_output_target **targets,
-				     unsigned append_bitmask)
+				     const unsigned *offsets)
 {
 	struct si_context *sctx = (struct si_context *)ctx;
 	struct si_buffer_resources *buffers = &sctx->rw_buffers[PIPE_SHADER_VERTEX];
@@ -618,7 +618,7 @@ static void si_set_streamout_targets(struct pipe_context *ctx,
 	 */
 
 	/* Set the VGT regs. */
-	r600_set_streamout_targets(ctx, num_targets, targets, append_bitmask);
+	r600_set_streamout_targets(ctx, num_targets, targets, offsets);
 
 	/* Set the shader resources.*/
 	for (i = 0; i < num_targets; i++) {
diff --git a/src/gallium/drivers/softpipe/sp_state_so.c b/src/gallium/drivers/softpipe/sp_state_so.c
index f456237..3878e4a 100644
--- a/src/gallium/drivers/softpipe/sp_state_so.c
+++ b/src/gallium/drivers/softpipe/sp_state_so.c
@@ -63,7 +63,7 @@ static void
 softpipe_set_so_targets(struct pipe_context *pipe,
                         unsigned num_targets,
                         struct pipe_stream_output_target **targets,
-                        unsigned append_bitmask)
+                        const unsigned *offsets)
 {
    struct softpipe_context *softpipe = softpipe_context(pipe);
    unsigned i;
diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c
index c10e010..3e99598 100644
--- a/src/gallium/drivers/trace/tr_context.c
+++ b/src/gallium/drivers/trace/tr_context.c
@@ -1080,7 +1080,7 @@ static INLINE void
 trace_context_set_stream_output_targets(struct pipe_context *_pipe,
                                         unsigned num_targets,
                                         struct pipe_stream_output_target **tgs,
-                                        unsigned append_bitmask)
+                                        const unsigned *offsets)
 {
    struct trace_context *tr_ctx = trace_context(_pipe);
    struct pipe_context *pipe = tr_ctx->pipe;
@@ -1090,9 +1090,9 @@ trace_context_set_stream_output_targets(struct pipe_context *_pipe,
    trace_dump_arg(ptr, pipe);
    trace_dump_arg(uint, num_targets);
    trace_dump_arg_array(ptr, tgs, num_targets);
-   trace_dump_arg(uint, append_bitmask);
+   trace_dump_arg_array(uint, offsets, num_targets);
 
-   pipe->set_stream_output_targets(pipe, num_targets, tgs, append_bitmask);
+   pipe->set_stream_output_targets(pipe, num_targets, tgs, offsets);
 
    trace_dump_call_end();
 }
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index 0702729..fe3045a 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -260,7 +260,7 @@ struct pipe_context {
    void (*set_stream_output_targets)(struct pipe_context *,
                               unsigned num_targets,
                               struct pipe_stream_output_target **targets,
-                              unsigned append_bitmask);
+                              const unsigned *offsets);
 
    /*@}*/
 
diff --git a/src/gallium/tools/trace/dump_state.py b/src/gallium/tools/trace/dump_state.py
index bde00ec..8bb29e7 100755
--- a/src/gallium/tools/trace/dump_state.py
+++ b/src/gallium/tools/trace/dump_state.py
@@ -536,9 +536,9 @@ class Context(Dispatcher):
         self._state.render_condition_condition = condition
         self._state.render_condition_mode = mode
 
-    def set_stream_output_targets(self, num_targets, tgs, append_bitmask):
+    def set_stream_output_targets(self, num_targets, tgs, offsets):
         self._state.so_targets = tgs
-        self._state.so_append_bitmask = append_bitmask
+        self._state.offsets = offsets
 
     def draw_vbo(self, info):
         self._draw_no += 1
diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c
index 874ff77..e3ba5a8 100644
--- a/src/mesa/state_tracker/st_cb_bitmap.c
+++ b/src/mesa/state_tracker/st_cb_bitmap.c
@@ -513,7 +513,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    }
 
    cso_set_vertex_elements(cso, 3, st->velems_util_draw);
-   cso_set_stream_outputs(st->cso_context, 0, NULL, 0);
+   cso_set_stream_outputs(st->cso_context, 0, NULL, NULL);
 
    /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
    z = z * 2.0f - 1.0f;
diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c
index 97cc5a2..fcd7e13 100644
--- a/src/mesa/state_tracker/st_cb_clear.c
+++ b/src/mesa/state_tracker/st_cb_clear.c
@@ -307,7 +307,7 @@ clear_with_quad(struct gl_context *ctx, unsigned clear_buffers)
    }
 
    cso_set_vertex_elements(st->cso_context, 2, st->velems_util_draw);
-   cso_set_stream_outputs(st->cso_context, 0, NULL, 0);
+   cso_set_stream_outputs(st->cso_context, 0, NULL, NULL);
    cso_set_sample_mask(st->cso_context, ~0);
    cso_set_rasterizer(st->cso_context, &st->clear.raster);
 
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index 90f34e3..2b36361 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -788,7 +788,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    }
 
    cso_set_vertex_elements(cso, 3, st->velems_util_draw);
-   cso_set_stream_outputs(st->cso_context, 0, NULL, 0);
+   cso_set_stream_outputs(st->cso_context, 0, NULL, NULL);
 
    /* texture state: */
    cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, num_sampler_view, sv);
diff --git a/src/mesa/state_tracker/st_cb_drawtex.c b/src/mesa/state_tracker/st_cb_drawtex.c
index 047cf47..b0a44fd 100644
--- a/src/mesa/state_tracker/st_cb_drawtex.c
+++ b/src/mesa/state_tracker/st_cb_drawtex.c
@@ -244,7 +244,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
       velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    }
    cso_set_vertex_elements(cso, numAttribs, velements);
-   cso_set_stream_outputs(st->cso_context, 0, NULL, 0);
+   cso_set_stream_outputs(st->cso_context, 0, NULL, NULL);
 
    /* viewport state: viewport matching window dims */
    {
diff --git a/src/mesa/state_tracker/st_cb_xformfb.c b/src/mesa/state_tracker/st_cb_xformfb.c
index e824fe9..8f75eda 100644
--- a/src/mesa/state_tracker/st_cb_xformfb.c
+++ b/src/mesa/state_tracker/st_cb_xformfb.c
@@ -113,6 +113,7 @@ st_begin_transform_feedback(struct gl_context *ctx, GLenum mode,
    struct st_transform_feedback_object *sobj =
          st_transform_feedback_object(obj);
    unsigned i, max_num_targets;
+   unsigned offsets[PIPE_MAX_SO_BUFFERS] = {0};
 
    max_num_targets = MIN2(Elements(sobj->base.Buffers),
                           Elements(sobj->targets));
@@ -145,8 +146,8 @@ st_begin_transform_feedback(struct gl_context *ctx, GLenum mode,
    }
 
    /* Start writing at the beginning of each target. */
-   cso_set_stream_outputs(st->cso_context, sobj->num_targets, sobj->targets,
-                          0);
+   cso_set_stream_outputs(st->cso_context, sobj->num_targets,
+                          sobj->targets, offsets);
 }
 
 
@@ -155,7 +156,7 @@ st_pause_transform_feedback(struct gl_context *ctx,
                            struct gl_transform_feedback_object *obj)
 {
    struct st_context *st = st_context(ctx);
-   cso_set_stream_outputs(st->cso_context, 0, NULL, 0);
+   cso_set_stream_outputs(st->cso_context, 0, NULL, NULL);
 }
 
 
@@ -165,10 +166,15 @@ st_resume_transform_feedback(struct gl_context *ctx,
 {
    struct st_context *st = st_context(ctx);
    struct st_transform_feedback_object *sobj =
-         st_transform_feedback_object(obj);
+      st_transform_feedback_object(obj);
+   unsigned offsets[PIPE_MAX_SO_BUFFERS];
+   unsigned i;
+
+   for (i = 0; i < PIPE_MAX_SO_BUFFERS; i++)
+      offsets[i] = (unsigned)-1;
 
-   cso_set_stream_outputs(st->cso_context, sobj->num_targets, sobj->targets,
-                          ~0);
+   cso_set_stream_outputs(st->cso_context, sobj->num_targets,
+                          sobj->targets, offsets);
 }
 
 
@@ -198,7 +204,7 @@ st_end_transform_feedback(struct gl_context *ctx,
    struct st_transform_feedback_object *sobj =
          st_transform_feedback_object(obj);
 
-   cso_set_stream_outputs(st->cso_context, 0, NULL, 0);
+   cso_set_stream_outputs(st->cso_context, 0, NULL, NULL);
 
    pipe_so_target_reference(&sobj->draw_count,
                             st_transform_feedback_get_draw_target(obj));
-- 
1.8.3.2


More information about the mesa-dev mailing list