1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "PixelShader.hpp"
16 
17 #include "Debug.hpp"
18 
19 #include <string.h>
20 
21 namespace sw
22 {
PixelShader(const PixelShader * ps)23 	PixelShader::PixelShader(const PixelShader *ps) : Shader()
24 	{
25 		version = 0x0300;
26 		vPosDeclared = false;
27 		vFaceDeclared = false;
28 		centroid = false;
29 
30 		if(ps)   // Make a copy
31 		{
32 			for(size_t i = 0; i < ps->getLength(); i++)
33 			{
34 				append(new sw::Shader::Instruction(*ps->getInstruction(i)));
35 			}
36 
37 			memcpy(semantic, ps->semantic, sizeof(semantic));
38 			vPosDeclared = ps->vPosDeclared;
39 			vFaceDeclared = ps->vFaceDeclared;
40 			usedSamplers = ps->usedSamplers;
41 
42 			optimize();
43 			analyze();
44 		}
45 	}
46 
PixelShader(const unsigned long * token)47 	PixelShader::PixelShader(const unsigned long *token) : Shader()
48 	{
49 		parse(token);
50 
51 		vPosDeclared = false;
52 		vFaceDeclared = false;
53 		centroid = false;
54 
55 		optimize();
56 		analyze();
57 	}
58 
~PixelShader()59 	PixelShader::~PixelShader()
60 	{
61 	}
62 
validate(const unsigned long * const token)63 	int PixelShader::validate(const unsigned long *const token)
64 	{
65 		if(!token)
66 		{
67 			return 0;
68 		}
69 
70 		unsigned short version = (unsigned short)(token[0] & 0x0000FFFF);
71 		unsigned char minorVersion = (unsigned char)(token[0] & 0x000000FF);
72 		unsigned char majorVersion = (unsigned char)((token[0] & 0x0000FF00) >> 8);
73 		ShaderType shaderType = (ShaderType)((token[0] & 0xFFFF0000) >> 16);
74 
75 		if(shaderType != SHADER_PIXEL || majorVersion > 3)
76 		{
77 			return 0;
78 		}
79 
80 		int instructionCount = 1;
81 
82 		for(int i = 0; token[i] != 0x0000FFFF; i++)
83 		{
84 			if((token[i] & 0x0000FFFF) == 0x0000FFFE)   // Comment token
85 			{
86 				int length = (token[i] & 0x7FFF0000) >> 16;
87 
88 				i += length;
89 			}
90 			else
91 			{
92 				Shader::Opcode opcode = (Shader::Opcode)(token[i] & 0x0000FFFF);
93 
94 				switch(opcode)
95 				{
96 				case Shader::OPCODE_RESERVED0:
97 				case Shader::OPCODE_MOVA:
98 					return 0;   // Unsupported operation
99 				default:
100 					instructionCount++;
101 					break;
102 				}
103 
104 				i += size(token[i], version);
105 			}
106 		}
107 
108 		return instructionCount;
109 	}
110 
depthOverride() const111 	bool PixelShader::depthOverride() const
112 	{
113 		return zOverride;
114 	}
115 
containsKill() const116 	bool PixelShader::containsKill() const
117 	{
118 		return kill;
119 	}
120 
containsCentroid() const121 	bool PixelShader::containsCentroid() const
122 	{
123 		return centroid;
124 	}
125 
usesDiffuse(int component) const126 	bool PixelShader::usesDiffuse(int component) const
127 	{
128 		return semantic[0][component].active();
129 	}
130 
usesSpecular(int component) const131 	bool PixelShader::usesSpecular(int component) const
132 	{
133 		return semantic[1][component].active();
134 	}
135 
usesTexture(int coordinate,int component) const136 	bool PixelShader::usesTexture(int coordinate, int component) const
137 	{
138 		return semantic[2 + coordinate][component].active();
139 	}
140 
analyze()141 	void PixelShader::analyze()
142 	{
143 		analyzeZOverride();
144 		analyzeKill();
145 		analyzeInterpolants();
146 		analyzeDirtyConstants();
147 		analyzeDynamicBranching();
148 		analyzeSamplers();
149 		analyzeCallSites();
150 		analyzeDynamicIndexing();
151 	}
152 
analyzeZOverride()153 	void PixelShader::analyzeZOverride()
154 	{
155 		zOverride = false;
156 
157 		for(unsigned int i = 0; i < instruction.size(); i++)
158 		{
159 			if(instruction[i]->opcode == Shader::OPCODE_TEXM3X2DEPTH ||
160 			   instruction[i]->opcode == Shader::OPCODE_TEXDEPTH ||
161 			   instruction[i]->dst.type == Shader::PARAMETER_DEPTHOUT)
162 			{
163 				zOverride = true;
164 
165 				break;
166 			}
167 		}
168 	}
169 
analyzeKill()170 	void PixelShader::analyzeKill()
171 	{
172 		kill = false;
173 
174 		for(unsigned int i = 0; i < instruction.size(); i++)
175 		{
176 			if(instruction[i]->opcode == Shader::OPCODE_TEXKILL ||
177 			   instruction[i]->opcode == Shader::OPCODE_DISCARD)
178 			{
179 				kill = true;
180 
181 				break;
182 			}
183 		}
184 	}
185 
analyzeInterpolants()186 	void PixelShader::analyzeInterpolants()
187 	{
188 		if(version < 0x0300)
189 		{
190 			// Set default mapping; disable unused interpolants below
191 			semantic[0][0] = Semantic(Shader::USAGE_COLOR, 0);
192 			semantic[0][1] = Semantic(Shader::USAGE_COLOR, 0);
193 			semantic[0][2] = Semantic(Shader::USAGE_COLOR, 0);
194 			semantic[0][3] = Semantic(Shader::USAGE_COLOR, 0);
195 
196 			semantic[1][0] = Semantic(Shader::USAGE_COLOR, 1);
197 			semantic[1][1] = Semantic(Shader::USAGE_COLOR, 1);
198 			semantic[1][2] = Semantic(Shader::USAGE_COLOR, 1);
199 			semantic[1][3] = Semantic(Shader::USAGE_COLOR, 1);
200 
201 			for(int i = 0; i < 8; i++)
202 			{
203 				semantic[2 + i][0] = Semantic(Shader::USAGE_TEXCOORD, i);
204 				semantic[2 + i][1] = Semantic(Shader::USAGE_TEXCOORD, i);
205 				semantic[2 + i][2] = Semantic(Shader::USAGE_TEXCOORD, i);
206 				semantic[2 + i][3] = Semantic(Shader::USAGE_TEXCOORD, i);
207 			}
208 
209 			Shader::SamplerType samplerType[16];
210 
211 			for(int i = 0; i < 16; i++)
212 			{
213 				samplerType[i] = Shader::SAMPLER_UNKNOWN;
214 			}
215 
216 			for(unsigned int i = 0; i < instruction.size(); i++)
217 			{
218 				if(instruction[i]->dst.type == Shader::PARAMETER_SAMPLER)
219 				{
220 					int sampler = instruction[i]->dst.index;
221 
222 					samplerType[sampler] = instruction[i]->samplerType;
223 				}
224 			}
225 
226 			bool interpolant[MAX_FRAGMENT_INPUTS][4] = {{false}};   // Interpolants in use
227 
228 			for(unsigned int i = 0; i < instruction.size(); i++)
229 			{
230 				if(instruction[i]->dst.type == Shader::PARAMETER_TEXTURE)
231 				{
232 					int index = instruction[i]->dst.index + 2;
233 					int mask = instruction[i]->dst.mask;
234 
235 					switch(instruction[i]->opcode)
236 					{
237 					case Shader::OPCODE_TEX:
238 					case Shader::OPCODE_TEXBEM:
239 					case Shader::OPCODE_TEXBEML:
240 					case Shader::OPCODE_TEXCOORD:
241 					case Shader::OPCODE_TEXDP3:
242 					case Shader::OPCODE_TEXDP3TEX:
243 					case Shader::OPCODE_TEXM3X2DEPTH:
244 					case Shader::OPCODE_TEXM3X2PAD:
245 					case Shader::OPCODE_TEXM3X2TEX:
246 					case Shader::OPCODE_TEXM3X3:
247 					case Shader::OPCODE_TEXM3X3PAD:
248 					case Shader::OPCODE_TEXM3X3TEX:
249 						interpolant[index][0] = true;
250 						interpolant[index][1] = true;
251 						interpolant[index][2] = true;
252 						break;
253 					case Shader::OPCODE_TEXKILL:
254 						if(majorVersion < 2)
255 						{
256 							interpolant[index][0] = true;
257 							interpolant[index][1] = true;
258 							interpolant[index][2] = true;
259 						}
260 						else
261 						{
262 							interpolant[index][0] = true;
263 							interpolant[index][1] = true;
264 							interpolant[index][2] = true;
265 							interpolant[index][3] = true;
266 						}
267 						break;
268 					case Shader::OPCODE_TEXM3X3VSPEC:
269 						interpolant[index][0] = true;
270 						interpolant[index][1] = true;
271 						interpolant[index][2] = true;
272 						interpolant[index - 2][3] = true;
273 						interpolant[index - 1][3] = true;
274 						interpolant[index - 0][3] = true;
275 						break;
276 					case Shader::OPCODE_DCL:
277 						break;   // Ignore
278 					default:   // Arithmetic instruction
279 						if(version >= 0x0104)
280 						{
281 							ASSERT(false);
282 						}
283 					}
284 				}
285 
286 				for(int argument = 0; argument < 4; argument++)
287 				{
288 					if(instruction[i]->src[argument].type == Shader::PARAMETER_INPUT ||
289 					   instruction[i]->src[argument].type == Shader::PARAMETER_TEXTURE)
290 					{
291 						int index = instruction[i]->src[argument].index;
292 						int swizzle = instruction[i]->src[argument].swizzle;
293 						int mask = instruction[i]->dst.mask;
294 
295 						if(instruction[i]->src[argument].type == Shader::PARAMETER_TEXTURE)
296 						{
297 							index += 2;
298 						}
299 
300 						switch(instruction[i]->opcode)
301 						{
302 						case Shader::OPCODE_TEX:
303 						case Shader::OPCODE_TEXLDD:
304 						case Shader::OPCODE_TEXLDL:
305 						case Shader::OPCODE_TEXOFFSET:
306 						case Shader::OPCODE_TEXLDLOFFSET:
307 						case Shader::OPCODE_TEXELFETCH:
308 						case Shader::OPCODE_TEXELFETCHOFFSET:
309 						case Shader::OPCODE_TEXGRAD:
310 						case Shader::OPCODE_TEXGRADOFFSET:
311 							{
312 								int sampler = instruction[i]->src[1].index;
313 
314 								switch(samplerType[sampler])
315 								{
316 								case Shader::SAMPLER_UNKNOWN:
317 									if(version == 0x0104)
318 									{
319 										if((instruction[i]->src[0].swizzle & 0x30) == 0x20)   // .xyz
320 										{
321 											interpolant[index][0] = true;
322 											interpolant[index][1] = true;
323 											interpolant[index][2] = true;
324 										}
325 										else   // .xyw
326 										{
327 											interpolant[index][0] = true;
328 											interpolant[index][1] = true;
329 											interpolant[index][3] = true;
330 										}
331 									}
332 									else
333 									{
334 										ASSERT(false);
335 									}
336 									break;
337 								case Shader::SAMPLER_1D:
338 									interpolant[index][0] = true;
339 									break;
340 								case Shader::SAMPLER_2D:
341 									interpolant[index][0] = true;
342 									interpolant[index][1] = true;
343 									break;
344 								case Shader::SAMPLER_CUBE:
345 									interpolant[index][0] = true;
346 									interpolant[index][1] = true;
347 									interpolant[index][2] = true;
348 									break;
349 								case Shader::SAMPLER_VOLUME:
350 									interpolant[index][0] = true;
351 									interpolant[index][1] = true;
352 									interpolant[index][2] = true;
353 									break;
354 								default:
355 									ASSERT(false);
356 								}
357 
358 								if(instruction[i]->bias)
359 								{
360 									interpolant[index][3] = true;
361 								}
362 
363 								if(instruction[i]->project)
364 								{
365 									interpolant[index][3] = true;
366 								}
367 
368 								if(version == 0x0104 && instruction[i]->opcode == Shader::OPCODE_TEX)
369 								{
370 									if(instruction[i]->src[0].modifier == Shader::MODIFIER_DZ)
371 									{
372 										interpolant[index][2] = true;
373 									}
374 
375 									if(instruction[i]->src[0].modifier == Shader::MODIFIER_DW)
376 									{
377 										interpolant[index][3] = true;
378 									}
379 								}
380 							}
381 							break;
382 						case Shader::OPCODE_M3X2:
383 							if(mask & 0x1)
384 							{
385 								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
386 								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
387 								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
388 								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
389 							}
390 
391 							if(argument == 1)
392 							{
393 								if(mask & 0x2)
394 								{
395 									interpolant[index + 1][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
396 									interpolant[index + 1][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
397 									interpolant[index + 1][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
398 									interpolant[index + 1][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
399 								}
400 							}
401 							break;
402 						case Shader::OPCODE_M3X3:
403 							if(mask & 0x1)
404 							{
405 								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
406 								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
407 								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
408 								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
409 							}
410 
411 							if(argument == 1)
412 							{
413 								if(mask & 0x2)
414 								{
415 									interpolant[index + 1][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
416 									interpolant[index + 1][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
417 									interpolant[index + 1][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
418 									interpolant[index + 1][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
419 								}
420 
421 								if(mask & 0x4)
422 								{
423 									interpolant[index + 2][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
424 									interpolant[index + 2][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
425 									interpolant[index + 2][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
426 									interpolant[index + 2][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
427 								}
428 							}
429 							break;
430 						case Shader::OPCODE_M3X4:
431 							if(mask & 0x1)
432 							{
433 								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
434 								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
435 								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
436 								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
437 							}
438 
439 							if(argument == 1)
440 							{
441 								if(mask & 0x2)
442 								{
443 									interpolant[index + 1][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
444 									interpolant[index + 1][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
445 									interpolant[index + 1][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
446 									interpolant[index + 1][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
447 								}
448 
449 								if(mask & 0x4)
450 								{
451 									interpolant[index + 2][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
452 									interpolant[index + 2][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
453 									interpolant[index + 2][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
454 									interpolant[index + 2][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
455 								}
456 
457 								if(mask & 0x8)
458 								{
459 									interpolant[index + 3][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
460 									interpolant[index + 3][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
461 									interpolant[index + 3][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
462 									interpolant[index + 3][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
463 								}
464 							}
465 							break;
466 						case Shader::OPCODE_M4X3:
467 							if(mask & 0x1)
468 							{
469 								interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
470 								interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
471 								interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
472 								interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
473 							}
474 
475 							if(argument == 1)
476 							{
477 								if(mask & 0x2)
478 								{
479 									interpolant[index + 1][0] |= swizzleContainsComponent(swizzle, 0);
480 									interpolant[index + 1][1] |= swizzleContainsComponent(swizzle, 1);
481 									interpolant[index + 1][2] |= swizzleContainsComponent(swizzle, 2);
482 									interpolant[index + 1][3] |= swizzleContainsComponent(swizzle, 3);
483 								}
484 
485 								if(mask & 0x4)
486 								{
487 									interpolant[index + 2][0] |= swizzleContainsComponent(swizzle, 0);
488 									interpolant[index + 2][1] |= swizzleContainsComponent(swizzle, 1);
489 									interpolant[index + 2][2] |= swizzleContainsComponent(swizzle, 2);
490 									interpolant[index + 2][3] |= swizzleContainsComponent(swizzle, 3);
491 								}
492 							}
493 							break;
494 						case Shader::OPCODE_M4X4:
495 							if(mask & 0x1)
496 							{
497 								interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
498 								interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
499 								interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
500 								interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
501 							}
502 
503 							if(argument == 1)
504 							{
505 								if(mask & 0x2)
506 								{
507 									interpolant[index + 1][0] |= swizzleContainsComponent(swizzle, 0);
508 									interpolant[index + 1][1] |= swizzleContainsComponent(swizzle, 1);
509 									interpolant[index + 1][2] |= swizzleContainsComponent(swizzle, 2);
510 									interpolant[index + 1][3] |= swizzleContainsComponent(swizzle, 3);
511 								}
512 
513 								if(mask & 0x4)
514 								{
515 									interpolant[index + 2][0] |= swizzleContainsComponent(swizzle, 0);
516 									interpolant[index + 2][1] |= swizzleContainsComponent(swizzle, 1);
517 									interpolant[index + 2][2] |= swizzleContainsComponent(swizzle, 2);
518 									interpolant[index + 2][3] |= swizzleContainsComponent(swizzle, 3);
519 								}
520 
521 								if(mask & 0x8)
522 								{
523 									interpolant[index + 3][0] |= swizzleContainsComponent(swizzle, 0);
524 									interpolant[index + 3][1] |= swizzleContainsComponent(swizzle, 1);
525 									interpolant[index + 3][2] |= swizzleContainsComponent(swizzle, 2);
526 									interpolant[index + 3][3] |= swizzleContainsComponent(swizzle, 3);
527 								}
528 							}
529 							break;
530 						case Shader::OPCODE_CRS:
531 							if(mask & 0x1)
532 							{
533 								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x6);
534 								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x6);
535 								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x6);
536 								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x6);
537 							}
538 
539 							if(mask & 0x2)
540 							{
541 								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x5);
542 								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x5);
543 								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x5);
544 								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x5);
545 							}
546 
547 							if(mask & 0x4)
548 							{
549 								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x3);
550 								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x3);
551 								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x3);
552 								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x3);
553 							}
554 							break;
555 						case Shader::OPCODE_DP2ADD:
556 							if(argument == 0 || argument == 1)
557 							{
558 								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x3);
559 								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x3);
560 								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x3);
561 								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x3);
562 							}
563 							else   // argument == 2
564 							{
565 								interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
566 								interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
567 								interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
568 								interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
569 							}
570 							break;
571 						case Shader::OPCODE_DP3:
572 							interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
573 							interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
574 							interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
575 							interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
576 							break;
577 						case Shader::OPCODE_DP4:
578 							interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
579 							interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
580 							interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
581 							interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
582 							break;
583 						case Shader::OPCODE_SINCOS:
584 						case Shader::OPCODE_EXP2X:
585 						case Shader::OPCODE_LOG2X:
586 						case Shader::OPCODE_POWX:
587 						case Shader::OPCODE_RCPX:
588 						case Shader::OPCODE_RSQX:
589 							interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
590 							interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
591 							interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
592 							interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
593 							break;
594 						case Shader::OPCODE_NRM3:
595 							interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7 | mask);
596 							interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7 | mask);
597 							interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7 | mask);
598 							interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7 | mask);
599 							break;
600 						case Shader::OPCODE_MOV:
601 						case Shader::OPCODE_ADD:
602 						case Shader::OPCODE_SUB:
603 						case Shader::OPCODE_MUL:
604 						case Shader::OPCODE_MAD:
605 						case Shader::OPCODE_ABS:
606 						case Shader::OPCODE_CMP0:
607 						case Shader::OPCODE_CND:
608 						case Shader::OPCODE_FRC:
609 						case Shader::OPCODE_LRP:
610 						case Shader::OPCODE_MAX:
611 						case Shader::OPCODE_MIN:
612 						case Shader::OPCODE_CMP:
613 						case Shader::OPCODE_BREAKC:
614 						case Shader::OPCODE_DFDX:
615 						case Shader::OPCODE_DFDY:
616 							interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, mask);
617 							interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, mask);
618 							interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, mask);
619 							interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, mask);
620 							break;
621 						case Shader::OPCODE_TEXCOORD:
622 							interpolant[index][0] = true;
623 							interpolant[index][1] = true;
624 							interpolant[index][2] = true;
625 							interpolant[index][3] = true;
626 							break;
627 						case Shader::OPCODE_TEXDP3:
628 						case Shader::OPCODE_TEXDP3TEX:
629 						case Shader::OPCODE_TEXM3X2PAD:
630 						case Shader::OPCODE_TEXM3X3PAD:
631 						case Shader::OPCODE_TEXM3X2TEX:
632 						case Shader::OPCODE_TEXM3X3SPEC:
633 						case Shader::OPCODE_TEXM3X3VSPEC:
634 						case Shader::OPCODE_TEXBEM:
635 						case Shader::OPCODE_TEXBEML:
636 						case Shader::OPCODE_TEXM3X2DEPTH:
637 						case Shader::OPCODE_TEXM3X3:
638 						case Shader::OPCODE_TEXM3X3TEX:
639 							interpolant[index][0] = true;
640 							interpolant[index][1] = true;
641 							interpolant[index][2] = true;
642 							break;
643 						case Shader::OPCODE_TEXREG2AR:
644 						case Shader::OPCODE_TEXREG2GB:
645 						case Shader::OPCODE_TEXREG2RGB:
646 							break;
647 						default:
648 						//	ASSERT(false);   // Refine component usage
649 							interpolant[index][0] = true;
650 							interpolant[index][1] = true;
651 							interpolant[index][2] = true;
652 							interpolant[index][3] = true;
653 						}
654 					}
655 				}
656 			}
657 
658 			for(int index = 0; index < MAX_FRAGMENT_INPUTS; index++)
659 			{
660 				for(int component = 0; component < 4; component++)
661 				{
662 					if(!interpolant[index][component])
663 					{
664 						semantic[index][component] = Semantic();
665 					}
666 				}
667 			}
668 		}
669 		else   // Shader Model 3.0 input declaration; v# indexable
670 		{
671 			for(unsigned int i = 0; i < instruction.size(); i++)
672 			{
673 				if(instruction[i]->opcode == Shader::OPCODE_DCL)
674 				{
675 					if(instruction[i]->dst.type == Shader::PARAMETER_INPUT)
676 					{
677 						unsigned char usage = instruction[i]->usage;
678 						unsigned char index = instruction[i]->usageIndex;
679 						unsigned char mask = instruction[i]->dst.mask;
680 						unsigned char reg = instruction[i]->dst.index;
681 
682 						if(mask & 0x01)	semantic[reg][0] = Semantic(usage, index);
683 						if(mask & 0x02) semantic[reg][1] = Semantic(usage, index);
684 						if(mask & 0x04) semantic[reg][2] = Semantic(usage, index);
685 						if(mask & 0x08)	semantic[reg][3] = Semantic(usage, index);
686 					}
687 					else if(instruction[i]->dst.type == Shader::PARAMETER_MISCTYPE)
688 					{
689 						unsigned char index = instruction[i]->dst.index;
690 
691 						if(index == 0)
692 						{
693 							vPosDeclared = true;
694 						}
695 						else if(index == 1)
696 						{
697 							vFaceDeclared = true;
698 						}
699 						else ASSERT(false);
700 					}
701 				}
702 			}
703 		}
704 
705 		if(version >= 0x0200)
706 		{
707 			for(unsigned int i = 0; i < instruction.size(); i++)
708 			{
709 				if(instruction[i]->opcode == Shader::OPCODE_DCL)
710 				{
711 					bool centroid = instruction[i]->dst.centroid;
712 					unsigned char reg = instruction[i]->dst.index;
713 
714 					switch(instruction[i]->dst.type)
715 					{
716 					case Shader::PARAMETER_INPUT:
717 						semantic[reg][0].centroid = centroid;
718 						break;
719 					case Shader::PARAMETER_TEXTURE:
720 						semantic[2 + reg][0].centroid = centroid;
721 						break;
722 					default:
723 						break;
724 					}
725 
726 					this->centroid = this->centroid || centroid;
727 				}
728 			}
729 		}
730 	}
731 }
732