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