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