Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * All Rights Reserved.
  5.  * Copyright 2009 Marek Olšák <maraeo@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 Olšák
  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 that replicates OUT[0]
  320.  * to all bound colorbuffers.
  321.  */
  322. void *
  323. util_make_fragment_passthrough_shader(struct pipe_context *pipe,
  324.                                       int input_semantic,
  325.                                       int input_interpolate,
  326.                                       boolean write_all_cbufs)
  327. {
  328.    static const char shader_templ[] =
  329.          "FRAG\n"
  330.          "%s"
  331.          "DCL IN[0], %s[0], %s\n"
  332.          "DCL OUT[0], COLOR[0]\n"
  333.  
  334.          "MOV OUT[0], IN[0]\n"
  335.          "END\n";
  336.  
  337.    char text[sizeof(shader_templ)+100];
  338.    struct tgsi_token tokens[1000];
  339.    struct pipe_shader_state state = {tokens};
  340.  
  341.    sprintf(text, shader_templ,
  342.            write_all_cbufs ? "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" : "",
  343.            tgsi_semantic_names[input_semantic],
  344.            tgsi_interpolate_names[input_interpolate]);
  345.  
  346.    if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
  347.       assert(0);
  348.       return NULL;
  349.    }
  350. #if 0
  351.    tgsi_dump(state.tokens, 0);
  352. #endif
  353.  
  354.    return pipe->create_fs_state(pipe, &state);
  355. }
  356.  
  357.  
  358. void *
  359. util_make_empty_fragment_shader(struct pipe_context *pipe)
  360. {
  361.    struct ureg_program *ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
  362.    if (ureg == NULL)
  363.       return NULL;
  364.  
  365.    ureg_END(ureg);
  366.    return ureg_create_shader_and_destroy(ureg, pipe);
  367. }
  368.  
  369.  
  370. /**
  371.  * Make a fragment shader that copies the input color to N output colors.
  372.  */
  373. void *
  374. util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs,
  375.                                      int input_semantic,
  376.                                      int input_interpolate)
  377. {
  378.    struct ureg_program *ureg;
  379.    struct ureg_src src;
  380.    struct ureg_dst dst[PIPE_MAX_COLOR_BUFS];
  381.    int i;
  382.  
  383.    assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
  384.  
  385.    ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
  386.    if (ureg == NULL)
  387.       return NULL;
  388.  
  389.    src = ureg_DECL_fs_input( ureg, input_semantic, 0,
  390.                              input_interpolate );
  391.  
  392.    for (i = 0; i < num_cbufs; i++)
  393.       dst[i] = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, i );
  394.  
  395.    for (i = 0; i < num_cbufs; i++)
  396.       ureg_MOV( ureg, dst[i], src );
  397.  
  398.    ureg_END( ureg );
  399.  
  400.    return ureg_create_shader_and_destroy( ureg, pipe );
  401. }
  402.  
  403.  
  404. static void *
  405. util_make_fs_blit_msaa_gen(struct pipe_context *pipe,
  406.                            unsigned tgsi_tex,
  407.                            const char *output_semantic,
  408.                            const char *output_mask)
  409. {
  410.    static const char shader_templ[] =
  411.          "FRAG\n"
  412.          "DCL IN[0], GENERIC[0], LINEAR\n"
  413.          "DCL SAMP[0]\n"
  414.          "DCL OUT[0], %s\n"
  415.          "DCL TEMP[0]\n"
  416.  
  417.          "F2U TEMP[0], IN[0]\n"
  418.          "TXF OUT[0]%s, TEMP[0], SAMP[0], %s\n"
  419.          "END\n";
  420.  
  421.    const char *type = tgsi_texture_names[tgsi_tex];
  422.    char text[sizeof(shader_templ)+100];
  423.    struct tgsi_token tokens[1000];
  424.    struct pipe_shader_state state = {tokens};
  425.  
  426.    assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
  427.           tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
  428.  
  429.    sprintf(text, shader_templ, output_semantic, output_mask, type);
  430.  
  431.    if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
  432.       puts(text);
  433.       assert(0);
  434.       return NULL;
  435.    }
  436. #if 0
  437.    tgsi_dump(state.tokens, 0);
  438. #endif
  439.  
  440.    return pipe->create_fs_state(pipe, &state);
  441. }
  442.  
  443.  
  444. /**
  445.  * Make a fragment shader that sets the output color to a color
  446.  * fetched from a multisample texture.
  447.  * \param tex_target  one of PIPE_TEXTURE_x
  448.  */
  449. void *
  450. util_make_fs_blit_msaa_color(struct pipe_context *pipe,
  451.                              unsigned tgsi_tex)
  452. {
  453.    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex,
  454.                                      "COLOR[0]", "");
  455. }
  456.  
  457.  
  458. /**
  459.  * Make a fragment shader that sets the output depth to a depth value
  460.  * fetched from a multisample texture.
  461.  * \param tex_target  one of PIPE_TEXTURE_x
  462.  */
  463. void *
  464. util_make_fs_blit_msaa_depth(struct pipe_context *pipe,
  465.                              unsigned tgsi_tex)
  466. {
  467.    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex,
  468.                                      "POSITION", ".z");
  469. }
  470.  
  471.  
  472. /**
  473.  * Make a fragment shader that sets the output stencil to a stencil value
  474.  * fetched from a multisample texture.
  475.  * \param tex_target  one of PIPE_TEXTURE_x
  476.  */
  477. void *
  478. util_make_fs_blit_msaa_stencil(struct pipe_context *pipe,
  479.                                unsigned tgsi_tex)
  480. {
  481.    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex,
  482.                                      "STENCIL", ".y");
  483. }
  484.  
  485.  
  486. /**
  487.  * Make a fragment shader that sets the output depth and stencil to depth
  488.  * and stencil values fetched from two multisample textures / samplers.
  489.  * The sizes of both textures should match (it should be one depth-stencil
  490.  * texture).
  491.  * \param tex_target  one of PIPE_TEXTURE_x
  492.  */
  493. void *
  494. util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe,
  495.                                     unsigned tgsi_tex)
  496. {
  497.    static const char shader_templ[] =
  498.          "FRAG\n"
  499.          "DCL IN[0], GENERIC[0], LINEAR\n"
  500.          "DCL SAMP[0..1]\n"
  501.          "DCL OUT[0], POSITION\n"
  502.          "DCL OUT[1], STENCIL\n"
  503.          "DCL TEMP[0]\n"
  504.  
  505.          "F2U TEMP[0], IN[0]\n"
  506.          "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
  507.          "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
  508.          "END\n";
  509.  
  510.    const char *type = tgsi_texture_names[tgsi_tex];
  511.    char text[sizeof(shader_templ)+100];
  512.    struct tgsi_token tokens[1000];
  513.    struct pipe_shader_state state = {tokens};
  514.  
  515.    assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
  516.           tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
  517.  
  518.    sprintf(text, shader_templ, type, type);
  519.  
  520.    if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
  521.       assert(0);
  522.       return NULL;
  523.    }
  524. #if 0
  525.    tgsi_dump(state.tokens, 0);
  526. #endif
  527.  
  528.    return pipe->create_fs_state(pipe, &state);
  529. }
  530.