Home | History | Annotate | Download | only in i965
      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 /**
     25  * @file gen7_sol_state.c
     26  *
     27  * Controls the stream output logic (SOL) stage of the gen7 hardware, which is
     28  * used to implement GL_EXT_transform_feedback.
     29  */
     30 
     31 #include "brw_context.h"
     32 #include "brw_state.h"
     33 #include "brw_defines.h"
     34 #include "intel_batchbuffer.h"
     35 #include "intel_buffer_objects.h"
     36 #include "main/transformfeedback.h"
     37 
     38 void
     39 gen7_begin_transform_feedback(struct gl_context *ctx, GLenum mode,
     40                               struct gl_transform_feedback_object *obj)
     41 {
     42    struct brw_context *brw = brw_context(ctx);
     43    struct brw_transform_feedback_object *brw_obj =
     44       (struct brw_transform_feedback_object *) obj;
     45 
     46    assert(brw->screen->devinfo.gen == 7);
     47 
     48    /* Store the starting value of the SO_NUM_PRIMS_WRITTEN counters. */
     49    brw_save_primitives_written_counters(brw, brw_obj);
     50 
     51    /* Reset the SO buffer offsets to 0. */
     52    if (!can_do_pipelined_register_writes(brw->screen)) {
     53       intel_batchbuffer_flush(brw);
     54       brw->batch.needs_sol_reset = true;
     55    } else {
     56       for (int i = 0; i < 4; i++) {
     57          brw_load_register_imm32(brw, GEN7_SO_WRITE_OFFSET(i), 0);
     58       }
     59    }
     60 
     61    brw_obj->primitive_mode = mode;
     62 }
     63 
     64 void
     65 gen7_end_transform_feedback(struct gl_context *ctx,
     66 			    struct gl_transform_feedback_object *obj)
     67 {
     68    /* After EndTransformFeedback, it's likely that the client program will try
     69     * to draw using the contents of the transform feedback buffer as vertex
     70     * input.  In order for this to work, we need to flush the data through at
     71     * least the GS stage of the pipeline, and flush out the render cache.  For
     72     * simplicity, just do a full flush.
     73     */
     74    struct brw_context *brw = brw_context(ctx);
     75    struct brw_transform_feedback_object *brw_obj =
     76       (struct brw_transform_feedback_object *) obj;
     77 
     78    /* Store the ending value of the SO_NUM_PRIMS_WRITTEN counters. */
     79    if (!obj->Paused)
     80       brw_save_primitives_written_counters(brw, brw_obj);
     81 
     82    /* We've reached the end of a transform feedback begin/end block.  This
     83     * means that future DrawTransformFeedback() calls will need to pick up the
     84     * results of the current counter, and that it's time to roll back the
     85     * current primitive counter to zero.
     86     */
     87    brw_obj->previous_counter = brw_obj->counter;
     88    brw_reset_transform_feedback_counter(&brw_obj->counter);
     89 
     90    /* EndTransformFeedback() means that we need to update the number of
     91     * vertices written.  Since it's only necessary if DrawTransformFeedback()
     92     * is called and it means mapping a buffer object, we delay computing it
     93     * until it's absolutely necessary to try and avoid stalls.
     94     */
     95    brw_obj->vertices_written_valid = false;
     96 }
     97 
     98 void
     99 gen7_pause_transform_feedback(struct gl_context *ctx,
    100                               struct gl_transform_feedback_object *obj)
    101 {
    102    struct brw_context *brw = brw_context(ctx);
    103    struct brw_transform_feedback_object *brw_obj =
    104       (struct brw_transform_feedback_object *) obj;
    105 
    106    /* Flush any drawing so that the counters have the right values. */
    107    brw_emit_mi_flush(brw);
    108 
    109    assert(brw->screen->devinfo.gen == 7);
    110 
    111    /* Save the SOL buffer offset register values. */
    112    for (int i = 0; i < 4; i++) {
    113       BEGIN_BATCH(3);
    114       OUT_BATCH(MI_STORE_REGISTER_MEM | (3 - 2));
    115       OUT_BATCH(GEN7_SO_WRITE_OFFSET(i));
    116       OUT_RELOC(brw_obj->offset_bo, RELOC_WRITE, i * sizeof(uint32_t));
    117       ADVANCE_BATCH();
    118    }
    119 
    120    /* Store the temporary ending value of the SO_NUM_PRIMS_WRITTEN counters.
    121     * While this operation is paused, other transform feedback actions may
    122     * occur, which will contribute to the counters.  We need to exclude that
    123     * from our counts.
    124     */
    125    brw_save_primitives_written_counters(brw, brw_obj);
    126 }
    127 
    128 void
    129 gen7_resume_transform_feedback(struct gl_context *ctx,
    130                                struct gl_transform_feedback_object *obj)
    131 {
    132    struct brw_context *brw = brw_context(ctx);
    133    struct brw_transform_feedback_object *brw_obj =
    134       (struct brw_transform_feedback_object *) obj;
    135 
    136    assert(brw->screen->devinfo.gen == 7);
    137 
    138    /* Reload the SOL buffer offset registers. */
    139    for (int i = 0; i < 4; i++) {
    140       BEGIN_BATCH(3);
    141       OUT_BATCH(GEN7_MI_LOAD_REGISTER_MEM | (3 - 2));
    142       OUT_BATCH(GEN7_SO_WRITE_OFFSET(i));
    143       OUT_RELOC(brw_obj->offset_bo, RELOC_WRITE, i * sizeof(uint32_t));
    144       ADVANCE_BATCH();
    145    }
    146 
    147    /* Store the new starting value of the SO_NUM_PRIMS_WRITTEN counters. */
    148    brw_save_primitives_written_counters(brw, brw_obj);
    149 }
    150