1/**************************************************************************
2 *
3 * Copyright 2010 Luca Barbieri
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 **************************************************************************/
26
27#include "util/u_debug.h"
28#include "pipe/p_shader_tokens.h"
29#include "tgsi/tgsi_parse.h"
30#include "tgsi/tgsi_scan.h"
31#include "util/u_linkage.h"
32
33/* we must only record the registers that are actually used, not just declared */
34static INLINE boolean
35util_semantic_set_test_and_set(struct util_semantic_set *set, unsigned value)
36{
37   unsigned mask = 1 << (value % (sizeof(long) * 8));
38   unsigned long *p = &set->masks[value / (sizeof(long) * 8)];
39   unsigned long v = *p & mask;
40   *p |= mask;
41   return !!v;
42}
43
44unsigned
45util_semantic_set_from_program_file(struct util_semantic_set *set, const struct tgsi_token *tokens, enum tgsi_file_type file)
46{
47   struct tgsi_shader_info info;
48   struct tgsi_parse_context parse;
49   unsigned count = 0;
50   ubyte *semantic_name;
51   ubyte *semantic_index;
52
53   tgsi_scan_shader(tokens, &info);
54
55   if(file == TGSI_FILE_INPUT)
56   {
57      semantic_name = info.input_semantic_name;
58      semantic_index = info.input_semantic_index;
59   }
60   else if(file == TGSI_FILE_OUTPUT)
61   {
62      semantic_name = info.output_semantic_name;
63      semantic_index = info.output_semantic_index;
64   }
65   else
66   {
67      assert(0);
68      semantic_name = NULL;
69      semantic_index = NULL;
70   }
71
72   tgsi_parse_init(&parse, tokens);
73
74   memset(set->masks, 0, sizeof(set->masks));
75   while(!tgsi_parse_end_of_tokens(&parse))
76   {
77      tgsi_parse_token(&parse);
78
79      if(parse.FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION)
80      {
81	 const struct tgsi_full_instruction *finst = &parse.FullToken.FullInstruction;
82	 unsigned i;
83	 for(i = 0; i < finst->Instruction.NumDstRegs; ++i)
84	 {
85	    if(finst->Dst[i].Register.File == file)
86	    {
87	       unsigned idx = finst->Dst[i].Register.Index;
88	       if(semantic_name[idx] == TGSI_SEMANTIC_GENERIC)
89	       {
90		  if(!util_semantic_set_test_and_set(set, semantic_index[idx]))
91		     ++count;
92	       }
93	    }
94	 }
95
96	 for(i = 0; i < finst->Instruction.NumSrcRegs; ++i)
97	 {
98	    if(finst->Src[i].Register.File == file)
99	    {
100	       unsigned idx = finst->Src[i].Register.Index;
101	       if(semantic_name[idx] == TGSI_SEMANTIC_GENERIC)
102	       {
103		  if(!util_semantic_set_test_and_set(set, semantic_index[idx]))
104		     ++count;
105	       }
106	    }
107	 }
108      }
109   }
110   tgsi_parse_free(&parse);
111
112   return count;
113}
114
115#define UTIL_SEMANTIC_SET_FOR_EACH(i, set) for(i = 0; i < 256; ++i) if(set->masks[i / (sizeof(long) * 8)] & (1 << (i % (sizeof(long) * 8))))
116
117void
118util_semantic_layout_from_set(unsigned char *layout, const struct util_semantic_set *set, unsigned efficient_slots, unsigned num_slots)
119{
120   int first = -1;
121   int last = -1;
122   unsigned i;
123
124   memset(layout, 0xff, num_slots);
125
126   UTIL_SEMANTIC_SET_FOR_EACH(i, set)
127   {
128      if(first < 0)
129	 first = i;
130      last = i;
131   }
132
133   if(last < efficient_slots)
134   {
135      UTIL_SEMANTIC_SET_FOR_EACH(i, set)
136         layout[i] = i;
137   }
138   else if((last - first) < efficient_slots)
139   {
140      UTIL_SEMANTIC_SET_FOR_EACH(i, set)
141         layout[i - first] = i;
142   }
143   else
144   {
145      unsigned idx = 0;
146      UTIL_SEMANTIC_SET_FOR_EACH(i, set)
147         layout[idx++] = i;
148   }
149}
150