Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 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 |
||
26 | */ |
||
27 | |||
28 | #include "tgsi/tgsi_parse.h" |
||
29 | #include "intel_winsys.h" |
||
30 | #include "brw_defines.h" /* for SBE setup */ |
||
31 | |||
32 | #include "shader/ilo_shader_internal.h" |
||
33 | #include "ilo_state.h" |
||
34 | #include "ilo_shader.h" |
||
35 | |||
36 | struct ilo_shader_cache { |
||
37 | struct list_head shaders; |
||
38 | struct list_head changed; |
||
39 | }; |
||
40 | |||
41 | /** |
||
42 | * Create a shader cache. A shader cache can manage shaders and upload them |
||
43 | * to a bo as a whole. |
||
44 | */ |
||
45 | struct ilo_shader_cache * |
||
46 | ilo_shader_cache_create(void) |
||
47 | { |
||
48 | struct ilo_shader_cache *shc; |
||
49 | |||
50 | shc = CALLOC_STRUCT(ilo_shader_cache); |
||
51 | if (!shc) |
||
52 | return NULL; |
||
53 | |||
54 | list_inithead(&shc->shaders); |
||
55 | list_inithead(&shc->changed); |
||
56 | |||
57 | return shc; |
||
58 | } |
||
59 | |||
60 | /** |
||
61 | * Destroy a shader cache. |
||
62 | */ |
||
63 | void |
||
64 | ilo_shader_cache_destroy(struct ilo_shader_cache *shc) |
||
65 | { |
||
66 | FREE(shc); |
||
67 | } |
||
68 | |||
69 | /** |
||
70 | * Add a shader to the cache. |
||
71 | */ |
||
72 | void |
||
73 | ilo_shader_cache_add(struct ilo_shader_cache *shc, |
||
74 | struct ilo_shader_state *shader) |
||
75 | { |
||
76 | struct ilo_shader *sh; |
||
77 | |||
78 | shader->cache = shc; |
||
79 | LIST_FOR_EACH_ENTRY(sh, &shader->variants, list) |
||
80 | sh->uploaded = false; |
||
81 | |||
82 | list_add(&shader->list, &shc->changed); |
||
83 | } |
||
84 | |||
85 | /** |
||
86 | * Remove a shader from the cache. |
||
87 | */ |
||
88 | void |
||
89 | ilo_shader_cache_remove(struct ilo_shader_cache *shc, |
||
90 | struct ilo_shader_state *shader) |
||
91 | { |
||
92 | list_del(&shader->list); |
||
93 | shader->cache = NULL; |
||
94 | } |
||
95 | |||
96 | /** |
||
97 | * Notify the cache that a managed shader has changed. |
||
98 | */ |
||
99 | static void |
||
100 | ilo_shader_cache_notify_change(struct ilo_shader_cache *shc, |
||
101 | struct ilo_shader_state *shader) |
||
102 | { |
||
103 | if (shader->cache == shc) { |
||
104 | list_del(&shader->list); |
||
105 | list_add(&shader->list, &shc->changed); |
||
106 | } |
||
107 | } |
||
108 | |||
109 | /** |
||
110 | * Upload a managed shader to the bo. |
||
111 | */ |
||
112 | static int |
||
113 | ilo_shader_cache_upload_shader(struct ilo_shader_cache *shc, |
||
114 | struct ilo_shader_state *shader, |
||
115 | struct intel_bo *bo, unsigned offset, |
||
116 | bool incremental) |
||
117 | { |
||
118 | const unsigned base = offset; |
||
119 | struct ilo_shader *sh; |
||
120 | |||
121 | LIST_FOR_EACH_ENTRY(sh, &shader->variants, list) { |
||
122 | int err; |
||
123 | |||
124 | if (incremental && sh->uploaded) |
||
125 | continue; |
||
126 | |||
127 | /* kernels must be aligned to 64-byte */ |
||
128 | offset = align(offset, 64); |
||
129 | |||
130 | err = intel_bo_pwrite(bo, offset, sh->kernel_size, sh->kernel); |
||
131 | if (unlikely(err)) |
||
132 | return -1; |
||
133 | |||
134 | sh->uploaded = true; |
||
135 | sh->cache_offset = offset; |
||
136 | |||
137 | offset += sh->kernel_size; |
||
138 | } |
||
139 | |||
140 | return (int) (offset - base); |
||
141 | } |
||
142 | |||
143 | /** |
||
144 | * Similar to ilo_shader_cache_upload(), except no upload happens. |
||
145 | */ |
||
146 | static int |
||
147 | ilo_shader_cache_get_upload_size(struct ilo_shader_cache *shc, |
||
148 | unsigned offset, |
||
149 | bool incremental) |
||
150 | { |
||
151 | const unsigned base = offset; |
||
152 | struct ilo_shader_state *shader; |
||
153 | |||
154 | if (!incremental) { |
||
155 | LIST_FOR_EACH_ENTRY(shader, &shc->shaders, list) { |
||
156 | struct ilo_shader *sh; |
||
157 | |||
158 | /* see ilo_shader_cache_upload_shader() */ |
||
159 | LIST_FOR_EACH_ENTRY(sh, &shader->variants, list) { |
||
160 | if (!incremental || !sh->uploaded) |
||
161 | offset = align(offset, 64) + sh->kernel_size; |
||
162 | } |
||
163 | } |
||
164 | } |
||
165 | |||
166 | LIST_FOR_EACH_ENTRY(shader, &shc->changed, list) { |
||
167 | struct ilo_shader *sh; |
||
168 | |||
169 | /* see ilo_shader_cache_upload_shader() */ |
||
170 | LIST_FOR_EACH_ENTRY(sh, &shader->variants, list) { |
||
171 | if (!incremental || !sh->uploaded) |
||
172 | offset = align(offset, 64) + sh->kernel_size; |
||
173 | } |
||
174 | } |
||
175 | |||
176 | /* |
||
177 | * From the Sandy Bridge PRM, volume 4 part 2, page 112: |
||
178 | * |
||
179 | * "Due to prefetch of the instruction stream, the EUs may attempt to |
||
180 | * access up to 8 instructions (128 bytes) beyond the end of the |
||
181 | * kernel program - possibly into the next memory page. Although |
||
182 | * these instructions will not be executed, software must account for |
||
183 | * the prefetch in order to avoid invalid page access faults." |
||
184 | */ |
||
185 | if (offset > base) |
||
186 | offset += 128; |
||
187 | |||
188 | return (int) (offset - base); |
||
189 | } |
||
190 | |||
191 | /** |
||
192 | * Upload managed shaders to the bo. When incremental is true, only shaders |
||
193 | * that are changed or added after the last upload are uploaded. |
||
194 | */ |
||
195 | int |
||
196 | ilo_shader_cache_upload(struct ilo_shader_cache *shc, |
||
197 | struct intel_bo *bo, unsigned offset, |
||
198 | bool incremental) |
||
199 | { |
||
200 | struct ilo_shader_state *shader, *next; |
||
201 | int size = 0, s; |
||
202 | |||
203 | if (!bo) |
||
204 | return ilo_shader_cache_get_upload_size(shc, offset, incremental); |
||
205 | |||
206 | if (!incremental) { |
||
207 | LIST_FOR_EACH_ENTRY(shader, &shc->shaders, list) { |
||
208 | s = ilo_shader_cache_upload_shader(shc, shader, |
||
209 | bo, offset, incremental); |
||
210 | if (unlikely(s < 0)) |
||
211 | return s; |
||
212 | |||
213 | size += s; |
||
214 | offset += s; |
||
215 | } |
||
216 | } |
||
217 | |||
218 | LIST_FOR_EACH_ENTRY_SAFE(shader, next, &shc->changed, list) { |
||
219 | s = ilo_shader_cache_upload_shader(shc, shader, |
||
220 | bo, offset, incremental); |
||
221 | if (unlikely(s < 0)) |
||
222 | return s; |
||
223 | |||
224 | size += s; |
||
225 | offset += s; |
||
226 | |||
227 | list_del(&shader->list); |
||
228 | list_add(&shader->list, &shc->shaders); |
||
229 | } |
||
230 | |||
231 | return size; |
||
232 | } |
||
233 | |||
234 | /** |
||
235 | * Initialize a shader variant. |
||
236 | */ |
||
237 | void |
||
238 | ilo_shader_variant_init(struct ilo_shader_variant *variant, |
||
239 | const struct ilo_shader_info *info, |
||
240 | const struct ilo_context *ilo) |
||
241 | { |
||
242 | int num_views, i; |
||
243 | |||
244 | memset(variant, 0, sizeof(*variant)); |
||
245 | |||
246 | switch (info->type) { |
||
247 | case PIPE_SHADER_VERTEX: |
||
248 | variant->u.vs.rasterizer_discard = |
||
249 | ilo->rasterizer->state.rasterizer_discard; |
||
250 | variant->u.vs.num_ucps = |
||
251 | util_last_bit(ilo->rasterizer->state.clip_plane_enable); |
||
252 | break; |
||
253 | case PIPE_SHADER_GEOMETRY: |
||
254 | variant->u.gs.rasterizer_discard = |
||
255 | ilo->rasterizer->state.rasterizer_discard; |
||
256 | variant->u.gs.num_inputs = ilo->vs->shader->out.count; |
||
257 | for (i = 0; i < ilo->vs->shader->out.count; i++) { |
||
258 | variant->u.gs.semantic_names[i] = |
||
259 | ilo->vs->shader->out.semantic_names[i]; |
||
260 | variant->u.gs.semantic_indices[i] = |
||
261 | ilo->vs->shader->out.semantic_indices[i]; |
||
262 | } |
||
263 | break; |
||
264 | case PIPE_SHADER_FRAGMENT: |
||
265 | variant->u.fs.flatshade = |
||
266 | (info->has_color_interp && ilo->rasterizer->state.flatshade); |
||
267 | variant->u.fs.fb_height = (info->has_pos) ? |
||
268 | ilo->fb.state.height : 1; |
||
269 | variant->u.fs.num_cbufs = ilo->fb.state.nr_cbufs; |
||
270 | break; |
||
271 | default: |
||
272 | assert(!"unknown shader type"); |
||
273 | break; |
||
274 | } |
||
275 | |||
276 | num_views = ilo->view[info->type].count; |
||
277 | assert(info->num_samplers <= num_views); |
||
278 | |||
279 | variant->num_sampler_views = info->num_samplers; |
||
280 | for (i = 0; i < info->num_samplers; i++) { |
||
281 | const struct pipe_sampler_view *view = ilo->view[info->type].states[i]; |
||
282 | const struct ilo_sampler_cso *sampler = ilo->sampler[info->type].cso[i]; |
||
283 | |||
284 | if (view) { |
||
285 | variant->sampler_view_swizzles[i].r = view->swizzle_r; |
||
286 | variant->sampler_view_swizzles[i].g = view->swizzle_g; |
||
287 | variant->sampler_view_swizzles[i].b = view->swizzle_b; |
||
288 | variant->sampler_view_swizzles[i].a = view->swizzle_a; |
||
289 | } |
||
290 | else if (info->shadow_samplers & (1 << i)) { |
||
291 | variant->sampler_view_swizzles[i].r = PIPE_SWIZZLE_RED; |
||
292 | variant->sampler_view_swizzles[i].g = PIPE_SWIZZLE_RED; |
||
293 | variant->sampler_view_swizzles[i].b = PIPE_SWIZZLE_RED; |
||
294 | variant->sampler_view_swizzles[i].a = PIPE_SWIZZLE_ONE; |
||
295 | } |
||
296 | else { |
||
297 | variant->sampler_view_swizzles[i].r = PIPE_SWIZZLE_RED; |
||
298 | variant->sampler_view_swizzles[i].g = PIPE_SWIZZLE_GREEN; |
||
299 | variant->sampler_view_swizzles[i].b = PIPE_SWIZZLE_BLUE; |
||
300 | variant->sampler_view_swizzles[i].a = PIPE_SWIZZLE_ALPHA; |
||
301 | } |
||
302 | |||
303 | /* |
||
304 | * When non-nearest filter and PIPE_TEX_WRAP_CLAMP wrap mode is used, |
||
305 | * the HW wrap mode is set to BRW_TEXCOORDMODE_CLAMP_BORDER, and we need |
||
306 | * to manually saturate the texture coordinates. |
||
307 | */ |
||
308 | if (sampler) { |
||
309 | variant->saturate_tex_coords[0] |= sampler->saturate_s << i; |
||
310 | variant->saturate_tex_coords[1] |= sampler->saturate_t << i; |
||
311 | variant->saturate_tex_coords[2] |= sampler->saturate_r << i; |
||
312 | } |
||
313 | } |
||
314 | } |
||
315 | |||
316 | /** |
||
317 | * Guess the shader variant, knowing that the context may still change. |
||
318 | */ |
||
319 | static void |
||
320 | ilo_shader_variant_guess(struct ilo_shader_variant *variant, |
||
321 | const struct ilo_shader_info *info, |
||
322 | const struct ilo_context *ilo) |
||
323 | { |
||
324 | int i; |
||
325 | |||
326 | memset(variant, 0, sizeof(*variant)); |
||
327 | |||
328 | switch (info->type) { |
||
329 | case PIPE_SHADER_VERTEX: |
||
330 | break; |
||
331 | case PIPE_SHADER_GEOMETRY: |
||
332 | break; |
||
333 | case PIPE_SHADER_FRAGMENT: |
||
334 | variant->u.fs.flatshade = false; |
||
335 | variant->u.fs.fb_height = (info->has_pos) ? |
||
336 | ilo->fb.state.height : 1; |
||
337 | variant->u.fs.num_cbufs = 1; |
||
338 | break; |
||
339 | default: |
||
340 | assert(!"unknown shader type"); |
||
341 | break; |
||
342 | } |
||
343 | |||
344 | variant->num_sampler_views = info->num_samplers; |
||
345 | for (i = 0; i < info->num_samplers; i++) { |
||
346 | if (info->shadow_samplers & (1 << i)) { |
||
347 | variant->sampler_view_swizzles[i].r = PIPE_SWIZZLE_RED; |
||
348 | variant->sampler_view_swizzles[i].g = PIPE_SWIZZLE_RED; |
||
349 | variant->sampler_view_swizzles[i].b = PIPE_SWIZZLE_RED; |
||
350 | variant->sampler_view_swizzles[i].a = PIPE_SWIZZLE_ONE; |
||
351 | } |
||
352 | else { |
||
353 | variant->sampler_view_swizzles[i].r = PIPE_SWIZZLE_RED; |
||
354 | variant->sampler_view_swizzles[i].g = PIPE_SWIZZLE_GREEN; |
||
355 | variant->sampler_view_swizzles[i].b = PIPE_SWIZZLE_BLUE; |
||
356 | variant->sampler_view_swizzles[i].a = PIPE_SWIZZLE_ALPHA; |
||
357 | } |
||
358 | } |
||
359 | } |
||
360 | |||
361 | |||
362 | /** |
||
363 | * Parse a TGSI instruction for the shader info. |
||
364 | */ |
||
365 | static void |
||
366 | ilo_shader_info_parse_inst(struct ilo_shader_info *info, |
||
367 | const struct tgsi_full_instruction *inst) |
||
368 | { |
||
369 | int i; |
||
370 | |||
371 | /* look for edgeflag passthrough */ |
||
372 | if (info->edgeflag_out >= 0 && |
||
373 | inst->Instruction.Opcode == TGSI_OPCODE_MOV && |
||
374 | inst->Dst[0].Register.File == TGSI_FILE_OUTPUT && |
||
375 | inst->Dst[0].Register.Index == info->edgeflag_out) { |
||
376 | |||
377 | assert(inst->Src[0].Register.File == TGSI_FILE_INPUT); |
||
378 | info->edgeflag_in = inst->Src[0].Register.Index; |
||
379 | } |
||
380 | |||
381 | if (inst->Instruction.Texture) { |
||
382 | bool shadow; |
||
383 | |||
384 | switch (inst->Texture.Texture) { |
||
385 | case TGSI_TEXTURE_SHADOW1D: |
||
386 | case TGSI_TEXTURE_SHADOW2D: |
||
387 | case TGSI_TEXTURE_SHADOWRECT: |
||
388 | case TGSI_TEXTURE_SHADOW1D_ARRAY: |
||
389 | case TGSI_TEXTURE_SHADOW2D_ARRAY: |
||
390 | case TGSI_TEXTURE_SHADOWCUBE: |
||
391 | case TGSI_TEXTURE_SHADOWCUBE_ARRAY: |
||
392 | shadow = true; |
||
393 | break; |
||
394 | default: |
||
395 | shadow = false; |
||
396 | break; |
||
397 | } |
||
398 | |||
399 | for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { |
||
400 | const struct tgsi_full_src_register *src = &inst->Src[i]; |
||
401 | |||
402 | if (src->Register.File == TGSI_FILE_SAMPLER) { |
||
403 | const int idx = src->Register.Index; |
||
404 | |||
405 | if (idx >= info->num_samplers) |
||
406 | info->num_samplers = idx + 1; |
||
407 | |||
408 | if (shadow) |
||
409 | info->shadow_samplers |= 1 << idx; |
||
410 | } |
||
411 | } |
||
412 | } |
||
413 | } |
||
414 | |||
415 | /** |
||
416 | * Parse a TGSI property for the shader info. |
||
417 | */ |
||
418 | static void |
||
419 | ilo_shader_info_parse_prop(struct ilo_shader_info *info, |
||
420 | const struct tgsi_full_property *prop) |
||
421 | { |
||
422 | switch (prop->Property.PropertyName) { |
||
423 | case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS: |
||
424 | info->fs_color0_writes_all_cbufs = prop->u[0].Data; |
||
425 | break; |
||
426 | default: |
||
427 | break; |
||
428 | } |
||
429 | } |
||
430 | |||
431 | /** |
||
432 | * Parse a TGSI declaration for the shader info. |
||
433 | */ |
||
434 | static void |
||
435 | ilo_shader_info_parse_decl(struct ilo_shader_info *info, |
||
436 | const struct tgsi_full_declaration *decl) |
||
437 | { |
||
438 | switch (decl->Declaration.File) { |
||
439 | case TGSI_FILE_INPUT: |
||
440 | if (decl->Declaration.Interpolate && |
||
441 | decl->Interp.Interpolate == TGSI_INTERPOLATE_COLOR) |
||
442 | info->has_color_interp = true; |
||
443 | if (decl->Declaration.Semantic && |
||
444 | decl->Semantic.Name == TGSI_SEMANTIC_POSITION) |
||
445 | info->has_pos = true; |
||
446 | break; |
||
447 | case TGSI_FILE_OUTPUT: |
||
448 | if (decl->Declaration.Semantic && |
||
449 | decl->Semantic.Name == TGSI_SEMANTIC_EDGEFLAG) |
||
450 | info->edgeflag_out = decl->Range.First; |
||
451 | break; |
||
452 | case TGSI_FILE_SYSTEM_VALUE: |
||
453 | if (decl->Declaration.Semantic && |
||
454 | decl->Semantic.Name == TGSI_SEMANTIC_INSTANCEID) |
||
455 | info->has_instanceid = true; |
||
456 | if (decl->Declaration.Semantic && |
||
457 | decl->Semantic.Name == TGSI_SEMANTIC_VERTEXID) |
||
458 | info->has_vertexid = true; |
||
459 | break; |
||
460 | default: |
||
461 | break; |
||
462 | } |
||
463 | } |
||
464 | |||
465 | static void |
||
466 | ilo_shader_info_parse_tokens(struct ilo_shader_info *info) |
||
467 | { |
||
468 | struct tgsi_parse_context parse; |
||
469 | |||
470 | info->edgeflag_in = -1; |
||
471 | info->edgeflag_out = -1; |
||
472 | |||
473 | tgsi_parse_init(&parse, info->tokens); |
||
474 | while (!tgsi_parse_end_of_tokens(&parse)) { |
||
475 | const union tgsi_full_token *token; |
||
476 | |||
477 | tgsi_parse_token(&parse); |
||
478 | token = &parse.FullToken; |
||
479 | |||
480 | switch (token->Token.Type) { |
||
481 | case TGSI_TOKEN_TYPE_DECLARATION: |
||
482 | ilo_shader_info_parse_decl(info, &token->FullDeclaration); |
||
483 | break; |
||
484 | case TGSI_TOKEN_TYPE_INSTRUCTION: |
||
485 | ilo_shader_info_parse_inst(info, &token->FullInstruction); |
||
486 | break; |
||
487 | case TGSI_TOKEN_TYPE_PROPERTY: |
||
488 | ilo_shader_info_parse_prop(info, &token->FullProperty); |
||
489 | break; |
||
490 | default: |
||
491 | break; |
||
492 | } |
||
493 | } |
||
494 | tgsi_parse_free(&parse); |
||
495 | } |
||
496 | |||
497 | /** |
||
498 | * Create a shader state. |
||
499 | */ |
||
500 | static struct ilo_shader_state * |
||
501 | ilo_shader_state_create(const struct ilo_context *ilo, |
||
502 | int type, const void *templ) |
||
503 | { |
||
504 | struct ilo_shader_state *state; |
||
505 | struct ilo_shader_variant variant; |
||
506 | |||
507 | state = CALLOC_STRUCT(ilo_shader_state); |
||
508 | if (!state) |
||
509 | return NULL; |
||
510 | |||
511 | state->info.dev = ilo->dev; |
||
512 | state->info.type = type; |
||
513 | |||
514 | if (type == PIPE_SHADER_COMPUTE) { |
||
515 | const struct pipe_compute_state *c = |
||
516 | (const struct pipe_compute_state *) templ; |
||
517 | |||
518 | state->info.tokens = tgsi_dup_tokens(c->prog); |
||
519 | state->info.compute.req_local_mem = c->req_local_mem; |
||
520 | state->info.compute.req_private_mem = c->req_private_mem; |
||
521 | state->info.compute.req_input_mem = c->req_input_mem; |
||
522 | } |
||
523 | else { |
||
524 | const struct pipe_shader_state *s = |
||
525 | (const struct pipe_shader_state *) templ; |
||
526 | |||
527 | state->info.tokens = tgsi_dup_tokens(s->tokens); |
||
528 | state->info.stream_output = s->stream_output; |
||
529 | } |
||
530 | |||
531 | list_inithead(&state->variants); |
||
532 | |||
533 | ilo_shader_info_parse_tokens(&state->info); |
||
534 | |||
535 | /* guess and compile now */ |
||
536 | ilo_shader_variant_guess(&variant, &state->info, ilo); |
||
537 | if (!ilo_shader_state_use_variant(state, &variant)) { |
||
538 | ilo_shader_destroy(state); |
||
539 | return NULL; |
||
540 | } |
||
541 | |||
542 | return state; |
||
543 | } |
||
544 | |||
545 | /** |
||
546 | * Add a compiled shader to the shader state. |
||
547 | */ |
||
548 | static void |
||
549 | ilo_shader_state_add_shader(struct ilo_shader_state *state, |
||
550 | struct ilo_shader *sh) |
||
551 | { |
||
552 | list_add(&sh->list, &state->variants); |
||
553 | state->num_variants++; |
||
554 | state->total_size += sh->kernel_size; |
||
555 | |||
556 | if (state->cache) |
||
557 | ilo_shader_cache_notify_change(state->cache, state); |
||
558 | } |
||
559 | |||
560 | /** |
||
561 | * Remove a compiled shader from the shader state. |
||
562 | */ |
||
563 | static void |
||
564 | ilo_shader_state_remove_shader(struct ilo_shader_state *state, |
||
565 | struct ilo_shader *sh) |
||
566 | { |
||
567 | list_del(&sh->list); |
||
568 | state->num_variants--; |
||
569 | state->total_size -= sh->kernel_size; |
||
570 | } |
||
571 | |||
572 | /** |
||
573 | * Garbage collect shader variants in the shader state. |
||
574 | */ |
||
575 | static void |
||
576 | ilo_shader_state_gc(struct ilo_shader_state *state) |
||
577 | { |
||
578 | /* activate when the variants take up more than 4KiB of space */ |
||
579 | const int limit = 4 * 1024; |
||
580 | struct ilo_shader *sh, *next; |
||
581 | |||
582 | if (state->total_size < limit) |
||
583 | return; |
||
584 | |||
585 | /* remove from the tail as the most recently ones are at the head */ |
||
586 | LIST_FOR_EACH_ENTRY_SAFE_REV(sh, next, &state->variants, list) { |
||
587 | ilo_shader_state_remove_shader(state, sh); |
||
588 | ilo_shader_destroy_kernel(sh); |
||
589 | |||
590 | if (state->total_size <= limit / 2) |
||
591 | break; |
||
592 | } |
||
593 | } |
||
594 | |||
595 | /** |
||
596 | * Search for a shader variant. |
||
597 | */ |
||
598 | static struct ilo_shader * |
||
599 | ilo_shader_state_search_variant(struct ilo_shader_state *state, |
||
600 | const struct ilo_shader_variant *variant) |
||
601 | { |
||
602 | struct ilo_shader *sh = NULL, *tmp; |
||
603 | |||
604 | LIST_FOR_EACH_ENTRY(tmp, &state->variants, list) { |
||
605 | if (memcmp(&tmp->variant, variant, sizeof(*variant)) == 0) { |
||
606 | sh = tmp; |
||
607 | break; |
||
608 | } |
||
609 | } |
||
610 | |||
611 | return sh; |
||
612 | } |
||
613 | |||
614 | static void |
||
615 | copy_so_info(struct ilo_shader *sh, |
||
616 | const struct pipe_stream_output_info *so_info) |
||
617 | { |
||
618 | unsigned i, attr; |
||
619 | |||
620 | if (!so_info->num_outputs) |
||
621 | return; |
||
622 | |||
623 | sh->so_info = *so_info; |
||
624 | |||
625 | for (i = 0; i < so_info->num_outputs; i++) { |
||
626 | /* figure out which attribute is sourced */ |
||
627 | for (attr = 0; attr < sh->out.count; attr++) { |
||
628 | const int reg_idx = sh->out.register_indices[attr]; |
||
629 | if (reg_idx == so_info->output[i].register_index) |
||
630 | break; |
||
631 | } |
||
632 | |||
633 | if (attr < sh->out.count) { |
||
634 | sh->so_info.output[i].register_index = attr; |
||
635 | } |
||
636 | else { |
||
637 | assert(!"stream output an undefined register"); |
||
638 | sh->so_info.output[i].register_index = 0; |
||
639 | } |
||
640 | |||
641 | /* PSIZE is at W channel */ |
||
642 | if (sh->out.semantic_names[attr] == TGSI_SEMANTIC_PSIZE) { |
||
643 | assert(so_info->output[i].start_component == 0); |
||
644 | assert(so_info->output[i].num_components == 1); |
||
645 | sh->so_info.output[i].start_component = 3; |
||
646 | } |
||
647 | } |
||
648 | } |
||
649 | |||
650 | /** |
||
651 | * Add a shader variant to the shader state. |
||
652 | */ |
||
653 | static struct ilo_shader * |
||
654 | ilo_shader_state_add_variant(struct ilo_shader_state *state, |
||
655 | const struct ilo_shader_variant *variant) |
||
656 | { |
||
657 | struct ilo_shader *sh; |
||
658 | |||
659 | switch (state->info.type) { |
||
660 | case PIPE_SHADER_VERTEX: |
||
661 | sh = ilo_shader_compile_vs(state, variant); |
||
662 | break; |
||
663 | case PIPE_SHADER_FRAGMENT: |
||
664 | sh = ilo_shader_compile_fs(state, variant); |
||
665 | break; |
||
666 | case PIPE_SHADER_GEOMETRY: |
||
667 | sh = ilo_shader_compile_gs(state, variant); |
||
668 | break; |
||
669 | case PIPE_SHADER_COMPUTE: |
||
670 | sh = ilo_shader_compile_cs(state, variant); |
||
671 | break; |
||
672 | default: |
||
673 | sh = NULL; |
||
674 | break; |
||
675 | } |
||
676 | if (!sh) { |
||
677 | assert(!"failed to compile shader"); |
||
678 | return NULL; |
||
679 | } |
||
680 | |||
681 | sh->variant = *variant; |
||
682 | |||
683 | copy_so_info(sh, &state->info.stream_output); |
||
684 | |||
685 | ilo_shader_state_add_shader(state, sh); |
||
686 | |||
687 | return sh; |
||
688 | } |
||
689 | |||
690 | /** |
||
691 | * Update state->shader to point to a variant. If the variant does not exist, |
||
692 | * it will be added first. |
||
693 | */ |
||
694 | bool |
||
695 | ilo_shader_state_use_variant(struct ilo_shader_state *state, |
||
696 | const struct ilo_shader_variant *variant) |
||
697 | { |
||
698 | struct ilo_shader *sh; |
||
699 | bool construct_cso = false; |
||
700 | |||
701 | sh = ilo_shader_state_search_variant(state, variant); |
||
702 | if (!sh) { |
||
703 | ilo_shader_state_gc(state); |
||
704 | |||
705 | sh = ilo_shader_state_add_variant(state, variant); |
||
706 | if (!sh) |
||
707 | return false; |
||
708 | |||
709 | construct_cso = true; |
||
710 | } |
||
711 | |||
712 | /* move to head */ |
||
713 | if (state->variants.next != &sh->list) { |
||
714 | list_del(&sh->list); |
||
715 | list_add(&sh->list, &state->variants); |
||
716 | } |
||
717 | |||
718 | state->shader = sh; |
||
719 | |||
720 | if (construct_cso) { |
||
721 | switch (state->info.type) { |
||
722 | case PIPE_SHADER_VERTEX: |
||
723 | ilo_gpe_init_vs_cso(state->info.dev, state, &sh->cso); |
||
724 | break; |
||
725 | case PIPE_SHADER_GEOMETRY: |
||
726 | ilo_gpe_init_gs_cso(state->info.dev, state, &sh->cso); |
||
727 | break; |
||
728 | case PIPE_SHADER_FRAGMENT: |
||
729 | ilo_gpe_init_fs_cso(state->info.dev, state, &sh->cso); |
||
730 | break; |
||
731 | default: |
||
732 | break; |
||
733 | } |
||
734 | } |
||
735 | |||
736 | return true; |
||
737 | } |
||
738 | |||
739 | struct ilo_shader_state * |
||
740 | ilo_shader_create_vs(const struct ilo_dev_info *dev, |
||
741 | const struct pipe_shader_state *state, |
||
742 | const struct ilo_context *precompile) |
||
743 | { |
||
744 | struct ilo_shader_state *shader; |
||
745 | |||
746 | shader = ilo_shader_state_create(precompile, PIPE_SHADER_VERTEX, state); |
||
747 | |||
748 | /* states used in ilo_shader_variant_init() */ |
||
749 | shader->info.non_orthogonal_states = ILO_DIRTY_VIEW_VS | |
||
750 | ILO_DIRTY_RASTERIZER; |
||
751 | |||
752 | return shader; |
||
753 | } |
||
754 | |||
755 | struct ilo_shader_state * |
||
756 | ilo_shader_create_gs(const struct ilo_dev_info *dev, |
||
757 | const struct pipe_shader_state *state, |
||
758 | const struct ilo_context *precompile) |
||
759 | { |
||
760 | struct ilo_shader_state *shader; |
||
761 | |||
762 | shader = ilo_shader_state_create(precompile, PIPE_SHADER_GEOMETRY, state); |
||
763 | |||
764 | /* states used in ilo_shader_variant_init() */ |
||
765 | shader->info.non_orthogonal_states = ILO_DIRTY_VIEW_GS | |
||
766 | ILO_DIRTY_VS | |
||
767 | ILO_DIRTY_RASTERIZER; |
||
768 | |||
769 | return shader; |
||
770 | } |
||
771 | |||
772 | struct ilo_shader_state * |
||
773 | ilo_shader_create_fs(const struct ilo_dev_info *dev, |
||
774 | const struct pipe_shader_state *state, |
||
775 | const struct ilo_context *precompile) |
||
776 | { |
||
777 | struct ilo_shader_state *shader; |
||
778 | |||
779 | shader = ilo_shader_state_create(precompile, PIPE_SHADER_FRAGMENT, state); |
||
780 | |||
781 | /* states used in ilo_shader_variant_init() */ |
||
782 | shader->info.non_orthogonal_states = ILO_DIRTY_VIEW_FS | |
||
783 | ILO_DIRTY_RASTERIZER | |
||
784 | ILO_DIRTY_FB; |
||
785 | |||
786 | return shader; |
||
787 | } |
||
788 | |||
789 | struct ilo_shader_state * |
||
790 | ilo_shader_create_cs(const struct ilo_dev_info *dev, |
||
791 | const struct pipe_compute_state *state, |
||
792 | const struct ilo_context *precompile) |
||
793 | { |
||
794 | struct ilo_shader_state *shader; |
||
795 | |||
796 | shader = ilo_shader_state_create(precompile, PIPE_SHADER_COMPUTE, state); |
||
797 | |||
798 | shader->info.non_orthogonal_states = 0; |
||
799 | |||
800 | return shader; |
||
801 | } |
||
802 | |||
803 | /** |
||
804 | * Destroy a shader state. |
||
805 | */ |
||
806 | void |
||
807 | ilo_shader_destroy(struct ilo_shader_state *shader) |
||
808 | { |
||
809 | struct ilo_shader *sh, *next; |
||
810 | |||
811 | LIST_FOR_EACH_ENTRY_SAFE(sh, next, &shader->variants, list) |
||
812 | ilo_shader_destroy_kernel(sh); |
||
813 | |||
814 | FREE((struct tgsi_token *) shader->info.tokens); |
||
815 | FREE(shader); |
||
816 | } |
||
817 | |||
818 | /** |
||
819 | * Return the type (PIPE_SHADER_x) of the shader. |
||
820 | */ |
||
821 | int |
||
822 | ilo_shader_get_type(const struct ilo_shader_state *shader) |
||
823 | { |
||
824 | return shader->info.type; |
||
825 | } |
||
826 | |||
827 | /** |
||
828 | * Select a kernel for the given context. This will compile a new kernel if |
||
829 | * none of the existing kernels work with the context. |
||
830 | * |
||
831 | * \param ilo the context |
||
832 | * \param dirty states of the context that are considered changed |
||
833 | * \return true if a different kernel is selected |
||
834 | */ |
||
835 | bool |
||
836 | ilo_shader_select_kernel(struct ilo_shader_state *shader, |
||
837 | const struct ilo_context *ilo, |
||
838 | uint32_t dirty) |
||
839 | { |
||
840 | const struct ilo_shader * const cur = shader->shader; |
||
841 | struct ilo_shader_variant variant; |
||
842 | |||
843 | if (!(shader->info.non_orthogonal_states & dirty)) |
||
844 | return false; |
||
845 | |||
846 | ilo_shader_variant_init(&variant, &shader->info, ilo); |
||
847 | ilo_shader_state_use_variant(shader, &variant); |
||
848 | |||
849 | return (shader->shader != cur); |
||
850 | } |
||
851 | |||
852 | static int |
||
853 | route_attr(const int *semantics, const int *indices, int len, |
||
854 | int semantic, int index) |
||
855 | { |
||
856 | int i; |
||
857 | |||
858 | for (i = 0; i < len; i++) { |
||
859 | if (semantics[i] == semantic && indices[i] == index) |
||
860 | return i; |
||
861 | } |
||
862 | |||
863 | /* failed to match for COLOR, try BCOLOR */ |
||
864 | if (semantic == TGSI_SEMANTIC_COLOR) { |
||
865 | for (i = 0; i < len; i++) { |
||
866 | if (semantics[i] == TGSI_SEMANTIC_BCOLOR && indices[i] == index) |
||
867 | return i; |
||
868 | } |
||
869 | } |
||
870 | |||
871 | return -1; |
||
872 | } |
||
873 | |||
874 | /** |
||
875 | * Select a routing for the given source shader and rasterizer state. |
||
876 | * |
||
877 | * \return true if a different routing is selected |
||
878 | */ |
||
879 | bool |
||
880 | ilo_shader_select_kernel_routing(struct ilo_shader_state *shader, |
||
881 | const struct ilo_shader_state *source, |
||
882 | const struct ilo_rasterizer_state *rasterizer) |
||
883 | { |
||
884 | const uint32_t sprite_coord_enable = rasterizer->state.sprite_coord_enable; |
||
885 | const bool light_twoside = rasterizer->state.light_twoside; |
||
886 | struct ilo_shader *kernel = shader->shader; |
||
887 | struct ilo_kernel_routing *routing = &kernel->routing; |
||
888 | const int *src_semantics, *src_indices; |
||
889 | int src_len, max_src_slot; |
||
890 | int dst_len, dst_slot; |
||
891 | |||
892 | /* we are constructing 3DSTATE_SBE here */ |
||
893 | assert(shader->info.dev->gen >= ILO_GEN(6) && |
||
894 | shader->info.dev->gen <= ILO_GEN(7)); |
||
895 | |||
896 | assert(kernel); |
||
897 | |||
898 | if (source) { |
||
899 | assert(source->shader); |
||
900 | src_semantics = source->shader->out.semantic_names; |
||
901 | src_indices = source->shader->out.semantic_indices; |
||
902 | src_len = source->shader->out.count; |
||
903 | } |
||
904 | else { |
||
905 | src_semantics = kernel->in.semantic_names; |
||
906 | src_indices = kernel->in.semantic_indices; |
||
907 | src_len = kernel->in.count; |
||
908 | } |
||
909 | |||
910 | /* no change */ |
||
911 | if (kernel->routing_initialized && |
||
912 | routing->source_skip + routing->source_len <= src_len && |
||
913 | kernel->routing_sprite_coord_enable == sprite_coord_enable && |
||
914 | !memcmp(kernel->routing_src_semantics, |
||
915 | &src_semantics[routing->source_skip], |
||
916 | sizeof(kernel->routing_src_semantics[0]) * routing->source_len) && |
||
917 | !memcmp(kernel->routing_src_indices, |
||
918 | &src_indices[routing->source_skip], |
||
919 | sizeof(kernel->routing_src_indices[0]) * routing->source_len)) |
||
920 | return false; |
||
921 | |||
922 | if (source) { |
||
923 | /* skip PSIZE and POSITION (how about the optional CLIPDISTs?) */ |
||
924 | assert(src_semantics[0] == TGSI_SEMANTIC_PSIZE); |
||
925 | assert(src_semantics[1] == TGSI_SEMANTIC_POSITION); |
||
926 | routing->source_skip = 2; |
||
927 | |||
928 | routing->source_len = src_len - routing->source_skip; |
||
929 | src_semantics += routing->source_skip; |
||
930 | src_indices += routing->source_skip; |
||
931 | } |
||
932 | else { |
||
933 | routing->source_skip = 0; |
||
934 | routing->source_len = src_len; |
||
935 | } |
||
936 | |||
937 | routing->const_interp_enable = kernel->in.const_interp_enable; |
||
938 | routing->point_sprite_enable = 0; |
||
939 | routing->swizzle_enable = false; |
||
940 | |||
941 | assert(kernel->in.count <= Elements(routing->swizzles)); |
||
942 | dst_len = MIN2(kernel->in.count, Elements(routing->swizzles)); |
||
943 | max_src_slot = -1; |
||
944 | |||
945 | for (dst_slot = 0; dst_slot < dst_len; dst_slot++) { |
||
946 | const int semantic = kernel->in.semantic_names[dst_slot]; |
||
947 | const int index = kernel->in.semantic_indices[dst_slot]; |
||
948 | int src_slot; |
||
949 | |||
950 | if (semantic == TGSI_SEMANTIC_GENERIC && |
||
951 | (sprite_coord_enable & (1 << index))) |
||
952 | routing->point_sprite_enable |= 1 << dst_slot; |
||
953 | |||
954 | if (source) { |
||
955 | src_slot = route_attr(src_semantics, src_indices, |
||
956 | routing->source_len, semantic, index); |
||
957 | |||
958 | /* |
||
959 | * The source shader stage does not output this attribute. The value |
||
960 | * is supposed to be undefined, unless the attribute goes through |
||
961 | * point sprite replacement or the attribute is |
||
962 | * TGSI_SEMANTIC_POSITION. In all cases, we do not care which source |
||
963 | * attribute is picked. |
||
964 | * |
||
965 | * We should update the kernel code and omit the output of |
||
966 | * TGSI_SEMANTIC_POSITION here. |
||
967 | */ |
||
968 | if (src_slot < 0) |
||
969 | src_slot = 0; |
||
970 | } |
||
971 | else { |
||
972 | src_slot = dst_slot; |
||
973 | } |
||
974 | |||
975 | routing->swizzles[dst_slot] = src_slot; |
||
976 | |||
977 | /* use the following slot for two-sided lighting */ |
||
978 | if (semantic == TGSI_SEMANTIC_COLOR && light_twoside && |
||
979 | src_slot + 1 < routing->source_len && |
||
980 | src_semantics[src_slot + 1] == TGSI_SEMANTIC_BCOLOR && |
||
981 | src_indices[src_slot + 1] == index) { |
||
982 | routing->swizzles[dst_slot] |= ATTRIBUTE_SWIZZLE_INPUTATTR_FACING << |
||
983 | ATTRIBUTE_SWIZZLE_SHIFT; |
||
984 | src_slot++; |
||
985 | } |
||
986 | |||
987 | if (routing->swizzles[dst_slot] != dst_slot) |
||
988 | routing->swizzle_enable = true; |
||
989 | |||
990 | if (max_src_slot < src_slot) |
||
991 | max_src_slot = src_slot; |
||
992 | } |
||
993 | |||
994 | memset(&routing->swizzles[dst_slot], 0, sizeof(routing->swizzles) - |
||
995 | sizeof(routing->swizzles[0]) * dst_slot); |
||
996 | |||
997 | /* |
||
998 | * From the Sandy Bridge PRM, volume 2 part 1, page 248: |
||
999 | * |
||
1000 | * "It is UNDEFINED to set this field (Vertex URB Entry Read Length) to |
||
1001 | * 0 indicating no Vertex URB data to be read. |
||
1002 | * |
||
1003 | * This field should be set to the minimum length required to read the |
||
1004 | * maximum source attribute. The maximum source attribute is indicated |
||
1005 | * by the maximum value of the enabled Attribute # Source Attribute if |
||
1006 | * Attribute Swizzle Enable is set, Number of Output Attributes-1 if |
||
1007 | * enable is not set. |
||
1008 | * |
||
1009 | * read_length = ceiling((max_source_attr+1)/2) |
||
1010 | * |
||
1011 | * [errata] Corruption/Hang possible if length programmed larger than |
||
1012 | * recommended" |
||
1013 | */ |
||
1014 | routing->source_len = max_src_slot + 1; |
||
1015 | |||
1016 | /* remember the states of the source */ |
||
1017 | kernel->routing_initialized = true; |
||
1018 | kernel->routing_sprite_coord_enable = sprite_coord_enable; |
||
1019 | memcpy(kernel->routing_src_semantics, src_semantics, |
||
1020 | sizeof(kernel->routing_src_semantics[0]) * routing->source_len); |
||
1021 | memcpy(kernel->routing_src_indices, src_indices, |
||
1022 | sizeof(kernel->routing_src_indices[0]) * routing->source_len); |
||
1023 | |||
1024 | return true; |
||
1025 | } |
||
1026 | |||
1027 | /** |
||
1028 | * Return the cache offset of the selected kernel. This must be called after |
||
1029 | * ilo_shader_select_kernel() and ilo_shader_cache_upload(). |
||
1030 | */ |
||
1031 | uint32_t |
||
1032 | ilo_shader_get_kernel_offset(const struct ilo_shader_state *shader) |
||
1033 | { |
||
1034 | const struct ilo_shader *kernel = shader->shader; |
||
1035 | |||
1036 | assert(kernel && kernel->uploaded); |
||
1037 | |||
1038 | return kernel->cache_offset; |
||
1039 | } |
||
1040 | |||
1041 | /** |
||
1042 | * Query a kernel parameter for the selected kernel. |
||
1043 | */ |
||
1044 | int |
||
1045 | ilo_shader_get_kernel_param(const struct ilo_shader_state *shader, |
||
1046 | enum ilo_kernel_param param) |
||
1047 | { |
||
1048 | const struct ilo_shader *kernel = shader->shader; |
||
1049 | int val; |
||
1050 | |||
1051 | assert(kernel); |
||
1052 | |||
1053 | switch (param) { |
||
1054 | case ILO_KERNEL_INPUT_COUNT: |
||
1055 | val = kernel->in.count; |
||
1056 | break; |
||
1057 | case ILO_KERNEL_OUTPUT_COUNT: |
||
1058 | val = kernel->out.count; |
||
1059 | break; |
||
1060 | case ILO_KERNEL_URB_DATA_START_REG: |
||
1061 | val = kernel->in.start_grf; |
||
1062 | break; |
||
1063 | |||
1064 | case ILO_KERNEL_VS_INPUT_INSTANCEID: |
||
1065 | val = shader->info.has_instanceid; |
||
1066 | break; |
||
1067 | case ILO_KERNEL_VS_INPUT_VERTEXID: |
||
1068 | val = shader->info.has_vertexid; |
||
1069 | break; |
||
1070 | case ILO_KERNEL_VS_INPUT_EDGEFLAG: |
||
1071 | if (shader->info.edgeflag_in >= 0) { |
||
1072 | /* we rely on the state tracker here */ |
||
1073 | assert(shader->info.edgeflag_in == kernel->in.count - 1); |
||
1074 | val = true; |
||
1075 | } |
||
1076 | else { |
||
1077 | val = false; |
||
1078 | } |
||
1079 | break; |
||
1080 | case ILO_KERNEL_VS_PCB_UCP_SIZE: |
||
1081 | val = kernel->pcb.clip_state_size; |
||
1082 | break; |
||
1083 | case ILO_KERNEL_VS_GEN6_SO: |
||
1084 | val = kernel->stream_output; |
||
1085 | break; |
||
1086 | case ILO_KERNEL_VS_GEN6_SO_START_REG: |
||
1087 | val = kernel->gs_start_grf; |
||
1088 | break; |
||
1089 | case ILO_KERNEL_VS_GEN6_SO_POINT_OFFSET: |
||
1090 | val = kernel->gs_offsets[0]; |
||
1091 | break; |
||
1092 | case ILO_KERNEL_VS_GEN6_SO_LINE_OFFSET: |
||
1093 | val = kernel->gs_offsets[1]; |
||
1094 | break; |
||
1095 | case ILO_KERNEL_VS_GEN6_SO_TRI_OFFSET: |
||
1096 | val = kernel->gs_offsets[2]; |
||
1097 | break; |
||
1098 | |||
1099 | case ILO_KERNEL_GS_DISCARD_ADJACENCY: |
||
1100 | val = kernel->in.discard_adj; |
||
1101 | break; |
||
1102 | case ILO_KERNEL_GS_GEN6_SVBI_POST_INC: |
||
1103 | val = kernel->svbi_post_inc; |
||
1104 | break; |
||
1105 | |||
1106 | case ILO_KERNEL_FS_INPUT_Z: |
||
1107 | case ILO_KERNEL_FS_INPUT_W: |
||
1108 | val = kernel->in.has_pos; |
||
1109 | break; |
||
1110 | case ILO_KERNEL_FS_OUTPUT_Z: |
||
1111 | val = kernel->out.has_pos; |
||
1112 | break; |
||
1113 | case ILO_KERNEL_FS_USE_KILL: |
||
1114 | val = kernel->has_kill; |
||
1115 | break; |
||
1116 | case ILO_KERNEL_FS_BARYCENTRIC_INTERPOLATIONS: |
||
1117 | val = kernel->in.barycentric_interpolation_mode; |
||
1118 | break; |
||
1119 | case ILO_KERNEL_FS_DISPATCH_16_OFFSET: |
||
1120 | val = 0; |
||
1121 | break; |
||
1122 | |||
1123 | default: |
||
1124 | assert(!"unknown kernel parameter"); |
||
1125 | val = 0; |
||
1126 | break; |
||
1127 | } |
||
1128 | |||
1129 | return val; |
||
1130 | } |
||
1131 | |||
1132 | /** |
||
1133 | * Return the CSO of the selected kernel. |
||
1134 | */ |
||
1135 | const struct ilo_shader_cso * |
||
1136 | ilo_shader_get_kernel_cso(const struct ilo_shader_state *shader) |
||
1137 | { |
||
1138 | const struct ilo_shader *kernel = shader->shader; |
||
1139 | |||
1140 | assert(kernel); |
||
1141 | |||
1142 | return &kernel->cso; |
||
1143 | } |
||
1144 | |||
1145 | /** |
||
1146 | * Return the SO info of the selected kernel. |
||
1147 | */ |
||
1148 | const struct pipe_stream_output_info * |
||
1149 | ilo_shader_get_kernel_so_info(const struct ilo_shader_state *shader) |
||
1150 | { |
||
1151 | const struct ilo_shader *kernel = shader->shader; |
||
1152 | |||
1153 | assert(kernel); |
||
1154 | |||
1155 | return &kernel->so_info; |
||
1156 | } |
||
1157 | |||
1158 | /** |
||
1159 | * Return the routing info of the selected kernel. |
||
1160 | */ |
||
1161 | const struct ilo_kernel_routing * |
||
1162 | ilo_shader_get_kernel_routing(const struct ilo_shader_state *shader) |
||
1163 | { |
||
1164 | const struct ilo_shader *kernel = shader->shader; |
||
1165 | |||
1166 | assert(kernel); |
||
1167 | |||
1168 | return &kernel->routing; |
||
1169 | }> |