Home | History | Annotate | Download | only in softpipe
      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 #include "sp_context.h"
     29 #include "sp_state.h"
     30 #include "sp_fs.h"
     31 #include "sp_texture.h"
     32 
     33 #include "pipe/p_defines.h"
     34 #include "util/u_memory.h"
     35 #include "util/u_inlines.h"
     36 #include "util/u_pstipple.h"
     37 #include "draw/draw_context.h"
     38 #include "draw/draw_vs.h"
     39 #include "draw/draw_gs.h"
     40 #include "tgsi/tgsi_dump.h"
     41 #include "tgsi/tgsi_scan.h"
     42 #include "tgsi/tgsi_parse.h"
     43 
     44 
     45 /**
     46  * Create a new fragment shader variant.
     47  */
     48 static struct sp_fragment_shader_variant *
     49 create_fs_variant(struct softpipe_context *softpipe,
     50                   struct sp_fragment_shader *fs,
     51                   const struct sp_fragment_shader_variant_key *key)
     52 {
     53    struct sp_fragment_shader_variant *var;
     54    struct pipe_shader_state *curfs = &fs->shader;
     55 
     56    /* codegen, create variant object */
     57    var = softpipe_create_fs_variant_exec(softpipe);
     58 
     59    if (var) {
     60       var->key = *key;
     61 
     62 #if DO_PSTIPPLE_IN_HELPER_MODULE
     63       if (key->polygon_stipple) {
     64          /* get new shader that implements polygon stippling */
     65          var->tokens =
     66             util_pstipple_create_fragment_shader(curfs->tokens,
     67                                                  &var->stipple_sampler_unit, 0,
     68                                                  TGSI_FILE_INPUT);
     69       }
     70       else
     71 #endif
     72       {
     73          var->tokens = tgsi_dup_tokens(curfs->tokens);
     74          var->stipple_sampler_unit = 0;
     75       }
     76 
     77       tgsi_scan_shader(var->tokens, &var->info);
     78 
     79       /* See comments elsewhere about draw fragment shaders */
     80 #if 0
     81       /* draw's fs state */
     82       var->draw_shader = draw_create_fragment_shader(softpipe->draw,
     83                                                      &fs->shader);
     84       if (!var->draw_shader) {
     85          var->delete(var);
     86          FREE((void *) var->tokens);
     87          return NULL;
     88       }
     89 #endif
     90 
     91       /* insert variant into linked list */
     92       var->next = fs->variants;
     93       fs->variants = var;
     94    }
     95 
     96    return var;
     97 }
     98 
     99 
    100 struct sp_fragment_shader_variant *
    101 softpipe_find_fs_variant(struct softpipe_context *sp,
    102                          struct sp_fragment_shader *fs,
    103                          const struct sp_fragment_shader_variant_key *key)
    104 {
    105    struct sp_fragment_shader_variant *var;
    106 
    107    for (var = fs->variants; var; var = var->next) {
    108       if (memcmp(&var->key, key, sizeof(*key)) == 0) {
    109          /* found it */
    110          return var;
    111       }
    112    }
    113 
    114    return create_fs_variant(sp, fs, key);
    115 }
    116 
    117 
    118 static void *
    119 softpipe_create_fs_state(struct pipe_context *pipe,
    120                          const struct pipe_shader_state *templ)
    121 {
    122    struct softpipe_context *softpipe = softpipe_context(pipe);
    123    struct sp_fragment_shader *state = CALLOC_STRUCT(sp_fragment_shader);
    124 
    125    /* debug */
    126    if (softpipe->dump_fs)
    127       tgsi_dump(templ->tokens, 0);
    128 
    129    /* we need to keep a local copy of the tokens */
    130    state->shader.tokens = tgsi_dup_tokens(templ->tokens);
    131 
    132    /* draw's fs state */
    133    state->draw_shader = draw_create_fragment_shader(softpipe->draw,
    134                                                     &state->shader);
    135    if (!state->draw_shader) {
    136       tgsi_free_tokens(state->shader.tokens);
    137       FREE(state);
    138       return NULL;
    139    }
    140 
    141    return state;
    142 }
    143 
    144 
    145 static void
    146 softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
    147 {
    148    struct softpipe_context *softpipe = softpipe_context(pipe);
    149    struct sp_fragment_shader *state = (struct sp_fragment_shader *) fs;
    150 
    151    if (softpipe->fs == fs)
    152       return;
    153 
    154    draw_flush(softpipe->draw);
    155 
    156    softpipe->fs = fs;
    157 
    158    /* This depends on the current fragment shader and must always be
    159     * re-validated before use.
    160     */
    161    softpipe->fs_variant = NULL;
    162 
    163    if (state)
    164       draw_bind_fragment_shader(softpipe->draw,
    165                                 state->draw_shader);
    166    else
    167       draw_bind_fragment_shader(softpipe->draw, NULL);
    168 
    169    softpipe->dirty |= SP_NEW_FS;
    170 }
    171 
    172 
    173 static void
    174 softpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
    175 {
    176    struct softpipe_context *softpipe = softpipe_context(pipe);
    177    struct sp_fragment_shader *state = fs;
    178    struct sp_fragment_shader_variant *var, *next_var;
    179 
    180    assert(fs != softpipe->fs);
    181 
    182    /* delete variants */
    183    for (var = state->variants; var; var = next_var) {
    184       next_var = var->next;
    185 
    186       assert(var != softpipe->fs_variant);
    187 
    188       /* See comments elsewhere about draw fragment shaders */
    189 #if 0
    190       draw_delete_fragment_shader(softpipe->draw, var->draw_shader);
    191 #endif
    192 
    193       var->delete(var, softpipe->fs_machine);
    194    }
    195 
    196    draw_delete_fragment_shader(softpipe->draw, state->draw_shader);
    197 
    198    tgsi_free_tokens(state->shader.tokens);
    199    FREE(state);
    200 }
    201 
    202 
    203 static void *
    204 softpipe_create_vs_state(struct pipe_context *pipe,
    205                          const struct pipe_shader_state *templ)
    206 {
    207    struct softpipe_context *softpipe = softpipe_context(pipe);
    208    struct sp_vertex_shader *state;
    209 
    210    state = CALLOC_STRUCT(sp_vertex_shader);
    211    if (!state)
    212       goto fail;
    213 
    214    /* copy shader tokens, the ones passed in will go away.
    215     */
    216    state->shader.tokens = tgsi_dup_tokens(templ->tokens);
    217    if (state->shader.tokens == NULL)
    218       goto fail;
    219 
    220    state->draw_data = draw_create_vertex_shader(softpipe->draw, templ);
    221    if (state->draw_data == NULL)
    222       goto fail;
    223 
    224    state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
    225 
    226    return state;
    227 
    228 fail:
    229    if (state) {
    230       tgsi_free_tokens(state->shader.tokens);
    231       FREE( state->draw_data );
    232       FREE( state );
    233    }
    234    return NULL;
    235 }
    236 
    237 
    238 static void
    239 softpipe_bind_vs_state(struct pipe_context *pipe, void *vs)
    240 {
    241    struct softpipe_context *softpipe = softpipe_context(pipe);
    242 
    243    softpipe->vs = (struct sp_vertex_shader *) vs;
    244 
    245    draw_bind_vertex_shader(softpipe->draw,
    246                            (softpipe->vs ? softpipe->vs->draw_data : NULL));
    247 
    248    softpipe->dirty |= SP_NEW_VS;
    249 }
    250 
    251 
    252 static void
    253 softpipe_delete_vs_state(struct pipe_context *pipe, void *vs)
    254 {
    255    struct softpipe_context *softpipe = softpipe_context(pipe);
    256 
    257    struct sp_vertex_shader *state = (struct sp_vertex_shader *) vs;
    258 
    259    draw_delete_vertex_shader(softpipe->draw, state->draw_data);
    260    tgsi_free_tokens(state->shader.tokens);
    261    FREE( state );
    262 }
    263 
    264 
    265 static void *
    266 softpipe_create_gs_state(struct pipe_context *pipe,
    267                          const struct pipe_shader_state *templ)
    268 {
    269    struct softpipe_context *softpipe = softpipe_context(pipe);
    270    struct sp_geometry_shader *state;
    271 
    272    state = CALLOC_STRUCT(sp_geometry_shader);
    273    if (!state)
    274       goto fail;
    275 
    276    state->shader = *templ;
    277 
    278    if (templ->tokens) {
    279       /* debug */
    280       if (softpipe->dump_gs)
    281          tgsi_dump(templ->tokens, 0);
    282 
    283       /* copy shader tokens, the ones passed in will go away.
    284        */
    285       state->shader.tokens = tgsi_dup_tokens(templ->tokens);
    286       if (state->shader.tokens == NULL)
    287          goto fail;
    288 
    289       state->draw_data = draw_create_geometry_shader(softpipe->draw, templ);
    290       if (state->draw_data == NULL)
    291          goto fail;
    292 
    293       state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
    294    }
    295 
    296    return state;
    297 
    298 fail:
    299    if (state) {
    300       tgsi_free_tokens(state->shader.tokens);
    301       FREE( state->draw_data );
    302       FREE( state );
    303    }
    304    return NULL;
    305 }
    306 
    307 
    308 static void
    309 softpipe_bind_gs_state(struct pipe_context *pipe, void *gs)
    310 {
    311    struct softpipe_context *softpipe = softpipe_context(pipe);
    312 
    313    softpipe->gs = (struct sp_geometry_shader *)gs;
    314 
    315    draw_bind_geometry_shader(softpipe->draw,
    316                              (softpipe->gs ? softpipe->gs->draw_data : NULL));
    317 
    318    softpipe->dirty |= SP_NEW_GS;
    319 }
    320 
    321 
    322 static void
    323 softpipe_delete_gs_state(struct pipe_context *pipe, void *gs)
    324 {
    325    struct softpipe_context *softpipe = softpipe_context(pipe);
    326 
    327    struct sp_geometry_shader *state =
    328       (struct sp_geometry_shader *)gs;
    329 
    330    draw_delete_geometry_shader(softpipe->draw,
    331                                (state) ? state->draw_data : 0);
    332 
    333    tgsi_free_tokens(state->shader.tokens);
    334    FREE(state);
    335 }
    336 
    337 
    338 static void
    339 softpipe_set_constant_buffer(struct pipe_context *pipe,
    340                              uint shader, uint index,
    341                              const struct pipe_constant_buffer *cb)
    342 {
    343    struct softpipe_context *softpipe = softpipe_context(pipe);
    344    struct pipe_resource *constants = cb ? cb->buffer : NULL;
    345    unsigned size;
    346    const void *data;
    347 
    348    assert(shader < PIPE_SHADER_TYPES);
    349 
    350    if (cb && cb->user_buffer) {
    351       constants = softpipe_user_buffer_create(pipe->screen,
    352                                               (void *) cb->user_buffer,
    353                                               cb->buffer_size,
    354                                               PIPE_BIND_CONSTANT_BUFFER);
    355    }
    356 
    357    size = cb ? cb->buffer_size : 0;
    358    data = constants ? softpipe_resource_data(constants) : NULL;
    359    if (data)
    360       data = (const char *) data + cb->buffer_offset;
    361 
    362    draw_flush(softpipe->draw);
    363 
    364    /* note: reference counting */
    365    pipe_resource_reference(&softpipe->constants[shader][index], constants);
    366 
    367    if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
    368       draw_set_mapped_constant_buffer(softpipe->draw, shader, index, data, size);
    369    }
    370 
    371    softpipe->mapped_constants[shader][index] = data;
    372    softpipe->const_buffer_size[shader][index] = size;
    373 
    374    softpipe->dirty |= SP_NEW_CONSTANTS;
    375 
    376    if (cb && cb->user_buffer) {
    377       pipe_resource_reference(&constants, NULL);
    378    }
    379 }
    380 
    381 static void *
    382 softpipe_create_compute_state(struct pipe_context *pipe,
    383                               const struct pipe_compute_state *templ)
    384 {
    385    struct softpipe_context *softpipe = softpipe_context(pipe);
    386    const struct tgsi_token *tokens;
    387    struct sp_compute_shader *state;
    388    if (templ->ir_type != PIPE_SHADER_IR_TGSI)
    389       return NULL;
    390 
    391    tokens = templ->prog;
    392    /* debug */
    393    if (softpipe->dump_cs)
    394       tgsi_dump(tokens, 0);
    395 
    396    state = CALLOC_STRUCT(sp_compute_shader);
    397 
    398    state->shader = *templ;
    399    state->tokens = tgsi_dup_tokens(tokens);
    400    tgsi_scan_shader(state->tokens, &state->info);
    401 
    402    state->max_sampler = state->info.file_max[TGSI_FILE_SAMPLER];
    403 
    404    return state;
    405 }
    406 
    407 static void
    408 softpipe_bind_compute_state(struct pipe_context *pipe,
    409                             void *cs)
    410 {
    411    struct softpipe_context *softpipe = softpipe_context(pipe);
    412    struct sp_compute_shader *state = (struct sp_compute_shader *)cs;
    413    if (softpipe->cs == state)
    414       return;
    415 
    416    softpipe->cs = state;
    417 }
    418 
    419 static void
    420 softpipe_delete_compute_state(struct pipe_context *pipe,
    421                               void *cs)
    422 {
    423    MAYBE_UNUSED struct softpipe_context *softpipe = softpipe_context(pipe);
    424    struct sp_compute_shader *state = (struct sp_compute_shader *)cs;
    425 
    426    assert(softpipe->cs != state);
    427    tgsi_free_tokens(state->tokens);
    428    FREE(state);
    429 }
    430 
    431 void
    432 softpipe_init_shader_funcs(struct pipe_context *pipe)
    433 {
    434    pipe->create_fs_state = softpipe_create_fs_state;
    435    pipe->bind_fs_state   = softpipe_bind_fs_state;
    436    pipe->delete_fs_state = softpipe_delete_fs_state;
    437 
    438    pipe->create_vs_state = softpipe_create_vs_state;
    439    pipe->bind_vs_state   = softpipe_bind_vs_state;
    440    pipe->delete_vs_state = softpipe_delete_vs_state;
    441 
    442    pipe->create_gs_state = softpipe_create_gs_state;
    443    pipe->bind_gs_state   = softpipe_bind_gs_state;
    444    pipe->delete_gs_state = softpipe_delete_gs_state;
    445 
    446    pipe->set_constant_buffer = softpipe_set_constant_buffer;
    447 
    448    pipe->create_compute_state = softpipe_create_compute_state;
    449    pipe->bind_compute_state = softpipe_bind_compute_state;
    450    pipe->delete_compute_state = softpipe_delete_compute_state;
    451 }
    452