ilo: add ilo_render_emit_launch_grid()
[mesa.git] / src / gallium / drivers / ilo / ilo_render_dynamic.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 "ilo_common.h"
29 #include "ilo_blitter.h"
30 #include "ilo_builder_3d.h"
31 #include "ilo_builder_media.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_dynamic_viewports(struct ilo_render *r,
39 const struct ilo_state_vector *vec,
40 struct ilo_render_draw_session *session)
41 {
42 ILO_DEV_ASSERT(r->dev, 6, 6);
43
44 /* SF_VIEWPORT, CLIP_VIEWPORT, and CC_VIEWPORT */
45 if (DIRTY(VIEWPORT)) {
46 r->state.CLIP_VIEWPORT = gen6_CLIP_VIEWPORT(r->builder,
47 vec->viewport.cso, vec->viewport.count);
48
49 r->state.SF_VIEWPORT = gen6_SF_VIEWPORT(r->builder,
50 vec->viewport.cso, vec->viewport.count);
51
52 r->state.CC_VIEWPORT = gen6_CC_VIEWPORT(r->builder,
53 vec->viewport.cso, vec->viewport.count);
54
55 session->viewport_changed = true;
56 }
57 }
58
59 static void
60 gen7_emit_draw_dynamic_viewports(struct ilo_render *r,
61 const struct ilo_state_vector *vec,
62 struct ilo_render_draw_session *session)
63 {
64 ILO_DEV_ASSERT(r->dev, 7, 7.5);
65
66 /* SF_CLIP_VIEWPORT and CC_VIEWPORT */
67 if (DIRTY(VIEWPORT)) {
68 r->state.SF_CLIP_VIEWPORT = gen7_SF_CLIP_VIEWPORT(r->builder,
69 vec->viewport.cso, vec->viewport.count);
70
71 r->state.CC_VIEWPORT = gen6_CC_VIEWPORT(r->builder,
72 vec->viewport.cso, vec->viewport.count);
73
74 session->viewport_changed = true;
75 }
76 }
77
78 static void
79 gen6_emit_draw_dynamic_scissors(struct ilo_render *r,
80 const struct ilo_state_vector *vec,
81 struct ilo_render_draw_session *session)
82 {
83 ILO_DEV_ASSERT(r->dev, 6, 7.5);
84
85 /* SCISSOR_RECT */
86 if (DIRTY(SCISSOR) || DIRTY(VIEWPORT)) {
87 /* there should be as many scissors as there are viewports */
88 r->state.SCISSOR_RECT = gen6_SCISSOR_RECT(r->builder,
89 &vec->scissor, vec->viewport.count);
90
91 session->scissor_changed = true;
92 }
93 }
94
95 static void
96 gen6_emit_draw_dynamic_cc(struct ilo_render *r,
97 const struct ilo_state_vector *vec,
98 struct ilo_render_draw_session *session)
99 {
100 ILO_DEV_ASSERT(r->dev, 6, 7.5);
101
102 /* BLEND_STATE */
103 if (DIRTY(BLEND) || DIRTY(FB) || DIRTY(DSA)) {
104 r->state.BLEND_STATE = gen6_BLEND_STATE(r->builder,
105 vec->blend, &vec->fb, vec->dsa);
106
107 session->blend_changed = true;
108 }
109
110 /* COLOR_CALC_STATE */
111 if (DIRTY(DSA) || DIRTY(STENCIL_REF) || DIRTY(BLEND_COLOR)) {
112 r->state.COLOR_CALC_STATE =
113 gen6_COLOR_CALC_STATE(r->builder, &vec->stencil_ref,
114 vec->dsa->alpha_ref, &vec->blend_color);
115
116 session->cc_changed = true;
117 }
118
119 /* DEPTH_STENCIL_STATE */
120 if (DIRTY(DSA)) {
121 r->state.DEPTH_STENCIL_STATE =
122 gen6_DEPTH_STENCIL_STATE(r->builder, vec->dsa);
123
124 session->dsa_changed = true;
125 }
126 }
127
128 static void
129 gen6_emit_draw_dynamic_samplers(struct ilo_render *r,
130 const struct ilo_state_vector *vec,
131 int shader_type,
132 struct ilo_render_draw_session *session)
133 {
134 const struct ilo_sampler_cso * const *samplers =
135 vec->sampler[shader_type].cso;
136 const struct pipe_sampler_view * const *views =
137 (const struct pipe_sampler_view **) vec->view[shader_type].states;
138 uint32_t *sampler_state, *border_color_state;
139 int sampler_count;
140 bool emit_border_color = false;
141 bool skip = false;
142
143 ILO_DEV_ASSERT(r->dev, 6, 7.5);
144
145 /* SAMPLER_BORDER_COLOR_STATE and SAMPLER_STATE */
146 switch (shader_type) {
147 case PIPE_SHADER_VERTEX:
148 if (DIRTY(VS) || DIRTY(SAMPLER_VS) || DIRTY(VIEW_VS)) {
149 sampler_state = &r->state.vs.SAMPLER_STATE;
150 border_color_state = r->state.vs.SAMPLER_BORDER_COLOR_STATE;
151
152 if (DIRTY(VS) || DIRTY(SAMPLER_VS))
153 emit_border_color = true;
154
155 sampler_count = (vec->vs) ? ilo_shader_get_kernel_param(vec->vs,
156 ILO_KERNEL_SAMPLER_COUNT) : 0;
157
158 session->sampler_vs_changed = true;
159 } else {
160 skip = true;
161 }
162 break;
163 case PIPE_SHADER_FRAGMENT:
164 if (DIRTY(FS) || DIRTY(SAMPLER_FS) || DIRTY(VIEW_FS)) {
165 sampler_state = &r->state.wm.SAMPLER_STATE;
166 border_color_state = r->state.wm.SAMPLER_BORDER_COLOR_STATE;
167
168 if (DIRTY(VS) || DIRTY(SAMPLER_FS))
169 emit_border_color = true;
170
171 sampler_count = (vec->fs) ? ilo_shader_get_kernel_param(vec->fs,
172 ILO_KERNEL_SAMPLER_COUNT) : 0;
173
174 session->sampler_fs_changed = true;
175 } else {
176 skip = true;
177 }
178 break;
179 default:
180 skip = true;
181 break;
182 }
183
184 if (skip)
185 return;
186
187 assert(sampler_count <= Elements(vec->view[shader_type].states) &&
188 sampler_count <= Elements(vec->sampler[shader_type].cso));
189
190 if (emit_border_color) {
191 int i;
192
193 for (i = 0; i < sampler_count; i++) {
194 border_color_state[i] = (samplers[i]) ?
195 gen6_SAMPLER_BORDER_COLOR_STATE(r->builder, samplers[i]) : 0;
196 }
197 }
198
199 *sampler_state = gen6_SAMPLER_STATE(r->builder,
200 samplers, views, border_color_state, sampler_count);
201 }
202
203 static void
204 gen6_emit_draw_dynamic_pcb(struct ilo_render *r,
205 const struct ilo_state_vector *vec,
206 struct ilo_render_draw_session *session)
207 {
208 ILO_DEV_ASSERT(r->dev, 6, 7.5);
209
210 /* push constant buffer for VS */
211 if (DIRTY(VS) || DIRTY(CBUF) || DIRTY(CLIP)) {
212 const int cbuf0_size = (vec->vs) ?
213 ilo_shader_get_kernel_param(vec->vs,
214 ILO_KERNEL_PCB_CBUF0_SIZE) : 0;
215 const int clip_state_size = (vec->vs) ?
216 ilo_shader_get_kernel_param(vec->vs,
217 ILO_KERNEL_VS_PCB_UCP_SIZE) : 0;
218 const int total_size = cbuf0_size + clip_state_size;
219
220 if (total_size) {
221 void *pcb;
222
223 r->state.vs.PUSH_CONSTANT_BUFFER =
224 gen6_push_constant_buffer(r->builder, total_size, &pcb);
225 r->state.vs.PUSH_CONSTANT_BUFFER_size = total_size;
226
227 if (cbuf0_size) {
228 const struct ilo_cbuf_state *cbuf =
229 &vec->cbuf[PIPE_SHADER_VERTEX];
230
231 if (cbuf0_size <= cbuf->cso[0].user_buffer_size) {
232 memcpy(pcb, cbuf->cso[0].user_buffer, cbuf0_size);
233 } else {
234 memcpy(pcb, cbuf->cso[0].user_buffer,
235 cbuf->cso[0].user_buffer_size);
236 memset(pcb + cbuf->cso[0].user_buffer_size, 0,
237 cbuf0_size - cbuf->cso[0].user_buffer_size);
238 }
239
240 pcb += cbuf0_size;
241 }
242
243 if (clip_state_size)
244 memcpy(pcb, &vec->clip, clip_state_size);
245
246 session->pcb_vs_changed = true;
247 } else if (r->state.vs.PUSH_CONSTANT_BUFFER_size) {
248 r->state.vs.PUSH_CONSTANT_BUFFER = 0;
249 r->state.vs.PUSH_CONSTANT_BUFFER_size = 0;
250
251 session->pcb_vs_changed = true;
252 }
253 }
254
255 /* push constant buffer for FS */
256 if (DIRTY(FS) || DIRTY(CBUF)) {
257 const int cbuf0_size = (vec->fs) ?
258 ilo_shader_get_kernel_param(vec->fs, ILO_KERNEL_PCB_CBUF0_SIZE) : 0;
259
260 if (cbuf0_size) {
261 const struct ilo_cbuf_state *cbuf = &vec->cbuf[PIPE_SHADER_FRAGMENT];
262 void *pcb;
263
264 r->state.wm.PUSH_CONSTANT_BUFFER =
265 gen6_push_constant_buffer(r->builder, cbuf0_size, &pcb);
266 r->state.wm.PUSH_CONSTANT_BUFFER_size = cbuf0_size;
267
268 if (cbuf0_size <= cbuf->cso[0].user_buffer_size) {
269 memcpy(pcb, cbuf->cso[0].user_buffer, cbuf0_size);
270 } else {
271 memcpy(pcb, cbuf->cso[0].user_buffer,
272 cbuf->cso[0].user_buffer_size);
273 memset(pcb + cbuf->cso[0].user_buffer_size, 0,
274 cbuf0_size - cbuf->cso[0].user_buffer_size);
275 }
276
277 session->pcb_fs_changed = true;
278 } else if (r->state.wm.PUSH_CONSTANT_BUFFER_size) {
279 r->state.wm.PUSH_CONSTANT_BUFFER = 0;
280 r->state.wm.PUSH_CONSTANT_BUFFER_size = 0;
281
282 session->pcb_fs_changed = true;
283 }
284 }
285 }
286
287 #undef DIRTY
288
289 int
290 ilo_render_get_draw_dynamic_states_len(const struct ilo_render *render,
291 const struct ilo_state_vector *vec)
292 {
293 static int static_len;
294 int sh_type, len;
295
296 ILO_DEV_ASSERT(render->dev, 6, 7.5);
297
298 if (!static_len) {
299 /* 64 bytes, or 16 dwords */
300 const int alignment = 64 / 4;
301
302 /* pad first */
303 len = alignment - 1;
304
305 /* CC states */
306 len += align(GEN6_BLEND_STATE__SIZE * ILO_MAX_DRAW_BUFFERS, alignment);
307 len += align(GEN6_DEPTH_STENCIL_STATE__SIZE, alignment);
308 len += align(GEN6_COLOR_CALC_STATE__SIZE, alignment);
309
310 /* viewport arrays */
311 if (ilo_dev_gen(render->dev) >= ILO_GEN(7)) {
312 len += 15 + /* pad first */
313 align(GEN7_SF_CLIP_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 16) +
314 align(GEN6_CC_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) +
315 align(GEN6_SCISSOR_RECT__SIZE * ILO_MAX_VIEWPORTS, 8);
316 } else {
317 len += 7 + /* pad first */
318 align(GEN6_SF_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) +
319 align(GEN6_CLIP_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) +
320 align(GEN6_CC_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) +
321 align(GEN6_SCISSOR_RECT__SIZE * ILO_MAX_VIEWPORTS, 8);
322 }
323
324 static_len = len;
325 }
326
327 len = static_len;
328
329 for (sh_type = 0; sh_type < PIPE_SHADER_TYPES; sh_type++) {
330 const int alignment = 32 / 4;
331 int num_samplers = 0, pcb_len = 0;
332
333 switch (sh_type) {
334 case PIPE_SHADER_VERTEX:
335 if (vec->vs) {
336 num_samplers = ilo_shader_get_kernel_param(vec->vs,
337 ILO_KERNEL_SAMPLER_COUNT);
338 pcb_len = ilo_shader_get_kernel_param(vec->vs,
339 ILO_KERNEL_PCB_CBUF0_SIZE);
340 pcb_len += ilo_shader_get_kernel_param(vec->vs,
341 ILO_KERNEL_VS_PCB_UCP_SIZE);
342 }
343 break;
344 case PIPE_SHADER_GEOMETRY:
345 break;
346 case PIPE_SHADER_FRAGMENT:
347 if (vec->fs) {
348 num_samplers = ilo_shader_get_kernel_param(vec->fs,
349 ILO_KERNEL_SAMPLER_COUNT);
350 pcb_len = ilo_shader_get_kernel_param(vec->fs,
351 ILO_KERNEL_PCB_CBUF0_SIZE);
352 }
353 break;
354 default:
355 break;
356 }
357
358 /* SAMPLER_STATE array and SAMPLER_BORDER_COLORs */
359 if (num_samplers) {
360 /* prefetches are done in multiples of 4 */
361 num_samplers = align(num_samplers, 4);
362
363 len += align(GEN6_SAMPLER_STATE__SIZE * num_samplers, alignment) +
364 align(GEN6_SAMPLER_BORDER_COLOR__SIZE, alignment) * num_samplers;
365 }
366
367 /* PCB */
368 if (pcb_len)
369 len += align(pcb_len, alignment);
370 }
371
372 return len;
373 }
374
375 void
376 ilo_render_emit_draw_dynamic_states(struct ilo_render *render,
377 const struct ilo_state_vector *vec,
378 struct ilo_render_draw_session *session)
379 {
380 const unsigned dynamic_used = ilo_builder_dynamic_used(render->builder);
381
382 ILO_DEV_ASSERT(render->dev, 6, 7.5);
383
384 if (ilo_dev_gen(render->dev) >= ILO_GEN(7))
385 gen7_emit_draw_dynamic_viewports(render, vec, session);
386 else
387 gen6_emit_draw_dynamic_viewports(render, vec, session);
388
389 gen6_emit_draw_dynamic_cc(render, vec, session);
390 gen6_emit_draw_dynamic_scissors(render, vec, session);
391 gen6_emit_draw_dynamic_pcb(render, vec, session);
392
393 gen6_emit_draw_dynamic_samplers(render, vec,
394 PIPE_SHADER_VERTEX, session);
395 gen6_emit_draw_dynamic_samplers(render, vec,
396 PIPE_SHADER_FRAGMENT, session);
397
398 assert(ilo_builder_dynamic_used(render->builder) <= dynamic_used +
399 ilo_render_get_draw_dynamic_states_len(render, vec));
400 }
401
402 int
403 ilo_render_get_rectlist_dynamic_states_len(const struct ilo_render *render,
404 const struct ilo_blitter *blitter)
405 {
406 ILO_DEV_ASSERT(render->dev, 6, 7.5);
407
408 return 96;
409 }
410
411 void
412 ilo_render_emit_rectlist_dynamic_states(struct ilo_render *render,
413 const struct ilo_blitter *blitter,
414 struct ilo_render_rectlist_session *session)
415 {
416 const unsigned dynamic_used = ilo_builder_dynamic_used(render->builder);
417
418 ILO_DEV_ASSERT(render->dev, 6, 7.5);
419
420 /* both are inclusive */
421 session->vb_start = gen6_user_vertex_buffer(render->builder,
422 sizeof(blitter->vertices), (const void *) blitter->vertices);
423 session->vb_end = session->vb_start + sizeof(blitter->vertices) - 1;
424
425 if (blitter->uses & ILO_BLITTER_USE_DSA) {
426 render->state.DEPTH_STENCIL_STATE =
427 gen6_DEPTH_STENCIL_STATE(render->builder, &blitter->dsa);
428 }
429
430 if (blitter->uses & ILO_BLITTER_USE_CC) {
431 render->state.COLOR_CALC_STATE =
432 gen6_COLOR_CALC_STATE(render->builder, &blitter->cc.stencil_ref,
433 blitter->cc.alpha_ref, &blitter->cc.blend_color);
434 }
435
436 if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) {
437 render->state.CC_VIEWPORT =
438 gen6_CC_VIEWPORT(render->builder, &blitter->viewport, 1);
439 }
440
441 assert(ilo_builder_dynamic_used(render->builder) <= dynamic_used +
442 ilo_render_get_rectlist_dynamic_states_len(render, blitter));
443 }
444
445 static void
446 gen6_emit_launch_grid_dynamic_samplers(struct ilo_render *r,
447 const struct ilo_state_vector *vec,
448 struct ilo_render_launch_grid_session *session)
449 {
450 const unsigned shader_type = PIPE_SHADER_COMPUTE;
451 const struct ilo_shader_state *cs = vec->cs;
452 const struct ilo_sampler_cso * const *samplers =
453 vec->sampler[shader_type].cso;
454 const struct pipe_sampler_view * const *views =
455 (const struct pipe_sampler_view **) vec->view[shader_type].states;
456 int sampler_count, i;
457
458 ILO_DEV_ASSERT(r->dev, 7, 7.5);
459
460 sampler_count = ilo_shader_get_kernel_param(cs, ILO_KERNEL_SAMPLER_COUNT);
461
462 assert(sampler_count <= Elements(vec->view[shader_type].states) &&
463 sampler_count <= Elements(vec->sampler[shader_type].cso));
464
465 for (i = 0; i < sampler_count; i++) {
466 r->state.cs.SAMPLER_BORDER_COLOR_STATE[i] = (samplers[i]) ?
467 gen6_SAMPLER_BORDER_COLOR_STATE(r->builder, samplers[i]) : 0;
468 }
469
470 r->state.cs.SAMPLER_STATE = gen6_SAMPLER_STATE(r->builder, samplers, views,
471 r->state.cs.SAMPLER_BORDER_COLOR_STATE, sampler_count);
472 }
473
474 static void
475 gen6_emit_launch_grid_dynamic_pcb(struct ilo_render *r,
476 const struct ilo_state_vector *vec,
477 struct ilo_render_launch_grid_session *session)
478 {
479 r->state.cs.PUSH_CONSTANT_BUFFER = 0;
480 r->state.cs.PUSH_CONSTANT_BUFFER_size = 0;
481 }
482
483 static void
484 gen6_emit_launch_grid_dynamic_idrt(struct ilo_render *r,
485 const struct ilo_state_vector *vec,
486 struct ilo_render_launch_grid_session *session)
487 {
488 const struct ilo_shader_state *cs = vec->cs;
489 struct gen6_idrt_data data;
490
491 ILO_DEV_ASSERT(r->dev, 7, 7.5);
492
493 memset(&data, 0, sizeof(data));
494
495 data.cs = cs;
496 data.sampler_offset = r->state.cs.SAMPLER_STATE;
497 data.binding_table_offset = r->state.cs.BINDING_TABLE_STATE;
498
499 data.curbe_size = r->state.cs.PUSH_CONSTANT_BUFFER_size;
500 data.thread_group_size = session->thread_group_size;
501
502 session->idrt = gen6_INTERFACE_DESCRIPTOR_DATA(r->builder, &data, 1);
503 session->idrt_size = 32;
504 }
505
506 int
507 ilo_render_get_launch_grid_dynamic_states_len(const struct ilo_render *render,
508 const struct ilo_state_vector *vec)
509 {
510 const int alignment = 32 / 4;
511 int num_samplers;
512 int len = 0;
513
514 ILO_DEV_ASSERT(render->dev, 7, 7.5);
515
516 num_samplers = ilo_shader_get_kernel_param(vec->cs,
517 ILO_KERNEL_SAMPLER_COUNT);
518
519 /* SAMPLER_STATE array and SAMPLER_BORDER_COLORs */
520 if (num_samplers) {
521 /* prefetches are done in multiples of 4 */
522 num_samplers = align(num_samplers, 4);
523
524 len += align(GEN6_SAMPLER_STATE__SIZE * num_samplers, alignment) +
525 align(GEN6_SAMPLER_BORDER_COLOR__SIZE, alignment) * num_samplers;
526 }
527
528 len += GEN6_INTERFACE_DESCRIPTOR_DATA__SIZE;
529
530 return len;
531 }
532
533 void
534 ilo_render_emit_launch_grid_dynamic_states(struct ilo_render *render,
535 const struct ilo_state_vector *vec,
536 struct ilo_render_launch_grid_session *session)
537 {
538 const unsigned dynamic_used = ilo_builder_dynamic_used(render->builder);
539
540 ILO_DEV_ASSERT(render->dev, 7, 7.5);
541
542 gen6_emit_launch_grid_dynamic_samplers(render, vec, session);
543 gen6_emit_launch_grid_dynamic_pcb(render, vec, session);
544 gen6_emit_launch_grid_dynamic_idrt(render, vec, session);
545
546 assert(ilo_builder_dynamic_used(render->builder) <= dynamic_used +
547 ilo_render_get_launch_grid_dynamic_states_len(render, vec));
548 }