Home | History | Annotate | Download | only in i965
      1 /*
      2  * Copyright  2014 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  * Authors:
     24  *    Neil Roberts <neil (at) linux.intel.com>
     25  */
     26 
     27 /** @file brw_conditional_render.c
     28  *
     29  * Support for conditional rendering based on query objects
     30  * (GL_NV_conditional_render, GL_ARB_conditional_render_inverted) on Gen7+.
     31  */
     32 
     33 #include "main/imports.h"
     34 #include "main/condrender.h"
     35 
     36 #include "brw_context.h"
     37 #include "brw_defines.h"
     38 #include "intel_batchbuffer.h"
     39 
     40 static void
     41 set_predicate_enable(struct brw_context *brw,
     42                      bool value)
     43 {
     44    if (value)
     45       brw->predicate.state = BRW_PREDICATE_STATE_RENDER;
     46    else
     47       brw->predicate.state = BRW_PREDICATE_STATE_DONT_RENDER;
     48 }
     49 
     50 static void
     51 set_predicate_for_result(struct brw_context *brw,
     52                          struct brw_query_object *query,
     53                          bool inverted)
     54 {
     55    int load_op;
     56 
     57    assert(query->bo != NULL);
     58 
     59    /* Needed to ensure the memory is coherent for the MI_LOAD_REGISTER_MEM
     60     * command when loading the values into the predicate source registers for
     61     * conditional rendering.
     62     */
     63    brw_emit_pipe_control_flush(brw, PIPE_CONTROL_FLUSH_ENABLE);
     64 
     65    brw_load_register_mem64(brw,
     66                            MI_PREDICATE_SRC0,
     67                            query->bo,
     68                            I915_GEM_DOMAIN_INSTRUCTION,
     69                            0, /* write domain */
     70                            0 /* offset */);
     71    brw_load_register_mem64(brw,
     72                            MI_PREDICATE_SRC1,
     73                            query->bo,
     74                            I915_GEM_DOMAIN_INSTRUCTION,
     75                            0, /* write domain */
     76                            8 /* offset */);
     77 
     78    if (inverted)
     79       load_op = MI_PREDICATE_LOADOP_LOAD;
     80    else
     81       load_op = MI_PREDICATE_LOADOP_LOADINV;
     82 
     83    BEGIN_BATCH(1);
     84    OUT_BATCH(GEN7_MI_PREDICATE |
     85              load_op |
     86              MI_PREDICATE_COMBINEOP_SET |
     87              MI_PREDICATE_COMPAREOP_SRCS_EQUAL);
     88    ADVANCE_BATCH();
     89 
     90    brw->predicate.state = BRW_PREDICATE_STATE_USE_BIT;
     91 }
     92 
     93 static void
     94 brw_begin_conditional_render(struct gl_context *ctx,
     95                              struct gl_query_object *q,
     96                              GLenum mode)
     97 {
     98    struct brw_context *brw = brw_context(ctx);
     99    struct brw_query_object *query = (struct brw_query_object *) q;
    100    bool inverted;
    101 
    102    if (!brw->predicate.supported)
    103       return;
    104 
    105    switch (mode) {
    106    case GL_QUERY_WAIT:
    107    case GL_QUERY_NO_WAIT:
    108    case GL_QUERY_BY_REGION_WAIT:
    109    case GL_QUERY_BY_REGION_NO_WAIT:
    110       inverted = false;
    111       break;
    112    case GL_QUERY_WAIT_INVERTED:
    113    case GL_QUERY_NO_WAIT_INVERTED:
    114    case GL_QUERY_BY_REGION_WAIT_INVERTED:
    115    case GL_QUERY_BY_REGION_NO_WAIT_INVERTED:
    116       inverted = true;
    117       break;
    118    default:
    119       unreachable("Unexpected conditional render mode");
    120    }
    121 
    122    /* If there are already samples from a BLT operation or if the query object
    123     * is ready then we can avoid looking at the values in the buffer and just
    124     * decide whether to draw using the CPU without stalling.
    125     */
    126    if (query->Base.Result || query->Base.Ready)
    127       set_predicate_enable(brw, (query->Base.Result != 0) ^ inverted);
    128    else
    129       set_predicate_for_result(brw, query, inverted);
    130 }
    131 
    132 static void
    133 brw_end_conditional_render(struct gl_context *ctx,
    134                            struct gl_query_object *q)
    135 {
    136    struct brw_context *brw = brw_context(ctx);
    137 
    138    /* When there is no longer a conditional render in progress it should
    139     * always render.
    140     */
    141    brw->predicate.state = BRW_PREDICATE_STATE_RENDER;
    142 }
    143 
    144 void
    145 brw_init_conditional_render_functions(struct dd_function_table *functions)
    146 {
    147    functions->BeginConditionalRender = brw_begin_conditional_render;
    148    functions->EndConditionalRender = brw_end_conditional_render;
    149 }
    150 
    151 bool
    152 brw_check_conditional_render(struct brw_context *brw)
    153 {
    154    if (brw->predicate.supported) {
    155       /* In some cases it is possible to determine that the primitives should
    156        * be skipped without needing the predicate enable bit and still without
    157        * stalling.
    158        */
    159       return brw->predicate.state != BRW_PREDICATE_STATE_DONT_RENDER;
    160    } else if (brw->ctx.Query.CondRenderQuery) {
    161       perf_debug("Conditional rendering is implemented in software and may "
    162                  "stall.\n");
    163       return _mesa_check_conditional_render(&brw->ctx);
    164    } else {
    165       return true;
    166    }
    167 }
    168