OSDN Git Service

ilo: add PIPE_QUERY_OCCLUSION_PREDICATE support
[android-x86/external-mesa.git] / src / gallium / drivers / ilo / ilo_render.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 "genhw/genhw.h"
29 #include "core/ilo_builder.h"
30 #include "core/ilo_builder_mi.h"
31 #include "core/ilo_builder_render.h"
32 #include "core/intel_winsys.h"
33 #include "util/u_prim.h"
34
35 #include "ilo_query.h"
36 #include "ilo_render_gen.h"
37
38 struct ilo_render *
39 ilo_render_create(struct ilo_builder *builder)
40 {
41    struct ilo_render *render;
42
43    render = CALLOC_STRUCT(ilo_render);
44    if (!render)
45       return NULL;
46
47    render->dev = builder->dev;
48    render->builder = builder;
49
50    render->workaround_bo = intel_winsys_alloc_bo(builder->winsys,
51          "PIPE_CONTROL workaround", 4096, false);
52    if (!render->workaround_bo) {
53       ilo_warn("failed to allocate PIPE_CONTROL workaround bo\n");
54       FREE(render);
55       return NULL;
56    }
57
58    ilo_state_sample_pattern_init_default(&render->sample_pattern,
59          render->dev);
60
61    ilo_render_invalidate_hw(render);
62    ilo_render_invalidate_builder(render);
63
64    return render;
65 }
66
67 void
68 ilo_render_destroy(struct ilo_render *render)
69 {
70    intel_bo_unref(render->vs_scratch.bo);
71    intel_bo_unref(render->gs_scratch.bo);
72    intel_bo_unref(render->fs_scratch.bo);
73
74    intel_bo_unref(render->workaround_bo);
75    FREE(render);
76 }
77
78 static bool
79 resize_scratch_space(struct ilo_render *render,
80                      struct ilo_render_scratch_space *scratch,
81                      const char *name, int new_size)
82 {
83    struct intel_bo *bo;
84
85    if (scratch->size >= new_size)
86       return true;
87
88    bo = intel_winsys_alloc_bo(render->builder->winsys, name, new_size, false);
89    if (!bo)
90       return false;
91
92    intel_bo_unref(scratch->bo);
93    scratch->bo = bo;
94    scratch->size = new_size;
95
96    return true;
97 }
98
99 bool
100 ilo_render_prepare_scratch_spaces(struct ilo_render *render,
101                                   int vs_scratch_size,
102                                   int gs_scratch_size,
103                                   int fs_scratch_size)
104 {
105    return (resize_scratch_space(render, &render->vs_scratch,
106             "vs scratch", vs_scratch_size) &&
107            resize_scratch_space(render, &render->gs_scratch,
108             "gs scratch", gs_scratch_size) &&
109            resize_scratch_space(render, &render->fs_scratch,
110             "fs scratch", fs_scratch_size));
111 }
112
113 void
114 ilo_render_get_sample_position(const struct ilo_render *render,
115                                unsigned sample_count,
116                                unsigned sample_index,
117                                float *x, float *y)
118 {
119    uint8_t off_x, off_y;
120
121    ilo_state_sample_pattern_get_offset(&render->sample_pattern, render->dev,
122          sample_count, sample_index, &off_x, &off_y);
123
124    *x = (float) off_x / 16.0f;
125    *y = (float) off_y / 16.0f;
126 }
127
128 void
129 ilo_render_invalidate_hw(struct ilo_render *render)
130 {
131    render->hw_ctx_changed = true;
132 }
133
134 void
135 ilo_render_invalidate_builder(struct ilo_render *render)
136 {
137    render->batch_bo_changed = true;
138    render->state_bo_changed = true;
139    render->instruction_bo_changed = true;
140
141    /* Kernel flushes everything.  Shouldn't we set all bits here? */
142    render->state.current_pipe_control_dw1 = 0;
143 }
144
145 /**
146  * Return the command length of ilo_render_emit_flush().
147  */
148 int
149 ilo_render_get_flush_len(const struct ilo_render *render)
150 {
151    int len;
152
153    ILO_DEV_ASSERT(render->dev, 6, 8);
154
155    len = GEN6_PIPE_CONTROL__SIZE;
156
157    /* plus gen6_wa_pre_pipe_control() */
158    if (ilo_dev_gen(render->dev) == ILO_GEN(6))
159       len *= 3;
160
161    return len;
162 }
163
164 /**
165  * Emit PIPE_CONTROLs to flush all caches.
166  */
167 void
168 ilo_render_emit_flush(struct ilo_render *render)
169 {
170    const uint32_t dw1 = GEN6_PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE |
171                         GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH |
172                         GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH |
173                         GEN6_PIPE_CONTROL_VF_CACHE_INVALIDATE |
174                         GEN6_PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
175                         GEN6_PIPE_CONTROL_CS_STALL;
176    const unsigned batch_used = ilo_builder_batch_used(render->builder);
177
178    ILO_DEV_ASSERT(render->dev, 6, 8);
179
180    if (ilo_dev_gen(render->dev) == ILO_GEN(6))
181       gen6_wa_pre_pipe_control(render, dw1);
182
183    ilo_render_pipe_control(render, dw1);
184
185    assert(ilo_builder_batch_used(render->builder) <= batch_used +
186          ilo_render_get_flush_len(render));
187 }
188
189 /**
190  * Return the command length of ilo_render_emit_query().
191  */
192 int
193 ilo_render_get_query_len(const struct ilo_render *render,
194                          unsigned query_type)
195 {
196    int len;
197
198    ILO_DEV_ASSERT(render->dev, 6, 8);
199
200    /* always a flush or a variant of flush */
201    len = ilo_render_get_flush_len(render);
202
203    switch (query_type) {
204    case PIPE_QUERY_OCCLUSION_COUNTER:
205    case PIPE_QUERY_OCCLUSION_PREDICATE:
206    case PIPE_QUERY_TIMESTAMP:
207    case PIPE_QUERY_TIME_ELAPSED:
208       /* no reg */
209       break;
210    case PIPE_QUERY_PRIMITIVES_GENERATED:
211    case PIPE_QUERY_PRIMITIVES_EMITTED:
212       len += GEN6_MI_STORE_REGISTER_MEM__SIZE * 2;
213       break;
214    case PIPE_QUERY_PIPELINE_STATISTICS:
215       {
216          const int num_regs =
217             (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ? 10 : 8;
218          const int num_pads =
219             (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ? 1 : 3;
220
221          len += GEN6_MI_STORE_REGISTER_MEM__SIZE * 2 * num_regs +
222                 GEN6_MI_STORE_DATA_IMM__SIZE * num_pads;
223       }
224       break;
225    default:
226       len = 0;
227       break;
228    }
229
230    return len;
231 }
232
233 /**
234  * Emit PIPE_CONTROLs or MI_STORE_REGISTER_MEMs to store register values.
235  */
236 void
237 ilo_render_emit_query(struct ilo_render *render,
238                       struct ilo_query *q, uint32_t offset)
239 {
240    const uint32_t pipeline_statistics_regs[11] = {
241       GEN6_REG_IA_VERTICES_COUNT,
242       GEN6_REG_IA_PRIMITIVES_COUNT,
243       GEN6_REG_VS_INVOCATION_COUNT,
244       GEN6_REG_GS_INVOCATION_COUNT,
245       GEN6_REG_GS_PRIMITIVES_COUNT,
246       GEN6_REG_CL_INVOCATION_COUNT,
247       GEN6_REG_CL_PRIMITIVES_COUNT,
248       GEN6_REG_PS_INVOCATION_COUNT,
249       (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ?
250          GEN7_REG_HS_INVOCATION_COUNT : 0,
251       (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ?
252          GEN7_REG_DS_INVOCATION_COUNT : 0,
253       0,
254    };
255    const uint32_t primitives_generated_reg =
256       (ilo_dev_gen(render->dev) >= ILO_GEN(7) && q->index > 0) ?
257       GEN7_REG_SO_PRIM_STORAGE_NEEDED(q->index) :
258       GEN6_REG_CL_INVOCATION_COUNT;
259    const uint32_t primitives_emitted_reg =
260       (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ?
261       GEN7_REG_SO_NUM_PRIMS_WRITTEN(q->index) :
262       GEN6_REG_SO_NUM_PRIMS_WRITTEN;
263    const unsigned batch_used = ilo_builder_batch_used(render->builder);
264    const uint32_t *regs;
265    int reg_count = 0, i;
266    uint32_t pipe_control_dw1 = 0;
267
268    ILO_DEV_ASSERT(render->dev, 6, 8);
269
270    switch (q->type) {
271    case PIPE_QUERY_OCCLUSION_COUNTER:
272    case PIPE_QUERY_OCCLUSION_PREDICATE:
273       pipe_control_dw1 = GEN6_PIPE_CONTROL_DEPTH_STALL |
274                          GEN6_PIPE_CONTROL_WRITE_PS_DEPTH_COUNT;
275       break;
276    case PIPE_QUERY_TIMESTAMP:
277    case PIPE_QUERY_TIME_ELAPSED:
278       pipe_control_dw1 = GEN6_PIPE_CONTROL_WRITE_TIMESTAMP;
279       break;
280    case PIPE_QUERY_PRIMITIVES_GENERATED:
281       regs = &primitives_generated_reg;
282       reg_count = 1;
283       break;
284    case PIPE_QUERY_PRIMITIVES_EMITTED:
285       regs = &primitives_emitted_reg;
286       reg_count = 1;
287       break;
288    case PIPE_QUERY_PIPELINE_STATISTICS:
289       regs = pipeline_statistics_regs;
290       reg_count = Elements(pipeline_statistics_regs);
291       break;
292    default:
293       break;
294    }
295
296    if (pipe_control_dw1) {
297       assert(!reg_count);
298
299       if (ilo_dev_gen(render->dev) == ILO_GEN(6))
300          gen6_wa_pre_pipe_control(render, pipe_control_dw1);
301
302       gen6_PIPE_CONTROL(render->builder, pipe_control_dw1, q->bo, offset, 0);
303
304       render->state.current_pipe_control_dw1 |= pipe_control_dw1;
305       render->state.deferred_pipe_control_dw1 &= ~pipe_control_dw1;
306    } else if (reg_count) {
307       ilo_render_emit_flush(render);
308    }
309
310    for (i = 0; i < reg_count; i++) {
311       if (regs[i]) {
312          /* store lower 32 bits */
313          gen6_MI_STORE_REGISTER_MEM(render->builder, regs[i], q->bo, offset);
314          /* store higher 32 bits */
315          gen6_MI_STORE_REGISTER_MEM(render->builder, regs[i] + 4,
316                q->bo, offset + 4);
317       } else {
318          gen6_MI_STORE_DATA_IMM(render->builder, q->bo, offset, 0);
319       }
320
321       offset += 8;
322    }
323
324    assert(ilo_builder_batch_used(render->builder) <= batch_used +
325          ilo_render_get_query_len(render, q->type));
326 }
327
328 int
329 ilo_render_get_rectlist_len(const struct ilo_render *render,
330                             const struct ilo_blitter *blitter)
331 {
332    ILO_DEV_ASSERT(render->dev, 6, 8);
333
334    return ilo_render_get_rectlist_dynamic_states_len(render, blitter) +
335           ilo_render_get_rectlist_commands_len(render, blitter);
336 }
337
338 void
339 ilo_render_emit_rectlist(struct ilo_render *render,
340                          const struct ilo_blitter *blitter)
341 {
342    struct ilo_render_rectlist_session session;
343
344    ILO_DEV_ASSERT(render->dev, 6, 8);
345
346    memset(&session, 0, sizeof(session));
347    ilo_render_emit_rectlist_dynamic_states(render, blitter, &session);
348    ilo_render_emit_rectlist_commands(render, blitter, &session);
349 }
350
351 int
352 ilo_render_get_draw_len(const struct ilo_render *render,
353                         const struct ilo_state_vector *vec)
354 {
355    ILO_DEV_ASSERT(render->dev, 6, 8);
356
357    return ilo_render_get_draw_dynamic_states_len(render, vec) +
358           ilo_render_get_draw_surface_states_len(render, vec) +
359           ilo_render_get_draw_commands_len(render, vec);
360 }
361
362 static void
363 draw_session_prepare(struct ilo_render *render,
364                      const struct ilo_state_vector *vec,
365                      struct ilo_render_draw_session *session)
366 {
367    memset(session, 0, sizeof(*session));
368    session->pipe_dirty = vec->dirty;
369    session->reduced_prim = u_reduced_prim(vec->draw->mode);
370
371    if (render->hw_ctx_changed) {
372       /* these should be enough to make everything uploaded */
373       render->batch_bo_changed = true;
374       render->state_bo_changed = true;
375       render->instruction_bo_changed = true;
376
377       session->prim_changed = true;
378
379       ilo_state_urb_full_delta(&vec->urb, render->dev, &session->urb_delta);
380       ilo_state_vf_full_delta(&vec->ve->vf, render->dev, &session->vf_delta);
381
382       ilo_state_raster_full_delta(&vec->rasterizer->rs, render->dev,
383             &session->rs_delta);
384
385       ilo_state_viewport_full_delta(&vec->viewport.vp, render->dev,
386             &session->vp_delta);
387
388       ilo_state_cc_full_delta(&vec->blend->cc, render->dev,
389             &session->cc_delta);
390    } else {
391       session->prim_changed =
392          (render->state.reduced_prim != session->reduced_prim);
393
394       ilo_state_urb_get_delta(&vec->urb, render->dev,
395             &render->state.urb, &session->urb_delta);
396
397       if (vec->dirty & ILO_DIRTY_VE) {
398          ilo_state_vf_full_delta(&vec->ve->vf, render->dev,
399                &session->vf_delta);
400       }
401
402       if (vec->dirty & ILO_DIRTY_RASTERIZER) {
403          ilo_state_raster_get_delta(&vec->rasterizer->rs, render->dev,
404                &render->state.rs, &session->rs_delta);
405       }
406
407       if (vec->dirty & ILO_DIRTY_VIEWPORT) {
408          ilo_state_viewport_full_delta(&vec->viewport.vp, render->dev,
409                &session->vp_delta);
410       }
411
412       if (vec->dirty & ILO_DIRTY_BLEND) {
413          ilo_state_cc_get_delta(&vec->blend->cc, render->dev,
414                &render->state.cc, &session->cc_delta);
415       }
416    }
417 }
418
419 static void
420 draw_session_end(struct ilo_render *render,
421                  const struct ilo_state_vector *vec,
422                  struct ilo_render_draw_session *session)
423 {
424    render->hw_ctx_changed = false;
425
426    render->batch_bo_changed = false;
427    render->state_bo_changed = false;
428    render->instruction_bo_changed = false;
429
430    render->state.reduced_prim = session->reduced_prim;
431
432    render->state.urb = vec->urb;
433    render->state.rs = vec->rasterizer->rs;
434    render->state.cc = vec->blend->cc;
435 }
436
437 void
438 ilo_render_emit_draw(struct ilo_render *render,
439                      const struct ilo_state_vector *vec)
440 {
441    struct ilo_render_draw_session session;
442
443    ILO_DEV_ASSERT(render->dev, 6, 8);
444
445    draw_session_prepare(render, vec, &session);
446
447    /* force all states to be uploaded if the state bo changed */
448    if (render->state_bo_changed)
449       session.pipe_dirty = ILO_DIRTY_ALL;
450    else
451       session.pipe_dirty = vec->dirty;
452
453    ilo_render_emit_draw_dynamic_states(render, vec, &session);
454    ilo_render_emit_draw_surface_states(render, vec, &session);
455
456    /* force all commands to be uploaded if the HW context changed */
457    if (render->hw_ctx_changed)
458       session.pipe_dirty = ILO_DIRTY_ALL;
459    else
460       session.pipe_dirty = vec->dirty;
461
462    ilo_render_emit_draw_commands(render, vec, &session);
463
464    draw_session_end(render, vec, &session);
465 }
466
467 int
468 ilo_render_get_launch_grid_len(const struct ilo_render *render,
469                                const struct ilo_state_vector *vec)
470 {
471    ILO_DEV_ASSERT(render->dev, 7, 7.5);
472
473    return ilo_render_get_launch_grid_surface_states_len(render, vec) +
474           ilo_render_get_launch_grid_dynamic_states_len(render, vec) +
475           ilo_render_get_launch_grid_commands_len(render, vec);
476 }
477
478 void
479 ilo_render_emit_launch_grid(struct ilo_render *render,
480                             const struct ilo_state_vector *vec,
481                             const unsigned thread_group_offset[3],
482                             const unsigned thread_group_dim[3],
483                             unsigned thread_group_size,
484                             const struct pipe_constant_buffer *input,
485                             uint32_t pc)
486 {
487    struct ilo_render_launch_grid_session session;
488
489    ILO_DEV_ASSERT(render->dev, 7, 7.5);
490
491    assert(input->buffer);
492
493    memset(&session, 0, sizeof(session));
494
495    session.thread_group_offset = thread_group_offset;
496    session.thread_group_dim = thread_group_dim;
497    session.thread_group_size = thread_group_size;
498    session.input = input;
499    session.pc = pc;
500
501    ilo_render_emit_launch_grid_surface_states(render, vec, &session);
502    ilo_render_emit_launch_grid_dynamic_states(render, vec, &session);
503    ilo_render_emit_launch_grid_commands(render, vec, &session);
504 }