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