OSDN Git Service

ilo: s/Elements/ARRAY_SIZE/
[android-x86/external-mesa.git] / src / gallium / drivers / ilo / ilo_render_surface.c
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 2012-2014 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 "core/ilo_builder_3d.h"
29
30 #include "ilo_common.h"
31 #include "ilo_blitter.h"
32 #include "ilo_resource.h"
33 #include "ilo_shader.h"
34 #include "ilo_state.h"
35 #include "ilo_render_gen.h"
36
37 #define DIRTY(state) (session->pipe_dirty & ILO_DIRTY_ ## state)
38
39 static inline uint32_t
40 gen6_so_SURFACE_STATE(struct ilo_builder *builder,
41                       const struct pipe_stream_output_target *so,
42                       const struct pipe_stream_output_info *so_info,
43                       int so_index)
44 {
45    struct ilo_state_surface_buffer_info info;
46    struct ilo_state_surface surf;
47
48    ILO_DEV_ASSERT(builder->dev, 6, 6);
49
50    memset(&info, 0, sizeof(info));
51
52    info.vma = ilo_resource_get_vma(so->buffer);
53    info.offset = so->buffer_offset + so_info->output[so_index].dst_offset * 4;
54    info.size = so->buffer_size - so_info->output[so_index].dst_offset * 4;
55
56    info.access = ILO_STATE_SURFACE_ACCESS_DP_SVB;
57
58    switch (so_info->output[so_index].num_components) {
59    case 1:
60       info.format = GEN6_FORMAT_R32_FLOAT;
61       info.format_size = 4;
62       break;
63    case 2:
64       info.format = GEN6_FORMAT_R32G32_FLOAT;
65       info.format_size = 8;
66       break;
67    case 3:
68       info.format = GEN6_FORMAT_R32G32B32_FLOAT;
69       info.format_size = 12;
70       break;
71    case 4:
72       info.format = GEN6_FORMAT_R32G32B32A32_FLOAT;
73       info.format_size = 16;
74       break;
75    default:
76       assert(!"unexpected SO components length");
77       info.format = GEN6_FORMAT_R32_FLOAT;
78       info.format_size = 4;
79       break;
80    }
81
82    info.struct_size =
83       so_info->stride[so_info->output[so_index].output_buffer] * 4;
84
85    memset(&surf, 0, sizeof(surf));
86    ilo_state_surface_init_for_buffer(&surf, builder->dev, &info);
87
88    return gen6_SURFACE_STATE(builder, &surf);
89 }
90
91 static void
92 gen6_emit_draw_surface_rt(struct ilo_render *r,
93                           const struct ilo_state_vector *vec,
94                           struct ilo_render_draw_session *session)
95 {
96    const struct ilo_shader_state *fs = vec->fs;
97    const struct ilo_fb_state *fb = &vec->fb;
98    uint32_t *surface_state;
99    int base, count, i;
100
101    ILO_DEV_ASSERT(r->dev, 6, 8);
102
103    if (!DIRTY(FS) && !DIRTY(FB))
104       return;
105    if (!fs)
106       return;
107
108    session->binding_table_fs_changed = true;
109
110    base = ilo_shader_get_kernel_param(fs, ILO_KERNEL_FS_SURFACE_RT_BASE);
111    count = ilo_shader_get_kernel_param(fs, ILO_KERNEL_FS_SURFACE_RT_COUNT);
112
113    /* SURFACE_STATEs for render targets */
114    surface_state = &r->state.wm.SURFACE_STATE[base];
115    for (i = 0; i < count; i++) {
116       if (i < fb->state.nr_cbufs && fb->state.cbufs[i]) {
117          const struct ilo_surface_cso *surface =
118             (const struct ilo_surface_cso *) fb->state.cbufs[i];
119
120          assert(surface->is_rt);
121          surface_state[i] = gen6_SURFACE_STATE(r->builder, &surface->u.rt);
122       } else {
123          surface_state[i] = gen6_SURFACE_STATE(r->builder, &fb->null_rt);
124       }
125    }
126 }
127
128 static void
129 gen6_emit_draw_surface_so(struct ilo_render *r,
130                           const struct ilo_state_vector *vec,
131                           struct ilo_render_draw_session *session)
132 {
133    const struct ilo_shader_state *vs = vec->vs;
134    const struct ilo_shader_state *gs = vec->gs;
135    const struct ilo_so_state *so = &vec->so;
136    const struct pipe_stream_output_info *so_info;
137    uint32_t *surface_state;
138    int base, count, i;
139
140    ILO_DEV_ASSERT(r->dev, 6, 6);
141
142    if (!DIRTY(VS) && !DIRTY(GS) && !DIRTY(SO))
143       return;
144
145    if (gs) {
146       so_info = ilo_shader_get_kernel_so_info(gs);
147       base = ilo_shader_get_kernel_param(gs,
148             ILO_KERNEL_GS_GEN6_SURFACE_SO_BASE);
149       count = ilo_shader_get_kernel_param(gs,
150             ILO_KERNEL_GS_GEN6_SURFACE_SO_COUNT);
151    } else if (vs) {
152       so_info = ilo_shader_get_kernel_so_info(vs);
153       base = 0;
154       count = ilo_shader_get_kernel_param(vs,
155             ILO_KERNEL_VS_GEN6_SO_SURFACE_COUNT);
156    } else {
157       return;
158    }
159
160    session->binding_table_gs_changed = true;
161
162    /* SURFACE_STATEs for stream output targets */
163    surface_state = &r->state.gs.SURFACE_STATE[base];
164    for (i = 0; i < count; i++) {
165       if (so_info && i < so_info->num_outputs &&
166           so_info->output[i].output_buffer < so->count &&
167           so->states[so_info->output[i].output_buffer]) {
168          const struct pipe_stream_output_target *so_target =
169             so->states[so_info->output[i].output_buffer];
170
171          surface_state[i] = gen6_so_SURFACE_STATE(r->builder,
172                so_target, so_info, i);
173       } else {
174          surface_state[i] = 0;
175       }
176    }
177 }
178
179 static void
180 gen6_emit_draw_surface_view(struct ilo_render *r,
181                             const struct ilo_state_vector *vec,
182                             int shader_type,
183                             struct ilo_render_draw_session *session)
184 {
185    const struct ilo_view_state *view = &vec->view[shader_type];
186    const struct ilo_shader_state *sh;
187    uint32_t *surface_state;
188    int base, count, i;
189
190    ILO_DEV_ASSERT(r->dev, 6, 8);
191
192    switch (shader_type) {
193    case PIPE_SHADER_VERTEX:
194       if (!DIRTY(VS) && !DIRTY(VIEW_VS))
195          return;
196       if (!vec->vs)
197          return;
198
199       sh = vec->vs;
200       surface_state = r->state.vs.SURFACE_STATE;
201       session->binding_table_vs_changed = true;
202       break;
203    case PIPE_SHADER_FRAGMENT:
204       if (!DIRTY(FS) && !DIRTY(VIEW_FS))
205          return;
206       if (!vec->fs)
207          return;
208
209       sh = vec->fs;
210       surface_state = r->state.wm.SURFACE_STATE;
211       session->binding_table_fs_changed = true;
212       break;
213    default:
214       return;
215       break;
216    }
217
218    base = ilo_shader_get_kernel_param(sh, ILO_KERNEL_SURFACE_TEX_BASE);
219    count = ilo_shader_get_kernel_param(sh, ILO_KERNEL_SURFACE_TEX_COUNT);
220
221    /* SURFACE_STATEs for sampler views */
222    surface_state += base;
223    for (i = 0; i < count; i++) {
224       if (i < view->count && view->states[i]) {
225          const struct ilo_view_cso *cso =
226             (const struct ilo_view_cso *) view->states[i];
227
228          surface_state[i] = gen6_SURFACE_STATE(r->builder, &cso->surface);
229       } else {
230          surface_state[i] = 0;
231       }
232    }
233 }
234
235 static void
236 gen6_emit_draw_surface_const(struct ilo_render *r,
237                              const struct ilo_state_vector *vec,
238                              int shader_type,
239                              struct ilo_render_draw_session *session)
240 {
241    const struct ilo_cbuf_state *cbuf = &vec->cbuf[shader_type];
242    const struct ilo_shader_state *sh;
243    uint32_t *surface_state;
244    int base, count, i;
245
246    ILO_DEV_ASSERT(r->dev, 6, 8);
247
248    switch (shader_type) {
249    case PIPE_SHADER_VERTEX:
250       if (!DIRTY(VS) && !DIRTY(CBUF))
251          return;
252       if (!vec->vs)
253          return;
254
255       sh = vec->vs;
256       surface_state = r->state.vs.SURFACE_STATE;
257       session->binding_table_vs_changed = true;
258       break;
259    case PIPE_SHADER_FRAGMENT:
260       if (!DIRTY(FS) && !DIRTY(CBUF))
261          return;
262       if (!vec->fs)
263          return;
264
265       sh = vec->fs;
266       surface_state = r->state.wm.SURFACE_STATE;
267       session->binding_table_fs_changed = true;
268       break;
269    default:
270       return;
271       break;
272    }
273
274    base = ilo_shader_get_kernel_param(sh, ILO_KERNEL_SURFACE_CONST_BASE);
275    count = ilo_shader_get_kernel_param(sh, ILO_KERNEL_SURFACE_CONST_COUNT);
276
277    /* SURFACE_STATEs for constant buffers */
278    surface_state += base;
279    for (i = 0; i < count; i++) {
280       const struct ilo_cbuf_cso *cso = &cbuf->cso[i];
281
282       if (cso->resource)
283          surface_state[i] = gen6_SURFACE_STATE(r->builder, &cso->surface);
284       else
285          surface_state[i] = 0;
286    }
287 }
288
289 static void
290 gen6_emit_draw_surface_binding_tables(struct ilo_render *r,
291                                       const struct ilo_state_vector *vec,
292                                       int shader_type,
293                                       struct ilo_render_draw_session *session)
294 {
295    int count;
296
297    ILO_DEV_ASSERT(r->dev, 6, 8);
298
299    /* BINDING_TABLE_STATE */
300    switch (shader_type) {
301    case PIPE_SHADER_VERTEX:
302       if (!session->binding_table_vs_changed)
303          return;
304       if (!vec->vs)
305          return;
306
307       count = ilo_shader_get_kernel_param(vec->vs,
308             ILO_KERNEL_SURFACE_TOTAL_COUNT);
309
310       r->state.vs.BINDING_TABLE_STATE = gen6_BINDING_TABLE_STATE(r->builder,
311             r->state.vs.SURFACE_STATE, count);
312       break;
313    case PIPE_SHADER_GEOMETRY:
314       if (!session->binding_table_gs_changed)
315          return;
316       if (vec->gs) {
317          count = ilo_shader_get_kernel_param(vec->gs,
318                ILO_KERNEL_SURFACE_TOTAL_COUNT);
319       } else if (ilo_dev_gen(r->dev) == ILO_GEN(6) && vec->vs) {
320          count = ilo_shader_get_kernel_param(vec->vs,
321                ILO_KERNEL_VS_GEN6_SO_SURFACE_COUNT);
322       } else {
323          return;
324       }
325
326       r->state.gs.BINDING_TABLE_STATE = gen6_BINDING_TABLE_STATE(r->builder,
327             r->state.gs.SURFACE_STATE, count);
328       break;
329    case PIPE_SHADER_FRAGMENT:
330       if (!session->binding_table_fs_changed)
331          return;
332       if (!vec->fs)
333          return;
334
335       count = ilo_shader_get_kernel_param(vec->fs,
336             ILO_KERNEL_SURFACE_TOTAL_COUNT);
337
338       r->state.wm.BINDING_TABLE_STATE = gen6_BINDING_TABLE_STATE(r->builder,
339             r->state.wm.SURFACE_STATE, count);
340       break;
341    default:
342       break;
343    }
344 }
345
346 #undef DIRTY
347
348 int
349 ilo_render_get_draw_surface_states_len(const struct ilo_render *render,
350                                        const struct ilo_state_vector *vec)
351 {
352    int sh_type, len;
353
354    ILO_DEV_ASSERT(render->dev, 6, 8);
355
356    len = 0;
357
358    for (sh_type = 0; sh_type < PIPE_SHADER_TYPES; sh_type++) {
359       const int alignment =
360          (ilo_dev_gen(render->dev) >= ILO_GEN(8) ? 64 : 32) / 4;
361       int num_surfaces = 0;
362
363       switch (sh_type) {
364       case PIPE_SHADER_VERTEX:
365          if (vec->vs) {
366             num_surfaces = ilo_shader_get_kernel_param(vec->vs,
367                   ILO_KERNEL_SURFACE_TOTAL_COUNT);
368
369             if (ilo_dev_gen(render->dev) == ILO_GEN(6)) {
370                num_surfaces += ilo_shader_get_kernel_param(vec->vs,
371                      ILO_KERNEL_VS_GEN6_SO_SURFACE_COUNT);
372             }
373          }
374          break;
375       case PIPE_SHADER_GEOMETRY:
376          if (vec->gs) {
377             num_surfaces = ilo_shader_get_kernel_param(vec->gs,
378                   ILO_KERNEL_SURFACE_TOTAL_COUNT);
379          }
380          break;
381       case PIPE_SHADER_FRAGMENT:
382          if (vec->fs) {
383             num_surfaces = ilo_shader_get_kernel_param(vec->fs,
384                   ILO_KERNEL_SURFACE_TOTAL_COUNT);
385          }
386          break;
387       default:
388          break;
389       }
390
391       /* BINDING_TABLE_STATE and SURFACE_STATEs */
392       if (num_surfaces) {
393          len += align(num_surfaces, alignment) +
394             align(GEN6_SURFACE_STATE__SIZE, alignment) * num_surfaces;
395       }
396    }
397
398    return len;
399 }
400
401 void
402 ilo_render_emit_draw_surface_states(struct ilo_render *render,
403                                     const struct ilo_state_vector *vec,
404                                     struct ilo_render_draw_session *session)
405 {
406    const unsigned surface_used = ilo_builder_surface_used(render->builder);
407    int shader_type;
408
409    ILO_DEV_ASSERT(render->dev, 6, 8);
410
411    /*
412     * upload all SURAFCE_STATEs together so that we know there are minimal
413     * paddings
414     */
415
416    gen6_emit_draw_surface_rt(render, vec, session);
417
418    if (ilo_dev_gen(render->dev) == ILO_GEN(6))
419       gen6_emit_draw_surface_so(render, vec, session);
420
421    for (shader_type = 0; shader_type < PIPE_SHADER_TYPES; shader_type++) {
422       gen6_emit_draw_surface_view(render, vec, shader_type, session);
423       gen6_emit_draw_surface_const(render, vec, shader_type, session);
424    }
425
426    /* this must be called after all SURFACE_STATEs have been uploaded */
427    for (shader_type = 0; shader_type < PIPE_SHADER_TYPES; shader_type++) {
428       gen6_emit_draw_surface_binding_tables(render, vec,
429             shader_type, session);
430    }
431
432    assert(ilo_builder_surface_used(render->builder) <= surface_used +
433          ilo_render_get_draw_surface_states_len(render, vec));
434 }
435
436 static void
437 gen6_emit_launch_grid_surface_view(struct ilo_render *r,
438                                    const struct ilo_state_vector *vec,
439                                    struct ilo_render_launch_grid_session *session)
440 {
441    const struct ilo_shader_state *cs = vec->cs;
442    const struct ilo_view_state *view = &vec->view[PIPE_SHADER_COMPUTE];
443    uint32_t *surface_state = r->state.cs.SURFACE_STATE;
444    int base, count, i;
445
446    ILO_DEV_ASSERT(r->dev, 7, 7.5);
447
448    base = ilo_shader_get_kernel_param(cs, ILO_KERNEL_SURFACE_TEX_BASE);
449    count = ilo_shader_get_kernel_param(cs, ILO_KERNEL_SURFACE_TEX_COUNT);
450
451    /* SURFACE_STATEs for sampler views */
452    surface_state += base;
453    for (i = 0; i < count; i++) {
454       if (i < view->count && view->states[i]) {
455          const struct ilo_view_cso *cso =
456             (const struct ilo_view_cso *) view->states[i];
457
458          surface_state[i] = gen6_SURFACE_STATE(r->builder, &cso->surface);
459       } else {
460          surface_state[i] = 0;
461       }
462    }
463 }
464
465 static void
466 gen6_emit_launch_grid_surface_const(struct ilo_render *r,
467                                     const struct ilo_state_vector *vec,
468                                     struct ilo_render_launch_grid_session *session)
469 {
470    const struct ilo_shader_state *cs = vec->cs;
471    uint32_t *surface_state = r->state.cs.SURFACE_STATE;
472    struct ilo_state_surface_buffer_info info;
473    struct ilo_state_surface surf;
474    int base, count;
475
476    ILO_DEV_ASSERT(r->dev, 7, 7.5);
477
478    base = ilo_shader_get_kernel_param(cs, ILO_KERNEL_SURFACE_CONST_BASE);
479    count = ilo_shader_get_kernel_param(cs, ILO_KERNEL_SURFACE_CONST_COUNT);
480
481    if (!count)
482       return;
483
484    memset(&info, 0, sizeof(info));
485
486    info.vma = ilo_resource_get_vma(session->input->buffer);
487    info.offset = session->input->buffer_offset;
488    info.size = session->input->buffer_size;
489
490    info.access = ILO_STATE_SURFACE_ACCESS_DP_UNTYPED;
491    info.format = GEN6_FORMAT_RAW;
492    info.format_size = 1;
493    info.struct_size = 1;
494    info.readonly = true;
495
496    memset(&surf, 0, sizeof(surf));
497    ilo_state_surface_init_for_buffer(&surf, r->dev, &info);
498
499    assert(count == 1 && session->input->buffer);
500    surface_state[base] = gen6_SURFACE_STATE(r->builder, &surf);
501 }
502
503 static void
504 gen6_emit_launch_grid_surface_cs_resource(struct ilo_render *r,
505                                           const struct ilo_state_vector *vec,
506                                           struct ilo_render_launch_grid_session *session)
507 {
508    ILO_DEV_ASSERT(r->dev, 7, 7.5);
509
510    /* TODO */
511    assert(!vec->cs_resource.count);
512 }
513
514 static void
515 gen6_emit_launch_grid_surface_global(struct ilo_render *r,
516                                           const struct ilo_state_vector *vec,
517                                           struct ilo_render_launch_grid_session *session)
518 {
519    const struct ilo_shader_state *cs = vec->cs;
520    const struct ilo_global_binding_cso *bindings =
521       util_dynarray_begin(&vec->global_binding.bindings);
522    uint32_t *surface_state = r->state.cs.SURFACE_STATE;
523    int base, count, i;
524
525    ILO_DEV_ASSERT(r->dev, 7, 7.5);
526
527    base = ilo_shader_get_kernel_param(cs, ILO_KERNEL_CS_SURFACE_GLOBAL_BASE);
528    count = ilo_shader_get_kernel_param(cs, ILO_KERNEL_CS_SURFACE_GLOBAL_COUNT);
529
530    if (!count)
531       return;
532
533    if (base + count > ARRAY_SIZE(r->state.cs.SURFACE_STATE)) {
534       ilo_warn("too many global bindings\n");
535       count = ARRAY_SIZE(r->state.cs.SURFACE_STATE) - base;
536    }
537
538    /* SURFACE_STATEs for global bindings */
539    surface_state += base;
540    for (i = 0; i < count; i++) {
541       if (i < vec->global_binding.count && bindings[i].resource) {
542          struct ilo_state_surface_buffer_info info;
543          struct ilo_state_surface surf;
544
545          assert(bindings[i].resource->target == PIPE_BUFFER);
546
547          memset(&info, 0, sizeof(info));
548
549          info.vma = ilo_resource_get_vma(bindings[i].resource);
550          info.size = info.vma->vm_size;
551
552          info.access = ILO_STATE_SURFACE_ACCESS_DP_UNTYPED;
553          info.format = GEN6_FORMAT_RAW;
554          info.format_size = 1;
555          info.struct_size = 1;
556
557          memset(&surf, 0, sizeof(surf));
558          ilo_state_surface_init_for_buffer(&surf, r->dev, &info);
559
560          surface_state[i] = gen6_SURFACE_STATE(r->builder, &surf);
561       } else {
562          surface_state[i] = 0;
563       }
564    }
565 }
566
567 static void
568 gen6_emit_launch_grid_surface_binding_table(struct ilo_render *r,
569                                             const struct ilo_state_vector *vec,
570                                             struct ilo_render_launch_grid_session *session)
571 {
572    const struct ilo_shader_state *cs = vec->cs;
573    int count;
574
575    ILO_DEV_ASSERT(r->dev, 7, 7.5);
576
577    count = ilo_shader_get_kernel_param(cs, ILO_KERNEL_SURFACE_TOTAL_COUNT);
578    if (count) {
579       r->state.cs.BINDING_TABLE_STATE = gen6_BINDING_TABLE_STATE(r->builder,
580             r->state.cs.SURFACE_STATE, count);
581    }
582 }
583
584 int
585 ilo_render_get_launch_grid_surface_states_len(const struct ilo_render *render,
586                                               const struct ilo_state_vector *vec)
587 {
588    const int alignment = 32 / 4;
589    int num_surfaces;
590    int len = 0;
591
592    ILO_DEV_ASSERT(render->dev, 7, 7.5);
593
594    num_surfaces = ilo_shader_get_kernel_param(vec->cs,
595          ILO_KERNEL_SURFACE_TOTAL_COUNT);
596
597    /* BINDING_TABLE_STATE and SURFACE_STATEs */
598    if (num_surfaces) {
599       len += align(num_surfaces, alignment) +
600          align(GEN6_SURFACE_STATE__SIZE, alignment) * num_surfaces;
601    }
602
603    return len;
604 }
605
606 void
607 ilo_render_emit_launch_grid_surface_states(struct ilo_render *render,
608                                            const struct ilo_state_vector *vec,
609                                            struct ilo_render_launch_grid_session *session)
610 {
611    const unsigned surface_used = ilo_builder_surface_used(render->builder);
612
613    ILO_DEV_ASSERT(render->dev, 7, 7.5);
614
615    /* idrt depends on the binding table */
616    assert(!session->idrt_size);
617
618    gen6_emit_launch_grid_surface_view(render, vec, session);
619    gen6_emit_launch_grid_surface_const(render, vec, session);
620    gen6_emit_launch_grid_surface_cs_resource(render, vec, session);
621    gen6_emit_launch_grid_surface_global(render, vec, session);
622    gen6_emit_launch_grid_surface_binding_table(render, vec, session);
623
624    assert(ilo_builder_surface_used(render->builder) <= surface_used +
625          ilo_render_get_launch_grid_surface_states_len(render, vec));
626 }