gallium/tgsi: Move interpolation info from tgsi_declaration to a separate token.
[mesa.git] / src / gallium / auxiliary / tgsi / tgsi_ureg.c
1 /**************************************************************************
2 *
3 * Copyright 2009-2010 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE, INC AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29 #include "pipe/p_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
40 union 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
66 struct 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
82 struct 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
93 struct 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
175 static union tgsi_any_token error_tokens[32];
176
177 static 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
188 static 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
209 static void set_bad( struct ureg_program *ureg )
210 {
211 tokens_error(&ureg->domain[0]);
212 }
213
214
215
216 static 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
232 static 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
244 static INLINE struct ureg_dst
245 ureg_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
268 void
269 ureg_property_gs_input_prim(struct ureg_program *ureg,
270 unsigned input_prim)
271 {
272 ureg->property_gs_input_prim = input_prim;
273 }
274
275 void
276 ureg_property_gs_output_prim(struct ureg_program *ureg,
277 unsigned output_prim)
278 {
279 ureg->property_gs_output_prim = output_prim;
280 }
281
282 void
283 ureg_property_gs_max_vertices(struct ureg_program *ureg,
284 unsigned max_vertices)
285 {
286 ureg->property_gs_max_vertices = max_vertices;
287 }
288
289 void
290 ureg_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
296 void
297 ureg_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
303 void
304 ureg_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
310 void
311 ureg_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
317 struct ureg_src
318 ureg_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
345 out:
346 return ureg_src_register(TGSI_FILE_INPUT, i);
347 }
348
349
350 struct ureg_src
351 ureg_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
361 struct ureg_src
362 ureg_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
381 struct ureg_src
382 ureg_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
400 struct ureg_dst
401 ureg_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
428 out:
429 return ureg_dst_register( TGSI_FILE_OUTPUT, i );
430 }
431
432
433 struct ureg_dst
434 ureg_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 */
452 void
453 ureg_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 */
476 struct ureg_src
477 ureg_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
526 out:
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 */
537 struct 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
553 out:
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
564 void 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 */
575 struct 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 */
586 struct ureg_dst
587 ureg_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 */
599 struct 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 */
621 struct ureg_src
622 ureg_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
654 static int
655 match_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
694 static struct ureg_src
695 decl_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
734 out:
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
750 struct ureg_src
751 ureg_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
769 struct ureg_src
770 ureg_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
778 struct ureg_src
779 ureg_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
807 struct ureg_src
808 ureg_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
816 void
817 ureg_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
881 void
882 ureg_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
921 static 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
935 struct ureg_emit_insn_result
936 ureg_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
980 void
981 ureg_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 */
1002 unsigned
1003 ureg_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 */
1011 void
1012 ureg_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
1022 void
1023 ureg_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
1039 void
1040 ureg_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
1053 void
1054 ureg_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
1064 void
1065 ureg_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
1110 void
1111 ureg_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
1165 void
1166 ureg_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
1196 static void
1197 emit_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
1223 static void
1224 emit_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
1258 static 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
1277 static void
1278 emit_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
1301 static void
1302 emit_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
1330 static void
1331 emit_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
1349 static void
1350 emit_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
1365 static 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 */
1541 static 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
1554 static void
1555 fixup_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
1563 static void
1564 emit_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
1576 const 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
1613 void *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
1635 const 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
1656 void ureg_free_tokens( const struct tgsi_token *tokens )
1657 {
1658 FREE((struct tgsi_token *)tokens);
1659 }
1660
1661
1662 struct 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
1676 void 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 }