fda50dc7c80e2397a3134bbda4c4a32cb3fc98bf
[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_state.h"
32 #include "ilo_render_gen.h"
33
34 #define DIRTY(state) (session->pipe_dirty & ILO_DIRTY_ ## state)
35
36 static void
37 gen6_emit_draw_dynamic_viewports(struct ilo_render *r,
38 const struct ilo_state_vector *vec,
39 struct gen6_draw_session *session)
40 {
41 ILO_DEV_ASSERT(r->dev, 6, 6);
42
43 /* SF_VIEWPORT, CLIP_VIEWPORT, and CC_VIEWPORT */
44 if (DIRTY(VIEWPORT)) {
45 r->state.CLIP_VIEWPORT = gen6_CLIP_VIEWPORT(r->builder,
46 vec->viewport.cso, vec->viewport.count);
47
48 r->state.SF_VIEWPORT = gen6_SF_VIEWPORT(r->builder,
49 vec->viewport.cso, vec->viewport.count);
50
51 r->state.CC_VIEWPORT = gen6_CC_VIEWPORT(r->builder,
52 vec->viewport.cso, vec->viewport.count);
53
54 session->viewport_changed = true;
55 }
56 }
57
58 static void
59 gen7_emit_draw_dynamic_viewports(struct ilo_render *r,
60 const struct ilo_state_vector *vec,
61 struct gen6_draw_session *session)
62 {
63 ILO_DEV_ASSERT(r->dev, 7, 7.5);
64
65 /* SF_CLIP_VIEWPORT and CC_VIEWPORT */
66 if (DIRTY(VIEWPORT)) {
67 r->state.SF_CLIP_VIEWPORT = gen7_SF_CLIP_VIEWPORT(r->builder,
68 vec->viewport.cso, vec->viewport.count);
69
70 r->state.CC_VIEWPORT = gen6_CC_VIEWPORT(r->builder,
71 vec->viewport.cso, vec->viewport.count);
72
73 session->viewport_changed = true;
74 }
75 }
76
77 static void
78 gen6_emit_draw_dynamic_scissors(struct ilo_render *r,
79 const struct ilo_state_vector *vec,
80 struct gen6_draw_session *session)
81 {
82 ILO_DEV_ASSERT(r->dev, 6, 7.5);
83
84 /* SCISSOR_RECT */
85 if (DIRTY(SCISSOR) || DIRTY(VIEWPORT)) {
86 /* there should be as many scissors as there are viewports */
87 r->state.SCISSOR_RECT = gen6_SCISSOR_RECT(r->builder,
88 &vec->scissor, vec->viewport.count);
89
90 session->scissor_changed = true;
91 }
92 }
93
94 static void
95 gen6_emit_draw_dynamic_cc(struct ilo_render *r,
96 const struct ilo_state_vector *vec,
97 struct gen6_draw_session *session)
98 {
99 ILO_DEV_ASSERT(r->dev, 6, 7.5);
100
101 /* BLEND_STATE */
102 if (DIRTY(BLEND) || DIRTY(FB) || DIRTY(DSA)) {
103 r->state.BLEND_STATE = gen6_BLEND_STATE(r->builder,
104 vec->blend, &vec->fb, vec->dsa);
105
106 session->blend_changed = true;
107 }
108
109 /* COLOR_CALC_STATE */
110 if (DIRTY(DSA) || DIRTY(STENCIL_REF) || DIRTY(BLEND_COLOR)) {
111 r->state.COLOR_CALC_STATE =
112 gen6_COLOR_CALC_STATE(r->builder, &vec->stencil_ref,
113 vec->dsa->alpha_ref, &vec->blend_color);
114
115 session->cc_changed = true;
116 }
117
118 /* DEPTH_STENCIL_STATE */
119 if (DIRTY(DSA)) {
120 r->state.DEPTH_STENCIL_STATE =
121 gen6_DEPTH_STENCIL_STATE(r->builder, vec->dsa);
122
123 session->dsa_changed = true;
124 }
125 }
126
127 static void
128 gen6_emit_draw_dynamic_samplers(struct ilo_render *r,
129 const struct ilo_state_vector *vec,
130 int shader_type,
131 struct gen6_draw_session *session)
132 {
133 const struct ilo_sampler_cso * const *samplers =
134 vec->sampler[shader_type].cso;
135 const struct pipe_sampler_view * const *views =
136 (const struct pipe_sampler_view **) vec->view[shader_type].states;
137 const int num_samplers = vec->sampler[shader_type].count;
138 const int num_views = vec->view[shader_type].count;
139 uint32_t *sampler_state, *border_color_state;
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(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(SAMPLER_VS))
153 emit_border_color = true;
154
155 session->sampler_vs_changed = true;
156 } else {
157 skip = true;
158 }
159 break;
160 case PIPE_SHADER_FRAGMENT:
161 if (DIRTY(SAMPLER_FS) || DIRTY(VIEW_FS)) {
162 sampler_state = &r->state.wm.SAMPLER_STATE;
163 border_color_state = r->state.wm.SAMPLER_BORDER_COLOR_STATE;
164
165 if (DIRTY(SAMPLER_FS))
166 emit_border_color = true;
167
168 session->sampler_fs_changed = true;
169 } else {
170 skip = true;
171 }
172 break;
173 default:
174 skip = true;
175 break;
176 }
177
178 if (skip)
179 return;
180
181 if (emit_border_color) {
182 int i;
183
184 for (i = 0; i < num_samplers; i++) {
185 border_color_state[i] = (samplers[i]) ?
186 gen6_SAMPLER_BORDER_COLOR_STATE(r->builder, samplers[i]) : 0;
187 }
188 }
189
190 /* should we take the minimum of num_samplers and num_views? */
191 *sampler_state = gen6_SAMPLER_STATE(r->builder,
192 samplers, views,
193 border_color_state,
194 MIN2(num_samplers, num_views));
195 }
196
197 static void
198 gen6_emit_draw_dynamic_pcb(struct ilo_render *r,
199 const struct ilo_state_vector *vec,
200 struct gen6_draw_session *session)
201 {
202 ILO_DEV_ASSERT(r->dev, 6, 7.5);
203
204 /* push constant buffer for VS */
205 if (DIRTY(VS) || DIRTY(CBUF) || DIRTY(CLIP)) {
206 const int cbuf0_size = (vec->vs) ?
207 ilo_shader_get_kernel_param(vec->vs,
208 ILO_KERNEL_PCB_CBUF0_SIZE) : 0;
209 const int clip_state_size = (vec->vs) ?
210 ilo_shader_get_kernel_param(vec->vs,
211 ILO_KERNEL_VS_PCB_UCP_SIZE) : 0;
212 const int total_size = cbuf0_size + clip_state_size;
213
214 if (total_size) {
215 void *pcb;
216
217 r->state.vs.PUSH_CONSTANT_BUFFER =
218 gen6_push_constant_buffer(r->builder, total_size, &pcb);
219 r->state.vs.PUSH_CONSTANT_BUFFER_size = total_size;
220
221 if (cbuf0_size) {
222 const struct ilo_cbuf_state *cbuf =
223 &vec->cbuf[PIPE_SHADER_VERTEX];
224
225 if (cbuf0_size <= cbuf->cso[0].user_buffer_size) {
226 memcpy(pcb, cbuf->cso[0].user_buffer, cbuf0_size);
227 } else {
228 memcpy(pcb, cbuf->cso[0].user_buffer,
229 cbuf->cso[0].user_buffer_size);
230 memset(pcb + cbuf->cso[0].user_buffer_size, 0,
231 cbuf0_size - cbuf->cso[0].user_buffer_size);
232 }
233
234 pcb += cbuf0_size;
235 }
236
237 if (clip_state_size)
238 memcpy(pcb, &vec->clip, clip_state_size);
239
240 session->pcb_vs_changed = true;
241 } else if (r->state.vs.PUSH_CONSTANT_BUFFER_size) {
242 r->state.vs.PUSH_CONSTANT_BUFFER = 0;
243 r->state.vs.PUSH_CONSTANT_BUFFER_size = 0;
244
245 session->pcb_vs_changed = true;
246 }
247 }
248
249 /* push constant buffer for FS */
250 if (DIRTY(FS) || DIRTY(CBUF)) {
251 const int cbuf0_size = (vec->fs) ?
252 ilo_shader_get_kernel_param(vec->fs, ILO_KERNEL_PCB_CBUF0_SIZE) : 0;
253
254 if (cbuf0_size) {
255 const struct ilo_cbuf_state *cbuf = &vec->cbuf[PIPE_SHADER_FRAGMENT];
256 void *pcb;
257
258 r->state.wm.PUSH_CONSTANT_BUFFER =
259 gen6_push_constant_buffer(r->builder, cbuf0_size, &pcb);
260 r->state.wm.PUSH_CONSTANT_BUFFER_size = cbuf0_size;
261
262 if (cbuf0_size <= cbuf->cso[0].user_buffer_size) {
263 memcpy(pcb, cbuf->cso[0].user_buffer, cbuf0_size);
264 } else {
265 memcpy(pcb, cbuf->cso[0].user_buffer,
266 cbuf->cso[0].user_buffer_size);
267 memset(pcb + cbuf->cso[0].user_buffer_size, 0,
268 cbuf0_size - cbuf->cso[0].user_buffer_size);
269 }
270
271 session->pcb_fs_changed = true;
272 } else if (r->state.wm.PUSH_CONSTANT_BUFFER_size) {
273 r->state.wm.PUSH_CONSTANT_BUFFER = 0;
274 r->state.wm.PUSH_CONSTANT_BUFFER_size = 0;
275
276 session->pcb_fs_changed = true;
277 }
278 }
279 }
280
281 #undef DIRTY
282
283 int
284 ilo_render_get_draw_dynamic_states_len(const struct ilo_render *render,
285 const struct ilo_state_vector *vec)
286 {
287 static int static_len;
288 int sh_type, len;
289
290 ILO_DEV_ASSERT(render->dev, 6, 7.5);
291
292 if (!static_len) {
293 /* 64 bytes, or 16 dwords */
294 const int alignment = 64 / 4;
295
296 /* pad first */
297 len = alignment - 1;
298
299 /* CC states */
300 len += align(GEN6_BLEND_STATE__SIZE * ILO_MAX_DRAW_BUFFERS, alignment);
301 len += align(GEN6_DEPTH_STENCIL_STATE__SIZE, alignment);
302 len += align(GEN6_COLOR_CALC_STATE__SIZE, alignment);
303
304 /* viewport arrays */
305 if (ilo_dev_gen(render->dev) >= ILO_GEN(7)) {
306 len += 15 + /* pad first */
307 align(GEN7_SF_CLIP_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 16) +
308 align(GEN6_CC_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) +
309 align(GEN6_SCISSOR_RECT__SIZE * ILO_MAX_VIEWPORTS, 8);
310 } else {
311 len += 7 + /* pad first */
312 align(GEN6_SF_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) +
313 align(GEN6_CLIP_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) +
314 align(GEN6_CC_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) +
315 align(GEN6_SCISSOR_RECT__SIZE * ILO_MAX_VIEWPORTS, 8);
316 }
317
318 static_len = len;
319 }
320
321 len = static_len;
322
323 for (sh_type = 0; sh_type < PIPE_SHADER_TYPES; sh_type++) {
324 const int alignment = 32 / 4;
325 int num_samplers, pcb_len;
326
327 num_samplers = vec->sampler[sh_type].count;
328 pcb_len = 0;
329
330 switch (sh_type) {
331 case PIPE_SHADER_VERTEX:
332 if (vec->vs) {
333 pcb_len = ilo_shader_get_kernel_param(vec->vs,
334 ILO_KERNEL_PCB_CBUF0_SIZE);
335 pcb_len += ilo_shader_get_kernel_param(vec->vs,
336 ILO_KERNEL_VS_PCB_UCP_SIZE);
337 }
338 break;
339 case PIPE_SHADER_GEOMETRY:
340 break;
341 case PIPE_SHADER_FRAGMENT:
342 if (vec->fs) {
343 pcb_len = ilo_shader_get_kernel_param(vec->fs,
344 ILO_KERNEL_PCB_CBUF0_SIZE);
345 }
346 break;
347 default:
348 break;
349 }
350
351 /* SAMPLER_STATE array and SAMPLER_BORDER_COLORs */
352 if (num_samplers) {
353 len += align(GEN6_SAMPLER_STATE__SIZE * num_samplers, alignment) +
354 align(GEN6_SAMPLER_BORDER_COLOR__SIZE, alignment) * num_samplers;
355 }
356
357 /* PCB */
358 if (pcb_len)
359 len += align(pcb_len, alignment);
360 }
361
362 return len;
363 }
364
365 void
366 ilo_render_emit_draw_dynamic_states(struct ilo_render *render,
367 const struct ilo_state_vector *vec,
368 struct gen6_draw_session *session)
369 {
370 const unsigned dynamic_used = ilo_builder_dynamic_used(render->builder);
371
372 ILO_DEV_ASSERT(render->dev, 6, 7.5);
373
374 if (ilo_dev_gen(render->dev) >= ILO_GEN(7))
375 gen7_emit_draw_dynamic_viewports(render, vec, session);
376 else
377 gen6_emit_draw_dynamic_viewports(render, vec, session);
378
379 gen6_emit_draw_dynamic_cc(render, vec, session);
380 gen6_emit_draw_dynamic_scissors(render, vec, session);
381 gen6_emit_draw_dynamic_pcb(render, vec, session);
382
383 gen6_emit_draw_dynamic_samplers(render, vec,
384 PIPE_SHADER_VERTEX, session);
385 gen6_emit_draw_dynamic_samplers(render, vec,
386 PIPE_SHADER_FRAGMENT, session);
387
388 assert(ilo_builder_dynamic_used(render->builder) <= dynamic_used +
389 ilo_render_get_draw_dynamic_states_len(render, vec));
390 }
391
392 int
393 ilo_render_get_rectlist_dynamic_states_len(const struct ilo_render *render,
394 const struct ilo_blitter *blitter)
395 {
396 ILO_DEV_ASSERT(render->dev, 6, 7.5);
397
398 return 64;
399 }
400
401 void
402 ilo_render_emit_rectlist_dynamic_states(struct ilo_render *render,
403 const struct ilo_blitter *blitter)
404 {
405 const unsigned dynamic_used = ilo_builder_dynamic_used(render->builder);
406
407 ILO_DEV_ASSERT(render->dev, 6, 7.5);
408
409 if (blitter->uses & ILO_BLITTER_USE_DSA) {
410 render->state.DEPTH_STENCIL_STATE =
411 gen6_DEPTH_STENCIL_STATE(render->builder, &blitter->dsa);
412 }
413
414 if (blitter->uses & ILO_BLITTER_USE_CC) {
415 render->state.COLOR_CALC_STATE =
416 gen6_COLOR_CALC_STATE(render->builder, &blitter->cc.stencil_ref,
417 blitter->cc.alpha_ref, &blitter->cc.blend_color);
418 }
419
420 if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) {
421 render->state.CC_VIEWPORT =
422 gen6_CC_VIEWPORT(render->builder, &blitter->viewport, 1);
423 }
424
425 assert(ilo_builder_dynamic_used(render->builder) <= dynamic_used +
426 ilo_render_get_rectlist_dynamic_states_len(render, blitter));
427 }