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