ilo: preliminary GEN 7.5 support
[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 case ILO_GEN(7.5):
85 ilo_3d_pipeline_init_gen7(p);
86 break;
87 default:
88 assert(!"unsupported GEN");
89 FREE(p);
90 return NULL;
91 break;
92 }
93
94 p->invalidate_flags = ILO_3D_PIPELINE_INVALIDATE_ALL;
95
96 p->workaround_bo = intel_winsys_alloc_buffer(p->cp->winsys,
97 "PIPE_CONTROL workaround", 4096, 0);
98 if (!p->workaround_bo) {
99 ilo_warn("failed to allocate PIPE_CONTROL workaround bo\n");
100 FREE(p);
101 return NULL;
102 }
103
104 p->packed_sample_position_1x =
105 sample_position_1x[0].x << 4 |
106 sample_position_1x[0].y;
107
108 /* pack into dwords */
109 for (i = 0; i < 4; i++) {
110 p->packed_sample_position_4x |=
111 sample_position_4x[i].x << (8 * i + 4) |
112 sample_position_4x[i].y << (8 * i);
113
114 p->packed_sample_position_8x[0] |=
115 sample_position_8x[i].x << (8 * i + 4) |
116 sample_position_8x[i].y << (8 * i);
117
118 p->packed_sample_position_8x[1] |=
119 sample_position_8x[4 + i].x << (8 * i + 4) |
120 sample_position_8x[4 + i].y << (8 * i);
121 }
122
123 return p;
124 }
125
126 void
127 ilo_3d_pipeline_destroy(struct ilo_3d_pipeline *p)
128 {
129 if (p->workaround_bo)
130 intel_bo_unreference(p->workaround_bo);
131
132 FREE(p);
133 }
134
135 static void
136 handle_invalid_batch_bo(struct ilo_3d_pipeline *p, bool unset)
137 {
138 if (p->invalidate_flags & ILO_3D_PIPELINE_INVALIDATE_BATCH_BO) {
139 if (p->dev->gen == ILO_GEN(6))
140 p->state.has_gen6_wa_pipe_control = false;
141
142 if (unset)
143 p->invalidate_flags &= ~ILO_3D_PIPELINE_INVALIDATE_BATCH_BO;
144 }
145 }
146
147 /**
148 * Emit context states and 3DPRIMITIVE.
149 */
150 bool
151 ilo_3d_pipeline_emit_draw(struct ilo_3d_pipeline *p,
152 const struct ilo_context *ilo,
153 int *prim_generated, int *prim_emitted)
154 {
155 bool success;
156
157 if (ilo->dirty & ILO_DIRTY_SO &&
158 ilo->so.enabled && !ilo->so.append_bitmask) {
159 /*
160 * We keep track of the SVBI in the driver, so that we can restore it
161 * when the HW context is invalidated (by another process). The value
162 * needs to be reset when stream output is enabled and the targets are
163 * changed.
164 */
165 p->state.so_num_vertices = 0;
166
167 /* on GEN7+, we need SOL_RESET to reset the SO write offsets */
168 if (p->dev->gen >= ILO_GEN(7))
169 ilo_cp_set_one_off_flags(p->cp, INTEL_EXEC_GEN7_SOL_RESET);
170 }
171
172
173 while (true) {
174 struct ilo_cp_jmp_buf jmp;
175 int err;
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 err = intel_winsys_check_aperture_space(ilo->winsys, &p->cp->bo, 1);
188 if (!err) {
189 success = true;
190 break;
191 }
192
193 /* rewind */
194 ilo_cp_longjmp(p->cp, &jmp);
195
196 if (ilo_cp_empty(p->cp)) {
197 success = false;
198 break;
199 }
200 else {
201 /* flush and try again */
202 ilo_cp_flush(p->cp, "out of aperture");
203 }
204 }
205
206 if (success) {
207 const int num_verts =
208 u_vertices_per_prim(u_reduced_prim(ilo->draw->mode));
209 const int max_emit =
210 (p->state.so_max_vertices - p->state.so_num_vertices) / num_verts;
211 const int generated =
212 u_reduced_prims_for_vertices(ilo->draw->mode, ilo->draw->count);
213 const int emitted = MIN2(generated, max_emit);
214
215 p->state.so_num_vertices += emitted * num_verts;
216
217 if (prim_generated)
218 *prim_generated = generated;
219
220 if (prim_emitted)
221 *prim_emitted = emitted;
222 }
223
224 p->invalidate_flags = 0x0;
225
226 return success;
227 }
228
229 /**
230 * Emit PIPE_CONTROL to flush all caches.
231 */
232 void
233 ilo_3d_pipeline_emit_flush(struct ilo_3d_pipeline *p)
234 {
235 handle_invalid_batch_bo(p, true);
236 p->emit_flush(p);
237 }
238
239 /**
240 * Emit PIPE_CONTROL with PIPE_CONTROL_WRITE_TIMESTAMP post-sync op.
241 */
242 void
243 ilo_3d_pipeline_emit_write_timestamp(struct ilo_3d_pipeline *p,
244 struct intel_bo *bo, int index)
245 {
246 handle_invalid_batch_bo(p, true);
247 p->emit_write_timestamp(p, bo, index);
248 }
249
250 /**
251 * Emit PIPE_CONTROL with PIPE_CONTROL_WRITE_DEPTH_COUNT post-sync op.
252 */
253 void
254 ilo_3d_pipeline_emit_write_depth_count(struct ilo_3d_pipeline *p,
255 struct intel_bo *bo, int index)
256 {
257 handle_invalid_batch_bo(p, true);
258 p->emit_write_depth_count(p, bo, index);
259 }
260
261 void
262 ilo_3d_pipeline_get_sample_position(struct ilo_3d_pipeline *p,
263 unsigned sample_count,
264 unsigned sample_index,
265 float *x, float *y)
266 {
267 const struct sample_position *pos;
268
269 switch (sample_count) {
270 case 1:
271 assert(sample_index < Elements(sample_position_1x));
272 pos = sample_position_1x;
273 break;
274 case 4:
275 assert(sample_index < Elements(sample_position_4x));
276 pos = sample_position_4x;
277 break;
278 case 8:
279 assert(sample_index < Elements(sample_position_8x));
280 pos = sample_position_8x;
281 break;
282 default:
283 assert(!"unknown sample count");
284 *x = 0.5f;
285 *y = 0.5f;
286 return;
287 break;
288 }
289
290 *x = (float) pos[sample_index].x / 16.0f;
291 *y = (float) pos[sample_index].y / 16.0f;
292 }