swr: allocate all scratch space in one go for vertex buffers
authorIlia Mirkin <imirkin@alum.mit.edu>
Sun, 20 Nov 2016 21:34:59 +0000 (16:34 -0500)
committerIlia Mirkin <imirkin@alum.mit.edu>
Tue, 22 Nov 2016 02:11:26 +0000 (21:11 -0500)
Multiple buffers may reference client arrays. When this happens, we
might reach for scratch space multiple times, which could cause later
arrays to invalidate the pointers allocated for the earlier ones.

This fixes copyteximage 2D_ARRAY.

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
Reviewed-by: Bruce Cherniak <bruce.cherniak@intel.com>
src/gallium/drivers/swr/swr_scratch.cpp
src/gallium/drivers/swr/swr_state.cpp

index 28eb2acb9102f019d6f0c00b938320ccba4423ec..2515c8beaf390e64f3f0978a90b085e4d3446e7a 100644 (file)
@@ -35,7 +35,6 @@ swr_copy_to_scratch_space(struct swr_context *ctx,
 {
    void *ptr;
    assert(space);
-   assert(user_buffer);
    assert(size);
 
    if (size >= 2048) { /* XXX TODO create KNOB_ for this */
@@ -82,7 +81,8 @@ swr_copy_to_scratch_space(struct swr_context *ctx,
    }
 
    /* Copy user_buffer to scratch */
-   memcpy(ptr, user_buffer, size);
+   if (user_buffer)
+      memcpy(ptr, user_buffer, size);
 
    return ptr;
 }
index e9ae786164afc8904f36357d8e3d7dfa4f3fda57..a48baec251ac1630ae946b44be747a2f1d3d3cb0 100644 (file)
@@ -1002,14 +1002,39 @@ swr_update_derived(struct pipe_context *pipe,
    /* Set vertex & index buffers */
    /* (using draw info if called by swr_draw_vbo) */
    if (ctx->dirty & SWR_NEW_VERTEX) {
-      uint32_t size, pitch, max_vertex, partial_inbounds;
+      uint32_t size, pitch, max_vertex, partial_inbounds, scratch_total;
       const uint8_t *p_data;
+      uint8_t *scratch = NULL;
 
       /* If being called by swr_draw_vbo, copy draw details */
       struct pipe_draw_info info = {0};
       if (p_draw_info)
          info = *p_draw_info;
 
+      /* We must get all the scratch space in one go */
+      scratch_total = 0;
+      for (UINT i = 0; i < ctx->num_vertex_buffers; i++) {
+         struct pipe_vertex_buffer *vb = &ctx->vertex_buffer[i];
+
+         if (!vb->user_buffer)
+            continue;
+
+         if (vb->stride) {
+            size = (info.max_index - info.min_index + 1) * vb->stride;
+         } else {
+            /* pitch = 0, means constant value
+             * set size to 1 vertex */
+            size = ctx->velems->stream_pitch[i];
+         }
+
+         scratch_total += AlignUp(size, 4);
+      }
+
+      if (scratch_total) {
+         scratch = (uint8_t *)swr_copy_to_scratch_space(
+               ctx, &ctx->scratch->vertex_buffer, NULL, scratch_total);
+      }
+
       /* vertex buffers */
       SWR_VERTEX_BUFFER_STATE swrVertexBuffers[PIPE_MAX_ATTRIBS];
       for (UINT i = 0; i < ctx->num_vertex_buffers; i++) {
@@ -1046,8 +1071,9 @@ swr_update_derived(struct pipe_context *pipe,
             size = AlignUp(size, 4);
             const void *ptr = (const uint8_t *) vb->user_buffer
                + info.min_index * pitch;
-            ptr = swr_copy_to_scratch_space(
-               ctx, &ctx->scratch->vertex_buffer, ptr, size);
+            memcpy(scratch, ptr, size);
+            ptr = scratch;
+            scratch += size;
             p_data = (const uint8_t *)ptr - info.min_index * pitch;
          }