• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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
set_predicate_enable(struct brw_context * brw,bool value)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
set_predicate_for_result(struct brw_context * brw,struct brw_query_object * query,bool inverted)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
brw_begin_conditional_render(struct gl_context * ctx,struct gl_query_object * q,GLenum mode)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
brw_end_conditional_render(struct gl_context * ctx,struct gl_query_object * q)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
brw_init_conditional_render_functions(struct dd_function_table * functions)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
brw_check_conditional_render(struct brw_context * brw)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