ilo: avoid brw_wm_barycentric_interp_mode in compiler
[mesa.git] / src / gallium / drivers / ilo / ilo_3d_pipeline.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2013 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
26 */
27
28 #include "util/u_prim.h"
29 #include "intel_winsys.h"
30
31 #include "ilo_blitter.h"
32 #include "ilo_context.h"
33 #include "ilo_cp.h"
34 #include "ilo_state.h"
35 #include "ilo_3d_pipeline_gen6.h"
36 #include "ilo_3d_pipeline_gen7.h"
37 #include "ilo_3d_pipeline.h"
38
39 /* in U0.4 */
40 struct sample_position {
41 uint8_t x, y;
42 };
43
44 /* \see gen6_get_sample_position() */
45 static const struct sample_position sample_position_1x[1] = {
46 { 8, 8 },
47 };
48
49 static const struct sample_position sample_position_4x[4] = {
50 { 6, 2 }, /* distance from the center is sqrt(40) */
51 { 14, 6 }, /* distance from the center is sqrt(40) */
52 { 2, 10 }, /* distance from the center is sqrt(40) */
53 { 10, 14 }, /* distance from the center is sqrt(40) */
54 };
55
56 static const struct sample_position sample_position_8x[8] = {
57 { 7, 9 }, /* distance from the center is sqrt(2) */
58 { 9, 13 }, /* distance from the center is sqrt(26) */
59 { 11, 3 }, /* distance from the center is sqrt(34) */
60 { 13, 11 }, /* distance from the center is sqrt(34) */
61 { 1, 7 }, /* distance from the center is sqrt(50) */
62 { 5, 1 }, /* distance from the center is sqrt(58) */
63 { 15, 5 }, /* distance from the center is sqrt(58) */
64 { 3, 15 }, /* distance from the center is sqrt(74) */
65 };
66
67 struct ilo_3d_pipeline *
68 ilo_3d_pipeline_create(struct ilo_cp *cp, const struct ilo_dev_info *dev)
69 {
70 struct ilo_3d_pipeline *p;
71 int i;
72
73 p = CALLOC_STRUCT(ilo_3d_pipeline);
74 if (!p)
75 return NULL;
76
77 p->cp = cp;
78 p->dev = dev;
79
80 switch (p->dev->gen) {
81 case ILO_GEN(6):
82 ilo_3d_pipeline_init_gen6(p);
83 break;
84 case ILO_GEN(7):
85 case ILO_GEN(7.5):
86 ilo_3d_pipeline_init_gen7(p);
87 break;
88 default:
89 assert(!"unsupported GEN");
90 FREE(p);
91 return NULL;
92 break;
93 }
94
95 p->invalidate_flags = ILO_3D_PIPELINE_INVALIDATE_ALL;
96
97 p->workaround_bo = intel_winsys_alloc_buffer(p->cp->winsys,
98 "PIPE_CONTROL workaround", 4096, INTEL_DOMAIN_INSTRUCTION);
99 if (!p->workaround_bo) {
100 ilo_warn("failed to allocate PIPE_CONTROL workaround bo\n");
101 FREE(p);
102 return NULL;
103 }
104
105 p->packed_sample_position_1x =
106 sample_position_1x[0].x << 4 |
107 sample_position_1x[0].y;
108
109 /* pack into dwords */
110 for (i = 0; i < 4; i++) {
111 p->packed_sample_position_4x |=
112 sample_position_4x[i].x << (8 * i + 4) |
113 sample_position_4x[i].y << (8 * i);
114
115 p->packed_sample_position_8x[0] |=
116 sample_position_8x[i].x << (8 * i + 4) |
117 sample_position_8x[i].y << (8 * i);
118
119 p->packed_sample_position_8x[1] |=
120 sample_position_8x[4 + i].x << (8 * i + 4) |
121 sample_position_8x[4 + i].y << (8 * i);
122 }
123
124 return p;
125 }
126
127 void
128 ilo_3d_pipeline_destroy(struct ilo_3d_pipeline *p)
129 {
130 if (p->workaround_bo)
131 intel_bo_unreference(p->workaround_bo);
132
133 FREE(p);
134 }
135
136 static void
137 handle_invalid_batch_bo(struct ilo_3d_pipeline *p, bool unset)
138 {
139 if (p->invalidate_flags & ILO_3D_PIPELINE_INVALIDATE_BATCH_BO) {
140 if (p->dev->gen == ILO_GEN(6))
141 p->state.has_gen6_wa_pipe_control = false;
142
143 if (unset)
144 p->invalidate_flags &= ~ILO_3D_PIPELINE_INVALIDATE_BATCH_BO;
145 }
146 }
147
148 /**
149 * Emit context states and 3DPRIMITIVE.
150 */
151 bool
152 ilo_3d_pipeline_emit_draw(struct ilo_3d_pipeline *p,
153 const struct ilo_context *ilo,
154 int *prim_generated, int *prim_emitted)
155 {
156 bool success;
157
158 if (ilo->dirty & ILO_DIRTY_SO &&
159 ilo->so.enabled && !ilo->so.append_bitmask) {
160 /*
161 * We keep track of the SVBI in the driver, so that we can restore it
162 * when the HW context is invalidated (by another process). The value
163 * needs to be reset when stream output is enabled and the targets are
164 * changed.
165 */
166 p->state.so_num_vertices = 0;
167
168 /* on GEN7+, we need SOL_RESET to reset the SO write offsets */
169 if (p->dev->gen >= ILO_GEN(7))
170 ilo_cp_set_one_off_flags(p->cp, INTEL_EXEC_GEN7_SOL_RESET);
171 }
172
173
174 while (true) {
175 struct ilo_cp_jmp_buf jmp;
176
177 /* we will rewind if aperture check below fails */
178 ilo_cp_setjmp(p->cp, &jmp);
179
180 handle_invalid_batch_bo(p, false);
181
182 /* draw! */
183 ilo_cp_assert_no_implicit_flush(p->cp, true);
184 p->emit_draw(p, ilo);
185 ilo_cp_assert_no_implicit_flush(p->cp, false);
186
187 if (intel_winsys_can_submit_bo(ilo->winsys, &p->cp->bo, 1)) {
188 success = true;
189 break;
190 }
191
192 /* rewind */
193 ilo_cp_longjmp(p->cp, &jmp);
194
195 if (ilo_cp_empty(p->cp)) {
196 success = false;
197 break;
198 }
199 else {
200 /* flush and try again */
201 ilo_cp_flush(p->cp, "out of aperture");
202 }
203 }
204
205 if (success) {
206 const int num_verts =
207 u_vertices_per_prim(u_reduced_prim(ilo->draw->mode));
208 const int max_emit =
209 (p->state.so_max_vertices - p->state.so_num_vertices) / num_verts;
210 const int generated =
211 u_reduced_prims_for_vertices(ilo->draw->mode, ilo->draw->count);
212 const int emitted = MIN2(generated, max_emit);
213
214 p->state.so_num_vertices += emitted * num_verts;
215
216 if (prim_generated)
217 *prim_generated = generated;
218
219 if (prim_emitted)
220 *prim_emitted = emitted;
221 }
222
223 p->invalidate_flags = 0x0;
224
225 return success;
226 }
227
228 /**
229 * Emit PIPE_CONTROL to flush all caches.
230 */
231 void
232 ilo_3d_pipeline_emit_flush(struct ilo_3d_pipeline *p)
233 {
234 handle_invalid_batch_bo(p, true);
235 p->emit_flush(p);
236 }
237
238 /**
239 * Emit PIPE_CONTROL with PIPE_CONTROL_WRITE_TIMESTAMP post-sync op.
240 */
241 void
242 ilo_3d_pipeline_emit_write_timestamp(struct ilo_3d_pipeline *p,
243 struct intel_bo *bo, int index)
244 {
245 handle_invalid_batch_bo(p, true);
246 p->emit_write_timestamp(p, bo, index);
247 }
248
249 /**
250 * Emit PIPE_CONTROL with PIPE_CONTROL_WRITE_DEPTH_COUNT post-sync op.
251 */
252 void
253 ilo_3d_pipeline_emit_write_depth_count(struct ilo_3d_pipeline *p,
254 struct intel_bo *bo, int index)
255 {
256 handle_invalid_batch_bo(p, true);
257 p->emit_write_depth_count(p, bo, index);
258 }
259
260 /**
261 * Emit MI_STORE_REGISTER_MEM to store statistics registers.
262 */
263 void
264 ilo_3d_pipeline_emit_write_statistics(struct ilo_3d_pipeline *p,
265 struct intel_bo *bo, int index)
266 {
267 handle_invalid_batch_bo(p, true);
268 p->emit_write_statistics(p, bo, index);
269 }
270
271 void
272 ilo_3d_pipeline_emit_rectlist(struct ilo_3d_pipeline *p,
273 const struct ilo_blitter *blitter)
274 {
275 const int max_len = ilo_3d_pipeline_estimate_size(p,
276 ILO_3D_PIPELINE_RECTLIST, blitter);
277
278 if (max_len > ilo_cp_space(p->cp))
279 ilo_cp_flush(p->cp, "out of space");
280
281 while (true) {
282 struct ilo_cp_jmp_buf jmp;
283
284 /* we will rewind if aperture check below fails */
285 ilo_cp_setjmp(p->cp, &jmp);
286
287 handle_invalid_batch_bo(p, false);
288
289 ilo_cp_assert_no_implicit_flush(p->cp, true);
290 p->emit_rectlist(p, blitter);
291 ilo_cp_assert_no_implicit_flush(p->cp, false);
292
293 if (!intel_winsys_can_submit_bo(blitter->ilo->winsys, &p->cp->bo, 1)) {
294 /* rewind */
295 ilo_cp_longjmp(p->cp, &jmp);
296
297 /* flush and try again */
298 if (!ilo_cp_empty(p->cp)) {
299 ilo_cp_flush(p->cp, "out of aperture");
300 continue;
301 }
302 }
303
304 break;
305 }
306
307 ilo_3d_pipeline_invalidate(p, ILO_3D_PIPELINE_INVALIDATE_HW);
308 }
309
310 void
311 ilo_3d_pipeline_get_sample_position(struct ilo_3d_pipeline *p,
312 unsigned sample_count,
313 unsigned sample_index,
314 float *x, float *y)
315 {
316 const struct sample_position *pos;
317
318 switch (sample_count) {
319 case 1:
320 assert(sample_index < Elements(sample_position_1x));
321 pos = sample_position_1x;
322 break;
323 case 4:
324 assert(sample_index < Elements(sample_position_4x));
325 pos = sample_position_4x;
326 break;
327 case 8:
328 assert(sample_index < Elements(sample_position_8x));
329 pos = sample_position_8x;
330 break;
331 default:
332 assert(!"unknown sample count");
333 *x = 0.5f;
334 *y = 0.5f;
335 return;
336 break;
337 }
338
339 *x = (float) pos[sample_index].x / 16.0f;
340 *y = (float) pos[sample_index].y / 16.0f;
341 }