• 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_overflow_query(struct brw_context * brw,struct brw_query_object * query,int stream_start,int count)51 set_predicate_for_overflow_query(struct brw_context *brw,
52                                  struct brw_query_object *query,
53                                  int stream_start, int count)
54 {
55    if (!can_do_mi_math_and_lrr(brw->screen)) {
56       brw->predicate.state = BRW_PREDICATE_STATE_STALL_FOR_QUERY;
57       return;
58    }
59 
60    brw->predicate.state = BRW_PREDICATE_STATE_USE_BIT;
61 
62    /* Needed to ensure the memory is coherent for the MI_LOAD_REGISTER_MEM
63     * command when loading the values into the predicate source registers for
64     * conditional rendering.
65     */
66    brw_emit_pipe_control_flush(brw, PIPE_CONTROL_FLUSH_ENABLE);
67 
68    hsw_overflow_result_to_gpr0(brw, query, count);
69    brw_load_register_reg64(brw, HSW_CS_GPR(0), MI_PREDICATE_SRC0);
70    brw_load_register_imm64(brw, MI_PREDICATE_SRC1, 0ull);
71 }
72 
73 static void
set_predicate_for_occlusion_query(struct brw_context * brw,struct brw_query_object * query)74 set_predicate_for_occlusion_query(struct brw_context *brw,
75                                   struct brw_query_object *query)
76 {
77    if (!brw->predicate.supported) {
78       brw->predicate.state = BRW_PREDICATE_STATE_STALL_FOR_QUERY;
79       return;
80    }
81 
82    brw->predicate.state = BRW_PREDICATE_STATE_USE_BIT;
83 
84    /* Needed to ensure the memory is coherent for the MI_LOAD_REGISTER_MEM
85     * command when loading the values into the predicate source registers for
86     * conditional rendering.
87     */
88    brw_emit_pipe_control_flush(brw, PIPE_CONTROL_FLUSH_ENABLE);
89 
90    brw_load_register_mem64(brw, MI_PREDICATE_SRC0, query->bo, 0 /* offset */);
91    brw_load_register_mem64(brw, MI_PREDICATE_SRC1, query->bo, 8 /* offset */);
92 }
93 
94 static void
set_predicate_for_result(struct brw_context * brw,struct brw_query_object * query,bool inverted)95 set_predicate_for_result(struct brw_context *brw,
96                          struct brw_query_object *query,
97                          bool inverted)
98 {
99    int load_op;
100 
101    assert(query->bo != NULL);
102 
103    switch (query->Base.Target) {
104    case GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB:
105       set_predicate_for_overflow_query(brw, query, 0, 1);
106       break;
107    case GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB:
108       set_predicate_for_overflow_query(brw, query, 0, MAX_VERTEX_STREAMS);
109       break;
110    default:
111       set_predicate_for_occlusion_query(brw, query);
112    }
113 
114    if (brw->predicate.state == BRW_PREDICATE_STATE_USE_BIT) {
115       if (inverted)
116          load_op = MI_PREDICATE_LOADOP_LOAD;
117       else
118          load_op = MI_PREDICATE_LOADOP_LOADINV;
119 
120       BEGIN_BATCH(1);
121       OUT_BATCH(GEN7_MI_PREDICATE |
122                 load_op |
123                 MI_PREDICATE_COMBINEOP_SET |
124                 MI_PREDICATE_COMPAREOP_SRCS_EQUAL);
125       ADVANCE_BATCH();
126    }
127 }
128 
129 static void
brw_begin_conditional_render(struct gl_context * ctx,struct gl_query_object * q,GLenum mode)130 brw_begin_conditional_render(struct gl_context *ctx,
131                              struct gl_query_object *q,
132                              GLenum mode)
133 {
134    struct brw_context *brw = brw_context(ctx);
135    struct brw_query_object *query = (struct brw_query_object *) q;
136    bool inverted;
137 
138    switch (mode) {
139    case GL_QUERY_WAIT:
140    case GL_QUERY_NO_WAIT:
141    case GL_QUERY_BY_REGION_WAIT:
142    case GL_QUERY_BY_REGION_NO_WAIT:
143       inverted = false;
144       break;
145    case GL_QUERY_WAIT_INVERTED:
146    case GL_QUERY_NO_WAIT_INVERTED:
147    case GL_QUERY_BY_REGION_WAIT_INVERTED:
148    case GL_QUERY_BY_REGION_NO_WAIT_INVERTED:
149       inverted = true;
150       break;
151    default:
152       unreachable("Unexpected conditional render mode");
153    }
154 
155    /* If there are already samples from a BLT operation or if the query object
156     * is ready then we can avoid looking at the values in the buffer and just
157     * decide whether to draw using the CPU without stalling.
158     */
159    if (query->Base.Result || query->Base.Ready)
160       set_predicate_enable(brw, (query->Base.Result != 0) ^ inverted);
161    else
162       set_predicate_for_result(brw, query, inverted);
163 }
164 
165 static void
brw_end_conditional_render(struct gl_context * ctx,struct gl_query_object * q)166 brw_end_conditional_render(struct gl_context *ctx,
167                            struct gl_query_object *q)
168 {
169    struct brw_context *brw = brw_context(ctx);
170 
171    /* When there is no longer a conditional render in progress it should
172     * always render.
173     */
174    brw->predicate.state = BRW_PREDICATE_STATE_RENDER;
175 }
176 
177 void
brw_init_conditional_render_functions(struct dd_function_table * functions)178 brw_init_conditional_render_functions(struct dd_function_table *functions)
179 {
180    functions->BeginConditionalRender = brw_begin_conditional_render;
181    functions->EndConditionalRender = brw_end_conditional_render;
182 }
183 
184 bool
brw_check_conditional_render(struct brw_context * brw)185 brw_check_conditional_render(struct brw_context *brw)
186 {
187    if (brw->predicate.state == BRW_PREDICATE_STATE_STALL_FOR_QUERY) {
188       perf_debug("Conditional rendering is implemented in software and may "
189                  "stall.\n");
190       return _mesa_check_conditional_render(&brw->ctx);
191    }
192 
193    return brw->predicate.state != BRW_PREDICATE_STATE_DONT_RENDER;
194 }
195