ilo: introduce ilo_shader_cso for VS
[mesa.git] / src / gallium / drivers / ilo / ilo_shader.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2012-2013 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 "tgsi/tgsi_parse.h"
29 #include "intel_winsys.h"
30
31 #include "shader/ilo_shader_internal.h"
32 #include "ilo_state.h"
33 #include "ilo_shader.h"
34
35 struct ilo_shader_cache {
36 struct list_head shaders;
37 struct list_head changed;
38 };
39
40 /**
41 * Create a shader cache. A shader cache can manage shaders and upload them
42 * to a bo as a whole.
43 */
44 struct ilo_shader_cache *
45 ilo_shader_cache_create(void)
46 {
47 struct ilo_shader_cache *shc;
48
49 shc = CALLOC_STRUCT(ilo_shader_cache);
50 if (!shc)
51 return NULL;
52
53 list_inithead(&shc->shaders);
54 list_inithead(&shc->changed);
55
56 return shc;
57 }
58
59 /**
60 * Destroy a shader cache.
61 */
62 void
63 ilo_shader_cache_destroy(struct ilo_shader_cache *shc)
64 {
65 FREE(shc);
66 }
67
68 /**
69 * Add a shader to the cache.
70 */
71 void
72 ilo_shader_cache_add(struct ilo_shader_cache *shc,
73 struct ilo_shader_state *shader)
74 {
75 struct ilo_shader *sh;
76
77 shader->cache = shc;
78 LIST_FOR_EACH_ENTRY(sh, &shader->variants, list)
79 sh->uploaded = false;
80
81 list_add(&shader->list, &shc->changed);
82 }
83
84 /**
85 * Remove a shader from the cache.
86 */
87 void
88 ilo_shader_cache_remove(struct ilo_shader_cache *shc,
89 struct ilo_shader_state *shader)
90 {
91 list_del(&shader->list);
92 shader->cache = NULL;
93 }
94
95 /**
96 * Notify the cache that a managed shader has changed.
97 */
98 static void
99 ilo_shader_cache_notify_change(struct ilo_shader_cache *shc,
100 struct ilo_shader_state *shader)
101 {
102 if (shader->cache == shc) {
103 list_del(&shader->list);
104 list_add(&shader->list, &shc->changed);
105 }
106 }
107
108 /**
109 * Upload a managed shader to the bo.
110 */
111 static int
112 ilo_shader_cache_upload_shader(struct ilo_shader_cache *shc,
113 struct ilo_shader_state *shader,
114 struct intel_bo *bo, unsigned offset,
115 bool incremental)
116 {
117 const unsigned base = offset;
118 struct ilo_shader *sh;
119
120 LIST_FOR_EACH_ENTRY(sh, &shader->variants, list) {
121 int err;
122
123 if (incremental && sh->uploaded)
124 continue;
125
126 /* kernels must be aligned to 64-byte */
127 offset = align(offset, 64);
128
129 err = intel_bo_pwrite(bo, offset, sh->kernel_size, sh->kernel);
130 if (unlikely(err))
131 return -1;
132
133 sh->uploaded = true;
134 sh->cache_offset = offset;
135
136 offset += sh->kernel_size;
137 }
138
139 return (int) (offset - base);
140 }
141
142 /**
143 * Similar to ilo_shader_cache_upload(), except no upload happens.
144 */
145 static int
146 ilo_shader_cache_get_upload_size(struct ilo_shader_cache *shc,
147 unsigned offset,
148 bool incremental)
149 {
150 const unsigned base = offset;
151 struct ilo_shader_state *shader;
152
153 if (!incremental) {
154 LIST_FOR_EACH_ENTRY(shader, &shc->shaders, list) {
155 struct ilo_shader *sh;
156
157 /* see ilo_shader_cache_upload_shader() */
158 LIST_FOR_EACH_ENTRY(sh, &shader->variants, list) {
159 if (!incremental || !sh->uploaded)
160 offset = align(offset, 64) + sh->kernel_size;
161 }
162 }
163 }
164
165 LIST_FOR_EACH_ENTRY(shader, &shc->changed, list) {
166 struct ilo_shader *sh;
167
168 /* see ilo_shader_cache_upload_shader() */
169 LIST_FOR_EACH_ENTRY(sh, &shader->variants, list) {
170 if (!incremental || !sh->uploaded)
171 offset = align(offset, 64) + sh->kernel_size;
172 }
173 }
174
175 /*
176 * From the Sandy Bridge PRM, volume 4 part 2, page 112:
177 *
178 * "Due to prefetch of the instruction stream, the EUs may attempt to
179 * access up to 8 instructions (128 bytes) beyond the end of the
180 * kernel program - possibly into the next memory page. Although
181 * these instructions will not be executed, software must account for
182 * the prefetch in order to avoid invalid page access faults."
183 */
184 if (offset > base)
185 offset += 128;
186
187 return (int) (offset - base);
188 }
189
190 /**
191 * Upload managed shaders to the bo. When incremental is true, only shaders
192 * that are changed or added after the last upload are uploaded.
193 */
194 int
195 ilo_shader_cache_upload(struct ilo_shader_cache *shc,
196 struct intel_bo *bo, unsigned offset,
197 bool incremental)
198 {
199 struct ilo_shader_state *shader, *next;
200 int size = 0, s;
201
202 if (!bo)
203 return ilo_shader_cache_get_upload_size(shc, offset, incremental);
204
205 if (!incremental) {
206 LIST_FOR_EACH_ENTRY(shader, &shc->shaders, list) {
207 s = ilo_shader_cache_upload_shader(shc, shader,
208 bo, offset, incremental);
209 if (unlikely(s < 0))
210 return s;
211
212 size += s;
213 offset += s;
214 }
215 }
216
217 LIST_FOR_EACH_ENTRY_SAFE(shader, next, &shc->changed, list) {
218 s = ilo_shader_cache_upload_shader(shc, shader,
219 bo, offset, incremental);
220 if (unlikely(s < 0))
221 return s;
222
223 size += s;
224 offset += s;
225
226 list_del(&shader->list);
227 list_add(&shader->list, &shc->shaders);
228 }
229
230 return size;
231 }
232
233 /**
234 * Initialize a shader variant.
235 */
236 void
237 ilo_shader_variant_init(struct ilo_shader_variant *variant,
238 const struct ilo_shader_info *info,
239 const struct ilo_context *ilo)
240 {
241 int num_views, i;
242
243 memset(variant, 0, sizeof(*variant));
244
245 switch (info->type) {
246 case PIPE_SHADER_VERTEX:
247 variant->u.vs.rasterizer_discard =
248 ilo->rasterizer->state.rasterizer_discard;
249 variant->u.vs.num_ucps =
250 util_last_bit(ilo->rasterizer->state.clip_plane_enable);
251 break;
252 case PIPE_SHADER_GEOMETRY:
253 variant->u.gs.rasterizer_discard =
254 ilo->rasterizer->state.rasterizer_discard;
255 variant->u.gs.num_inputs = ilo->vs->shader->out.count;
256 for (i = 0; i < ilo->vs->shader->out.count; i++) {
257 variant->u.gs.semantic_names[i] =
258 ilo->vs->shader->out.semantic_names[i];
259 variant->u.gs.semantic_indices[i] =
260 ilo->vs->shader->out.semantic_indices[i];
261 }
262 break;
263 case PIPE_SHADER_FRAGMENT:
264 variant->u.fs.flatshade =
265 (info->has_color_interp && ilo->rasterizer->state.flatshade);
266 variant->u.fs.fb_height = (info->has_pos) ?
267 ilo->fb.state.height : 1;
268 variant->u.fs.num_cbufs = ilo->fb.state.nr_cbufs;
269 break;
270 default:
271 assert(!"unknown shader type");
272 break;
273 }
274
275 num_views = ilo->view[info->type].count;
276 assert(info->num_samplers <= num_views);
277
278 variant->num_sampler_views = info->num_samplers;
279 for (i = 0; i < info->num_samplers; i++) {
280 const struct pipe_sampler_view *view = ilo->view[info->type].states[i];
281 const struct ilo_sampler_cso *sampler = ilo->sampler[info->type].cso[i];
282
283 if (view) {
284 variant->sampler_view_swizzles[i].r = view->swizzle_r;
285 variant->sampler_view_swizzles[i].g = view->swizzle_g;
286 variant->sampler_view_swizzles[i].b = view->swizzle_b;
287 variant->sampler_view_swizzles[i].a = view->swizzle_a;
288 }
289 else if (info->shadow_samplers & (1 << i)) {
290 variant->sampler_view_swizzles[i].r = PIPE_SWIZZLE_RED;
291 variant->sampler_view_swizzles[i].g = PIPE_SWIZZLE_RED;
292 variant->sampler_view_swizzles[i].b = PIPE_SWIZZLE_RED;
293 variant->sampler_view_swizzles[i].a = PIPE_SWIZZLE_ONE;
294 }
295 else {
296 variant->sampler_view_swizzles[i].r = PIPE_SWIZZLE_RED;
297 variant->sampler_view_swizzles[i].g = PIPE_SWIZZLE_GREEN;
298 variant->sampler_view_swizzles[i].b = PIPE_SWIZZLE_BLUE;
299 variant->sampler_view_swizzles[i].a = PIPE_SWIZZLE_ALPHA;
300 }
301
302 /*
303 * When non-nearest filter and PIPE_TEX_WRAP_CLAMP wrap mode is used,
304 * the HW wrap mode is set to BRW_TEXCOORDMODE_CLAMP_BORDER, and we need
305 * to manually saturate the texture coordinates.
306 */
307 if (sampler) {
308 variant->saturate_tex_coords[0] |= sampler->saturate_s << i;
309 variant->saturate_tex_coords[1] |= sampler->saturate_t << i;
310 variant->saturate_tex_coords[2] |= sampler->saturate_r << i;
311 }
312 }
313 }
314
315 /**
316 * Guess the shader variant, knowing that the context may still change.
317 */
318 static void
319 ilo_shader_variant_guess(struct ilo_shader_variant *variant,
320 const struct ilo_shader_info *info,
321 const struct ilo_context *ilo)
322 {
323 int i;
324
325 memset(variant, 0, sizeof(*variant));
326
327 switch (info->type) {
328 case PIPE_SHADER_VERTEX:
329 break;
330 case PIPE_SHADER_GEOMETRY:
331 break;
332 case PIPE_SHADER_FRAGMENT:
333 variant->u.fs.flatshade = false;
334 variant->u.fs.fb_height = (info->has_pos) ?
335 ilo->fb.state.height : 1;
336 variant->u.fs.num_cbufs = 1;
337 break;
338 default:
339 assert(!"unknown shader type");
340 break;
341 }
342
343 variant->num_sampler_views = info->num_samplers;
344 for (i = 0; i < info->num_samplers; i++) {
345 if (info->shadow_samplers & (1 << i)) {
346 variant->sampler_view_swizzles[i].r = PIPE_SWIZZLE_RED;
347 variant->sampler_view_swizzles[i].g = PIPE_SWIZZLE_RED;
348 variant->sampler_view_swizzles[i].b = PIPE_SWIZZLE_RED;
349 variant->sampler_view_swizzles[i].a = PIPE_SWIZZLE_ONE;
350 }
351 else {
352 variant->sampler_view_swizzles[i].r = PIPE_SWIZZLE_RED;
353 variant->sampler_view_swizzles[i].g = PIPE_SWIZZLE_GREEN;
354 variant->sampler_view_swizzles[i].b = PIPE_SWIZZLE_BLUE;
355 variant->sampler_view_swizzles[i].a = PIPE_SWIZZLE_ALPHA;
356 }
357 }
358 }
359
360
361 /**
362 * Parse a TGSI instruction for the shader info.
363 */
364 static void
365 ilo_shader_info_parse_inst(struct ilo_shader_info *info,
366 const struct tgsi_full_instruction *inst)
367 {
368 int i;
369
370 /* look for edgeflag passthrough */
371 if (info->edgeflag_out >= 0 &&
372 inst->Instruction.Opcode == TGSI_OPCODE_MOV &&
373 inst->Dst[0].Register.File == TGSI_FILE_OUTPUT &&
374 inst->Dst[0].Register.Index == info->edgeflag_out) {
375
376 assert(inst->Src[0].Register.File == TGSI_FILE_INPUT);
377 info->edgeflag_in = inst->Src[0].Register.Index;
378 }
379
380 if (inst->Instruction.Texture) {
381 bool shadow;
382
383 switch (inst->Texture.Texture) {
384 case TGSI_TEXTURE_SHADOW1D:
385 case TGSI_TEXTURE_SHADOW2D:
386 case TGSI_TEXTURE_SHADOWRECT:
387 case TGSI_TEXTURE_SHADOW1D_ARRAY:
388 case TGSI_TEXTURE_SHADOW2D_ARRAY:
389 case TGSI_TEXTURE_SHADOWCUBE:
390 case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
391 shadow = true;
392 break;
393 default:
394 shadow = false;
395 break;
396 }
397
398 for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
399 const struct tgsi_full_src_register *src = &inst->Src[i];
400
401 if (src->Register.File == TGSI_FILE_SAMPLER) {
402 const int idx = src->Register.Index;
403
404 if (idx >= info->num_samplers)
405 info->num_samplers = idx + 1;
406
407 if (shadow)
408 info->shadow_samplers |= 1 << idx;
409 }
410 }
411 }
412 }
413
414 /**
415 * Parse a TGSI property for the shader info.
416 */
417 static void
418 ilo_shader_info_parse_prop(struct ilo_shader_info *info,
419 const struct tgsi_full_property *prop)
420 {
421 switch (prop->Property.PropertyName) {
422 case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
423 info->fs_color0_writes_all_cbufs = prop->u[0].Data;
424 break;
425 default:
426 break;
427 }
428 }
429
430 /**
431 * Parse a TGSI declaration for the shader info.
432 */
433 static void
434 ilo_shader_info_parse_decl(struct ilo_shader_info *info,
435 const struct tgsi_full_declaration *decl)
436 {
437 switch (decl->Declaration.File) {
438 case TGSI_FILE_INPUT:
439 if (decl->Declaration.Interpolate &&
440 decl->Interp.Interpolate == TGSI_INTERPOLATE_COLOR)
441 info->has_color_interp = true;
442 if (decl->Declaration.Semantic &&
443 decl->Semantic.Name == TGSI_SEMANTIC_POSITION)
444 info->has_pos = true;
445 break;
446 case TGSI_FILE_OUTPUT:
447 if (decl->Declaration.Semantic &&
448 decl->Semantic.Name == TGSI_SEMANTIC_EDGEFLAG)
449 info->edgeflag_out = decl->Range.First;
450 break;
451 case TGSI_FILE_SYSTEM_VALUE:
452 if (decl->Declaration.Semantic &&
453 decl->Semantic.Name == TGSI_SEMANTIC_INSTANCEID)
454 info->has_instanceid = true;
455 if (decl->Declaration.Semantic &&
456 decl->Semantic.Name == TGSI_SEMANTIC_VERTEXID)
457 info->has_vertexid = true;
458 break;
459 default:
460 break;
461 }
462 }
463
464 static void
465 ilo_shader_info_parse_tokens(struct ilo_shader_info *info)
466 {
467 struct tgsi_parse_context parse;
468
469 info->edgeflag_in = -1;
470 info->edgeflag_out = -1;
471
472 tgsi_parse_init(&parse, info->tokens);
473 while (!tgsi_parse_end_of_tokens(&parse)) {
474 const union tgsi_full_token *token;
475
476 tgsi_parse_token(&parse);
477 token = &parse.FullToken;
478
479 switch (token->Token.Type) {
480 case TGSI_TOKEN_TYPE_DECLARATION:
481 ilo_shader_info_parse_decl(info, &token->FullDeclaration);
482 break;
483 case TGSI_TOKEN_TYPE_INSTRUCTION:
484 ilo_shader_info_parse_inst(info, &token->FullInstruction);
485 break;
486 case TGSI_TOKEN_TYPE_PROPERTY:
487 ilo_shader_info_parse_prop(info, &token->FullProperty);
488 break;
489 default:
490 break;
491 }
492 }
493 tgsi_parse_free(&parse);
494 }
495
496 /**
497 * Create a shader state.
498 */
499 static struct ilo_shader_state *
500 ilo_shader_state_create(const struct ilo_context *ilo,
501 int type, const void *templ)
502 {
503 struct ilo_shader_state *state;
504 struct ilo_shader_variant variant;
505
506 state = CALLOC_STRUCT(ilo_shader_state);
507 if (!state)
508 return NULL;
509
510 state->info.dev = ilo->dev;
511 state->info.type = type;
512
513 if (type == PIPE_SHADER_COMPUTE) {
514 const struct pipe_compute_state *c =
515 (const struct pipe_compute_state *) templ;
516
517 state->info.tokens = tgsi_dup_tokens(c->prog);
518 state->info.compute.req_local_mem = c->req_local_mem;
519 state->info.compute.req_private_mem = c->req_private_mem;
520 state->info.compute.req_input_mem = c->req_input_mem;
521 }
522 else {
523 const struct pipe_shader_state *s =
524 (const struct pipe_shader_state *) templ;
525
526 state->info.tokens = tgsi_dup_tokens(s->tokens);
527 state->info.stream_output = s->stream_output;
528 }
529
530 list_inithead(&state->variants);
531
532 ilo_shader_info_parse_tokens(&state->info);
533
534 /* guess and compile now */
535 ilo_shader_variant_guess(&variant, &state->info, ilo);
536 if (!ilo_shader_state_use_variant(state, &variant)) {
537 ilo_shader_destroy(state);
538 return NULL;
539 }
540
541 return state;
542 }
543
544 /**
545 * Add a compiled shader to the shader state.
546 */
547 static void
548 ilo_shader_state_add_shader(struct ilo_shader_state *state,
549 struct ilo_shader *sh)
550 {
551 list_add(&sh->list, &state->variants);
552 state->num_variants++;
553 state->total_size += sh->kernel_size;
554
555 if (state->cache)
556 ilo_shader_cache_notify_change(state->cache, state);
557 }
558
559 /**
560 * Remove a compiled shader from the shader state.
561 */
562 static void
563 ilo_shader_state_remove_shader(struct ilo_shader_state *state,
564 struct ilo_shader *sh)
565 {
566 list_del(&sh->list);
567 state->num_variants--;
568 state->total_size -= sh->kernel_size;
569 }
570
571 /**
572 * Garbage collect shader variants in the shader state.
573 */
574 static void
575 ilo_shader_state_gc(struct ilo_shader_state *state)
576 {
577 /* activate when the variants take up more than 4KiB of space */
578 const int limit = 4 * 1024;
579 struct ilo_shader *sh, *next;
580
581 if (state->total_size < limit)
582 return;
583
584 /* remove from the tail as the most recently ones are at the head */
585 LIST_FOR_EACH_ENTRY_SAFE_REV(sh, next, &state->variants, list) {
586 ilo_shader_state_remove_shader(state, sh);
587 ilo_shader_destroy_kernel(sh);
588
589 if (state->total_size <= limit / 2)
590 break;
591 }
592 }
593
594 /**
595 * Search for a shader variant.
596 */
597 static struct ilo_shader *
598 ilo_shader_state_search_variant(struct ilo_shader_state *state,
599 const struct ilo_shader_variant *variant)
600 {
601 struct ilo_shader *sh = NULL, *tmp;
602
603 LIST_FOR_EACH_ENTRY(tmp, &state->variants, list) {
604 if (memcmp(&tmp->variant, variant, sizeof(*variant)) == 0) {
605 sh = tmp;
606 break;
607 }
608 }
609
610 return sh;
611 }
612
613 /**
614 * Add a shader variant to the shader state.
615 */
616 static struct ilo_shader *
617 ilo_shader_state_add_variant(struct ilo_shader_state *state,
618 const struct ilo_shader_variant *variant)
619 {
620 struct ilo_shader *sh;
621
622 switch (state->info.type) {
623 case PIPE_SHADER_VERTEX:
624 sh = ilo_shader_compile_vs(state, variant);
625 break;
626 case PIPE_SHADER_FRAGMENT:
627 sh = ilo_shader_compile_fs(state, variant);
628 break;
629 case PIPE_SHADER_GEOMETRY:
630 sh = ilo_shader_compile_gs(state, variant);
631 break;
632 case PIPE_SHADER_COMPUTE:
633 sh = ilo_shader_compile_cs(state, variant);
634 break;
635 default:
636 sh = NULL;
637 break;
638 }
639 if (!sh) {
640 assert(!"failed to compile shader");
641 return NULL;
642 }
643
644 sh->variant = *variant;
645
646 ilo_shader_state_add_shader(state, sh);
647
648 return sh;
649 }
650
651 /**
652 * Update state->shader to point to a variant. If the variant does not exist,
653 * it will be added first.
654 */
655 bool
656 ilo_shader_state_use_variant(struct ilo_shader_state *state,
657 const struct ilo_shader_variant *variant)
658 {
659 struct ilo_shader *sh;
660 bool construct_cso = false;
661
662 sh = ilo_shader_state_search_variant(state, variant);
663 if (!sh) {
664 ilo_shader_state_gc(state);
665
666 sh = ilo_shader_state_add_variant(state, variant);
667 if (!sh)
668 return false;
669
670 construct_cso = true;
671 }
672
673 /* move to head */
674 if (state->variants.next != &sh->list) {
675 list_del(&sh->list);
676 list_add(&sh->list, &state->variants);
677 }
678
679 state->shader = sh;
680
681 if (construct_cso) {
682 switch (state->info.type) {
683 case PIPE_SHADER_VERTEX:
684 ilo_gpe_init_vs_cso(state->info.dev, state, &sh->cso);
685 break;
686 default:
687 break;
688 }
689 }
690
691 return true;
692 }
693
694 struct ilo_shader_state *
695 ilo_shader_create_vs(const struct ilo_dev_info *dev,
696 const struct pipe_shader_state *state,
697 const struct ilo_context *precompile)
698 {
699 struct ilo_shader_state *shader;
700
701 shader = ilo_shader_state_create(precompile, PIPE_SHADER_VERTEX, state);
702
703 /* states used in ilo_shader_variant_init() */
704 shader->info.non_orthogonal_states = ILO_DIRTY_VERTEX_SAMPLER_VIEWS |
705 ILO_DIRTY_RASTERIZER;
706
707 return shader;
708 }
709
710 struct ilo_shader_state *
711 ilo_shader_create_gs(const struct ilo_dev_info *dev,
712 const struct pipe_shader_state *state,
713 const struct ilo_context *precompile)
714 {
715 struct ilo_shader_state *shader;
716
717 shader = ilo_shader_state_create(precompile, PIPE_SHADER_GEOMETRY, state);
718
719 /* states used in ilo_shader_variant_init() */
720 shader->info.non_orthogonal_states = ILO_DIRTY_GEOMETRY_SAMPLER_VIEWS |
721 ILO_DIRTY_VS |
722 ILO_DIRTY_RASTERIZER;
723
724 return shader;
725 }
726
727 struct ilo_shader_state *
728 ilo_shader_create_fs(const struct ilo_dev_info *dev,
729 const struct pipe_shader_state *state,
730 const struct ilo_context *precompile)
731 {
732 struct ilo_shader_state *shader;
733
734 shader = ilo_shader_state_create(precompile, PIPE_SHADER_FRAGMENT, state);
735
736 /* states used in ilo_shader_variant_init() */
737 shader->info.non_orthogonal_states = ILO_DIRTY_FRAGMENT_SAMPLER_VIEWS |
738 ILO_DIRTY_RASTERIZER |
739 ILO_DIRTY_FRAMEBUFFER;
740
741 return shader;
742 }
743
744 struct ilo_shader_state *
745 ilo_shader_create_cs(const struct ilo_dev_info *dev,
746 const struct pipe_compute_state *state,
747 const struct ilo_context *precompile)
748 {
749 struct ilo_shader_state *shader;
750
751 shader = ilo_shader_state_create(precompile, PIPE_SHADER_COMPUTE, state);
752
753 shader->info.non_orthogonal_states = 0;
754
755 return shader;
756 }
757
758 /**
759 * Destroy a shader state.
760 */
761 void
762 ilo_shader_destroy(struct ilo_shader_state *shader)
763 {
764 struct ilo_shader *sh, *next;
765
766 LIST_FOR_EACH_ENTRY_SAFE(sh, next, &shader->variants, list)
767 ilo_shader_destroy_kernel(sh);
768
769 FREE((struct tgsi_token *) shader->info.tokens);
770 FREE(shader);
771 }
772
773 /**
774 * Return the type (PIPE_SHADER_x) of the shader.
775 */
776 int
777 ilo_shader_get_type(const struct ilo_shader_state *shader)
778 {
779 return shader->info.type;
780 }
781
782 /**
783 * Select a kernel for the given context. This will compile a new kernel if
784 * none of the existing kernels work with the context.
785 *
786 * \param ilo the context
787 * \param dirty states of the context that are considered changed
788 * \return true if a different kernel is selected
789 */
790 bool
791 ilo_shader_select_kernel(struct ilo_shader_state *shader,
792 const struct ilo_context *ilo,
793 uint32_t dirty)
794 {
795 const struct ilo_shader * const cur = shader->shader;
796 struct ilo_shader_variant variant;
797
798 if (!(shader->info.non_orthogonal_states & dirty))
799 return false;
800
801 ilo_shader_variant_init(&variant, &shader->info, ilo);
802 ilo_shader_state_use_variant(shader, &variant);
803
804 return (shader->shader != cur);
805 }
806
807 /**
808 * Return the cache offset of the selected kernel. This must be called after
809 * ilo_shader_select_kernel() and ilo_shader_cache_upload().
810 */
811 uint32_t
812 ilo_shader_get_kernel_offset(const struct ilo_shader_state *shader)
813 {
814 const struct ilo_shader *kernel = shader->shader;
815
816 assert(kernel && kernel->uploaded);
817
818 return kernel->cache_offset;
819 }
820
821 /**
822 * Query a kernel parameter for the selected kernel.
823 */
824 int
825 ilo_shader_get_kernel_param(const struct ilo_shader_state *shader,
826 enum ilo_kernel_param param)
827 {
828 const struct ilo_shader *kernel = shader->shader;
829 int val;
830
831 assert(kernel);
832
833 switch (param) {
834 case ILO_KERNEL_INPUT_COUNT:
835 val = kernel->in.count;
836 break;
837 case ILO_KERNEL_OUTPUT_COUNT:
838 val = kernel->out.count;
839 break;
840 case ILO_KERNEL_URB_DATA_START_REG:
841 val = kernel->in.start_grf;
842 break;
843
844 case ILO_KERNEL_VS_INPUT_INSTANCEID:
845 val = shader->info.has_instanceid;
846 break;
847 case ILO_KERNEL_VS_INPUT_VERTEXID:
848 val = shader->info.has_vertexid;
849 break;
850 case ILO_KERNEL_VS_INPUT_EDGEFLAG:
851 if (shader->info.edgeflag_in >= 0) {
852 /* we rely on the state tracker here */
853 assert(shader->info.edgeflag_in == kernel->in.count - 1);
854 val = true;
855 }
856 else {
857 val = false;
858 }
859 break;
860 case ILO_KERNEL_VS_PCB_UCP_SIZE:
861 val = kernel->pcb.clip_state_size;
862 break;
863 case ILO_KERNEL_VS_GEN6_SO:
864 val = kernel->stream_output;
865 break;
866 case ILO_KERNEL_VS_GEN6_SO_START_REG:
867 val = kernel->gs_start_grf;
868 break;
869 case ILO_KERNEL_VS_GEN6_SO_POINT_OFFSET:
870 val = kernel->gs_offsets[0];
871 break;
872 case ILO_KERNEL_VS_GEN6_SO_LINE_OFFSET:
873 val = kernel->gs_offsets[1];
874 break;
875 case ILO_KERNEL_VS_GEN6_SO_TRI_OFFSET:
876 val = kernel->gs_offsets[2];
877 break;
878
879 case ILO_KERNEL_GS_DISCARD_ADJACENCY:
880 val = kernel->in.discard_adj;
881 break;
882 case ILO_KERNEL_GS_GEN6_SVBI_POST_INC:
883 val = kernel->svbi_post_inc;
884 break;
885
886 case ILO_KERNEL_FS_INPUT_Z:
887 case ILO_KERNEL_FS_INPUT_W:
888 val = kernel->in.has_pos;
889 break;
890 case ILO_KERNEL_FS_OUTPUT_Z:
891 val = kernel->out.has_pos;
892 break;
893 case ILO_KERNEL_FS_USE_KILL:
894 val = kernel->has_kill;
895 break;
896 case ILO_KERNEL_FS_BARYCENTRIC_INTERPOLATIONS:
897 val = kernel->in.barycentric_interpolation_mode;
898 break;
899 case ILO_KERNEL_FS_DISPATCH_16_OFFSET:
900 val = 0;
901 break;
902
903 default:
904 assert(!"unknown kernel parameter");
905 val = 0;
906 break;
907 }
908
909 return val;
910 }
911
912 /**
913 * Return the CSO of the selected kernel.
914 */
915 const struct ilo_shader_cso *
916 ilo_shader_get_kernel_cso(const struct ilo_shader_state *shader)
917 {
918 const struct ilo_shader *kernel = shader->shader;
919
920 assert(kernel);
921
922 return &kernel->cso;
923 }