Home | History | Annotate | Download | only in util
      1 /**************************************************************************
      2  *
      3  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
      4  * All Rights Reserved.
      5  * Copyright 2009 Marek Olk <maraeo (at) gmail.com>
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the
      9  * "Software"), to deal in the Software without restriction, including
     10  * without limitation the rights to use, copy, modify, merge, publish,
     11  * distribute, sub license, and/or sell copies of the Software, and to
     12  * permit persons to whom the Software is furnished to do so, subject to
     13  * the following conditions:
     14  *
     15  * The above copyright notice and this permission notice (including the
     16  * next paragraph) shall be included in all copies or substantial portions
     17  * of the Software.
     18  *
     19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     22  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
     23  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     26  *
     27  **************************************************************************/
     28 
     29 /**
     30  * @file
     31  * Simple vertex/fragment shader generators.
     32  *
     33  * @author Brian Paul
     34            Marek Olk
     35  */
     36 
     37 
     38 #include "pipe/p_context.h"
     39 #include "pipe/p_shader_tokens.h"
     40 #include "pipe/p_state.h"
     41 #include "util/u_simple_shaders.h"
     42 #include "util/u_debug.h"
     43 #include "util/u_memory.h"
     44 #include "tgsi/tgsi_dump.h"
     45 #include "tgsi/tgsi_strings.h"
     46 #include "tgsi/tgsi_ureg.h"
     47 #include "tgsi/tgsi_text.h"
     48 #include <stdio.h> /* include last */
     49 
     50 
     51 
     52 /**
     53  * Make simple vertex pass-through shader.
     54  * \param num_attribs  number of attributes to pass through
     55  * \param semantic_names  array of semantic names for each attribute
     56  * \param semantic_indexes  array of semantic indexes for each attribute
     57  */
     58 void *
     59 util_make_vertex_passthrough_shader(struct pipe_context *pipe,
     60                                     uint num_attribs,
     61                                     const uint *semantic_names,
     62                                     const uint *semantic_indexes)
     63 {
     64    return util_make_vertex_passthrough_shader_with_so(pipe, num_attribs,
     65                                                       semantic_names,
     66                                                       semantic_indexes, NULL);
     67 }
     68 
     69 void *
     70 util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe,
     71                                     uint num_attribs,
     72                                     const uint *semantic_names,
     73                                     const uint *semantic_indexes,
     74 				    const struct pipe_stream_output_info *so)
     75 {
     76    struct ureg_program *ureg;
     77    uint i;
     78 
     79    ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
     80    if (ureg == NULL)
     81       return NULL;
     82 
     83    for (i = 0; i < num_attribs; i++) {
     84       struct ureg_src src;
     85       struct ureg_dst dst;
     86 
     87       src = ureg_DECL_vs_input( ureg, i );
     88 
     89       dst = ureg_DECL_output( ureg,
     90                               semantic_names[i],
     91                               semantic_indexes[i]);
     92 
     93       ureg_MOV( ureg, dst, src );
     94    }
     95 
     96    ureg_END( ureg );
     97 
     98    return ureg_create_shader_with_so_and_destroy( ureg, pipe, so );
     99 }
    100 
    101 
    102 /**
    103  * Make simple fragment texture shader:
    104  *  IMM {0,0,0,1}                         // (if writemask != 0xf)
    105  *  MOV OUT[0], IMM[0]                    // (if writemask != 0xf)
    106  *  TEX OUT[0].writemask, IN[0], SAMP[0], 2D;
    107  *  END;
    108  *
    109  * \param tex_target  one of PIPE_TEXTURE_x
    110  * \parma interp_mode  either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE
    111  * \param writemask  mask of TGSI_WRITEMASK_x
    112  */
    113 void *
    114 util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
    115                                         unsigned tex_target,
    116                                         unsigned interp_mode,
    117                                         unsigned writemask )
    118 {
    119    struct ureg_program *ureg;
    120    struct ureg_src sampler;
    121    struct ureg_src tex;
    122    struct ureg_dst out;
    123 
    124    assert(interp_mode == TGSI_INTERPOLATE_LINEAR ||
    125           interp_mode == TGSI_INTERPOLATE_PERSPECTIVE);
    126 
    127    ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
    128    if (ureg == NULL)
    129       return NULL;
    130 
    131    sampler = ureg_DECL_sampler( ureg, 0 );
    132 
    133    tex = ureg_DECL_fs_input( ureg,
    134                              TGSI_SEMANTIC_GENERIC, 0,
    135                              interp_mode );
    136 
    137    out = ureg_DECL_output( ureg,
    138                            TGSI_SEMANTIC_COLOR,
    139                            0 );
    140 
    141    if (writemask != TGSI_WRITEMASK_XYZW) {
    142       struct ureg_src imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
    143 
    144       ureg_MOV( ureg, out, imm );
    145    }
    146 
    147    ureg_TEX( ureg,
    148              ureg_writemask(out, writemask),
    149              tex_target, tex, sampler );
    150    ureg_END( ureg );
    151 
    152    return ureg_create_shader_and_destroy( ureg, pipe );
    153 }
    154 
    155 
    156 /**
    157  * Make a simple fragment shader that sets the output color to a color
    158  * taken from a texture.
    159  * \param tex_target  one of PIPE_TEXTURE_x
    160  */
    161 void *
    162 util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target,
    163                               unsigned interp_mode)
    164 {
    165    return util_make_fragment_tex_shader_writemask( pipe,
    166                                                    tex_target,
    167                                                    interp_mode,
    168                                                    TGSI_WRITEMASK_XYZW );
    169 }
    170 
    171 
    172 /**
    173  * Make a simple fragment texture shader which reads an X component from
    174  * a texture and writes it as depth.
    175  */
    176 void *
    177 util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
    178                                          unsigned tex_target,
    179                                          unsigned interp_mode)
    180 {
    181    struct ureg_program *ureg;
    182    struct ureg_src sampler;
    183    struct ureg_src tex;
    184    struct ureg_dst out, depth;
    185    struct ureg_src imm;
    186 
    187    ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
    188    if (ureg == NULL)
    189       return NULL;
    190 
    191    sampler = ureg_DECL_sampler( ureg, 0 );
    192 
    193    tex = ureg_DECL_fs_input( ureg,
    194                              TGSI_SEMANTIC_GENERIC, 0,
    195                              interp_mode );
    196 
    197    out = ureg_DECL_output( ureg,
    198                            TGSI_SEMANTIC_COLOR,
    199                            0 );
    200 
    201    depth = ureg_DECL_output( ureg,
    202                              TGSI_SEMANTIC_POSITION,
    203                              0 );
    204 
    205    imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
    206 
    207    ureg_MOV( ureg, out, imm );
    208 
    209    ureg_TEX( ureg,
    210              ureg_writemask(depth, TGSI_WRITEMASK_Z),
    211              tex_target, tex, sampler );
    212    ureg_END( ureg );
    213 
    214    return ureg_create_shader_and_destroy( ureg, pipe );
    215 }
    216 
    217 
    218 /**
    219  * Make a simple fragment texture shader which reads the texture unit 0 and 1
    220  * and writes it as depth and stencil, respectively.
    221  */
    222 void *
    223 util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe,
    224                                                 unsigned tex_target,
    225                                                 unsigned interp_mode)
    226 {
    227    struct ureg_program *ureg;
    228    struct ureg_src depth_sampler, stencil_sampler;
    229    struct ureg_src tex;
    230    struct ureg_dst out, depth, stencil;
    231    struct ureg_src imm;
    232 
    233    ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
    234    if (ureg == NULL)
    235       return NULL;
    236 
    237    depth_sampler = ureg_DECL_sampler( ureg, 0 );
    238    stencil_sampler = ureg_DECL_sampler( ureg, 1 );
    239 
    240    tex = ureg_DECL_fs_input( ureg,
    241                              TGSI_SEMANTIC_GENERIC, 0,
    242                              interp_mode );
    243 
    244    out = ureg_DECL_output( ureg,
    245                            TGSI_SEMANTIC_COLOR,
    246                            0 );
    247 
    248    depth = ureg_DECL_output( ureg,
    249                              TGSI_SEMANTIC_POSITION,
    250                              0 );
    251 
    252    stencil = ureg_DECL_output( ureg,
    253                              TGSI_SEMANTIC_STENCIL,
    254                              0 );
    255 
    256    imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
    257 
    258    ureg_MOV( ureg, out, imm );
    259 
    260    ureg_TEX( ureg,
    261              ureg_writemask(depth, TGSI_WRITEMASK_Z),
    262              tex_target, tex, depth_sampler );
    263    ureg_TEX( ureg,
    264              ureg_writemask(stencil, TGSI_WRITEMASK_Y),
    265              tex_target, tex, stencil_sampler );
    266    ureg_END( ureg );
    267 
    268    return ureg_create_shader_and_destroy( ureg, pipe );
    269 }
    270 
    271 
    272 /**
    273  * Make a simple fragment texture shader which reads a texture and writes it
    274  * as stencil.
    275  */
    276 void *
    277 util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe,
    278                                            unsigned tex_target,
    279                                            unsigned interp_mode)
    280 {
    281    struct ureg_program *ureg;
    282    struct ureg_src stencil_sampler;
    283    struct ureg_src tex;
    284    struct ureg_dst out, stencil;
    285    struct ureg_src imm;
    286 
    287    ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
    288    if (ureg == NULL)
    289       return NULL;
    290 
    291    stencil_sampler = ureg_DECL_sampler( ureg, 0 );
    292 
    293    tex = ureg_DECL_fs_input( ureg,
    294                              TGSI_SEMANTIC_GENERIC, 0,
    295                              interp_mode );
    296 
    297    out = ureg_DECL_output( ureg,
    298                            TGSI_SEMANTIC_COLOR,
    299                            0 );
    300 
    301    stencil = ureg_DECL_output( ureg,
    302                              TGSI_SEMANTIC_STENCIL,
    303                              0 );
    304 
    305    imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
    306 
    307    ureg_MOV( ureg, out, imm );
    308 
    309    ureg_TEX( ureg,
    310              ureg_writemask(stencil, TGSI_WRITEMASK_Y),
    311              tex_target, tex, stencil_sampler );
    312    ureg_END( ureg );
    313 
    314    return ureg_create_shader_and_destroy( ureg, pipe );
    315 }
    316 
    317 
    318 /**
    319  * Make simple fragment color pass-through shader.
    320  */
    321 void *
    322 util_make_fragment_passthrough_shader(struct pipe_context *pipe)
    323 {
    324    return util_make_fragment_cloneinput_shader(pipe, 1, TGSI_SEMANTIC_COLOR,
    325                                                TGSI_INTERPOLATE_PERSPECTIVE);
    326 }
    327 
    328 
    329 /**
    330  * Make a fragment shader that copies the input color to N output colors.
    331  */
    332 void *
    333 util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs,
    334                                      int input_semantic,
    335                                      int input_interpolate)
    336 {
    337    struct ureg_program *ureg;
    338    struct ureg_src src;
    339    struct ureg_dst dst[PIPE_MAX_COLOR_BUFS];
    340    int i;
    341 
    342    assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
    343 
    344    ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
    345    if (ureg == NULL)
    346       return NULL;
    347 
    348    src = ureg_DECL_fs_input( ureg, input_semantic, 0,
    349                              input_interpolate );
    350 
    351    for (i = 0; i < num_cbufs; i++)
    352       dst[i] = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, i );
    353 
    354    for (i = 0; i < num_cbufs; i++)
    355       ureg_MOV( ureg, dst[i], src );
    356 
    357    ureg_END( ureg );
    358 
    359    return ureg_create_shader_and_destroy( ureg, pipe );
    360 }
    361 
    362 
    363 static void *
    364 util_make_fs_blit_msaa_gen(struct pipe_context *pipe,
    365                            unsigned tgsi_tex,
    366                            const char *output_semantic,
    367                            const char *output_mask)
    368 {
    369    static const char shader_templ[] =
    370          "FRAG\n"
    371          "DCL IN[0], GENERIC[0], LINEAR\n"
    372          "DCL SAMP[0]\n"
    373          "DCL OUT[0], %s\n"
    374          "DCL TEMP[0]\n"
    375 
    376          "F2U TEMP[0], IN[0]\n"
    377          "TXF OUT[0]%s, TEMP[0].xyzz, SAMP[0], %s\n"
    378          "END\n";
    379 
    380    const char *type = tgsi_texture_names[tgsi_tex];
    381    char text[sizeof(shader_templ)+100];
    382    struct tgsi_token tokens[1000];
    383    struct pipe_shader_state state = {tokens};
    384 
    385    assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
    386           tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
    387 
    388    sprintf(text, shader_templ, output_semantic, output_mask, type);
    389 
    390    if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
    391       puts(text);
    392       assert(0);
    393       return NULL;
    394    }
    395 #if 0
    396    tgsi_dump(state.tokens, 0);
    397 #endif
    398 
    399    return pipe->create_fs_state(pipe, &state);
    400 }
    401 
    402 
    403 /**
    404  * Make a fragment shader that sets the output color to a color
    405  * fetched from a multisample texture.
    406  * \param tex_target  one of PIPE_TEXTURE_x
    407  */
    408 void *
    409 util_make_fs_blit_msaa_color(struct pipe_context *pipe,
    410                              unsigned tgsi_tex)
    411 {
    412    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex,
    413                                      "COLOR[0]", "");
    414 }
    415 
    416 
    417 /**
    418  * Make a fragment shader that sets the output depth to a depth value
    419  * fetched from a multisample texture.
    420  * \param tex_target  one of PIPE_TEXTURE_x
    421  */
    422 void *
    423 util_make_fs_blit_msaa_depth(struct pipe_context *pipe,
    424                              unsigned tgsi_tex)
    425 {
    426    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex,
    427                                      "POSITION", ".z");
    428 }
    429 
    430 
    431 /**
    432  * Make a fragment shader that sets the output stencil to a stencil value
    433  * fetched from a multisample texture.
    434  * \param tex_target  one of PIPE_TEXTURE_x
    435  */
    436 void *
    437 util_make_fs_blit_msaa_stencil(struct pipe_context *pipe,
    438                                unsigned tgsi_tex)
    439 {
    440    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex,
    441                                      "STENCIL", ".y");
    442 }
    443 
    444 
    445 /**
    446  * Make a fragment shader that sets the output depth and stencil to depth
    447  * and stencil values fetched from two multisample textures / samplers.
    448  * The sizes of both textures should match (it should be one depth-stencil
    449  * texture).
    450  * \param tex_target  one of PIPE_TEXTURE_x
    451  */
    452 void *
    453 util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe,
    454                                     unsigned tgsi_tex)
    455 {
    456    static const char shader_templ[] =
    457          "FRAG\n"
    458          "DCL IN[0], GENERIC[0], LINEAR\n"
    459          "DCL SAMP[0..1]\n"
    460          "DCL OUT[0], POSITION\n"
    461          "DCL OUT[1], STENCIL\n"
    462          "DCL TEMP[0]\n"
    463 
    464          "F2U TEMP[0], IN[0]\n"
    465          "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
    466          "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
    467          "END\n";
    468 
    469    const char *type = tgsi_texture_names[tgsi_tex];
    470    char text[sizeof(shader_templ)+100];
    471    struct tgsi_token tokens[1000];
    472    struct pipe_shader_state state = {tokens};
    473 
    474    assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
    475           tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
    476 
    477    sprintf(text, shader_templ, type, type);
    478 
    479    if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
    480       assert(0);
    481       return NULL;
    482    }
    483 #if 0
    484    tgsi_dump(state.tokens, 0);
    485 #endif
    486 
    487    return pipe->create_fs_state(pipe, &state);
    488 }
    489