ilo: use ilo_dev_info in GPE and 3D pipeline
[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_context.h"
32 #include "ilo_cp.h"
33 #include "ilo_state.h"
34 #include "ilo_3d_pipeline_gen6.h"
35 #include "ilo_3d_pipeline_gen7.h"
36 #include "ilo_3d_pipeline.h"
37
38 /* in U0.4 */
39 struct sample_position {
40 uint8_t x, y;
41 };
42
43 /* \see gen6_get_sample_position() */
44 static const struct sample_position sample_position_1x[1] = {
45 { 8, 8 },
46 };
47
48 static const struct sample_position sample_position_4x[4] = {
49 { 6, 2 }, /* distance from the center is sqrt(40) */
50 { 14, 6 }, /* distance from the center is sqrt(40) */
51 { 2, 10 }, /* distance from the center is sqrt(40) */
52 { 10, 14 }, /* distance from the center is sqrt(40) */
53 };
54
55 static const struct sample_position sample_position_8x[8] = {
56 { 7, 9 }, /* distance from the center is sqrt(2) */
57 { 9, 13 }, /* distance from the center is sqrt(26) */
58 { 11, 3 }, /* distance from the center is sqrt(34) */
59 { 13, 11 }, /* distance from the center is sqrt(34) */
60 { 1, 7 }, /* distance from the center is sqrt(50) */
61 { 5, 1 }, /* distance from the center is sqrt(58) */
62 { 15, 5 }, /* distance from the center is sqrt(58) */
63 { 3, 15 }, /* distance from the center is sqrt(74) */
64 };
65
66 struct ilo_3d_pipeline *
67 ilo_3d_pipeline_create(struct ilo_cp *cp, const struct ilo_dev_info *dev)
68 {
69 struct ilo_3d_pipeline *p;
70 int i;
71
72 p = CALLOC_STRUCT(ilo_3d_pipeline);
73 if (!p)
74 return NULL;
75
76 p->cp = cp;
77 p->dev = dev;
78
79 switch (p->dev->gen) {
80 case ILO_GEN(6):
81 ilo_3d_pipeline_init_gen6(p);
82 break;
83 case ILO_GEN(7):
84 ilo_3d_pipeline_init_gen7(p);
85 break;
86 default:
87 assert(!"unsupported GEN");
88 FREE(p);
89 return NULL;
90 break;
91 }
92
93 p->invalidate_flags = ILO_3D_PIPELINE_INVALIDATE_ALL;
94
95 p->workaround_bo = p->cp->winsys->alloc_buffer(p->cp->winsys,
96 "PIPE_CONTROL workaround", 4096, 0);
97 if (!p->workaround_bo) {
98 ilo_warn("failed to allocate PIPE_CONTROL workaround bo\n");
99 FREE(p);
100 return NULL;
101 }
102
103 p->packed_sample_position_1x =
104 sample_position_1x[0].x << 4 |
105 sample_position_1x[0].y;
106
107 /* pack into dwords */
108 for (i = 0; i < 4; i++) {
109 p->packed_sample_position_4x |=
110 sample_position_4x[i].x << (8 * i + 4) |
111 sample_position_4x[i].y << (8 * i);
112
113 p->packed_sample_position_8x[0] |=
114 sample_position_8x[i].x << (8 * i + 4) |
115 sample_position_8x[i].y << (8 * i);
116
117 p->packed_sample_position_8x[1] |=
118 sample_position_8x[4 + i].x << (8 * i + 4) |
119 sample_position_8x[4 + i].y << (8 * i);
120 }
121
122 return p;
123 }
124
125 void
126 ilo_3d_pipeline_destroy(struct ilo_3d_pipeline *p)
127 {
128 if (p->workaround_bo)
129 p->workaround_bo->unreference(p->workaround_bo);
130
131 FREE(p);
132 }
133
134 static void
135 handle_invalid_batch_bo(struct ilo_3d_pipeline *p, bool unset)
136 {
137 if (p->invalidate_flags & ILO_3D_PIPELINE_INVALIDATE_BATCH_BO) {
138 if (p->dev->gen == ILO_GEN(6))
139 p->state.has_gen6_wa_pipe_control = false;
140
141 if (unset)
142 p->invalidate_flags &= ~ILO_3D_PIPELINE_INVALIDATE_BATCH_BO;
143 }
144 }
145
146 /* XXX move to u_prim.h */
147 static unsigned
148 prim_count(unsigned prim, unsigned num_verts)
149 {
150 unsigned num_prims;
151
152 u_trim_pipe_prim(prim, &num_verts);
153
154 switch (prim) {
155 case PIPE_PRIM_POINTS:
156 num_prims = num_verts;
157 break;
158 case PIPE_PRIM_LINES:
159 num_prims = num_verts / 2;
160 break;
161 case PIPE_PRIM_LINE_LOOP:
162 num_prims = num_verts;
163 break;
164 case PIPE_PRIM_LINE_STRIP:
165 num_prims = num_verts - 1;
166 break;
167 case PIPE_PRIM_TRIANGLES:
168 num_prims = num_verts / 3;
169 break;
170 case PIPE_PRIM_TRIANGLE_STRIP:
171 case PIPE_PRIM_TRIANGLE_FAN:
172 num_prims = num_verts - 2;
173 break;
174 case PIPE_PRIM_QUADS:
175 num_prims = (num_verts / 4) * 2;
176 break;
177 case PIPE_PRIM_QUAD_STRIP:
178 num_prims = (num_verts / 2 - 1) * 2;
179 break;
180 case PIPE_PRIM_POLYGON:
181 num_prims = num_verts - 2;
182 break;
183 case PIPE_PRIM_LINES_ADJACENCY:
184 num_prims = num_verts / 4;
185 break;
186 case PIPE_PRIM_LINE_STRIP_ADJACENCY:
187 num_prims = num_verts - 3;
188 break;
189 case PIPE_PRIM_TRIANGLES_ADJACENCY:
190 /* u_trim_pipe_prim is wrong? */
191 num_verts += 1;
192
193 num_prims = num_verts / 6;
194 break;
195 case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
196 /* u_trim_pipe_prim is wrong? */
197 if (num_verts >= 6)
198 num_verts -= (num_verts % 2);
199 else
200 num_verts = 0;
201
202 num_prims = (num_verts / 2 - 2);
203 break;
204 default:
205 assert(!"unknown pipe prim");
206 num_prims = 0;
207 break;
208 }
209
210 return num_prims;
211 }
212
213 /**
214 * Emit context states and 3DPRIMITIVE.
215 */
216 bool
217 ilo_3d_pipeline_emit_draw(struct ilo_3d_pipeline *p,
218 const struct ilo_context *ilo,
219 const struct pipe_draw_info *info,
220 int *prim_generated, int *prim_emitted)
221 {
222 bool success;
223
224 /*
225 * We keep track of the SVBI in the driver, so that we can restore it when
226 * the HW context is invalidated (by another process). The value needs to
227 * be reset when the stream output targets are changed.
228 */
229 if (ilo->dirty & ILO_DIRTY_STREAM_OUTPUT_TARGETS)
230 p->state.so_num_vertices = 0;
231
232 while (true) {
233 struct ilo_cp_jmp_buf jmp;
234 int err;
235
236 /* we will rewind if aperture check below fails */
237 ilo_cp_setjmp(p->cp, &jmp);
238
239 handle_invalid_batch_bo(p, false);
240
241 /* draw! */
242 ilo_cp_assert_no_implicit_flush(p->cp, true);
243 p->emit_draw(p, ilo, info);
244 ilo_cp_assert_no_implicit_flush(p->cp, false);
245
246 err = ilo->winsys->check_aperture_space(ilo->winsys, &p->cp->bo, 1);
247 if (!err) {
248 success = true;
249 break;
250 }
251
252 /* rewind */
253 ilo_cp_longjmp(p->cp, &jmp);
254
255 if (ilo_cp_empty(p->cp)) {
256 success = false;
257 break;
258 }
259 else {
260 /* flush and try again */
261 ilo_cp_flush(p->cp);
262 }
263 }
264
265 if (success) {
266 const int num_verts = u_vertices_per_prim(u_reduced_prim(info->mode));
267 const int max_emit =
268 (p->state.so_max_vertices - p->state.so_num_vertices) / num_verts;
269 const int generated = prim_count(info->mode, info->count);
270 const int emitted = MIN2(generated, max_emit);
271
272 p->state.so_num_vertices += emitted * num_verts;
273
274 if (prim_generated)
275 *prim_generated = generated;
276
277 if (prim_emitted)
278 *prim_emitted = emitted;
279 }
280
281 p->invalidate_flags = 0x0;
282
283 return success;
284 }
285
286 /**
287 * Emit PIPE_CONTROL to flush all caches.
288 */
289 void
290 ilo_3d_pipeline_emit_flush(struct ilo_3d_pipeline *p)
291 {
292 handle_invalid_batch_bo(p, true);
293 p->emit_flush(p);
294 }
295
296 /**
297 * Emit PIPE_CONTROL with PIPE_CONTROL_WRITE_TIMESTAMP post-sync op.
298 */
299 void
300 ilo_3d_pipeline_emit_write_timestamp(struct ilo_3d_pipeline *p,
301 struct intel_bo *bo, int index)
302 {
303 handle_invalid_batch_bo(p, true);
304 p->emit_write_timestamp(p, bo, index);
305 }
306
307 /**
308 * Emit PIPE_CONTROL with PIPE_CONTROL_WRITE_DEPTH_COUNT post-sync op.
309 */
310 void
311 ilo_3d_pipeline_emit_write_depth_count(struct ilo_3d_pipeline *p,
312 struct intel_bo *bo, int index)
313 {
314 handle_invalid_batch_bo(p, true);
315 p->emit_write_depth_count(p, bo, index);
316 }
317
318 void
319 ilo_3d_pipeline_get_sample_position(struct ilo_3d_pipeline *p,
320 unsigned sample_count,
321 unsigned sample_index,
322 float *x, float *y)
323 {
324 const struct sample_position *pos;
325
326 switch (sample_count) {
327 case 1:
328 assert(sample_index < Elements(sample_position_1x));
329 pos = sample_position_1x;
330 break;
331 case 4:
332 assert(sample_index < Elements(sample_position_4x));
333 pos = sample_position_4x;
334 break;
335 case 8:
336 assert(sample_index < Elements(sample_position_8x));
337 pos = sample_position_8x;
338 break;
339 default:
340 assert(!"unknown sample count");
341 *x = 0.5f;
342 *y = 0.5f;
343 return;
344 break;
345 }
346
347 *x = (float) pos[sample_index].x / 16.0f;
348 *y = (float) pos[sample_index].y / 16.0f;
349 }