2 * Mesa 3-D graphics library
4 * Copyright (C) 2012-2014 LunarG, Inc.
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:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
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.
25 * Chia-I Wu <olv@lunarg.com>
28 #include "core/ilo_builder_3d.h"
29 #include "core/ilo_builder_media.h"
31 #include "ilo_common.h"
32 #include "ilo_blitter.h"
33 #include "ilo_state.h"
34 #include "ilo_render_gen.h"
36 #define DIRTY(state) (session->pipe_dirty & ILO_DIRTY_ ## state)
39 gen6_emit_draw_dynamic_viewports(struct ilo_render
*r
,
40 const struct ilo_state_vector
*vec
,
41 struct ilo_render_draw_session
*session
)
43 ILO_DEV_ASSERT(r
->dev
, 6, 6);
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
);
50 r
->state
.SF_VIEWPORT
= gen6_SF_VIEWPORT(r
->builder
,
51 vec
->viewport
.cso
, vec
->viewport
.count
);
53 r
->state
.CC_VIEWPORT
= gen6_CC_VIEWPORT(r
->builder
,
54 vec
->viewport
.cso
, vec
->viewport
.count
);
56 session
->viewport_changed
= true;
61 gen7_emit_draw_dynamic_viewports(struct ilo_render
*r
,
62 const struct ilo_state_vector
*vec
,
63 struct ilo_render_draw_session
*session
)
65 ILO_DEV_ASSERT(r
->dev
, 7, 8);
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
);
72 r
->state
.CC_VIEWPORT
= gen6_CC_VIEWPORT(r
->builder
,
73 vec
->viewport
.cso
, vec
->viewport
.count
);
75 session
->viewport_changed
= true;
80 gen6_emit_draw_dynamic_scissors(struct ilo_render
*r
,
81 const struct ilo_state_vector
*vec
,
82 struct ilo_render_draw_session
*session
)
84 ILO_DEV_ASSERT(r
->dev
, 6, 8);
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
);
92 session
->scissor_changed
= true;
97 gen6_emit_draw_dynamic_cc(struct ilo_render
*r
,
98 const struct ilo_state_vector
*vec
,
99 struct ilo_render_draw_session
*session
)
101 ILO_DEV_ASSERT(r
->dev
, 6, 8);
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
);
109 r
->state
.BLEND_STATE
= gen6_BLEND_STATE(r
->builder
,
110 vec
->blend
, &vec
->fb
, vec
->dsa
);
113 session
->blend_changed
= true;
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
);
122 session
->cc_changed
= true;
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
);
130 session
->dsa_changed
= true;
135 gen6_emit_draw_dynamic_samplers(struct ilo_render
*r
,
136 const struct ilo_state_vector
*vec
,
138 struct ilo_render_draw_session
*session
)
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
;
146 bool emit_border_color
= false;
149 ILO_DEV_ASSERT(r
->dev
, 6, 8);
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
;
158 if (DIRTY(VS
) || DIRTY(SAMPLER_VS
))
159 emit_border_color
= true;
161 sampler_count
= (vec
->vs
) ? ilo_shader_get_kernel_param(vec
->vs
,
162 ILO_KERNEL_SAMPLER_COUNT
) : 0;
164 session
->sampler_vs_changed
= true;
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
;
174 if (DIRTY(VS
) || DIRTY(SAMPLER_FS
))
175 emit_border_color
= true;
177 sampler_count
= (vec
->fs
) ? ilo_shader_get_kernel_param(vec
->fs
,
178 ILO_KERNEL_SAMPLER_COUNT
) : 0;
180 session
->sampler_fs_changed
= true;
193 assert(sampler_count
<= Elements(vec
->view
[shader_type
].states
) &&
194 sampler_count
<= Elements(vec
->sampler
[shader_type
].cso
));
196 if (emit_border_color
) {
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;
205 *sampler_state
= gen6_SAMPLER_STATE(r
->builder
,
206 samplers
, views
, border_color_state
, sampler_count
);
210 gen6_emit_draw_dynamic_pcb(struct ilo_render
*r
,
211 const struct ilo_state_vector
*vec
,
212 struct ilo_render_draw_session
*session
)
214 ILO_DEV_ASSERT(r
->dev
, 6, 8);
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
;
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
;
234 const struct ilo_cbuf_state
*cbuf
=
235 &vec
->cbuf
[PIPE_SHADER_VERTEX
];
237 if (cbuf0_size
<= cbuf
->cso
[0].info
.size
) {
238 memcpy(pcb
, cbuf
->cso
[0].user_buffer
, cbuf0_size
);
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
);
250 memcpy(pcb
, &vec
->clip
, clip_state_size
);
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;
257 session
->pcb_vs_changed
= true;
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;
267 const struct ilo_cbuf_state
*cbuf
= &vec
->cbuf
[PIPE_SHADER_FRAGMENT
];
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
;
274 if (cbuf0_size
<= cbuf
->cso
[0].info
.size
) {
275 memcpy(pcb
, cbuf
->cso
[0].user_buffer
, cbuf0_size
);
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
);
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;
288 session
->pcb_fs_changed
= true;
296 ilo_render_get_draw_dynamic_states_len(const struct ilo_render
*render
,
297 const struct ilo_state_vector
*vec
)
299 static int static_len
;
302 ILO_DEV_ASSERT(render
->dev
, 6, 8);
305 /* 64 bytes, or 16 dwords */
306 const int alignment
= 64 / 4;
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
);
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);
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);
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;
341 case PIPE_SHADER_VERTEX
:
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
);
351 case PIPE_SHADER_GEOMETRY
:
353 case PIPE_SHADER_FRAGMENT
:
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
);
365 /* SAMPLER_STATE array and SAMPLER_BORDER_COLORs */
367 /* prefetches are done in multiples of 4 */
368 num_samplers
= align(num_samplers
, 4);
370 len
+= align(GEN6_SAMPLER_STATE__SIZE
* num_samplers
, alignment
);
372 if (ilo_dev_gen(render
->dev
) >= ILO_GEN(8)) {
373 len
+= align(GEN6_SAMPLER_BORDER_COLOR_STATE__SIZE
, 64 / 4) *
376 len
+= align(GEN6_SAMPLER_BORDER_COLOR_STATE__SIZE
, alignment
) *
383 len
+= align(pcb_len
, alignment
);
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
)
394 const unsigned dynamic_used
= ilo_builder_dynamic_used(render
->builder
);
396 ILO_DEV_ASSERT(render
->dev
, 6, 8);
398 if (ilo_dev_gen(render
->dev
) >= ILO_GEN(7))
399 gen7_emit_draw_dynamic_viewports(render
, vec
, session
);
401 gen6_emit_draw_dynamic_viewports(render
, vec
, session
);
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
);
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
);
412 assert(ilo_builder_dynamic_used(render
->builder
) <= dynamic_used
+
413 ilo_render_get_draw_dynamic_states_len(render
, vec
));
417 ilo_render_get_rectlist_dynamic_states_len(const struct ilo_render
*render
,
418 const struct ilo_blitter
*blitter
)
420 ILO_DEV_ASSERT(render
->dev
, 6, 8);
422 return (ilo_dev_gen(render
->dev
) >= ILO_GEN(8)) ? 0 : 96;
426 ilo_render_emit_rectlist_dynamic_states(struct ilo_render
*render
,
427 const struct ilo_blitter
*blitter
,
428 struct ilo_render_rectlist_session
*session
)
430 const unsigned dynamic_used
= ilo_builder_dynamic_used(render
->builder
);
432 ILO_DEV_ASSERT(render
->dev
, 6, 8);
434 if (ilo_dev_gen(render
->dev
) >= ILO_GEN(8))
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;
442 if (blitter
->uses
& ILO_BLITTER_USE_DSA
) {
443 render
->state
.DEPTH_STENCIL_STATE
=
444 gen6_DEPTH_STENCIL_STATE(render
->builder
, &blitter
->dsa
);
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
);
453 if (blitter
->uses
& ILO_BLITTER_USE_VIEWPORT
) {
454 render
->state
.CC_VIEWPORT
=
455 gen6_CC_VIEWPORT(render
->builder
, &blitter
->viewport
, 1);
458 assert(ilo_builder_dynamic_used(render
->builder
) <= dynamic_used
+
459 ilo_render_get_rectlist_dynamic_states_len(render
, blitter
));
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
)
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
;
475 ILO_DEV_ASSERT(r
->dev
, 7, 7.5);
477 sampler_count
= ilo_shader_get_kernel_param(cs
, ILO_KERNEL_SAMPLER_COUNT
);
479 assert(sampler_count
<= Elements(vec
->view
[shader_type
].states
) &&
480 sampler_count
<= Elements(vec
->sampler
[shader_type
].cso
));
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;
487 r
->state
.cs
.SAMPLER_STATE
= gen6_SAMPLER_STATE(r
->builder
, samplers
, views
,
488 r
->state
.cs
.SAMPLER_BORDER_COLOR_STATE
, sampler_count
);
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
)
496 r
->state
.cs
.PUSH_CONSTANT_BUFFER
= 0;
497 r
->state
.cs
.PUSH_CONSTANT_BUFFER_size
= 0;
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
)
505 const struct ilo_shader_state
*cs
= vec
->cs
;
506 struct gen6_idrt_data data
;
508 ILO_DEV_ASSERT(r
->dev
, 7, 7.5);
510 memset(&data
, 0, sizeof(data
));
513 data
.sampler_offset
= r
->state
.cs
.SAMPLER_STATE
;
514 data
.binding_table_offset
= r
->state
.cs
.BINDING_TABLE_STATE
;
516 data
.curbe_size
= r
->state
.cs
.PUSH_CONSTANT_BUFFER_size
;
517 data
.thread_group_size
= session
->thread_group_size
;
519 session
->idrt
= gen6_INTERFACE_DESCRIPTOR_DATA(r
->builder
, &data
, 1);
520 session
->idrt_size
= 32;
524 ilo_render_get_launch_grid_dynamic_states_len(const struct ilo_render
*render
,
525 const struct ilo_state_vector
*vec
)
527 const int alignment
= 32 / 4;
531 ILO_DEV_ASSERT(render
->dev
, 7, 7.5);
533 num_samplers
= ilo_shader_get_kernel_param(vec
->cs
,
534 ILO_KERNEL_SAMPLER_COUNT
);
536 /* SAMPLER_STATE array and SAMPLER_BORDER_COLORs */
538 /* prefetches are done in multiples of 4 */
539 num_samplers
= align(num_samplers
, 4);
541 len
+= align(GEN6_SAMPLER_STATE__SIZE
* num_samplers
, alignment
) +
542 align(GEN6_SAMPLER_BORDER_COLOR_STATE__SIZE
, alignment
) *
546 len
+= GEN6_INTERFACE_DESCRIPTOR_DATA__SIZE
;
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
)
556 const unsigned dynamic_used
= ilo_builder_dynamic_used(render
->builder
);
558 ILO_DEV_ASSERT(render
->dev
, 7, 7.5);
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
);
564 assert(ilo_builder_dynamic_used(render
->builder
) <= dynamic_used
+
565 ilo_render_get_launch_grid_dynamic_states_len(render
, vec
));