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 "util/u_memory.h"
     34 #include "util/u_math.h"
     35 #include "draw/draw_context.h"
     36 #include "draw/draw_private.h"
     37 #include "draw/draw_vbuf.h"
     38 #include "draw/draw_vertex.h"
     39 #include "draw/draw_vs.h"
     40 #include "translate/translate.h"
     41 
     42 /* A first pass at incorporating vertex fetch/emit functionality into
     43  */
     44 struct draw_vs_variant_generic {
     45    struct draw_vs_variant base;
     46 
     47    struct draw_vertex_shader *shader;
     48    struct draw_context *draw;
     49 
     50    /* Basic plan is to run these two translate functions before/after
     51     * the vertex shader's existing run_linear() routine to simulate
     52     * the inclusion of this functionality into the shader...
     53     *
     54     * Next will look at actually including it.
     55     */
     56    struct translate *fetch;
     57    struct translate *emit;
     58 
     59    unsigned temp_vertex_stride;
     60 };
     61 
     62 
     63 
     64 
     65 
     66 static void vsvg_set_buffer( struct draw_vs_variant *variant,
     67                              unsigned buffer,
     68                              const void *ptr,
     69                              unsigned stride,
     70                              unsigned max_index )
     71 {
     72    struct draw_vs_variant_generic *vsvg = (struct draw_vs_variant_generic *)variant;
     73 
     74    vsvg->fetch->set_buffer(vsvg->fetch,
     75                            buffer,
     76                            ptr,
     77                            stride,
     78                            max_index );
     79 }
     80 
     81 static const struct pipe_viewport_state *
     82 find_viewport(struct draw_context *draw,
     83               char *buffer,
     84               unsigned vertex_idx,
     85               unsigned stride)
     86 {
     87    int viewport_index_output =
     88       draw_current_shader_viewport_index_output(draw);
     89    char *ptr = buffer + vertex_idx * stride;
     90    unsigned *data = (unsigned *)ptr;
     91    int viewport_index =
     92       draw_current_shader_uses_viewport_index(draw) ?
     93       data[viewport_index_output * 4] : 0;
     94 
     95    viewport_index = draw_clamp_viewport_idx(viewport_index);
     96 
     97    return &draw->viewports[viewport_index];
     98 }
     99 
    100 
    101 /* Mainly for debug at this stage:
    102  */
    103 static void do_rhw_viewport( struct draw_vs_variant_generic *vsvg,
    104                              unsigned count,
    105                              void *output_buffer )
    106 {
    107    char *ptr = (char *)output_buffer;
    108    unsigned stride = vsvg->temp_vertex_stride;
    109    unsigned j;
    110 
    111    ptr += vsvg->base.vs->position_output * 4 * sizeof(float);
    112 
    113    for (j = 0; j < count; j++, ptr += stride) {
    114       const struct pipe_viewport_state *viewport =
    115          find_viewport(vsvg->base.vs->draw, (char*)output_buffer,
    116                        j, stride);
    117       const float *scale = viewport->scale;
    118       const float *trans = viewport->translate;
    119       float *data = (float *)ptr;
    120       float w = 1.0f / data[3];
    121 
    122       data[0] = data[0] * w * scale[0] + trans[0];
    123       data[1] = data[1] * w * scale[1] + trans[1];
    124       data[2] = data[2] * w * scale[2] + trans[2];
    125       data[3] = w;
    126    }
    127 }
    128 
    129 static void do_viewport( struct draw_vs_variant_generic *vsvg,
    130                          unsigned count,
    131                          void *output_buffer )
    132 {
    133    char *ptr = (char *)output_buffer;
    134    unsigned stride = vsvg->temp_vertex_stride;
    135    unsigned j;
    136 
    137    ptr += vsvg->base.vs->position_output * 4 * sizeof(float);
    138 
    139    for (j = 0; j < count; j++, ptr += stride) {
    140       const struct pipe_viewport_state *viewport =
    141          find_viewport(vsvg->base.vs->draw, (char*)output_buffer,
    142                        j, stride);
    143       const float *scale = viewport->scale;
    144       const float *trans = viewport->translate;
    145       float *data = (float *)ptr;
    146 
    147       data[0] = data[0] * scale[0] + trans[0];
    148       data[1] = data[1] * scale[1] + trans[1];
    149       data[2] = data[2] * scale[2] + trans[2];
    150    }
    151 }
    152 
    153 
    154 static void PIPE_CDECL vsvg_run_elts( struct draw_vs_variant *variant,
    155                                       const unsigned *elts,
    156                                       unsigned count,
    157                                       void *output_buffer)
    158 {
    159    struct draw_vs_variant_generic *vsvg = (struct draw_vs_variant_generic *)variant;
    160    unsigned temp_vertex_stride = vsvg->temp_vertex_stride;
    161    void *temp_buffer = MALLOC( align(count,4) * temp_vertex_stride );
    162 
    163    if (0) debug_printf("%s %d \n", __FUNCTION__,  count);
    164 
    165    /* Want to do this in small batches for cache locality?
    166     */
    167 
    168    vsvg->fetch->run_elts( vsvg->fetch,
    169                           elts,
    170                           count,
    171                           vsvg->draw->start_instance,
    172                           vsvg->draw->instance_id,
    173                           temp_buffer );
    174 
    175    vsvg->base.vs->run_linear( vsvg->base.vs,
    176                               temp_buffer,
    177                               temp_buffer,
    178                               vsvg->base.vs->draw->pt.user.vs_constants,
    179                               vsvg->base.vs->draw->pt.user.vs_constants_size,
    180                               count,
    181                               temp_vertex_stride,
    182                               temp_vertex_stride);
    183 
    184    /* FIXME: geometry shading? */
    185 
    186    if (vsvg->base.key.clip) {
    187       /* not really handling clipping, just do the rhw so we can
    188        * see the results...
    189        */
    190       do_rhw_viewport( vsvg,
    191                        count,
    192                        temp_buffer );
    193    }
    194    else if (vsvg->base.key.viewport) {
    195       do_viewport( vsvg,
    196                    count,
    197                    temp_buffer );
    198    }
    199 
    200 
    201    vsvg->emit->set_buffer( vsvg->emit,
    202                            0,
    203                            temp_buffer,
    204                            temp_vertex_stride,
    205                            ~0 );
    206 
    207    vsvg->emit->set_buffer( vsvg->emit,
    208                            1,
    209                            &vsvg->draw->rasterizer->point_size,
    210                            0,
    211                            ~0 );
    212 
    213    vsvg->emit->run( vsvg->emit,
    214                     0, count,
    215                     vsvg->draw->start_instance,
    216                     vsvg->draw->instance_id,
    217                     output_buffer );
    218 
    219    FREE(temp_buffer);
    220 }
    221 
    222 
    223 static void PIPE_CDECL vsvg_run_linear( struct draw_vs_variant *variant,
    224                                         unsigned start,
    225                                         unsigned count,
    226                                         void *output_buffer )
    227 {
    228    struct draw_vs_variant_generic *vsvg = (struct draw_vs_variant_generic *)variant;
    229    unsigned temp_vertex_stride = vsvg->temp_vertex_stride;
    230    void *temp_buffer = MALLOC( align(count,4) * temp_vertex_stride );
    231 
    232    if (0) debug_printf("%s %d %d (sz %d, %d)\n", __FUNCTION__, start, count,
    233                        vsvg->base.key.output_stride,
    234                        temp_vertex_stride);
    235 
    236    vsvg->fetch->run( vsvg->fetch,
    237                      start,
    238                      count,
    239                      vsvg->draw->start_instance,
    240                      vsvg->draw->instance_id,
    241                      temp_buffer );
    242 
    243    vsvg->base.vs->run_linear( vsvg->base.vs,
    244                               temp_buffer,
    245                               temp_buffer,
    246                               vsvg->base.vs->draw->pt.user.vs_constants,
    247                               vsvg->base.vs->draw->pt.user.vs_constants_size,
    248                               count,
    249                               temp_vertex_stride,
    250                               temp_vertex_stride);
    251 
    252    if (vsvg->base.key.clip) {
    253       /* not really handling clipping, just do the rhw so we can
    254        * see the results...
    255        */
    256       do_rhw_viewport( vsvg,
    257                        count,
    258                        temp_buffer );
    259    }
    260    else if (vsvg->base.key.viewport) {
    261       do_viewport( vsvg,
    262                    count,
    263                    temp_buffer );
    264    }
    265 
    266    vsvg->emit->set_buffer( vsvg->emit,
    267                            0,
    268                            temp_buffer,
    269                            temp_vertex_stride,
    270                            ~0 );
    271 
    272    vsvg->emit->set_buffer( vsvg->emit,
    273                            1,
    274                            &vsvg->draw->rasterizer->point_size,
    275                            0,
    276                            ~0 );
    277 
    278    vsvg->emit->run( vsvg->emit,
    279                     0, count,
    280                     vsvg->draw->start_instance,
    281                     vsvg->draw->instance_id,
    282                     output_buffer );
    283 
    284    FREE(temp_buffer);
    285 }
    286 
    287 
    288 
    289 
    290 
    291 static void vsvg_destroy( struct draw_vs_variant *variant )
    292 {
    293    FREE(variant);
    294 }
    295 
    296 
    297 struct draw_vs_variant *
    298 draw_vs_create_variant_generic( struct draw_vertex_shader *vs,
    299                                 const struct draw_vs_variant_key *key )
    300 {
    301    unsigned i;
    302    struct translate_key fetch, emit;
    303 
    304    struct draw_vs_variant_generic *vsvg = CALLOC_STRUCT( draw_vs_variant_generic );
    305    if (!vsvg)
    306       return NULL;
    307 
    308    vsvg->base.key = *key;
    309    vsvg->base.vs = vs;
    310    vsvg->base.set_buffer    = vsvg_set_buffer;
    311    vsvg->base.run_elts      = vsvg_run_elts;
    312    vsvg->base.run_linear    = vsvg_run_linear;
    313    vsvg->base.destroy       = vsvg_destroy;
    314 
    315    vsvg->draw = vs->draw;
    316 
    317    vsvg->temp_vertex_stride = MAX2(key->nr_inputs,
    318                                    draw_total_vs_outputs(vs->draw)) * 4 * sizeof(float);
    319 
    320    /* Build free-standing fetch and emit functions:
    321     */
    322    fetch.nr_elements = key->nr_inputs;
    323    fetch.output_stride = vsvg->temp_vertex_stride;
    324    for (i = 0; i < key->nr_inputs; i++) {
    325       fetch.element[i].type = TRANSLATE_ELEMENT_NORMAL;
    326       fetch.element[i].input_format = key->element[i].in.format;
    327       fetch.element[i].input_buffer = key->element[i].in.buffer;
    328       fetch.element[i].input_offset = key->element[i].in.offset;
    329       fetch.element[i].instance_divisor = 0;
    330       fetch.element[i].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    331       fetch.element[i].output_offset = i * 4 * sizeof(float);
    332       assert(fetch.element[i].output_offset < fetch.output_stride);
    333    }
    334 
    335 
    336    emit.nr_elements = key->nr_outputs;
    337    emit.output_stride = key->output_stride;
    338    for (i = 0; i < key->nr_outputs; i++) {
    339       if (key->element[i].out.format != EMIT_1F_PSIZE)
    340       {
    341          emit.element[i].type = TRANSLATE_ELEMENT_NORMAL;
    342          emit.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    343          emit.element[i].input_buffer = 0;
    344          emit.element[i].input_offset = key->element[i].out.vs_output * 4 * sizeof(float);
    345          emit.element[i].instance_divisor = 0;
    346          emit.element[i].output_format = draw_translate_vinfo_format(key->element[i].out.format);
    347          emit.element[i].output_offset = key->element[i].out.offset;
    348          assert(emit.element[i].input_offset <= fetch.output_stride);
    349       }
    350       else {
    351          emit.element[i].type = TRANSLATE_ELEMENT_NORMAL;
    352          emit.element[i].input_format = PIPE_FORMAT_R32_FLOAT;
    353          emit.element[i].input_buffer = 1;
    354          emit.element[i].input_offset = 0;
    355          emit.element[i].instance_divisor = 0;
    356          emit.element[i].output_format = PIPE_FORMAT_R32_FLOAT;
    357          emit.element[i].output_offset = key->element[i].out.offset;
    358       }
    359    }
    360 
    361    vsvg->fetch = draw_vs_get_fetch( vs->draw, &fetch );
    362    vsvg->emit = draw_vs_get_emit( vs->draw, &emit );
    363 
    364    return &vsvg->base;
    365 }
    366 
    367 
    368 
    369 
    370 
    371