• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "Common/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 		shaderModel = 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(input, ps->input, sizeof(input));
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 input[0][component].active();
129 	}
130 
usesSpecular(int component) const131 	bool PixelShader::usesSpecular(int component) const
132 	{
133 		return input[1][component].active();
134 	}
135 
usesTexture(int coordinate,int component) const136 	bool PixelShader::usesTexture(int coordinate, int component) const
137 	{
138 		return input[2 + coordinate][component].active();
139 	}
140 
setInput(int inputIdx,int nbComponents,const sw::Shader::Semantic & semantic)141 	void PixelShader::setInput(int inputIdx, int nbComponents, const sw::Shader::Semantic& semantic)
142 	{
143 		for(int i = 0; i < nbComponents; ++i)
144 		{
145 			input[inputIdx][i] = semantic;
146 		}
147 	}
148 
getInput(int inputIdx,int component) const149 	const sw::Shader::Semantic& PixelShader::getInput(int inputIdx, int component) const
150 	{
151 		return input[inputIdx][component];
152 	}
153 
analyze()154 	void PixelShader::analyze()
155 	{
156 		analyzeZOverride();
157 		analyzeKill();
158 		analyzeInterpolants();
159 		analyzeDirtyConstants();
160 		analyzeDynamicBranching();
161 		analyzeSamplers();
162 		analyzeCallSites();
163 		analyzeDynamicIndexing();
164 	}
165 
analyzeZOverride()166 	void PixelShader::analyzeZOverride()
167 	{
168 		zOverride = false;
169 
170 		for(const auto &inst : instruction)
171 		{
172 			if(inst->opcode == Shader::OPCODE_TEXM3X2DEPTH ||
173 			   inst->opcode == Shader::OPCODE_TEXDEPTH ||
174 			   inst->dst.type == Shader::PARAMETER_DEPTHOUT)
175 			{
176 				zOverride = true;
177 
178 				break;
179 			}
180 		}
181 	}
182 
analyzeKill()183 	void PixelShader::analyzeKill()
184 	{
185 		kill = false;
186 
187 		for(const auto &inst : instruction)
188 		{
189 			if(inst->opcode == Shader::OPCODE_TEXKILL ||
190 			   inst->opcode == Shader::OPCODE_DISCARD)
191 			{
192 				kill = true;
193 
194 				break;
195 			}
196 		}
197 	}
198 
analyzeInterpolants()199 	void PixelShader::analyzeInterpolants()
200 	{
201 		if(shaderModel < 0x0300)
202 		{
203 			// Set default mapping; disable unused interpolants below
204 			input[0][0] = Semantic(Shader::USAGE_COLOR, 0);
205 			input[0][1] = Semantic(Shader::USAGE_COLOR, 0);
206 			input[0][2] = Semantic(Shader::USAGE_COLOR, 0);
207 			input[0][3] = Semantic(Shader::USAGE_COLOR, 0);
208 
209 			input[1][0] = Semantic(Shader::USAGE_COLOR, 1);
210 			input[1][1] = Semantic(Shader::USAGE_COLOR, 1);
211 			input[1][2] = Semantic(Shader::USAGE_COLOR, 1);
212 			input[1][3] = Semantic(Shader::USAGE_COLOR, 1);
213 
214 			for(int i = 0; i < 8; i++)
215 			{
216 				input[2 + i][0] = Semantic(Shader::USAGE_TEXCOORD, i);
217 				input[2 + i][1] = Semantic(Shader::USAGE_TEXCOORD, i);
218 				input[2 + i][2] = Semantic(Shader::USAGE_TEXCOORD, i);
219 				input[2 + i][3] = Semantic(Shader::USAGE_TEXCOORD, i);
220 			}
221 
222 			Shader::SamplerType samplerType[16];
223 
224 			for(int i = 0; i < 16; i++)
225 			{
226 				samplerType[i] = Shader::SAMPLER_UNKNOWN;
227 			}
228 
229 			for(const auto &inst : instruction)
230 			{
231 				if(inst->dst.type == Shader::PARAMETER_SAMPLER)
232 				{
233 					int sampler = inst->dst.index;
234 
235 					samplerType[sampler] = inst->samplerType;
236 				}
237 			}
238 
239 			bool interpolant[MAX_FRAGMENT_INPUTS][4] = {{false}};   // Interpolants in use
240 
241 			for(const auto &inst : instruction)
242 			{
243 				if(inst->dst.type == Shader::PARAMETER_TEXTURE)
244 				{
245 					int index = inst->dst.index + 2;
246 
247 					switch(inst->opcode)
248 					{
249 					case Shader::OPCODE_TEX:
250 					case Shader::OPCODE_TEXBEM:
251 					case Shader::OPCODE_TEXBEML:
252 					case Shader::OPCODE_TEXCOORD:
253 					case Shader::OPCODE_TEXDP3:
254 					case Shader::OPCODE_TEXDP3TEX:
255 					case Shader::OPCODE_TEXM3X2DEPTH:
256 					case Shader::OPCODE_TEXM3X2PAD:
257 					case Shader::OPCODE_TEXM3X2TEX:
258 					case Shader::OPCODE_TEXM3X3:
259 					case Shader::OPCODE_TEXM3X3PAD:
260 					case Shader::OPCODE_TEXM3X3TEX:
261 						interpolant[index][0] = true;
262 						interpolant[index][1] = true;
263 						interpolant[index][2] = true;
264 						break;
265 					case Shader::OPCODE_TEXKILL:
266 						if(majorVersion < 2)
267 						{
268 							interpolant[index][0] = true;
269 							interpolant[index][1] = true;
270 							interpolant[index][2] = true;
271 						}
272 						else
273 						{
274 							interpolant[index][0] = true;
275 							interpolant[index][1] = true;
276 							interpolant[index][2] = true;
277 							interpolant[index][3] = true;
278 						}
279 						break;
280 					case Shader::OPCODE_TEXM3X3VSPEC:
281 						interpolant[index][0] = true;
282 						interpolant[index][1] = true;
283 						interpolant[index][2] = true;
284 						interpolant[index - 2][3] = true;
285 						interpolant[index - 1][3] = true;
286 						interpolant[index - 0][3] = true;
287 						break;
288 					case Shader::OPCODE_DCL:
289 						break;   // Ignore
290 					default:   // Arithmetic instruction
291 						if(shaderModel >= 0x0104)
292 						{
293 							ASSERT(false);
294 						}
295 					}
296 				}
297 
298 				for(int argument = 0; argument < 4; argument++)
299 				{
300 					if(inst->src[argument].type == Shader::PARAMETER_INPUT ||
301 					   inst->src[argument].type == Shader::PARAMETER_TEXTURE)
302 					{
303 						int index = inst->src[argument].index;
304 						int swizzle = inst->src[argument].swizzle;
305 						int mask = inst->dst.mask;
306 
307 						if(inst->src[argument].type == Shader::PARAMETER_TEXTURE)
308 						{
309 							index += 2;
310 						}
311 
312 						switch(inst->opcode)
313 						{
314 						case Shader::OPCODE_TEX:
315 						case Shader::OPCODE_TEXLDD:
316 						case Shader::OPCODE_TEXLDL:
317 						case Shader::OPCODE_TEXLOD:
318 						case Shader::OPCODE_TEXBIAS:
319 						case Shader::OPCODE_TEXOFFSET:
320 						case Shader::OPCODE_TEXOFFSETBIAS:
321 						case Shader::OPCODE_TEXLODOFFSET:
322 						case Shader::OPCODE_TEXELFETCH:
323 						case Shader::OPCODE_TEXELFETCHOFFSET:
324 						case Shader::OPCODE_TEXGRAD:
325 						case Shader::OPCODE_TEXGRADOFFSET:
326 							{
327 								int sampler = inst->src[1].index;
328 
329 								switch(samplerType[sampler])
330 								{
331 								case Shader::SAMPLER_UNKNOWN:
332 									if(shaderModel == 0x0104)
333 									{
334 										if((inst->src[0].swizzle & 0x30) == 0x20)   // .xyz
335 										{
336 											interpolant[index][0] = true;
337 											interpolant[index][1] = true;
338 											interpolant[index][2] = true;
339 										}
340 										else   // .xyw
341 										{
342 											interpolant[index][0] = true;
343 											interpolant[index][1] = true;
344 											interpolant[index][3] = true;
345 										}
346 									}
347 									else
348 									{
349 										ASSERT(false);
350 									}
351 									break;
352 								case Shader::SAMPLER_1D:
353 									interpolant[index][0] = true;
354 									break;
355 								case Shader::SAMPLER_2D:
356 									interpolant[index][0] = true;
357 									interpolant[index][1] = true;
358 									break;
359 								case Shader::SAMPLER_CUBE:
360 									interpolant[index][0] = true;
361 									interpolant[index][1] = true;
362 									interpolant[index][2] = true;
363 									break;
364 								case Shader::SAMPLER_VOLUME:
365 									interpolant[index][0] = true;
366 									interpolant[index][1] = true;
367 									interpolant[index][2] = true;
368 									break;
369 								default:
370 									ASSERT(false);
371 								}
372 
373 								if(inst->bias)
374 								{
375 									interpolant[index][3] = true;
376 								}
377 
378 								if(inst->project)
379 								{
380 									interpolant[index][3] = true;
381 								}
382 
383 								if(shaderModel == 0x0104 && inst->opcode == Shader::OPCODE_TEX)
384 								{
385 									if(inst->src[0].modifier == Shader::MODIFIER_DZ)
386 									{
387 										interpolant[index][2] = true;
388 									}
389 
390 									if(inst->src[0].modifier == Shader::MODIFIER_DW)
391 									{
392 										interpolant[index][3] = true;
393 									}
394 								}
395 							}
396 							break;
397 						case Shader::OPCODE_M3X2:
398 							if(mask & 0x1)
399 							{
400 								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
401 								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
402 								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
403 								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
404 							}
405 
406 							if(argument == 1)
407 							{
408 								if(mask & 0x2)
409 								{
410 									interpolant[index + 1][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
411 									interpolant[index + 1][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
412 									interpolant[index + 1][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
413 									interpolant[index + 1][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
414 								}
415 							}
416 							break;
417 						case Shader::OPCODE_M3X3:
418 							if(mask & 0x1)
419 							{
420 								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
421 								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
422 								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
423 								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
424 							}
425 
426 							if(argument == 1)
427 							{
428 								if(mask & 0x2)
429 								{
430 									interpolant[index + 1][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
431 									interpolant[index + 1][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
432 									interpolant[index + 1][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
433 									interpolant[index + 1][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
434 								}
435 
436 								if(mask & 0x4)
437 								{
438 									interpolant[index + 2][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
439 									interpolant[index + 2][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
440 									interpolant[index + 2][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
441 									interpolant[index + 2][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
442 								}
443 							}
444 							break;
445 						case Shader::OPCODE_M3X4:
446 							if(mask & 0x1)
447 							{
448 								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
449 								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
450 								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
451 								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
452 							}
453 
454 							if(argument == 1)
455 							{
456 								if(mask & 0x2)
457 								{
458 									interpolant[index + 1][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
459 									interpolant[index + 1][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
460 									interpolant[index + 1][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
461 									interpolant[index + 1][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
462 								}
463 
464 								if(mask & 0x4)
465 								{
466 									interpolant[index + 2][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
467 									interpolant[index + 2][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
468 									interpolant[index + 2][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
469 									interpolant[index + 2][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
470 								}
471 
472 								if(mask & 0x8)
473 								{
474 									interpolant[index + 3][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
475 									interpolant[index + 3][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
476 									interpolant[index + 3][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
477 									interpolant[index + 3][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
478 								}
479 							}
480 							break;
481 						case Shader::OPCODE_M4X3:
482 							if(mask & 0x1)
483 							{
484 								interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
485 								interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
486 								interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
487 								interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
488 							}
489 
490 							if(argument == 1)
491 							{
492 								if(mask & 0x2)
493 								{
494 									interpolant[index + 1][0] |= swizzleContainsComponent(swizzle, 0);
495 									interpolant[index + 1][1] |= swizzleContainsComponent(swizzle, 1);
496 									interpolant[index + 1][2] |= swizzleContainsComponent(swizzle, 2);
497 									interpolant[index + 1][3] |= swizzleContainsComponent(swizzle, 3);
498 								}
499 
500 								if(mask & 0x4)
501 								{
502 									interpolant[index + 2][0] |= swizzleContainsComponent(swizzle, 0);
503 									interpolant[index + 2][1] |= swizzleContainsComponent(swizzle, 1);
504 									interpolant[index + 2][2] |= swizzleContainsComponent(swizzle, 2);
505 									interpolant[index + 2][3] |= swizzleContainsComponent(swizzle, 3);
506 								}
507 							}
508 							break;
509 						case Shader::OPCODE_M4X4:
510 							if(mask & 0x1)
511 							{
512 								interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
513 								interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
514 								interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
515 								interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
516 							}
517 
518 							if(argument == 1)
519 							{
520 								if(mask & 0x2)
521 								{
522 									interpolant[index + 1][0] |= swizzleContainsComponent(swizzle, 0);
523 									interpolant[index + 1][1] |= swizzleContainsComponent(swizzle, 1);
524 									interpolant[index + 1][2] |= swizzleContainsComponent(swizzle, 2);
525 									interpolant[index + 1][3] |= swizzleContainsComponent(swizzle, 3);
526 								}
527 
528 								if(mask & 0x4)
529 								{
530 									interpolant[index + 2][0] |= swizzleContainsComponent(swizzle, 0);
531 									interpolant[index + 2][1] |= swizzleContainsComponent(swizzle, 1);
532 									interpolant[index + 2][2] |= swizzleContainsComponent(swizzle, 2);
533 									interpolant[index + 2][3] |= swizzleContainsComponent(swizzle, 3);
534 								}
535 
536 								if(mask & 0x8)
537 								{
538 									interpolant[index + 3][0] |= swizzleContainsComponent(swizzle, 0);
539 									interpolant[index + 3][1] |= swizzleContainsComponent(swizzle, 1);
540 									interpolant[index + 3][2] |= swizzleContainsComponent(swizzle, 2);
541 									interpolant[index + 3][3] |= swizzleContainsComponent(swizzle, 3);
542 								}
543 							}
544 							break;
545 						case Shader::OPCODE_CRS:
546 							if(mask & 0x1)
547 							{
548 								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x6);
549 								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x6);
550 								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x6);
551 								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x6);
552 							}
553 
554 							if(mask & 0x2)
555 							{
556 								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x5);
557 								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x5);
558 								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x5);
559 								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x5);
560 							}
561 
562 							if(mask & 0x4)
563 							{
564 								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x3);
565 								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x3);
566 								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x3);
567 								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x3);
568 							}
569 							break;
570 						case Shader::OPCODE_DP2ADD:
571 							if(argument == 0 || argument == 1)
572 							{
573 								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x3);
574 								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x3);
575 								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x3);
576 								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x3);
577 							}
578 							else   // argument == 2
579 							{
580 								interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
581 								interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
582 								interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
583 								interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
584 							}
585 							break;
586 						case Shader::OPCODE_DP3:
587 							interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
588 							interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
589 							interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
590 							interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
591 							break;
592 						case Shader::OPCODE_DP4:
593 							interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
594 							interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
595 							interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
596 							interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
597 							break;
598 						case Shader::OPCODE_SINCOS:
599 						case Shader::OPCODE_EXP2X:
600 						case Shader::OPCODE_LOG2X:
601 						case Shader::OPCODE_POWX:
602 						case Shader::OPCODE_RCPX:
603 						case Shader::OPCODE_RSQX:
604 							interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
605 							interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
606 							interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
607 							interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
608 							break;
609 						case Shader::OPCODE_NRM3:
610 							interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7 | mask);
611 							interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7 | mask);
612 							interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7 | mask);
613 							interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7 | mask);
614 							break;
615 						case Shader::OPCODE_MOV:
616 						case Shader::OPCODE_ADD:
617 						case Shader::OPCODE_SUB:
618 						case Shader::OPCODE_MUL:
619 						case Shader::OPCODE_MAD:
620 						case Shader::OPCODE_ABS:
621 						case Shader::OPCODE_CMP0:
622 						case Shader::OPCODE_CND:
623 						case Shader::OPCODE_FRC:
624 						case Shader::OPCODE_LRP:
625 						case Shader::OPCODE_MAX:
626 						case Shader::OPCODE_MIN:
627 						case Shader::OPCODE_CMP:
628 						case Shader::OPCODE_BREAKC:
629 						case Shader::OPCODE_DFDX:
630 						case Shader::OPCODE_DFDY:
631 							interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, mask);
632 							interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, mask);
633 							interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, mask);
634 							interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, mask);
635 							break;
636 						case Shader::OPCODE_TEXCOORD:
637 							interpolant[index][0] = true;
638 							interpolant[index][1] = true;
639 							interpolant[index][2] = true;
640 							interpolant[index][3] = true;
641 							break;
642 						case Shader::OPCODE_TEXDP3:
643 						case Shader::OPCODE_TEXDP3TEX:
644 						case Shader::OPCODE_TEXM3X2PAD:
645 						case Shader::OPCODE_TEXM3X3PAD:
646 						case Shader::OPCODE_TEXM3X2TEX:
647 						case Shader::OPCODE_TEXM3X3SPEC:
648 						case Shader::OPCODE_TEXM3X3VSPEC:
649 						case Shader::OPCODE_TEXBEM:
650 						case Shader::OPCODE_TEXBEML:
651 						case Shader::OPCODE_TEXM3X2DEPTH:
652 						case Shader::OPCODE_TEXM3X3:
653 						case Shader::OPCODE_TEXM3X3TEX:
654 							interpolant[index][0] = true;
655 							interpolant[index][1] = true;
656 							interpolant[index][2] = true;
657 							break;
658 						case Shader::OPCODE_TEXREG2AR:
659 						case Shader::OPCODE_TEXREG2GB:
660 						case Shader::OPCODE_TEXREG2RGB:
661 							break;
662 						default:
663 						//	ASSERT(false);   // Refine component usage
664 							interpolant[index][0] = true;
665 							interpolant[index][1] = true;
666 							interpolant[index][2] = true;
667 							interpolant[index][3] = true;
668 						}
669 					}
670 				}
671 			}
672 
673 			for(int index = 0; index < MAX_FRAGMENT_INPUTS; index++)
674 			{
675 				for(int component = 0; component < 4; component++)
676 				{
677 					if(!interpolant[index][component])
678 					{
679 						input[index][component] = Semantic();
680 					}
681 				}
682 			}
683 		}
684 		else   // Shader Model 3.0 input declaration; v# indexable
685 		{
686 			for(const auto &inst : instruction)
687 			{
688 				if(inst->opcode == Shader::OPCODE_DCL)
689 				{
690 					if(inst->dst.type == Shader::PARAMETER_INPUT)
691 					{
692 						unsigned char usage = inst->usage;
693 						unsigned char index = inst->usageIndex;
694 						unsigned char mask = inst->dst.mask;
695 						unsigned char reg = inst->dst.index;
696 
697 						if(mask & 0x01) input[reg][0] = Semantic(usage, index);
698 						if(mask & 0x02) input[reg][1] = Semantic(usage, index);
699 						if(mask & 0x04) input[reg][2] = Semantic(usage, index);
700 						if(mask & 0x08) input[reg][3] = Semantic(usage, index);
701 					}
702 					else if(inst->dst.type == Shader::PARAMETER_MISCTYPE)
703 					{
704 						unsigned char index = inst->dst.index;
705 
706 						if(index == Shader::VPosIndex)
707 						{
708 							vPosDeclared = true;
709 						}
710 						else if(index == Shader::VFaceIndex)
711 						{
712 							vFaceDeclared = true;
713 						}
714 						else ASSERT(false);
715 					}
716 				}
717 			}
718 		}
719 
720 		if(shaderModel >= 0x0200)
721 		{
722 			for(const auto &inst : instruction)
723 			{
724 				if(inst->opcode == Shader::OPCODE_DCL)
725 				{
726 					bool centroid = inst->dst.centroid;
727 					unsigned char reg = inst->dst.index;
728 
729 					switch(inst->dst.type)
730 					{
731 					case Shader::PARAMETER_INPUT:
732 						input[reg][0].centroid = centroid;
733 						break;
734 					case Shader::PARAMETER_TEXTURE:
735 						input[2 + reg][0].centroid = centroid;
736 						break;
737 					default:
738 						break;
739 					}
740 
741 					this->centroid = this->centroid || centroid;
742 				}
743 			}
744 		}
745 	}
746 }
747