Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
  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 TUNGSTEN GRAPHICS 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 "util/u_math.h"
  29. #include "util/u_memory.h"
  30. #include "util/u_prim.h"
  31. #include "draw/draw_context.h"
  32. #include "draw/draw_vbuf.h"
  33. #include "draw/draw_vertex.h"
  34. #include "draw/draw_prim_assembler.h"
  35. #include "draw/draw_pt.h"
  36. #include "draw/draw_vs.h"
  37. #include "draw/draw_gs.h"
  38.  
  39.  
  40. struct fetch_pipeline_middle_end {
  41.    struct draw_pt_middle_end base;
  42.    struct draw_context *draw;
  43.  
  44.    struct pt_emit *emit;
  45.    struct pt_so_emit *so_emit;
  46.    struct pt_fetch *fetch;
  47.    struct pt_post_vs *post_vs;
  48.  
  49.    unsigned vertex_data_offset;
  50.    unsigned vertex_size;
  51.    unsigned input_prim;
  52.    unsigned opt;
  53. };
  54.  
  55.  
  56. /**
  57.  * Prepare/validate middle part of the vertex pipeline.
  58.  * NOTE: if you change this function, also look at the LLVM
  59.  * function llvm_middle_end_prepare() for similar changes.
  60.  */
  61. static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
  62.                                     unsigned prim,
  63.                                     unsigned opt,
  64.                                     unsigned *max_vertices )
  65. {
  66.    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
  67.    struct draw_context *draw = fpme->draw;
  68.    struct draw_vertex_shader *vs = draw->vs.vertex_shader;
  69.    struct draw_geometry_shader *gs = draw->gs.geometry_shader;
  70.    unsigned i;
  71.    unsigned instance_id_index = ~0;
  72.  
  73.    const unsigned gs_out_prim = (gs ? gs->output_primitive :
  74.                                  u_assembled_prim(prim));
  75.  
  76.    /* Add one to num_outputs because the pipeline occasionally tags on
  77.     * an additional texcoord, eg for AA lines.
  78.     */
  79.    unsigned nr = MAX2( vs->info.num_inputs,
  80.                        vs->info.num_outputs + 1 );
  81.  
  82.    if (gs) {
  83.       nr = MAX2(nr, gs->info.num_outputs + 1);
  84.    }
  85.  
  86.    /* Scan for instanceID system value.
  87.     */
  88.    for (i = 0; i < vs->info.num_inputs; i++) {
  89.       if (vs->info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
  90.          instance_id_index = i;
  91.          break;
  92.       }
  93.    }
  94.  
  95.    fpme->input_prim = prim;
  96.    fpme->opt = opt;
  97.  
  98.    /* Always leave room for the vertex header whether we need it or
  99.     * not.  It's hard to get rid of it in particular because of the
  100.     * viewport code in draw_pt_post_vs.c.  
  101.     */
  102.    fpme->vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float);
  103.  
  104.    
  105.  
  106.    draw_pt_fetch_prepare( fpme->fetch,
  107.                           vs->info.num_inputs,
  108.                           fpme->vertex_size,
  109.                           instance_id_index );
  110.    draw_pt_post_vs_prepare( fpme->post_vs,
  111.                             draw->clip_xy,
  112.                             draw->clip_z,
  113.                             draw->clip_user,
  114.                             draw->guard_band_xy,
  115.                             draw->identity_viewport,
  116.                             draw->rasterizer->clip_halfz,
  117.                             (draw->vs.edgeflag_output ? TRUE : FALSE) );
  118.  
  119.    draw_pt_so_emit_prepare( fpme->so_emit, FALSE );
  120.  
  121.    if (!(opt & PT_PIPELINE)) {
  122.       draw_pt_emit_prepare( fpme->emit,
  123.                             gs_out_prim,
  124.                             max_vertices );
  125.  
  126.       *max_vertices = MAX2( *max_vertices, 4096 );
  127.    }
  128.    else {
  129.       /* limit max fetches by limiting max_vertices */
  130.       *max_vertices = 4096;
  131.    }
  132.  
  133.    /* No need to prepare the shader.
  134.     */
  135.    vs->prepare(vs, draw);
  136. }
  137.  
  138.  
  139. static void
  140. fetch_pipeline_bind_parameters(struct draw_pt_middle_end *middle)
  141. {
  142.    /* No-op since the vertex shader executor and drawing pipeline
  143.     * just grab the constants, viewport, etc. from the draw context state.
  144.     */
  145. }
  146.  
  147.  
  148. static void fetch( struct pt_fetch *fetch,
  149.                    const struct draw_fetch_info *fetch_info,
  150.                    char *output)
  151. {
  152.    if (fetch_info->linear) {
  153.       draw_pt_fetch_run_linear( fetch,
  154.                                 fetch_info->start,
  155.                                 fetch_info->count,
  156.                                 output );
  157.    }
  158.    else {
  159.       draw_pt_fetch_run( fetch,
  160.                          fetch_info->elts,
  161.                          fetch_info->count,
  162.                          output );
  163.    }
  164. }
  165.  
  166.  
  167. static void pipeline(struct fetch_pipeline_middle_end *fpme,
  168.                      const struct draw_vertex_info *vert_info,
  169.                      const struct draw_prim_info *prim_info)
  170. {
  171.    if (prim_info->linear)
  172.       draw_pipeline_run_linear( fpme->draw,
  173.                                 vert_info,
  174.                                 prim_info);
  175.    else
  176.       draw_pipeline_run( fpme->draw,
  177.                          vert_info,
  178.                          prim_info );
  179. }
  180.  
  181. static void emit(struct pt_emit *emit,
  182.                  const struct draw_vertex_info *vert_info,
  183.                  const struct draw_prim_info *prim_info)
  184. {
  185.    if (prim_info->linear) {
  186.       draw_pt_emit_linear(emit, vert_info, prim_info);
  187.    }
  188.    else {
  189.       draw_pt_emit(emit, vert_info, prim_info);
  190.    }
  191. }
  192.  
  193.  
  194. static void draw_vertex_shader_run(struct draw_vertex_shader *vshader,
  195.                                    const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
  196.                                    unsigned const_size[PIPE_MAX_CONSTANT_BUFFERS],
  197.                                    const struct draw_vertex_info *input_verts,
  198.                                    struct draw_vertex_info *output_verts )
  199. {
  200.    output_verts->vertex_size = input_verts->vertex_size;
  201.    output_verts->stride = input_verts->vertex_size;
  202.    output_verts->count = input_verts->count;
  203.    output_verts->verts =
  204.       (struct vertex_header *)MALLOC(output_verts->vertex_size *
  205.                                      align(output_verts->count, 4));
  206.  
  207.    vshader->run_linear(vshader,
  208.                        (const float (*)[4])input_verts->verts->data,
  209.                        (      float (*)[4])output_verts->verts->data,
  210.                        constants,
  211.                        const_size,
  212.                        input_verts->count,
  213.                        input_verts->vertex_size,
  214.                        input_verts->vertex_size);
  215. }
  216.  
  217. static void fetch_pipeline_generic( struct draw_pt_middle_end *middle,
  218.                                     const struct draw_fetch_info *fetch_info,
  219.                                     const struct draw_prim_info *in_prim_info )
  220. {
  221.    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
  222.    struct draw_context *draw = fpme->draw;
  223.    struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
  224.    struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
  225.    struct draw_prim_info gs_prim_info;
  226.    struct draw_vertex_info fetched_vert_info;
  227.    struct draw_vertex_info vs_vert_info;
  228.    struct draw_vertex_info gs_vert_info;
  229.    struct draw_vertex_info *vert_info;
  230.    struct draw_prim_info ia_prim_info;
  231.    struct draw_vertex_info ia_vert_info;
  232.    const struct draw_prim_info *prim_info = in_prim_info;
  233.    boolean free_prim_info = FALSE;
  234.    unsigned opt = fpme->opt;
  235.  
  236.    fetched_vert_info.count = fetch_info->count;
  237.    fetched_vert_info.vertex_size = fpme->vertex_size;
  238.    fetched_vert_info.stride = fpme->vertex_size;
  239.    fetched_vert_info.verts =
  240.       (struct vertex_header *)MALLOC(fpme->vertex_size *
  241.                                      align(fetch_info->count,  4));
  242.    if (!fetched_vert_info.verts) {
  243.       assert(0);
  244.       return;
  245.    }
  246.    if (draw->collect_statistics) {
  247.       draw->statistics.ia_vertices += prim_info->count;
  248.       draw->statistics.ia_primitives +=
  249.          u_decomposed_prims_for_vertices(prim_info->prim, fetch_info->count);
  250.       draw->statistics.vs_invocations += fetch_info->count;
  251.    }
  252.  
  253.    /* Fetch into our vertex buffer.
  254.     */
  255.    fetch( fpme->fetch, fetch_info, (char *)fetched_vert_info.verts );
  256.  
  257.    /* Finished with fetch:
  258.     */
  259.    fetch_info = NULL;
  260.    vert_info = &fetched_vert_info;
  261.  
  262.    /* Run the shader, note that this overwrites the data[] parts of
  263.     * the pipeline verts.
  264.     */
  265.    if (fpme->opt & PT_SHADE) {
  266.       draw_vertex_shader_run(vshader,
  267.                              draw->pt.user.vs_constants,
  268.                              draw->pt.user.vs_constants_size,
  269.                              vert_info,
  270.                              &vs_vert_info);
  271.  
  272.       FREE(vert_info->verts);
  273.       vert_info = &vs_vert_info;
  274.    }
  275.  
  276.    if ((fpme->opt & PT_SHADE) && gshader) {
  277.       draw_geometry_shader_run(gshader,
  278.                                draw->pt.user.gs_constants,
  279.                                draw->pt.user.gs_constants_size,
  280.                                vert_info,
  281.                                prim_info,
  282.                                &vshader->info,
  283.                                &gs_vert_info,
  284.                                &gs_prim_info);
  285.  
  286.       FREE(vert_info->verts);
  287.       vert_info = &gs_vert_info;
  288.       prim_info = &gs_prim_info;
  289.    } else {
  290.       if (draw_prim_assembler_is_required(draw, prim_info, vert_info)) {
  291.          draw_prim_assembler_run(draw, prim_info, vert_info,
  292.                                  &ia_prim_info, &ia_vert_info);
  293.  
  294.          if (ia_vert_info.count) {
  295.             FREE(vert_info->verts);
  296.             vert_info = &ia_vert_info;
  297.             prim_info = &ia_prim_info;
  298.             free_prim_info = TRUE;
  299.          }
  300.       }
  301.    }
  302.    if (prim_info->count == 0) {
  303.       debug_printf("GS/IA didn't emit any vertices!\n");
  304.      
  305.       FREE(vert_info->verts);
  306.       if (free_prim_info) {
  307.          FREE(prim_info->primitive_lengths);
  308.       }
  309.       return;
  310.    }
  311.  
  312.  
  313.    /* Stream output needs to be done before clipping.
  314.     *
  315.     * XXX: Stream output surely needs to respect the prim_info->elt
  316.     *      lists.
  317.     */
  318.    draw_pt_so_emit( fpme->so_emit, vert_info, prim_info );
  319.  
  320.    draw_stats_clipper_primitives(draw, prim_info);
  321.  
  322.    /*
  323.     * if there's no position, need to stop now, or the latter stages
  324.     * will try to access non-existent position output.
  325.     */
  326.    if (draw_current_shader_position_output(draw) != -1) {
  327.  
  328.       if (draw_pt_post_vs_run( fpme->post_vs, vert_info, prim_info ))
  329.       {
  330.          opt |= PT_PIPELINE;
  331.       }
  332.  
  333.       /* Do we need to run the pipeline?
  334.        */
  335.       if (opt & PT_PIPELINE) {
  336.          pipeline( fpme, vert_info, prim_info );
  337.       }
  338.       else {
  339.          emit( fpme->emit, vert_info, prim_info );
  340.       }
  341.    }
  342.    FREE(vert_info->verts);
  343.    if (free_prim_info) {
  344.       FREE(prim_info->primitive_lengths);
  345.    }
  346. }
  347.  
  348. static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
  349.                                 const unsigned *fetch_elts,
  350.                                 unsigned fetch_count,
  351.                                 const ushort *draw_elts,
  352.                                 unsigned draw_count,
  353.                                 unsigned prim_flags )
  354. {
  355.    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
  356.    struct draw_fetch_info fetch_info;
  357.    struct draw_prim_info prim_info;
  358.  
  359.    fetch_info.linear = FALSE;
  360.    fetch_info.start = 0;
  361.    fetch_info.elts = fetch_elts;
  362.    fetch_info.count = fetch_count;
  363.  
  364.    prim_info.linear = FALSE;
  365.    prim_info.start = 0;
  366.    prim_info.count = draw_count;
  367.    prim_info.elts = draw_elts;
  368.    prim_info.prim = fpme->input_prim;
  369.    prim_info.flags = prim_flags;
  370.    prim_info.primitive_count = 1;
  371.    prim_info.primitive_lengths = &draw_count;
  372.  
  373.    fetch_pipeline_generic( middle, &fetch_info, &prim_info );
  374. }
  375.  
  376.  
  377. static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
  378.                                        unsigned start,
  379.                                        unsigned count,
  380.                                        unsigned prim_flags)
  381. {
  382.    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
  383.    struct draw_fetch_info fetch_info;
  384.    struct draw_prim_info prim_info;
  385.  
  386.    fetch_info.linear = TRUE;
  387.    fetch_info.start = start;
  388.    fetch_info.count = count;
  389.    fetch_info.elts = NULL;
  390.  
  391.    prim_info.linear = TRUE;
  392.    prim_info.start = 0;
  393.    prim_info.count = count;
  394.    prim_info.elts = NULL;
  395.    prim_info.prim = fpme->input_prim;
  396.    prim_info.flags = prim_flags;
  397.    prim_info.primitive_count = 1;
  398.    prim_info.primitive_lengths = &count;
  399.  
  400.    fetch_pipeline_generic( middle, &fetch_info, &prim_info );
  401. }
  402.  
  403.  
  404.  
  405. static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle,
  406.                                                unsigned start,
  407.                                                unsigned count,
  408.                                                const ushort *draw_elts,
  409.                                                unsigned draw_count,
  410.                                                unsigned prim_flags )
  411. {
  412.    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
  413.    struct draw_fetch_info fetch_info;
  414.    struct draw_prim_info prim_info;
  415.  
  416.    fetch_info.linear = TRUE;
  417.    fetch_info.start = start;
  418.    fetch_info.count = count;
  419.    fetch_info.elts = NULL;
  420.  
  421.    prim_info.linear = FALSE;
  422.    prim_info.start = 0;
  423.    prim_info.count = draw_count;
  424.    prim_info.elts = draw_elts;
  425.    prim_info.prim = fpme->input_prim;
  426.    prim_info.flags = prim_flags;
  427.    prim_info.primitive_count = 1;
  428.    prim_info.primitive_lengths = &draw_count;
  429.  
  430.    fetch_pipeline_generic( middle, &fetch_info, &prim_info );
  431.  
  432.    return TRUE;
  433. }
  434.  
  435.  
  436.  
  437. static void fetch_pipeline_finish( struct draw_pt_middle_end *middle )
  438. {
  439.    /* nothing to do */
  440. }
  441.  
  442. static void fetch_pipeline_destroy( struct draw_pt_middle_end *middle )
  443. {
  444.    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
  445.  
  446.    if (fpme->fetch)
  447.       draw_pt_fetch_destroy( fpme->fetch );
  448.  
  449.    if (fpme->emit)
  450.       draw_pt_emit_destroy( fpme->emit );
  451.  
  452.    if (fpme->so_emit)
  453.       draw_pt_so_emit_destroy( fpme->so_emit );
  454.  
  455.    if (fpme->post_vs)
  456.       draw_pt_post_vs_destroy( fpme->post_vs );
  457.  
  458.    FREE(middle);
  459. }
  460.  
  461.  
  462. struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit( struct draw_context *draw )
  463. {
  464.    struct fetch_pipeline_middle_end *fpme = CALLOC_STRUCT( fetch_pipeline_middle_end );
  465.    if (!fpme)
  466.       goto fail;
  467.  
  468.    fpme->base.prepare        = fetch_pipeline_prepare;
  469.    fpme->base.bind_parameters  = fetch_pipeline_bind_parameters;
  470.    fpme->base.run            = fetch_pipeline_run;
  471.    fpme->base.run_linear     = fetch_pipeline_linear_run;
  472.    fpme->base.run_linear_elts = fetch_pipeline_linear_run_elts;
  473.    fpme->base.finish         = fetch_pipeline_finish;
  474.    fpme->base.destroy        = fetch_pipeline_destroy;
  475.  
  476.    fpme->draw = draw;
  477.  
  478.    fpme->fetch = draw_pt_fetch_create( draw );
  479.    if (!fpme->fetch)
  480.       goto fail;
  481.  
  482.    fpme->post_vs = draw_pt_post_vs_create( draw );
  483.    if (!fpme->post_vs)
  484.       goto fail;
  485.  
  486.    fpme->emit = draw_pt_emit_create( draw );
  487.    if (!fpme->emit)
  488.       goto fail;
  489.  
  490.    fpme->so_emit = draw_pt_so_emit_create( draw );
  491.    if (!fpme->so_emit)
  492.       goto fail;
  493.  
  494.    return &fpme->base;
  495.  
  496.  fail:
  497.    if (fpme)
  498.       fetch_pipeline_destroy( &fpme->base );
  499.  
  500.    return NULL;
  501. }
  502.