Пример #1
0
enum u_vbuf_return_flags
u_vbuf_draw_begin(struct u_vbuf *mgrb,
                  const struct pipe_draw_info *info)
{
   struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)mgrb;
   int min_index, max_index;

   if (!mgr->incompatible_vb_layout &&
       !mgr->ve->incompatible_layout &&
       !mgr->any_user_vbs) {
      return 0;
   }

   if (info->indexed) {
      if (info->max_index != ~0) {
         min_index = info->min_index + info->index_bias;
         max_index = info->max_index + info->index_bias;
      } else if (u_vbuf_need_minmax_index(mgr)) {
         u_vbuf_get_minmax_index(mgr->pipe, &mgr->b.index_buffer, info,
                                 &min_index, &max_index);
         min_index += info->index_bias;
         max_index += info->index_bias;
      } else {
         min_index = 0;
         max_index = 0;
      }
   } else {
      min_index = info->start;
      max_index = info->start + info->count - 1;
   }

   /* Translate vertices with non-native layouts or formats. */
   if (mgr->incompatible_vb_layout || mgr->ve->incompatible_layout) {
      u_vbuf_translate_begin(mgr, min_index, max_index);
   }

   /* Upload user buffers. */
   if (mgr->any_user_vbs) {
      u_vbuf_upload_buffers(mgr, min_index, max_index, info->instance_count);
   }
   return U_VBUF_BUFFERS_UPDATED;
}
Пример #2
0
void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info)
{
   struct pipe_context *pipe = mgr->pipe;
   int start_vertex, min_index;
   unsigned num_vertices;
   boolean unroll_indices = FALSE;
   uint32_t used_vb_mask = mgr->ve->used_vb_mask;
   uint32_t user_vb_mask = mgr->user_vb_mask & used_vb_mask;
   uint32_t incompatible_vb_mask = mgr->incompatible_vb_mask & used_vb_mask;
   struct pipe_draw_info new_info;

   /* Normal draw. No fallback and no user buffers. */
   if (!incompatible_vb_mask &&
       !mgr->ve->incompatible_elem_mask &&
       !user_vb_mask) {

      /* Set vertex buffers if needed. */
      if (mgr->dirty_real_vb_mask & used_vb_mask) {
         u_vbuf_set_driver_vertex_buffers(mgr);
      }

      pipe->draw_vbo(pipe, info);
      return;
   }

   new_info = *info;

   /* Fallback. We need to know all the parameters. */
   if (new_info.indirect) {
      struct pipe_transfer *transfer = NULL;
      int *data;

      if (new_info.indexed) {
         data = pipe_buffer_map_range(pipe, new_info.indirect,
                                      new_info.indirect_offset, 20,
                                      PIPE_TRANSFER_READ, &transfer);
         new_info.index_bias = data[3];
         new_info.start_instance = data[4];
      }
      else {
         data = pipe_buffer_map_range(pipe, new_info.indirect,
                                      new_info.indirect_offset, 16,
                                      PIPE_TRANSFER_READ, &transfer);
         new_info.start_instance = data[3];
      }

      new_info.count = data[0];
      new_info.instance_count = data[1];
      new_info.start = data[2];
      pipe_buffer_unmap(pipe, transfer);
      new_info.indirect = NULL;
   }

   if (new_info.indexed) {
      /* See if anything needs to be done for per-vertex attribs. */
      if (u_vbuf_need_minmax_index(mgr)) {
         int max_index;

         if (new_info.max_index != ~0u) {
            min_index = new_info.min_index;
            max_index = new_info.max_index;
         } else {
            u_vbuf_get_minmax_index(mgr->pipe, &mgr->index_buffer,
                                    new_info.primitive_restart,
                                    new_info.restart_index, new_info.start,
                                    new_info.count, &min_index, &max_index);
         }

         assert(min_index <= max_index);

         start_vertex = min_index + new_info.index_bias;
         num_vertices = max_index + 1 - min_index;

         /* Primitive restart doesn't work when unrolling indices.
          * We would have to break this drawing operation into several ones. */
         /* Use some heuristic to see if unrolling indices improves
          * performance. */
         if (!new_info.primitive_restart &&
             num_vertices > new_info.count*2 &&
             num_vertices - new_info.count > 32 &&
             !u_vbuf_mapping_vertex_buffer_blocks(mgr)) {
            unroll_indices = TRUE;
            user_vb_mask &= ~(mgr->nonzero_stride_vb_mask &
                              mgr->ve->noninstance_vb_mask_any);
         }
      } else {
         /* Nothing to do for per-vertex attribs. */
         start_vertex = 0;
         num_vertices = 0;
         min_index = 0;
      }
   } else {
      start_vertex = new_info.start;
      num_vertices = new_info.count;
      min_index = 0;
   }

   /* Translate vertices with non-native layouts or formats. */
   if (unroll_indices ||
       incompatible_vb_mask ||
       mgr->ve->incompatible_elem_mask) {
      if (!u_vbuf_translate_begin(mgr, start_vertex, num_vertices,
                                  new_info.start_instance,
                                  new_info.instance_count, new_info.start,
                                  new_info.count, min_index, unroll_indices)) {
         debug_warn_once("u_vbuf_translate_begin() failed");
         return;
      }

      if (unroll_indices) {
         new_info.indexed = FALSE;
         new_info.index_bias = 0;
         new_info.min_index = 0;
         new_info.max_index = new_info.count - 1;
         new_info.start = 0;
      }

      user_vb_mask &= ~(incompatible_vb_mask |
                        mgr->ve->incompatible_vb_mask_all);
   }

   /* Upload user buffers. */
   if (user_vb_mask) {
      if (u_vbuf_upload_buffers(mgr, start_vertex, num_vertices,
                                new_info.start_instance,
                                new_info.instance_count) != PIPE_OK) {
         debug_warn_once("u_vbuf_upload_buffers() failed");
         return;
      }

      mgr->dirty_real_vb_mask |= user_vb_mask;
   }

   /*
   if (unroll_indices) {
      printf("unrolling indices: start_vertex = %i, num_vertices = %i\n",
             start_vertex, num_vertices);
      util_dump_draw_info(stdout, info);
      printf("\n");
   }

   unsigned i;
   for (i = 0; i < mgr->nr_vertex_buffers; i++) {
      printf("input %i: ", i);
      util_dump_vertex_buffer(stdout, mgr->vertex_buffer+i);
      printf("\n");
   }
   for (i = 0; i < mgr->nr_real_vertex_buffers; i++) {
      printf("real %i: ", i);
      util_dump_vertex_buffer(stdout, mgr->real_vertex_buffer+i);
      printf("\n");
   }
   */

   u_upload_unmap(pipe->stream_uploader);
   u_vbuf_set_driver_vertex_buffers(mgr);

   pipe->draw_vbo(pipe, &new_info);

   if (mgr->using_translate) {
      u_vbuf_translate_end(mgr);
   }
}
Пример #3
0
void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info)
{
   struct pipe_context *pipe = mgr->pipe;
   int start_vertex, min_index;
   unsigned num_vertices;
   boolean unroll_indices = FALSE;
   uint32_t user_vb_mask = mgr->user_vb_mask;

   /* Normal draw. No fallback and no user buffers. */
   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;
      }

      pipe->draw_vbo(pipe, info);
      return;
   }

   if (info->indexed) {
      /* See if anything needs to be done for per-vertex attribs. */
      if (u_vbuf_need_minmax_index(mgr)) {
         int max_index;

         if (info->max_index != ~0) {
            min_index = info->min_index;
            max_index = info->max_index;
         } else {
            u_vbuf_get_minmax_index(mgr->pipe, &mgr->index_buffer, info,
                                    &min_index, &max_index);
         }

         assert(min_index <= max_index);

         start_vertex = min_index + info->index_bias;
         num_vertices = max_index + 1 - min_index;

         /* Primitive restart doesn't work when unrolling indices.
          * We would have to break this drawing operation into several ones. */
         /* Use some heuristic to see if unrolling indices improves
          * performance. */
         if (!info->primitive_restart &&
             num_vertices > info->count*2 &&
             num_vertices-info->count > 32 &&
             !u_vbuf_mapping_vertex_buffer_blocks(mgr)) {
            /*printf("num_vertices=%i count=%i\n", num_vertices, info->count);*/
            unroll_indices = TRUE;
            user_vb_mask &= ~(mgr->nonzero_stride_vb_mask &
                              mgr->ve->noninstance_vb_mask_any);
         }
      } else {
         /* Nothing to do for per-vertex attribs. */
         start_vertex = 0;
         num_vertices = 0;
         min_index = 0;
      }
   } else {
      start_vertex = info->start;
      num_vertices = info->count;
      min_index = 0;
   }

   /* Translate vertices with non-native layouts or formats. */
   if (unroll_indices ||
       mgr->incompatible_vb_mask ||
       mgr->ve->incompatible_elem_mask) {
      /* XXX check the return value */
      u_vbuf_translate_begin(mgr, start_vertex, num_vertices,
                             info->start_instance, info->instance_count,
                             info->start, info->count, min_index,
                             unroll_indices);

      user_vb_mask &= ~(mgr->incompatible_vb_mask |
                        mgr->ve->incompatible_vb_mask_all);
   }

   /* Upload user buffers. */
   if (user_vb_mask) {
      u_vbuf_upload_buffers(mgr, start_vertex, num_vertices,
                            info->start_instance, info->instance_count);
   }

   /*
   if (unroll_indices) {
      printf("unrolling indices: start_vertex = %i, num_vertices = %i\n",
             start_vertex, num_vertices);
      util_dump_draw_info(stdout, info);
      printf("\n");
   }

   unsigned i;
   for (i = 0; i < mgr->nr_vertex_buffers; i++) {
      printf("input %i: ", i);
      util_dump_vertex_buffer(stdout, mgr->vertex_buffer+i);
      printf("\n");
   }
   for (i = 0; i < mgr->nr_real_vertex_buffers; i++) {
      printf("real %i: ", i);
      util_dump_vertex_buffer(stdout, mgr->real_vertex_buffer+i);
      printf("\n");
   }
   */

   u_upload_unmap(mgr->uploader);
   pipe->set_vertex_buffers(pipe, mgr->nr_real_vertex_buffers,
                            mgr->real_vertex_buffer);

   if (unlikely(unroll_indices)) {
      struct pipe_draw_info new_info = *info;
      new_info.indexed = FALSE;
      new_info.index_bias = 0;
      new_info.min_index = 0;
      new_info.max_index = info->count - 1;
      new_info.start = 0;

      pipe->draw_vbo(pipe, &new_info);
   } else {
      pipe->draw_vbo(pipe, info);
   }

   if (mgr->using_translate) {
      u_vbuf_translate_end(mgr);
   }
   mgr->vertex_buffers_dirty = TRUE;
}