vc4: fixup for new nir_foreach_block()
[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 }