i965: Fix PBO cache coherency issue after _mesa_meta_pbo_GetTexSubImage().
[mesa.git] / src / mesa / drivers / dri / i965 / brw_conditional_render.c
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
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 brw_load_register_mem64(brw,
60 MI_PREDICATE_SRC0,
61 query->bo,
62 I915_GEM_DOMAIN_INSTRUCTION,
63 0, /* write domain */
64 0 /* offset */);
65 brw_load_register_mem64(brw,
66 MI_PREDICATE_SRC1,
67 query->bo,
68 I915_GEM_DOMAIN_INSTRUCTION,
69 0, /* write domain */
70 8 /* offset */);
71
72 if (inverted)
73 load_op = MI_PREDICATE_LOADOP_LOAD;
74 else
75 load_op = MI_PREDICATE_LOADOP_LOADINV;
76
77 BEGIN_BATCH(1);
78 OUT_BATCH(GEN7_MI_PREDICATE |
79 load_op |
80 MI_PREDICATE_COMBINEOP_SET |
81 MI_PREDICATE_COMPAREOP_SRCS_EQUAL);
82 ADVANCE_BATCH();
83
84 brw->predicate.state = BRW_PREDICATE_STATE_USE_BIT;
85 }
86
87 static void
88 brw_begin_conditional_render(struct gl_context *ctx,
89 struct gl_query_object *q,
90 GLenum mode)
91 {
92 struct brw_context *brw = brw_context(ctx);
93 struct brw_query_object *query = (struct brw_query_object *) q;
94 bool inverted;
95
96 if (!brw->predicate.supported)
97 return;
98
99 switch (mode) {
100 case GL_QUERY_WAIT:
101 case GL_QUERY_NO_WAIT:
102 case GL_QUERY_BY_REGION_WAIT:
103 case GL_QUERY_BY_REGION_NO_WAIT:
104 inverted = false;
105 break;
106 case GL_QUERY_WAIT_INVERTED:
107 case GL_QUERY_NO_WAIT_INVERTED:
108 case GL_QUERY_BY_REGION_WAIT_INVERTED:
109 case GL_QUERY_BY_REGION_NO_WAIT_INVERTED:
110 inverted = true;
111 break;
112 default:
113 unreachable("Unexpected conditional render mode");
114 }
115
116 /* If there are already samples from a BLT operation or if the query object
117 * is ready then we can avoid looking at the values in the buffer and just
118 * decide whether to draw using the CPU without stalling.
119 */
120 if (query->Base.Result || query->Base.Ready)
121 set_predicate_enable(brw, (query->Base.Result != 0) ^ inverted);
122 else
123 set_predicate_for_result(brw, query, inverted);
124 }
125
126 static void
127 brw_end_conditional_render(struct gl_context *ctx,
128 struct gl_query_object *q)
129 {
130 struct brw_context *brw = brw_context(ctx);
131
132 /* When there is no longer a conditional render in progress it should
133 * always render.
134 */
135 brw->predicate.state = BRW_PREDICATE_STATE_RENDER;
136 }
137
138 void
139 brw_init_conditional_render_functions(struct dd_function_table *functions)
140 {
141 functions->BeginConditionalRender = brw_begin_conditional_render;
142 functions->EndConditionalRender = brw_end_conditional_render;
143 }
144
145 bool
146 brw_check_conditional_render(struct brw_context *brw)
147 {
148 if (brw->predicate.supported) {
149 /* In some cases it is possible to determine that the primitives should
150 * be skipped without needing the predicate enable bit and still without
151 * stalling.
152 */
153 return brw->predicate.state != BRW_PREDICATE_STATE_DONT_RENDER;
154 } else if (brw->ctx.Query.CondRenderQuery) {
155 perf_debug("Conditional rendering is implemented in software and may "
156 "stall.\n");
157 return _mesa_check_conditional_render(&brw->ctx);
158 } else {
159 return true;
160 }
161 }