Home | History | Annotate | Download | only in draw
      1 /**************************************************************************
      2  *
      3  * Copyright 2010 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 TUNGSTEN GRAPHICS 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 #include "util/u_math.h"
     29 #include "util/u_memory.h"
     30 #include "draw/draw_context.h"
     31 #include "draw/draw_gs.h"
     32 #include "draw/draw_vbuf.h"
     33 #include "draw/draw_vertex.h"
     34 #include "draw/draw_pt.h"
     35 #include "draw/draw_vs.h"
     36 #include "draw/draw_llvm.h"
     37 #include "gallivm/lp_bld_init.h"
     38 
     39 
     40 struct llvm_middle_end {
     41    struct draw_pt_middle_end base;
     42    struct draw_context *draw;
     43 
     44    struct pt_emit *emit;
     45    struct pt_so_emit *so_emit;
     46    struct pt_fetch *fetch;
     47    struct pt_post_vs *post_vs;
     48 
     49 
     50    unsigned vertex_data_offset;
     51    unsigned vertex_size;
     52    unsigned input_prim;
     53    unsigned opt;
     54 
     55    struct draw_llvm *llvm;
     56    struct draw_llvm_variant *current_variant;
     57 };
     58 
     59 
     60 static void
     61 llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
     62                          unsigned in_prim,
     63                          unsigned opt,
     64                          unsigned *max_vertices )
     65 {
     66    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
     67    struct draw_context *draw = fpme->draw;
     68    struct llvm_vertex_shader *shader =
     69       llvm_vertex_shader(draw->vs.vertex_shader);
     70    char store[DRAW_LLVM_MAX_VARIANT_KEY_SIZE];
     71    struct draw_llvm_variant_key *key;
     72    struct draw_llvm_variant *variant = NULL;
     73    struct draw_llvm_variant_list_item *li;
     74    const unsigned out_prim = (draw->gs.geometry_shader ?
     75                               draw->gs.geometry_shader->output_primitive :
     76                               in_prim);
     77 
     78    /* Add one to num_outputs because the pipeline occasionally tags on
     79     * an additional texcoord, eg for AA lines.
     80     */
     81    const unsigned nr = MAX2( shader->base.info.num_inputs,
     82                              shader->base.info.num_outputs + 1 );
     83 
     84    fpme->input_prim = in_prim;
     85    fpme->opt = opt;
     86 
     87    /* Always leave room for the vertex header whether we need it or
     88     * not.  It's hard to get rid of it in particular because of the
     89     * viewport code in draw_pt_post_vs.c.
     90     */
     91    fpme->vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float);
     92 
     93 
     94    /* XXX: it's not really gl rasterization rules we care about here,
     95     * but gl vs dx9 clip spaces.
     96     */
     97    draw_pt_post_vs_prepare( fpme->post_vs,
     98 			    draw->clip_xy,
     99 			    draw->clip_z,
    100 			    draw->clip_user,
    101                             draw->guard_band_xy,
    102 			    draw->identity_viewport,
    103 			    (boolean)draw->rasterizer->gl_rasterization_rules,
    104 			    (draw->vs.edgeflag_output ? TRUE : FALSE) );
    105 
    106    draw_pt_so_emit_prepare( fpme->so_emit );
    107 
    108    if (!(opt & PT_PIPELINE)) {
    109       draw_pt_emit_prepare( fpme->emit,
    110 			    out_prim,
    111                             max_vertices );
    112 
    113       *max_vertices = MAX2( *max_vertices, 4096 );
    114    }
    115    else {
    116       /* limit max fetches by limiting max_vertices */
    117       *max_vertices = 4096;
    118    }
    119 
    120    /* return even number */
    121    *max_vertices = *max_vertices & ~1;
    122 
    123    key = draw_llvm_make_variant_key(fpme->llvm, store);
    124 
    125    /* Search shader's list of variants for the key */
    126    li = first_elem(&shader->variants);
    127    while (!at_end(&shader->variants, li)) {
    128       if (memcmp(&li->base->key, key, shader->variant_key_size) == 0) {
    129          variant = li->base;
    130          break;
    131       }
    132       li = next_elem(li);
    133    }
    134 
    135    if (variant) {
    136       /* found the variant, move to head of global list (for LRU) */
    137       move_to_head(&fpme->llvm->vs_variants_list, &variant->list_item_global);
    138    }
    139    else {
    140       /* Need to create new variant */
    141       unsigned i;
    142 
    143       /* First check if we've created too many variants.  If so, free
    144        * 25% of the LRU to avoid using too much memory.
    145        */
    146       if (fpme->llvm->nr_variants >= DRAW_MAX_SHADER_VARIANTS) {
    147          /*
    148           * XXX: should we flush here ?
    149           */
    150          for (i = 0; i < DRAW_MAX_SHADER_VARIANTS / 4; i++) {
    151             struct draw_llvm_variant_list_item *item;
    152             if (is_empty_list(&fpme->llvm->vs_variants_list)) {
    153                break;
    154             }
    155             item = last_elem(&fpme->llvm->vs_variants_list);
    156             assert(item);
    157             assert(item->base);
    158             draw_llvm_destroy_variant(item->base);
    159          }
    160       }
    161 
    162       variant = draw_llvm_create_variant(fpme->llvm, nr, key);
    163 
    164       if (variant) {
    165          insert_at_head(&shader->variants, &variant->list_item_local);
    166          insert_at_head(&fpme->llvm->vs_variants_list, &variant->list_item_global);
    167          fpme->llvm->nr_variants++;
    168          shader->variants_cached++;
    169       }
    170    }
    171 
    172    fpme->current_variant = variant;
    173 
    174    /*XXX we only support one constant buffer */
    175    fpme->llvm->jit_context.vs_constants =
    176       draw->pt.user.vs_constants[0];
    177    fpme->llvm->jit_context.gs_constants =
    178       draw->pt.user.gs_constants[0];
    179    fpme->llvm->jit_context.planes =
    180       (float (*) [DRAW_TOTAL_CLIP_PLANES][4]) draw->pt.user.planes[0];
    181    fpme->llvm->jit_context.viewport =
    182       (float *)draw->viewport.scale;
    183 
    184 }
    185 
    186 
    187 static void pipeline(struct llvm_middle_end *llvm,
    188                      const struct draw_vertex_info *vert_info,
    189                      const struct draw_prim_info *prim_info)
    190 {
    191    if (prim_info->linear)
    192       draw_pipeline_run_linear( llvm->draw,
    193                                 vert_info,
    194                                 prim_info);
    195    else
    196       draw_pipeline_run( llvm->draw,
    197                          vert_info,
    198                          prim_info );
    199 }
    200 
    201 static void emit(struct pt_emit *emit,
    202                  const struct draw_vertex_info *vert_info,
    203                  const struct draw_prim_info *prim_info)
    204 {
    205    if (prim_info->linear) {
    206       draw_pt_emit_linear(emit, vert_info, prim_info);
    207    }
    208    else {
    209       draw_pt_emit(emit, vert_info, prim_info);
    210    }
    211 }
    212 
    213 static void
    214 llvm_pipeline_generic( struct draw_pt_middle_end *middle,
    215                        const struct draw_fetch_info *fetch_info,
    216                        const struct draw_prim_info *prim_info )
    217 {
    218    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
    219    struct draw_context *draw = fpme->draw;
    220    struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
    221    struct draw_prim_info gs_prim_info;
    222    struct draw_vertex_info llvm_vert_info;
    223    struct draw_vertex_info gs_vert_info;
    224    struct draw_vertex_info *vert_info;
    225    unsigned opt = fpme->opt;
    226    unsigned clipped = 0;
    227 
    228    llvm_vert_info.count = fetch_info->count;
    229    llvm_vert_info.vertex_size = fpme->vertex_size;
    230    llvm_vert_info.stride = fpme->vertex_size;
    231    llvm_vert_info.verts =
    232       (struct vertex_header *)MALLOC(fpme->vertex_size *
    233                                      align(fetch_info->count,  lp_native_vector_width / 32));
    234    if (!llvm_vert_info.verts) {
    235       assert(0);
    236       return;
    237    }
    238 
    239    if (fetch_info->linear)
    240       clipped = fpme->current_variant->jit_func( &fpme->llvm->jit_context,
    241                                        llvm_vert_info.verts,
    242                                        (const char **)draw->pt.user.vbuffer,
    243                                        fetch_info->start,
    244                                        fetch_info->count,
    245                                        fpme->vertex_size,
    246                                        draw->pt.vertex_buffer,
    247                                        draw->instance_id);
    248    else
    249       clipped = fpme->current_variant->jit_func_elts( &fpme->llvm->jit_context,
    250                                             llvm_vert_info.verts,
    251                                             (const char **)draw->pt.user.vbuffer,
    252                                             fetch_info->elts,
    253                                             fetch_info->count,
    254                                             fpme->vertex_size,
    255                                             draw->pt.vertex_buffer,
    256                                             draw->instance_id);
    257 
    258    /* Finished with fetch and vs:
    259     */
    260    fetch_info = NULL;
    261    vert_info = &llvm_vert_info;
    262 
    263 
    264    if ((opt & PT_SHADE) && gshader) {
    265       draw_geometry_shader_run(gshader,
    266                                draw->pt.user.gs_constants,
    267                                draw->pt.user.gs_constants_size,
    268                                vert_info,
    269                                prim_info,
    270                                &gs_vert_info,
    271                                &gs_prim_info);
    272 
    273       FREE(vert_info->verts);
    274       vert_info = &gs_vert_info;
    275       prim_info = &gs_prim_info;
    276 
    277       clipped = draw_pt_post_vs_run( fpme->post_vs, vert_info );
    278 
    279    }
    280 
    281    /* stream output needs to be done before clipping */
    282    draw_pt_so_emit( fpme->so_emit,
    283 		    vert_info,
    284                     prim_info );
    285 
    286    if (clipped) {
    287       opt |= PT_PIPELINE;
    288    }
    289 
    290    /* Do we need to run the pipeline? Now will come here if clipped
    291     */
    292    if (opt & PT_PIPELINE) {
    293       pipeline( fpme,
    294                 vert_info,
    295                 prim_info );
    296    }
    297    else {
    298       emit( fpme->emit,
    299             vert_info,
    300             prim_info );
    301    }
    302    FREE(vert_info->verts);
    303 }
    304 
    305 
    306 static void llvm_middle_end_run( struct draw_pt_middle_end *middle,
    307                                  const unsigned *fetch_elts,
    308                                  unsigned fetch_count,
    309                                  const ushort *draw_elts,
    310                                  unsigned draw_count,
    311                                  unsigned prim_flags )
    312 {
    313    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
    314    struct draw_fetch_info fetch_info;
    315    struct draw_prim_info prim_info;
    316 
    317    fetch_info.linear = FALSE;
    318    fetch_info.start = 0;
    319    fetch_info.elts = fetch_elts;
    320    fetch_info.count = fetch_count;
    321 
    322    prim_info.linear = FALSE;
    323    prim_info.start = 0;
    324    prim_info.count = draw_count;
    325    prim_info.elts = draw_elts;
    326    prim_info.prim = fpme->input_prim;
    327    prim_info.flags = prim_flags;
    328    prim_info.primitive_count = 1;
    329    prim_info.primitive_lengths = &draw_count;
    330 
    331    llvm_pipeline_generic( middle, &fetch_info, &prim_info );
    332 }
    333 
    334 
    335 static void llvm_middle_end_linear_run( struct draw_pt_middle_end *middle,
    336                                        unsigned start,
    337                                        unsigned count,
    338                                        unsigned prim_flags)
    339 {
    340    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
    341    struct draw_fetch_info fetch_info;
    342    struct draw_prim_info prim_info;
    343 
    344    fetch_info.linear = TRUE;
    345    fetch_info.start = start;
    346    fetch_info.count = count;
    347    fetch_info.elts = NULL;
    348 
    349    prim_info.linear = TRUE;
    350    prim_info.start = 0;
    351    prim_info.count = count;
    352    prim_info.elts = NULL;
    353    prim_info.prim = fpme->input_prim;
    354    prim_info.flags = prim_flags;
    355    prim_info.primitive_count = 1;
    356    prim_info.primitive_lengths = &count;
    357 
    358    llvm_pipeline_generic( middle, &fetch_info, &prim_info );
    359 }
    360 
    361 
    362 
    363 static boolean
    364 llvm_middle_end_linear_run_elts( struct draw_pt_middle_end *middle,
    365                                  unsigned start,
    366                                  unsigned count,
    367                                  const ushort *draw_elts,
    368                                  unsigned draw_count,
    369                                  unsigned prim_flags )
    370 {
    371    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
    372    struct draw_fetch_info fetch_info;
    373    struct draw_prim_info prim_info;
    374 
    375    fetch_info.linear = TRUE;
    376    fetch_info.start = start;
    377    fetch_info.count = count;
    378    fetch_info.elts = NULL;
    379 
    380    prim_info.linear = FALSE;
    381    prim_info.start = 0;
    382    prim_info.count = draw_count;
    383    prim_info.elts = draw_elts;
    384    prim_info.prim = fpme->input_prim;
    385    prim_info.flags = prim_flags;
    386    prim_info.primitive_count = 1;
    387    prim_info.primitive_lengths = &draw_count;
    388 
    389    llvm_pipeline_generic( middle, &fetch_info, &prim_info );
    390 
    391    return TRUE;
    392 }
    393 
    394 
    395 
    396 static void llvm_middle_end_finish( struct draw_pt_middle_end *middle )
    397 {
    398    /* nothing to do */
    399 }
    400 
    401 static void llvm_middle_end_destroy( struct draw_pt_middle_end *middle )
    402 {
    403    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
    404 
    405    if (fpme->fetch)
    406       draw_pt_fetch_destroy( fpme->fetch );
    407 
    408    if (fpme->emit)
    409       draw_pt_emit_destroy( fpme->emit );
    410 
    411    if (fpme->so_emit)
    412       draw_pt_so_emit_destroy( fpme->so_emit );
    413 
    414    if (fpme->post_vs)
    415       draw_pt_post_vs_destroy( fpme->post_vs );
    416 
    417    FREE(middle);
    418 }
    419 
    420 
    421 struct draw_pt_middle_end *
    422 draw_pt_fetch_pipeline_or_emit_llvm(struct draw_context *draw)
    423 {
    424    struct llvm_middle_end *fpme = 0;
    425 
    426    if (!draw->llvm)
    427       return NULL;
    428 
    429    fpme = CALLOC_STRUCT( llvm_middle_end );
    430    if (!fpme)
    431       goto fail;
    432 
    433    fpme->base.prepare         = llvm_middle_end_prepare;
    434    fpme->base.run             = llvm_middle_end_run;
    435    fpme->base.run_linear      = llvm_middle_end_linear_run;
    436    fpme->base.run_linear_elts = llvm_middle_end_linear_run_elts;
    437    fpme->base.finish          = llvm_middle_end_finish;
    438    fpme->base.destroy         = llvm_middle_end_destroy;
    439 
    440    fpme->draw = draw;
    441 
    442    fpme->fetch = draw_pt_fetch_create( draw );
    443    if (!fpme->fetch)
    444       goto fail;
    445 
    446    fpme->post_vs = draw_pt_post_vs_create( draw );
    447    if (!fpme->post_vs)
    448       goto fail;
    449 
    450    fpme->emit = draw_pt_emit_create( draw );
    451    if (!fpme->emit)
    452       goto fail;
    453 
    454    fpme->so_emit = draw_pt_so_emit_create( draw );
    455    if (!fpme->so_emit)
    456       goto fail;
    457 
    458    fpme->llvm = draw->llvm;
    459    if (!fpme->llvm)
    460       goto fail;
    461 
    462    fpme->current_variant = NULL;
    463 
    464    return &fpme->base;
    465 
    466  fail:
    467    if (fpme)
    468       llvm_middle_end_destroy( &fpme->base );
    469 
    470    return NULL;
    471 }
    472