OSDN Git Service

ilo: reset SO write offsets for new SO targets
[android-x86/external-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    const bool so_enabled = (ilo->stream_output_targets.num_targets > 0);
223    bool success;
224
225    if (ilo->dirty & ILO_DIRTY_STREAM_OUTPUT_TARGETS &&
226        so_enabled && !ilo->stream_output_targets.append_bitmask) {
227       /*
228        * We keep track of the SVBI in the driver, so that we can restore it
229        * when the HW context is invalidated (by another process).  The value
230        * needs to be reset when stream output is enabled and the targets are
231        * changed.
232        */
233       p->state.so_num_vertices = 0;
234
235       /* on GEN7+, we need SOL_RESET to reset the SO write offsets */
236       if (p->dev->gen >= ILO_GEN(7))
237          ilo_cp_set_one_off_flags(p->cp, INTEL_EXEC_GEN7_SOL_RESET);
238    }
239
240
241    while (true) {
242       struct ilo_cp_jmp_buf jmp;
243       int err;
244
245       /* we will rewind if aperture check below fails */
246       ilo_cp_setjmp(p->cp, &jmp);
247
248       handle_invalid_batch_bo(p, false);
249
250       /* draw! */
251       ilo_cp_assert_no_implicit_flush(p->cp, true);
252       p->emit_draw(p, ilo, info);
253       ilo_cp_assert_no_implicit_flush(p->cp, false);
254
255       err = ilo->winsys->check_aperture_space(ilo->winsys, &p->cp->bo, 1);
256       if (!err) {
257          success = true;
258          break;
259       }
260
261       /* rewind */
262       ilo_cp_longjmp(p->cp, &jmp);
263
264       if (ilo_cp_empty(p->cp)) {
265          success = false;
266          break;
267       }
268       else {
269          /* flush and try again */
270          ilo_cp_flush(p->cp);
271       }
272    }
273
274    if (success) {
275       const int num_verts = u_vertices_per_prim(u_reduced_prim(info->mode));
276       const int max_emit =
277          (p->state.so_max_vertices - p->state.so_num_vertices) / num_verts;
278       const int generated = prim_count(info->mode, info->count);
279       const int emitted = MIN2(generated, max_emit);
280
281       p->state.so_num_vertices += emitted * num_verts;
282
283       if (prim_generated)
284          *prim_generated = generated;
285
286       if (prim_emitted)
287          *prim_emitted = emitted;
288    }
289
290    p->invalidate_flags = 0x0;
291
292    return success;
293 }
294
295 /**
296  * Emit PIPE_CONTROL to flush all caches.
297  */
298 void
299 ilo_3d_pipeline_emit_flush(struct ilo_3d_pipeline *p)
300 {
301    handle_invalid_batch_bo(p, true);
302    p->emit_flush(p);
303 }
304
305 /**
306  * Emit PIPE_CONTROL with PIPE_CONTROL_WRITE_TIMESTAMP post-sync op.
307  */
308 void
309 ilo_3d_pipeline_emit_write_timestamp(struct ilo_3d_pipeline *p,
310                                      struct intel_bo *bo, int index)
311 {
312    handle_invalid_batch_bo(p, true);
313    p->emit_write_timestamp(p, bo, index);
314 }
315
316 /**
317  * Emit PIPE_CONTROL with PIPE_CONTROL_WRITE_DEPTH_COUNT post-sync op.
318  */
319 void
320 ilo_3d_pipeline_emit_write_depth_count(struct ilo_3d_pipeline *p,
321                                        struct intel_bo *bo, int index)
322 {
323    handle_invalid_batch_bo(p, true);
324    p->emit_write_depth_count(p, bo, index);
325 }
326
327 void
328 ilo_3d_pipeline_get_sample_position(struct ilo_3d_pipeline *p,
329                                     unsigned sample_count,
330                                     unsigned sample_index,
331                                     float *x, float *y)
332 {
333    const struct sample_position *pos;
334
335    switch (sample_count) {
336    case 1:
337       assert(sample_index < Elements(sample_position_1x));
338       pos = sample_position_1x;
339       break;
340    case 4:
341       assert(sample_index < Elements(sample_position_4x));
342       pos = sample_position_4x;
343       break;
344    case 8:
345       assert(sample_index < Elements(sample_position_8x));
346       pos = sample_position_8x;
347       break;
348    default:
349       assert(!"unknown sample count");
350       *x = 0.5f;
351       *y = 0.5f;
352       return;
353       break;
354    }
355
356    *x = (float) pos[sample_index].x / 16.0f;
357    *y = (float) pos[sample_index].y / 16.0f;
358 }