Merge remote branch 'origin/master' into lp-binning
[mesa.git] / src / gallium / auxiliary / tgsi / tgsi_ureg.c
1 /**************************************************************************
2 *
3 * Copyright 2009 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_context.h"
30 #include "pipe/p_state.h"
31 #include "tgsi/tgsi_ureg.h"
32 #include "tgsi/tgsi_build.h"
33 #include "tgsi/tgsi_info.h"
34 #include "tgsi/tgsi_dump.h"
35 #include "tgsi/tgsi_sanity.h"
36 #include "util/u_memory.h"
37 #include "util/u_math.h"
38
39 union tgsi_any_token {
40 struct tgsi_header header;
41 struct tgsi_processor processor;
42 struct tgsi_token token;
43 struct tgsi_property prop;
44 struct tgsi_property_data prop_data;
45 struct tgsi_declaration decl;
46 struct tgsi_declaration_range decl_range;
47 struct tgsi_declaration_semantic decl_semantic;
48 struct tgsi_immediate imm;
49 union tgsi_immediate_data imm_data;
50 struct tgsi_instruction insn;
51 struct tgsi_instruction_predicate insn_predicate;
52 struct tgsi_instruction_label insn_label;
53 struct tgsi_instruction_texture insn_texture;
54 struct tgsi_src_register src;
55 struct tgsi_dimension dim;
56 struct tgsi_dst_register dst;
57 unsigned value;
58 };
59
60
61 struct ureg_tokens {
62 union tgsi_any_token *tokens;
63 unsigned size;
64 unsigned order;
65 unsigned count;
66 };
67
68 #define UREG_MAX_INPUT PIPE_MAX_ATTRIBS
69 #define UREG_MAX_SYSTEM_VALUE PIPE_MAX_ATTRIBS
70 #define UREG_MAX_OUTPUT PIPE_MAX_ATTRIBS
71 #define UREG_MAX_CONSTANT_RANGE 32
72 #define UREG_MAX_IMMEDIATE 32
73 #define UREG_MAX_TEMP 256
74 #define UREG_MAX_ADDR 2
75 #define UREG_MAX_LOOP 1
76 #define UREG_MAX_PRED 1
77
78 #define DOMAIN_DECL 0
79 #define DOMAIN_INSN 1
80
81 struct ureg_program
82 {
83 unsigned processor;
84 struct pipe_context *pipe;
85
86 struct {
87 unsigned semantic_name;
88 unsigned semantic_index;
89 unsigned interp;
90 } fs_input[UREG_MAX_INPUT];
91 unsigned nr_fs_inputs;
92
93 unsigned vs_inputs[UREG_MAX_INPUT/32];
94
95 struct {
96 unsigned index;
97 } gs_input[UREG_MAX_INPUT];
98 unsigned nr_gs_inputs;
99
100 struct {
101 unsigned index;
102 unsigned semantic_name;
103 unsigned semantic_index;
104 } system_value[UREG_MAX_SYSTEM_VALUE];
105 unsigned nr_system_values;
106
107 struct {
108 unsigned semantic_name;
109 unsigned semantic_index;
110 } output[UREG_MAX_OUTPUT];
111 unsigned nr_outputs;
112
113 struct {
114 union {
115 float f[4];
116 unsigned u[4];
117 int i[4];
118 } value;
119 unsigned nr;
120 unsigned type;
121 } immediate[UREG_MAX_IMMEDIATE];
122 unsigned nr_immediates;
123
124 struct ureg_src sampler[PIPE_MAX_SAMPLERS];
125 unsigned nr_samplers;
126
127 unsigned temps_active[UREG_MAX_TEMP / 32];
128 unsigned nr_temps;
129
130 struct {
131 unsigned first;
132 unsigned last;
133 } constant_range[UREG_MAX_CONSTANT_RANGE];
134 unsigned nr_constant_ranges;
135
136 unsigned property_gs_input_prim;
137
138 unsigned nr_addrs;
139 unsigned nr_preds;
140 unsigned nr_loops;
141 unsigned nr_instructions;
142
143 struct ureg_tokens domain[2];
144 };
145
146 static union tgsi_any_token error_tokens[32];
147
148 static void tokens_error( struct ureg_tokens *tokens )
149 {
150 if (tokens->tokens && tokens->tokens != error_tokens)
151 FREE(tokens->tokens);
152
153 tokens->tokens = error_tokens;
154 tokens->size = Elements(error_tokens);
155 tokens->count = 0;
156 }
157
158
159 static void tokens_expand( struct ureg_tokens *tokens,
160 unsigned count )
161 {
162 unsigned old_size = tokens->size * sizeof(unsigned);
163
164 if (tokens->tokens == error_tokens) {
165 return;
166 }
167
168 while (tokens->count + count > tokens->size) {
169 tokens->size = (1 << ++tokens->order);
170 }
171
172 tokens->tokens = REALLOC(tokens->tokens,
173 old_size,
174 tokens->size * sizeof(unsigned));
175 if (tokens->tokens == NULL) {
176 tokens_error(tokens);
177 }
178 }
179
180 static void set_bad( struct ureg_program *ureg )
181 {
182 tokens_error(&ureg->domain[0]);
183 }
184
185
186
187 static union tgsi_any_token *get_tokens( struct ureg_program *ureg,
188 unsigned domain,
189 unsigned count )
190 {
191 struct ureg_tokens *tokens = &ureg->domain[domain];
192 union tgsi_any_token *result;
193
194 if (tokens->count + count > tokens->size)
195 tokens_expand(tokens, count);
196
197 result = &tokens->tokens[tokens->count];
198 tokens->count += count;
199 return result;
200 }
201
202
203 static union tgsi_any_token *retrieve_token( struct ureg_program *ureg,
204 unsigned domain,
205 unsigned nr )
206 {
207 if (ureg->domain[domain].tokens == error_tokens)
208 return &error_tokens[0];
209
210 return &ureg->domain[domain].tokens[nr];
211 }
212
213
214
215 static INLINE struct ureg_dst
216 ureg_dst_register( unsigned file,
217 unsigned index )
218 {
219 struct ureg_dst dst;
220
221 dst.File = file;
222 dst.WriteMask = TGSI_WRITEMASK_XYZW;
223 dst.Indirect = 0;
224 dst.IndirectIndex = 0;
225 dst.IndirectSwizzle = 0;
226 dst.Saturate = 0;
227 dst.Predicate = 0;
228 dst.PredNegate = 0;
229 dst.PredSwizzleX = TGSI_SWIZZLE_X;
230 dst.PredSwizzleY = TGSI_SWIZZLE_Y;
231 dst.PredSwizzleZ = TGSI_SWIZZLE_Z;
232 dst.PredSwizzleW = TGSI_SWIZZLE_W;
233 dst.Index = index;
234
235 return dst;
236 }
237
238 static INLINE struct ureg_src
239 ureg_src_register( unsigned file,
240 unsigned index )
241 {
242 struct ureg_src src;
243
244 src.File = file;
245 src.SwizzleX = TGSI_SWIZZLE_X;
246 src.SwizzleY = TGSI_SWIZZLE_Y;
247 src.SwizzleZ = TGSI_SWIZZLE_Z;
248 src.SwizzleW = TGSI_SWIZZLE_W;
249 src.Indirect = 0;
250 src.IndirectIndex = 0;
251 src.IndirectSwizzle = 0;
252 src.Absolute = 0;
253 src.Index = index;
254 src.Negate = 0;
255 src.Dimension = 0;
256 src.DimensionIndex = 0;
257
258 return src;
259 }
260
261
262
263 void
264 ureg_property_gs_input_prim(struct ureg_program *ureg,
265 unsigned gs_input_prim)
266 {
267 ureg->property_gs_input_prim = gs_input_prim;
268 }
269
270
271
272 struct ureg_src
273 ureg_DECL_fs_input( struct ureg_program *ureg,
274 unsigned name,
275 unsigned index,
276 unsigned interp_mode )
277 {
278 unsigned i;
279
280 for (i = 0; i < ureg->nr_fs_inputs; i++) {
281 if (ureg->fs_input[i].semantic_name == name &&
282 ureg->fs_input[i].semantic_index == index)
283 goto out;
284 }
285
286 if (ureg->nr_fs_inputs < UREG_MAX_INPUT) {
287 ureg->fs_input[i].semantic_name = name;
288 ureg->fs_input[i].semantic_index = index;
289 ureg->fs_input[i].interp = interp_mode;
290 ureg->nr_fs_inputs++;
291 }
292 else {
293 set_bad( ureg );
294 }
295
296 out:
297 return ureg_src_register( TGSI_FILE_INPUT, i );
298 }
299
300
301 struct ureg_src
302 ureg_DECL_vs_input( struct ureg_program *ureg,
303 unsigned index )
304 {
305 assert(ureg->processor == TGSI_PROCESSOR_VERTEX);
306
307 ureg->vs_inputs[index/32] |= 1 << (index % 32);
308 return ureg_src_register( TGSI_FILE_INPUT, index );
309 }
310
311
312 struct ureg_src
313 ureg_DECL_gs_input(struct ureg_program *ureg,
314 unsigned index)
315 {
316 if (ureg->nr_gs_inputs < UREG_MAX_INPUT) {
317 ureg->gs_input[ureg->nr_gs_inputs].index = index;
318 ureg->nr_gs_inputs++;
319 } else {
320 set_bad(ureg);
321 }
322
323 /* XXX: Add suport for true 2D input registers. */
324 return ureg_src_register(TGSI_FILE_INPUT, index);
325 }
326
327
328 struct ureg_src
329 ureg_DECL_system_value(struct ureg_program *ureg,
330 unsigned index,
331 unsigned semantic_name,
332 unsigned semantic_index)
333 {
334 if (ureg->nr_system_values < UREG_MAX_SYSTEM_VALUE) {
335 ureg->system_value[ureg->nr_system_values].index = index;
336 ureg->system_value[ureg->nr_system_values].semantic_name = semantic_name;
337 ureg->system_value[ureg->nr_system_values].semantic_index = semantic_index;
338 ureg->nr_system_values++;
339 } else {
340 set_bad(ureg);
341 }
342
343 return ureg_src_register(TGSI_FILE_SYSTEM_VALUE, index);
344 }
345
346
347 struct ureg_dst
348 ureg_DECL_output( struct ureg_program *ureg,
349 unsigned name,
350 unsigned index )
351 {
352 unsigned i;
353
354 for (i = 0; i < ureg->nr_outputs; i++) {
355 if (ureg->output[i].semantic_name == name &&
356 ureg->output[i].semantic_index == index)
357 goto out;
358 }
359
360 if (ureg->nr_outputs < UREG_MAX_OUTPUT) {
361 ureg->output[i].semantic_name = name;
362 ureg->output[i].semantic_index = index;
363 ureg->nr_outputs++;
364 }
365 else {
366 set_bad( ureg );
367 }
368
369 out:
370 return ureg_dst_register( TGSI_FILE_OUTPUT, i );
371 }
372
373
374 /* Returns a new constant register. Keep track of which have been
375 * referred to so that we can emit decls later.
376 *
377 * There is nothing in this code to bind this constant to any tracked
378 * value or manage any constant_buffer contents -- that's the
379 * resposibility of the calling code.
380 */
381 struct ureg_src ureg_DECL_constant(struct ureg_program *ureg,
382 unsigned index )
383 {
384 unsigned minconst = index, maxconst = index;
385 unsigned i;
386
387 /* Inside existing range?
388 */
389 for (i = 0; i < ureg->nr_constant_ranges; i++) {
390 if (ureg->constant_range[i].first <= index &&
391 ureg->constant_range[i].last >= index)
392 goto out;
393 }
394
395 /* Extend existing range?
396 */
397 for (i = 0; i < ureg->nr_constant_ranges; i++) {
398 if (ureg->constant_range[i].last == index - 1) {
399 ureg->constant_range[i].last = index;
400 goto out;
401 }
402
403 if (ureg->constant_range[i].first == index + 1) {
404 ureg->constant_range[i].first = index;
405 goto out;
406 }
407
408 minconst = MIN2(minconst, ureg->constant_range[i].first);
409 maxconst = MAX2(maxconst, ureg->constant_range[i].last);
410 }
411
412 /* Create new range?
413 */
414 if (ureg->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) {
415 i = ureg->nr_constant_ranges++;
416 ureg->constant_range[i].first = index;
417 ureg->constant_range[i].last = index;
418 goto out;
419 }
420
421 /* Collapse all ranges down to one:
422 */
423 i = 0;
424 ureg->constant_range[0].first = minconst;
425 ureg->constant_range[0].last = maxconst;
426 ureg->nr_constant_ranges = 1;
427
428 out:
429 assert(i < ureg->nr_constant_ranges);
430 assert(ureg->constant_range[i].first <= index);
431 assert(ureg->constant_range[i].last >= index);
432 return ureg_src_register( TGSI_FILE_CONSTANT, index );
433 }
434
435
436 /* Allocate a new temporary. Temporaries greater than UREG_MAX_TEMP
437 * are legal, but will not be released.
438 */
439 struct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg )
440 {
441 unsigned i;
442
443 for (i = 0; i < UREG_MAX_TEMP; i += 32) {
444 int bit = ffs(~ureg->temps_active[i/32]);
445 if (bit != 0) {
446 i += bit - 1;
447 goto out;
448 }
449 }
450
451 /* No reusable temps, so allocate a new one:
452 */
453 i = ureg->nr_temps++;
454
455 out:
456 if (i < UREG_MAX_TEMP)
457 ureg->temps_active[i/32] |= 1 << (i % 32);
458
459 if (i >= ureg->nr_temps)
460 ureg->nr_temps = i + 1;
461
462 return ureg_dst_register( TGSI_FILE_TEMPORARY, i );
463 }
464
465
466 void ureg_release_temporary( struct ureg_program *ureg,
467 struct ureg_dst tmp )
468 {
469 if(tmp.File == TGSI_FILE_TEMPORARY)
470 if (tmp.Index < UREG_MAX_TEMP)
471 ureg->temps_active[tmp.Index/32] &= ~(1 << (tmp.Index % 32));
472 }
473
474
475 /* Allocate a new address register.
476 */
477 struct ureg_dst ureg_DECL_address( struct ureg_program *ureg )
478 {
479 if (ureg->nr_addrs < UREG_MAX_ADDR)
480 return ureg_dst_register( TGSI_FILE_ADDRESS, ureg->nr_addrs++ );
481
482 assert( 0 );
483 return ureg_dst_register( TGSI_FILE_ADDRESS, 0 );
484 }
485
486 /* Allocate a new loop register.
487 */
488 struct ureg_dst
489 ureg_DECL_loop(struct ureg_program *ureg)
490 {
491 if (ureg->nr_loops < UREG_MAX_LOOP) {
492 return ureg_dst_register(TGSI_FILE_LOOP, ureg->nr_loops++);
493 }
494
495 assert(0);
496 return ureg_dst_register(TGSI_FILE_LOOP, 0);
497 }
498
499 /* Allocate a new predicate register.
500 */
501 struct ureg_dst
502 ureg_DECL_predicate(struct ureg_program *ureg)
503 {
504 if (ureg->nr_preds < UREG_MAX_PRED) {
505 return ureg_dst_register(TGSI_FILE_PREDICATE, ureg->nr_preds++);
506 }
507
508 assert(0);
509 return ureg_dst_register(TGSI_FILE_PREDICATE, 0);
510 }
511
512 /* Allocate a new sampler.
513 */
514 struct ureg_src ureg_DECL_sampler( struct ureg_program *ureg,
515 unsigned nr )
516 {
517 unsigned i;
518
519 for (i = 0; i < ureg->nr_samplers; i++)
520 if (ureg->sampler[i].Index == nr)
521 return ureg->sampler[i];
522
523 if (i < PIPE_MAX_SAMPLERS) {
524 ureg->sampler[i] = ureg_src_register( TGSI_FILE_SAMPLER, nr );
525 ureg->nr_samplers++;
526 return ureg->sampler[i];
527 }
528
529 assert( 0 );
530 return ureg->sampler[0];
531 }
532
533
534 static int
535 match_or_expand_immediate( const unsigned *v,
536 unsigned nr,
537 unsigned *v2,
538 unsigned *pnr2,
539 unsigned *swizzle )
540 {
541 unsigned nr2 = *pnr2;
542 unsigned i, j;
543
544 *swizzle = 0;
545
546 for (i = 0; i < nr; i++) {
547 boolean found = FALSE;
548
549 for (j = 0; j < nr2 && !found; j++) {
550 if (v[i] == v2[j]) {
551 *swizzle |= j << (i * 2);
552 found = TRUE;
553 }
554 }
555
556 if (!found) {
557 if (nr2 >= 4) {
558 return FALSE;
559 }
560
561 v2[nr2] = v[i];
562 *swizzle |= nr2 << (i * 2);
563 nr2++;
564 }
565 }
566
567 /* Actually expand immediate only when fully succeeded.
568 */
569 *pnr2 = nr2;
570 return TRUE;
571 }
572
573
574 static struct ureg_src
575 decl_immediate( struct ureg_program *ureg,
576 const unsigned *v,
577 unsigned nr,
578 unsigned type )
579 {
580 unsigned i, j;
581 unsigned swizzle;
582
583 /* Could do a first pass where we examine all existing immediates
584 * without expanding.
585 */
586
587 for (i = 0; i < ureg->nr_immediates; i++) {
588 if (ureg->immediate[i].type != type) {
589 continue;
590 }
591 if (match_or_expand_immediate(v,
592 nr,
593 ureg->immediate[i].value.u,
594 &ureg->immediate[i].nr,
595 &swizzle)) {
596 goto out;
597 }
598 }
599
600 if (ureg->nr_immediates < UREG_MAX_IMMEDIATE) {
601 i = ureg->nr_immediates++;
602 ureg->immediate[i].type = type;
603 if (match_or_expand_immediate(v,
604 nr,
605 ureg->immediate[i].value.u,
606 &ureg->immediate[i].nr,
607 &swizzle)) {
608 goto out;
609 }
610 }
611
612 set_bad(ureg);
613
614 out:
615 /* Make sure that all referenced elements are from this immediate.
616 * Has the effect of making size-one immediates into scalars.
617 */
618 for (j = nr; j < 4; j++) {
619 swizzle |= (swizzle & 0x3) << (j * 2);
620 }
621
622 return ureg_swizzle(ureg_src_register(TGSI_FILE_IMMEDIATE, i),
623 (swizzle >> 0) & 0x3,
624 (swizzle >> 2) & 0x3,
625 (swizzle >> 4) & 0x3,
626 (swizzle >> 6) & 0x3);
627 }
628
629
630 struct ureg_src
631 ureg_DECL_immediate( struct ureg_program *ureg,
632 const float *v,
633 unsigned nr )
634 {
635 union {
636 float f[4];
637 unsigned u[4];
638 } fu;
639 unsigned int i;
640
641 for (i = 0; i < nr; i++) {
642 fu.f[i] = v[i];
643 }
644
645 return decl_immediate(ureg, fu.u, nr, TGSI_IMM_FLOAT32);
646 }
647
648
649 struct ureg_src
650 ureg_DECL_immediate_uint( struct ureg_program *ureg,
651 const unsigned *v,
652 unsigned nr )
653 {
654 return decl_immediate(ureg, v, nr, TGSI_IMM_UINT32);
655 }
656
657
658 struct ureg_src
659 ureg_DECL_immediate_int( struct ureg_program *ureg,
660 const int *v,
661 unsigned nr )
662 {
663 return decl_immediate(ureg, (const unsigned *)v, nr, TGSI_IMM_INT32);
664 }
665
666
667 void
668 ureg_emit_src( struct ureg_program *ureg,
669 struct ureg_src src )
670 {
671 unsigned size = 1 + (src.Indirect ? 1 : 0) + (src.Dimension ? 1 : 0);
672
673 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
674 unsigned n = 0;
675
676 assert(src.File != TGSI_FILE_NULL);
677 assert(src.File != TGSI_FILE_OUTPUT);
678 assert(src.File < TGSI_FILE_COUNT);
679
680 out[n].value = 0;
681 out[n].src.File = src.File;
682 out[n].src.SwizzleX = src.SwizzleX;
683 out[n].src.SwizzleY = src.SwizzleY;
684 out[n].src.SwizzleZ = src.SwizzleZ;
685 out[n].src.SwizzleW = src.SwizzleW;
686 out[n].src.Index = src.Index;
687 out[n].src.Negate = src.Negate;
688 out[0].src.Absolute = src.Absolute;
689 n++;
690
691 if (src.Indirect) {
692 out[0].src.Indirect = 1;
693 out[n].value = 0;
694 out[n].src.File = TGSI_FILE_ADDRESS;
695 out[n].src.SwizzleX = src.IndirectSwizzle;
696 out[n].src.SwizzleY = src.IndirectSwizzle;
697 out[n].src.SwizzleZ = src.IndirectSwizzle;
698 out[n].src.SwizzleW = src.IndirectSwizzle;
699 out[n].src.Index = src.IndirectIndex;
700 n++;
701 }
702
703 if (src.Dimension) {
704 out[0].src.Dimension = 1;
705 out[n].dim.Indirect = 0;
706 out[n].dim.Dimension = 0;
707 out[n].dim.Padding = 0;
708 out[n].dim.Index = src.DimensionIndex;
709 n++;
710 }
711
712 assert(n == size);
713 }
714
715
716 void
717 ureg_emit_dst( struct ureg_program *ureg,
718 struct ureg_dst dst )
719 {
720 unsigned size = (1 +
721 (dst.Indirect ? 1 : 0));
722
723 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
724 unsigned n = 0;
725
726 assert(dst.File != TGSI_FILE_NULL);
727 assert(dst.File != TGSI_FILE_CONSTANT);
728 assert(dst.File != TGSI_FILE_INPUT);
729 assert(dst.File != TGSI_FILE_SAMPLER);
730 assert(dst.File != TGSI_FILE_IMMEDIATE);
731 assert(dst.File < TGSI_FILE_COUNT);
732
733 out[n].value = 0;
734 out[n].dst.File = dst.File;
735 out[n].dst.WriteMask = dst.WriteMask;
736 out[n].dst.Indirect = dst.Indirect;
737 out[n].dst.Index = dst.Index;
738 n++;
739
740 if (dst.Indirect) {
741 out[n].value = 0;
742 out[n].src.File = TGSI_FILE_ADDRESS;
743 out[n].src.SwizzleX = dst.IndirectSwizzle;
744 out[n].src.SwizzleY = dst.IndirectSwizzle;
745 out[n].src.SwizzleZ = dst.IndirectSwizzle;
746 out[n].src.SwizzleW = dst.IndirectSwizzle;
747 out[n].src.Index = dst.IndirectIndex;
748 n++;
749 }
750
751 assert(n == size);
752 }
753
754
755 static void validate( unsigned opcode,
756 unsigned nr_dst,
757 unsigned nr_src )
758 {
759 #ifdef DEBUG
760 const struct tgsi_opcode_info *info = tgsi_get_opcode_info( opcode );
761 assert(info);
762 if(info) {
763 assert(nr_dst == info->num_dst);
764 assert(nr_src == info->num_src);
765 }
766 #endif
767 }
768
769 struct ureg_emit_insn_result
770 ureg_emit_insn(struct ureg_program *ureg,
771 unsigned opcode,
772 boolean saturate,
773 boolean predicate,
774 boolean pred_negate,
775 unsigned pred_swizzle_x,
776 unsigned pred_swizzle_y,
777 unsigned pred_swizzle_z,
778 unsigned pred_swizzle_w,
779 unsigned num_dst,
780 unsigned num_src )
781 {
782 union tgsi_any_token *out;
783 uint count = predicate ? 2 : 1;
784 struct ureg_emit_insn_result result;
785
786 validate( opcode, num_dst, num_src );
787
788 out = get_tokens( ureg, DOMAIN_INSN, count );
789 out[0].insn = tgsi_default_instruction();
790 out[0].insn.Opcode = opcode;
791 out[0].insn.Saturate = saturate;
792 out[0].insn.NumDstRegs = num_dst;
793 out[0].insn.NumSrcRegs = num_src;
794
795 result.insn_token = ureg->domain[DOMAIN_INSN].count - count;
796 result.extended_token = result.insn_token;
797
798 if (predicate) {
799 out[0].insn.Predicate = 1;
800 out[1].insn_predicate = tgsi_default_instruction_predicate();
801 out[1].insn_predicate.Negate = pred_negate;
802 out[1].insn_predicate.SwizzleX = pred_swizzle_x;
803 out[1].insn_predicate.SwizzleY = pred_swizzle_y;
804 out[1].insn_predicate.SwizzleZ = pred_swizzle_z;
805 out[1].insn_predicate.SwizzleW = pred_swizzle_w;
806 }
807
808 ureg->nr_instructions++;
809
810 return result;
811 }
812
813
814 void
815 ureg_emit_label(struct ureg_program *ureg,
816 unsigned extended_token,
817 unsigned *label_token )
818 {
819 union tgsi_any_token *out, *insn;
820
821 if(!label_token)
822 return;
823
824 out = get_tokens( ureg, DOMAIN_INSN, 1 );
825 out[0].value = 0;
826
827 insn = retrieve_token( ureg, DOMAIN_INSN, extended_token );
828 insn->insn.Label = 1;
829
830 *label_token = ureg->domain[DOMAIN_INSN].count - 1;
831 }
832
833 /* Will return a number which can be used in a label to point to the
834 * next instruction to be emitted.
835 */
836 unsigned
837 ureg_get_instruction_number( struct ureg_program *ureg )
838 {
839 return ureg->nr_instructions;
840 }
841
842 /* Patch a given label (expressed as a token number) to point to a
843 * given instruction (expressed as an instruction number).
844 */
845 void
846 ureg_fixup_label(struct ureg_program *ureg,
847 unsigned label_token,
848 unsigned instruction_number )
849 {
850 union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, label_token );
851
852 out->insn_label.Label = instruction_number;
853 }
854
855
856 void
857 ureg_emit_texture(struct ureg_program *ureg,
858 unsigned extended_token,
859 unsigned target )
860 {
861 union tgsi_any_token *out, *insn;
862
863 out = get_tokens( ureg, DOMAIN_INSN, 1 );
864 insn = retrieve_token( ureg, DOMAIN_INSN, extended_token );
865
866 insn->insn.Texture = 1;
867
868 out[0].value = 0;
869 out[0].insn_texture.Texture = target;
870 }
871
872
873 void
874 ureg_fixup_insn_size(struct ureg_program *ureg,
875 unsigned insn )
876 {
877 union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, insn );
878
879 assert(out->insn.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
880 out->insn.NrTokens = ureg->domain[DOMAIN_INSN].count - insn - 1;
881 }
882
883
884 void
885 ureg_insn(struct ureg_program *ureg,
886 unsigned opcode,
887 const struct ureg_dst *dst,
888 unsigned nr_dst,
889 const struct ureg_src *src,
890 unsigned nr_src )
891 {
892 struct ureg_emit_insn_result insn;
893 unsigned i;
894 boolean saturate;
895 boolean predicate;
896 boolean negate = FALSE;
897 unsigned swizzle[4] = { 0 };
898
899 saturate = nr_dst ? dst[0].Saturate : FALSE;
900 predicate = nr_dst ? dst[0].Predicate : FALSE;
901 if (predicate) {
902 negate = dst[0].PredNegate;
903 swizzle[0] = dst[0].PredSwizzleX;
904 swizzle[1] = dst[0].PredSwizzleY;
905 swizzle[2] = dst[0].PredSwizzleZ;
906 swizzle[3] = dst[0].PredSwizzleW;
907 }
908
909 insn = ureg_emit_insn(ureg,
910 opcode,
911 saturate,
912 predicate,
913 negate,
914 swizzle[0],
915 swizzle[1],
916 swizzle[2],
917 swizzle[3],
918 nr_dst,
919 nr_src);
920
921 for (i = 0; i < nr_dst; i++)
922 ureg_emit_dst( ureg, dst[i] );
923
924 for (i = 0; i < nr_src; i++)
925 ureg_emit_src( ureg, src[i] );
926
927 ureg_fixup_insn_size( ureg, insn.insn_token );
928 }
929
930 void
931 ureg_tex_insn(struct ureg_program *ureg,
932 unsigned opcode,
933 const struct ureg_dst *dst,
934 unsigned nr_dst,
935 unsigned target,
936 const struct ureg_src *src,
937 unsigned nr_src )
938 {
939 struct ureg_emit_insn_result insn;
940 unsigned i;
941 boolean saturate;
942 boolean predicate;
943 boolean negate = FALSE;
944 unsigned swizzle[4] = { 0 };
945
946 saturate = nr_dst ? dst[0].Saturate : FALSE;
947 predicate = nr_dst ? dst[0].Predicate : FALSE;
948 if (predicate) {
949 negate = dst[0].PredNegate;
950 swizzle[0] = dst[0].PredSwizzleX;
951 swizzle[1] = dst[0].PredSwizzleY;
952 swizzle[2] = dst[0].PredSwizzleZ;
953 swizzle[3] = dst[0].PredSwizzleW;
954 }
955
956 insn = ureg_emit_insn(ureg,
957 opcode,
958 saturate,
959 predicate,
960 negate,
961 swizzle[0],
962 swizzle[1],
963 swizzle[2],
964 swizzle[3],
965 nr_dst,
966 nr_src);
967
968 ureg_emit_texture( ureg, insn.extended_token, target );
969
970 for (i = 0; i < nr_dst; i++)
971 ureg_emit_dst( ureg, dst[i] );
972
973 for (i = 0; i < nr_src; i++)
974 ureg_emit_src( ureg, src[i] );
975
976 ureg_fixup_insn_size( ureg, insn.insn_token );
977 }
978
979
980 void
981 ureg_label_insn(struct ureg_program *ureg,
982 unsigned opcode,
983 const struct ureg_src *src,
984 unsigned nr_src,
985 unsigned *label_token )
986 {
987 struct ureg_emit_insn_result insn;
988 unsigned i;
989
990 insn = ureg_emit_insn(ureg,
991 opcode,
992 FALSE,
993 FALSE,
994 FALSE,
995 TGSI_SWIZZLE_X,
996 TGSI_SWIZZLE_Y,
997 TGSI_SWIZZLE_Z,
998 TGSI_SWIZZLE_W,
999 0,
1000 nr_src);
1001
1002 ureg_emit_label( ureg, insn.extended_token, label_token );
1003
1004 for (i = 0; i < nr_src; i++)
1005 ureg_emit_src( ureg, src[i] );
1006
1007 ureg_fixup_insn_size( ureg, insn.insn_token );
1008 }
1009
1010
1011
1012 static void emit_decl( struct ureg_program *ureg,
1013 unsigned file,
1014 unsigned index,
1015 unsigned semantic_name,
1016 unsigned semantic_index,
1017 unsigned interp )
1018 {
1019 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 3 );
1020
1021 out[0].value = 0;
1022 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
1023 out[0].decl.NrTokens = 3;
1024 out[0].decl.File = file;
1025 out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; /* FIXME! */
1026 out[0].decl.Interpolate = interp;
1027 out[0].decl.Semantic = 1;
1028
1029 out[1].value = 0;
1030 out[1].decl_range.First =
1031 out[1].decl_range.Last = index;
1032
1033 out[2].value = 0;
1034 out[2].decl_semantic.Name = semantic_name;
1035 out[2].decl_semantic.Index = semantic_index;
1036
1037 }
1038
1039
1040 static void emit_decl_range( struct ureg_program *ureg,
1041 unsigned file,
1042 unsigned first,
1043 unsigned count )
1044 {
1045 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 );
1046
1047 out[0].value = 0;
1048 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
1049 out[0].decl.NrTokens = 2;
1050 out[0].decl.File = file;
1051 out[0].decl.UsageMask = 0xf;
1052 out[0].decl.Interpolate = TGSI_INTERPOLATE_CONSTANT;
1053 out[0].decl.Semantic = 0;
1054
1055 out[1].value = 0;
1056 out[1].decl_range.First = first;
1057 out[1].decl_range.Last = first + count - 1;
1058 }
1059
1060 static void
1061 emit_immediate( struct ureg_program *ureg,
1062 const unsigned *v,
1063 unsigned type )
1064 {
1065 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 5 );
1066
1067 out[0].value = 0;
1068 out[0].imm.Type = TGSI_TOKEN_TYPE_IMMEDIATE;
1069 out[0].imm.NrTokens = 5;
1070 out[0].imm.DataType = type;
1071 out[0].imm.Padding = 0;
1072
1073 out[1].imm_data.Uint = v[0];
1074 out[2].imm_data.Uint = v[1];
1075 out[3].imm_data.Uint = v[2];
1076 out[4].imm_data.Uint = v[3];
1077 }
1078
1079 static void
1080 emit_property(struct ureg_program *ureg,
1081 unsigned name,
1082 unsigned data)
1083 {
1084 union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 2);
1085
1086 out[0].value = 0;
1087 out[0].prop.Type = TGSI_TOKEN_TYPE_PROPERTY;
1088 out[0].prop.NrTokens = 2;
1089 out[0].prop.PropertyName = name;
1090
1091 out[1].prop_data.Data = data;
1092 }
1093
1094
1095 static void emit_decls( struct ureg_program *ureg )
1096 {
1097 unsigned i;
1098
1099 if (ureg->property_gs_input_prim != ~0) {
1100 assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY);
1101
1102 emit_property(ureg,
1103 TGSI_PROPERTY_GS_INPUT_PRIM,
1104 ureg->property_gs_input_prim);
1105 }
1106
1107 if (ureg->processor == TGSI_PROCESSOR_VERTEX) {
1108 for (i = 0; i < UREG_MAX_INPUT; i++) {
1109 if (ureg->vs_inputs[i/32] & (1 << (i%32))) {
1110 emit_decl_range( ureg, TGSI_FILE_INPUT, i, 1 );
1111 }
1112 }
1113 } else if (ureg->processor == TGSI_PROCESSOR_FRAGMENT) {
1114 for (i = 0; i < ureg->nr_fs_inputs; i++) {
1115 emit_decl( ureg,
1116 TGSI_FILE_INPUT,
1117 i,
1118 ureg->fs_input[i].semantic_name,
1119 ureg->fs_input[i].semantic_index,
1120 ureg->fs_input[i].interp );
1121 }
1122 } else {
1123 for (i = 0; i < ureg->nr_gs_inputs; i++) {
1124 emit_decl_range(ureg,
1125 TGSI_FILE_INPUT,
1126 ureg->gs_input[i].index,
1127 1);
1128 }
1129 }
1130
1131 for (i = 0; i < ureg->nr_system_values; i++) {
1132 emit_decl(ureg,
1133 TGSI_FILE_SYSTEM_VALUE,
1134 ureg->system_value[i].index,
1135 ureg->system_value[i].semantic_name,
1136 ureg->system_value[i].semantic_index,
1137 TGSI_INTERPOLATE_CONSTANT);
1138 }
1139
1140 for (i = 0; i < ureg->nr_outputs; i++) {
1141 emit_decl( ureg,
1142 TGSI_FILE_OUTPUT,
1143 i,
1144 ureg->output[i].semantic_name,
1145 ureg->output[i].semantic_index,
1146 TGSI_INTERPOLATE_CONSTANT );
1147 }
1148
1149 for (i = 0; i < ureg->nr_samplers; i++) {
1150 emit_decl_range( ureg,
1151 TGSI_FILE_SAMPLER,
1152 ureg->sampler[i].Index, 1 );
1153 }
1154
1155 if (ureg->nr_constant_ranges) {
1156 for (i = 0; i < ureg->nr_constant_ranges; i++)
1157 emit_decl_range( ureg,
1158 TGSI_FILE_CONSTANT,
1159 ureg->constant_range[i].first,
1160 (ureg->constant_range[i].last + 1 -
1161 ureg->constant_range[i].first) );
1162 }
1163
1164 if (ureg->nr_temps) {
1165 emit_decl_range( ureg,
1166 TGSI_FILE_TEMPORARY,
1167 0, ureg->nr_temps );
1168 }
1169
1170 if (ureg->nr_addrs) {
1171 emit_decl_range( ureg,
1172 TGSI_FILE_ADDRESS,
1173 0, ureg->nr_addrs );
1174 }
1175
1176 if (ureg->nr_loops) {
1177 emit_decl_range(ureg,
1178 TGSI_FILE_LOOP,
1179 0,
1180 ureg->nr_loops);
1181 }
1182
1183 if (ureg->nr_preds) {
1184 emit_decl_range(ureg,
1185 TGSI_FILE_PREDICATE,
1186 0,
1187 ureg->nr_preds);
1188 }
1189
1190 for (i = 0; i < ureg->nr_immediates; i++) {
1191 emit_immediate( ureg,
1192 ureg->immediate[i].value.u,
1193 ureg->immediate[i].type );
1194 }
1195 }
1196
1197 /* Append the instruction tokens onto the declarations to build a
1198 * contiguous stream suitable to send to the driver.
1199 */
1200 static void copy_instructions( struct ureg_program *ureg )
1201 {
1202 unsigned nr_tokens = ureg->domain[DOMAIN_INSN].count;
1203 union tgsi_any_token *out = get_tokens( ureg,
1204 DOMAIN_DECL,
1205 nr_tokens );
1206
1207 memcpy(out,
1208 ureg->domain[DOMAIN_INSN].tokens,
1209 nr_tokens * sizeof out[0] );
1210 }
1211
1212
1213 static void
1214 fixup_header_size(struct ureg_program *ureg)
1215 {
1216 union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_DECL, 0 );
1217
1218 out->header.BodySize = ureg->domain[DOMAIN_DECL].count - 2;
1219 }
1220
1221
1222 static void
1223 emit_header( struct ureg_program *ureg )
1224 {
1225 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 );
1226
1227 out[0].header.HeaderSize = 2;
1228 out[0].header.BodySize = 0;
1229
1230 out[1].processor.Processor = ureg->processor;
1231 out[1].processor.Padding = 0;
1232 }
1233
1234
1235 const struct tgsi_token *ureg_finalize( struct ureg_program *ureg )
1236 {
1237 const struct tgsi_token *tokens;
1238
1239 emit_header( ureg );
1240 emit_decls( ureg );
1241 copy_instructions( ureg );
1242 fixup_header_size( ureg );
1243
1244 if (ureg->domain[0].tokens == error_tokens ||
1245 ureg->domain[1].tokens == error_tokens) {
1246 debug_printf("%s: error in generated shader\n", __FUNCTION__);
1247 assert(0);
1248 return NULL;
1249 }
1250
1251 tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token;
1252
1253 if (0) {
1254 debug_printf("%s: emitted shader %d tokens:\n", __FUNCTION__,
1255 ureg->domain[DOMAIN_DECL].count);
1256 tgsi_dump( tokens, 0 );
1257 }
1258
1259 #if DEBUG
1260 if (tokens && !tgsi_sanity_check(tokens)) {
1261 debug_printf("tgsi_ureg.c, sanity check failed on generated tokens:\n");
1262 tgsi_dump(tokens, 0);
1263 assert(0);
1264 }
1265 #endif
1266
1267
1268 return tokens;
1269 }
1270
1271
1272 void *ureg_create_shader( struct ureg_program *ureg,
1273 struct pipe_context *pipe )
1274 {
1275 struct pipe_shader_state state;
1276
1277 state.tokens = ureg_finalize(ureg);
1278 if(!state.tokens)
1279 return NULL;
1280
1281 if (ureg->processor == TGSI_PROCESSOR_VERTEX)
1282 return pipe->create_vs_state( pipe, &state );
1283 else
1284 return pipe->create_fs_state( pipe, &state );
1285 }
1286
1287
1288 const struct tgsi_token *ureg_get_tokens( struct ureg_program *ureg,
1289 unsigned *nr_tokens )
1290 {
1291 const struct tgsi_token *tokens;
1292
1293 ureg_finalize(ureg);
1294
1295 tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token;
1296
1297 if (nr_tokens)
1298 *nr_tokens = ureg->domain[DOMAIN_DECL].size;
1299
1300 ureg->domain[DOMAIN_DECL].tokens = 0;
1301 ureg->domain[DOMAIN_DECL].size = 0;
1302 ureg->domain[DOMAIN_DECL].order = 0;
1303 ureg->domain[DOMAIN_DECL].count = 0;
1304
1305 return tokens;
1306 }
1307
1308
1309 struct ureg_program *ureg_create( unsigned processor )
1310 {
1311 struct ureg_program *ureg = CALLOC_STRUCT( ureg_program );
1312 if (ureg == NULL)
1313 return NULL;
1314
1315 ureg->processor = processor;
1316 ureg->property_gs_input_prim = ~0;
1317 return ureg;
1318 }
1319
1320
1321 void ureg_destroy( struct ureg_program *ureg )
1322 {
1323 unsigned i;
1324
1325 for (i = 0; i < Elements(ureg->domain); i++) {
1326 if (ureg->domain[i].tokens &&
1327 ureg->domain[i].tokens != error_tokens)
1328 FREE(ureg->domain[i].tokens);
1329 }
1330
1331 FREE(ureg);
1332 }