OSDN Git Service

8bc04df4fabb6e485171de4539e8b1b83eeac33d
[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_TIMESTAMP:
206    case PIPE_QUERY_TIME_ELAPSED:
207       /* no reg */
208       break;
209    case PIPE_QUERY_PRIMITIVES_GENERATED:
210    case PIPE_QUERY_PRIMITIVES_EMITTED:
211       len += GEN6_MI_STORE_REGISTER_MEM__SIZE * 2;
212       break;
213    case PIPE_QUERY_PIPELINE_STATISTICS:
214       {
215          const int num_regs =
216             (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ? 10 : 8;
217          const int num_pads =
218             (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ? 1 : 3;
219
220          len += GEN6_MI_STORE_REGISTER_MEM__SIZE * 2 * num_regs +
221                 GEN6_MI_STORE_DATA_IMM__SIZE * num_pads;
222       }
223       break;
224    default:
225       len = 0;
226       break;
227    }
228
229    return len;
230 }
231
232 /**
233  * Emit PIPE_CONTROLs or MI_STORE_REGISTER_MEMs to store register values.
234  */
235 void
236 ilo_render_emit_query(struct ilo_render *render,
237                       struct ilo_query *q, uint32_t offset)
238 {
239    const uint32_t pipeline_statistics_regs[11] = {
240       GEN6_REG_IA_VERTICES_COUNT,
241       GEN6_REG_IA_PRIMITIVES_COUNT,
242       GEN6_REG_VS_INVOCATION_COUNT,
243       GEN6_REG_GS_INVOCATION_COUNT,
244       GEN6_REG_GS_PRIMITIVES_COUNT,
245       GEN6_REG_CL_INVOCATION_COUNT,
246       GEN6_REG_CL_PRIMITIVES_COUNT,
247       GEN6_REG_PS_INVOCATION_COUNT,
248       (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ?
249          GEN7_REG_HS_INVOCATION_COUNT : 0,
250       (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ?
251          GEN7_REG_DS_INVOCATION_COUNT : 0,
252       0,
253    };
254    const uint32_t primitives_generated_reg =
255       (ilo_dev_gen(render->dev) >= ILO_GEN(7) && q->index > 0) ?
256       GEN7_REG_SO_PRIM_STORAGE_NEEDED(q->index) :
257       GEN6_REG_CL_INVOCATION_COUNT;
258    const uint32_t primitives_emitted_reg =
259       (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ?
260       GEN7_REG_SO_NUM_PRIMS_WRITTEN(q->index) :
261       GEN6_REG_SO_NUM_PRIMS_WRITTEN;
262    const unsigned batch_used = ilo_builder_batch_used(render->builder);
263    const uint32_t *regs;
264    int reg_count = 0, i;
265    uint32_t pipe_control_dw1 = 0;
266
267    ILO_DEV_ASSERT(render->dev, 6, 8);
268
269    switch (q->type) {
270    case PIPE_QUERY_OCCLUSION_COUNTER:
271       pipe_control_dw1 = GEN6_PIPE_CONTROL_DEPTH_STALL |
272                          GEN6_PIPE_CONTROL_WRITE_PS_DEPTH_COUNT;
273       break;
274    case PIPE_QUERY_TIMESTAMP:
275    case PIPE_QUERY_TIME_ELAPSED:
276       pipe_control_dw1 = GEN6_PIPE_CONTROL_WRITE_TIMESTAMP;
277       break;
278    case PIPE_QUERY_PRIMITIVES_GENERATED:
279       regs = &primitives_generated_reg;
280       reg_count = 1;
281       break;
282    case PIPE_QUERY_PRIMITIVES_EMITTED:
283       regs = &primitives_emitted_reg;
284       reg_count = 1;
285       break;
286    case PIPE_QUERY_PIPELINE_STATISTICS:
287       regs = pipeline_statistics_regs;
288       reg_count = Elements(pipeline_statistics_regs);
289       break;
290    default:
291       break;
292    }
293
294    if (pipe_control_dw1) {
295       assert(!reg_count);
296
297       if (ilo_dev_gen(render->dev) == ILO_GEN(6))
298          gen6_wa_pre_pipe_control(render, pipe_control_dw1);
299
300       gen6_PIPE_CONTROL(render->builder, pipe_control_dw1, q->bo, offset, 0);
301
302       render->state.current_pipe_control_dw1 |= pipe_control_dw1;
303       render->state.deferred_pipe_control_dw1 &= ~pipe_control_dw1;
304    } else if (reg_count) {
305       ilo_render_emit_flush(render);
306    }
307
308    for (i = 0; i < reg_count; i++) {
309       if (regs[i]) {
310          /* store lower 32 bits */
311          gen6_MI_STORE_REGISTER_MEM(render->builder, regs[i], q->bo, offset);
312          /* store higher 32 bits */
313          gen6_MI_STORE_REGISTER_MEM(render->builder, regs[i] + 4,
314                q->bo, offset + 4);
315       } else {
316          gen6_MI_STORE_DATA_IMM(render->builder, q->bo, offset, 0);
317       }
318
319       offset += 8;
320    }
321
322    assert(ilo_builder_batch_used(render->builder) <= batch_used +
323          ilo_render_get_query_len(render, q->type));
324 }
325
326 int
327 ilo_render_get_rectlist_len(const struct ilo_render *render,
328                             const struct ilo_blitter *blitter)
329 {
330    ILO_DEV_ASSERT(render->dev, 6, 8);
331
332    return ilo_render_get_rectlist_dynamic_states_len(render, blitter) +
333           ilo_render_get_rectlist_commands_len(render, blitter);
334 }
335
336 void
337 ilo_render_emit_rectlist(struct ilo_render *render,
338                          const struct ilo_blitter *blitter)
339 {
340    struct ilo_render_rectlist_session session;
341
342    ILO_DEV_ASSERT(render->dev, 6, 8);
343
344    memset(&session, 0, sizeof(session));
345    ilo_render_emit_rectlist_dynamic_states(render, blitter, &session);
346    ilo_render_emit_rectlist_commands(render, blitter, &session);
347 }
348
349 int
350 ilo_render_get_draw_len(const struct ilo_render *render,
351                         const struct ilo_state_vector *vec)
352 {
353    ILO_DEV_ASSERT(render->dev, 6, 8);
354
355    return ilo_render_get_draw_dynamic_states_len(render, vec) +
356           ilo_render_get_draw_surface_states_len(render, vec) +
357           ilo_render_get_draw_commands_len(render, vec);
358 }
359
360 static void
361 draw_session_prepare(struct ilo_render *render,
362                      const struct ilo_state_vector *vec,
363                      struct ilo_render_draw_session *session)
364 {
365    memset(session, 0, sizeof(*session));
366    session->pipe_dirty = vec->dirty;
367    session->reduced_prim = u_reduced_prim(vec->draw->mode);
368
369    if (render->hw_ctx_changed) {
370       /* these should be enough to make everything uploaded */
371       render->batch_bo_changed = true;
372       render->state_bo_changed = true;
373       render->instruction_bo_changed = true;
374
375       session->prim_changed = true;
376
377       ilo_state_urb_full_delta(&vec->urb, render->dev, &session->urb_delta);
378       ilo_state_vf_full_delta(&vec->ve->vf, render->dev, &session->vf_delta);
379
380       ilo_state_raster_full_delta(&vec->rasterizer->rs, render->dev,
381             &session->rs_delta);
382
383       ilo_state_viewport_full_delta(&vec->viewport.vp, render->dev,
384             &session->vp_delta);
385
386       ilo_state_cc_full_delta(&vec->blend->cc, render->dev,
387             &session->cc_delta);
388    } else {
389       session->prim_changed =
390          (render->state.reduced_prim != session->reduced_prim);
391
392       ilo_state_urb_get_delta(&vec->urb, render->dev,
393             &render->state.urb, &session->urb_delta);
394
395       if (vec->dirty & ILO_DIRTY_VE) {
396          ilo_state_vf_full_delta(&vec->ve->vf, render->dev,
397                &session->vf_delta);
398       }
399
400       if (vec->dirty & ILO_DIRTY_RASTERIZER) {
401          ilo_state_raster_get_delta(&vec->rasterizer->rs, render->dev,
402                &render->state.rs, &session->rs_delta);
403       }
404
405       if (vec->dirty & ILO_DIRTY_VIEWPORT) {
406          ilo_state_viewport_full_delta(&vec->viewport.vp, render->dev,
407                &session->vp_delta);
408       }
409
410       if (vec->dirty & ILO_DIRTY_BLEND) {
411          ilo_state_cc_get_delta(&vec->blend->cc, render->dev,
412                &render->state.cc, &session->cc_delta);
413       }
414    }
415 }
416
417 static void
418 draw_session_end(struct ilo_render *render,
419                  const struct ilo_state_vector *vec,
420                  struct ilo_render_draw_session *session)
421 {
422    render->hw_ctx_changed = false;
423
424    render->batch_bo_changed = false;
425    render->state_bo_changed = false;
426    render->instruction_bo_changed = false;
427
428    render->state.reduced_prim = session->reduced_prim;
429
430    render->state.urb = vec->urb;
431    render->state.rs = vec->rasterizer->rs;
432    render->state.cc = vec->blend->cc;
433 }
434
435 void
436 ilo_render_emit_draw(struct ilo_render *render,
437                      const struct ilo_state_vector *vec)
438 {
439    struct ilo_render_draw_session session;
440
441    ILO_DEV_ASSERT(render->dev, 6, 8);
442
443    draw_session_prepare(render, vec, &session);
444
445    /* force all states to be uploaded if the state bo changed */
446    if (render->state_bo_changed)
447       session.pipe_dirty = ILO_DIRTY_ALL;
448    else
449       session.pipe_dirty = vec->dirty;
450
451    ilo_render_emit_draw_dynamic_states(render, vec, &session);
452    ilo_render_emit_draw_surface_states(render, vec, &session);
453
454    /* force all commands to be uploaded if the HW context changed */
455    if (render->hw_ctx_changed)
456       session.pipe_dirty = ILO_DIRTY_ALL;
457    else
458       session.pipe_dirty = vec->dirty;
459
460    ilo_render_emit_draw_commands(render, vec, &session);
461
462    draw_session_end(render, vec, &session);
463 }
464
465 int
466 ilo_render_get_launch_grid_len(const struct ilo_render *render,
467                                const struct ilo_state_vector *vec)
468 {
469    ILO_DEV_ASSERT(render->dev, 7, 7.5);
470
471    return ilo_render_get_launch_grid_surface_states_len(render, vec) +
472           ilo_render_get_launch_grid_dynamic_states_len(render, vec) +
473           ilo_render_get_launch_grid_commands_len(render, vec);
474 }
475
476 void
477 ilo_render_emit_launch_grid(struct ilo_render *render,
478                             const struct ilo_state_vector *vec,
479                             const unsigned thread_group_offset[3],
480                             const unsigned thread_group_dim[3],
481                             unsigned thread_group_size,
482                             const struct pipe_constant_buffer *input,
483                             uint32_t pc)
484 {
485    struct ilo_render_launch_grid_session session;
486
487    ILO_DEV_ASSERT(render->dev, 7, 7.5);
488
489    assert(input->buffer);
490
491    memset(&session, 0, sizeof(session));
492
493    session.thread_group_offset = thread_group_offset;
494    session.thread_group_dim = thread_group_dim;
495    session.thread_group_size = thread_group_size;
496    session.input = input;
497    session.pc = pc;
498
499    ilo_render_emit_launch_grid_surface_states(render, vec, &session);
500    ilo_render_emit_launch_grid_dynamic_states(render, vec, &session);
501    ilo_render_emit_launch_grid_commands(render, vec, &session);
502 }