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