Home | History | Annotate | Download | only in draw
      1 /**************************************************************************
      2  *
      3  * Copyright 2007 VMware, Inc.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 
     28  /*
     29   * Authors:
     30   *   Keith Whitwell <keithw (at) vmware.com>
     31   */
     32 
     33 #include "draw/draw_context.h"
     34 #include "draw/draw_gs.h"
     35 #include "draw/draw_private.h"
     36 #include "draw/draw_pt.h"
     37 #include "draw/draw_vbuf.h"
     38 #include "draw/draw_vs.h"
     39 #include "tgsi/tgsi_dump.h"
     40 #include "util/u_math.h"
     41 #include "util/u_prim.h"
     42 #include "util/u_format.h"
     43 #include "util/u_draw.h"
     44 
     45 
     46 DEBUG_GET_ONCE_BOOL_OPTION(draw_fse, "DRAW_FSE", FALSE)
     47 DEBUG_GET_ONCE_BOOL_OPTION(draw_no_fse, "DRAW_NO_FSE", FALSE)
     48 
     49 /* Overall we split things into:
     50  *     - frontend -- prepare fetch_elts, draw_elts - eg vsplit
     51  *     - middle   -- fetch, shade, cliptest, viewport
     52  *     - pipeline -- the prim pipeline: clipping, wide lines, etc
     53  *     - backend  -- the vbuf_render provided by the driver.
     54  */
     55 static boolean
     56 draw_pt_arrays(struct draw_context *draw,
     57                unsigned prim,
     58                unsigned start,
     59                unsigned count)
     60 {
     61    struct draw_pt_front_end *frontend = NULL;
     62    struct draw_pt_middle_end *middle = NULL;
     63    unsigned opt = 0;
     64 
     65    /* Sanitize primitive length:
     66     */
     67    {
     68       unsigned first, incr;
     69       draw_pt_split_prim(prim, &first, &incr);
     70       count = draw_pt_trim_count(count, first, incr);
     71       if (count < first)
     72          return TRUE;
     73    }
     74 
     75    if (!draw->force_passthrough) {
     76       unsigned gs_out_prim = (draw->gs.geometry_shader ?
     77                               draw->gs.geometry_shader->output_primitive :
     78                               prim);
     79 
     80       if (!draw->render) {
     81          opt |= PT_PIPELINE;
     82       }
     83 
     84       if (draw_need_pipeline(draw,
     85                              draw->rasterizer,
     86                              gs_out_prim)) {
     87          opt |= PT_PIPELINE;
     88       }
     89 
     90       if ((draw->clip_xy ||
     91            draw->clip_z ||
     92            draw->clip_user) && !draw->pt.test_fse) {
     93          opt |= PT_CLIPTEST;
     94       }
     95 
     96       opt |= PT_SHADE;
     97    }
     98 
     99    if (draw->pt.middle.llvm) {
    100       middle = draw->pt.middle.llvm;
    101    } else {
    102       if (opt == 0)
    103          middle = draw->pt.middle.fetch_emit;
    104       else if (opt == PT_SHADE && !draw->pt.no_fse)
    105          middle = draw->pt.middle.fetch_shade_emit;
    106       else
    107          middle = draw->pt.middle.general;
    108    }
    109 
    110    frontend = draw->pt.frontend;
    111 
    112    if (frontend) {
    113       if (draw->pt.prim != prim || draw->pt.opt != opt) {
    114          /* In certain conditions switching primitives requires us to flush
    115           * and validate the different stages. One example is when smooth
    116           * lines are active but first drawn with triangles and then with
    117           * lines.
    118           */
    119          draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
    120          frontend = NULL;
    121       } else if (draw->pt.eltSize != draw->pt.user.eltSize) {
    122          /* Flush draw state if eltSize changed.
    123           * This could be improved so only the frontend is flushed since it
    124           * converts all indices to ushorts and the fetch part of the middle
    125           * always prepares both linear and indexed.
    126           */
    127          frontend->flush( frontend, DRAW_FLUSH_STATE_CHANGE );
    128          frontend = NULL;
    129       }
    130    }
    131 
    132    if (!frontend) {
    133       frontend = draw->pt.front.vsplit;
    134 
    135       frontend->prepare( frontend, prim, middle, opt );
    136 
    137       draw->pt.frontend = frontend;
    138       draw->pt.eltSize = draw->pt.user.eltSize;
    139       draw->pt.prim = prim;
    140       draw->pt.opt = opt;
    141    }
    142 
    143    if (draw->pt.rebind_parameters) {
    144       /* update constants, viewport dims, clip planes, etc */
    145       middle->bind_parameters(middle);
    146       draw->pt.rebind_parameters = FALSE;
    147    }
    148 
    149    frontend->run( frontend, start, count );
    150 
    151    return TRUE;
    152 }
    153 
    154 void draw_pt_flush( struct draw_context *draw, unsigned flags )
    155 {
    156    assert(flags);
    157 
    158    if (draw->pt.frontend) {
    159       draw->pt.frontend->flush( draw->pt.frontend, flags );
    160 
    161       /* don't prepare if we only are flushing the backend */
    162       if (flags & DRAW_FLUSH_STATE_CHANGE)
    163          draw->pt.frontend = NULL;
    164    }
    165 
    166    if (flags & DRAW_FLUSH_PARAMETER_CHANGE) {
    167       draw->pt.rebind_parameters = TRUE;
    168    }
    169 }
    170 
    171 
    172 
    173 boolean draw_pt_init( struct draw_context *draw )
    174 {
    175    draw->pt.test_fse = debug_get_option_draw_fse();
    176    draw->pt.no_fse = debug_get_option_draw_no_fse();
    177 
    178    draw->pt.front.vsplit = draw_pt_vsplit(draw);
    179    if (!draw->pt.front.vsplit)
    180       return FALSE;
    181 
    182    draw->pt.middle.fetch_emit = draw_pt_fetch_emit( draw );
    183    if (!draw->pt.middle.fetch_emit)
    184       return FALSE;
    185 
    186    draw->pt.middle.fetch_shade_emit = draw_pt_middle_fse( draw );
    187    if (!draw->pt.middle.fetch_shade_emit)
    188       return FALSE;
    189 
    190    draw->pt.middle.general = draw_pt_fetch_pipeline_or_emit( draw );
    191    if (!draw->pt.middle.general)
    192       return FALSE;
    193 
    194 #if HAVE_LLVM
    195    if (draw->llvm)
    196       draw->pt.middle.llvm = draw_pt_fetch_pipeline_or_emit_llvm( draw );
    197 #endif
    198 
    199    return TRUE;
    200 }
    201 
    202 
    203 void draw_pt_destroy( struct draw_context *draw )
    204 {
    205    if (draw->pt.middle.llvm) {
    206       draw->pt.middle.llvm->destroy( draw->pt.middle.llvm );
    207       draw->pt.middle.llvm = NULL;
    208    }
    209 
    210    if (draw->pt.middle.general) {
    211       draw->pt.middle.general->destroy( draw->pt.middle.general );
    212       draw->pt.middle.general = NULL;
    213    }
    214 
    215    if (draw->pt.middle.fetch_emit) {
    216       draw->pt.middle.fetch_emit->destroy( draw->pt.middle.fetch_emit );
    217       draw->pt.middle.fetch_emit = NULL;
    218    }
    219 
    220    if (draw->pt.middle.fetch_shade_emit) {
    221       draw->pt.middle.fetch_shade_emit->destroy( draw->pt.middle.fetch_shade_emit );
    222       draw->pt.middle.fetch_shade_emit = NULL;
    223    }
    224 
    225    if (draw->pt.front.vsplit) {
    226       draw->pt.front.vsplit->destroy( draw->pt.front.vsplit );
    227       draw->pt.front.vsplit = NULL;
    228    }
    229 }
    230 
    231 
    232 /**
    233  * Debug- print the first 'count' vertices.
    234  */
    235 static void
    236 draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count)
    237 {
    238    uint i;
    239 
    240    debug_printf("Draw arrays(prim = %u, start = %u, count = %u)\n",
    241                 prim, start, count);
    242 
    243    for (i = 0; i < count; i++) {
    244       uint ii = 0;
    245       uint j;
    246 
    247       if (draw->pt.user.eltSize) {
    248          /* indexed arrays */
    249 
    250          switch (draw->pt.user.eltSize) {
    251          case 1:
    252             {
    253                const ubyte *elem = (const ubyte *) draw->pt.user.elts;
    254                ii = elem[start + i];
    255             }
    256             break;
    257          case 2:
    258             {
    259                const ushort *elem = (const ushort *) draw->pt.user.elts;
    260                ii = elem[start + i];
    261             }
    262             break;
    263          case 4:
    264             {
    265                const uint *elem = (const uint *) draw->pt.user.elts;
    266                ii = elem[start + i];
    267             }
    268             break;
    269          default:
    270             assert(0);
    271             return;
    272          }
    273          ii += draw->pt.user.eltBias;
    274          debug_printf("Element[%u + %u] + %i -> Vertex %u:\n", start, i,
    275                       draw->pt.user.eltBias, ii);
    276       }
    277       else {
    278          /* non-indexed arrays */
    279          ii = start + i;
    280          debug_printf("Vertex %u:\n", ii);
    281       }
    282 
    283       for (j = 0; j < draw->pt.nr_vertex_elements; j++) {
    284          uint buf = draw->pt.vertex_element[j].vertex_buffer_index;
    285          ubyte *ptr = (ubyte *) draw->pt.user.vbuffer[buf].map;
    286 
    287          if (draw->pt.vertex_element[j].instance_divisor) {
    288             ii = draw->instance_id / draw->pt.vertex_element[j].instance_divisor;
    289          }
    290 
    291          ptr += draw->pt.vertex_buffer[buf].buffer_offset;
    292          ptr += draw->pt.vertex_buffer[buf].stride * ii;
    293          ptr += draw->pt.vertex_element[j].src_offset;
    294 
    295          debug_printf("  Attr %u: ", j);
    296          switch (draw->pt.vertex_element[j].src_format) {
    297          case PIPE_FORMAT_R32_FLOAT:
    298             {
    299                float *v = (float *) ptr;
    300                debug_printf("R %f  @ %p\n", v[0], (void *) v);
    301             }
    302             break;
    303          case PIPE_FORMAT_R32G32_FLOAT:
    304             {
    305                float *v = (float *) ptr;
    306                debug_printf("RG %f %f  @ %p\n", v[0], v[1], (void *) v);
    307             }
    308             break;
    309          case PIPE_FORMAT_R32G32B32_FLOAT:
    310             {
    311                float *v = (float *) ptr;
    312                debug_printf("RGB %f %f %f  @ %p\n", v[0], v[1], v[2], (void *) v);
    313             }
    314             break;
    315          case PIPE_FORMAT_R32G32B32A32_FLOAT:
    316             {
    317                float *v = (float *) ptr;
    318                debug_printf("RGBA %f %f %f %f  @ %p\n", v[0], v[1], v[2], v[3],
    319                             (void *) v);
    320             }
    321             break;
    322          case PIPE_FORMAT_B8G8R8A8_UNORM:
    323             {
    324                ubyte *u = (ubyte *) ptr;
    325                debug_printf("BGRA %d %d %d %d  @ %p\n", u[0], u[1], u[2], u[3],
    326                             (void *) u);
    327             }
    328             break;
    329          case PIPE_FORMAT_A8R8G8B8_UNORM:
    330             {
    331                ubyte *u = (ubyte *) ptr;
    332                debug_printf("ARGB %d %d %d %d  @ %p\n", u[0], u[1], u[2], u[3],
    333                             (void *) u);
    334             }
    335             break;
    336          default:
    337             debug_printf("other format %s (fix me)\n",
    338                      util_format_name(draw->pt.vertex_element[j].src_format));
    339          }
    340       }
    341    }
    342 }
    343 
    344 
    345 /** Helper code for below */
    346 #define PRIM_RESTART_LOOP(elements) \
    347    do { \
    348       for (j = 0; j < count; j++) {               \
    349          i = draw_overflow_uadd(start, j, MAX_LOOP_IDX);  \
    350          if (i < elt_max && elements[i] == info->restart_index) { \
    351             if (cur_count > 0) { \
    352                /* draw elts up to prev pos */ \
    353                draw_pt_arrays(draw, prim, cur_start, cur_count); \
    354             } \
    355             /* begin new prim at next elt */ \
    356             cur_start = i + 1; \
    357             cur_count = 0; \
    358          } \
    359          else { \
    360             cur_count++; \
    361          } \
    362       } \
    363       if (cur_count > 0) { \
    364          draw_pt_arrays(draw, prim, cur_start, cur_count); \
    365       } \
    366    } while (0)
    367 
    368 
    369 /**
    370  * For drawing prims with primitive restart enabled.
    371  * Scan for restart indexes and draw the runs of elements/vertices between
    372  * the restarts.
    373  */
    374 static void
    375 draw_pt_arrays_restart(struct draw_context *draw,
    376                        const struct pipe_draw_info *info)
    377 {
    378    const unsigned prim = info->mode;
    379    const unsigned start = info->start;
    380    const unsigned count = info->count;
    381    const unsigned elt_max = draw->pt.user.eltMax;
    382    unsigned i, j, cur_start, cur_count;
    383    /* The largest index within a loop using the i variable as the index.
    384     * Used for overflow detection */
    385    const unsigned MAX_LOOP_IDX = 0xffffffff;
    386 
    387    assert(info->primitive_restart);
    388 
    389    if (draw->pt.user.eltSize) {
    390       /* indexed prims (draw_elements) */
    391       cur_start = start;
    392       cur_count = 0;
    393 
    394       switch (draw->pt.user.eltSize) {
    395       case 1:
    396          {
    397             const ubyte *elt_ub = (const ubyte *) draw->pt.user.elts;
    398             PRIM_RESTART_LOOP(elt_ub);
    399          }
    400          break;
    401       case 2:
    402          {
    403             const ushort *elt_us = (const ushort *) draw->pt.user.elts;
    404             PRIM_RESTART_LOOP(elt_us);
    405          }
    406          break;
    407       case 4:
    408          {
    409             const uint *elt_ui = (const uint *) draw->pt.user.elts;
    410             PRIM_RESTART_LOOP(elt_ui);
    411          }
    412          break;
    413       default:
    414          assert(0 && "bad eltSize in draw_arrays()");
    415       }
    416    }
    417    else {
    418       /* Non-indexed prims (draw_arrays).
    419        * Primitive restart should have been handled in the state tracker.
    420        */
    421       draw_pt_arrays(draw, prim, start, count);
    422    }
    423 }
    424 
    425 
    426 /**
    427  * Resolve true values within pipe_draw_info.
    428  * If we're rendering from transform feedback/stream output
    429  * buffers both the count and max_index need to be computed
    430  * from the attached stream output target.
    431  */
    432 static void
    433 resolve_draw_info(const struct pipe_draw_info *raw_info,
    434                   struct pipe_draw_info *info,
    435                   struct pipe_vertex_buffer *vertex_buffer)
    436 {
    437    memcpy(info, raw_info, sizeof(struct pipe_draw_info));
    438 
    439    if (raw_info->count_from_stream_output) {
    440       struct draw_so_target *target =
    441          (struct draw_so_target *)info->count_from_stream_output;
    442       assert(vertex_buffer != NULL);
    443       info->count = target->internal_offset / vertex_buffer->stride;
    444 
    445       /* Stream output draw can not be indexed */
    446       debug_assert(!info->indexed);
    447       info->max_index = info->count - 1;
    448    }
    449 }
    450 
    451 /**
    452  * Draw vertex arrays.
    453  * This is the main entrypoint into the drawing module.  If drawing an indexed
    454  * primitive, the draw_set_indexes() function should have already been called
    455  * to specify the element/index buffer information.
    456  */
    457 void
    458 draw_vbo(struct draw_context *draw,
    459          const struct pipe_draw_info *info)
    460 {
    461    unsigned instance;
    462    unsigned index_limit;
    463    unsigned count;
    464    unsigned fpstate = util_fpstate_get();
    465    struct pipe_draw_info resolved_info;
    466 
    467    /* Make sure that denorms are treated like zeros. This is
    468     * the behavior required by D3D10. OpenGL doesn't care.
    469     */
    470    util_fpstate_set_denorms_to_zero(fpstate);
    471 
    472    resolve_draw_info(info, &resolved_info, &(draw->pt.vertex_buffer[0]));
    473    info = &resolved_info;
    474 
    475    assert(info->instance_count > 0);
    476    if (info->indexed)
    477       assert(draw->pt.user.elts);
    478 
    479    count = info->count;
    480 
    481    draw->pt.user.eltBias = info->index_bias;
    482    draw->pt.user.min_index = info->min_index;
    483    draw->pt.user.max_index = info->max_index;
    484    draw->pt.user.eltSize = info->indexed ? draw->pt.user.eltSizeIB : 0;
    485 
    486    if (0)
    487       debug_printf("draw_vbo(mode=%u start=%u count=%u):\n",
    488                    info->mode, info->start, count);
    489 
    490    if (0)
    491       tgsi_dump(draw->vs.vertex_shader->state.tokens, 0);
    492 
    493    if (0) {
    494       unsigned int i;
    495       debug_printf("Elements:\n");
    496       for (i = 0; i < draw->pt.nr_vertex_elements; i++) {
    497          debug_printf("  %u: src_offset=%u  inst_div=%u   vbuf=%u  format=%s\n",
    498                       i,
    499                       draw->pt.vertex_element[i].src_offset,
    500                       draw->pt.vertex_element[i].instance_divisor,
    501                       draw->pt.vertex_element[i].vertex_buffer_index,
    502                       util_format_name(draw->pt.vertex_element[i].src_format));
    503       }
    504       debug_printf("Buffers:\n");
    505       for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
    506          debug_printf("  %u: stride=%u offset=%u size=%d ptr=%p\n",
    507                       i,
    508                       draw->pt.vertex_buffer[i].stride,
    509                       draw->pt.vertex_buffer[i].buffer_offset,
    510                       (int) draw->pt.user.vbuffer[i].size,
    511                       draw->pt.user.vbuffer[i].map);
    512       }
    513    }
    514 
    515    if (0)
    516       draw_print_arrays(draw, info->mode, info->start, MIN2(count, 20));
    517 
    518    index_limit = util_draw_max_index(draw->pt.vertex_buffer,
    519                                      draw->pt.vertex_element,
    520                                      draw->pt.nr_vertex_elements,
    521                                      info);
    522 #if HAVE_LLVM
    523    if (!draw->llvm)
    524 #endif
    525    {
    526       if (index_limit == 0) {
    527          /* one of the buffers is too small to do any valid drawing */
    528          debug_warning("draw: VBO too small to draw anything\n");
    529          util_fpstate_set(fpstate);
    530          return;
    531       }
    532    }
    533 
    534    /* If we're collecting stats then make sure we start from scratch */
    535    if (draw->collect_statistics) {
    536       memset(&draw->statistics, 0, sizeof(draw->statistics));
    537    }
    538 
    539    draw->pt.max_index = index_limit - 1;
    540    draw->start_index = info->start;
    541 
    542    /*
    543     * TODO: We could use draw->pt.max_index to further narrow
    544     * the min_index/max_index hints given by the state tracker.
    545     */
    546 
    547    for (instance = 0; instance < info->instance_count; instance++) {
    548       unsigned instance_idx = instance + info->start_instance;
    549       draw->start_instance = info->start_instance;
    550       draw->instance_id = instance;
    551       /* check for overflow */
    552       if (instance_idx < instance ||
    553           instance_idx < draw->start_instance) {
    554          /* if we overflown just set the instance id to the max */
    555          draw->instance_id = 0xffffffff;
    556       }
    557 
    558       draw_new_instance(draw);
    559 
    560       if (info->primitive_restart) {
    561          draw_pt_arrays_restart(draw, info);
    562       }
    563       else {
    564          draw_pt_arrays(draw, info->mode, info->start, count);
    565       }
    566    }
    567 
    568    /* If requested emit the pipeline statistics for this run */
    569    if (draw->collect_statistics) {
    570       draw->render->pipeline_statistics(draw->render, &draw->statistics);
    571    }
    572    util_fpstate_set(fpstate);
    573 }
    574