Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 VMware, Inc.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. #include "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. /** cast wrapper */
  57. static INLINE struct fetch_pipeline_middle_end *
  58. fetch_pipeline_middle_end(struct draw_pt_middle_end *middle)
  59. {
  60.    return (struct fetch_pipeline_middle_end *) middle;
  61. }
  62.  
  63.  
  64. /**
  65.  * Prepare/validate middle part of the vertex pipeline.
  66.  * NOTE: if you change this function, also look at the LLVM
  67.  * function llvm_middle_end_prepare() for similar changes.
  68.  */
  69. static void
  70. fetch_pipeline_prepare(struct draw_pt_middle_end *middle,
  71.                        unsigned prim,
  72.                        unsigned opt,
  73.                        unsigned *max_vertices)
  74. {
  75.    struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle);
  76.    struct draw_context *draw = fpme->draw;
  77.    struct draw_vertex_shader *vs = draw->vs.vertex_shader;
  78.    struct draw_geometry_shader *gs = draw->gs.geometry_shader;
  79.    unsigned i;
  80.    unsigned instance_id_index = ~0;
  81.    const unsigned gs_out_prim = (gs ? gs->output_primitive :
  82.                                  u_assembled_prim(prim));
  83.    unsigned nr_vs_outputs = draw_total_vs_outputs(draw);
  84.    unsigned nr = MAX2(vs->info.num_inputs, nr_vs_outputs);
  85.    unsigned point_clip = draw->rasterizer->fill_front == PIPE_POLYGON_MODE_POINT ||
  86.                          gs_out_prim == PIPE_PRIM_POINTS;
  87.  
  88.    if (gs) {
  89.       nr = MAX2(nr, gs->info.num_outputs + 1);
  90.    }
  91.  
  92.    /* Scan for instanceID system value.
  93.     */
  94.    for (i = 0; i < vs->info.num_inputs; i++) {
  95.       if (vs->info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
  96.          instance_id_index = i;
  97.          break;
  98.       }
  99.    }
  100.  
  101.    fpme->input_prim = prim;
  102.    fpme->opt = opt;
  103.  
  104.    /* Always leave room for the vertex header whether we need it or
  105.     * not.  It's hard to get rid of it in particular because of the
  106.     * viewport code in draw_pt_post_vs.c.
  107.     */
  108.    fpme->vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float);
  109.  
  110.    draw_pt_fetch_prepare( fpme->fetch,
  111.                           vs->info.num_inputs,
  112.                           fpme->vertex_size,
  113.                           instance_id_index );
  114.    draw_pt_post_vs_prepare( fpme->post_vs,
  115.                             draw->clip_xy,
  116.                             draw->clip_z,
  117.                             draw->clip_user,
  118.                             point_clip ? draw->guard_band_points_xy :
  119.                                          draw->guard_band_xy,
  120.                             draw->bypass_viewport,
  121.                             draw->rasterizer->clip_halfz,
  122.                             (draw->vs.edgeflag_output ? TRUE : FALSE) );
  123.  
  124.    draw_pt_so_emit_prepare( fpme->so_emit, FALSE );
  125.  
  126.    if (!(opt & PT_PIPELINE)) {
  127.       draw_pt_emit_prepare( fpme->emit,
  128.                             gs_out_prim,
  129.                             max_vertices );
  130.  
  131.       *max_vertices = MAX2( *max_vertices, 4096 );
  132.    }
  133.    else {
  134.       /* limit max fetches by limiting max_vertices */
  135.       *max_vertices = 4096;
  136.    }
  137.  
  138.    /* No need to prepare the shader.
  139.     */
  140.    vs->prepare(vs, draw);
  141.  
  142.    /* Make sure that the vertex size didn't change at any point above */
  143.    assert(nr_vs_outputs == draw_total_vs_outputs(draw));
  144. }
  145.  
  146.  
  147. static void
  148. fetch_pipeline_bind_parameters(struct draw_pt_middle_end *middle)
  149. {
  150.    /* No-op since the vertex shader executor and drawing pipeline
  151.     * just grab the constants, viewport, etc. from the draw context state.
  152.     */
  153. }
  154.  
  155.  
  156. static void fetch( struct pt_fetch *fetch,
  157.                    const struct draw_fetch_info *fetch_info,
  158.                    char *output)
  159. {
  160.    if (fetch_info->linear) {
  161.       draw_pt_fetch_run_linear( fetch,
  162.                                 fetch_info->start,
  163.                                 fetch_info->count,
  164.                                 output );
  165.    }
  166.    else {
  167.       draw_pt_fetch_run( fetch,
  168.                          fetch_info->elts,
  169.                          fetch_info->count,
  170.                          output );
  171.    }
  172. }
  173.  
  174.  
  175. static void pipeline(struct fetch_pipeline_middle_end *fpme,
  176.                      const struct draw_vertex_info *vert_info,
  177.                      const struct draw_prim_info *prim_info)
  178. {
  179.    if (prim_info->linear)
  180.       draw_pipeline_run_linear( fpme->draw,
  181.                                 vert_info,
  182.                                 prim_info);
  183.    else
  184.       draw_pipeline_run( fpme->draw,
  185.                          vert_info,
  186.                          prim_info );
  187. }
  188.  
  189.  
  190. static void
  191. emit(struct pt_emit *emit,
  192.      const struct draw_vertex_info *vert_info,
  193.      const struct draw_prim_info *prim_info)
  194. {
  195.    if (prim_info->linear) {
  196.       draw_pt_emit_linear(emit, vert_info, prim_info);
  197.    }
  198.    else {
  199.       draw_pt_emit(emit, vert_info, prim_info);
  200.    }
  201. }
  202.  
  203.  
  204. static void
  205. draw_vertex_shader_run(struct draw_vertex_shader *vshader,
  206.                        const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
  207.                        unsigned const_size[PIPE_MAX_CONSTANT_BUFFERS],
  208.                        const struct draw_vertex_info *input_verts,
  209.                        struct draw_vertex_info *output_verts)
  210. {
  211.    output_verts->vertex_size = input_verts->vertex_size;
  212.    output_verts->stride = input_verts->vertex_size;
  213.    output_verts->count = input_verts->count;
  214.    output_verts->verts =
  215.       (struct vertex_header *)MALLOC(output_verts->vertex_size *
  216.                                      align(output_verts->count, 4));
  217.  
  218.    vshader->run_linear(vshader,
  219.                        (const float (*)[4])input_verts->verts->data,
  220.                        (      float (*)[4])output_verts->verts->data,
  221.                        constants,
  222.                        const_size,
  223.                        input_verts->count,
  224.                        input_verts->vertex_size,
  225.                        input_verts->vertex_size);
  226. }
  227.  
  228.  
  229. static void
  230. fetch_pipeline_generic(struct draw_pt_middle_end *middle,
  231.                        const struct draw_fetch_info *fetch_info,
  232.                        const struct draw_prim_info *in_prim_info)
  233. {
  234.    struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle);
  235.    struct draw_context *draw = fpme->draw;
  236.    struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
  237.    struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
  238.    struct draw_prim_info gs_prim_info;
  239.    struct draw_vertex_info fetched_vert_info;
  240.    struct draw_vertex_info vs_vert_info;
  241.    struct draw_vertex_info gs_vert_info;
  242.    struct draw_vertex_info *vert_info;
  243.    struct draw_prim_info ia_prim_info;
  244.    struct draw_vertex_info ia_vert_info;
  245.    const struct draw_prim_info *prim_info = in_prim_info;
  246.    boolean free_prim_info = FALSE;
  247.    unsigned opt = fpme->opt;
  248.  
  249.    fetched_vert_info.count = fetch_info->count;
  250.    fetched_vert_info.vertex_size = fpme->vertex_size;
  251.    fetched_vert_info.stride = fpme->vertex_size;
  252.    fetched_vert_info.verts =
  253.       (struct vertex_header *)MALLOC(fpme->vertex_size *
  254.                                      align(fetch_info->count,  4));
  255.    if (!fetched_vert_info.verts) {
  256.       assert(0);
  257.       return;
  258.    }
  259.    if (draw->collect_statistics) {
  260.       draw->statistics.ia_vertices += prim_info->count;
  261.       draw->statistics.ia_primitives +=
  262.          u_decomposed_prims_for_vertices(prim_info->prim, fetch_info->count);
  263.       draw->statistics.vs_invocations += fetch_info->count;
  264.    }
  265.  
  266.    /* Fetch into our vertex buffer.
  267.     */
  268.    fetch( fpme->fetch, fetch_info, (char *)fetched_vert_info.verts );
  269.  
  270.    /* Finished with fetch:
  271.     */
  272.    fetch_info = NULL;
  273.    vert_info = &fetched_vert_info;
  274.  
  275.    /* Run the shader, note that this overwrites the data[] parts of
  276.     * the pipeline verts.
  277.     */
  278.    if (fpme->opt & PT_SHADE) {
  279.       draw_vertex_shader_run(vshader,
  280.                              draw->pt.user.vs_constants,
  281.                              draw->pt.user.vs_constants_size,
  282.                              vert_info,
  283.                              &vs_vert_info);
  284.  
  285.       FREE(vert_info->verts);
  286.       vert_info = &vs_vert_info;
  287.    }
  288.  
  289.    if ((fpme->opt & PT_SHADE) && gshader) {
  290.       draw_geometry_shader_run(gshader,
  291.                                draw->pt.user.gs_constants,
  292.                                draw->pt.user.gs_constants_size,
  293.                                vert_info,
  294.                                prim_info,
  295.                                &vshader->info,
  296.                                &gs_vert_info,
  297.                                &gs_prim_info);
  298.  
  299.       FREE(vert_info->verts);
  300.       vert_info = &gs_vert_info;
  301.       prim_info = &gs_prim_info;
  302.    } else {
  303.       if (draw_prim_assembler_is_required(draw, prim_info, vert_info)) {
  304.          draw_prim_assembler_run(draw, prim_info, vert_info,
  305.                                  &ia_prim_info, &ia_vert_info);
  306.  
  307.          if (ia_vert_info.count) {
  308.             FREE(vert_info->verts);
  309.             vert_info = &ia_vert_info;
  310.             prim_info = &ia_prim_info;
  311.             free_prim_info = TRUE;
  312.          }
  313.       }
  314.    }
  315.    if (prim_info->count == 0) {
  316.       debug_printf("GS/IA didn't emit any vertices!\n");
  317.  
  318.       FREE(vert_info->verts);
  319.       if (free_prim_info) {
  320.          FREE(prim_info->primitive_lengths);
  321.       }
  322.       return;
  323.    }
  324.  
  325.  
  326.    /* Stream output needs to be done before clipping.
  327.     *
  328.     * XXX: Stream output surely needs to respect the prim_info->elt
  329.     *      lists.
  330.     */
  331.    draw_pt_so_emit( fpme->so_emit, vert_info, prim_info );
  332.  
  333.    draw_stats_clipper_primitives(draw, prim_info);
  334.  
  335.    /*
  336.     * if there's no position, need to stop now, or the latter stages
  337.     * will try to access non-existent position output.
  338.     */
  339.    if (draw_current_shader_position_output(draw) != -1) {
  340.  
  341.       if (draw_pt_post_vs_run( fpme->post_vs, vert_info, prim_info ))
  342.       {
  343.          opt |= PT_PIPELINE;
  344.       }
  345.  
  346.       /* Do we need to run the pipeline?
  347.        */
  348.       if (opt & PT_PIPELINE) {
  349.          pipeline( fpme, vert_info, prim_info );
  350.       }
  351.       else {
  352.          emit( fpme->emit, vert_info, prim_info );
  353.       }
  354.    }
  355.    FREE(vert_info->verts);
  356.    if (free_prim_info) {
  357.       FREE(prim_info->primitive_lengths);
  358.    }
  359. }
  360.  
  361.  
  362. static void
  363. fetch_pipeline_run(struct draw_pt_middle_end *middle,
  364.                    const unsigned *fetch_elts,
  365.                    unsigned fetch_count,
  366.                    const ushort *draw_elts,
  367.                    unsigned draw_count,
  368.                    unsigned prim_flags)
  369. {
  370.    struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle);
  371.    struct draw_fetch_info fetch_info;
  372.    struct draw_prim_info prim_info;
  373.  
  374.    fetch_info.linear = FALSE;
  375.    fetch_info.start = 0;
  376.    fetch_info.elts = fetch_elts;
  377.    fetch_info.count = fetch_count;
  378.  
  379.    prim_info.linear = FALSE;
  380.    prim_info.start = 0;
  381.    prim_info.count = draw_count;
  382.    prim_info.elts = draw_elts;
  383.    prim_info.prim = fpme->input_prim;
  384.    prim_info.flags = prim_flags;
  385.    prim_info.primitive_count = 1;
  386.    prim_info.primitive_lengths = &draw_count;
  387.  
  388.    fetch_pipeline_generic( middle, &fetch_info, &prim_info );
  389. }
  390.  
  391.  
  392. static void
  393. fetch_pipeline_linear_run(struct draw_pt_middle_end *middle,
  394.                           unsigned start,
  395.                           unsigned count,
  396.                           unsigned prim_flags)
  397. {
  398.    struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle);
  399.    struct draw_fetch_info fetch_info;
  400.    struct draw_prim_info prim_info;
  401.  
  402.    fetch_info.linear = TRUE;
  403.    fetch_info.start = start;
  404.    fetch_info.count = count;
  405.    fetch_info.elts = NULL;
  406.  
  407.    prim_info.linear = TRUE;
  408.    prim_info.start = 0;
  409.    prim_info.count = count;
  410.    prim_info.elts = NULL;
  411.    prim_info.prim = fpme->input_prim;
  412.    prim_info.flags = prim_flags;
  413.    prim_info.primitive_count = 1;
  414.    prim_info.primitive_lengths = &count;
  415.  
  416.    fetch_pipeline_generic( middle, &fetch_info, &prim_info );
  417. }
  418.  
  419.  
  420.  
  421. static boolean
  422. fetch_pipeline_linear_run_elts(struct draw_pt_middle_end *middle,
  423.                                unsigned start,
  424.                                unsigned count,
  425.                                const ushort *draw_elts,
  426.                                unsigned draw_count,
  427.                                unsigned prim_flags )
  428. {
  429.    struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle);
  430.    struct draw_fetch_info fetch_info;
  431.    struct draw_prim_info prim_info;
  432.  
  433.    fetch_info.linear = TRUE;
  434.    fetch_info.start = start;
  435.    fetch_info.count = count;
  436.    fetch_info.elts = NULL;
  437.  
  438.    prim_info.linear = FALSE;
  439.    prim_info.start = 0;
  440.    prim_info.count = draw_count;
  441.    prim_info.elts = draw_elts;
  442.    prim_info.prim = fpme->input_prim;
  443.    prim_info.flags = prim_flags;
  444.    prim_info.primitive_count = 1;
  445.    prim_info.primitive_lengths = &draw_count;
  446.  
  447.    fetch_pipeline_generic( middle, &fetch_info, &prim_info );
  448.  
  449.    return TRUE;
  450. }
  451.  
  452.  
  453. static void
  454. fetch_pipeline_finish( struct draw_pt_middle_end *middle )
  455. {
  456.    /* nothing to do */
  457. }
  458.  
  459.  
  460. static void
  461. fetch_pipeline_destroy( struct draw_pt_middle_end *middle )
  462. {
  463.    struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle);
  464.  
  465.    if (fpme->fetch)
  466.       draw_pt_fetch_destroy( fpme->fetch );
  467.  
  468.    if (fpme->emit)
  469.       draw_pt_emit_destroy( fpme->emit );
  470.  
  471.    if (fpme->so_emit)
  472.       draw_pt_so_emit_destroy( fpme->so_emit );
  473.  
  474.    if (fpme->post_vs)
  475.       draw_pt_post_vs_destroy( fpme->post_vs );
  476.  
  477.    FREE(middle);
  478. }
  479.  
  480.  
  481. struct draw_pt_middle_end *
  482. draw_pt_fetch_pipeline_or_emit(struct draw_context *draw)
  483. {
  484.    struct fetch_pipeline_middle_end *fpme =
  485.       CALLOC_STRUCT( fetch_pipeline_middle_end );
  486.    if (!fpme)
  487.       goto fail;
  488.  
  489.    fpme->base.prepare        = fetch_pipeline_prepare;
  490.    fpme->base.bind_parameters  = fetch_pipeline_bind_parameters;
  491.    fpme->base.run            = fetch_pipeline_run;
  492.    fpme->base.run_linear     = fetch_pipeline_linear_run;
  493.    fpme->base.run_linear_elts = fetch_pipeline_linear_run_elts;
  494.    fpme->base.finish         = fetch_pipeline_finish;
  495.    fpme->base.destroy        = fetch_pipeline_destroy;
  496.  
  497.    fpme->draw = draw;
  498.  
  499.    fpme->fetch = draw_pt_fetch_create( draw );
  500.    if (!fpme->fetch)
  501.       goto fail;
  502.  
  503.    fpme->post_vs = draw_pt_post_vs_create( draw );
  504.    if (!fpme->post_vs)
  505.       goto fail;
  506.  
  507.    fpme->emit = draw_pt_emit_create( draw );
  508.    if (!fpme->emit)
  509.       goto fail;
  510.  
  511.    fpme->so_emit = draw_pt_so_emit_create( draw );
  512.    if (!fpme->so_emit)
  513.       goto fail;
  514.  
  515.    return &fpme->base;
  516.  
  517.  fail:
  518.    if (fpme)
  519.       fetch_pipeline_destroy( &fpme->base );
  520.  
  521.    return NULL;
  522. }
  523.