1 /**************************************************************************
3 * Copyright 2009-2010 VMware, Inc.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
29 #include "pipe/p_screen.h"
30 #include "pipe/p_context.h"
31 #include "pipe/p_state.h"
32 #include "tgsi/tgsi_ureg.h"
33 #include "tgsi/tgsi_build.h"
34 #include "tgsi/tgsi_info.h"
35 #include "tgsi/tgsi_dump.h"
36 #include "tgsi/tgsi_sanity.h"
37 #include "util/u_debug.h"
38 #include "util/u_inlines.h"
39 #include "util/u_memory.h"
40 #include "util/u_math.h"
41 #include "util/u_bitmask.h"
43 union tgsi_any_token
{
44 struct tgsi_header header
;
45 struct tgsi_processor processor
;
46 struct tgsi_token token
;
47 struct tgsi_property prop
;
48 struct tgsi_property_data prop_data
;
49 struct tgsi_declaration decl
;
50 struct tgsi_declaration_range decl_range
;
51 struct tgsi_declaration_dimension decl_dim
;
52 struct tgsi_declaration_interp decl_interp
;
53 struct tgsi_declaration_image decl_image
;
54 struct tgsi_declaration_semantic decl_semantic
;
55 struct tgsi_declaration_sampler_view decl_sampler_view
;
56 struct tgsi_declaration_array array
;
57 struct tgsi_immediate imm
;
58 union tgsi_immediate_data imm_data
;
59 struct tgsi_instruction insn
;
60 struct tgsi_instruction_predicate insn_predicate
;
61 struct tgsi_instruction_label insn_label
;
62 struct tgsi_instruction_texture insn_texture
;
63 struct tgsi_instruction_memory insn_memory
;
64 struct tgsi_texture_offset insn_texture_offset
;
65 struct tgsi_src_register src
;
66 struct tgsi_ind_register ind
;
67 struct tgsi_dimension dim
;
68 struct tgsi_dst_register dst
;
74 union tgsi_any_token
*tokens
;
80 #define UREG_MAX_INPUT (4 * PIPE_MAX_SHADER_INPUTS)
81 #define UREG_MAX_SYSTEM_VALUE PIPE_MAX_ATTRIBS
82 #define UREG_MAX_OUTPUT (4 * PIPE_MAX_SHADER_OUTPUTS)
83 #define UREG_MAX_CONSTANT_RANGE 32
84 #define UREG_MAX_IMMEDIATE 4096
85 #define UREG_MAX_ADDR 3
86 #define UREG_MAX_PRED 1
87 #define UREG_MAX_ARRAY_TEMPS 256
93 } constant_range
[UREG_MAX_CONSTANT_RANGE
];
94 unsigned nr_constant_ranges
;
103 bool supports_any_inout_decl_range
;
104 int next_shader_processor
;
107 unsigned semantic_name
;
108 unsigned semantic_index
;
110 unsigned char cylindrical_wrap
;
111 unsigned char usage_mask
;
112 unsigned interp_location
;
116 } input
[UREG_MAX_INPUT
];
117 unsigned nr_inputs
, nr_input_regs
;
119 unsigned vs_inputs
[PIPE_MAX_ATTRIBS
/32];
122 unsigned semantic_name
;
123 unsigned semantic_index
;
124 } system_value
[UREG_MAX_SYSTEM_VALUE
];
125 unsigned nr_system_values
;
128 unsigned semantic_name
;
129 unsigned semantic_index
;
131 unsigned usage_mask
; /* = TGSI_WRITEMASK_* */
135 } output
[UREG_MAX_OUTPUT
];
136 unsigned nr_outputs
, nr_output_regs
;
146 } immediate
[UREG_MAX_IMMEDIATE
];
147 unsigned nr_immediates
;
149 struct ureg_src sampler
[PIPE_MAX_SAMPLERS
];
150 unsigned nr_samplers
;
155 unsigned return_type_x
;
156 unsigned return_type_y
;
157 unsigned return_type_z
;
158 unsigned return_type_w
;
159 } sampler_view
[PIPE_MAX_SHADER_SAMPLER_VIEWS
];
160 unsigned nr_sampler_views
;
168 } image
[PIPE_MAX_SHADER_IMAGES
];
174 } buffer
[PIPE_MAX_SHADER_BUFFERS
];
177 struct util_bitmask
*free_temps
;
178 struct util_bitmask
*local_temps
;
179 struct util_bitmask
*decl_temps
;
182 unsigned array_temps
[UREG_MAX_ARRAY_TEMPS
];
183 unsigned nr_array_temps
;
185 struct const_decl const_decls
;
186 struct const_decl const_decls2D
[PIPE_MAX_CONSTANT_BUFFERS
];
188 unsigned properties
[TGSI_PROPERTY_COUNT
];
192 unsigned nr_instructions
;
194 struct ureg_tokens domain
[2];
196 bool use_memory
[TGSI_MEMORY_TYPE_COUNT
];
199 static union tgsi_any_token error_tokens
[32];
201 static void tokens_error( struct ureg_tokens
*tokens
)
203 if (tokens
->tokens
&& tokens
->tokens
!= error_tokens
)
204 FREE(tokens
->tokens
);
206 tokens
->tokens
= error_tokens
;
207 tokens
->size
= ARRAY_SIZE(error_tokens
);
212 static void tokens_expand( struct ureg_tokens
*tokens
,
215 unsigned old_size
= tokens
->size
* sizeof(unsigned);
217 if (tokens
->tokens
== error_tokens
) {
221 while (tokens
->count
+ count
> tokens
->size
) {
222 tokens
->size
= (1 << ++tokens
->order
);
225 tokens
->tokens
= REALLOC(tokens
->tokens
,
227 tokens
->size
* sizeof(unsigned));
228 if (tokens
->tokens
== NULL
) {
229 tokens_error(tokens
);
233 static void set_bad( struct ureg_program
*ureg
)
235 tokens_error(&ureg
->domain
[0]);
240 static union tgsi_any_token
*get_tokens( struct ureg_program
*ureg
,
244 struct ureg_tokens
*tokens
= &ureg
->domain
[domain
];
245 union tgsi_any_token
*result
;
247 if (tokens
->count
+ count
> tokens
->size
)
248 tokens_expand(tokens
, count
);
250 result
= &tokens
->tokens
[tokens
->count
];
251 tokens
->count
+= count
;
256 static union tgsi_any_token
*retrieve_token( struct ureg_program
*ureg
,
260 if (ureg
->domain
[domain
].tokens
== error_tokens
)
261 return &error_tokens
[0];
263 return &ureg
->domain
[domain
].tokens
[nr
];
267 ureg_property(struct ureg_program
*ureg
, unsigned name
, unsigned value
)
269 assert(name
< ARRAY_SIZE(ureg
->properties
));
270 ureg
->properties
[name
] = value
;
274 ureg_DECL_fs_input_cyl_centroid_layout(struct ureg_program
*ureg
,
275 unsigned semantic_name
,
276 unsigned semantic_index
,
277 unsigned interp_mode
,
278 unsigned cylindrical_wrap
,
279 unsigned interp_location
,
287 assert(usage_mask
!= 0);
288 assert(usage_mask
<= TGSI_WRITEMASK_XYZW
);
290 for (i
= 0; i
< ureg
->nr_inputs
; i
++) {
291 if (ureg
->input
[i
].semantic_name
== semantic_name
&&
292 ureg
->input
[i
].semantic_index
== semantic_index
) {
293 assert(ureg
->input
[i
].interp
== interp_mode
);
294 assert(ureg
->input
[i
].cylindrical_wrap
== cylindrical_wrap
);
295 assert(ureg
->input
[i
].interp_location
== interp_location
);
296 if (ureg
->input
[i
].array_id
== array_id
) {
297 ureg
->input
[i
].usage_mask
|= usage_mask
;
300 assert((ureg
->input
[i
].usage_mask
& usage_mask
) == 0);
304 if (ureg
->nr_inputs
< UREG_MAX_INPUT
) {
305 assert(array_size
>= 1);
306 ureg
->input
[i
].semantic_name
= semantic_name
;
307 ureg
->input
[i
].semantic_index
= semantic_index
;
308 ureg
->input
[i
].interp
= interp_mode
;
309 ureg
->input
[i
].cylindrical_wrap
= cylindrical_wrap
;
310 ureg
->input
[i
].interp_location
= interp_location
;
311 ureg
->input
[i
].first
= index
;
312 ureg
->input
[i
].last
= index
+ array_size
- 1;
313 ureg
->input
[i
].array_id
= array_id
;
314 ureg
->input
[i
].usage_mask
= usage_mask
;
315 ureg
->nr_input_regs
= MAX2(ureg
->nr_input_regs
, index
+ array_size
);
322 return ureg_src_array_register(TGSI_FILE_INPUT
, ureg
->input
[i
].first
,
327 ureg_DECL_fs_input_cyl_centroid(struct ureg_program
*ureg
,
328 unsigned semantic_name
,
329 unsigned semantic_index
,
330 unsigned interp_mode
,
331 unsigned cylindrical_wrap
,
332 unsigned interp_location
,
336 return ureg_DECL_fs_input_cyl_centroid_layout(ureg
,
337 semantic_name
, semantic_index
, interp_mode
, cylindrical_wrap
, interp_location
,
338 ureg
->nr_input_regs
, TGSI_WRITEMASK_XYZW
, array_id
, array_size
);
343 ureg_DECL_vs_input( struct ureg_program
*ureg
,
346 assert(ureg
->processor
== PIPE_SHADER_VERTEX
);
347 assert(index
/ 32 < ARRAY_SIZE(ureg
->vs_inputs
));
349 ureg
->vs_inputs
[index
/32] |= 1 << (index
% 32);
350 return ureg_src_register( TGSI_FILE_INPUT
, index
);
355 ureg_DECL_input_layout(struct ureg_program
*ureg
,
356 unsigned semantic_name
,
357 unsigned semantic_index
,
363 return ureg_DECL_fs_input_cyl_centroid_layout(ureg
,
364 semantic_name
, semantic_index
, 0, 0, 0,
365 index
, usage_mask
, array_id
, array_size
);
370 ureg_DECL_input(struct ureg_program
*ureg
,
371 unsigned semantic_name
,
372 unsigned semantic_index
,
376 return ureg_DECL_fs_input_cyl_centroid(ureg
, semantic_name
, semantic_index
,
377 0, 0, 0, array_id
, array_size
);
382 ureg_DECL_system_value(struct ureg_program
*ureg
,
383 unsigned semantic_name
,
384 unsigned semantic_index
)
388 for (i
= 0; i
< ureg
->nr_system_values
; i
++) {
389 if (ureg
->system_value
[i
].semantic_name
== semantic_name
&&
390 ureg
->system_value
[i
].semantic_index
== semantic_index
) {
395 if (ureg
->nr_system_values
< UREG_MAX_SYSTEM_VALUE
) {
396 ureg
->system_value
[ureg
->nr_system_values
].semantic_name
= semantic_name
;
397 ureg
->system_value
[ureg
->nr_system_values
].semantic_index
= semantic_index
;
398 i
= ureg
->nr_system_values
;
399 ureg
->nr_system_values
++;
405 return ureg_src_register(TGSI_FILE_SYSTEM_VALUE
, i
);
410 ureg_DECL_output_layout(struct ureg_program
*ureg
,
411 unsigned semantic_name
,
412 unsigned semantic_index
,
421 assert(usage_mask
!= 0);
422 assert(!(streams
& 0x03) || (usage_mask
& 1));
423 assert(!(streams
& 0x0c) || (usage_mask
& 2));
424 assert(!(streams
& 0x30) || (usage_mask
& 4));
425 assert(!(streams
& 0xc0) || (usage_mask
& 8));
427 for (i
= 0; i
< ureg
->nr_outputs
; i
++) {
428 if (ureg
->output
[i
].semantic_name
== semantic_name
&&
429 ureg
->output
[i
].semantic_index
== semantic_index
) {
430 if (ureg
->output
[i
].array_id
== array_id
) {
431 ureg
->output
[i
].usage_mask
|= usage_mask
;
434 assert((ureg
->output
[i
].usage_mask
& usage_mask
) == 0);
438 if (ureg
->nr_outputs
< UREG_MAX_OUTPUT
) {
439 ureg
->output
[i
].semantic_name
= semantic_name
;
440 ureg
->output
[i
].semantic_index
= semantic_index
;
441 ureg
->output
[i
].usage_mask
= usage_mask
;
442 ureg
->output
[i
].first
= index
;
443 ureg
->output
[i
].last
= index
+ array_size
- 1;
444 ureg
->output
[i
].array_id
= array_id
;
445 ureg
->nr_output_regs
= MAX2(ureg
->nr_output_regs
, index
+ array_size
);
454 ureg
->output
[i
].streams
|= streams
;
456 return ureg_dst_array_register(TGSI_FILE_OUTPUT
, ureg
->output
[i
].first
,
462 ureg_DECL_output_masked(struct ureg_program
*ureg
,
469 return ureg_DECL_output_layout(ureg
, name
, index
, 0,
470 ureg
->nr_output_regs
, usage_mask
, array_id
, array_size
);
475 ureg_DECL_output(struct ureg_program
*ureg
,
479 return ureg_DECL_output_masked(ureg
, name
, index
, TGSI_WRITEMASK_XYZW
,
484 ureg_DECL_output_array(struct ureg_program
*ureg
,
485 unsigned semantic_name
,
486 unsigned semantic_index
,
490 return ureg_DECL_output_masked(ureg
, semantic_name
, semantic_index
,
492 array_id
, array_size
);
496 /* Returns a new constant register. Keep track of which have been
497 * referred to so that we can emit decls later.
499 * Constant operands declared with this function must be addressed
500 * with a two-dimensional index.
502 * There is nothing in this code to bind this constant to any tracked
503 * value or manage any constant_buffer contents -- that's the
504 * resposibility of the calling code.
507 ureg_DECL_constant2D(struct ureg_program
*ureg
,
512 struct const_decl
*decl
= &ureg
->const_decls2D
[index2D
];
514 assert(index2D
< PIPE_MAX_CONSTANT_BUFFERS
);
516 if (decl
->nr_constant_ranges
< UREG_MAX_CONSTANT_RANGE
) {
517 uint i
= decl
->nr_constant_ranges
++;
519 decl
->constant_range
[i
].first
= first
;
520 decl
->constant_range
[i
].last
= last
;
525 /* A one-dimensional, deprecated version of ureg_DECL_constant2D().
527 * Constant operands declared with this function must be addressed
528 * with a one-dimensional index.
531 ureg_DECL_constant(struct ureg_program
*ureg
,
534 struct const_decl
*decl
= &ureg
->const_decls
;
535 unsigned minconst
= index
, maxconst
= index
;
538 /* Inside existing range?
540 for (i
= 0; i
< decl
->nr_constant_ranges
; i
++) {
541 if (decl
->constant_range
[i
].first
<= index
&&
542 decl
->constant_range
[i
].last
>= index
) {
547 /* Extend existing range?
549 for (i
= 0; i
< decl
->nr_constant_ranges
; i
++) {
550 if (decl
->constant_range
[i
].last
== index
- 1) {
551 decl
->constant_range
[i
].last
= index
;
555 if (decl
->constant_range
[i
].first
== index
+ 1) {
556 decl
->constant_range
[i
].first
= index
;
560 minconst
= MIN2(minconst
, decl
->constant_range
[i
].first
);
561 maxconst
= MAX2(maxconst
, decl
->constant_range
[i
].last
);
566 if (decl
->nr_constant_ranges
< UREG_MAX_CONSTANT_RANGE
) {
567 i
= decl
->nr_constant_ranges
++;
568 decl
->constant_range
[i
].first
= index
;
569 decl
->constant_range
[i
].last
= index
;
573 /* Collapse all ranges down to one:
576 decl
->constant_range
[0].first
= minconst
;
577 decl
->constant_range
[0].last
= maxconst
;
578 decl
->nr_constant_ranges
= 1;
581 assert(i
< decl
->nr_constant_ranges
);
582 assert(decl
->constant_range
[i
].first
<= index
);
583 assert(decl
->constant_range
[i
].last
>= index
);
584 return ureg_src_register(TGSI_FILE_CONSTANT
, index
);
587 static struct ureg_dst
alloc_temporary( struct ureg_program
*ureg
,
592 /* Look for a released temporary.
594 for (i
= util_bitmask_get_first_index(ureg
->free_temps
);
595 i
!= UTIL_BITMASK_INVALID_INDEX
;
596 i
= util_bitmask_get_next_index(ureg
->free_temps
, i
+ 1)) {
597 if (util_bitmask_get(ureg
->local_temps
, i
) == local
)
601 /* Or allocate a new one.
603 if (i
== UTIL_BITMASK_INVALID_INDEX
) {
604 i
= ureg
->nr_temps
++;
607 util_bitmask_set(ureg
->local_temps
, i
);
609 /* Start a new declaration when the local flag changes */
610 if (!i
|| util_bitmask_get(ureg
->local_temps
, i
- 1) != local
)
611 util_bitmask_set(ureg
->decl_temps
, i
);
614 util_bitmask_clear(ureg
->free_temps
, i
);
616 return ureg_dst_register( TGSI_FILE_TEMPORARY
, i
);
619 struct ureg_dst
ureg_DECL_temporary( struct ureg_program
*ureg
)
621 return alloc_temporary(ureg
, FALSE
);
624 struct ureg_dst
ureg_DECL_local_temporary( struct ureg_program
*ureg
)
626 return alloc_temporary(ureg
, TRUE
);
629 struct ureg_dst
ureg_DECL_array_temporary( struct ureg_program
*ureg
,
633 unsigned i
= ureg
->nr_temps
;
634 struct ureg_dst dst
= ureg_dst_register( TGSI_FILE_TEMPORARY
, i
);
637 util_bitmask_set(ureg
->local_temps
, i
);
639 /* Always start a new declaration at the start */
640 util_bitmask_set(ureg
->decl_temps
, i
);
642 ureg
->nr_temps
+= size
;
644 /* and also at the end of the array */
645 util_bitmask_set(ureg
->decl_temps
, ureg
->nr_temps
);
647 if (ureg
->nr_array_temps
< UREG_MAX_ARRAY_TEMPS
) {
648 ureg
->array_temps
[ureg
->nr_array_temps
++] = i
;
649 dst
.ArrayID
= ureg
->nr_array_temps
;
655 void ureg_release_temporary( struct ureg_program
*ureg
,
656 struct ureg_dst tmp
)
658 if(tmp
.File
== TGSI_FILE_TEMPORARY
)
659 util_bitmask_set(ureg
->free_temps
, tmp
.Index
);
663 /* Allocate a new address register.
665 struct ureg_dst
ureg_DECL_address( struct ureg_program
*ureg
)
667 if (ureg
->nr_addrs
< UREG_MAX_ADDR
)
668 return ureg_dst_register( TGSI_FILE_ADDRESS
, ureg
->nr_addrs
++ );
671 return ureg_dst_register( TGSI_FILE_ADDRESS
, 0 );
674 /* Allocate a new predicate register.
677 ureg_DECL_predicate(struct ureg_program
*ureg
)
679 if (ureg
->nr_preds
< UREG_MAX_PRED
) {
680 return ureg_dst_register(TGSI_FILE_PREDICATE
, ureg
->nr_preds
++);
684 return ureg_dst_register(TGSI_FILE_PREDICATE
, 0);
687 /* Allocate a new sampler.
689 struct ureg_src
ureg_DECL_sampler( struct ureg_program
*ureg
,
694 for (i
= 0; i
< ureg
->nr_samplers
; i
++)
695 if (ureg
->sampler
[i
].Index
== nr
)
696 return ureg
->sampler
[i
];
698 if (i
< PIPE_MAX_SAMPLERS
) {
699 ureg
->sampler
[i
] = ureg_src_register( TGSI_FILE_SAMPLER
, nr
);
701 return ureg
->sampler
[i
];
705 return ureg
->sampler
[0];
709 * Allocate a new shader sampler view.
712 ureg_DECL_sampler_view(struct ureg_program
*ureg
,
715 unsigned return_type_x
,
716 unsigned return_type_y
,
717 unsigned return_type_z
,
718 unsigned return_type_w
)
720 struct ureg_src reg
= ureg_src_register(TGSI_FILE_SAMPLER_VIEW
, index
);
723 for (i
= 0; i
< ureg
->nr_sampler_views
; i
++) {
724 if (ureg
->sampler_view
[i
].index
== index
) {
729 if (i
< PIPE_MAX_SHADER_SAMPLER_VIEWS
) {
730 ureg
->sampler_view
[i
].index
= index
;
731 ureg
->sampler_view
[i
].target
= target
;
732 ureg
->sampler_view
[i
].return_type_x
= return_type_x
;
733 ureg
->sampler_view
[i
].return_type_y
= return_type_y
;
734 ureg
->sampler_view
[i
].return_type_z
= return_type_z
;
735 ureg
->sampler_view
[i
].return_type_w
= return_type_w
;
736 ureg
->nr_sampler_views
++;
744 /* Allocate a new image.
747 ureg_DECL_image(struct ureg_program
*ureg
,
754 struct ureg_src reg
= ureg_src_register(TGSI_FILE_IMAGE
, index
);
757 for (i
= 0; i
< ureg
->nr_images
; i
++)
758 if (ureg
->image
[i
].index
== index
)
761 if (i
< PIPE_MAX_SHADER_IMAGES
) {
762 ureg
->image
[i
].index
= index
;
763 ureg
->image
[i
].target
= target
;
764 ureg
->image
[i
].wr
= wr
;
765 ureg
->image
[i
].raw
= raw
;
766 ureg
->image
[i
].format
= format
;
775 /* Allocate a new buffer.
777 struct ureg_src
ureg_DECL_buffer(struct ureg_program
*ureg
, unsigned nr
,
780 struct ureg_src reg
= ureg_src_register(TGSI_FILE_BUFFER
, nr
);
783 for (i
= 0; i
< ureg
->nr_buffers
; i
++)
784 if (ureg
->buffer
[i
].index
== nr
)
787 if (i
< PIPE_MAX_SHADER_BUFFERS
) {
788 ureg
->buffer
[i
].index
= nr
;
789 ureg
->buffer
[i
].atomic
= atomic
;
798 /* Allocate a memory area.
800 struct ureg_src
ureg_DECL_memory(struct ureg_program
*ureg
,
801 unsigned memory_type
)
803 struct ureg_src reg
= ureg_src_register(TGSI_FILE_MEMORY
, memory_type
);
805 ureg
->use_memory
[memory_type
] = true;
810 match_or_expand_immediate64( const unsigned *v
,
817 unsigned nr2
= *pnr2
;
821 for (i
= 0; i
< nr
; i
+= 2) {
822 boolean found
= FALSE
;
824 for (j
= 0; j
< nr2
&& !found
; j
+= 2) {
825 if (v
[i
] == v2
[j
] && v
[i
+ 1] == v2
[j
+ 1]) {
826 *swizzle
|= (j
<< (i
* 2)) | ((j
+ 1) << ((i
+ 1) * 2));
836 v2
[nr2
+ 1] = v
[i
+ 1];
838 *swizzle
|= (nr2
<< (i
* 2)) | ((nr2
+ 1) << ((i
+ 1) * 2));
843 /* Actually expand immediate only when fully succeeded.
850 match_or_expand_immediate( const unsigned *v
,
857 unsigned nr2
= *pnr2
;
860 if (type
== TGSI_IMM_FLOAT64
||
861 type
== TGSI_IMM_UINT64
||
862 type
== TGSI_IMM_INT64
)
863 return match_or_expand_immediate64(v
, type
, nr
, v2
, pnr2
, swizzle
);
867 for (i
= 0; i
< nr
; i
++) {
868 boolean found
= FALSE
;
870 for (j
= 0; j
< nr2
&& !found
; j
++) {
872 *swizzle
|= j
<< (i
* 2);
883 *swizzle
|= nr2
<< (i
* 2);
888 /* Actually expand immediate only when fully succeeded.
895 static struct ureg_src
896 decl_immediate( struct ureg_program
*ureg
,
902 unsigned swizzle
= 0;
904 /* Could do a first pass where we examine all existing immediates
908 for (i
= 0; i
< ureg
->nr_immediates
; i
++) {
909 if (ureg
->immediate
[i
].type
!= type
) {
912 if (match_or_expand_immediate(v
,
915 ureg
->immediate
[i
].value
.u
,
916 &ureg
->immediate
[i
].nr
,
922 if (ureg
->nr_immediates
< UREG_MAX_IMMEDIATE
) {
923 i
= ureg
->nr_immediates
++;
924 ureg
->immediate
[i
].type
= type
;
925 if (match_or_expand_immediate(v
,
928 ureg
->immediate
[i
].value
.u
,
929 &ureg
->immediate
[i
].nr
,
938 /* Make sure that all referenced elements are from this immediate.
939 * Has the effect of making size-one immediates into scalars.
941 if (type
== TGSI_IMM_FLOAT64
||
942 type
== TGSI_IMM_UINT64
||
943 type
== TGSI_IMM_INT64
) {
944 for (j
= nr
; j
< 4; j
+=2) {
945 swizzle
|= (swizzle
& 0xf) << (j
* 2);
948 for (j
= nr
; j
< 4; j
++) {
949 swizzle
|= (swizzle
& 0x3) << (j
* 2);
952 return ureg_swizzle(ureg_src_register(TGSI_FILE_IMMEDIATE
, i
),
953 (swizzle
>> 0) & 0x3,
954 (swizzle
>> 2) & 0x3,
955 (swizzle
>> 4) & 0x3,
956 (swizzle
>> 6) & 0x3);
961 ureg_DECL_immediate( struct ureg_program
*ureg
,
971 for (i
= 0; i
< nr
; i
++) {
975 return decl_immediate(ureg
, fu
.u
, nr
, TGSI_IMM_FLOAT32
);
979 ureg_DECL_immediate_f64( struct ureg_program
*ureg
,
989 assert((nr
/ 2) < 3);
990 for (i
= 0; i
< nr
/ 2; i
++) {
994 return decl_immediate(ureg
, fu
.u
, nr
, TGSI_IMM_FLOAT64
);
998 ureg_DECL_immediate_uint( struct ureg_program
*ureg
,
1002 return decl_immediate(ureg
, v
, nr
, TGSI_IMM_UINT32
);
1007 ureg_DECL_immediate_block_uint( struct ureg_program
*ureg
,
1014 if (ureg
->nr_immediates
+ (nr
+ 3) / 4 > UREG_MAX_IMMEDIATE
) {
1016 return ureg_src_register(TGSI_FILE_IMMEDIATE
, 0);
1019 index
= ureg
->nr_immediates
;
1020 ureg
->nr_immediates
+= (nr
+ 3) / 4;
1022 for (i
= index
; i
< ureg
->nr_immediates
; i
++) {
1023 ureg
->immediate
[i
].type
= TGSI_IMM_UINT32
;
1024 ureg
->immediate
[i
].nr
= nr
> 4 ? 4 : nr
;
1025 memcpy(ureg
->immediate
[i
].value
.u
,
1026 &v
[(i
- index
) * 4],
1027 ureg
->immediate
[i
].nr
* sizeof(uint
));
1031 return ureg_src_register(TGSI_FILE_IMMEDIATE
, index
);
1036 ureg_DECL_immediate_int( struct ureg_program
*ureg
,
1040 return decl_immediate(ureg
, (const unsigned *)v
, nr
, TGSI_IMM_INT32
);
1044 ureg_DECL_immediate_uint64( struct ureg_program
*ureg
,
1054 assert((nr
/ 2) < 3);
1055 for (i
= 0; i
< nr
/ 2; i
++) {
1059 return decl_immediate(ureg
, fu
.u
, nr
, TGSI_IMM_UINT64
);
1063 ureg_DECL_immediate_int64( struct ureg_program
*ureg
,
1073 assert((nr
/ 2) < 3);
1074 for (i
= 0; i
< nr
/ 2; i
++) {
1078 return decl_immediate(ureg
, fu
.u
, nr
, TGSI_IMM_INT64
);
1082 ureg_emit_src( struct ureg_program
*ureg
,
1083 struct ureg_src src
)
1085 unsigned size
= 1 + (src
.Indirect
? 1 : 0) +
1086 (src
.Dimension
? (src
.DimIndirect
? 2 : 1) : 0);
1088 union tgsi_any_token
*out
= get_tokens( ureg
, DOMAIN_INSN
, size
);
1091 assert(src
.File
!= TGSI_FILE_NULL
);
1092 assert(src
.File
< TGSI_FILE_COUNT
);
1095 out
[n
].src
.File
= src
.File
;
1096 out
[n
].src
.SwizzleX
= src
.SwizzleX
;
1097 out
[n
].src
.SwizzleY
= src
.SwizzleY
;
1098 out
[n
].src
.SwizzleZ
= src
.SwizzleZ
;
1099 out
[n
].src
.SwizzleW
= src
.SwizzleW
;
1100 out
[n
].src
.Index
= src
.Index
;
1101 out
[n
].src
.Negate
= src
.Negate
;
1102 out
[0].src
.Absolute
= src
.Absolute
;
1106 out
[0].src
.Indirect
= 1;
1108 out
[n
].ind
.File
= src
.IndirectFile
;
1109 out
[n
].ind
.Swizzle
= src
.IndirectSwizzle
;
1110 out
[n
].ind
.Index
= src
.IndirectIndex
;
1111 if (!ureg
->supports_any_inout_decl_range
&&
1112 (src
.File
== TGSI_FILE_INPUT
|| src
.File
== TGSI_FILE_OUTPUT
))
1113 out
[n
].ind
.ArrayID
= 0;
1115 out
[n
].ind
.ArrayID
= src
.ArrayID
;
1119 if (src
.Dimension
) {
1120 out
[0].src
.Dimension
= 1;
1121 out
[n
].dim
.Dimension
= 0;
1122 out
[n
].dim
.Padding
= 0;
1123 if (src
.DimIndirect
) {
1124 out
[n
].dim
.Indirect
= 1;
1125 out
[n
].dim
.Index
= src
.DimensionIndex
;
1128 out
[n
].ind
.File
= src
.DimIndFile
;
1129 out
[n
].ind
.Swizzle
= src
.DimIndSwizzle
;
1130 out
[n
].ind
.Index
= src
.DimIndIndex
;
1131 if (!ureg
->supports_any_inout_decl_range
&&
1132 (src
.File
== TGSI_FILE_INPUT
|| src
.File
== TGSI_FILE_OUTPUT
))
1133 out
[n
].ind
.ArrayID
= 0;
1135 out
[n
].ind
.ArrayID
= src
.ArrayID
;
1137 out
[n
].dim
.Indirect
= 0;
1138 out
[n
].dim
.Index
= src
.DimensionIndex
;
1148 ureg_emit_dst( struct ureg_program
*ureg
,
1149 struct ureg_dst dst
)
1151 unsigned size
= 1 + (dst
.Indirect
? 1 : 0) +
1152 (dst
.Dimension
? (dst
.DimIndirect
? 2 : 1) : 0);
1154 union tgsi_any_token
*out
= get_tokens( ureg
, DOMAIN_INSN
, size
);
1157 assert(dst
.File
!= TGSI_FILE_NULL
);
1158 assert(dst
.File
!= TGSI_FILE_CONSTANT
);
1159 assert(dst
.File
!= TGSI_FILE_INPUT
);
1160 assert(dst
.File
!= TGSI_FILE_SAMPLER
);
1161 assert(dst
.File
!= TGSI_FILE_SAMPLER_VIEW
);
1162 assert(dst
.File
!= TGSI_FILE_IMMEDIATE
);
1163 assert(dst
.File
< TGSI_FILE_COUNT
);
1166 out
[n
].dst
.File
= dst
.File
;
1167 out
[n
].dst
.WriteMask
= dst
.WriteMask
;
1168 out
[n
].dst
.Indirect
= dst
.Indirect
;
1169 out
[n
].dst
.Index
= dst
.Index
;
1174 out
[n
].ind
.File
= dst
.IndirectFile
;
1175 out
[n
].ind
.Swizzle
= dst
.IndirectSwizzle
;
1176 out
[n
].ind
.Index
= dst
.IndirectIndex
;
1177 if (!ureg
->supports_any_inout_decl_range
&&
1178 (dst
.File
== TGSI_FILE_INPUT
|| dst
.File
== TGSI_FILE_OUTPUT
))
1179 out
[n
].ind
.ArrayID
= 0;
1181 out
[n
].ind
.ArrayID
= dst
.ArrayID
;
1185 if (dst
.Dimension
) {
1186 out
[0].dst
.Dimension
= 1;
1187 out
[n
].dim
.Dimension
= 0;
1188 out
[n
].dim
.Padding
= 0;
1189 if (dst
.DimIndirect
) {
1190 out
[n
].dim
.Indirect
= 1;
1191 out
[n
].dim
.Index
= dst
.DimensionIndex
;
1194 out
[n
].ind
.File
= dst
.DimIndFile
;
1195 out
[n
].ind
.Swizzle
= dst
.DimIndSwizzle
;
1196 out
[n
].ind
.Index
= dst
.DimIndIndex
;
1197 if (!ureg
->supports_any_inout_decl_range
&&
1198 (dst
.File
== TGSI_FILE_INPUT
|| dst
.File
== TGSI_FILE_OUTPUT
))
1199 out
[n
].ind
.ArrayID
= 0;
1201 out
[n
].ind
.ArrayID
= dst
.ArrayID
;
1203 out
[n
].dim
.Indirect
= 0;
1204 out
[n
].dim
.Index
= dst
.DimensionIndex
;
1213 static void validate( unsigned opcode
,
1218 const struct tgsi_opcode_info
*info
= tgsi_get_opcode_info( opcode
);
1221 assert(nr_dst
== info
->num_dst
);
1222 assert(nr_src
== info
->num_src
);
1227 struct ureg_emit_insn_result
1228 ureg_emit_insn(struct ureg_program
*ureg
,
1232 boolean pred_negate
,
1233 unsigned pred_swizzle_x
,
1234 unsigned pred_swizzle_y
,
1235 unsigned pred_swizzle_z
,
1236 unsigned pred_swizzle_w
,
1240 union tgsi_any_token
*out
;
1241 uint count
= predicate
? 2 : 1;
1242 struct ureg_emit_insn_result result
;
1244 validate( opcode
, num_dst
, num_src
);
1246 out
= get_tokens( ureg
, DOMAIN_INSN
, count
);
1247 out
[0].insn
= tgsi_default_instruction();
1248 out
[0].insn
.Opcode
= opcode
;
1249 out
[0].insn
.Saturate
= saturate
;
1250 out
[0].insn
.NumDstRegs
= num_dst
;
1251 out
[0].insn
.NumSrcRegs
= num_src
;
1253 result
.insn_token
= ureg
->domain
[DOMAIN_INSN
].count
- count
;
1254 result
.extended_token
= result
.insn_token
;
1257 out
[0].insn
.Predicate
= 1;
1258 out
[1].insn_predicate
= tgsi_default_instruction_predicate();
1259 out
[1].insn_predicate
.Negate
= pred_negate
;
1260 out
[1].insn_predicate
.SwizzleX
= pred_swizzle_x
;
1261 out
[1].insn_predicate
.SwizzleY
= pred_swizzle_y
;
1262 out
[1].insn_predicate
.SwizzleZ
= pred_swizzle_z
;
1263 out
[1].insn_predicate
.SwizzleW
= pred_swizzle_w
;
1266 ureg
->nr_instructions
++;
1273 * Emit a label token.
1274 * \param label_token returns a token number indicating where the label
1275 * needs to be patched later. Later, this value should be passed to the
1276 * ureg_fixup_label() function.
1279 ureg_emit_label(struct ureg_program
*ureg
,
1280 unsigned extended_token
,
1281 unsigned *label_token
)
1283 union tgsi_any_token
*out
, *insn
;
1288 out
= get_tokens( ureg
, DOMAIN_INSN
, 1 );
1291 insn
= retrieve_token( ureg
, DOMAIN_INSN
, extended_token
);
1292 insn
->insn
.Label
= 1;
1294 *label_token
= ureg
->domain
[DOMAIN_INSN
].count
- 1;
1297 /* Will return a number which can be used in a label to point to the
1298 * next instruction to be emitted.
1301 ureg_get_instruction_number( struct ureg_program
*ureg
)
1303 return ureg
->nr_instructions
;
1306 /* Patch a given label (expressed as a token number) to point to a
1307 * given instruction (expressed as an instruction number).
1310 ureg_fixup_label(struct ureg_program
*ureg
,
1311 unsigned label_token
,
1312 unsigned instruction_number
)
1314 union tgsi_any_token
*out
= retrieve_token( ureg
, DOMAIN_INSN
, label_token
);
1316 out
->insn_label
.Label
= instruction_number
;
1321 ureg_emit_texture(struct ureg_program
*ureg
,
1322 unsigned extended_token
,
1323 unsigned target
, unsigned num_offsets
)
1325 union tgsi_any_token
*out
, *insn
;
1327 out
= get_tokens( ureg
, DOMAIN_INSN
, 1 );
1328 insn
= retrieve_token( ureg
, DOMAIN_INSN
, extended_token
);
1330 insn
->insn
.Texture
= 1;
1333 out
[0].insn_texture
.Texture
= target
;
1334 out
[0].insn_texture
.NumOffsets
= num_offsets
;
1338 ureg_emit_texture_offset(struct ureg_program
*ureg
,
1339 const struct tgsi_texture_offset
*offset
)
1341 union tgsi_any_token
*out
;
1343 out
= get_tokens( ureg
, DOMAIN_INSN
, 1);
1346 out
[0].insn_texture_offset
= *offset
;
1351 ureg_emit_memory(struct ureg_program
*ureg
,
1352 unsigned extended_token
,
1357 union tgsi_any_token
*out
, *insn
;
1359 out
= get_tokens( ureg
, DOMAIN_INSN
, 1 );
1360 insn
= retrieve_token( ureg
, DOMAIN_INSN
, extended_token
);
1362 insn
->insn
.Memory
= 1;
1365 out
[0].insn_memory
.Qualifier
= qualifier
;
1366 out
[0].insn_memory
.Texture
= texture
;
1367 out
[0].insn_memory
.Format
= format
;
1371 ureg_fixup_insn_size(struct ureg_program
*ureg
,
1374 union tgsi_any_token
*out
= retrieve_token( ureg
, DOMAIN_INSN
, insn
);
1376 assert(out
->insn
.Type
== TGSI_TOKEN_TYPE_INSTRUCTION
);
1377 out
->insn
.NrTokens
= ureg
->domain
[DOMAIN_INSN
].count
- insn
- 1;
1382 ureg_insn(struct ureg_program
*ureg
,
1384 const struct ureg_dst
*dst
,
1386 const struct ureg_src
*src
,
1389 struct ureg_emit_insn_result insn
;
1393 boolean negate
= FALSE
;
1394 unsigned swizzle
[4] = { 0 };
1396 if (nr_dst
&& ureg_dst_is_empty(dst
[0])) {
1400 saturate
= nr_dst
? dst
[0].Saturate
: FALSE
;
1401 predicate
= nr_dst
? dst
[0].Predicate
: FALSE
;
1403 negate
= dst
[0].PredNegate
;
1404 swizzle
[0] = dst
[0].PredSwizzleX
;
1405 swizzle
[1] = dst
[0].PredSwizzleY
;
1406 swizzle
[2] = dst
[0].PredSwizzleZ
;
1407 swizzle
[3] = dst
[0].PredSwizzleW
;
1410 insn
= ureg_emit_insn(ureg
,
1422 for (i
= 0; i
< nr_dst
; i
++)
1423 ureg_emit_dst( ureg
, dst
[i
] );
1425 for (i
= 0; i
< nr_src
; i
++)
1426 ureg_emit_src( ureg
, src
[i
] );
1428 ureg_fixup_insn_size( ureg
, insn
.insn_token
);
1432 ureg_tex_insn(struct ureg_program
*ureg
,
1434 const struct ureg_dst
*dst
,
1437 const struct tgsi_texture_offset
*texoffsets
,
1439 const struct ureg_src
*src
,
1442 struct ureg_emit_insn_result insn
;
1446 boolean negate
= FALSE
;
1447 unsigned swizzle
[4] = { 0 };
1449 if (nr_dst
&& ureg_dst_is_empty(dst
[0])) {
1453 saturate
= nr_dst
? dst
[0].Saturate
: FALSE
;
1454 predicate
= nr_dst
? dst
[0].Predicate
: FALSE
;
1456 negate
= dst
[0].PredNegate
;
1457 swizzle
[0] = dst
[0].PredSwizzleX
;
1458 swizzle
[1] = dst
[0].PredSwizzleY
;
1459 swizzle
[2] = dst
[0].PredSwizzleZ
;
1460 swizzle
[3] = dst
[0].PredSwizzleW
;
1463 insn
= ureg_emit_insn(ureg
,
1475 ureg_emit_texture( ureg
, insn
.extended_token
, target
, nr_offset
);
1477 for (i
= 0; i
< nr_offset
; i
++)
1478 ureg_emit_texture_offset( ureg
, &texoffsets
[i
]);
1480 for (i
= 0; i
< nr_dst
; i
++)
1481 ureg_emit_dst( ureg
, dst
[i
] );
1483 for (i
= 0; i
< nr_src
; i
++)
1484 ureg_emit_src( ureg
, src
[i
] );
1486 ureg_fixup_insn_size( ureg
, insn
.insn_token
);
1491 ureg_memory_insn(struct ureg_program
*ureg
,
1493 const struct ureg_dst
*dst
,
1495 const struct ureg_src
*src
,
1501 struct ureg_emit_insn_result insn
;
1504 insn
= ureg_emit_insn(ureg
,
1516 ureg_emit_memory(ureg
, insn
.extended_token
, qualifier
, texture
, format
);
1518 for (i
= 0; i
< nr_dst
; i
++)
1519 ureg_emit_dst(ureg
, dst
[i
]);
1521 for (i
= 0; i
< nr_src
; i
++)
1522 ureg_emit_src(ureg
, src
[i
]);
1524 ureg_fixup_insn_size(ureg
, insn
.insn_token
);
1529 emit_decl_semantic(struct ureg_program
*ureg
,
1533 unsigned semantic_name
,
1534 unsigned semantic_index
,
1536 unsigned usage_mask
,
1539 union tgsi_any_token
*out
= get_tokens(ureg
, DOMAIN_DECL
, array_id
? 4 : 3);
1542 out
[0].decl
.Type
= TGSI_TOKEN_TYPE_DECLARATION
;
1543 out
[0].decl
.NrTokens
= 3;
1544 out
[0].decl
.File
= file
;
1545 out
[0].decl
.UsageMask
= usage_mask
;
1546 out
[0].decl
.Semantic
= 1;
1547 out
[0].decl
.Array
= array_id
!= 0;
1550 out
[1].decl_range
.First
= first
;
1551 out
[1].decl_range
.Last
= last
;
1554 out
[2].decl_semantic
.Name
= semantic_name
;
1555 out
[2].decl_semantic
.Index
= semantic_index
;
1556 out
[2].decl_semantic
.StreamX
= streams
& 3;
1557 out
[2].decl_semantic
.StreamY
= (streams
>> 2) & 3;
1558 out
[2].decl_semantic
.StreamZ
= (streams
>> 4) & 3;
1559 out
[2].decl_semantic
.StreamW
= (streams
>> 6) & 3;
1563 out
[3].array
.ArrayID
= array_id
;
1569 emit_decl_fs(struct ureg_program
*ureg
,
1573 unsigned semantic_name
,
1574 unsigned semantic_index
,
1575 unsigned interpolate
,
1576 unsigned cylindrical_wrap
,
1577 unsigned interpolate_location
,
1579 unsigned usage_mask
)
1581 union tgsi_any_token
*out
= get_tokens(ureg
, DOMAIN_DECL
,
1585 out
[0].decl
.Type
= TGSI_TOKEN_TYPE_DECLARATION
;
1586 out
[0].decl
.NrTokens
= 4;
1587 out
[0].decl
.File
= file
;
1588 out
[0].decl
.UsageMask
= usage_mask
;
1589 out
[0].decl
.Interpolate
= 1;
1590 out
[0].decl
.Semantic
= 1;
1591 out
[0].decl
.Array
= array_id
!= 0;
1594 out
[1].decl_range
.First
= first
;
1595 out
[1].decl_range
.Last
= last
;
1598 out
[2].decl_interp
.Interpolate
= interpolate
;
1599 out
[2].decl_interp
.CylindricalWrap
= cylindrical_wrap
;
1600 out
[2].decl_interp
.Location
= interpolate_location
;
1603 out
[3].decl_semantic
.Name
= semantic_name
;
1604 out
[3].decl_semantic
.Index
= semantic_index
;
1608 out
[4].array
.ArrayID
= array_id
;
1613 emit_decl_temps( struct ureg_program
*ureg
,
1614 unsigned first
, unsigned last
,
1618 union tgsi_any_token
*out
= get_tokens( ureg
, DOMAIN_DECL
,
1622 out
[0].decl
.Type
= TGSI_TOKEN_TYPE_DECLARATION
;
1623 out
[0].decl
.NrTokens
= 2;
1624 out
[0].decl
.File
= TGSI_FILE_TEMPORARY
;
1625 out
[0].decl
.UsageMask
= TGSI_WRITEMASK_XYZW
;
1626 out
[0].decl
.Local
= local
;
1629 out
[1].decl_range
.First
= first
;
1630 out
[1].decl_range
.Last
= last
;
1633 out
[0].decl
.Array
= 1;
1635 out
[2].array
.ArrayID
= arrayid
;
1639 static void emit_decl_range( struct ureg_program
*ureg
,
1644 union tgsi_any_token
*out
= get_tokens( ureg
, DOMAIN_DECL
, 2 );
1647 out
[0].decl
.Type
= TGSI_TOKEN_TYPE_DECLARATION
;
1648 out
[0].decl
.NrTokens
= 2;
1649 out
[0].decl
.File
= file
;
1650 out
[0].decl
.UsageMask
= TGSI_WRITEMASK_XYZW
;
1651 out
[0].decl
.Semantic
= 0;
1654 out
[1].decl_range
.First
= first
;
1655 out
[1].decl_range
.Last
= first
+ count
- 1;
1659 emit_decl_range2D(struct ureg_program
*ureg
,
1665 union tgsi_any_token
*out
= get_tokens(ureg
, DOMAIN_DECL
, 3);
1668 out
[0].decl
.Type
= TGSI_TOKEN_TYPE_DECLARATION
;
1669 out
[0].decl
.NrTokens
= 3;
1670 out
[0].decl
.File
= file
;
1671 out
[0].decl
.UsageMask
= TGSI_WRITEMASK_XYZW
;
1672 out
[0].decl
.Dimension
= 1;
1675 out
[1].decl_range
.First
= first
;
1676 out
[1].decl_range
.Last
= last
;
1679 out
[2].decl_dim
.Index2D
= index2D
;
1683 emit_decl_sampler_view(struct ureg_program
*ureg
,
1686 unsigned return_type_x
,
1687 unsigned return_type_y
,
1688 unsigned return_type_z
,
1689 unsigned return_type_w
)
1691 union tgsi_any_token
*out
= get_tokens(ureg
, DOMAIN_DECL
, 3);
1694 out
[0].decl
.Type
= TGSI_TOKEN_TYPE_DECLARATION
;
1695 out
[0].decl
.NrTokens
= 3;
1696 out
[0].decl
.File
= TGSI_FILE_SAMPLER_VIEW
;
1697 out
[0].decl
.UsageMask
= TGSI_WRITEMASK_XYZW
;
1700 out
[1].decl_range
.First
= index
;
1701 out
[1].decl_range
.Last
= index
;
1704 out
[2].decl_sampler_view
.Resource
= target
;
1705 out
[2].decl_sampler_view
.ReturnTypeX
= return_type_x
;
1706 out
[2].decl_sampler_view
.ReturnTypeY
= return_type_y
;
1707 out
[2].decl_sampler_view
.ReturnTypeZ
= return_type_z
;
1708 out
[2].decl_sampler_view
.ReturnTypeW
= return_type_w
;
1712 emit_decl_image(struct ureg_program
*ureg
,
1719 union tgsi_any_token
*out
= get_tokens(ureg
, DOMAIN_DECL
, 3);
1722 out
[0].decl
.Type
= TGSI_TOKEN_TYPE_DECLARATION
;
1723 out
[0].decl
.NrTokens
= 3;
1724 out
[0].decl
.File
= TGSI_FILE_IMAGE
;
1725 out
[0].decl
.UsageMask
= TGSI_WRITEMASK_XYZW
;
1728 out
[1].decl_range
.First
= index
;
1729 out
[1].decl_range
.Last
= index
;
1732 out
[2].decl_image
.Resource
= target
;
1733 out
[2].decl_image
.Writable
= wr
;
1734 out
[2].decl_image
.Raw
= raw
;
1735 out
[2].decl_image
.Format
= format
;
1739 emit_decl_buffer(struct ureg_program
*ureg
,
1743 union tgsi_any_token
*out
= get_tokens(ureg
, DOMAIN_DECL
, 2);
1746 out
[0].decl
.Type
= TGSI_TOKEN_TYPE_DECLARATION
;
1747 out
[0].decl
.NrTokens
= 2;
1748 out
[0].decl
.File
= TGSI_FILE_BUFFER
;
1749 out
[0].decl
.UsageMask
= TGSI_WRITEMASK_XYZW
;
1750 out
[0].decl
.Atomic
= atomic
;
1753 out
[1].decl_range
.First
= index
;
1754 out
[1].decl_range
.Last
= index
;
1758 emit_decl_memory(struct ureg_program
*ureg
, unsigned memory_type
)
1760 union tgsi_any_token
*out
= get_tokens(ureg
, DOMAIN_DECL
, 2);
1763 out
[0].decl
.Type
= TGSI_TOKEN_TYPE_DECLARATION
;
1764 out
[0].decl
.NrTokens
= 2;
1765 out
[0].decl
.File
= TGSI_FILE_MEMORY
;
1766 out
[0].decl
.UsageMask
= TGSI_WRITEMASK_XYZW
;
1767 out
[0].decl
.MemType
= memory_type
;
1770 out
[1].decl_range
.First
= memory_type
;
1771 out
[1].decl_range
.Last
= memory_type
;
1775 emit_immediate( struct ureg_program
*ureg
,
1779 union tgsi_any_token
*out
= get_tokens( ureg
, DOMAIN_DECL
, 5 );
1782 out
[0].imm
.Type
= TGSI_TOKEN_TYPE_IMMEDIATE
;
1783 out
[0].imm
.NrTokens
= 5;
1784 out
[0].imm
.DataType
= type
;
1785 out
[0].imm
.Padding
= 0;
1787 out
[1].imm_data
.Uint
= v
[0];
1788 out
[2].imm_data
.Uint
= v
[1];
1789 out
[3].imm_data
.Uint
= v
[2];
1790 out
[4].imm_data
.Uint
= v
[3];
1794 emit_property(struct ureg_program
*ureg
,
1798 union tgsi_any_token
*out
= get_tokens(ureg
, DOMAIN_DECL
, 2);
1801 out
[0].prop
.Type
= TGSI_TOKEN_TYPE_PROPERTY
;
1802 out
[0].prop
.NrTokens
= 2;
1803 out
[0].prop
.PropertyName
= name
;
1805 out
[1].prop_data
.Data
= data
;
1809 static void emit_decls( struct ureg_program
*ureg
)
1813 for (i
= 0; i
< ARRAY_SIZE(ureg
->properties
); i
++)
1814 if (ureg
->properties
[i
] != ~0)
1815 emit_property(ureg
, i
, ureg
->properties
[i
]);
1817 if (ureg
->processor
== PIPE_SHADER_VERTEX
) {
1818 for (i
= 0; i
< PIPE_MAX_ATTRIBS
; i
++) {
1819 if (ureg
->vs_inputs
[i
/32] & (1u << (i
%32))) {
1820 emit_decl_range( ureg
, TGSI_FILE_INPUT
, i
, 1 );
1823 } else if (ureg
->processor
== PIPE_SHADER_FRAGMENT
) {
1824 if (ureg
->supports_any_inout_decl_range
) {
1825 for (i
= 0; i
< ureg
->nr_inputs
; i
++) {
1828 ureg
->input
[i
].first
,
1829 ureg
->input
[i
].last
,
1830 ureg
->input
[i
].semantic_name
,
1831 ureg
->input
[i
].semantic_index
,
1832 ureg
->input
[i
].interp
,
1833 ureg
->input
[i
].cylindrical_wrap
,
1834 ureg
->input
[i
].interp_location
,
1835 ureg
->input
[i
].array_id
,
1836 ureg
->input
[i
].usage_mask
);
1840 for (i
= 0; i
< ureg
->nr_inputs
; i
++) {
1841 for (j
= ureg
->input
[i
].first
; j
<= ureg
->input
[i
].last
; j
++) {
1845 ureg
->input
[i
].semantic_name
,
1846 ureg
->input
[i
].semantic_index
+
1847 (j
- ureg
->input
[i
].first
),
1848 ureg
->input
[i
].interp
,
1849 ureg
->input
[i
].cylindrical_wrap
,
1850 ureg
->input
[i
].interp_location
, 0,
1851 ureg
->input
[i
].usage_mask
);
1856 if (ureg
->supports_any_inout_decl_range
) {
1857 for (i
= 0; i
< ureg
->nr_inputs
; i
++) {
1858 emit_decl_semantic(ureg
,
1860 ureg
->input
[i
].first
,
1861 ureg
->input
[i
].last
,
1862 ureg
->input
[i
].semantic_name
,
1863 ureg
->input
[i
].semantic_index
,
1865 TGSI_WRITEMASK_XYZW
,
1866 ureg
->input
[i
].array_id
);
1870 for (i
= 0; i
< ureg
->nr_inputs
; i
++) {
1871 for (j
= ureg
->input
[i
].first
; j
<= ureg
->input
[i
].last
; j
++) {
1872 emit_decl_semantic(ureg
,
1875 ureg
->input
[i
].semantic_name
,
1876 ureg
->input
[i
].semantic_index
+
1877 (j
- ureg
->input
[i
].first
),
1879 TGSI_WRITEMASK_XYZW
, 0);
1885 for (i
= 0; i
< ureg
->nr_system_values
; i
++) {
1886 emit_decl_semantic(ureg
,
1887 TGSI_FILE_SYSTEM_VALUE
,
1890 ureg
->system_value
[i
].semantic_name
,
1891 ureg
->system_value
[i
].semantic_index
,
1893 TGSI_WRITEMASK_XYZW
, 0);
1896 if (ureg
->supports_any_inout_decl_range
) {
1897 for (i
= 0; i
< ureg
->nr_outputs
; i
++) {
1898 emit_decl_semantic(ureg
,
1900 ureg
->output
[i
].first
,
1901 ureg
->output
[i
].last
,
1902 ureg
->output
[i
].semantic_name
,
1903 ureg
->output
[i
].semantic_index
,
1904 ureg
->output
[i
].streams
,
1905 ureg
->output
[i
].usage_mask
,
1906 ureg
->output
[i
].array_id
);
1910 for (i
= 0; i
< ureg
->nr_outputs
; i
++) {
1911 for (j
= ureg
->output
[i
].first
; j
<= ureg
->output
[i
].last
; j
++) {
1912 emit_decl_semantic(ureg
,
1915 ureg
->output
[i
].semantic_name
,
1916 ureg
->output
[i
].semantic_index
+
1917 (j
- ureg
->output
[i
].first
),
1918 ureg
->output
[i
].streams
,
1919 ureg
->output
[i
].usage_mask
, 0);
1924 for (i
= 0; i
< ureg
->nr_samplers
; i
++) {
1925 emit_decl_range( ureg
,
1927 ureg
->sampler
[i
].Index
, 1 );
1930 for (i
= 0; i
< ureg
->nr_sampler_views
; i
++) {
1931 emit_decl_sampler_view(ureg
,
1932 ureg
->sampler_view
[i
].index
,
1933 ureg
->sampler_view
[i
].target
,
1934 ureg
->sampler_view
[i
].return_type_x
,
1935 ureg
->sampler_view
[i
].return_type_y
,
1936 ureg
->sampler_view
[i
].return_type_z
,
1937 ureg
->sampler_view
[i
].return_type_w
);
1940 for (i
= 0; i
< ureg
->nr_images
; i
++) {
1941 emit_decl_image(ureg
,
1942 ureg
->image
[i
].index
,
1943 ureg
->image
[i
].target
,
1944 ureg
->image
[i
].format
,
1946 ureg
->image
[i
].raw
);
1949 for (i
= 0; i
< ureg
->nr_buffers
; i
++) {
1950 emit_decl_buffer(ureg
, ureg
->buffer
[i
].index
, ureg
->buffer
[i
].atomic
);
1953 for (i
= 0; i
< TGSI_MEMORY_TYPE_COUNT
; i
++) {
1954 if (ureg
->use_memory
[i
])
1955 emit_decl_memory(ureg
, i
);
1958 if (ureg
->const_decls
.nr_constant_ranges
) {
1959 for (i
= 0; i
< ureg
->const_decls
.nr_constant_ranges
; i
++) {
1960 emit_decl_range(ureg
,
1962 ureg
->const_decls
.constant_range
[i
].first
,
1963 ureg
->const_decls
.constant_range
[i
].last
- ureg
->const_decls
.constant_range
[i
].first
+ 1);
1967 for (i
= 0; i
< PIPE_MAX_CONSTANT_BUFFERS
; i
++) {
1968 struct const_decl
*decl
= &ureg
->const_decls2D
[i
];
1970 if (decl
->nr_constant_ranges
) {
1973 for (j
= 0; j
< decl
->nr_constant_ranges
; j
++) {
1974 emit_decl_range2D(ureg
,
1976 decl
->constant_range
[j
].first
,
1977 decl
->constant_range
[j
].last
,
1983 if (ureg
->nr_temps
) {
1985 for (i
= 0; i
< ureg
->nr_temps
;) {
1986 boolean local
= util_bitmask_get(ureg
->local_temps
, i
);
1988 i
= util_bitmask_get_next_index(ureg
->decl_temps
, i
+ 1);
1989 if (i
== UTIL_BITMASK_INVALID_INDEX
)
1992 if (array
< ureg
->nr_array_temps
&& ureg
->array_temps
[array
] == first
)
1993 emit_decl_temps( ureg
, first
, i
- 1, local
, ++array
);
1995 emit_decl_temps( ureg
, first
, i
- 1, local
, 0 );
1999 if (ureg
->nr_addrs
) {
2000 emit_decl_range( ureg
,
2002 0, ureg
->nr_addrs
);
2005 if (ureg
->nr_preds
) {
2006 emit_decl_range(ureg
,
2007 TGSI_FILE_PREDICATE
,
2012 for (i
= 0; i
< ureg
->nr_immediates
; i
++) {
2013 emit_immediate( ureg
,
2014 ureg
->immediate
[i
].value
.u
,
2015 ureg
->immediate
[i
].type
);
2019 /* Append the instruction tokens onto the declarations to build a
2020 * contiguous stream suitable to send to the driver.
2022 static void copy_instructions( struct ureg_program
*ureg
)
2024 unsigned nr_tokens
= ureg
->domain
[DOMAIN_INSN
].count
;
2025 union tgsi_any_token
*out
= get_tokens( ureg
,
2030 ureg
->domain
[DOMAIN_INSN
].tokens
,
2031 nr_tokens
* sizeof out
[0] );
2036 fixup_header_size(struct ureg_program
*ureg
)
2038 union tgsi_any_token
*out
= retrieve_token( ureg
, DOMAIN_DECL
, 0 );
2040 out
->header
.BodySize
= ureg
->domain
[DOMAIN_DECL
].count
- 2;
2045 emit_header( struct ureg_program
*ureg
)
2047 union tgsi_any_token
*out
= get_tokens( ureg
, DOMAIN_DECL
, 2 );
2049 out
[0].header
.HeaderSize
= 2;
2050 out
[0].header
.BodySize
= 0;
2052 out
[1].processor
.Processor
= ureg
->processor
;
2053 out
[1].processor
.Padding
= 0;
2057 const struct tgsi_token
*ureg_finalize( struct ureg_program
*ureg
)
2059 const struct tgsi_token
*tokens
;
2061 switch (ureg
->processor
) {
2062 case PIPE_SHADER_VERTEX
:
2063 case PIPE_SHADER_TESS_EVAL
:
2064 ureg_property(ureg
, TGSI_PROPERTY_NEXT_SHADER
,
2065 ureg
->next_shader_processor
== -1 ?
2066 PIPE_SHADER_FRAGMENT
:
2067 ureg
->next_shader_processor
);
2071 emit_header( ureg
);
2073 copy_instructions( ureg
);
2074 fixup_header_size( ureg
);
2076 if (ureg
->domain
[0].tokens
== error_tokens
||
2077 ureg
->domain
[1].tokens
== error_tokens
) {
2078 debug_printf("%s: error in generated shader\n", __FUNCTION__
);
2083 tokens
= &ureg
->domain
[DOMAIN_DECL
].tokens
[0].token
;
2086 debug_printf("%s: emitted shader %d tokens:\n", __FUNCTION__
,
2087 ureg
->domain
[DOMAIN_DECL
].count
);
2088 tgsi_dump( tokens
, 0 );
2092 if (tokens
&& !tgsi_sanity_check(tokens
)) {
2093 debug_printf("tgsi_ureg.c, sanity check failed on generated tokens:\n");
2094 tgsi_dump(tokens
, 0);
2104 void *ureg_create_shader( struct ureg_program
*ureg
,
2105 struct pipe_context
*pipe
,
2106 const struct pipe_stream_output_info
*so
)
2108 struct pipe_shader_state state
;
2110 pipe_shader_state_from_tgsi(&state
, ureg_finalize(ureg
));
2115 state
.stream_output
= *so
;
2117 switch (ureg
->processor
) {
2118 case PIPE_SHADER_VERTEX
:
2119 return pipe
->create_vs_state(pipe
, &state
);
2120 case PIPE_SHADER_TESS_CTRL
:
2121 return pipe
->create_tcs_state(pipe
, &state
);
2122 case PIPE_SHADER_TESS_EVAL
:
2123 return pipe
->create_tes_state(pipe
, &state
);
2124 case PIPE_SHADER_GEOMETRY
:
2125 return pipe
->create_gs_state(pipe
, &state
);
2126 case PIPE_SHADER_FRAGMENT
:
2127 return pipe
->create_fs_state(pipe
, &state
);
2134 const struct tgsi_token
*ureg_get_tokens( struct ureg_program
*ureg
,
2135 unsigned *nr_tokens
)
2137 const struct tgsi_token
*tokens
;
2139 ureg_finalize(ureg
);
2141 tokens
= &ureg
->domain
[DOMAIN_DECL
].tokens
[0].token
;
2144 *nr_tokens
= ureg
->domain
[DOMAIN_DECL
].size
;
2146 ureg
->domain
[DOMAIN_DECL
].tokens
= 0;
2147 ureg
->domain
[DOMAIN_DECL
].size
= 0;
2148 ureg
->domain
[DOMAIN_DECL
].order
= 0;
2149 ureg
->domain
[DOMAIN_DECL
].count
= 0;
2155 void ureg_free_tokens( const struct tgsi_token
*tokens
)
2157 FREE((struct tgsi_token
*)tokens
);
2161 struct ureg_program
*
2162 ureg_create(unsigned processor
)
2164 return ureg_create_with_screen(processor
, NULL
);
2168 struct ureg_program
*
2169 ureg_create_with_screen(unsigned processor
, struct pipe_screen
*screen
)
2172 struct ureg_program
*ureg
= CALLOC_STRUCT( ureg_program
);
2176 ureg
->processor
= processor
;
2177 ureg
->supports_any_inout_decl_range
=
2179 screen
->get_shader_param(screen
, processor
,
2180 PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE
) != 0;
2181 ureg
->next_shader_processor
= -1;
2183 for (i
= 0; i
< ARRAY_SIZE(ureg
->properties
); i
++)
2184 ureg
->properties
[i
] = ~0;
2186 ureg
->free_temps
= util_bitmask_create();
2187 if (ureg
->free_temps
== NULL
)
2190 ureg
->local_temps
= util_bitmask_create();
2191 if (ureg
->local_temps
== NULL
)
2192 goto no_local_temps
;
2194 ureg
->decl_temps
= util_bitmask_create();
2195 if (ureg
->decl_temps
== NULL
)
2201 util_bitmask_destroy(ureg
->local_temps
);
2203 util_bitmask_destroy(ureg
->free_temps
);
2212 ureg_set_next_shader_processor(struct ureg_program
*ureg
, unsigned processor
)
2214 ureg
->next_shader_processor
= processor
;
2219 ureg_get_nr_outputs( const struct ureg_program
*ureg
)
2223 return ureg
->nr_outputs
;
2227 void ureg_destroy( struct ureg_program
*ureg
)
2231 for (i
= 0; i
< ARRAY_SIZE(ureg
->domain
); i
++) {
2232 if (ureg
->domain
[i
].tokens
&&
2233 ureg
->domain
[i
].tokens
!= error_tokens
)
2234 FREE(ureg
->domain
[i
].tokens
);
2237 util_bitmask_destroy(ureg
->free_temps
);
2238 util_bitmask_destroy(ureg
->local_temps
);
2239 util_bitmask_destroy(ureg
->decl_temps
);