Home | History | Annotate | Download | only in util
      1 /**************************************************************************
      2  *
      3  * Copyright 2008 VMware, Inc.
      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 VMWARE 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 "util/u_string.h"
     45 #include "tgsi/tgsi_dump.h"
     46 #include "tgsi/tgsi_strings.h"
     47 #include "tgsi/tgsi_ureg.h"
     48 #include "tgsi/tgsi_text.h"
     49 #include <stdio.h> /* include last */
     50 
     51 
     52 
     53 /**
     54  * Make simple vertex pass-through shader.
     55  * \param num_attribs  number of attributes to pass through
     56  * \param semantic_names  array of semantic names for each attribute
     57  * \param semantic_indexes  array of semantic indexes for each attribute
     58  */
     59 void *
     60 util_make_vertex_passthrough_shader(struct pipe_context *pipe,
     61                                     uint num_attribs,
     62                                     const uint *semantic_names,
     63                                     const uint *semantic_indexes,
     64                                     bool window_space)
     65 {
     66    return util_make_vertex_passthrough_shader_with_so(pipe, num_attribs,
     67                                                       semantic_names,
     68                                                       semantic_indexes,
     69                                                       window_space, NULL);
     70 }
     71 
     72 void *
     73 util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe,
     74                                     uint num_attribs,
     75                                     const uint *semantic_names,
     76                                     const uint *semantic_indexes,
     77                                     bool window_space,
     78 				    const struct pipe_stream_output_info *so)
     79 {
     80    struct ureg_program *ureg;
     81    uint i;
     82 
     83    ureg = ureg_create( PIPE_SHADER_VERTEX );
     84    if (!ureg)
     85       return NULL;
     86 
     87    if (window_space)
     88       ureg_property(ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, TRUE);
     89 
     90    for (i = 0; i < num_attribs; i++) {
     91       struct ureg_src src;
     92       struct ureg_dst dst;
     93 
     94       src = ureg_DECL_vs_input( ureg, i );
     95 
     96       dst = ureg_DECL_output( ureg,
     97                               semantic_names[i],
     98                               semantic_indexes[i]);
     99 
    100       ureg_MOV( ureg, dst, src );
    101    }
    102 
    103    ureg_END( ureg );
    104 
    105    return ureg_create_shader_with_so_and_destroy( ureg, pipe, so );
    106 }
    107 
    108 
    109 void *util_make_layered_clear_vertex_shader(struct pipe_context *pipe)
    110 {
    111    static const char text[] =
    112          "VERT\n"
    113          "DCL IN[0]\n"
    114          "DCL IN[1]\n"
    115          "DCL SV[0], INSTANCEID\n"
    116          "DCL OUT[0], POSITION\n"
    117          "DCL OUT[1], GENERIC[0]\n"
    118          "DCL OUT[2], LAYER\n"
    119 
    120          "MOV OUT[0], IN[0]\n"
    121          "MOV OUT[1], IN[1]\n"
    122          "MOV OUT[2], SV[0]\n"
    123          "END\n";
    124    struct tgsi_token tokens[1000];
    125    struct pipe_shader_state state;
    126 
    127    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
    128       assert(0);
    129       return NULL;
    130    }
    131    pipe_shader_state_from_tgsi(&state, tokens);
    132    return pipe->create_vs_state(pipe, &state);
    133 }
    134 
    135 /**
    136  * Takes position and color, and outputs position, color, and instance id.
    137  */
    138 void *util_make_layered_clear_helper_vertex_shader(struct pipe_context *pipe)
    139 {
    140    static const char text[] =
    141          "VERT\n"
    142          "DCL IN[0]\n"
    143          "DCL IN[1]\n"
    144          "DCL SV[0], INSTANCEID\n"
    145          "DCL OUT[0], POSITION\n"
    146          "DCL OUT[1], GENERIC[0]\n"
    147          "DCL OUT[2], GENERIC[1]\n"
    148 
    149          "MOV OUT[0], IN[0]\n"
    150          "MOV OUT[1], IN[1]\n"
    151          "MOV OUT[2].x, SV[0].xxxx\n"
    152          "END\n";
    153    struct tgsi_token tokens[1000];
    154    struct pipe_shader_state state;
    155 
    156    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
    157       assert(0);
    158       return NULL;
    159    }
    160    pipe_shader_state_from_tgsi(&state, tokens);
    161    return pipe->create_vs_state(pipe, &state);
    162 }
    163 
    164 /**
    165  * Takes position, color, and target layer, and emits vertices on that target
    166  * layer, with the specified color.
    167  */
    168 void *util_make_layered_clear_geometry_shader(struct pipe_context *pipe)
    169 {
    170    static const char text[] =
    171       "GEOM\n"
    172       "PROPERTY GS_INPUT_PRIMITIVE TRIANGLES\n"
    173       "PROPERTY GS_OUTPUT_PRIMITIVE TRIANGLE_STRIP\n"
    174       "PROPERTY GS_MAX_OUTPUT_VERTICES 3\n"
    175       "PROPERTY GS_INVOCATIONS 1\n"
    176       "DCL IN[][0], POSITION\n" /* position */
    177       "DCL IN[][1], GENERIC[0]\n" /* color */
    178       "DCL IN[][2], GENERIC[1]\n" /* vs invocation */
    179       "DCL OUT[0], POSITION\n"
    180       "DCL OUT[1], GENERIC[0]\n"
    181       "DCL OUT[2], LAYER\n"
    182       "IMM[0] INT32 {0, 0, 0, 0}\n"
    183 
    184       "MOV OUT[0], IN[0][0]\n"
    185       "MOV OUT[1], IN[0][1]\n"
    186       "MOV OUT[2].x, IN[0][2].xxxx\n"
    187       "EMIT IMM[0].xxxx\n"
    188       "MOV OUT[0], IN[1][0]\n"
    189       "MOV OUT[1], IN[1][1]\n"
    190       "MOV OUT[2].x, IN[1][2].xxxx\n"
    191       "EMIT IMM[0].xxxx\n"
    192       "MOV OUT[0], IN[2][0]\n"
    193       "MOV OUT[1], IN[2][1]\n"
    194       "MOV OUT[2].x, IN[2][2].xxxx\n"
    195       "EMIT IMM[0].xxxx\n"
    196       "END\n";
    197    struct tgsi_token tokens[1000];
    198    struct pipe_shader_state state;
    199 
    200    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
    201       assert(0);
    202       return NULL;
    203    }
    204    pipe_shader_state_from_tgsi(&state, tokens);
    205    return pipe->create_gs_state(pipe, &state);
    206 }
    207 
    208 /**
    209  * Make simple fragment texture shader:
    210  *  IMM {0,0,0,1}                         // (if writemask != 0xf)
    211  *  MOV TEMP[0], IMM[0]                   // (if writemask != 0xf)
    212  *  TEX TEMP[0].writemask, IN[0], SAMP[0], 2D;
    213  *   .. optional SINT <-> UINT clamping ..
    214  *  MOV OUT[0], TEMP[0]
    215  *  END;
    216  *
    217  * \param tex_target  one of PIPE_TEXTURE_x
    218  * \parma interp_mode  either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE
    219  * \param writemask  mask of TGSI_WRITEMASK_x
    220  */
    221 void *
    222 util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
    223                                         unsigned tex_target,
    224                                         unsigned interp_mode,
    225                                         unsigned writemask,
    226                                         enum tgsi_return_type stype,
    227                                         enum tgsi_return_type dtype)
    228 {
    229    struct ureg_program *ureg;
    230    struct ureg_src sampler;
    231    struct ureg_src tex;
    232    struct ureg_dst temp;
    233    struct ureg_dst out;
    234 
    235    assert((stype == TGSI_RETURN_TYPE_FLOAT) == (dtype == TGSI_RETURN_TYPE_FLOAT));
    236    assert(interp_mode == TGSI_INTERPOLATE_LINEAR ||
    237           interp_mode == TGSI_INTERPOLATE_PERSPECTIVE);
    238 
    239    ureg = ureg_create( PIPE_SHADER_FRAGMENT );
    240    if (!ureg)
    241       return NULL;
    242 
    243    sampler = ureg_DECL_sampler( ureg, 0 );
    244 
    245    ureg_DECL_sampler_view(ureg, 0, tex_target, stype, stype, stype, stype);
    246 
    247    tex = ureg_DECL_fs_input( ureg,
    248                              TGSI_SEMANTIC_GENERIC, 0,
    249                              interp_mode );
    250 
    251    out = ureg_DECL_output( ureg,
    252                            TGSI_SEMANTIC_COLOR,
    253                            0 );
    254 
    255    temp = ureg_DECL_temporary(ureg);
    256 
    257    if (writemask != TGSI_WRITEMASK_XYZW) {
    258       struct ureg_src imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
    259 
    260       ureg_MOV( ureg, out, imm );
    261    }
    262 
    263    if (tex_target == TGSI_TEXTURE_BUFFER)
    264       ureg_TXF(ureg,
    265                ureg_writemask(temp, writemask),
    266                tex_target, tex, sampler);
    267    else
    268       ureg_TEX(ureg,
    269                ureg_writemask(temp, writemask),
    270                tex_target, tex, sampler);
    271 
    272    if (stype != dtype) {
    273       if (stype == TGSI_RETURN_TYPE_SINT) {
    274          assert(dtype == TGSI_RETURN_TYPE_UINT);
    275 
    276          ureg_IMAX(ureg, temp, ureg_src(temp), ureg_imm1i(ureg, 0));
    277       } else {
    278          assert(stype == TGSI_RETURN_TYPE_UINT);
    279          assert(dtype == TGSI_RETURN_TYPE_SINT);
    280 
    281          ureg_UMIN(ureg, temp, ureg_src(temp), ureg_imm1u(ureg, (1u << 31) - 1));
    282       }
    283    }
    284 
    285    ureg_MOV(ureg, out, ureg_src(temp));
    286 
    287    ureg_END( ureg );
    288 
    289    return ureg_create_shader_and_destroy( ureg, pipe );
    290 }
    291 
    292 
    293 /**
    294  * Make a simple fragment shader that sets the output color to a color
    295  * taken from a texture.
    296  * \param tex_target  one of PIPE_TEXTURE_x
    297  */
    298 void *
    299 util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target,
    300                               unsigned interp_mode,
    301                               enum tgsi_return_type stype,
    302                               enum tgsi_return_type dtype)
    303 {
    304    return util_make_fragment_tex_shader_writemask( pipe,
    305                                                    tex_target,
    306                                                    interp_mode,
    307                                                    TGSI_WRITEMASK_XYZW,
    308                                                    stype, dtype );
    309 }
    310 
    311 
    312 /**
    313  * Make a simple fragment texture shader which reads an X component from
    314  * a texture and writes it as depth.
    315  */
    316 void *
    317 util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
    318                                          unsigned tex_target,
    319                                          unsigned interp_mode)
    320 {
    321    struct ureg_program *ureg;
    322    struct ureg_src sampler;
    323    struct ureg_src tex;
    324    struct ureg_dst out, depth;
    325    struct ureg_src imm;
    326 
    327    ureg = ureg_create( PIPE_SHADER_FRAGMENT );
    328    if (!ureg)
    329       return NULL;
    330 
    331    sampler = ureg_DECL_sampler( ureg, 0 );
    332 
    333    ureg_DECL_sampler_view(ureg, 0, tex_target,
    334                           TGSI_RETURN_TYPE_FLOAT,
    335                           TGSI_RETURN_TYPE_FLOAT,
    336                           TGSI_RETURN_TYPE_FLOAT,
    337                           TGSI_RETURN_TYPE_FLOAT);
    338 
    339    tex = ureg_DECL_fs_input( ureg,
    340                              TGSI_SEMANTIC_GENERIC, 0,
    341                              interp_mode );
    342 
    343    out = ureg_DECL_output( ureg,
    344                            TGSI_SEMANTIC_COLOR,
    345                            0 );
    346 
    347    depth = ureg_DECL_output( ureg,
    348                              TGSI_SEMANTIC_POSITION,
    349                              0 );
    350 
    351    imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
    352 
    353    ureg_MOV( ureg, out, imm );
    354 
    355    ureg_TEX( ureg,
    356              ureg_writemask(depth, TGSI_WRITEMASK_Z),
    357              tex_target, tex, sampler );
    358    ureg_END( ureg );
    359 
    360    return ureg_create_shader_and_destroy( ureg, pipe );
    361 }
    362 
    363 
    364 /**
    365  * Make a simple fragment texture shader which reads the texture unit 0 and 1
    366  * and writes it as depth and stencil, respectively.
    367  */
    368 void *
    369 util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe,
    370                                                 unsigned tex_target,
    371                                                 unsigned interp_mode)
    372 {
    373    struct ureg_program *ureg;
    374    struct ureg_src depth_sampler, stencil_sampler;
    375    struct ureg_src tex;
    376    struct ureg_dst out, depth, stencil;
    377    struct ureg_src imm;
    378 
    379    ureg = ureg_create( PIPE_SHADER_FRAGMENT );
    380    if (!ureg)
    381       return NULL;
    382 
    383    depth_sampler = ureg_DECL_sampler( ureg, 0 );
    384    ureg_DECL_sampler_view(ureg, 0, tex_target,
    385                           TGSI_RETURN_TYPE_FLOAT,
    386                           TGSI_RETURN_TYPE_FLOAT,
    387                           TGSI_RETURN_TYPE_FLOAT,
    388                           TGSI_RETURN_TYPE_FLOAT);
    389    stencil_sampler = ureg_DECL_sampler( ureg, 1 );
    390    ureg_DECL_sampler_view(ureg, 0, tex_target,
    391                           TGSI_RETURN_TYPE_UINT,
    392                           TGSI_RETURN_TYPE_UINT,
    393                           TGSI_RETURN_TYPE_UINT,
    394                           TGSI_RETURN_TYPE_UINT);
    395 
    396    tex = ureg_DECL_fs_input( ureg,
    397                              TGSI_SEMANTIC_GENERIC, 0,
    398                              interp_mode );
    399 
    400    out = ureg_DECL_output( ureg,
    401                            TGSI_SEMANTIC_COLOR,
    402                            0 );
    403 
    404    depth = ureg_DECL_output( ureg,
    405                              TGSI_SEMANTIC_POSITION,
    406                              0 );
    407 
    408    stencil = ureg_DECL_output( ureg,
    409                              TGSI_SEMANTIC_STENCIL,
    410                              0 );
    411 
    412    imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
    413 
    414    ureg_MOV( ureg, out, imm );
    415 
    416    ureg_TEX( ureg,
    417              ureg_writemask(depth, TGSI_WRITEMASK_Z),
    418              tex_target, tex, depth_sampler );
    419    ureg_TEX( ureg,
    420              ureg_writemask(stencil, TGSI_WRITEMASK_Y),
    421              tex_target, tex, stencil_sampler );
    422    ureg_END( ureg );
    423 
    424    return ureg_create_shader_and_destroy( ureg, pipe );
    425 }
    426 
    427 
    428 /**
    429  * Make a simple fragment texture shader which reads a texture and writes it
    430  * as stencil.
    431  */
    432 void *
    433 util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe,
    434                                            unsigned tex_target,
    435                                            unsigned interp_mode)
    436 {
    437    struct ureg_program *ureg;
    438    struct ureg_src stencil_sampler;
    439    struct ureg_src tex;
    440    struct ureg_dst out, stencil;
    441    struct ureg_src imm;
    442 
    443    ureg = ureg_create( PIPE_SHADER_FRAGMENT );
    444    if (!ureg)
    445       return NULL;
    446 
    447    stencil_sampler = ureg_DECL_sampler( ureg, 0 );
    448 
    449    ureg_DECL_sampler_view(ureg, 0, tex_target,
    450                           TGSI_RETURN_TYPE_UINT,
    451                           TGSI_RETURN_TYPE_UINT,
    452                           TGSI_RETURN_TYPE_UINT,
    453                           TGSI_RETURN_TYPE_UINT);
    454 
    455    tex = ureg_DECL_fs_input( ureg,
    456                              TGSI_SEMANTIC_GENERIC, 0,
    457                              interp_mode );
    458 
    459    out = ureg_DECL_output( ureg,
    460                            TGSI_SEMANTIC_COLOR,
    461                            0 );
    462 
    463    stencil = ureg_DECL_output( ureg,
    464                              TGSI_SEMANTIC_STENCIL,
    465                              0 );
    466 
    467    imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
    468 
    469    ureg_MOV( ureg, out, imm );
    470 
    471    ureg_TEX( ureg,
    472              ureg_writemask(stencil, TGSI_WRITEMASK_Y),
    473              tex_target, tex, stencil_sampler );
    474    ureg_END( ureg );
    475 
    476    return ureg_create_shader_and_destroy( ureg, pipe );
    477 }
    478 
    479 
    480 /**
    481  * Make simple fragment color pass-through shader that replicates OUT[0]
    482  * to all bound colorbuffers.
    483  */
    484 void *
    485 util_make_fragment_passthrough_shader(struct pipe_context *pipe,
    486                                       int input_semantic,
    487                                       int input_interpolate,
    488                                       boolean write_all_cbufs)
    489 {
    490    static const char shader_templ[] =
    491          "FRAG\n"
    492          "%s"
    493          "DCL IN[0], %s[0], %s\n"
    494          "DCL OUT[0], COLOR[0]\n"
    495 
    496          "MOV OUT[0], IN[0]\n"
    497          "END\n";
    498 
    499    char text[sizeof(shader_templ)+100];
    500    struct tgsi_token tokens[1000];
    501    struct pipe_shader_state state;
    502 
    503    sprintf(text, shader_templ,
    504            write_all_cbufs ? "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" : "",
    505            tgsi_semantic_names[input_semantic],
    506            tgsi_interpolate_names[input_interpolate]);
    507 
    508    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
    509       assert(0);
    510       return NULL;
    511    }
    512    pipe_shader_state_from_tgsi(&state, tokens);
    513 #if 0
    514    tgsi_dump(state.tokens, 0);
    515 #endif
    516 
    517    return pipe->create_fs_state(pipe, &state);
    518 }
    519 
    520 
    521 void *
    522 util_make_empty_fragment_shader(struct pipe_context *pipe)
    523 {
    524    struct ureg_program *ureg = ureg_create(PIPE_SHADER_FRAGMENT);
    525    if (!ureg)
    526       return NULL;
    527 
    528    ureg_END(ureg);
    529    return ureg_create_shader_and_destroy(ureg, pipe);
    530 }
    531 
    532 
    533 /**
    534  * Make a fragment shader that copies the input color to N output colors.
    535  */
    536 void *
    537 util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs,
    538                                      int input_semantic,
    539                                      int input_interpolate)
    540 {
    541    struct ureg_program *ureg;
    542    struct ureg_src src;
    543    struct ureg_dst dst[PIPE_MAX_COLOR_BUFS];
    544    int i;
    545 
    546    assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
    547 
    548    ureg = ureg_create( PIPE_SHADER_FRAGMENT );
    549    if (!ureg)
    550       return NULL;
    551 
    552    src = ureg_DECL_fs_input( ureg, input_semantic, 0,
    553                              input_interpolate );
    554 
    555    for (i = 0; i < num_cbufs; i++)
    556       dst[i] = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, i );
    557 
    558    for (i = 0; i < num_cbufs; i++)
    559       ureg_MOV( ureg, dst[i], src );
    560 
    561    ureg_END( ureg );
    562 
    563    return ureg_create_shader_and_destroy( ureg, pipe );
    564 }
    565 
    566 
    567 static void *
    568 util_make_fs_blit_msaa_gen(struct pipe_context *pipe,
    569                            unsigned tgsi_tex,
    570                            const char *samp_type,
    571                            const char *output_semantic,
    572                            const char *output_mask,
    573                            const char *conversion_decl,
    574                            const char *conversion)
    575 {
    576    static const char shader_templ[] =
    577          "FRAG\n"
    578          "DCL IN[0], GENERIC[0], LINEAR\n"
    579          "DCL SAMP[0]\n"
    580          "DCL SVIEW[0], %s, %s\n"
    581          "DCL OUT[0], %s\n"
    582          "DCL TEMP[0]\n"
    583          "%s"
    584 
    585          "F2U TEMP[0], IN[0]\n"
    586          "TXF TEMP[0], TEMP[0], SAMP[0], %s\n"
    587          "%s"
    588          "MOV OUT[0]%s, TEMP[0]\n"
    589          "END\n";
    590 
    591    const char *type = tgsi_texture_names[tgsi_tex];
    592    char text[sizeof(shader_templ)+100];
    593    struct tgsi_token tokens[1000];
    594    struct pipe_shader_state state;
    595 
    596    assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
    597           tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
    598 
    599    util_snprintf(text, sizeof(text), shader_templ, type, samp_type,
    600                  output_semantic, conversion_decl, type, conversion, output_mask);
    601 
    602    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
    603       puts(text);
    604       assert(0);
    605       return NULL;
    606    }
    607    pipe_shader_state_from_tgsi(&state, tokens);
    608 #if 0
    609    tgsi_dump(state.tokens, 0);
    610 #endif
    611 
    612    return pipe->create_fs_state(pipe, &state);
    613 }
    614 
    615 
    616 /**
    617  * Make a fragment shader that sets the output color to a color
    618  * fetched from a multisample texture.
    619  * \param tex_target  one of PIPE_TEXTURE_x
    620  */
    621 void *
    622 util_make_fs_blit_msaa_color(struct pipe_context *pipe,
    623                              unsigned tgsi_tex,
    624                              enum tgsi_return_type stype,
    625                              enum tgsi_return_type dtype)
    626 {
    627    const char *samp_type;
    628    const char *conversion_decl = "";
    629    const char *conversion = "";
    630 
    631    if (stype == TGSI_RETURN_TYPE_UINT) {
    632       samp_type = "UINT";
    633 
    634       if (dtype == TGSI_RETURN_TYPE_SINT) {
    635          conversion_decl = "IMM[0] UINT32 {2147483647, 0, 0, 0}\n";
    636          conversion = "UMIN TEMP[0], TEMP[0], IMM[0].xxxx\n";
    637       }
    638    } else if (stype == TGSI_RETURN_TYPE_SINT) {
    639       samp_type = "SINT";
    640 
    641       if (dtype == TGSI_RETURN_TYPE_UINT) {
    642          conversion_decl = "IMM[0] INT32 {0, 0, 0, 0}\n";
    643          conversion = "IMAX TEMP[0], TEMP[0], IMM[0].xxxx\n";
    644       }
    645    } else {
    646       assert(dtype == TGSI_RETURN_TYPE_FLOAT);
    647       samp_type = "FLOAT";
    648    }
    649 
    650    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, samp_type,
    651                                      "COLOR[0]", "", conversion_decl,
    652                                      conversion);
    653 }
    654 
    655 
    656 /**
    657  * Make a fragment shader that sets the output depth to a depth value
    658  * fetched from a multisample texture.
    659  * \param tex_target  one of PIPE_TEXTURE_x
    660  */
    661 void *
    662 util_make_fs_blit_msaa_depth(struct pipe_context *pipe,
    663                              unsigned tgsi_tex)
    664 {
    665    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, "FLOAT",
    666                                      "POSITION", ".z", "", "");
    667 }
    668 
    669 
    670 /**
    671  * Make a fragment shader that sets the output stencil to a stencil value
    672  * fetched from a multisample texture.
    673  * \param tex_target  one of PIPE_TEXTURE_x
    674  */
    675 void *
    676 util_make_fs_blit_msaa_stencil(struct pipe_context *pipe,
    677                                unsigned tgsi_tex)
    678 {
    679    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, "UINT",
    680                                      "STENCIL", ".y", "", "");
    681 }
    682 
    683 
    684 /**
    685  * Make a fragment shader that sets the output depth and stencil to depth
    686  * and stencil values fetched from two multisample textures / samplers.
    687  * The sizes of both textures should match (it should be one depth-stencil
    688  * texture).
    689  * \param tex_target  one of PIPE_TEXTURE_x
    690  */
    691 void *
    692 util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe,
    693                                     unsigned tgsi_tex)
    694 {
    695    static const char shader_templ[] =
    696          "FRAG\n"
    697          "DCL IN[0], GENERIC[0], LINEAR\n"
    698          "DCL SAMP[0..1]\n"
    699          "DCL SVIEW[0..1], %s, FLOAT\n"
    700          "DCL OUT[0], POSITION\n"
    701          "DCL OUT[1], STENCIL\n"
    702          "DCL TEMP[0]\n"
    703 
    704          "F2U TEMP[0], IN[0]\n"
    705          "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
    706          "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
    707          "END\n";
    708 
    709    const char *type = tgsi_texture_names[tgsi_tex];
    710    char text[sizeof(shader_templ)+100];
    711    struct tgsi_token tokens[1000];
    712    struct pipe_shader_state state;
    713 
    714    assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
    715           tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
    716 
    717    sprintf(text, shader_templ, type, type, type);
    718 
    719    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
    720       assert(0);
    721       return NULL;
    722    }
    723    pipe_shader_state_from_tgsi(&state, tokens);
    724 #if 0
    725    tgsi_dump(state.tokens, 0);
    726 #endif
    727 
    728    return pipe->create_fs_state(pipe, &state);
    729 }
    730 
    731 
    732 void *
    733 util_make_fs_msaa_resolve(struct pipe_context *pipe,
    734                           unsigned tgsi_tex, unsigned nr_samples,
    735                           enum tgsi_return_type stype)
    736 {
    737    struct ureg_program *ureg;
    738    struct ureg_src sampler, coord;
    739    struct ureg_dst out, tmp_sum, tmp_coord, tmp;
    740    unsigned i;
    741 
    742    ureg = ureg_create(PIPE_SHADER_FRAGMENT);
    743    if (!ureg)
    744       return NULL;
    745 
    746    /* Declarations. */
    747    sampler = ureg_DECL_sampler(ureg, 0);
    748    ureg_DECL_sampler_view(ureg, 0, tgsi_tex, stype, stype, stype, stype);
    749    coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0,
    750                               TGSI_INTERPOLATE_LINEAR);
    751    out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
    752    tmp_sum = ureg_DECL_temporary(ureg);
    753    tmp_coord = ureg_DECL_temporary(ureg);
    754    tmp = ureg_DECL_temporary(ureg);
    755 
    756    /* Instructions. */
    757    ureg_MOV(ureg, tmp_sum, ureg_imm1f(ureg, 0));
    758    ureg_F2U(ureg, tmp_coord, coord);
    759 
    760    for (i = 0; i < nr_samples; i++) {
    761       /* Read one sample. */
    762       ureg_MOV(ureg, ureg_writemask(tmp_coord, TGSI_WRITEMASK_W),
    763                ureg_imm1u(ureg, i));
    764       ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord), sampler);
    765 
    766       if (stype == TGSI_RETURN_TYPE_UINT)
    767          ureg_U2F(ureg, tmp, ureg_src(tmp));
    768       else if (stype == TGSI_RETURN_TYPE_SINT)
    769          ureg_I2F(ureg, tmp, ureg_src(tmp));
    770 
    771       /* Add it to the sum.*/
    772       ureg_ADD(ureg, tmp_sum, ureg_src(tmp_sum), ureg_src(tmp));
    773    }
    774 
    775    /* Calculate the average and return. */
    776    ureg_MUL(ureg, tmp_sum, ureg_src(tmp_sum),
    777             ureg_imm1f(ureg, 1.0 / nr_samples));
    778 
    779    if (stype == TGSI_RETURN_TYPE_UINT)
    780       ureg_F2U(ureg, out, ureg_src(tmp_sum));
    781    else if (stype == TGSI_RETURN_TYPE_SINT)
    782       ureg_F2I(ureg, out, ureg_src(tmp_sum));
    783    else
    784       ureg_MOV(ureg, out, ureg_src(tmp_sum));
    785 
    786    ureg_END(ureg);
    787 
    788    return ureg_create_shader_and_destroy(ureg, pipe);
    789 }
    790 
    791 
    792 void *
    793 util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe,
    794                                    unsigned tgsi_tex, unsigned nr_samples,
    795                                    enum tgsi_return_type stype)
    796 {
    797    struct ureg_program *ureg;
    798    struct ureg_src sampler, coord;
    799    struct ureg_dst out, tmp, top, bottom;
    800    struct ureg_dst tmp_coord[4], tmp_sum[4];
    801    unsigned i, c;
    802 
    803    ureg = ureg_create(PIPE_SHADER_FRAGMENT);
    804    if (!ureg)
    805       return NULL;
    806 
    807    /* Declarations. */
    808    sampler = ureg_DECL_sampler(ureg, 0);
    809    ureg_DECL_sampler_view(ureg, 0, tgsi_tex, stype, stype, stype, stype);
    810    coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0,
    811                               TGSI_INTERPOLATE_LINEAR);
    812    out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
    813    for (c = 0; c < 4; c++)
    814       tmp_sum[c] = ureg_DECL_temporary(ureg);
    815    for (c = 0; c < 4; c++)
    816       tmp_coord[c] = ureg_DECL_temporary(ureg);
    817    tmp = ureg_DECL_temporary(ureg);
    818    top = ureg_DECL_temporary(ureg);
    819    bottom = ureg_DECL_temporary(ureg);
    820 
    821    /* Instructions. */
    822    for (c = 0; c < 4; c++)
    823       ureg_MOV(ureg, tmp_sum[c], ureg_imm1f(ureg, 0));
    824 
    825    /* Get 4 texture coordinates for the bilinear filter. */
    826    ureg_F2U(ureg, tmp_coord[0], coord); /* top-left */
    827    ureg_UADD(ureg, tmp_coord[1], ureg_src(tmp_coord[0]),
    828              ureg_imm4u(ureg, 1, 0, 0, 0)); /* top-right */
    829    ureg_UADD(ureg, tmp_coord[2], ureg_src(tmp_coord[0]),
    830              ureg_imm4u(ureg, 0, 1, 0, 0)); /* bottom-left */
    831    ureg_UADD(ureg, tmp_coord[3], ureg_src(tmp_coord[0]),
    832              ureg_imm4u(ureg, 1, 1, 0, 0)); /* bottom-right */
    833 
    834    for (i = 0; i < nr_samples; i++) {
    835       for (c = 0; c < 4; c++) {
    836          /* Read one sample. */
    837          ureg_MOV(ureg, ureg_writemask(tmp_coord[c], TGSI_WRITEMASK_W),
    838                   ureg_imm1u(ureg, i));
    839          ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord[c]), sampler);
    840 
    841          if (stype == TGSI_RETURN_TYPE_UINT)
    842             ureg_U2F(ureg, tmp, ureg_src(tmp));
    843          else if (stype == TGSI_RETURN_TYPE_SINT)
    844             ureg_I2F(ureg, tmp, ureg_src(tmp));
    845 
    846          /* Add it to the sum.*/
    847          ureg_ADD(ureg, tmp_sum[c], ureg_src(tmp_sum[c]), ureg_src(tmp));
    848       }
    849    }
    850 
    851    /* Calculate the average. */
    852    for (c = 0; c < 4; c++)
    853       ureg_MUL(ureg, tmp_sum[c], ureg_src(tmp_sum[c]),
    854                ureg_imm1f(ureg, 1.0 / nr_samples));
    855 
    856    /* Take the 4 average values and apply a standard bilinear filter. */
    857    ureg_FRC(ureg, tmp, coord);
    858 
    859    ureg_LRP(ureg, top,
    860             ureg_scalar(ureg_src(tmp), 0),
    861             ureg_src(tmp_sum[1]),
    862             ureg_src(tmp_sum[0]));
    863 
    864    ureg_LRP(ureg, bottom,
    865             ureg_scalar(ureg_src(tmp), 0),
    866             ureg_src(tmp_sum[3]),
    867             ureg_src(tmp_sum[2]));
    868 
    869    ureg_LRP(ureg, tmp,
    870             ureg_scalar(ureg_src(tmp), 1),
    871             ureg_src(bottom),
    872             ureg_src(top));
    873 
    874    /* Convert to the texture format and return. */
    875    if (stype == TGSI_RETURN_TYPE_UINT)
    876       ureg_F2U(ureg, out, ureg_src(tmp));
    877    else if (stype == TGSI_RETURN_TYPE_SINT)
    878       ureg_F2I(ureg, out, ureg_src(tmp));
    879    else
    880       ureg_MOV(ureg, out, ureg_src(tmp));
    881 
    882    ureg_END(ureg);
    883 
    884    return ureg_create_shader_and_destroy(ureg, pipe);
    885 }
    886 
    887 void *
    888 util_make_geometry_passthrough_shader(struct pipe_context *pipe,
    889                                       uint num_attribs,
    890                                       const ubyte *semantic_names,
    891                                       const ubyte *semantic_indexes)
    892 {
    893    static const unsigned zero[4] = {0, 0, 0, 0};
    894 
    895    struct ureg_program *ureg;
    896    struct ureg_dst dst[PIPE_MAX_SHADER_OUTPUTS];
    897    struct ureg_src src[PIPE_MAX_SHADER_INPUTS];
    898    struct ureg_src imm;
    899 
    900    unsigned i;
    901 
    902    ureg = ureg_create(PIPE_SHADER_GEOMETRY);
    903    if (!ureg)
    904       return NULL;
    905 
    906    ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, PIPE_PRIM_POINTS);
    907    ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, PIPE_PRIM_POINTS);
    908    ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, 1);
    909    ureg_property(ureg, TGSI_PROPERTY_GS_INVOCATIONS, 1);
    910    imm = ureg_DECL_immediate_uint(ureg, zero, 4);
    911 
    912    /**
    913     * Loop over all the attribs and declare the corresponding
    914     * declarations in the geometry shader
    915     */
    916    for (i = 0; i < num_attribs; i++) {
    917       src[i] = ureg_DECL_input(ureg, semantic_names[i],
    918                                semantic_indexes[i], 0, 1);
    919       src[i] = ureg_src_dimension(src[i], 0);
    920       dst[i] = ureg_DECL_output(ureg, semantic_names[i], semantic_indexes[i]);
    921    }
    922 
    923    /* MOV dst[i] src[i] */
    924    for (i = 0; i < num_attribs; i++) {
    925       ureg_MOV(ureg, dst[i], src[i]);
    926    }
    927 
    928    /* EMIT IMM[0] */
    929    ureg_insn(ureg, TGSI_OPCODE_EMIT, NULL, 0, &imm, 1);
    930 
    931    /* END */
    932    ureg_END(ureg);
    933 
    934    return ureg_create_shader_and_destroy(ureg, pipe);
    935 }
    936 
    937