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 "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"
35 #define DIRTY(state) (session->pipe_dirty & ILO_DIRTY_ ## state)
38 gen6_emit_draw_dynamic_viewports(struct ilo_render
*r
,
39 const struct ilo_state_vector
*vec
,
40 struct ilo_render_draw_session
*session
)
42 ILO_DEV_ASSERT(r
->dev
, 6, 6);
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
);
49 r
->state
.SF_VIEWPORT
= gen6_SF_VIEWPORT(r
->builder
,
50 vec
->viewport
.cso
, vec
->viewport
.count
);
52 r
->state
.CC_VIEWPORT
= gen6_CC_VIEWPORT(r
->builder
,
53 vec
->viewport
.cso
, vec
->viewport
.count
);
55 session
->viewport_changed
= true;
60 gen7_emit_draw_dynamic_viewports(struct ilo_render
*r
,
61 const struct ilo_state_vector
*vec
,
62 struct ilo_render_draw_session
*session
)
64 ILO_DEV_ASSERT(r
->dev
, 7, 7.5);
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
);
71 r
->state
.CC_VIEWPORT
= gen6_CC_VIEWPORT(r
->builder
,
72 vec
->viewport
.cso
, vec
->viewport
.count
);
74 session
->viewport_changed
= true;
79 gen6_emit_draw_dynamic_scissors(struct ilo_render
*r
,
80 const struct ilo_state_vector
*vec
,
81 struct ilo_render_draw_session
*session
)
83 ILO_DEV_ASSERT(r
->dev
, 6, 7.5);
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
);
91 session
->scissor_changed
= true;
96 gen6_emit_draw_dynamic_cc(struct ilo_render
*r
,
97 const struct ilo_state_vector
*vec
,
98 struct ilo_render_draw_session
*session
)
100 ILO_DEV_ASSERT(r
->dev
, 6, 7.5);
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
);
107 session
->blend_changed
= true;
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
);
116 session
->cc_changed
= true;
119 /* DEPTH_STENCIL_STATE */
121 r
->state
.DEPTH_STENCIL_STATE
=
122 gen6_DEPTH_STENCIL_STATE(r
->builder
, vec
->dsa
);
124 session
->dsa_changed
= true;
129 gen6_emit_draw_dynamic_samplers(struct ilo_render
*r
,
130 const struct ilo_state_vector
*vec
,
132 struct ilo_render_draw_session
*session
)
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
;
140 bool emit_border_color
= false;
143 ILO_DEV_ASSERT(r
->dev
, 6, 7.5);
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
;
152 if (DIRTY(VS
) || DIRTY(SAMPLER_VS
))
153 emit_border_color
= true;
155 sampler_count
= (vec
->vs
) ? ilo_shader_get_kernel_param(vec
->vs
,
156 ILO_KERNEL_SAMPLER_COUNT
) : 0;
158 session
->sampler_vs_changed
= true;
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
;
168 if (DIRTY(VS
) || DIRTY(SAMPLER_FS
))
169 emit_border_color
= true;
171 sampler_count
= (vec
->fs
) ? ilo_shader_get_kernel_param(vec
->fs
,
172 ILO_KERNEL_SAMPLER_COUNT
) : 0;
174 session
->sampler_fs_changed
= true;
187 assert(sampler_count
<= Elements(vec
->view
[shader_type
].states
) &&
188 sampler_count
<= Elements(vec
->sampler
[shader_type
].cso
));
190 if (emit_border_color
) {
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;
199 *sampler_state
= gen6_SAMPLER_STATE(r
->builder
,
200 samplers
, views
, border_color_state
, sampler_count
);
204 gen6_emit_draw_dynamic_pcb(struct ilo_render
*r
,
205 const struct ilo_state_vector
*vec
,
206 struct ilo_render_draw_session
*session
)
208 ILO_DEV_ASSERT(r
->dev
, 6, 7.5);
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
;
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
;
228 const struct ilo_cbuf_state
*cbuf
=
229 &vec
->cbuf
[PIPE_SHADER_VERTEX
];
231 if (cbuf0_size
<= cbuf
->cso
[0].user_buffer_size
) {
232 memcpy(pcb
, cbuf
->cso
[0].user_buffer
, cbuf0_size
);
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
);
244 memcpy(pcb
, &vec
->clip
, clip_state_size
);
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;
251 session
->pcb_vs_changed
= true;
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;
261 const struct ilo_cbuf_state
*cbuf
= &vec
->cbuf
[PIPE_SHADER_FRAGMENT
];
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
;
268 if (cbuf0_size
<= cbuf
->cso
[0].user_buffer_size
) {
269 memcpy(pcb
, cbuf
->cso
[0].user_buffer
, cbuf0_size
);
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
);
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;
282 session
->pcb_fs_changed
= true;
290 ilo_render_get_draw_dynamic_states_len(const struct ilo_render
*render
,
291 const struct ilo_state_vector
*vec
)
293 static int static_len
;
296 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
299 /* 64 bytes, or 16 dwords */
300 const int alignment
= 64 / 4;
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
);
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);
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);
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;
334 case PIPE_SHADER_VERTEX
:
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
);
344 case PIPE_SHADER_GEOMETRY
:
346 case PIPE_SHADER_FRAGMENT
:
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
);
358 /* SAMPLER_STATE array and SAMPLER_BORDER_COLORs */
360 /* prefetches are done in multiples of 4 */
361 num_samplers
= align(num_samplers
, 4);
363 len
+= align(GEN6_SAMPLER_STATE__SIZE
* num_samplers
, alignment
) +
364 align(GEN6_SAMPLER_BORDER_COLOR__SIZE
, alignment
) * num_samplers
;
369 len
+= align(pcb_len
, alignment
);
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
)
380 const unsigned dynamic_used
= ilo_builder_dynamic_used(render
->builder
);
382 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
384 if (ilo_dev_gen(render
->dev
) >= ILO_GEN(7))
385 gen7_emit_draw_dynamic_viewports(render
, vec
, session
);
387 gen6_emit_draw_dynamic_viewports(render
, vec
, session
);
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
);
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
);
398 assert(ilo_builder_dynamic_used(render
->builder
) <= dynamic_used
+
399 ilo_render_get_draw_dynamic_states_len(render
, vec
));
403 ilo_render_get_rectlist_dynamic_states_len(const struct ilo_render
*render
,
404 const struct ilo_blitter
*blitter
)
406 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
412 ilo_render_emit_rectlist_dynamic_states(struct ilo_render
*render
,
413 const struct ilo_blitter
*blitter
,
414 struct ilo_render_rectlist_session
*session
)
416 const unsigned dynamic_used
= ilo_builder_dynamic_used(render
->builder
);
418 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
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;
425 if (blitter
->uses
& ILO_BLITTER_USE_DSA
) {
426 render
->state
.DEPTH_STENCIL_STATE
=
427 gen6_DEPTH_STENCIL_STATE(render
->builder
, &blitter
->dsa
);
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
);
436 if (blitter
->uses
& ILO_BLITTER_USE_VIEWPORT
) {
437 render
->state
.CC_VIEWPORT
=
438 gen6_CC_VIEWPORT(render
->builder
, &blitter
->viewport
, 1);
441 assert(ilo_builder_dynamic_used(render
->builder
) <= dynamic_used
+
442 ilo_render_get_rectlist_dynamic_states_len(render
, blitter
));
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
)
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
;
458 ILO_DEV_ASSERT(r
->dev
, 7, 7.5);
460 sampler_count
= ilo_shader_get_kernel_param(cs
, ILO_KERNEL_SAMPLER_COUNT
);
462 assert(sampler_count
<= Elements(vec
->view
[shader_type
].states
) &&
463 sampler_count
<= Elements(vec
->sampler
[shader_type
].cso
));
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;
470 r
->state
.cs
.SAMPLER_STATE
= gen6_SAMPLER_STATE(r
->builder
, samplers
, views
,
471 r
->state
.cs
.SAMPLER_BORDER_COLOR_STATE
, sampler_count
);
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
)
479 r
->state
.cs
.PUSH_CONSTANT_BUFFER
= 0;
480 r
->state
.cs
.PUSH_CONSTANT_BUFFER_size
= 0;
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
)
488 const struct ilo_shader_state
*cs
= vec
->cs
;
489 struct gen6_idrt_data data
;
491 ILO_DEV_ASSERT(r
->dev
, 7, 7.5);
493 memset(&data
, 0, sizeof(data
));
496 data
.sampler_offset
= r
->state
.cs
.SAMPLER_STATE
;
497 data
.binding_table_offset
= r
->state
.cs
.BINDING_TABLE_STATE
;
499 data
.curbe_size
= r
->state
.cs
.PUSH_CONSTANT_BUFFER_size
;
500 data
.thread_group_size
= session
->thread_group_size
;
502 session
->idrt
= gen6_INTERFACE_DESCRIPTOR_DATA(r
->builder
, &data
, 1);
503 session
->idrt_size
= 32;
507 ilo_render_get_launch_grid_dynamic_states_len(const struct ilo_render
*render
,
508 const struct ilo_state_vector
*vec
)
510 const int alignment
= 32 / 4;
514 ILO_DEV_ASSERT(render
->dev
, 7, 7.5);
516 num_samplers
= ilo_shader_get_kernel_param(vec
->cs
,
517 ILO_KERNEL_SAMPLER_COUNT
);
519 /* SAMPLER_STATE array and SAMPLER_BORDER_COLORs */
521 /* prefetches are done in multiples of 4 */
522 num_samplers
= align(num_samplers
, 4);
524 len
+= align(GEN6_SAMPLER_STATE__SIZE
* num_samplers
, alignment
) +
525 align(GEN6_SAMPLER_BORDER_COLOR__SIZE
, alignment
) * num_samplers
;
528 len
+= GEN6_INTERFACE_DESCRIPTOR_DATA__SIZE
;
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
)
538 const unsigned dynamic_used
= ilo_builder_dynamic_used(render
->builder
);
540 ILO_DEV_ASSERT(render
->dev
, 7, 7.5);
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
);
546 assert(ilo_builder_dynamic_used(render
->builder
) <= dynamic_used
+
547 ilo_render_get_launch_grid_dynamic_states_len(render
, vec
));