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