Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2011 Intel Corporation
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21.  * IN THE SOFTWARE.
  22.  */
  23.  
  24. /** \file gen6_sol.c
  25.  *
  26.  * Code to initialize the binding table entries used by transform feedback.
  27.  */
  28.  
  29. #include "main/bufferobj.h"
  30. #include "main/macros.h"
  31. #include "brw_context.h"
  32. #include "intel_batchbuffer.h"
  33. #include "brw_defines.h"
  34. #include "brw_state.h"
  35. #include "main/transformfeedback.h"
  36.  
  37. static void
  38. gen6_update_sol_surfaces(struct brw_context *brw)
  39. {
  40.    struct gl_context *ctx = &brw->ctx;
  41.    /* BRW_NEW_TRANSFORM_FEEDBACK */
  42.    struct gl_transform_feedback_object *xfb_obj =
  43.       ctx->TransformFeedback.CurrentObject;
  44.    const struct gl_shader_program *shaderprog;
  45.    const struct gl_transform_feedback_info *linked_xfb_info;
  46.    int i;
  47.  
  48.    if (brw->geometry_program) {
  49.       /* BRW_NEW_GEOMETRY_PROGRAM */
  50.       shaderprog =
  51.          ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
  52.    } else {
  53.       /* BRW_NEW_VERTEX_PROGRAM */
  54.       shaderprog =
  55.          ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
  56.    }
  57.    linked_xfb_info = &shaderprog->LinkedTransformFeedback;
  58.  
  59.    for (i = 0; i < BRW_MAX_SOL_BINDINGS; ++i) {
  60.       const int surf_index = SURF_INDEX_GEN6_SOL_BINDING(i);
  61.       if (_mesa_is_xfb_active_and_unpaused(ctx) &&
  62.           i < linked_xfb_info->NumOutputs) {
  63.          unsigned buffer = linked_xfb_info->Outputs[i].OutputBuffer;
  64.          unsigned buffer_offset =
  65.             xfb_obj->Offset[buffer] / 4 +
  66.             linked_xfb_info->Outputs[i].DstOffset;
  67.          if (brw->geometry_program) {
  68.             brw_update_sol_surface(
  69.                brw, xfb_obj->Buffers[buffer],
  70.                &brw->gs.base.surf_offset[surf_index],
  71.                linked_xfb_info->Outputs[i].NumComponents,
  72.                linked_xfb_info->BufferStride[buffer], buffer_offset);
  73.          } else {
  74.             brw_update_sol_surface(
  75.                brw, xfb_obj->Buffers[buffer],
  76.                &brw->ff_gs.surf_offset[surf_index],
  77.                linked_xfb_info->Outputs[i].NumComponents,
  78.                linked_xfb_info->BufferStride[buffer], buffer_offset);
  79.          }
  80.       } else {
  81.          if (!brw->geometry_program)
  82.             brw->ff_gs.surf_offset[surf_index] = 0;
  83.          else
  84.             brw->gs.base.surf_offset[surf_index] = 0;
  85.       }
  86.    }
  87.  
  88.    brw->ctx.NewDriverState |= BRW_NEW_SURFACES;
  89. }
  90.  
  91. const struct brw_tracked_state gen6_sol_surface = {
  92.    .dirty = {
  93.       .mesa = 0,
  94.       .brw = BRW_NEW_BATCH |
  95.              BRW_NEW_GEOMETRY_PROGRAM |
  96.              BRW_NEW_VERTEX_PROGRAM |
  97.              BRW_NEW_TRANSFORM_FEEDBACK,
  98.    },
  99.    .emit = gen6_update_sol_surfaces,
  100. };
  101.  
  102. /**
  103.  * Constructs the binding table for the WM surface state, which maps unit
  104.  * numbers to surface state objects.
  105.  */
  106. static void
  107. brw_gs_upload_binding_table(struct brw_context *brw)
  108. {
  109.    uint32_t *bind;
  110.    struct gl_context *ctx = &brw->ctx;
  111.    const struct gl_shader_program *shaderprog;
  112.    bool need_binding_table = false;
  113.  
  114.    /* We have two scenarios here:
  115.     * 1) We are using a geometry shader only to implement transform feedback
  116.     *    for a vertex shader (brw->geometry_program == NULL). In this case, we
  117.     *    only need surfaces for transform feedback in the GS stage.
  118.     * 2) We have a user-provided geometry shader. In this case we may need
  119.     *    surfaces for transform feedback and/or other stuff, like textures,
  120.     *    in the GS stage.
  121.     */
  122.  
  123.    if (!brw->geometry_program) {
  124.       /* BRW_NEW_VERTEX_PROGRAM */
  125.       shaderprog = ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
  126.       if (shaderprog) {
  127.          /* Skip making a binding table if we don't have anything to put in it */
  128.          const struct gl_transform_feedback_info *linked_xfb_info =
  129.             &shaderprog->LinkedTransformFeedback;
  130.          need_binding_table = linked_xfb_info->NumOutputs > 0;
  131.       }
  132.       if (!need_binding_table) {
  133.          if (brw->ff_gs.bind_bo_offset != 0) {
  134.             brw->ctx.NewDriverState |= BRW_NEW_GS_BINDING_TABLE;
  135.             brw->ff_gs.bind_bo_offset = 0;
  136.          }
  137.          return;
  138.       }
  139.  
  140.       /* Might want to calculate nr_surfaces first, to avoid taking up so much
  141.        * space for the binding table. Anyway, in this case we know that we only
  142.        * use BRW_MAX_SOL_BINDINGS surfaces at most.
  143.        */
  144.       bind = brw_state_batch(brw, AUB_TRACE_BINDING_TABLE,
  145.                              sizeof(uint32_t) * BRW_MAX_SOL_BINDINGS,
  146.                              32, &brw->ff_gs.bind_bo_offset);
  147.  
  148.       /* BRW_NEW_SURFACES */
  149.       memcpy(bind, brw->ff_gs.surf_offset,
  150.              BRW_MAX_SOL_BINDINGS * sizeof(uint32_t));
  151.    } else {
  152.       /* BRW_NEW_GEOMETRY_PROGRAM */
  153.       shaderprog = ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
  154.       if (shaderprog) {
  155.          /* Skip making a binding table if we don't have anything to put in it */
  156.          struct brw_stage_prog_data *prog_data = brw->gs.base.prog_data;
  157.          const struct gl_transform_feedback_info *linked_xfb_info =
  158.             &shaderprog->LinkedTransformFeedback;
  159.          need_binding_table = linked_xfb_info->NumOutputs > 0 ||
  160.                               prog_data->binding_table.size_bytes > 0;
  161.       }
  162.       if (!need_binding_table) {
  163.          if (brw->gs.base.bind_bo_offset != 0) {
  164.             brw->gs.base.bind_bo_offset = 0;
  165.             brw->ctx.NewDriverState |= BRW_NEW_GS_BINDING_TABLE;
  166.          }
  167.          return;
  168.       }
  169.  
  170.       /* Might want to calculate nr_surfaces first, to avoid taking up so much
  171.        * space for the binding table.
  172.        */
  173.       bind = brw_state_batch(brw, AUB_TRACE_BINDING_TABLE,
  174.                              sizeof(uint32_t) * BRW_MAX_SURFACES,
  175.                              32, &brw->gs.base.bind_bo_offset);
  176.  
  177.       /* BRW_NEW_SURFACES */
  178.       memcpy(bind, brw->gs.base.surf_offset,
  179.              BRW_MAX_SURFACES * sizeof(uint32_t));
  180.    }
  181.  
  182.    brw->ctx.NewDriverState |= BRW_NEW_GS_BINDING_TABLE;
  183. }
  184.  
  185. const struct brw_tracked_state gen6_gs_binding_table = {
  186.    .dirty = {
  187.       .mesa = 0,
  188.       .brw = BRW_NEW_BATCH |
  189.              BRW_NEW_GEOMETRY_PROGRAM |
  190.              BRW_NEW_VERTEX_PROGRAM |
  191.              BRW_NEW_SURFACES,
  192.    },
  193.    .emit = brw_gs_upload_binding_table,
  194. };
  195.  
  196. struct gl_transform_feedback_object *
  197. brw_new_transform_feedback(struct gl_context *ctx, GLuint name)
  198. {
  199.    struct brw_context *brw = brw_context(ctx);
  200.    struct brw_transform_feedback_object *brw_obj =
  201.       CALLOC_STRUCT(brw_transform_feedback_object);
  202.    if (!brw_obj)
  203.       return NULL;
  204.  
  205.    _mesa_init_transform_feedback_object(&brw_obj->base, name);
  206.  
  207.    brw_obj->offset_bo =
  208.       drm_intel_bo_alloc(brw->bufmgr, "transform feedback offsets", 16, 64);
  209.    brw_obj->prim_count_bo =
  210.       drm_intel_bo_alloc(brw->bufmgr, "xfb primitive counts", 4096, 64);
  211.  
  212.    return &brw_obj->base;
  213. }
  214.  
  215. void
  216. brw_delete_transform_feedback(struct gl_context *ctx,
  217.                               struct gl_transform_feedback_object *obj)
  218. {
  219.    struct brw_transform_feedback_object *brw_obj =
  220.       (struct brw_transform_feedback_object *) obj;
  221.  
  222.    for (unsigned i = 0; i < ARRAY_SIZE(obj->Buffers); i++) {
  223.       _mesa_reference_buffer_object(ctx, &obj->Buffers[i], NULL);
  224.    }
  225.  
  226.    drm_intel_bo_unreference(brw_obj->offset_bo);
  227.    drm_intel_bo_unreference(brw_obj->prim_count_bo);
  228.  
  229.    free(brw_obj);
  230. }
  231.  
  232. void
  233. brw_begin_transform_feedback(struct gl_context *ctx, GLenum mode,
  234.                              struct gl_transform_feedback_object *obj)
  235. {
  236.    struct brw_context *brw = brw_context(ctx);
  237.    const struct gl_shader_program *shaderprog;
  238.    const struct gl_transform_feedback_info *linked_xfb_info;
  239.    struct gl_transform_feedback_object *xfb_obj =
  240.       ctx->TransformFeedback.CurrentObject;
  241.  
  242.    assert(brw->gen == 6);
  243.  
  244.    if (ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]) {
  245.       /* BRW_NEW_GEOMETRY_PROGRAM */
  246.       shaderprog =
  247.          ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
  248.    } else {
  249.       /* BRW_NEW_VERTEX_PROGRAM */
  250.       shaderprog =
  251.          ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
  252.    }
  253.    linked_xfb_info = &shaderprog->LinkedTransformFeedback;
  254.  
  255.    /* Compute the maximum number of vertices that we can write without
  256.     * overflowing any of the buffers currently being used for feedback.
  257.     */
  258.    unsigned max_index
  259.       = _mesa_compute_max_transform_feedback_vertices(xfb_obj,
  260.                                                       linked_xfb_info);
  261.  
  262.    /* Initialize the SVBI 0 register to zero and set the maximum index. */
  263.    BEGIN_BATCH(4);
  264.    OUT_BATCH(_3DSTATE_GS_SVB_INDEX << 16 | (4 - 2));
  265.    OUT_BATCH(0); /* SVBI 0 */
  266.    OUT_BATCH(0); /* starting index */
  267.    OUT_BATCH(max_index);
  268.    ADVANCE_BATCH();
  269.  
  270.    /* Initialize the rest of the unused streams to sane values.  Otherwise,
  271.     * they may indicate that there is no room to write data and prevent
  272.     * anything from happening at all.
  273.     */
  274.    for (int i = 1; i < 4; i++) {
  275.       BEGIN_BATCH(4);
  276.       OUT_BATCH(_3DSTATE_GS_SVB_INDEX << 16 | (4 - 2));
  277.       OUT_BATCH(i << SVB_INDEX_SHIFT);
  278.       OUT_BATCH(0); /* starting index */
  279.       OUT_BATCH(0xffffffff);
  280.       ADVANCE_BATCH();
  281.    }
  282. }
  283.  
  284. void
  285. brw_end_transform_feedback(struct gl_context *ctx,
  286.                            struct gl_transform_feedback_object *obj)
  287. {
  288.    /* After EndTransformFeedback, it's likely that the client program will try
  289.     * to draw using the contents of the transform feedback buffer as vertex
  290.     * input.  In order for this to work, we need to flush the data through at
  291.     * least the GS stage of the pipeline, and flush out the render cache.  For
  292.     * simplicity, just do a full flush.
  293.     */
  294.    struct brw_context *brw = brw_context(ctx);
  295.    intel_batchbuffer_emit_mi_flush(brw);
  296. }
  297.