Home | History | Annotate | Download | only in Shader
      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 {
     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 
     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 
     59 	PixelShader::~PixelShader()
     60 	{
     61 	}
     62 
     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 
    111 	bool PixelShader::depthOverride() const
    112 	{
    113 		return zOverride;
    114 	}
    115 
    116 	bool PixelShader::containsKill() const
    117 	{
    118 		return kill;
    119 	}
    120 
    121 	bool PixelShader::containsCentroid() const
    122 	{
    123 		return centroid;
    124 	}
    125 
    126 	bool PixelShader::usesDiffuse(int component) const
    127 	{
    128 		return semantic[0][component].active();
    129 	}
    130 
    131 	bool PixelShader::usesSpecular(int component) const
    132 	{
    133 		return semantic[1][component].active();
    134 	}
    135 
    136 	bool PixelShader::usesTexture(int coordinate, int component) const
    137 	{
    138 		return semantic[2 + coordinate][component].active();
    139 	}
    140 
    141 	void PixelShader::analyze()
    142 	{
    143 		analyzeZOverride();
    144 		analyzeKill();
    145 		analyzeInterpolants();
    146 		analyzeDirtyConstants();
    147 		analyzeDynamicBranching();
    148 		analyzeSamplers();
    149 		analyzeCallSites();
    150 		analyzeDynamicIndexing();
    151 	}
    152 
    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 
    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 
    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