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
21namespace sw
22{
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
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 analyzeIndirectAddressing();
164 analyzeLimits();
165 }
166
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
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
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