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