tgsi_ureg.c revision 1279923d72942ee201fcc6ad40d552143f651f03
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_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_debug.h"
37#include "util/u_memory.h"
38#include "util/u_math.h"
39
40union tgsi_any_token {
41   struct tgsi_header header;
42   struct tgsi_processor processor;
43   struct tgsi_token token;
44   struct tgsi_property prop;
45   struct tgsi_property_data prop_data;
46   struct tgsi_declaration decl;
47   struct tgsi_declaration_range decl_range;
48   struct tgsi_declaration_dimension decl_dim;
49   struct tgsi_declaration_interp decl_interp;
50   struct tgsi_declaration_semantic decl_semantic;
51   struct tgsi_declaration_sampler_view decl_sampler_view;
52   struct tgsi_immediate imm;
53   union  tgsi_immediate_data imm_data;
54   struct tgsi_instruction insn;
55   struct tgsi_instruction_predicate insn_predicate;
56   struct tgsi_instruction_label insn_label;
57   struct tgsi_instruction_texture insn_texture;
58   struct tgsi_texture_offset insn_texture_offset;
59   struct tgsi_src_register src;
60   struct tgsi_dimension dim;
61   struct tgsi_dst_register dst;
62   unsigned value;
63};
64
65
66struct ureg_tokens {
67   union tgsi_any_token *tokens;
68   unsigned size;
69   unsigned order;
70   unsigned count;
71};
72
73#define UREG_MAX_INPUT PIPE_MAX_ATTRIBS
74#define UREG_MAX_SYSTEM_VALUE PIPE_MAX_ATTRIBS
75#define UREG_MAX_OUTPUT PIPE_MAX_ATTRIBS
76#define UREG_MAX_CONSTANT_RANGE 32
77#define UREG_MAX_IMMEDIATE 256
78#define UREG_MAX_TEMP 256
79#define UREG_MAX_ADDR 2
80#define UREG_MAX_PRED 1
81
82struct const_decl {
83   struct {
84      unsigned first;
85      unsigned last;
86   } constant_range[UREG_MAX_CONSTANT_RANGE];
87   unsigned nr_constant_ranges;
88};
89
90#define DOMAIN_DECL 0
91#define DOMAIN_INSN 1
92
93struct ureg_program
94{
95   unsigned processor;
96   struct pipe_context *pipe;
97
98   struct {
99      unsigned semantic_name;
100      unsigned semantic_index;
101      unsigned interp;
102      unsigned char cylindrical_wrap;
103      unsigned char centroid;
104   } fs_input[UREG_MAX_INPUT];
105   unsigned nr_fs_inputs;
106
107   unsigned vs_inputs[UREG_MAX_INPUT/32];
108
109   struct {
110      unsigned index;
111      unsigned semantic_name;
112      unsigned semantic_index;
113   } gs_input[UREG_MAX_INPUT];
114   unsigned nr_gs_inputs;
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   } output[UREG_MAX_OUTPUT];
128   unsigned nr_outputs;
129
130   struct {
131      union {
132         float f[4];
133         unsigned u[4];
134         int i[4];
135      } value;
136      unsigned nr;
137      unsigned type;
138   } immediate[UREG_MAX_IMMEDIATE];
139   unsigned nr_immediates;
140
141   struct ureg_src sampler[PIPE_MAX_SAMPLERS];
142   unsigned nr_samplers;
143
144   struct {
145      unsigned index;
146      unsigned target;
147      unsigned return_type_x;
148      unsigned return_type_y;
149      unsigned return_type_z;
150      unsigned return_type_w;
151   } sampler_view[PIPE_MAX_SHADER_SAMPLER_VIEWS];
152   unsigned nr_sampler_views;
153
154   unsigned temps_active[UREG_MAX_TEMP / 32];
155   unsigned nr_temps;
156
157   struct const_decl const_decls;
158   struct const_decl const_decls2D[PIPE_MAX_CONSTANT_BUFFERS];
159
160   unsigned property_gs_input_prim;
161   unsigned property_gs_output_prim;
162   unsigned property_gs_max_vertices;
163   unsigned char property_fs_coord_origin; /* = TGSI_FS_COORD_ORIGIN_* */
164   unsigned char property_fs_coord_pixel_center; /* = TGSI_FS_COORD_PIXEL_CENTER_* */
165   unsigned char property_fs_color0_writes_all_cbufs; /* = TGSI_FS_COLOR0_WRITES_ALL_CBUFS * */
166   unsigned char property_fs_depth_layout; /* TGSI_FS_DEPTH_LAYOUT */
167
168   unsigned nr_addrs;
169   unsigned nr_preds;
170   unsigned nr_instructions;
171
172   struct ureg_tokens domain[2];
173};
174
175static union tgsi_any_token error_tokens[32];
176
177static void tokens_error( struct ureg_tokens *tokens )
178{
179   if (tokens->tokens && tokens->tokens != error_tokens)
180      FREE(tokens->tokens);
181
182   tokens->tokens = error_tokens;
183   tokens->size = Elements(error_tokens);
184   tokens->count = 0;
185}
186
187
188static void tokens_expand( struct ureg_tokens *tokens,
189                           unsigned count )
190{
191   unsigned old_size = tokens->size * sizeof(unsigned);
192
193   if (tokens->tokens == error_tokens) {
194      return;
195   }
196
197   while (tokens->count + count > tokens->size) {
198      tokens->size = (1 << ++tokens->order);
199   }
200
201   tokens->tokens = REALLOC(tokens->tokens,
202                            old_size,
203                            tokens->size * sizeof(unsigned));
204   if (tokens->tokens == NULL) {
205      tokens_error(tokens);
206   }
207}
208
209static void set_bad( struct ureg_program *ureg )
210{
211   tokens_error(&ureg->domain[0]);
212}
213
214
215
216static union tgsi_any_token *get_tokens( struct ureg_program *ureg,
217                                         unsigned domain,
218                                         unsigned count )
219{
220   struct ureg_tokens *tokens = &ureg->domain[domain];
221   union tgsi_any_token *result;
222
223   if (tokens->count + count > tokens->size)
224      tokens_expand(tokens, count);
225
226   result = &tokens->tokens[tokens->count];
227   tokens->count += count;
228   return result;
229}
230
231
232static union tgsi_any_token *retrieve_token( struct ureg_program *ureg,
233                                            unsigned domain,
234                                            unsigned nr )
235{
236   if (ureg->domain[domain].tokens == error_tokens)
237      return &error_tokens[0];
238
239   return &ureg->domain[domain].tokens[nr];
240}
241
242
243
244static INLINE struct ureg_dst
245ureg_dst_register( unsigned file,
246                   unsigned index )
247{
248   struct ureg_dst dst;
249
250   dst.File      = file;
251   dst.WriteMask = TGSI_WRITEMASK_XYZW;
252   dst.Indirect  = 0;
253   dst.IndirectIndex = 0;
254   dst.IndirectSwizzle = 0;
255   dst.Saturate  = 0;
256   dst.Predicate = 0;
257   dst.PredNegate = 0;
258   dst.PredSwizzleX = TGSI_SWIZZLE_X;
259   dst.PredSwizzleY = TGSI_SWIZZLE_Y;
260   dst.PredSwizzleZ = TGSI_SWIZZLE_Z;
261   dst.PredSwizzleW = TGSI_SWIZZLE_W;
262   dst.Index     = index;
263
264   return dst;
265}
266
267
268void
269ureg_property_gs_input_prim(struct ureg_program *ureg,
270                            unsigned input_prim)
271{
272   ureg->property_gs_input_prim = input_prim;
273}
274
275void
276ureg_property_gs_output_prim(struct ureg_program *ureg,
277                             unsigned output_prim)
278{
279   ureg->property_gs_output_prim = output_prim;
280}
281
282void
283ureg_property_gs_max_vertices(struct ureg_program *ureg,
284                              unsigned max_vertices)
285{
286   ureg->property_gs_max_vertices = max_vertices;
287}
288
289void
290ureg_property_fs_coord_origin(struct ureg_program *ureg,
291                            unsigned fs_coord_origin)
292{
293   ureg->property_fs_coord_origin = fs_coord_origin;
294}
295
296void
297ureg_property_fs_coord_pixel_center(struct ureg_program *ureg,
298                            unsigned fs_coord_pixel_center)
299{
300   ureg->property_fs_coord_pixel_center = fs_coord_pixel_center;
301}
302
303void
304ureg_property_fs_color0_writes_all_cbufs(struct ureg_program *ureg,
305                            unsigned fs_color0_writes_all_cbufs)
306{
307   ureg->property_fs_color0_writes_all_cbufs = fs_color0_writes_all_cbufs;
308}
309
310void
311ureg_property_fs_depth_layout(struct ureg_program *ureg,
312                              unsigned fs_depth_layout)
313{
314   ureg->property_fs_depth_layout = fs_depth_layout;
315}
316
317struct ureg_src
318ureg_DECL_fs_input_cyl_centroid(struct ureg_program *ureg,
319                       unsigned semantic_name,
320                       unsigned semantic_index,
321                       unsigned interp_mode,
322                       unsigned cylindrical_wrap,
323                       unsigned centroid)
324{
325   unsigned i;
326
327   for (i = 0; i < ureg->nr_fs_inputs; i++) {
328      if (ureg->fs_input[i].semantic_name == semantic_name &&
329          ureg->fs_input[i].semantic_index == semantic_index) {
330         goto out;
331      }
332   }
333
334   if (ureg->nr_fs_inputs < UREG_MAX_INPUT) {
335      ureg->fs_input[i].semantic_name = semantic_name;
336      ureg->fs_input[i].semantic_index = semantic_index;
337      ureg->fs_input[i].interp = interp_mode;
338      ureg->fs_input[i].cylindrical_wrap = cylindrical_wrap;
339      ureg->fs_input[i].centroid = centroid;
340      ureg->nr_fs_inputs++;
341   } else {
342      set_bad(ureg);
343   }
344
345out:
346   return ureg_src_register(TGSI_FILE_INPUT, i);
347}
348
349
350struct ureg_src
351ureg_DECL_vs_input( struct ureg_program *ureg,
352                    unsigned index )
353{
354   assert(ureg->processor == TGSI_PROCESSOR_VERTEX);
355
356   ureg->vs_inputs[index/32] |= 1 << (index % 32);
357   return ureg_src_register( TGSI_FILE_INPUT, index );
358}
359
360
361struct ureg_src
362ureg_DECL_gs_input(struct ureg_program *ureg,
363                   unsigned index,
364                   unsigned semantic_name,
365                   unsigned semantic_index)
366{
367   if (ureg->nr_gs_inputs < UREG_MAX_INPUT) {
368      ureg->gs_input[ureg->nr_gs_inputs].index = index;
369      ureg->gs_input[ureg->nr_gs_inputs].semantic_name = semantic_name;
370      ureg->gs_input[ureg->nr_gs_inputs].semantic_index = semantic_index;
371      ureg->nr_gs_inputs++;
372   } else {
373      set_bad(ureg);
374   }
375
376   /* XXX: Add suport for true 2D input registers. */
377   return ureg_src_register(TGSI_FILE_INPUT, index);
378}
379
380
381struct ureg_src
382ureg_DECL_system_value(struct ureg_program *ureg,
383                       unsigned index,
384                       unsigned semantic_name,
385                       unsigned semantic_index)
386{
387   if (ureg->nr_system_values < UREG_MAX_SYSTEM_VALUE) {
388      ureg->system_value[ureg->nr_system_values].index = index;
389      ureg->system_value[ureg->nr_system_values].semantic_name = semantic_name;
390      ureg->system_value[ureg->nr_system_values].semantic_index = semantic_index;
391      ureg->nr_system_values++;
392   } else {
393      set_bad(ureg);
394   }
395
396   return ureg_src_register(TGSI_FILE_SYSTEM_VALUE, index);
397}
398
399
400struct ureg_dst
401ureg_DECL_output_masked( struct ureg_program *ureg,
402                         unsigned name,
403                         unsigned index,
404                         unsigned usage_mask )
405{
406   unsigned i;
407
408   assert(usage_mask != 0);
409
410   for (i = 0; i < ureg->nr_outputs; i++) {
411      if (ureg->output[i].semantic_name == name &&
412          ureg->output[i].semantic_index == index) {
413         ureg->output[i].usage_mask |= usage_mask;
414         goto out;
415      }
416   }
417
418   if (ureg->nr_outputs < UREG_MAX_OUTPUT) {
419      ureg->output[i].semantic_name = name;
420      ureg->output[i].semantic_index = index;
421      ureg->output[i].usage_mask = usage_mask;
422      ureg->nr_outputs++;
423   }
424   else {
425      set_bad( ureg );
426   }
427
428out:
429   return ureg_dst_register( TGSI_FILE_OUTPUT, i );
430}
431
432
433struct ureg_dst
434ureg_DECL_output( struct ureg_program *ureg,
435                  unsigned name,
436                  unsigned index )
437{
438   return ureg_DECL_output_masked(ureg, name, index, TGSI_WRITEMASK_XYZW);
439}
440
441
442/* Returns a new constant register.  Keep track of which have been
443 * referred to so that we can emit decls later.
444 *
445 * Constant operands declared with this function must be addressed
446 * with a two-dimensional index.
447 *
448 * There is nothing in this code to bind this constant to any tracked
449 * value or manage any constant_buffer contents -- that's the
450 * resposibility of the calling code.
451 */
452void
453ureg_DECL_constant2D(struct ureg_program *ureg,
454                     unsigned first,
455                     unsigned last,
456                     unsigned index2D)
457{
458   struct const_decl *decl = &ureg->const_decls2D[index2D];
459
460   assert(index2D < PIPE_MAX_CONSTANT_BUFFERS);
461
462   if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) {
463      uint i = decl->nr_constant_ranges++;
464
465      decl->constant_range[i].first = first;
466      decl->constant_range[i].last = last;
467   }
468}
469
470
471/* A one-dimensional, depricated version of ureg_DECL_constant2D().
472 *
473 * Constant operands declared with this function must be addressed
474 * with a one-dimensional index.
475 */
476struct ureg_src
477ureg_DECL_constant(struct ureg_program *ureg,
478                   unsigned index)
479{
480   struct const_decl *decl = &ureg->const_decls;
481   unsigned minconst = index, maxconst = index;
482   unsigned i;
483
484   /* Inside existing range?
485    */
486   for (i = 0; i < decl->nr_constant_ranges; i++) {
487      if (decl->constant_range[i].first <= index &&
488          decl->constant_range[i].last >= index) {
489         goto out;
490      }
491   }
492
493   /* Extend existing range?
494    */
495   for (i = 0; i < decl->nr_constant_ranges; i++) {
496      if (decl->constant_range[i].last == index - 1) {
497         decl->constant_range[i].last = index;
498         goto out;
499      }
500
501      if (decl->constant_range[i].first == index + 1) {
502         decl->constant_range[i].first = index;
503         goto out;
504      }
505
506      minconst = MIN2(minconst, decl->constant_range[i].first);
507      maxconst = MAX2(maxconst, decl->constant_range[i].last);
508   }
509
510   /* Create new range?
511    */
512   if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) {
513      i = decl->nr_constant_ranges++;
514      decl->constant_range[i].first = index;
515      decl->constant_range[i].last = index;
516      goto out;
517   }
518
519   /* Collapse all ranges down to one:
520    */
521   i = 0;
522   decl->constant_range[0].first = minconst;
523   decl->constant_range[0].last = maxconst;
524   decl->nr_constant_ranges = 1;
525
526out:
527   assert(i < decl->nr_constant_ranges);
528   assert(decl->constant_range[i].first <= index);
529   assert(decl->constant_range[i].last >= index);
530   return ureg_src_register(TGSI_FILE_CONSTANT, index);
531}
532
533
534/* Allocate a new temporary.  Temporaries greater than UREG_MAX_TEMP
535 * are legal, but will not be released.
536 */
537struct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg )
538{
539   unsigned i;
540
541   for (i = 0; i < UREG_MAX_TEMP; i += 32) {
542      int bit = ffs(~ureg->temps_active[i/32]);
543      if (bit != 0) {
544         i += bit - 1;
545         goto out;
546      }
547   }
548
549   /* No reusable temps, so allocate a new one:
550    */
551   i = ureg->nr_temps++;
552
553out:
554   if (i < UREG_MAX_TEMP)
555      ureg->temps_active[i/32] |= 1 << (i % 32);
556
557   if (i >= ureg->nr_temps)
558      ureg->nr_temps = i + 1;
559
560   return ureg_dst_register( TGSI_FILE_TEMPORARY, i );
561}
562
563
564void ureg_release_temporary( struct ureg_program *ureg,
565                             struct ureg_dst tmp )
566{
567   if(tmp.File == TGSI_FILE_TEMPORARY)
568      if (tmp.Index < UREG_MAX_TEMP)
569         ureg->temps_active[tmp.Index/32] &= ~(1 << (tmp.Index % 32));
570}
571
572
573/* Allocate a new address register.
574 */
575struct ureg_dst ureg_DECL_address( struct ureg_program *ureg )
576{
577   if (ureg->nr_addrs < UREG_MAX_ADDR)
578      return ureg_dst_register( TGSI_FILE_ADDRESS, ureg->nr_addrs++ );
579
580   assert( 0 );
581   return ureg_dst_register( TGSI_FILE_ADDRESS, 0 );
582}
583
584/* Allocate a new predicate register.
585 */
586struct ureg_dst
587ureg_DECL_predicate(struct ureg_program *ureg)
588{
589   if (ureg->nr_preds < UREG_MAX_PRED) {
590      return ureg_dst_register(TGSI_FILE_PREDICATE, ureg->nr_preds++);
591   }
592
593   assert(0);
594   return ureg_dst_register(TGSI_FILE_PREDICATE, 0);
595}
596
597/* Allocate a new sampler.
598 */
599struct ureg_src ureg_DECL_sampler( struct ureg_program *ureg,
600                                   unsigned nr )
601{
602   unsigned i;
603
604   for (i = 0; i < ureg->nr_samplers; i++)
605      if (ureg->sampler[i].Index == nr)
606         return ureg->sampler[i];
607
608   if (i < PIPE_MAX_SAMPLERS) {
609      ureg->sampler[i] = ureg_src_register( TGSI_FILE_SAMPLER, nr );
610      ureg->nr_samplers++;
611      return ureg->sampler[i];
612   }
613
614   assert( 0 );
615   return ureg->sampler[0];
616}
617
618/*
619 * Allocate a new shader sampler view.
620 */
621struct ureg_src
622ureg_DECL_sampler_view(struct ureg_program *ureg,
623                       unsigned index,
624                       unsigned target,
625                       unsigned return_type_x,
626                       unsigned return_type_y,
627                       unsigned return_type_z,
628                       unsigned return_type_w)
629{
630   struct ureg_src reg = ureg_src_register(TGSI_FILE_SAMPLER_VIEW, index);
631   uint i;
632
633   for (i = 0; i < ureg->nr_sampler_views; i++) {
634      if (ureg->sampler_view[i].index == index) {
635         return reg;
636      }
637   }
638
639   if (i < PIPE_MAX_SHADER_SAMPLER_VIEWS) {
640      ureg->sampler_view[i].index = index;
641      ureg->sampler_view[i].target = target;
642      ureg->sampler_view[i].return_type_x = return_type_x;
643      ureg->sampler_view[i].return_type_y = return_type_y;
644      ureg->sampler_view[i].return_type_z = return_type_z;
645      ureg->sampler_view[i].return_type_w = return_type_w;
646      ureg->nr_sampler_views++;
647      return reg;
648   }
649
650   assert(0);
651   return reg;
652}
653
654static int
655match_or_expand_immediate( const unsigned *v,
656                           unsigned nr,
657                           unsigned *v2,
658                           unsigned *pnr2,
659                           unsigned *swizzle )
660{
661   unsigned nr2 = *pnr2;
662   unsigned i, j;
663
664   *swizzle = 0;
665
666   for (i = 0; i < nr; i++) {
667      boolean found = FALSE;
668
669      for (j = 0; j < nr2 && !found; j++) {
670         if (v[i] == v2[j]) {
671            *swizzle |= j << (i * 2);
672            found = TRUE;
673         }
674      }
675
676      if (!found) {
677         if (nr2 >= 4) {
678            return FALSE;
679         }
680
681         v2[nr2] = v[i];
682         *swizzle |= nr2 << (i * 2);
683         nr2++;
684      }
685   }
686
687   /* Actually expand immediate only when fully succeeded.
688    */
689   *pnr2 = nr2;
690   return TRUE;
691}
692
693
694static struct ureg_src
695decl_immediate( struct ureg_program *ureg,
696                const unsigned *v,
697                unsigned nr,
698                unsigned type )
699{
700   unsigned i, j;
701   unsigned swizzle = 0;
702
703   /* Could do a first pass where we examine all existing immediates
704    * without expanding.
705    */
706
707   for (i = 0; i < ureg->nr_immediates; i++) {
708      if (ureg->immediate[i].type != type) {
709         continue;
710      }
711      if (match_or_expand_immediate(v,
712                                    nr,
713                                    ureg->immediate[i].value.u,
714                                    &ureg->immediate[i].nr,
715                                    &swizzle)) {
716         goto out;
717      }
718   }
719
720   if (ureg->nr_immediates < UREG_MAX_IMMEDIATE) {
721      i = ureg->nr_immediates++;
722      ureg->immediate[i].type = type;
723      if (match_or_expand_immediate(v,
724                                    nr,
725                                    ureg->immediate[i].value.u,
726                                    &ureg->immediate[i].nr,
727                                    &swizzle)) {
728         goto out;
729      }
730   }
731
732   set_bad(ureg);
733
734out:
735   /* Make sure that all referenced elements are from this immediate.
736    * Has the effect of making size-one immediates into scalars.
737    */
738   for (j = nr; j < 4; j++) {
739      swizzle |= (swizzle & 0x3) << (j * 2);
740   }
741
742   return ureg_swizzle(ureg_src_register(TGSI_FILE_IMMEDIATE, i),
743                       (swizzle >> 0) & 0x3,
744                       (swizzle >> 2) & 0x3,
745                       (swizzle >> 4) & 0x3,
746                       (swizzle >> 6) & 0x3);
747}
748
749
750struct ureg_src
751ureg_DECL_immediate( struct ureg_program *ureg,
752                     const float *v,
753                     unsigned nr )
754{
755   union {
756      float f[4];
757      unsigned u[4];
758   } fu;
759   unsigned int i;
760
761   for (i = 0; i < nr; i++) {
762      fu.f[i] = v[i];
763   }
764
765   return decl_immediate(ureg, fu.u, nr, TGSI_IMM_FLOAT32);
766}
767
768
769struct ureg_src
770ureg_DECL_immediate_uint( struct ureg_program *ureg,
771                          const unsigned *v,
772                          unsigned nr )
773{
774   return decl_immediate(ureg, v, nr, TGSI_IMM_UINT32);
775}
776
777
778struct ureg_src
779ureg_DECL_immediate_block_uint( struct ureg_program *ureg,
780                                const unsigned *v,
781                                unsigned nr )
782{
783   uint index;
784   uint i;
785
786   if (ureg->nr_immediates + (nr + 3) / 4 > UREG_MAX_IMMEDIATE) {
787      set_bad(ureg);
788      return ureg_src_register(TGSI_FILE_IMMEDIATE, 0);
789   }
790
791   index = ureg->nr_immediates;
792   ureg->nr_immediates += (nr + 3) / 4;
793
794   for (i = index; i < ureg->nr_immediates; i++) {
795      ureg->immediate[i].type = TGSI_IMM_UINT32;
796      ureg->immediate[i].nr = nr > 4 ? 4 : nr;
797      memcpy(ureg->immediate[i].value.u,
798             &v[(i - index) * 4],
799             ureg->immediate[i].nr * sizeof(uint));
800      nr -= 4;
801   }
802
803   return ureg_src_register(TGSI_FILE_IMMEDIATE, index);
804}
805
806
807struct ureg_src
808ureg_DECL_immediate_int( struct ureg_program *ureg,
809                         const int *v,
810                         unsigned nr )
811{
812   return decl_immediate(ureg, (const unsigned *)v, nr, TGSI_IMM_INT32);
813}
814
815
816void
817ureg_emit_src( struct ureg_program *ureg,
818               struct ureg_src src )
819{
820   unsigned size = 1 + (src.Indirect ? 1 : 0) +
821                   (src.Dimension ? (src.DimIndirect ? 2 : 1) : 0);
822
823   union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
824   unsigned n = 0;
825
826   assert(src.File != TGSI_FILE_NULL);
827   assert(src.File < TGSI_FILE_COUNT);
828
829   out[n].value = 0;
830   out[n].src.File = src.File;
831   out[n].src.SwizzleX = src.SwizzleX;
832   out[n].src.SwizzleY = src.SwizzleY;
833   out[n].src.SwizzleZ = src.SwizzleZ;
834   out[n].src.SwizzleW = src.SwizzleW;
835   out[n].src.Index = src.Index;
836   out[n].src.Negate = src.Negate;
837   out[0].src.Absolute = src.Absolute;
838   n++;
839
840   if (src.Indirect) {
841      out[0].src.Indirect = 1;
842      out[n].value = 0;
843      out[n].src.File = src.IndirectFile;
844      out[n].src.SwizzleX = src.IndirectSwizzle;
845      out[n].src.SwizzleY = src.IndirectSwizzle;
846      out[n].src.SwizzleZ = src.IndirectSwizzle;
847      out[n].src.SwizzleW = src.IndirectSwizzle;
848      out[n].src.Index = src.IndirectIndex;
849      n++;
850   }
851
852   if (src.Dimension) {
853      if (src.DimIndirect) {
854         out[0].src.Dimension = 1;
855         out[n].dim.Indirect = 1;
856         out[n].dim.Dimension = 0;
857         out[n].dim.Padding = 0;
858         out[n].dim.Index = src.DimensionIndex;
859         n++;
860         out[n].value = 0;
861         out[n].src.File = src.DimIndFile;
862         out[n].src.SwizzleX = src.DimIndSwizzle;
863         out[n].src.SwizzleY = src.DimIndSwizzle;
864         out[n].src.SwizzleZ = src.DimIndSwizzle;
865         out[n].src.SwizzleW = src.DimIndSwizzle;
866         out[n].src.Index = src.DimIndIndex;
867      } else {
868         out[0].src.Dimension = 1;
869         out[n].dim.Indirect = 0;
870         out[n].dim.Dimension = 0;
871         out[n].dim.Padding = 0;
872         out[n].dim.Index = src.DimensionIndex;
873      }
874      n++;
875   }
876
877   assert(n == size);
878}
879
880
881void
882ureg_emit_dst( struct ureg_program *ureg,
883               struct ureg_dst dst )
884{
885   unsigned size = (1 +
886                    (dst.Indirect ? 1 : 0));
887
888   union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
889   unsigned n = 0;
890
891   assert(dst.File != TGSI_FILE_NULL);
892   assert(dst.File != TGSI_FILE_CONSTANT);
893   assert(dst.File != TGSI_FILE_INPUT);
894   assert(dst.File != TGSI_FILE_SAMPLER);
895   assert(dst.File != TGSI_FILE_SAMPLER_VIEW);
896   assert(dst.File != TGSI_FILE_IMMEDIATE);
897   assert(dst.File < TGSI_FILE_COUNT);
898
899   out[n].value = 0;
900   out[n].dst.File = dst.File;
901   out[n].dst.WriteMask = dst.WriteMask;
902   out[n].dst.Indirect = dst.Indirect;
903   out[n].dst.Index = dst.Index;
904   n++;
905
906   if (dst.Indirect) {
907      out[n].value = 0;
908      out[n].src.File = TGSI_FILE_ADDRESS;
909      out[n].src.SwizzleX = dst.IndirectSwizzle;
910      out[n].src.SwizzleY = dst.IndirectSwizzle;
911      out[n].src.SwizzleZ = dst.IndirectSwizzle;
912      out[n].src.SwizzleW = dst.IndirectSwizzle;
913      out[n].src.Index = dst.IndirectIndex;
914      n++;
915   }
916
917   assert(n == size);
918}
919
920
921static void validate( unsigned opcode,
922                      unsigned nr_dst,
923                      unsigned nr_src )
924{
925#ifdef DEBUG
926   const struct tgsi_opcode_info *info = tgsi_get_opcode_info( opcode );
927   assert(info);
928   if(info) {
929      assert(nr_dst == info->num_dst);
930      assert(nr_src == info->num_src);
931   }
932#endif
933}
934
935struct ureg_emit_insn_result
936ureg_emit_insn(struct ureg_program *ureg,
937               unsigned opcode,
938               boolean saturate,
939               boolean predicate,
940               boolean pred_negate,
941               unsigned pred_swizzle_x,
942               unsigned pred_swizzle_y,
943               unsigned pred_swizzle_z,
944               unsigned pred_swizzle_w,
945               unsigned num_dst,
946               unsigned num_src )
947{
948   union tgsi_any_token *out;
949   uint count = predicate ? 2 : 1;
950   struct ureg_emit_insn_result result;
951
952   validate( opcode, num_dst, num_src );
953
954   out = get_tokens( ureg, DOMAIN_INSN, count );
955   out[0].insn = tgsi_default_instruction();
956   out[0].insn.Opcode = opcode;
957   out[0].insn.Saturate = saturate;
958   out[0].insn.NumDstRegs = num_dst;
959   out[0].insn.NumSrcRegs = num_src;
960
961   result.insn_token = ureg->domain[DOMAIN_INSN].count - count;
962   result.extended_token = result.insn_token;
963
964   if (predicate) {
965      out[0].insn.Predicate = 1;
966      out[1].insn_predicate = tgsi_default_instruction_predicate();
967      out[1].insn_predicate.Negate = pred_negate;
968      out[1].insn_predicate.SwizzleX = pred_swizzle_x;
969      out[1].insn_predicate.SwizzleY = pred_swizzle_y;
970      out[1].insn_predicate.SwizzleZ = pred_swizzle_z;
971      out[1].insn_predicate.SwizzleW = pred_swizzle_w;
972   }
973
974   ureg->nr_instructions++;
975
976   return result;
977}
978
979
980void
981ureg_emit_label(struct ureg_program *ureg,
982                unsigned extended_token,
983                unsigned *label_token )
984{
985   union tgsi_any_token *out, *insn;
986
987   if(!label_token)
988      return;
989
990   out = get_tokens( ureg, DOMAIN_INSN, 1 );
991   out[0].value = 0;
992
993   insn = retrieve_token( ureg, DOMAIN_INSN, extended_token );
994   insn->insn.Label = 1;
995
996   *label_token = ureg->domain[DOMAIN_INSN].count - 1;
997}
998
999/* Will return a number which can be used in a label to point to the
1000 * next instruction to be emitted.
1001 */
1002unsigned
1003ureg_get_instruction_number( struct ureg_program *ureg )
1004{
1005   return ureg->nr_instructions;
1006}
1007
1008/* Patch a given label (expressed as a token number) to point to a
1009 * given instruction (expressed as an instruction number).
1010 */
1011void
1012ureg_fixup_label(struct ureg_program *ureg,
1013                 unsigned label_token,
1014                 unsigned instruction_number )
1015{
1016   union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, label_token );
1017
1018   out->insn_label.Label = instruction_number;
1019}
1020
1021
1022void
1023ureg_emit_texture(struct ureg_program *ureg,
1024                  unsigned extended_token,
1025                  unsigned target, unsigned num_offsets)
1026{
1027   union tgsi_any_token *out, *insn;
1028
1029   out = get_tokens( ureg, DOMAIN_INSN, 1 );
1030   insn = retrieve_token( ureg, DOMAIN_INSN, extended_token );
1031
1032   insn->insn.Texture = 1;
1033
1034   out[0].value = 0;
1035   out[0].insn_texture.Texture = target;
1036   out[0].insn_texture.NumOffsets = num_offsets;
1037}
1038
1039void
1040ureg_emit_texture_offset(struct ureg_program *ureg,
1041                         const struct tgsi_texture_offset *offset)
1042{
1043   union tgsi_any_token *out;
1044
1045   out = get_tokens( ureg, DOMAIN_INSN, 1);
1046
1047   out[0].value = 0;
1048   out[0].insn_texture_offset = *offset;
1049
1050}
1051
1052
1053void
1054ureg_fixup_insn_size(struct ureg_program *ureg,
1055                     unsigned insn )
1056{
1057   union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, insn );
1058
1059   assert(out->insn.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
1060   out->insn.NrTokens = ureg->domain[DOMAIN_INSN].count - insn - 1;
1061}
1062
1063
1064void
1065ureg_insn(struct ureg_program *ureg,
1066          unsigned opcode,
1067          const struct ureg_dst *dst,
1068          unsigned nr_dst,
1069          const struct ureg_src *src,
1070          unsigned nr_src )
1071{
1072   struct ureg_emit_insn_result insn;
1073   unsigned i;
1074   boolean saturate;
1075   boolean predicate;
1076   boolean negate = FALSE;
1077   unsigned swizzle[4] = { 0 };
1078
1079   saturate = nr_dst ? dst[0].Saturate : FALSE;
1080   predicate = nr_dst ? dst[0].Predicate : FALSE;
1081   if (predicate) {
1082      negate = dst[0].PredNegate;
1083      swizzle[0] = dst[0].PredSwizzleX;
1084      swizzle[1] = dst[0].PredSwizzleY;
1085      swizzle[2] = dst[0].PredSwizzleZ;
1086      swizzle[3] = dst[0].PredSwizzleW;
1087   }
1088
1089   insn = ureg_emit_insn(ureg,
1090                         opcode,
1091                         saturate,
1092                         predicate,
1093                         negate,
1094                         swizzle[0],
1095                         swizzle[1],
1096                         swizzle[2],
1097                         swizzle[3],
1098                         nr_dst,
1099                         nr_src);
1100
1101   for (i = 0; i < nr_dst; i++)
1102      ureg_emit_dst( ureg, dst[i] );
1103
1104   for (i = 0; i < nr_src; i++)
1105      ureg_emit_src( ureg, src[i] );
1106
1107   ureg_fixup_insn_size( ureg, insn.insn_token );
1108}
1109
1110void
1111ureg_tex_insn(struct ureg_program *ureg,
1112              unsigned opcode,
1113              const struct ureg_dst *dst,
1114              unsigned nr_dst,
1115              unsigned target,
1116              const struct tgsi_texture_offset *texoffsets,
1117              unsigned nr_offset,
1118              const struct ureg_src *src,
1119              unsigned nr_src )
1120{
1121   struct ureg_emit_insn_result insn;
1122   unsigned i;
1123   boolean saturate;
1124   boolean predicate;
1125   boolean negate = FALSE;
1126   unsigned swizzle[4] = { 0 };
1127
1128   saturate = nr_dst ? dst[0].Saturate : FALSE;
1129   predicate = nr_dst ? dst[0].Predicate : FALSE;
1130   if (predicate) {
1131      negate = dst[0].PredNegate;
1132      swizzle[0] = dst[0].PredSwizzleX;
1133      swizzle[1] = dst[0].PredSwizzleY;
1134      swizzle[2] = dst[0].PredSwizzleZ;
1135      swizzle[3] = dst[0].PredSwizzleW;
1136   }
1137
1138   insn = ureg_emit_insn(ureg,
1139                         opcode,
1140                         saturate,
1141                         predicate,
1142                         negate,
1143                         swizzle[0],
1144                         swizzle[1],
1145                         swizzle[2],
1146                         swizzle[3],
1147                         nr_dst,
1148                         nr_src);
1149
1150   ureg_emit_texture( ureg, insn.extended_token, target, nr_offset );
1151
1152   for (i = 0; i < nr_offset; i++)
1153      ureg_emit_texture_offset( ureg, &texoffsets[i]);
1154
1155   for (i = 0; i < nr_dst; i++)
1156      ureg_emit_dst( ureg, dst[i] );
1157
1158   for (i = 0; i < nr_src; i++)
1159      ureg_emit_src( ureg, src[i] );
1160
1161   ureg_fixup_insn_size( ureg, insn.insn_token );
1162}
1163
1164
1165void
1166ureg_label_insn(struct ureg_program *ureg,
1167                unsigned opcode,
1168                const struct ureg_src *src,
1169                unsigned nr_src,
1170                unsigned *label_token )
1171{
1172   struct ureg_emit_insn_result insn;
1173   unsigned i;
1174
1175   insn = ureg_emit_insn(ureg,
1176                         opcode,
1177                         FALSE,
1178                         FALSE,
1179                         FALSE,
1180                         TGSI_SWIZZLE_X,
1181                         TGSI_SWIZZLE_Y,
1182                         TGSI_SWIZZLE_Z,
1183                         TGSI_SWIZZLE_W,
1184                         0,
1185                         nr_src);
1186
1187   ureg_emit_label( ureg, insn.extended_token, label_token );
1188
1189   for (i = 0; i < nr_src; i++)
1190      ureg_emit_src( ureg, src[i] );
1191
1192   ureg_fixup_insn_size( ureg, insn.insn_token );
1193}
1194
1195
1196static void
1197emit_decl_semantic(struct ureg_program *ureg,
1198                   unsigned file,
1199                   unsigned index,
1200                   unsigned semantic_name,
1201                   unsigned semantic_index,
1202                   unsigned usage_mask)
1203{
1204   union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3);
1205
1206   out[0].value = 0;
1207   out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
1208   out[0].decl.NrTokens = 3;
1209   out[0].decl.File = file;
1210   out[0].decl.UsageMask = usage_mask;
1211   out[0].decl.Semantic = 1;
1212
1213   out[1].value = 0;
1214   out[1].decl_range.First = index;
1215   out[1].decl_range.Last = index;
1216
1217   out[2].value = 0;
1218   out[2].decl_semantic.Name = semantic_name;
1219   out[2].decl_semantic.Index = semantic_index;
1220}
1221
1222
1223static void
1224emit_decl_fs(struct ureg_program *ureg,
1225             unsigned file,
1226             unsigned index,
1227             unsigned semantic_name,
1228             unsigned semantic_index,
1229             unsigned interpolate,
1230             unsigned cylindrical_wrap,
1231             unsigned centroid)
1232{
1233   union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 4);
1234
1235   out[0].value = 0;
1236   out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
1237   out[0].decl.NrTokens = 4;
1238   out[0].decl.File = file;
1239   out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; /* FIXME! */
1240   out[0].decl.Interpolate = 1;
1241   out[0].decl.Semantic = 1;
1242
1243   out[1].value = 0;
1244   out[1].decl_range.First = index;
1245   out[1].decl_range.Last = index;
1246
1247   out[2].value = 0;
1248   out[2].decl_interp.Interpolate = interpolate;
1249   out[2].decl_interp.CylindricalWrap = cylindrical_wrap;
1250   out[2].decl_interp.Centroid = centroid;
1251
1252   out[3].value = 0;
1253   out[3].decl_semantic.Name = semantic_name;
1254   out[3].decl_semantic.Index = semantic_index;
1255}
1256
1257
1258static void emit_decl_range( struct ureg_program *ureg,
1259                             unsigned file,
1260                             unsigned first,
1261                             unsigned count )
1262{
1263   union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 );
1264
1265   out[0].value = 0;
1266   out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
1267   out[0].decl.NrTokens = 2;
1268   out[0].decl.File = file;
1269   out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
1270   out[0].decl.Semantic = 0;
1271
1272   out[1].value = 0;
1273   out[1].decl_range.First = first;
1274   out[1].decl_range.Last = first + count - 1;
1275}
1276
1277static void
1278emit_decl_range2D(struct ureg_program *ureg,
1279                  unsigned file,
1280                  unsigned first,
1281                  unsigned last,
1282                  unsigned index2D)
1283{
1284   union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3);
1285
1286   out[0].value = 0;
1287   out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
1288   out[0].decl.NrTokens = 3;
1289   out[0].decl.File = file;
1290   out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
1291   out[0].decl.Dimension = 1;
1292
1293   out[1].value = 0;
1294   out[1].decl_range.First = first;
1295   out[1].decl_range.Last = last;
1296
1297   out[2].value = 0;
1298   out[2].decl_dim.Index2D = index2D;
1299}
1300
1301static void
1302emit_decl_sampler_view(struct ureg_program *ureg,
1303                       unsigned index,
1304                       unsigned target,
1305                       unsigned return_type_x,
1306                       unsigned return_type_y,
1307                       unsigned return_type_z,
1308                       unsigned return_type_w )
1309{
1310   union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3);
1311
1312   out[0].value = 0;
1313   out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
1314   out[0].decl.NrTokens = 3;
1315   out[0].decl.File = TGSI_FILE_SAMPLER_VIEW;
1316   out[0].decl.UsageMask = 0xf;
1317
1318   out[1].value = 0;
1319   out[1].decl_range.First = index;
1320   out[1].decl_range.Last = index;
1321
1322   out[2].value = 0;
1323   out[2].decl_sampler_view.Resource    = target;
1324   out[2].decl_sampler_view.ReturnTypeX = return_type_x;
1325   out[2].decl_sampler_view.ReturnTypeY = return_type_y;
1326   out[2].decl_sampler_view.ReturnTypeZ = return_type_z;
1327   out[2].decl_sampler_view.ReturnTypeW = return_type_w;
1328}
1329
1330static void
1331emit_immediate( struct ureg_program *ureg,
1332                const unsigned *v,
1333                unsigned type )
1334{
1335   union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 5 );
1336
1337   out[0].value = 0;
1338   out[0].imm.Type = TGSI_TOKEN_TYPE_IMMEDIATE;
1339   out[0].imm.NrTokens = 5;
1340   out[0].imm.DataType = type;
1341   out[0].imm.Padding = 0;
1342
1343   out[1].imm_data.Uint = v[0];
1344   out[2].imm_data.Uint = v[1];
1345   out[3].imm_data.Uint = v[2];
1346   out[4].imm_data.Uint = v[3];
1347}
1348
1349static void
1350emit_property(struct ureg_program *ureg,
1351              unsigned name,
1352              unsigned data)
1353{
1354   union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 2);
1355
1356   out[0].value = 0;
1357   out[0].prop.Type = TGSI_TOKEN_TYPE_PROPERTY;
1358   out[0].prop.NrTokens = 2;
1359   out[0].prop.PropertyName = name;
1360
1361   out[1].prop_data.Data = data;
1362}
1363
1364
1365static void emit_decls( struct ureg_program *ureg )
1366{
1367   unsigned i;
1368
1369   if (ureg->property_gs_input_prim != ~0) {
1370      assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY);
1371
1372      emit_property(ureg,
1373                    TGSI_PROPERTY_GS_INPUT_PRIM,
1374                    ureg->property_gs_input_prim);
1375   }
1376
1377   if (ureg->property_gs_output_prim != ~0) {
1378      assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY);
1379
1380      emit_property(ureg,
1381                    TGSI_PROPERTY_GS_OUTPUT_PRIM,
1382                    ureg->property_gs_output_prim);
1383   }
1384
1385   if (ureg->property_gs_max_vertices != ~0) {
1386      assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY);
1387
1388      emit_property(ureg,
1389                    TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES,
1390                    ureg->property_gs_max_vertices);
1391   }
1392
1393   if (ureg->property_fs_coord_origin) {
1394      assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT);
1395
1396      emit_property(ureg,
1397                    TGSI_PROPERTY_FS_COORD_ORIGIN,
1398                    ureg->property_fs_coord_origin);
1399   }
1400
1401   if (ureg->property_fs_coord_pixel_center) {
1402      assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT);
1403
1404      emit_property(ureg,
1405                    TGSI_PROPERTY_FS_COORD_PIXEL_CENTER,
1406                    ureg->property_fs_coord_pixel_center);
1407   }
1408
1409   if (ureg->property_fs_color0_writes_all_cbufs) {
1410      assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT);
1411
1412      emit_property(ureg,
1413                    TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS,
1414                    ureg->property_fs_color0_writes_all_cbufs);
1415   }
1416
1417   if (ureg->property_fs_depth_layout) {
1418      assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT);
1419
1420      emit_property(ureg,
1421                    TGSI_PROPERTY_FS_DEPTH_LAYOUT,
1422                    ureg->property_fs_depth_layout);
1423   }
1424
1425   if (ureg->processor == TGSI_PROCESSOR_VERTEX) {
1426      for (i = 0; i < UREG_MAX_INPUT; i++) {
1427         if (ureg->vs_inputs[i/32] & (1 << (i%32))) {
1428            emit_decl_range( ureg, TGSI_FILE_INPUT, i, 1 );
1429         }
1430      }
1431   } else if (ureg->processor == TGSI_PROCESSOR_FRAGMENT) {
1432      for (i = 0; i < ureg->nr_fs_inputs; i++) {
1433         emit_decl_fs(ureg,
1434                      TGSI_FILE_INPUT,
1435                      i,
1436                      ureg->fs_input[i].semantic_name,
1437                      ureg->fs_input[i].semantic_index,
1438                      ureg->fs_input[i].interp,
1439                      ureg->fs_input[i].cylindrical_wrap,
1440                      ureg->fs_input[i].centroid);
1441      }
1442   } else {
1443      for (i = 0; i < ureg->nr_gs_inputs; i++) {
1444         emit_decl_semantic(ureg,
1445                            TGSI_FILE_INPUT,
1446                            ureg->gs_input[i].index,
1447                            ureg->gs_input[i].semantic_name,
1448                            ureg->gs_input[i].semantic_index,
1449                            TGSI_WRITEMASK_XYZW);
1450      }
1451   }
1452
1453   for (i = 0; i < ureg->nr_system_values; i++) {
1454      emit_decl_semantic(ureg,
1455                         TGSI_FILE_SYSTEM_VALUE,
1456                         ureg->system_value[i].index,
1457                         ureg->system_value[i].semantic_name,
1458                         ureg->system_value[i].semantic_index,
1459                         TGSI_WRITEMASK_XYZW);
1460   }
1461
1462   for (i = 0; i < ureg->nr_outputs; i++) {
1463      emit_decl_semantic(ureg,
1464                         TGSI_FILE_OUTPUT,
1465                         i,
1466                         ureg->output[i].semantic_name,
1467                         ureg->output[i].semantic_index,
1468                         ureg->output[i].usage_mask);
1469   }
1470
1471   for (i = 0; i < ureg->nr_samplers; i++) {
1472      emit_decl_range( ureg,
1473                       TGSI_FILE_SAMPLER,
1474                       ureg->sampler[i].Index, 1 );
1475   }
1476
1477   for (i = 0; i < ureg->nr_sampler_views; i++) {
1478      emit_decl_sampler_view(ureg,
1479                             ureg->sampler_view[i].index,
1480                             ureg->sampler_view[i].target,
1481                             ureg->sampler_view[i].return_type_x,
1482                             ureg->sampler_view[i].return_type_y,
1483                             ureg->sampler_view[i].return_type_z,
1484                             ureg->sampler_view[i].return_type_w);
1485   }
1486
1487   if (ureg->const_decls.nr_constant_ranges) {
1488      for (i = 0; i < ureg->const_decls.nr_constant_ranges; i++) {
1489         emit_decl_range(ureg,
1490                         TGSI_FILE_CONSTANT,
1491                         ureg->const_decls.constant_range[i].first,
1492                         ureg->const_decls.constant_range[i].last - ureg->const_decls.constant_range[i].first + 1);
1493      }
1494   }
1495
1496   for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
1497      struct const_decl *decl = &ureg->const_decls2D[i];
1498
1499      if (decl->nr_constant_ranges) {
1500         uint j;
1501
1502         for (j = 0; j < decl->nr_constant_ranges; j++) {
1503            emit_decl_range2D(ureg,
1504                              TGSI_FILE_CONSTANT,
1505                              decl->constant_range[j].first,
1506                              decl->constant_range[j].last,
1507                              i);
1508         }
1509      }
1510   }
1511
1512   if (ureg->nr_temps) {
1513      emit_decl_range( ureg,
1514                       TGSI_FILE_TEMPORARY,
1515                       0, ureg->nr_temps );
1516   }
1517
1518   if (ureg->nr_addrs) {
1519      emit_decl_range( ureg,
1520                       TGSI_FILE_ADDRESS,
1521                       0, ureg->nr_addrs );
1522   }
1523
1524   if (ureg->nr_preds) {
1525      emit_decl_range(ureg,
1526                      TGSI_FILE_PREDICATE,
1527                      0,
1528                      ureg->nr_preds);
1529   }
1530
1531   for (i = 0; i < ureg->nr_immediates; i++) {
1532      emit_immediate( ureg,
1533                      ureg->immediate[i].value.u,
1534                      ureg->immediate[i].type );
1535   }
1536}
1537
1538/* Append the instruction tokens onto the declarations to build a
1539 * contiguous stream suitable to send to the driver.
1540 */
1541static void copy_instructions( struct ureg_program *ureg )
1542{
1543   unsigned nr_tokens = ureg->domain[DOMAIN_INSN].count;
1544   union tgsi_any_token *out = get_tokens( ureg,
1545                                           DOMAIN_DECL,
1546                                           nr_tokens );
1547
1548   memcpy(out,
1549          ureg->domain[DOMAIN_INSN].tokens,
1550          nr_tokens * sizeof out[0] );
1551}
1552
1553
1554static void
1555fixup_header_size(struct ureg_program *ureg)
1556{
1557   union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_DECL, 0 );
1558
1559   out->header.BodySize = ureg->domain[DOMAIN_DECL].count - 2;
1560}
1561
1562
1563static void
1564emit_header( struct ureg_program *ureg )
1565{
1566   union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 );
1567
1568   out[0].header.HeaderSize = 2;
1569   out[0].header.BodySize = 0;
1570
1571   out[1].processor.Processor = ureg->processor;
1572   out[1].processor.Padding = 0;
1573}
1574
1575
1576const struct tgsi_token *ureg_finalize( struct ureg_program *ureg )
1577{
1578   const struct tgsi_token *tokens;
1579
1580   emit_header( ureg );
1581   emit_decls( ureg );
1582   copy_instructions( ureg );
1583   fixup_header_size( ureg );
1584
1585   if (ureg->domain[0].tokens == error_tokens ||
1586       ureg->domain[1].tokens == error_tokens) {
1587      debug_printf("%s: error in generated shader\n", __FUNCTION__);
1588      assert(0);
1589      return NULL;
1590   }
1591
1592   tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token;
1593
1594   if (0) {
1595      debug_printf("%s: emitted shader %d tokens:\n", __FUNCTION__,
1596                   ureg->domain[DOMAIN_DECL].count);
1597      tgsi_dump( tokens, 0 );
1598   }
1599
1600#if DEBUG
1601   if (tokens && !tgsi_sanity_check(tokens)) {
1602      debug_printf("tgsi_ureg.c, sanity check failed on generated tokens:\n");
1603      tgsi_dump(tokens, 0);
1604      assert(0);
1605   }
1606#endif
1607
1608
1609   return tokens;
1610}
1611
1612
1613void *ureg_create_shader( struct ureg_program *ureg,
1614                          struct pipe_context *pipe,
1615                          const struct pipe_stream_output_info *so )
1616{
1617   struct pipe_shader_state state;
1618
1619   state.tokens = ureg_finalize(ureg);
1620   if(!state.tokens)
1621      return NULL;
1622
1623   if (so)
1624      state.stream_output = *so;
1625   else
1626      memset(&state.stream_output, 0, sizeof(state.stream_output));
1627
1628   if (ureg->processor == TGSI_PROCESSOR_VERTEX)
1629      return pipe->create_vs_state( pipe, &state );
1630   else
1631      return pipe->create_fs_state( pipe, &state );
1632}
1633
1634
1635const struct tgsi_token *ureg_get_tokens( struct ureg_program *ureg,
1636                                          unsigned *nr_tokens )
1637{
1638   const struct tgsi_token *tokens;
1639
1640   ureg_finalize(ureg);
1641
1642   tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token;
1643
1644   if (nr_tokens)
1645      *nr_tokens = ureg->domain[DOMAIN_DECL].size;
1646
1647   ureg->domain[DOMAIN_DECL].tokens = 0;
1648   ureg->domain[DOMAIN_DECL].size = 0;
1649   ureg->domain[DOMAIN_DECL].order = 0;
1650   ureg->domain[DOMAIN_DECL].count = 0;
1651
1652   return tokens;
1653}
1654
1655
1656void ureg_free_tokens( const struct tgsi_token *tokens )
1657{
1658   FREE((struct tgsi_token *)tokens);
1659}
1660
1661
1662struct ureg_program *ureg_create( unsigned processor )
1663{
1664   struct ureg_program *ureg = CALLOC_STRUCT( ureg_program );
1665   if (ureg == NULL)
1666      return NULL;
1667
1668   ureg->processor = processor;
1669   ureg->property_gs_input_prim = ~0;
1670   ureg->property_gs_output_prim = ~0;
1671   ureg->property_gs_max_vertices = ~0;
1672   return ureg;
1673}
1674
1675
1676void ureg_destroy( struct ureg_program *ureg )
1677{
1678   unsigned i;
1679
1680   for (i = 0; i < Elements(ureg->domain); i++) {
1681      if (ureg->domain[i].tokens &&
1682          ureg->domain[i].tokens != error_tokens)
1683         FREE(ureg->domain[i].tokens);
1684   }
1685
1686   FREE(ureg);
1687}
1688