tgsi/ureg: don't emit in/out arrays if drivers don't support ranged declarations
[mesa.git] / src / gallium / auxiliary / tgsi / tgsi_ureg.c
1 /**************************************************************************
2 *
3 * Copyright 2009-2010 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE, INC AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29 #include "pipe/p_screen.h"
30 #include "pipe/p_context.h"
31 #include "pipe/p_state.h"
32 #include "tgsi/tgsi_ureg.h"
33 #include "tgsi/tgsi_build.h"
34 #include "tgsi/tgsi_info.h"
35 #include "tgsi/tgsi_dump.h"
36 #include "tgsi/tgsi_sanity.h"
37 #include "util/u_debug.h"
38 #include "util/u_memory.h"
39 #include "util/u_math.h"
40 #include "util/u_bitmask.h"
41
42 union tgsi_any_token {
43 struct tgsi_header header;
44 struct tgsi_processor processor;
45 struct tgsi_token token;
46 struct tgsi_property prop;
47 struct tgsi_property_data prop_data;
48 struct tgsi_declaration decl;
49 struct tgsi_declaration_range decl_range;
50 struct tgsi_declaration_dimension decl_dim;
51 struct tgsi_declaration_interp decl_interp;
52 struct tgsi_declaration_semantic decl_semantic;
53 struct tgsi_declaration_sampler_view decl_sampler_view;
54 struct tgsi_declaration_array array;
55 struct tgsi_immediate imm;
56 union tgsi_immediate_data imm_data;
57 struct tgsi_instruction insn;
58 struct tgsi_instruction_predicate insn_predicate;
59 struct tgsi_instruction_label insn_label;
60 struct tgsi_instruction_texture insn_texture;
61 struct tgsi_texture_offset insn_texture_offset;
62 struct tgsi_src_register src;
63 struct tgsi_ind_register ind;
64 struct tgsi_dimension dim;
65 struct tgsi_dst_register dst;
66 unsigned value;
67 };
68
69
70 struct ureg_tokens {
71 union tgsi_any_token *tokens;
72 unsigned size;
73 unsigned order;
74 unsigned count;
75 };
76
77 #define UREG_MAX_INPUT PIPE_MAX_SHADER_INPUTS
78 #define UREG_MAX_SYSTEM_VALUE PIPE_MAX_ATTRIBS
79 #define UREG_MAX_OUTPUT PIPE_MAX_SHADER_OUTPUTS
80 #define UREG_MAX_CONSTANT_RANGE 32
81 #define UREG_MAX_IMMEDIATE 4096
82 #define UREG_MAX_ADDR 3
83 #define UREG_MAX_PRED 1
84 #define UREG_MAX_ARRAY_TEMPS 256
85
86 struct const_decl {
87 struct {
88 unsigned first;
89 unsigned last;
90 } constant_range[UREG_MAX_CONSTANT_RANGE];
91 unsigned nr_constant_ranges;
92 };
93
94 #define DOMAIN_DECL 0
95 #define DOMAIN_INSN 1
96
97 struct ureg_program
98 {
99 unsigned processor;
100 bool supports_any_inout_decl_range;
101
102 struct {
103 unsigned semantic_name;
104 unsigned semantic_index;
105 unsigned interp;
106 unsigned char cylindrical_wrap;
107 unsigned interp_location;
108 unsigned first;
109 unsigned last;
110 unsigned array_id;
111 } input[UREG_MAX_INPUT];
112 unsigned nr_inputs, nr_input_regs;
113
114 unsigned vs_inputs[UREG_MAX_INPUT/32];
115
116 struct {
117 unsigned index;
118 unsigned semantic_name;
119 unsigned semantic_index;
120 } system_value[UREG_MAX_SYSTEM_VALUE];
121 unsigned nr_system_values;
122
123 struct {
124 unsigned semantic_name;
125 unsigned semantic_index;
126 unsigned usage_mask; /* = TGSI_WRITEMASK_* */
127 unsigned first;
128 unsigned last;
129 unsigned array_id;
130 } output[UREG_MAX_OUTPUT];
131 unsigned nr_outputs, nr_output_regs;
132
133 struct {
134 union {
135 float f[4];
136 unsigned u[4];
137 int i[4];
138 } value;
139 unsigned nr;
140 unsigned type;
141 } immediate[UREG_MAX_IMMEDIATE];
142 unsigned nr_immediates;
143
144 struct ureg_src sampler[PIPE_MAX_SAMPLERS];
145 unsigned nr_samplers;
146
147 struct {
148 unsigned index;
149 unsigned target;
150 unsigned return_type_x;
151 unsigned return_type_y;
152 unsigned return_type_z;
153 unsigned return_type_w;
154 } sampler_view[PIPE_MAX_SHADER_SAMPLER_VIEWS];
155 unsigned nr_sampler_views;
156
157 struct util_bitmask *free_temps;
158 struct util_bitmask *local_temps;
159 struct util_bitmask *decl_temps;
160 unsigned nr_temps;
161
162 unsigned array_temps[UREG_MAX_ARRAY_TEMPS];
163 unsigned nr_array_temps;
164
165 struct const_decl const_decls;
166 struct const_decl const_decls2D[PIPE_MAX_CONSTANT_BUFFERS];
167
168 unsigned properties[TGSI_PROPERTY_COUNT];
169
170 unsigned nr_addrs;
171 unsigned nr_preds;
172 unsigned nr_instructions;
173
174 struct ureg_tokens domain[2];
175 };
176
177 static union tgsi_any_token error_tokens[32];
178
179 static void tokens_error( struct ureg_tokens *tokens )
180 {
181 if (tokens->tokens && tokens->tokens != error_tokens)
182 FREE(tokens->tokens);
183
184 tokens->tokens = error_tokens;
185 tokens->size = Elements(error_tokens);
186 tokens->count = 0;
187 }
188
189
190 static void tokens_expand( struct ureg_tokens *tokens,
191 unsigned count )
192 {
193 unsigned old_size = tokens->size * sizeof(unsigned);
194
195 if (tokens->tokens == error_tokens) {
196 return;
197 }
198
199 while (tokens->count + count > tokens->size) {
200 tokens->size = (1 << ++tokens->order);
201 }
202
203 tokens->tokens = REALLOC(tokens->tokens,
204 old_size,
205 tokens->size * sizeof(unsigned));
206 if (tokens->tokens == NULL) {
207 tokens_error(tokens);
208 }
209 }
210
211 static void set_bad( struct ureg_program *ureg )
212 {
213 tokens_error(&ureg->domain[0]);
214 }
215
216
217
218 static union tgsi_any_token *get_tokens( struct ureg_program *ureg,
219 unsigned domain,
220 unsigned count )
221 {
222 struct ureg_tokens *tokens = &ureg->domain[domain];
223 union tgsi_any_token *result;
224
225 if (tokens->count + count > tokens->size)
226 tokens_expand(tokens, count);
227
228 result = &tokens->tokens[tokens->count];
229 tokens->count += count;
230 return result;
231 }
232
233
234 static union tgsi_any_token *retrieve_token( struct ureg_program *ureg,
235 unsigned domain,
236 unsigned nr )
237 {
238 if (ureg->domain[domain].tokens == error_tokens)
239 return &error_tokens[0];
240
241 return &ureg->domain[domain].tokens[nr];
242 }
243
244 void
245 ureg_property(struct ureg_program *ureg, unsigned name, unsigned value)
246 {
247 assert(name < Elements(ureg->properties));
248 ureg->properties[name] = value;
249 }
250
251 struct ureg_src
252 ureg_DECL_fs_input_cyl_centroid(struct ureg_program *ureg,
253 unsigned semantic_name,
254 unsigned semantic_index,
255 unsigned interp_mode,
256 unsigned cylindrical_wrap,
257 unsigned interp_location,
258 unsigned array_id,
259 unsigned array_size)
260 {
261 unsigned i;
262
263 for (i = 0; i < ureg->nr_inputs; i++) {
264 if (ureg->input[i].semantic_name == semantic_name &&
265 ureg->input[i].semantic_index == semantic_index) {
266 assert(ureg->input[i].interp == interp_mode);
267 assert(ureg->input[i].cylindrical_wrap == cylindrical_wrap);
268 assert(ureg->input[i].interp_location == interp_location);
269 assert(ureg->input[i].array_id == array_id);
270 goto out;
271 }
272 }
273
274 if (ureg->nr_inputs < UREG_MAX_INPUT) {
275 assert(array_size >= 1);
276 ureg->input[i].semantic_name = semantic_name;
277 ureg->input[i].semantic_index = semantic_index;
278 ureg->input[i].interp = interp_mode;
279 ureg->input[i].cylindrical_wrap = cylindrical_wrap;
280 ureg->input[i].interp_location = interp_location;
281 ureg->input[i].first = ureg->nr_input_regs;
282 ureg->input[i].last = ureg->nr_input_regs + array_size - 1;
283 ureg->input[i].array_id = array_id;
284 ureg->nr_input_regs += array_size;
285 ureg->nr_inputs++;
286 } else {
287 set_bad(ureg);
288 }
289
290 out:
291 return ureg_src_array_register(TGSI_FILE_INPUT, ureg->input[i].first,
292 array_id);
293 }
294
295
296 struct ureg_src
297 ureg_DECL_vs_input( struct ureg_program *ureg,
298 unsigned index )
299 {
300 assert(ureg->processor == TGSI_PROCESSOR_VERTEX);
301
302 ureg->vs_inputs[index/32] |= 1 << (index % 32);
303 return ureg_src_register( TGSI_FILE_INPUT, index );
304 }
305
306
307 struct ureg_src
308 ureg_DECL_input(struct ureg_program *ureg,
309 unsigned semantic_name,
310 unsigned semantic_index,
311 unsigned array_id,
312 unsigned array_size)
313 {
314 return ureg_DECL_fs_input_cyl_centroid(ureg, semantic_name, semantic_index,
315 0, 0, 0, array_id, array_size);
316 }
317
318
319 struct ureg_src
320 ureg_DECL_system_value(struct ureg_program *ureg,
321 unsigned index,
322 unsigned semantic_name,
323 unsigned semantic_index)
324 {
325 if (ureg->nr_system_values < UREG_MAX_SYSTEM_VALUE) {
326 ureg->system_value[ureg->nr_system_values].index = index;
327 ureg->system_value[ureg->nr_system_values].semantic_name = semantic_name;
328 ureg->system_value[ureg->nr_system_values].semantic_index = semantic_index;
329 ureg->nr_system_values++;
330 } else {
331 set_bad(ureg);
332 }
333
334 return ureg_src_register(TGSI_FILE_SYSTEM_VALUE, index);
335 }
336
337
338 struct ureg_dst
339 ureg_DECL_output_masked(struct ureg_program *ureg,
340 unsigned name,
341 unsigned index,
342 unsigned usage_mask,
343 unsigned array_id,
344 unsigned array_size)
345 {
346 unsigned i;
347
348 assert(usage_mask != 0);
349
350 for (i = 0; i < ureg->nr_outputs; i++) {
351 if (ureg->output[i].semantic_name == name &&
352 ureg->output[i].semantic_index == index) {
353 assert(ureg->output[i].array_id == array_id);
354 ureg->output[i].usage_mask |= usage_mask;
355 goto out;
356 }
357 }
358
359 if (ureg->nr_outputs < UREG_MAX_OUTPUT) {
360 ureg->output[i].semantic_name = name;
361 ureg->output[i].semantic_index = index;
362 ureg->output[i].usage_mask = usage_mask;
363 ureg->output[i].first = ureg->nr_output_regs;
364 ureg->output[i].last = ureg->nr_output_regs + array_size - 1;
365 ureg->output[i].array_id = array_id;
366 ureg->nr_output_regs += array_size;
367 ureg->nr_outputs++;
368 }
369 else {
370 set_bad( ureg );
371 }
372
373 out:
374 return ureg_dst_array_register(TGSI_FILE_OUTPUT, ureg->output[i].first,
375 array_id);
376 }
377
378
379 struct ureg_dst
380 ureg_DECL_output(struct ureg_program *ureg,
381 unsigned name,
382 unsigned index)
383 {
384 return ureg_DECL_output_masked(ureg, name, index, TGSI_WRITEMASK_XYZW,
385 0, 1);
386 }
387
388 struct ureg_dst
389 ureg_DECL_output_array(struct ureg_program *ureg,
390 unsigned semantic_name,
391 unsigned semantic_index,
392 unsigned array_id,
393 unsigned array_size)
394 {
395 return ureg_DECL_output_masked(ureg, semantic_name, semantic_index,
396 TGSI_WRITEMASK_XYZW,
397 array_id, array_size);
398 }
399
400
401 /* Returns a new constant register. Keep track of which have been
402 * referred to so that we can emit decls later.
403 *
404 * Constant operands declared with this function must be addressed
405 * with a two-dimensional index.
406 *
407 * There is nothing in this code to bind this constant to any tracked
408 * value or manage any constant_buffer contents -- that's the
409 * resposibility of the calling code.
410 */
411 void
412 ureg_DECL_constant2D(struct ureg_program *ureg,
413 unsigned first,
414 unsigned last,
415 unsigned index2D)
416 {
417 struct const_decl *decl = &ureg->const_decls2D[index2D];
418
419 assert(index2D < PIPE_MAX_CONSTANT_BUFFERS);
420
421 if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) {
422 uint i = decl->nr_constant_ranges++;
423
424 decl->constant_range[i].first = first;
425 decl->constant_range[i].last = last;
426 }
427 }
428
429
430 /* A one-dimensional, depricated version of ureg_DECL_constant2D().
431 *
432 * Constant operands declared with this function must be addressed
433 * with a one-dimensional index.
434 */
435 struct ureg_src
436 ureg_DECL_constant(struct ureg_program *ureg,
437 unsigned index)
438 {
439 struct const_decl *decl = &ureg->const_decls;
440 unsigned minconst = index, maxconst = index;
441 unsigned i;
442
443 /* Inside existing range?
444 */
445 for (i = 0; i < decl->nr_constant_ranges; i++) {
446 if (decl->constant_range[i].first <= index &&
447 decl->constant_range[i].last >= index) {
448 goto out;
449 }
450 }
451
452 /* Extend existing range?
453 */
454 for (i = 0; i < decl->nr_constant_ranges; i++) {
455 if (decl->constant_range[i].last == index - 1) {
456 decl->constant_range[i].last = index;
457 goto out;
458 }
459
460 if (decl->constant_range[i].first == index + 1) {
461 decl->constant_range[i].first = index;
462 goto out;
463 }
464
465 minconst = MIN2(minconst, decl->constant_range[i].first);
466 maxconst = MAX2(maxconst, decl->constant_range[i].last);
467 }
468
469 /* Create new range?
470 */
471 if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) {
472 i = decl->nr_constant_ranges++;
473 decl->constant_range[i].first = index;
474 decl->constant_range[i].last = index;
475 goto out;
476 }
477
478 /* Collapse all ranges down to one:
479 */
480 i = 0;
481 decl->constant_range[0].first = minconst;
482 decl->constant_range[0].last = maxconst;
483 decl->nr_constant_ranges = 1;
484
485 out:
486 assert(i < decl->nr_constant_ranges);
487 assert(decl->constant_range[i].first <= index);
488 assert(decl->constant_range[i].last >= index);
489 return ureg_src_register(TGSI_FILE_CONSTANT, index);
490 }
491
492 static struct ureg_dst alloc_temporary( struct ureg_program *ureg,
493 boolean local )
494 {
495 unsigned i;
496
497 /* Look for a released temporary.
498 */
499 for (i = util_bitmask_get_first_index(ureg->free_temps);
500 i != UTIL_BITMASK_INVALID_INDEX;
501 i = util_bitmask_get_next_index(ureg->free_temps, i + 1)) {
502 if (util_bitmask_get(ureg->local_temps, i) == local)
503 break;
504 }
505
506 /* Or allocate a new one.
507 */
508 if (i == UTIL_BITMASK_INVALID_INDEX) {
509 i = ureg->nr_temps++;
510
511 if (local)
512 util_bitmask_set(ureg->local_temps, i);
513
514 /* Start a new declaration when the local flag changes */
515 if (!i || util_bitmask_get(ureg->local_temps, i - 1) != local)
516 util_bitmask_set(ureg->decl_temps, i);
517 }
518
519 util_bitmask_clear(ureg->free_temps, i);
520
521 return ureg_dst_register( TGSI_FILE_TEMPORARY, i );
522 }
523
524 struct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg )
525 {
526 return alloc_temporary(ureg, FALSE);
527 }
528
529 struct ureg_dst ureg_DECL_local_temporary( struct ureg_program *ureg )
530 {
531 return alloc_temporary(ureg, TRUE);
532 }
533
534 struct ureg_dst ureg_DECL_array_temporary( struct ureg_program *ureg,
535 unsigned size,
536 boolean local )
537 {
538 unsigned i = ureg->nr_temps;
539 struct ureg_dst dst = ureg_dst_register( TGSI_FILE_TEMPORARY, i );
540
541 if (local)
542 util_bitmask_set(ureg->local_temps, i);
543
544 /* Always start a new declaration at the start */
545 util_bitmask_set(ureg->decl_temps, i);
546
547 ureg->nr_temps += size;
548
549 /* and also at the end of the array */
550 util_bitmask_set(ureg->decl_temps, ureg->nr_temps);
551
552 if (ureg->nr_array_temps < UREG_MAX_ARRAY_TEMPS) {
553 ureg->array_temps[ureg->nr_array_temps++] = i;
554 dst.ArrayID = ureg->nr_array_temps;
555 }
556
557 return dst;
558 }
559
560 void ureg_release_temporary( struct ureg_program *ureg,
561 struct ureg_dst tmp )
562 {
563 if(tmp.File == TGSI_FILE_TEMPORARY)
564 util_bitmask_set(ureg->free_temps, tmp.Index);
565 }
566
567
568 /* Allocate a new address register.
569 */
570 struct ureg_dst ureg_DECL_address( struct ureg_program *ureg )
571 {
572 if (ureg->nr_addrs < UREG_MAX_ADDR)
573 return ureg_dst_register( TGSI_FILE_ADDRESS, ureg->nr_addrs++ );
574
575 assert( 0 );
576 return ureg_dst_register( TGSI_FILE_ADDRESS, 0 );
577 }
578
579 /* Allocate a new predicate register.
580 */
581 struct ureg_dst
582 ureg_DECL_predicate(struct ureg_program *ureg)
583 {
584 if (ureg->nr_preds < UREG_MAX_PRED) {
585 return ureg_dst_register(TGSI_FILE_PREDICATE, ureg->nr_preds++);
586 }
587
588 assert(0);
589 return ureg_dst_register(TGSI_FILE_PREDICATE, 0);
590 }
591
592 /* Allocate a new sampler.
593 */
594 struct ureg_src ureg_DECL_sampler( struct ureg_program *ureg,
595 unsigned nr )
596 {
597 unsigned i;
598
599 for (i = 0; i < ureg->nr_samplers; i++)
600 if (ureg->sampler[i].Index == nr)
601 return ureg->sampler[i];
602
603 if (i < PIPE_MAX_SAMPLERS) {
604 ureg->sampler[i] = ureg_src_register( TGSI_FILE_SAMPLER, nr );
605 ureg->nr_samplers++;
606 return ureg->sampler[i];
607 }
608
609 assert( 0 );
610 return ureg->sampler[0];
611 }
612
613 /*
614 * Allocate a new shader sampler view.
615 */
616 struct ureg_src
617 ureg_DECL_sampler_view(struct ureg_program *ureg,
618 unsigned index,
619 unsigned target,
620 unsigned return_type_x,
621 unsigned return_type_y,
622 unsigned return_type_z,
623 unsigned return_type_w)
624 {
625 struct ureg_src reg = ureg_src_register(TGSI_FILE_SAMPLER_VIEW, index);
626 uint i;
627
628 for (i = 0; i < ureg->nr_sampler_views; i++) {
629 if (ureg->sampler_view[i].index == index) {
630 return reg;
631 }
632 }
633
634 if (i < PIPE_MAX_SHADER_SAMPLER_VIEWS) {
635 ureg->sampler_view[i].index = index;
636 ureg->sampler_view[i].target = target;
637 ureg->sampler_view[i].return_type_x = return_type_x;
638 ureg->sampler_view[i].return_type_y = return_type_y;
639 ureg->sampler_view[i].return_type_z = return_type_z;
640 ureg->sampler_view[i].return_type_w = return_type_w;
641 ureg->nr_sampler_views++;
642 return reg;
643 }
644
645 assert(0);
646 return reg;
647 }
648
649 static int
650 match_or_expand_immediate64( const unsigned *v,
651 int type,
652 unsigned nr,
653 unsigned *v2,
654 unsigned *pnr2,
655 unsigned *swizzle )
656 {
657 unsigned nr2 = *pnr2;
658 unsigned i, j;
659 *swizzle = 0;
660
661 for (i = 0; i < nr; i += 2) {
662 boolean found = FALSE;
663
664 for (j = 0; j < nr2 && !found; j += 2) {
665 if (v[i] == v2[j] && v[i + 1] == v2[j + 1]) {
666 *swizzle |= (j << (i * 2)) | ((j + 1) << ((i + 1) * 2));
667 found = TRUE;
668 }
669 }
670 if (!found) {
671 if ((nr2) >= 4) {
672 return FALSE;
673 }
674
675 v2[nr2] = v[i];
676 v2[nr2 + 1] = v[i + 1];
677
678 *swizzle |= (nr2 << (i * 2)) | ((nr2 + 1) << ((i + 1) * 2));
679 nr2 += 2;
680 }
681 }
682
683 /* Actually expand immediate only when fully succeeded.
684 */
685 *pnr2 = nr2;
686 return TRUE;
687 }
688
689 static int
690 match_or_expand_immediate( const unsigned *v,
691 int type,
692 unsigned nr,
693 unsigned *v2,
694 unsigned *pnr2,
695 unsigned *swizzle )
696 {
697 unsigned nr2 = *pnr2;
698 unsigned i, j;
699
700 if (type == TGSI_IMM_FLOAT64)
701 return match_or_expand_immediate64(v, type, nr, v2, pnr2, swizzle);
702
703 *swizzle = 0;
704
705 for (i = 0; i < nr; i++) {
706 boolean found = FALSE;
707
708 for (j = 0; j < nr2 && !found; j++) {
709 if (v[i] == v2[j]) {
710 *swizzle |= j << (i * 2);
711 found = TRUE;
712 }
713 }
714
715 if (!found) {
716 if (nr2 >= 4) {
717 return FALSE;
718 }
719
720 v2[nr2] = v[i];
721 *swizzle |= nr2 << (i * 2);
722 nr2++;
723 }
724 }
725
726 /* Actually expand immediate only when fully succeeded.
727 */
728 *pnr2 = nr2;
729 return TRUE;
730 }
731
732
733 static struct ureg_src
734 decl_immediate( struct ureg_program *ureg,
735 const unsigned *v,
736 unsigned nr,
737 unsigned type )
738 {
739 unsigned i, j;
740 unsigned swizzle = 0;
741
742 /* Could do a first pass where we examine all existing immediates
743 * without expanding.
744 */
745
746 for (i = 0; i < ureg->nr_immediates; i++) {
747 if (ureg->immediate[i].type != type) {
748 continue;
749 }
750 if (match_or_expand_immediate(v,
751 type,
752 nr,
753 ureg->immediate[i].value.u,
754 &ureg->immediate[i].nr,
755 &swizzle)) {
756 goto out;
757 }
758 }
759
760 if (ureg->nr_immediates < UREG_MAX_IMMEDIATE) {
761 i = ureg->nr_immediates++;
762 ureg->immediate[i].type = type;
763 if (match_or_expand_immediate(v,
764 type,
765 nr,
766 ureg->immediate[i].value.u,
767 &ureg->immediate[i].nr,
768 &swizzle)) {
769 goto out;
770 }
771 }
772
773 set_bad(ureg);
774
775 out:
776 /* Make sure that all referenced elements are from this immediate.
777 * Has the effect of making size-one immediates into scalars.
778 */
779 if (type == TGSI_IMM_FLOAT64) {
780 for (j = nr; j < 4; j+=2) {
781 swizzle |= (swizzle & 0xf) << (j * 2);
782 }
783 } else {
784 for (j = nr; j < 4; j++) {
785 swizzle |= (swizzle & 0x3) << (j * 2);
786 }
787 }
788 return ureg_swizzle(ureg_src_register(TGSI_FILE_IMMEDIATE, i),
789 (swizzle >> 0) & 0x3,
790 (swizzle >> 2) & 0x3,
791 (swizzle >> 4) & 0x3,
792 (swizzle >> 6) & 0x3);
793 }
794
795
796 struct ureg_src
797 ureg_DECL_immediate( struct ureg_program *ureg,
798 const float *v,
799 unsigned nr )
800 {
801 union {
802 float f[4];
803 unsigned u[4];
804 } fu;
805 unsigned int i;
806
807 for (i = 0; i < nr; i++) {
808 fu.f[i] = v[i];
809 }
810
811 return decl_immediate(ureg, fu.u, nr, TGSI_IMM_FLOAT32);
812 }
813
814 struct ureg_src
815 ureg_DECL_immediate_f64( struct ureg_program *ureg,
816 const double *v,
817 unsigned nr )
818 {
819 union {
820 unsigned u[4];
821 double d[2];
822 } fu;
823 unsigned int i;
824
825 assert((nr / 2) < 3);
826 for (i = 0; i < nr / 2; i++) {
827 fu.d[i] = v[i];
828 }
829
830 return decl_immediate(ureg, fu.u, nr, TGSI_IMM_FLOAT64);
831 }
832
833 struct ureg_src
834 ureg_DECL_immediate_uint( struct ureg_program *ureg,
835 const unsigned *v,
836 unsigned nr )
837 {
838 return decl_immediate(ureg, v, nr, TGSI_IMM_UINT32);
839 }
840
841
842 struct ureg_src
843 ureg_DECL_immediate_block_uint( struct ureg_program *ureg,
844 const unsigned *v,
845 unsigned nr )
846 {
847 uint index;
848 uint i;
849
850 if (ureg->nr_immediates + (nr + 3) / 4 > UREG_MAX_IMMEDIATE) {
851 set_bad(ureg);
852 return ureg_src_register(TGSI_FILE_IMMEDIATE, 0);
853 }
854
855 index = ureg->nr_immediates;
856 ureg->nr_immediates += (nr + 3) / 4;
857
858 for (i = index; i < ureg->nr_immediates; i++) {
859 ureg->immediate[i].type = TGSI_IMM_UINT32;
860 ureg->immediate[i].nr = nr > 4 ? 4 : nr;
861 memcpy(ureg->immediate[i].value.u,
862 &v[(i - index) * 4],
863 ureg->immediate[i].nr * sizeof(uint));
864 nr -= 4;
865 }
866
867 return ureg_src_register(TGSI_FILE_IMMEDIATE, index);
868 }
869
870
871 struct ureg_src
872 ureg_DECL_immediate_int( struct ureg_program *ureg,
873 const int *v,
874 unsigned nr )
875 {
876 return decl_immediate(ureg, (const unsigned *)v, nr, TGSI_IMM_INT32);
877 }
878
879
880 void
881 ureg_emit_src( struct ureg_program *ureg,
882 struct ureg_src src )
883 {
884 unsigned size = 1 + (src.Indirect ? 1 : 0) +
885 (src.Dimension ? (src.DimIndirect ? 2 : 1) : 0);
886
887 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
888 unsigned n = 0;
889
890 assert(src.File != TGSI_FILE_NULL);
891 assert(src.File < TGSI_FILE_COUNT);
892
893 out[n].value = 0;
894 out[n].src.File = src.File;
895 out[n].src.SwizzleX = src.SwizzleX;
896 out[n].src.SwizzleY = src.SwizzleY;
897 out[n].src.SwizzleZ = src.SwizzleZ;
898 out[n].src.SwizzleW = src.SwizzleW;
899 out[n].src.Index = src.Index;
900 out[n].src.Negate = src.Negate;
901 out[0].src.Absolute = src.Absolute;
902 n++;
903
904 if (src.Indirect) {
905 out[0].src.Indirect = 1;
906 out[n].value = 0;
907 out[n].ind.File = src.IndirectFile;
908 out[n].ind.Swizzle = src.IndirectSwizzle;
909 out[n].ind.Index = src.IndirectIndex;
910 if (!ureg->supports_any_inout_decl_range &&
911 (src.File == TGSI_FILE_INPUT || src.File == TGSI_FILE_OUTPUT))
912 out[n].ind.ArrayID = 0;
913 else
914 out[n].ind.ArrayID = src.ArrayID;
915 n++;
916 }
917
918 if (src.Dimension) {
919 out[0].src.Dimension = 1;
920 out[n].dim.Dimension = 0;
921 out[n].dim.Padding = 0;
922 if (src.DimIndirect) {
923 out[n].dim.Indirect = 1;
924 out[n].dim.Index = src.DimensionIndex;
925 n++;
926 out[n].value = 0;
927 out[n].ind.File = src.DimIndFile;
928 out[n].ind.Swizzle = src.DimIndSwizzle;
929 out[n].ind.Index = src.DimIndIndex;
930 if (!ureg->supports_any_inout_decl_range &&
931 (src.File == TGSI_FILE_INPUT || src.File == TGSI_FILE_OUTPUT))
932 out[n].ind.ArrayID = 0;
933 else
934 out[n].ind.ArrayID = src.ArrayID;
935 } else {
936 out[n].dim.Indirect = 0;
937 out[n].dim.Index = src.DimensionIndex;
938 }
939 n++;
940 }
941
942 assert(n == size);
943 }
944
945
946 void
947 ureg_emit_dst( struct ureg_program *ureg,
948 struct ureg_dst dst )
949 {
950 unsigned size = 1 + (dst.Indirect ? 1 : 0) +
951 (dst.Dimension ? (dst.DimIndirect ? 2 : 1) : 0);
952
953 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
954 unsigned n = 0;
955
956 assert(dst.File != TGSI_FILE_NULL);
957 assert(dst.File != TGSI_FILE_CONSTANT);
958 assert(dst.File != TGSI_FILE_INPUT);
959 assert(dst.File != TGSI_FILE_SAMPLER);
960 assert(dst.File != TGSI_FILE_SAMPLER_VIEW);
961 assert(dst.File != TGSI_FILE_IMMEDIATE);
962 assert(dst.File < TGSI_FILE_COUNT);
963
964 out[n].value = 0;
965 out[n].dst.File = dst.File;
966 out[n].dst.WriteMask = dst.WriteMask;
967 out[n].dst.Indirect = dst.Indirect;
968 out[n].dst.Index = dst.Index;
969 n++;
970
971 if (dst.Indirect) {
972 out[n].value = 0;
973 out[n].ind.File = dst.IndirectFile;
974 out[n].ind.Swizzle = dst.IndirectSwizzle;
975 out[n].ind.Index = dst.IndirectIndex;
976 if (!ureg->supports_any_inout_decl_range &&
977 (dst.File == TGSI_FILE_INPUT || dst.File == TGSI_FILE_OUTPUT))
978 out[n].ind.ArrayID = 0;
979 else
980 out[n].ind.ArrayID = dst.ArrayID;
981 n++;
982 }
983
984 if (dst.Dimension) {
985 out[0].dst.Dimension = 1;
986 out[n].dim.Dimension = 0;
987 out[n].dim.Padding = 0;
988 if (dst.DimIndirect) {
989 out[n].dim.Indirect = 1;
990 out[n].dim.Index = dst.DimensionIndex;
991 n++;
992 out[n].value = 0;
993 out[n].ind.File = dst.DimIndFile;
994 out[n].ind.Swizzle = dst.DimIndSwizzle;
995 out[n].ind.Index = dst.DimIndIndex;
996 if (!ureg->supports_any_inout_decl_range &&
997 (dst.File == TGSI_FILE_INPUT || dst.File == TGSI_FILE_OUTPUT))
998 out[n].ind.ArrayID = 0;
999 else
1000 out[n].ind.ArrayID = dst.ArrayID;
1001 } else {
1002 out[n].dim.Indirect = 0;
1003 out[n].dim.Index = dst.DimensionIndex;
1004 }
1005 n++;
1006 }
1007
1008 assert(n == size);
1009 }
1010
1011
1012 static void validate( unsigned opcode,
1013 unsigned nr_dst,
1014 unsigned nr_src )
1015 {
1016 #ifdef DEBUG
1017 const struct tgsi_opcode_info *info = tgsi_get_opcode_info( opcode );
1018 assert(info);
1019 if(info) {
1020 assert(nr_dst == info->num_dst);
1021 assert(nr_src == info->num_src);
1022 }
1023 #endif
1024 }
1025
1026 struct ureg_emit_insn_result
1027 ureg_emit_insn(struct ureg_program *ureg,
1028 unsigned opcode,
1029 boolean saturate,
1030 boolean predicate,
1031 boolean pred_negate,
1032 unsigned pred_swizzle_x,
1033 unsigned pred_swizzle_y,
1034 unsigned pred_swizzle_z,
1035 unsigned pred_swizzle_w,
1036 unsigned num_dst,
1037 unsigned num_src )
1038 {
1039 union tgsi_any_token *out;
1040 uint count = predicate ? 2 : 1;
1041 struct ureg_emit_insn_result result;
1042
1043 validate( opcode, num_dst, num_src );
1044
1045 out = get_tokens( ureg, DOMAIN_INSN, count );
1046 out[0].insn = tgsi_default_instruction();
1047 out[0].insn.Opcode = opcode;
1048 out[0].insn.Saturate = saturate;
1049 out[0].insn.NumDstRegs = num_dst;
1050 out[0].insn.NumSrcRegs = num_src;
1051
1052 result.insn_token = ureg->domain[DOMAIN_INSN].count - count;
1053 result.extended_token = result.insn_token;
1054
1055 if (predicate) {
1056 out[0].insn.Predicate = 1;
1057 out[1].insn_predicate = tgsi_default_instruction_predicate();
1058 out[1].insn_predicate.Negate = pred_negate;
1059 out[1].insn_predicate.SwizzleX = pred_swizzle_x;
1060 out[1].insn_predicate.SwizzleY = pred_swizzle_y;
1061 out[1].insn_predicate.SwizzleZ = pred_swizzle_z;
1062 out[1].insn_predicate.SwizzleW = pred_swizzle_w;
1063 }
1064
1065 ureg->nr_instructions++;
1066
1067 return result;
1068 }
1069
1070
1071 void
1072 ureg_emit_label(struct ureg_program *ureg,
1073 unsigned extended_token,
1074 unsigned *label_token )
1075 {
1076 union tgsi_any_token *out, *insn;
1077
1078 if(!label_token)
1079 return;
1080
1081 out = get_tokens( ureg, DOMAIN_INSN, 1 );
1082 out[0].value = 0;
1083
1084 insn = retrieve_token( ureg, DOMAIN_INSN, extended_token );
1085 insn->insn.Label = 1;
1086
1087 *label_token = ureg->domain[DOMAIN_INSN].count - 1;
1088 }
1089
1090 /* Will return a number which can be used in a label to point to the
1091 * next instruction to be emitted.
1092 */
1093 unsigned
1094 ureg_get_instruction_number( struct ureg_program *ureg )
1095 {
1096 return ureg->nr_instructions;
1097 }
1098
1099 /* Patch a given label (expressed as a token number) to point to a
1100 * given instruction (expressed as an instruction number).
1101 */
1102 void
1103 ureg_fixup_label(struct ureg_program *ureg,
1104 unsigned label_token,
1105 unsigned instruction_number )
1106 {
1107 union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, label_token );
1108
1109 out->insn_label.Label = instruction_number;
1110 }
1111
1112
1113 void
1114 ureg_emit_texture(struct ureg_program *ureg,
1115 unsigned extended_token,
1116 unsigned target, unsigned num_offsets)
1117 {
1118 union tgsi_any_token *out, *insn;
1119
1120 out = get_tokens( ureg, DOMAIN_INSN, 1 );
1121 insn = retrieve_token( ureg, DOMAIN_INSN, extended_token );
1122
1123 insn->insn.Texture = 1;
1124
1125 out[0].value = 0;
1126 out[0].insn_texture.Texture = target;
1127 out[0].insn_texture.NumOffsets = num_offsets;
1128 }
1129
1130 void
1131 ureg_emit_texture_offset(struct ureg_program *ureg,
1132 const struct tgsi_texture_offset *offset)
1133 {
1134 union tgsi_any_token *out;
1135
1136 out = get_tokens( ureg, DOMAIN_INSN, 1);
1137
1138 out[0].value = 0;
1139 out[0].insn_texture_offset = *offset;
1140
1141 }
1142
1143
1144 void
1145 ureg_fixup_insn_size(struct ureg_program *ureg,
1146 unsigned insn )
1147 {
1148 union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, insn );
1149
1150 assert(out->insn.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
1151 out->insn.NrTokens = ureg->domain[DOMAIN_INSN].count - insn - 1;
1152 }
1153
1154
1155 void
1156 ureg_insn(struct ureg_program *ureg,
1157 unsigned opcode,
1158 const struct ureg_dst *dst,
1159 unsigned nr_dst,
1160 const struct ureg_src *src,
1161 unsigned nr_src )
1162 {
1163 struct ureg_emit_insn_result insn;
1164 unsigned i;
1165 boolean saturate;
1166 boolean predicate;
1167 boolean negate = FALSE;
1168 unsigned swizzle[4] = { 0 };
1169
1170 if (nr_dst && ureg_dst_is_empty(dst[0])) {
1171 return;
1172 }
1173
1174 saturate = nr_dst ? dst[0].Saturate : FALSE;
1175 predicate = nr_dst ? dst[0].Predicate : FALSE;
1176 if (predicate) {
1177 negate = dst[0].PredNegate;
1178 swizzle[0] = dst[0].PredSwizzleX;
1179 swizzle[1] = dst[0].PredSwizzleY;
1180 swizzle[2] = dst[0].PredSwizzleZ;
1181 swizzle[3] = dst[0].PredSwizzleW;
1182 }
1183
1184 insn = ureg_emit_insn(ureg,
1185 opcode,
1186 saturate,
1187 predicate,
1188 negate,
1189 swizzle[0],
1190 swizzle[1],
1191 swizzle[2],
1192 swizzle[3],
1193 nr_dst,
1194 nr_src);
1195
1196 for (i = 0; i < nr_dst; i++)
1197 ureg_emit_dst( ureg, dst[i] );
1198
1199 for (i = 0; i < nr_src; i++)
1200 ureg_emit_src( ureg, src[i] );
1201
1202 ureg_fixup_insn_size( ureg, insn.insn_token );
1203 }
1204
1205 void
1206 ureg_tex_insn(struct ureg_program *ureg,
1207 unsigned opcode,
1208 const struct ureg_dst *dst,
1209 unsigned nr_dst,
1210 unsigned target,
1211 const struct tgsi_texture_offset *texoffsets,
1212 unsigned nr_offset,
1213 const struct ureg_src *src,
1214 unsigned nr_src )
1215 {
1216 struct ureg_emit_insn_result insn;
1217 unsigned i;
1218 boolean saturate;
1219 boolean predicate;
1220 boolean negate = FALSE;
1221 unsigned swizzle[4] = { 0 };
1222
1223 if (nr_dst && ureg_dst_is_empty(dst[0])) {
1224 return;
1225 }
1226
1227 saturate = nr_dst ? dst[0].Saturate : FALSE;
1228 predicate = nr_dst ? dst[0].Predicate : FALSE;
1229 if (predicate) {
1230 negate = dst[0].PredNegate;
1231 swizzle[0] = dst[0].PredSwizzleX;
1232 swizzle[1] = dst[0].PredSwizzleY;
1233 swizzle[2] = dst[0].PredSwizzleZ;
1234 swizzle[3] = dst[0].PredSwizzleW;
1235 }
1236
1237 insn = ureg_emit_insn(ureg,
1238 opcode,
1239 saturate,
1240 predicate,
1241 negate,
1242 swizzle[0],
1243 swizzle[1],
1244 swizzle[2],
1245 swizzle[3],
1246 nr_dst,
1247 nr_src);
1248
1249 ureg_emit_texture( ureg, insn.extended_token, target, nr_offset );
1250
1251 for (i = 0; i < nr_offset; i++)
1252 ureg_emit_texture_offset( ureg, &texoffsets[i]);
1253
1254 for (i = 0; i < nr_dst; i++)
1255 ureg_emit_dst( ureg, dst[i] );
1256
1257 for (i = 0; i < nr_src; i++)
1258 ureg_emit_src( ureg, src[i] );
1259
1260 ureg_fixup_insn_size( ureg, insn.insn_token );
1261 }
1262
1263
1264 void
1265 ureg_label_insn(struct ureg_program *ureg,
1266 unsigned opcode,
1267 const struct ureg_src *src,
1268 unsigned nr_src,
1269 unsigned *label_token )
1270 {
1271 struct ureg_emit_insn_result insn;
1272 unsigned i;
1273
1274 insn = ureg_emit_insn(ureg,
1275 opcode,
1276 FALSE,
1277 FALSE,
1278 FALSE,
1279 TGSI_SWIZZLE_X,
1280 TGSI_SWIZZLE_Y,
1281 TGSI_SWIZZLE_Z,
1282 TGSI_SWIZZLE_W,
1283 0,
1284 nr_src);
1285
1286 ureg_emit_label( ureg, insn.extended_token, label_token );
1287
1288 for (i = 0; i < nr_src; i++)
1289 ureg_emit_src( ureg, src[i] );
1290
1291 ureg_fixup_insn_size( ureg, insn.insn_token );
1292 }
1293
1294
1295 static void
1296 emit_decl_semantic(struct ureg_program *ureg,
1297 unsigned file,
1298 unsigned first,
1299 unsigned last,
1300 unsigned semantic_name,
1301 unsigned semantic_index,
1302 unsigned usage_mask,
1303 unsigned array_id)
1304 {
1305 union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, array_id ? 4 : 3);
1306
1307 out[0].value = 0;
1308 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
1309 out[0].decl.NrTokens = 3;
1310 out[0].decl.File = file;
1311 out[0].decl.UsageMask = usage_mask;
1312 out[0].decl.Semantic = 1;
1313 out[0].decl.Array = array_id != 0;
1314
1315 out[1].value = 0;
1316 out[1].decl_range.First = first;
1317 out[1].decl_range.Last = last;
1318
1319 out[2].value = 0;
1320 out[2].decl_semantic.Name = semantic_name;
1321 out[2].decl_semantic.Index = semantic_index;
1322
1323 if (array_id) {
1324 out[3].value = 0;
1325 out[3].array.ArrayID = array_id;
1326 }
1327 }
1328
1329
1330 static void
1331 emit_decl_fs(struct ureg_program *ureg,
1332 unsigned file,
1333 unsigned first,
1334 unsigned last,
1335 unsigned semantic_name,
1336 unsigned semantic_index,
1337 unsigned interpolate,
1338 unsigned cylindrical_wrap,
1339 unsigned interpolate_location,
1340 unsigned array_id)
1341 {
1342 union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL,
1343 array_id ? 5 : 4);
1344
1345 out[0].value = 0;
1346 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
1347 out[0].decl.NrTokens = 4;
1348 out[0].decl.File = file;
1349 out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; /* FIXME! */
1350 out[0].decl.Interpolate = 1;
1351 out[0].decl.Semantic = 1;
1352 out[0].decl.Array = array_id != 0;
1353
1354 out[1].value = 0;
1355 out[1].decl_range.First = first;
1356 out[1].decl_range.Last = last;
1357
1358 out[2].value = 0;
1359 out[2].decl_interp.Interpolate = interpolate;
1360 out[2].decl_interp.CylindricalWrap = cylindrical_wrap;
1361 out[2].decl_interp.Location = interpolate_location;
1362
1363 out[3].value = 0;
1364 out[3].decl_semantic.Name = semantic_name;
1365 out[3].decl_semantic.Index = semantic_index;
1366
1367 if (array_id) {
1368 out[4].value = 0;
1369 out[4].array.ArrayID = array_id;
1370 }
1371 }
1372
1373 static void
1374 emit_decl_temps( struct ureg_program *ureg,
1375 unsigned first, unsigned last,
1376 boolean local,
1377 unsigned arrayid )
1378 {
1379 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL,
1380 arrayid ? 3 : 2 );
1381
1382 out[0].value = 0;
1383 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
1384 out[0].decl.NrTokens = 2;
1385 out[0].decl.File = TGSI_FILE_TEMPORARY;
1386 out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
1387 out[0].decl.Local = local;
1388
1389 out[1].value = 0;
1390 out[1].decl_range.First = first;
1391 out[1].decl_range.Last = last;
1392
1393 if (arrayid) {
1394 out[0].decl.Array = 1;
1395 out[2].value = 0;
1396 out[2].array.ArrayID = arrayid;
1397 }
1398 }
1399
1400 static void emit_decl_range( struct ureg_program *ureg,
1401 unsigned file,
1402 unsigned first,
1403 unsigned count )
1404 {
1405 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 );
1406
1407 out[0].value = 0;
1408 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
1409 out[0].decl.NrTokens = 2;
1410 out[0].decl.File = file;
1411 out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
1412 out[0].decl.Semantic = 0;
1413
1414 out[1].value = 0;
1415 out[1].decl_range.First = first;
1416 out[1].decl_range.Last = first + count - 1;
1417 }
1418
1419 static void
1420 emit_decl_range2D(struct ureg_program *ureg,
1421 unsigned file,
1422 unsigned first,
1423 unsigned last,
1424 unsigned index2D)
1425 {
1426 union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3);
1427
1428 out[0].value = 0;
1429 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
1430 out[0].decl.NrTokens = 3;
1431 out[0].decl.File = file;
1432 out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
1433 out[0].decl.Dimension = 1;
1434
1435 out[1].value = 0;
1436 out[1].decl_range.First = first;
1437 out[1].decl_range.Last = last;
1438
1439 out[2].value = 0;
1440 out[2].decl_dim.Index2D = index2D;
1441 }
1442
1443 static void
1444 emit_decl_sampler_view(struct ureg_program *ureg,
1445 unsigned index,
1446 unsigned target,
1447 unsigned return_type_x,
1448 unsigned return_type_y,
1449 unsigned return_type_z,
1450 unsigned return_type_w )
1451 {
1452 union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3);
1453
1454 out[0].value = 0;
1455 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
1456 out[0].decl.NrTokens = 3;
1457 out[0].decl.File = TGSI_FILE_SAMPLER_VIEW;
1458 out[0].decl.UsageMask = 0xf;
1459
1460 out[1].value = 0;
1461 out[1].decl_range.First = index;
1462 out[1].decl_range.Last = index;
1463
1464 out[2].value = 0;
1465 out[2].decl_sampler_view.Resource = target;
1466 out[2].decl_sampler_view.ReturnTypeX = return_type_x;
1467 out[2].decl_sampler_view.ReturnTypeY = return_type_y;
1468 out[2].decl_sampler_view.ReturnTypeZ = return_type_z;
1469 out[2].decl_sampler_view.ReturnTypeW = return_type_w;
1470 }
1471
1472 static void
1473 emit_immediate( struct ureg_program *ureg,
1474 const unsigned *v,
1475 unsigned type )
1476 {
1477 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 5 );
1478
1479 out[0].value = 0;
1480 out[0].imm.Type = TGSI_TOKEN_TYPE_IMMEDIATE;
1481 out[0].imm.NrTokens = 5;
1482 out[0].imm.DataType = type;
1483 out[0].imm.Padding = 0;
1484
1485 out[1].imm_data.Uint = v[0];
1486 out[2].imm_data.Uint = v[1];
1487 out[3].imm_data.Uint = v[2];
1488 out[4].imm_data.Uint = v[3];
1489 }
1490
1491 static void
1492 emit_property(struct ureg_program *ureg,
1493 unsigned name,
1494 unsigned data)
1495 {
1496 union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 2);
1497
1498 out[0].value = 0;
1499 out[0].prop.Type = TGSI_TOKEN_TYPE_PROPERTY;
1500 out[0].prop.NrTokens = 2;
1501 out[0].prop.PropertyName = name;
1502
1503 out[1].prop_data.Data = data;
1504 }
1505
1506
1507 static void emit_decls( struct ureg_program *ureg )
1508 {
1509 unsigned i,j;
1510
1511 for (i = 0; i < Elements(ureg->properties); i++)
1512 if (ureg->properties[i] != ~0)
1513 emit_property(ureg, i, ureg->properties[i]);
1514
1515 if (ureg->processor == TGSI_PROCESSOR_VERTEX) {
1516 for (i = 0; i < UREG_MAX_INPUT; i++) {
1517 if (ureg->vs_inputs[i/32] & (1 << (i%32))) {
1518 emit_decl_range( ureg, TGSI_FILE_INPUT, i, 1 );
1519 }
1520 }
1521 } else if (ureg->processor == TGSI_PROCESSOR_FRAGMENT) {
1522 if (ureg->supports_any_inout_decl_range) {
1523 for (i = 0; i < ureg->nr_inputs; i++) {
1524 emit_decl_fs(ureg,
1525 TGSI_FILE_INPUT,
1526 ureg->input[i].first,
1527 ureg->input[i].last,
1528 ureg->input[i].semantic_name,
1529 ureg->input[i].semantic_index,
1530 ureg->input[i].interp,
1531 ureg->input[i].cylindrical_wrap,
1532 ureg->input[i].interp_location,
1533 ureg->input[i].array_id);
1534 }
1535 }
1536 else {
1537 for (i = 0; i < ureg->nr_inputs; i++) {
1538 for (j = ureg->input[i].first; j <= ureg->input[i].last; j++) {
1539 emit_decl_fs(ureg,
1540 TGSI_FILE_INPUT,
1541 j, j,
1542 ureg->input[i].semantic_name,
1543 ureg->input[i].semantic_index +
1544 (j - ureg->input[i].first),
1545 ureg->input[i].interp,
1546 ureg->input[i].cylindrical_wrap,
1547 ureg->input[i].interp_location, 0);
1548 }
1549 }
1550 }
1551 } else {
1552 if (ureg->supports_any_inout_decl_range) {
1553 for (i = 0; i < ureg->nr_inputs; i++) {
1554 emit_decl_semantic(ureg,
1555 TGSI_FILE_INPUT,
1556 ureg->input[i].first,
1557 ureg->input[i].last,
1558 ureg->input[i].semantic_name,
1559 ureg->input[i].semantic_index,
1560 TGSI_WRITEMASK_XYZW,
1561 ureg->input[i].array_id);
1562 }
1563 }
1564 else {
1565 for (i = 0; i < ureg->nr_inputs; i++) {
1566 for (j = ureg->input[i].first; j <= ureg->input[i].last; j++) {
1567 emit_decl_semantic(ureg,
1568 TGSI_FILE_INPUT,
1569 j, j,
1570 ureg->input[i].semantic_name,
1571 ureg->input[i].semantic_index +
1572 (j - ureg->input[i].first),
1573 TGSI_WRITEMASK_XYZW, 0);
1574 }
1575 }
1576 }
1577 }
1578
1579 for (i = 0; i < ureg->nr_system_values; i++) {
1580 emit_decl_semantic(ureg,
1581 TGSI_FILE_SYSTEM_VALUE,
1582 ureg->system_value[i].index,
1583 ureg->system_value[i].index,
1584 ureg->system_value[i].semantic_name,
1585 ureg->system_value[i].semantic_index,
1586 TGSI_WRITEMASK_XYZW, 0);
1587 }
1588
1589 if (ureg->supports_any_inout_decl_range) {
1590 for (i = 0; i < ureg->nr_outputs; i++) {
1591 emit_decl_semantic(ureg,
1592 TGSI_FILE_OUTPUT,
1593 ureg->output[i].first,
1594 ureg->output[i].last,
1595 ureg->output[i].semantic_name,
1596 ureg->output[i].semantic_index,
1597 ureg->output[i].usage_mask,
1598 ureg->output[i].array_id);
1599 }
1600 }
1601 else {
1602 for (i = 0; i < ureg->nr_outputs; i++) {
1603 for (j = ureg->output[i].first; j <= ureg->output[i].last; j++) {
1604 emit_decl_semantic(ureg,
1605 TGSI_FILE_OUTPUT,
1606 j, j,
1607 ureg->output[i].semantic_name,
1608 ureg->output[i].semantic_index +
1609 (j - ureg->output[i].first),
1610 ureg->output[i].usage_mask, 0);
1611 }
1612 }
1613 }
1614
1615 for (i = 0; i < ureg->nr_samplers; i++) {
1616 emit_decl_range( ureg,
1617 TGSI_FILE_SAMPLER,
1618 ureg->sampler[i].Index, 1 );
1619 }
1620
1621 for (i = 0; i < ureg->nr_sampler_views; i++) {
1622 emit_decl_sampler_view(ureg,
1623 ureg->sampler_view[i].index,
1624 ureg->sampler_view[i].target,
1625 ureg->sampler_view[i].return_type_x,
1626 ureg->sampler_view[i].return_type_y,
1627 ureg->sampler_view[i].return_type_z,
1628 ureg->sampler_view[i].return_type_w);
1629 }
1630
1631 if (ureg->const_decls.nr_constant_ranges) {
1632 for (i = 0; i < ureg->const_decls.nr_constant_ranges; i++) {
1633 emit_decl_range(ureg,
1634 TGSI_FILE_CONSTANT,
1635 ureg->const_decls.constant_range[i].first,
1636 ureg->const_decls.constant_range[i].last - ureg->const_decls.constant_range[i].first + 1);
1637 }
1638 }
1639
1640 for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
1641 struct const_decl *decl = &ureg->const_decls2D[i];
1642
1643 if (decl->nr_constant_ranges) {
1644 uint j;
1645
1646 for (j = 0; j < decl->nr_constant_ranges; j++) {
1647 emit_decl_range2D(ureg,
1648 TGSI_FILE_CONSTANT,
1649 decl->constant_range[j].first,
1650 decl->constant_range[j].last,
1651 i);
1652 }
1653 }
1654 }
1655
1656 if (ureg->nr_temps) {
1657 unsigned array = 0;
1658 for (i = 0; i < ureg->nr_temps;) {
1659 boolean local = util_bitmask_get(ureg->local_temps, i);
1660 unsigned first = i;
1661 i = util_bitmask_get_next_index(ureg->decl_temps, i + 1);
1662 if (i == UTIL_BITMASK_INVALID_INDEX)
1663 i = ureg->nr_temps;
1664
1665 if (array < ureg->nr_array_temps && ureg->array_temps[array] == first)
1666 emit_decl_temps( ureg, first, i - 1, local, ++array );
1667 else
1668 emit_decl_temps( ureg, first, i - 1, local, 0 );
1669 }
1670 }
1671
1672 if (ureg->nr_addrs) {
1673 emit_decl_range( ureg,
1674 TGSI_FILE_ADDRESS,
1675 0, ureg->nr_addrs );
1676 }
1677
1678 if (ureg->nr_preds) {
1679 emit_decl_range(ureg,
1680 TGSI_FILE_PREDICATE,
1681 0,
1682 ureg->nr_preds);
1683 }
1684
1685 for (i = 0; i < ureg->nr_immediates; i++) {
1686 emit_immediate( ureg,
1687 ureg->immediate[i].value.u,
1688 ureg->immediate[i].type );
1689 }
1690 }
1691
1692 /* Append the instruction tokens onto the declarations to build a
1693 * contiguous stream suitable to send to the driver.
1694 */
1695 static void copy_instructions( struct ureg_program *ureg )
1696 {
1697 unsigned nr_tokens = ureg->domain[DOMAIN_INSN].count;
1698 union tgsi_any_token *out = get_tokens( ureg,
1699 DOMAIN_DECL,
1700 nr_tokens );
1701
1702 memcpy(out,
1703 ureg->domain[DOMAIN_INSN].tokens,
1704 nr_tokens * sizeof out[0] );
1705 }
1706
1707
1708 static void
1709 fixup_header_size(struct ureg_program *ureg)
1710 {
1711 union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_DECL, 0 );
1712
1713 out->header.BodySize = ureg->domain[DOMAIN_DECL].count - 2;
1714 }
1715
1716
1717 static void
1718 emit_header( struct ureg_program *ureg )
1719 {
1720 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 );
1721
1722 out[0].header.HeaderSize = 2;
1723 out[0].header.BodySize = 0;
1724
1725 out[1].processor.Processor = ureg->processor;
1726 out[1].processor.Padding = 0;
1727 }
1728
1729
1730 const struct tgsi_token *ureg_finalize( struct ureg_program *ureg )
1731 {
1732 const struct tgsi_token *tokens;
1733
1734 emit_header( ureg );
1735 emit_decls( ureg );
1736 copy_instructions( ureg );
1737 fixup_header_size( ureg );
1738
1739 if (ureg->domain[0].tokens == error_tokens ||
1740 ureg->domain[1].tokens == error_tokens) {
1741 debug_printf("%s: error in generated shader\n", __FUNCTION__);
1742 assert(0);
1743 return NULL;
1744 }
1745
1746 tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token;
1747
1748 if (0) {
1749 debug_printf("%s: emitted shader %d tokens:\n", __FUNCTION__,
1750 ureg->domain[DOMAIN_DECL].count);
1751 tgsi_dump( tokens, 0 );
1752 }
1753
1754 #if DEBUG
1755 if (tokens && !tgsi_sanity_check(tokens)) {
1756 debug_printf("tgsi_ureg.c, sanity check failed on generated tokens:\n");
1757 tgsi_dump(tokens, 0);
1758 assert(0);
1759 }
1760 #endif
1761
1762
1763 return tokens;
1764 }
1765
1766
1767 void *ureg_create_shader( struct ureg_program *ureg,
1768 struct pipe_context *pipe,
1769 const struct pipe_stream_output_info *so )
1770 {
1771 struct pipe_shader_state state;
1772
1773 state.tokens = ureg_finalize(ureg);
1774 if(!state.tokens)
1775 return NULL;
1776
1777 if (so)
1778 state.stream_output = *so;
1779 else
1780 memset(&state.stream_output, 0, sizeof(state.stream_output));
1781
1782 switch (ureg->processor) {
1783 case TGSI_PROCESSOR_VERTEX:
1784 return pipe->create_vs_state(pipe, &state);
1785 case TGSI_PROCESSOR_TESS_CTRL:
1786 return pipe->create_tcs_state(pipe, &state);
1787 case TGSI_PROCESSOR_TESS_EVAL:
1788 return pipe->create_tes_state(pipe, &state);
1789 case TGSI_PROCESSOR_GEOMETRY:
1790 return pipe->create_gs_state(pipe, &state);
1791 case TGSI_PROCESSOR_FRAGMENT:
1792 return pipe->create_fs_state(pipe, &state);
1793 default:
1794 return NULL;
1795 }
1796 }
1797
1798
1799 const struct tgsi_token *ureg_get_tokens( struct ureg_program *ureg,
1800 unsigned *nr_tokens )
1801 {
1802 const struct tgsi_token *tokens;
1803
1804 ureg_finalize(ureg);
1805
1806 tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token;
1807
1808 if (nr_tokens)
1809 *nr_tokens = ureg->domain[DOMAIN_DECL].size;
1810
1811 ureg->domain[DOMAIN_DECL].tokens = 0;
1812 ureg->domain[DOMAIN_DECL].size = 0;
1813 ureg->domain[DOMAIN_DECL].order = 0;
1814 ureg->domain[DOMAIN_DECL].count = 0;
1815
1816 return tokens;
1817 }
1818
1819
1820 void ureg_free_tokens( const struct tgsi_token *tokens )
1821 {
1822 FREE((struct tgsi_token *)tokens);
1823 }
1824
1825
1826 static INLINE unsigned
1827 pipe_shader_from_tgsi_processor(unsigned processor)
1828 {
1829 switch (processor) {
1830 case TGSI_PROCESSOR_VERTEX:
1831 return PIPE_SHADER_VERTEX;
1832 case TGSI_PROCESSOR_TESS_CTRL:
1833 return PIPE_SHADER_TESS_CTRL;
1834 case TGSI_PROCESSOR_TESS_EVAL:
1835 return PIPE_SHADER_TESS_EVAL;
1836 case TGSI_PROCESSOR_GEOMETRY:
1837 return PIPE_SHADER_GEOMETRY;
1838 case TGSI_PROCESSOR_FRAGMENT:
1839 return PIPE_SHADER_FRAGMENT;
1840 case TGSI_PROCESSOR_COMPUTE:
1841 return PIPE_SHADER_COMPUTE;
1842 default:
1843 assert(0);
1844 return PIPE_SHADER_VERTEX;
1845 }
1846 }
1847
1848
1849 struct ureg_program *
1850 ureg_create(unsigned processor)
1851 {
1852 return ureg_create_with_screen(processor, NULL);
1853 }
1854
1855
1856 struct ureg_program *
1857 ureg_create_with_screen(unsigned processor, struct pipe_screen *screen)
1858 {
1859 int i;
1860 struct ureg_program *ureg = CALLOC_STRUCT( ureg_program );
1861 if (ureg == NULL)
1862 goto no_ureg;
1863
1864 ureg->processor = processor;
1865 ureg->supports_any_inout_decl_range =
1866 screen &&
1867 screen->get_shader_param(screen,
1868 pipe_shader_from_tgsi_processor(processor),
1869 PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE) != 0;
1870
1871 for (i = 0; i < Elements(ureg->properties); i++)
1872 ureg->properties[i] = ~0;
1873
1874 ureg->free_temps = util_bitmask_create();
1875 if (ureg->free_temps == NULL)
1876 goto no_free_temps;
1877
1878 ureg->local_temps = util_bitmask_create();
1879 if (ureg->local_temps == NULL)
1880 goto no_local_temps;
1881
1882 ureg->decl_temps = util_bitmask_create();
1883 if (ureg->decl_temps == NULL)
1884 goto no_decl_temps;
1885
1886 return ureg;
1887
1888 no_decl_temps:
1889 util_bitmask_destroy(ureg->local_temps);
1890 no_local_temps:
1891 util_bitmask_destroy(ureg->free_temps);
1892 no_free_temps:
1893 FREE(ureg);
1894 no_ureg:
1895 return NULL;
1896 }
1897
1898
1899 unsigned
1900 ureg_get_nr_outputs( const struct ureg_program *ureg )
1901 {
1902 if (!ureg)
1903 return 0;
1904 return ureg->nr_outputs;
1905 }
1906
1907
1908 void ureg_destroy( struct ureg_program *ureg )
1909 {
1910 unsigned i;
1911
1912 for (i = 0; i < Elements(ureg->domain); i++) {
1913 if (ureg->domain[i].tokens &&
1914 ureg->domain[i].tokens != error_tokens)
1915 FREE(ureg->domain[i].tokens);
1916 }
1917
1918 util_bitmask_destroy(ureg->free_temps);
1919 util_bitmask_destroy(ureg->local_temps);
1920 util_bitmask_destroy(ureg->decl_temps);
1921
1922 FREE(ureg);
1923 }