OSDN Git Service

Add SwiftShader source to repo
[android-x86/external-swiftshader.git] / src / Shader / Shader.cpp
1 // SwiftShader Software Renderer
2 //
3 // Copyright(c) 2005-2011 TransGaming Inc.
4 //
5 // All rights reserved. No part of this software may be copied, distributed, transmitted,
6 // transcribed, stored in a retrieval system, translated into any human or computer
7 // language by any means, or disclosed to third parties without the explicit written
8 // agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9 // or implied, including but not limited to any patent rights, are granted to you.
10 //
11
12 #include "Shader.hpp"
13
14 #include "Math.hpp"
15 #include "Debug.hpp"
16
17 #include <stdarg.h>
18 #include <fstream>
19 #include <sstream>
20
21 namespace sw
22 {
23         Shader::Instruction::Instruction()
24         {
25                 operation.opcode = Operation::OPCODE_NOP;
26                 destinationParameter.type = Parameter::PARAMETER_VOID;
27                 sourceParameter[0].type = Parameter::PARAMETER_VOID;
28                 sourceParameter[1].type = Parameter::PARAMETER_VOID;
29                 sourceParameter[2].type = Parameter::PARAMETER_VOID;
30                 sourceParameter[3].type = Parameter::PARAMETER_VOID;
31         }
32
33         Shader::Instruction::Instruction(const unsigned long *token, int size, unsigned char majorVersion)
34         {
35                 parseOperationToken(*token++, majorVersion);
36
37                 if(operation.opcode == Operation::OPCODE_IF ||
38                    operation.opcode == Operation::OPCODE_IFC ||
39                    operation.opcode == Operation::OPCODE_LOOP ||
40                    operation.opcode == Operation::OPCODE_REP ||
41                    operation.opcode == Operation::OPCODE_BREAKC ||
42                    operation.opcode == Operation::OPCODE_BREAKP)   // No destination operand
43                 {
44                         if(size > 0) parseSourceToken(0, token++, majorVersion);
45                         if(size > 1) parseSourceToken(1, token++, majorVersion);
46                         if(size > 2) parseSourceToken(2, token++, majorVersion);
47                         if(size > 3) ASSERT(false);
48                 }
49                 else if(operation.opcode == Operation::OPCODE_DCL)
50                 {
51                         parseDeclarationToken(*token++);
52                         parseDestinationToken(token++, majorVersion);
53                 }
54                 else
55                 {
56                         if(size > 0)
57                         {
58                                 parseDestinationToken(token, majorVersion);
59
60                                 if(destinationParameter.relative && majorVersion >= 3)
61                                 {
62                                         token++;
63                                         size--;
64                                 }
65                                 
66                                 token++;
67                                 size--;
68                         }
69
70                         if(operation.predicate)
71                         {
72                                 ASSERT(size != 0);
73
74                                 operation.predicateNot = (SourceParameter::Modifier)((*token & 0x0F000000) >> 24) == SourceParameter::MODIFIER_NOT;
75                                 operation.predicateSwizzle = (unsigned char)((*token & 0x00FF0000) >> 16);
76                                 
77                                 token++;
78                                 size--;
79                         }
80
81                         for(int i = 0; size > 0; i++)
82                         {
83                                 parseSourceToken(i, token, majorVersion);
84
85                                 token++;
86                                 size--;
87
88                                 if(sourceParameter[i].relative && majorVersion >= 2)
89                                 {
90                                         token++;
91                                         size--;
92                                 }
93                         }
94                 }
95         }
96
97         Shader::Instruction::~Instruction()
98         {
99         }
100
101         Shader::Instruction::Operation::Opcode Shader::Instruction::getOpcode() const
102         {
103                 return operation.opcode;
104         }
105
106         const Shader::Instruction::DestinationParameter &Shader::Instruction::getDestinationParameter() const
107         {
108                 return destinationParameter;
109         }
110
111         const Shader::Instruction::SourceParameter &Shader::Instruction::getSourceParameter(int i) const
112         {
113                 return sourceParameter[i];
114         }
115
116         bool Shader::Instruction::isCoissue() const
117         {
118                 return operation.coissue;
119         }
120
121         bool Shader::Instruction::isProject() const
122         {
123                 return operation.project;
124         }
125
126         bool Shader::Instruction::isBias() const
127         {
128                 return operation.bias;
129         }
130
131         bool Shader::Instruction::isPredicate() const
132         {
133                 return operation.predicate;
134         }
135
136         bool Shader::Instruction::isPredicateNot() const
137         {
138                 return operation.predicateNot;
139         }
140
141         unsigned char Shader::Instruction::getPredicateSwizzle() const
142         {
143                 return operation.predicateSwizzle;
144         }
145
146         Shader::Instruction::Operation::Control Shader::Instruction::getControl() const
147         {
148                 return operation.control;
149         }
150
151         Shader::Instruction::Operation::Usage Shader::Instruction::getUsage() const
152         {
153                 return operation.usage;
154         }
155
156         unsigned char Shader::Instruction::getUsageIndex() const
157         {
158                 return operation.usageIndex;
159         }
160
161         Shader::Instruction::Operation::SamplerType Shader::Instruction::getSamplerType() const
162         {
163                 return operation.samplerType;
164         }
165
166         std::string Shader::Instruction::string(ShaderType shaderType, unsigned short version) const
167         {
168                 std::string instructionString;
169                 
170                 if(operation.opcode != Operation::OPCODE_DCL)
171                 {
172                         instructionString += operation.coissue ? "+ " : "";
173                         
174                         if(operation.predicate)
175                         {
176                                 instructionString += operation.predicateNot ? "(!p0" : "(p0";
177                                 instructionString += swizzleString(Parameter::PARAMETER_PREDICATE, operation.predicateSwizzle);
178                                 instructionString += ") ";
179                         }
180
181                         instructionString += operation.string(version) + operation.controlString() + destinationParameter.shiftString() + destinationParameter.modifierString();
182
183                         if(destinationParameter.type != Parameter::PARAMETER_VOID)
184                         {
185                                 instructionString += " " + destinationParameter.string(shaderType, version) +
186                                                            destinationParameter.relativeString() +
187                                                            destinationParameter.maskString(); 
188                         }
189
190                         for(int i = 0; i < 4; i++)
191                         {
192                                 if(sourceParameter[i].type != Parameter::PARAMETER_VOID)
193                                 {
194                                         instructionString += (destinationParameter.type != Parameter::PARAMETER_VOID || i > 0) ? ", " : " ";
195                                         instructionString += sourceParameter[i].preModifierString() +
196                                                                                  sourceParameter[i].string(shaderType, version) +
197                                                                                  sourceParameter[i].relativeString() + 
198                                                                                  sourceParameter[i].postModifierString() + 
199                                                                                  sourceParameter[i].swizzleString();
200                                 }
201                         }
202                 }
203                 else   // DCL
204                 {
205                         instructionString += "dcl";
206
207                         if(destinationParameter.type == Parameter::PARAMETER_SAMPLER)
208                         {
209                                 switch(operation.samplerType)
210                                 {
211                                 case Operation::SAMPLER_UNKNOWN:        instructionString += " ";                       break;
212                                 case Operation::SAMPLER_1D:                     instructionString += "_1d ";            break;
213                                 case Operation::SAMPLER_2D:                     instructionString += "_2d ";            break;
214                                 case Operation::SAMPLER_CUBE:           instructionString += "_cube ";          break;
215                                 case Operation::SAMPLER_VOLUME:         instructionString += "_volume ";        break;
216                                 default:
217                                         ASSERT(false);
218                                 }
219
220                                 instructionString += destinationParameter.string(shaderType, version);
221                         }
222                         else if(destinationParameter.type == Parameter::PARAMETER_INPUT ||
223                                     destinationParameter.type == Parameter::PARAMETER_OUTPUT ||
224                                     destinationParameter.type == Parameter::PARAMETER_TEXTURE)
225                         {
226                                 if(version >= 0x0300)
227                                 {
228                                         switch(operation.usage)
229                                         {
230                                         case Operation::USAGE_POSITION:         instructionString += "_position";               break;
231                                         case Operation::USAGE_BLENDWEIGHT:      instructionString += "_blendweight";    break;
232                                         case Operation::USAGE_BLENDINDICES:     instructionString += "_blendindices";   break;
233                                         case Operation::USAGE_NORMAL:           instructionString += "_normal";                 break;
234                                         case Operation::USAGE_PSIZE:            instructionString += "_psize";                  break;
235                                         case Operation::USAGE_TEXCOORD:         instructionString += "_texcoord";               break;
236                                         case Operation::USAGE_TANGENT:          instructionString += "_tangent";                break;
237                                         case Operation::USAGE_BINORMAL:         instructionString += "_binormal";               break;
238                                         case Operation::USAGE_TESSFACTOR:       instructionString += "_tessfactor";             break;
239                                         case Operation::USAGE_POSITIONT:        instructionString += "_positiont";              break;
240                                         case Operation::USAGE_COLOR:            instructionString += "_color";                  break;
241                                         case Operation::USAGE_FOG:                      instructionString += "_fog";                    break;
242                                         case Operation::USAGE_DEPTH:            instructionString += "_depth";                  break;
243                                         case Operation::USAGE_SAMPLE:           instructionString += "_sample";                 break;
244                                         default:
245                                                 ASSERT(false);
246                                         }
247
248                                         if(operation.usageIndex > 0)
249                                         {
250                                                 std::ostringstream buffer;
251
252                                                 buffer << (int)operation.usageIndex;
253
254                                                 instructionString += buffer.str();
255                                         }
256                                 }
257                                 else ASSERT(destinationParameter.type != Parameter::PARAMETER_OUTPUT);
258
259                                 instructionString += " ";
260
261                                 instructionString += destinationParameter.string(shaderType, version);
262                                 instructionString += destinationParameter.maskString();
263                         }
264                         else if(destinationParameter.type == Parameter::PARAMETER_MISCTYPE)   // vPos and vFace
265                         {
266                                 instructionString += " ";
267
268                                 instructionString += destinationParameter.string(shaderType, version);
269                         }
270                         else ASSERT(false);
271                 }
272
273                 return instructionString;
274         }
275
276         std::string Shader::Instruction::Operation::string(unsigned short version) const
277         {
278                 switch(opcode)
279                 {
280                 case OPCODE_NOP:                        return "nop";
281                 case OPCODE_MOV:                        return "mov";
282                 case OPCODE_ADD:                        return "add";
283                 case OPCODE_SUB:                        return "sub";
284                 case OPCODE_MAD:                        return "mad";
285                 case OPCODE_MUL:                        return "mul";
286                 case OPCODE_RCP:                        return "rcp";
287                 case OPCODE_RSQ:                        return "rsq";
288                 case OPCODE_DP3:                        return "dp3";
289                 case OPCODE_DP4:                        return "dp4";
290                 case OPCODE_MIN:                        return "min";
291                 case OPCODE_MAX:                        return "max";
292                 case OPCODE_SLT:                        return "slt";
293                 case OPCODE_SGE:                        return "sge";
294                 case OPCODE_EXP:                        return "exp";
295                 case OPCODE_LOG:                        return "log";
296                 case OPCODE_LIT:                        return "lit";
297                 case OPCODE_DST:                        return "dst";
298                 case OPCODE_LRP:                        return "lrp";
299                 case OPCODE_FRC:                        return "frc";
300                 case OPCODE_M4X4:                       return "m4x4";
301                 case OPCODE_M4X3:                       return "m4x3";
302                 case OPCODE_M3X4:                       return "m3x4";
303                 case OPCODE_M3X3:                       return "m3x3";
304                 case OPCODE_M3X2:                       return "m3x2";
305                 case OPCODE_CALL:                       return "call";
306                 case OPCODE_CALLNZ:                     return "callnz";
307                 case OPCODE_LOOP:                       return "loop";
308                 case OPCODE_RET:                        return "ret";
309                 case OPCODE_ENDLOOP:            return "endloop";
310                 case OPCODE_LABEL:                      return "label";
311                 case OPCODE_DCL:                        return "dcl";
312                 case OPCODE_POW:                        return "pow";
313                 case OPCODE_CRS:                        return "crs";
314                 case OPCODE_SGN:                        return "sgn";
315                 case OPCODE_ABS:                        return "abs";
316                 case OPCODE_NRM:                        return "nrm";
317                 case OPCODE_SINCOS:                     return "sincos";
318                 case OPCODE_REP:                        return "rep";
319                 case OPCODE_ENDREP:                     return "endrep";
320                 case OPCODE_IF:                         return "if";
321                 case OPCODE_IFC:                        return "ifc";
322                 case OPCODE_ELSE:                       return "else";
323                 case OPCODE_ENDIF:                      return "endif";
324                 case OPCODE_BREAK:                      return "break";
325                 case OPCODE_BREAKC:                     return "breakc";
326                 case OPCODE_MOVA:                       return "mova";
327                 case OPCODE_DEFB:                       return "defb";
328                 case OPCODE_DEFI:                       return "defi";
329                 case OPCODE_TEXCOORD:           return "texcoord";
330                 case OPCODE_TEXKILL:            return "texkill";
331                 case OPCODE_TEX:
332                         if(version < 0x0104)    return "tex";
333                         else                                    return "texld";
334                 case OPCODE_TEXBEM:                     return "texbem";
335                 case OPCODE_TEXBEML:            return "texbeml";
336                 case OPCODE_TEXREG2AR:          return "texreg2ar";
337                 case OPCODE_TEXREG2GB:          return "texreg2gb";
338                 case OPCODE_TEXM3X2PAD:         return "texm3x2pad";
339                 case OPCODE_TEXM3X2TEX:         return "texm3x2tex";
340                 case OPCODE_TEXM3X3PAD:         return "texm3x3pad";
341                 case OPCODE_TEXM3X3TEX:         return "texm3x3tex";
342                 case OPCODE_RESERVED0:          return "reserved0";
343                 case OPCODE_TEXM3X3SPEC:        return "texm3x3spec";
344                 case OPCODE_TEXM3X3VSPEC:       return "texm3x3vspec";
345                 case OPCODE_EXPP:                       return "expp";
346                 case OPCODE_LOGP:                       return "logp";
347                 case OPCODE_CND:                        return "cnd";
348                 case OPCODE_DEF:                        return "def";
349                 case OPCODE_TEXREG2RGB:         return "texreg2rgb";
350                 case OPCODE_TEXDP3TEX:          return "texdp3tex";
351                 case OPCODE_TEXM3X2DEPTH:       return "texm3x2depth";
352                 case OPCODE_TEXDP3:                     return "texdp3";
353                 case OPCODE_TEXM3X3:            return "texm3x3";
354                 case OPCODE_TEXDEPTH:           return "texdepth";
355                 case OPCODE_CMP:                        return "cmp";
356                 case OPCODE_BEM:                        return "bem";
357                 case OPCODE_DP2ADD:                     return "dp2add";
358                 case OPCODE_DSX:                        return "dsx";
359                 case OPCODE_DSY:                        return "dsy";
360                 case OPCODE_TEXLDD:                     return "texldd";
361                 case OPCODE_SETP:                       return "setp";
362                 case OPCODE_TEXLDL:                     return "texldl";
363                 case OPCODE_BREAKP:                     return "breakp";
364                 case OPCODE_PHASE:                      return "phase";
365                 case OPCODE_COMMENT:            return "comment";
366                 case OPCODE_END:                        return "end";
367                 case OPCODE_PS_1_0:                     return "ps_1_0";
368                 case OPCODE_PS_1_1:                     return "ps_1_1";
369                 case OPCODE_PS_1_2:                     return "ps_1_2";
370                 case OPCODE_PS_1_3:                     return "ps_1_3";
371                 case OPCODE_PS_1_4:                     return "ps_1_4";
372                 case OPCODE_PS_2_0:                     return "ps_2_0";
373                 case OPCODE_PS_2_x:                     return "ps_2_x";
374                 case OPCODE_PS_3_0:                     return "ps_3_0";
375                 case OPCODE_VS_1_0:                     return "vs_1_0";
376                 case OPCODE_VS_1_1:                     return "vs_1_1";
377                 case OPCODE_VS_2_0:                     return "vs_2_0";
378                 case OPCODE_VS_2_x:                     return "vs_2_x";
379                 case OPCODE_VS_2_sw:            return "vs_2_sw";
380                 case OPCODE_VS_3_0:                     return "vs_3_0";
381                 case OPCODE_VS_3_sw:            return "vs_3_sw";
382                 default:
383                         ASSERT(false);
384                 }
385
386                 return "<unknown>";
387         }
388
389         std::string Shader::Instruction::Operation::controlString() const
390         {
391                 if(opcode != OPCODE_LOOP && opcode != OPCODE_BREAKC && opcode != OPCODE_IFC && opcode != OPCODE_SETP)
392                 {
393                         if(project) return "p";
394
395                         if(bias) return "b";
396
397                         // FIXME: LOD
398                 }
399
400                 switch(control)
401                 {
402                 case 1: return "_gt";
403                 case 2: return "_eq";
404                 case 3: return "_ge";
405                 case 4: return "_lt";
406                 case 5: return "_ne";
407                 case 6: return "_le";
408                 default:
409                         return "";
410                 //      ASSERT(false);   // FIXME
411                 }
412         }
413
414         std::string Shader::Instruction::DestinationParameter::modifierString() const
415         {
416                 if(type == PARAMETER_VOID || type == PARAMETER_LABEL)
417                 {
418                         return "";
419                 }
420
421                 std::string modifierString;
422
423                 if(saturate)
424                 {
425                         modifierString += "_sat";
426                 }
427
428                 if(partialPrecision)
429                 {
430                         modifierString += "_pp";
431                 }
432
433                 if(centroid)
434                 {
435                         modifierString += "_centroid";
436                 }
437
438                 return modifierString;
439         }
440
441         std::string Shader::Instruction::DestinationParameter::shiftString() const
442         {
443                 if(type == PARAMETER_VOID || type == PARAMETER_LABEL)
444                 {
445                         return "";
446                 }
447
448                 switch(shift)
449                 {
450                 case 0:         return "";
451                 case 1:         return "_x2";
452                 case 2:         return "_x4"; 
453                 case 3:         return "_x8";
454                 case -1:        return "_d2";
455                 case -2:        return "_d4"; 
456                 case -3:        return "_d8";
457                 default:
458                         return "";
459                 //      ASSERT(false);   // FIXME
460                 }
461         }
462
463         std::string Shader::Instruction::DestinationParameter::maskString() const
464         {
465                 if(type == PARAMETER_VOID || type == PARAMETER_LABEL)
466                 {
467                         return "";
468                 }
469
470                 switch(mask)
471                 {
472                 case 0x0:       return "";
473                 case 0x1:       return ".x";
474                 case 0x2:       return ".y";
475                 case 0x3:       return ".xy";
476                 case 0x4:       return ".z";
477                 case 0x5:       return ".xz";
478                 case 0x6:       return ".yz";
479                 case 0x7:       return ".xyz";
480                 case 0x8:       return ".w";
481                 case 0x9:       return ".xw";
482                 case 0xA:       return ".yw";
483                 case 0xB:       return ".xyw";
484                 case 0xC:       return ".zw";
485                 case 0xD:       return ".xzw";
486                 case 0xE:       return ".yzw";
487                 case 0xF:       return "";
488                 default:
489                         ASSERT(false);
490                 }
491
492                 return "";
493         }
494
495         std::string Shader::Instruction::SourceParameter::preModifierString() const
496         {
497                 if(type == PARAMETER_VOID)
498                 {
499                         return "";
500                 }
501
502                 switch(modifier)
503                 {
504                 case MODIFIER_NONE:                     return "";
505                 case MODIFIER_NEGATE:           return "-";
506                 case MODIFIER_BIAS:                     return "";
507                 case MODIFIER_BIAS_NEGATE:      return "-";
508                 case MODIFIER_SIGN:                     return "";
509                 case MODIFIER_SIGN_NEGATE:      return "-";
510                 case MODIFIER_COMPLEMENT:       return "1-";
511                 case MODIFIER_X2:                       return "";
512                 case MODIFIER_X2_NEGATE:        return "-";
513                 case MODIFIER_DZ:                       return "";
514                 case MODIFIER_DW:                       return "";
515                 case MODIFIER_ABS:                      return "";
516                 case MODIFIER_ABS_NEGATE:       return "-";
517                 case MODIFIER_NOT:                      return "!";
518                 default:
519                         ASSERT(false);
520                 }
521
522                 return "";
523         }
524
525         std::string Shader::Instruction::Parameter::relativeString() const
526         {
527                 if(!relative) return "";
528
529                 if(relativeType == Parameter::PARAMETER_ADDR)
530                 {
531                         switch(relativeSwizzle & 0x03)
532                         {
533                         case 0: return "[a0.x]";
534                         case 1: return "[a0.y]";
535                         case 2: return "[a0.z]";
536                         case 3: return "[a0.w]";
537                         }
538                 }
539                 else if(relativeType == Parameter::PARAMETER_LOOP)
540                 {
541                         return "[aL]";
542                 }
543                 else ASSERT(false);
544
545                 return "";
546         }
547
548         std::string Shader::Instruction::SourceParameter::postModifierString() const
549         {
550                 if(type == PARAMETER_VOID)
551                 {
552                         return "";
553                 }
554
555                 switch(modifier)
556                 {
557                 case MODIFIER_NONE:                     return "";
558                 case MODIFIER_NEGATE:           return "";
559                 case MODIFIER_BIAS:                     return "_bias";
560                 case MODIFIER_BIAS_NEGATE:      return "_bias";
561                 case MODIFIER_SIGN:                     return "_bx2";
562                 case MODIFIER_SIGN_NEGATE:      return "_bx2";
563                 case MODIFIER_COMPLEMENT:       return "";
564                 case MODIFIER_X2:                       return "_x2";
565                 case MODIFIER_X2_NEGATE:        return "_x2";
566                 case MODIFIER_DZ:                       return "_dz";
567                 case MODIFIER_DW:                       return "_dw";
568                 case MODIFIER_ABS:                      return "_abs";
569                 case MODIFIER_ABS_NEGATE:       return "_abs";
570                 case MODIFIER_NOT:                      return "";
571                 default:
572                         ASSERT(false);
573                 }
574
575                 return "";
576         }
577
578         std::string Shader::Instruction::SourceParameter::swizzleString() const
579         {
580                 return Instruction::swizzleString(type, swizzle);
581         }
582
583         void Shader::Instruction::parseOperationToken(unsigned long token, unsigned char majorVersion)
584         {
585                 if((token & 0xFFFF0000) == 0xFFFF0000 || (token & 0xFFFF0000) == 0xFFFE0000)   // Version token
586                 {
587                         operation.opcode = (Operation::Opcode)token;
588                         operation.predicate = false;
589                         operation.coissue = false;
590                 }
591                 else
592                 {
593                         operation.opcode = (Operation::Opcode)(token & 0x0000FFFF);
594                         operation.control = (Operation::Control)((token & 0x00FF0000) >> 16);
595
596                         int size = (token & 0x0F000000) >> 24;
597
598                         operation.predicate = (token & 0x10000000) != 0x00000000;
599                         operation.coissue = (token & 0x40000000) != 0x00000000;
600
601                         if(majorVersion < 2)
602                         {
603                                 if(size != 0)
604                                 {
605                                         ASSERT(false);   // Reserved
606                                 }
607                         }
608
609                         if(majorVersion < 2)
610                         {
611                                 if(operation.predicate)
612                                 {
613                                         ASSERT(false);
614                                 }
615                         }
616
617                         if((token & 0x20000000) != 0x00000000)
618                         {
619                                 ASSERT(false);   // Reserved
620                         }
621
622                         if(majorVersion >= 2)
623                         {
624                                 if(operation.coissue)
625                                 {
626                                         ASSERT(false);   // Reserved
627                                 }
628                         }
629
630                         if((token & 0x80000000) != 0x00000000)
631                         {
632                                 ASSERT(false);
633                         }
634                 }
635         }
636
637         void Shader::Instruction::parseDeclarationToken(unsigned long token)
638         {
639                 operation.samplerType = (Operation::SamplerType)((token & 0x78000000) >> 27);
640                 operation.usage = (Operation::Usage)(token & 0x0000001F);
641                 operation.usageIndex = (unsigned char)((token & 0x000F0000) >> 16);
642         }
643
644         void Shader::Instruction::parseDestinationToken(const unsigned long *token, unsigned char majorVersion)
645         {
646                 destinationParameter.index = (unsigned short)(token[0] & 0x000007FF);
647                 destinationParameter.type = (Parameter::Type)(((token[0] & 0x00001800) >> 8) | ((token[0] & 0x70000000) >> 28));
648
649                 // TODO: Check type and index range
650
651                 destinationParameter.relative = (token[0] & 0x00002000) != 0x00000000;
652                 destinationParameter.relativeType = Parameter::PARAMETER_ADDR;
653                 destinationParameter.relativeSwizzle = 0x00;
654
655                 if(destinationParameter.relative && majorVersion >= 3)
656                 {
657                         destinationParameter.relativeType = (Parameter::Type)(((token[1] & 0x00001800) >> 8) | ((token[1] & 0x70000000) >> 28));
658                         destinationParameter.relativeSwizzle = (unsigned char)((token[1] & 0x00FF0000) >> 16);
659                 }
660                 else if(destinationParameter.relative) ASSERT(false);   // Reserved
661
662                 if((token[0] & 0x0000C000) != 0x00000000)
663                 {
664                         ASSERT(false);   // Reserved
665                 }
666
667                 destinationParameter.mask = (unsigned char)((token[0] & 0x000F0000) >> 16);
668                 destinationParameter.saturate = (token[0] & 0x00100000) != 0;
669                 destinationParameter.partialPrecision = (token[0] & 0x00200000) != 0;
670                 destinationParameter.centroid = (token[0] & 0x00400000) != 0;
671                 destinationParameter.shift = (signed char)((token[0] & 0x0F000000) >> 20) >> 4;
672
673                 if(majorVersion >= 2)
674                 {
675                         if(destinationParameter.shift)
676                         {
677                                 ASSERT(false);   // Reserved
678                         }
679                 }
680
681                 if((token[0] & 0x80000000) != 0x80000000)
682                 {
683                         ASSERT(false);
684                 }
685         }
686
687         void Shader::Instruction::parseSourceToken(int i, const unsigned long *token, unsigned char majorVersion)
688         {
689                 // Defaults
690                 sourceParameter[i].value = (float&)*token;
691                 sourceParameter[i].type = Parameter::PARAMETER_VOID;
692                 sourceParameter[i].modifier = SourceParameter::MODIFIER_NONE;
693                 sourceParameter[i].swizzle = 0xE4;
694                 sourceParameter[i].relative = false;
695                 sourceParameter[i].relativeType = Parameter::PARAMETER_ADDR;
696                 sourceParameter[i].relativeSwizzle = 0x00;
697                 
698                 switch(operation.opcode)
699                 {
700                 case Instruction::Operation::OPCODE_DEF:
701                         sourceParameter[i].type = Parameter::PARAMETER_FLOATLITERAL;
702                         break;
703                 case Instruction::Operation::OPCODE_DEFB:
704                         sourceParameter[i].type = Parameter::PARAMETER_BOOLLITERAL;
705                         break;
706                 case Instruction::Operation::OPCODE_DEFI:
707                         sourceParameter[i].type = Parameter::PARAMETER_INTLITERAL;
708                         break;
709                 default:
710                         sourceParameter[i].index = (unsigned short)(token[0] & 0x000007FF);
711                         sourceParameter[i].type = (Parameter::Type)(((token[0] & 0x00001800) >> 8) | ((token[0] & 0x70000000) >> 28));
712
713                         // FIXME: Check type and index range
714
715                         sourceParameter[i].relative = (token[0] & 0x00002000) != 0x00000000;
716
717                         if((token[0] & 0x0000C000) != 0x00000000)
718                         {
719                                 if(operation.opcode != Operation::OPCODE_DEF &&
720                                    operation.opcode != Operation::OPCODE_DEFI &&
721                                    operation.opcode != Operation::OPCODE_DEFB)
722                                 {
723                                         ASSERT(false);
724                                 }
725                         }
726
727                         sourceParameter[i].swizzle = (unsigned char)((token[0] & 0x00FF0000) >> 16);
728                         sourceParameter[i].modifier = (SourceParameter::Modifier)((token[0] & 0x0F000000) >> 24);
729
730                         if((token[0] & 0x80000000) != 0x80000000)
731                         {
732                                 if(operation.opcode != Operation::OPCODE_DEF &&
733                                    operation.opcode != Operation::OPCODE_DEFI &&
734                                    operation.opcode != Operation::OPCODE_DEFB)
735                                 {
736                                         ASSERT(false);
737                                 }
738                         }
739
740                         if(sourceParameter[i].relative && majorVersion >= 2)
741                         {
742                                 sourceParameter[i].relativeType = (Parameter::Type)(((token[1] & 0x00001800) >> 8) | ((token[1] & 0x70000000) >> 28));
743                                 sourceParameter[i].relativeSwizzle = (unsigned char)((token[1] & 0x00FF0000) >> 16);
744                         }
745                 }
746         }
747
748         std::string Shader::Instruction::swizzleString(Parameter::Type type, unsigned char swizzle)
749         {
750                 if(type == Parameter::PARAMETER_VOID || type == Parameter::PARAMETER_LABEL || swizzle == 0xE4)
751                 {
752                         return "";
753                 }
754
755                 int x = (swizzle & 0x03) >> 0;
756                 int y = (swizzle & 0x0C) >> 2;
757                 int z = (swizzle & 0x30) >> 4;
758                 int w = (swizzle & 0xC0) >> 6;
759
760                 std::string swizzleString = ".";
761
762                 switch(x)
763                 {
764                 case 0: swizzleString += "x"; break;
765                 case 1: swizzleString += "y"; break;
766                 case 2: swizzleString += "z"; break;
767                 case 3: swizzleString += "w"; break;
768                 }
769
770                 if(!(x == y && y == z && z == w))
771                 {
772                         switch(y)
773                         {
774                         case 0: swizzleString += "x"; break;
775                         case 1: swizzleString += "y"; break;
776                         case 2: swizzleString += "z"; break;
777                         case 3: swizzleString += "w"; break;
778                         }
779
780                         if(!(y == z && z == w))
781                         {
782                                 switch(z)
783                                 {
784                                 case 0: swizzleString += "x"; break;
785                                 case 1: swizzleString += "y"; break;
786                                 case 2: swizzleString += "z"; break;
787                                 case 3: swizzleString += "w"; break;
788                                 }
789
790                                 if(!(z == w))
791                                 {
792                                         switch(w)
793                                         {
794                                         case 0: swizzleString += "x"; break;
795                                         case 1: swizzleString += "y"; break;
796                                         case 2: swizzleString += "z"; break;
797                                         case 3: swizzleString += "w"; break;
798                                         }
799                                 }
800                         }
801                 }
802
803                 return swizzleString;
804         }
805
806         std::string Shader::Instruction::Parameter::string(ShaderType shaderType, unsigned short version) const
807         {
808                 std::ostringstream buffer;
809
810                 if(type == PARAMETER_FLOATLITERAL)
811                 {
812                         buffer << value;
813
814                         return buffer.str();
815                 }
816                 else
817                 {
818                         if(type != PARAMETER_RASTOUT && !(type == PARAMETER_ADDR && shaderType == SHADER_VERTEX) && type != PARAMETER_LOOP && type != PARAMETER_PREDICATE && type != PARAMETER_MISCTYPE)
819                         {
820                                 buffer << index;
821
822                                 return typeString(shaderType, version) + buffer.str();
823                         }
824                         else
825                         {
826                                 return typeString(shaderType, version);
827                         }
828                 }
829         }
830
831         std::string Shader::Instruction::Parameter::typeString(ShaderType shaderType, unsigned short version) const
832         {
833                 switch(type)
834                 {
835                 case PARAMETER_TEMP:                    return "r";
836                 case PARAMETER_INPUT:                   return "v";
837                 case PARAMETER_CONST:                   return "c";
838                 case PARAMETER_TEXTURE:
839         //      case PARAMETER_ADDR:
840                         if(shaderType == SHADER_PIXEL)  return "t";
841                         else                                                    return "a0";
842                 case PARAMETER_RASTOUT:
843                         if(index == 0)              return "oPos";
844                         else if(index == 1)         return "oFog";
845                         else if(index == 2)         return "oPts";
846                         else                        ASSERT(false);
847                 case PARAMETER_ATTROUT:                 return "oD";
848                 case PARAMETER_TEXCRDOUT:
849         //      case PARAMETER_OUTPUT:                  return "";
850                         if(version < 0x0300)            return "oT";
851                         else                                            return "o";
852                 case PARAMETER_CONSTINT:                return "i";
853                 case PARAMETER_COLOROUT:                return "oC";
854                 case PARAMETER_DEPTHOUT:                return "oDepth";
855                 case PARAMETER_SAMPLER:                 return "s";
856         //      case PARAMETER_CONST2:                  return "";
857         //      case PARAMETER_CONST3:                  return "";
858         //      case PARAMETER_CONST4:                  return "";
859                 case PARAMETER_CONSTBOOL:               return "b";
860                 case PARAMETER_LOOP:                    return "aL";
861         //      case PARAMETER_TEMPFLOAT16:             return "";
862                 case PARAMETER_MISCTYPE:
863                         if(index == 0)                          return "vPos";
864                         else if(index == 1)                     return "vFace";
865                         else                                            ASSERT(false);
866                 case PARAMETER_LABEL:                   return "l";
867                 case PARAMETER_PREDICATE:               return "p0";
868                 case PARAMETER_FLOATLITERAL:    return "";
869                 case PARAMETER_BOOLLITERAL:             return "";
870                 case PARAMETER_INTLITERAL:              return "";
871         //      case PARAMETER_VOID:                    return "";
872                 default:
873                         ASSERT(false);
874                 }
875
876                 return "";
877         }
878
879         Shader::Shader(const unsigned long *shaderToken)
880         {
881                 instruction = 0;
882                 length = 0;
883
884                 tokenCount = 0;
885
886                 while(shaderToken[tokenCount] != 0x0000FFFF)
887                 {
888                         tokenCount += sw::Shader::size(shaderToken[tokenCount], (unsigned short)(shaderToken[0] & 0xFFFF)) + 1;
889                 }
890
891                 tokenCount += 1;
892
893                 this->shaderToken = new unsigned long[tokenCount];
894                 memcpy(this->shaderToken, shaderToken, tokenCount * sizeof(unsigned long));
895
896                 unsigned long *hashTokens = new unsigned long[tokenCount];
897                 memcpy(hashTokens, shaderToken, tokenCount * sizeof(unsigned long));
898                 removeComments(hashTokens, tokenCount);
899                 hash = FNV_1((unsigned char*)hashTokens, tokenCount * sizeof(unsigned long));
900                 delete[] hashTokens;
901         }
902
903         Shader::~Shader()
904         {
905                 delete[] shaderToken;
906                 shaderToken = 0;
907
908                 for(int i = 0; i < length; i++)
909                 {
910                         delete instruction[i];
911                         instruction[i] = 0;
912                 }
913
914                 delete[] instruction;
915                 instruction = 0;
916         }
917
918         void Shader::getFunction(void *data, unsigned int *size)
919         {
920                 if(data)
921                 {
922                         memcpy(data, shaderToken, tokenCount * 4);
923                 }
924
925                 *size = tokenCount * 4;
926         }
927
928         int Shader::size(unsigned long opcode) const
929         {
930                 return size(opcode, version);
931         }
932
933         int Shader::size(unsigned long opcode, unsigned short version)
934         {
935                 if(version > 0x0300)
936                 {
937                         ASSERT(false);
938                 }
939
940                 static const char size[] =
941                 {
942                         0,   // NOP = 0
943                         2,   // MOV
944                         3,   // ADD
945                         3,   // SUB
946                         4,   // MAD
947                         3,   // MUL
948                         2,   // RCP
949                         2,   // RSQ
950                         3,   // DP3
951                         3,   // DP4
952                         3,   // MIN
953                         3,   // MAX
954                         3,   // SLT
955                         3,   // SGE
956                         2,   // EXP
957                         2,   // LOG
958                         2,   // LIT
959                         3,   // DST
960                         4,   // LRP
961                         2,   // FRC
962                         3,   // M4x4
963                         3,   // M4x3
964                         3,   // M3x4
965                         3,   // M3x3
966                         3,   // M3x2
967                         1,   // CALL
968                         2,   // CALLNZ
969                         2,   // LOOP
970                         0,   // RET
971                         0,   // ENDLOOP
972                         1,   // LABEL
973                         2,   // DCL
974                         3,   // POW
975                         3,   // CRS
976                         4,   // SGN
977                         2,   // ABS
978                         2,   // NRM
979                         4,   // SINCOS
980                         1,   // REP
981                         0,   // ENDREP
982                         1,   // IF
983                         2,   // IFC
984                         0,   // ELSE
985                         0,   // ENDIF
986                         0,   // BREAK
987                         2,   // BREAKC
988                         2,   // MOVA
989                         2,   // DEFB
990                         5,   // DEFI
991                         -1,  // 49
992                         -1,  // 50
993                         -1,  // 51
994                         -1,  // 52
995                         -1,  // 53
996                         -1,  // 54
997                         -1,  // 55
998                         -1,  // 56
999                         -1,  // 57
1000                         -1,  // 58
1001                         -1,  // 59
1002                         -1,  // 60
1003                         -1,  // 61
1004                         -1,  // 62
1005                         -1,  // 63
1006                         1,   // TEXCOORD = 64
1007                         1,   // TEXKILL
1008                         1,   // TEX
1009                         2,   // TEXBEM
1010                         2,   // TEXBEML
1011                         2,   // TEXREG2AR
1012                         2,   // TEXREG2GB
1013                         2,   // TEXM3x2PAD
1014                         2,   // TEXM3x2TEX
1015                         2,   // TEXM3x3PAD
1016                         2,   // TEXM3x3TEX
1017                         -1,  // RESERVED0
1018                         3,   // TEXM3x3SPEC
1019                         2,   // TEXM3x3VSPEC
1020                         2,   // EXPP
1021                         2,   // LOGP
1022                         4,   // CND
1023                         5,   // DEF
1024                         2,   // TEXREG2RGB
1025                         2,   // TEXDP3TEX
1026                         2,   // TEXM3x2DEPTH
1027                         2,   // TEXDP3
1028                         2,   // TEXM3x3
1029                         1,   // TEXDEPTH
1030                         4,   // CMP
1031                         3,   // BEM
1032                         4,   // DP2ADD
1033                         2,   // DSX
1034                         2,   // DSY
1035                         5,   // TEXLDD
1036                         3,   // SETP
1037                         3,   // TEXLDL
1038                         2,   // BREAKP
1039                         -1,  // 97
1040                         -1,  // 98
1041                         -1,  // 99
1042                         -1,  // 100
1043                         -1,  // 101
1044                         -1,  // 102
1045                         -1,  // 103
1046                         -1,  // 104
1047                         -1,  // 105
1048                         -1,  // 106
1049                         -1,  // 107
1050                         -1,  // 108
1051                         -1,  // 109
1052                         -1,  // 110
1053                         -1,  // 111
1054                         -1,  // 112
1055                 };
1056
1057                 int length = 0;
1058
1059                 if((opcode & 0x0000FFFF) == ShaderOperation::OPCODE_COMMENT)
1060                 {
1061                         return (opcode & 0x7FFF0000) >> 16;
1062                 }
1063
1064                 if(opcode != ShaderOperation::OPCODE_PS_1_0 &&
1065                    opcode != ShaderOperation::OPCODE_PS_1_1 &&
1066                    opcode != ShaderOperation::OPCODE_PS_1_2 &&
1067                    opcode != ShaderOperation::OPCODE_PS_1_3 &&
1068                    opcode != ShaderOperation::OPCODE_PS_1_4 &&
1069                    opcode != ShaderOperation::OPCODE_PS_2_0 &&
1070                    opcode != ShaderOperation::OPCODE_PS_2_x &&
1071                    opcode != ShaderOperation::OPCODE_PS_3_0 &&
1072                    opcode != ShaderOperation::OPCODE_VS_1_0 &&
1073                    opcode != ShaderOperation::OPCODE_VS_1_1 &&
1074                    opcode != ShaderOperation::OPCODE_VS_2_0 &&
1075                    opcode != ShaderOperation::OPCODE_VS_2_x &&
1076                    opcode != ShaderOperation::OPCODE_VS_2_sw &&
1077                    opcode != ShaderOperation::OPCODE_VS_3_0 &&
1078                    opcode != ShaderOperation::OPCODE_VS_3_sw &&
1079                    opcode != ShaderOperation::OPCODE_PHASE &&
1080                    opcode != ShaderOperation::OPCODE_END)
1081                 {
1082                         if(version >= 0x0200)
1083                         {
1084                                 length = (opcode & 0x0F000000) >> 24;
1085                         }
1086                         else
1087                         {
1088                                 length = size[opcode & 0x0000FFFF];
1089                         }
1090                 }
1091
1092                 if(length < 0)
1093                 {
1094                         ASSERT(false);
1095                 }
1096
1097                 if(version == 0x0104)
1098                 {
1099                         switch(opcode & 0x0000FFFF)
1100                         {
1101                         case ShaderOperation::OPCODE_TEX:
1102                                 length += 1;
1103                                 break;
1104                         case ShaderOperation::OPCODE_TEXCOORD:
1105                                 length += 1;
1106                                 break;
1107                         default:
1108                                 break;
1109                         }
1110                 }
1111
1112                 return length;
1113         }
1114
1115         bool Shader::maskContainsComponent(int mask, int component)
1116         {
1117                 return (mask & (1 << component)) != 0;
1118         }
1119
1120         bool Shader::swizzleContainsComponent(int swizzle, int component)
1121         {
1122                 if((swizzle & 0x03) >> 0 == component) return true;
1123                 if((swizzle & 0x0C) >> 2 == component) return true;
1124                 if((swizzle & 0x30) >> 4 == component) return true;
1125                 if((swizzle & 0xC0) >> 6 == component) return true;
1126
1127                 return false;
1128         }
1129
1130         bool Shader::swizzleContainsComponentMasked(int swizzle, int component, int mask)
1131         {
1132                 if(mask & 0x1) if((swizzle & 0x03) >> 0 == component) return true;
1133                 if(mask & 0x2) if((swizzle & 0x0C) >> 2 == component) return true;
1134                 if(mask & 0x4) if((swizzle & 0x30) >> 4 == component) return true;
1135                 if(mask & 0x8) if((swizzle & 0xC0) >> 6 == component) return true;
1136
1137                 return false;
1138         }
1139
1140         bool Shader::containsDynamicBranching() const
1141         {
1142                 return dynamicBranching;
1143         }
1144
1145         bool Shader::usesSampler(int index) const
1146         {
1147                 return (sampler & (1 << index)) != 0;
1148         }
1149
1150         int64_t Shader::getHash() const
1151         {
1152                 return hash;
1153         }
1154
1155         int Shader::getLength() const
1156         {
1157                 return length;
1158         }
1159
1160         Shader::ShaderType Shader::getShaderType() const
1161         {
1162                 return shaderType;
1163         }
1164
1165         unsigned short Shader::getVersion() const
1166         {
1167                 return version;
1168         }
1169
1170         void Shader::print(const char *fileName, ...) const
1171         {
1172                 char fullName[1024 + 1];
1173
1174                 va_list vararg;
1175                 va_start(vararg, fileName);
1176                 vsnprintf(fullName, 1024, fileName, vararg);
1177                 va_end(vararg);
1178
1179                 std::ofstream file(fullName, std::ofstream::out | std::ofstream::app);
1180
1181                 for(int i = 0; i < length; i++)
1182                 {
1183                         file << instruction[i]->string(shaderType, version) << std::endl;
1184                 }
1185         }
1186
1187         void Shader::printInstruction(int index, const char *fileName) const
1188         {
1189                 std::ofstream file(fileName, std::ofstream::out | std::ofstream::app);
1190
1191                 file << instruction[index]->string(shaderType, version) << std::endl;
1192         }
1193
1194         const ShaderInstruction *Shader::getInstruction(int i) const
1195         {
1196                 if(i < 0 || i >= length)
1197                 {
1198                         ASSERT(false);
1199                 }
1200
1201                 return instruction[i];
1202         }
1203
1204         void Shader::analyzeDirtyConstants()
1205         {
1206                 dirtyConstantsF = 0;
1207                 dirtyConstantsI = 0;
1208                 dirtyConstantsB = 0;
1209
1210                 for(int i = 0; i < length; i++)
1211                 {
1212                         switch(instruction[i]->operation.opcode)
1213                         {
1214                         case ShaderOperation::OPCODE_DEF:
1215                                 if(instruction[i]->destinationParameter.index + 1 > dirtyConstantsF)
1216                                 {
1217                                         dirtyConstantsF = instruction[i]->destinationParameter.index + 1;
1218                                 }
1219                                 break;
1220                         case ShaderOperation::OPCODE_DEFI:
1221                                 if(instruction[i]->destinationParameter.index + 1 > dirtyConstantsI)
1222                                 {
1223                                         dirtyConstantsI = instruction[i]->destinationParameter.index + 1;
1224                                 }
1225                                 break;
1226                         case ShaderOperation::OPCODE_DEFB:
1227                                 if(instruction[i]->destinationParameter.index + 1 > dirtyConstantsB)
1228                                 {
1229                                         dirtyConstantsB = instruction[i]->destinationParameter.index + 1;
1230                                 }
1231                                 break;
1232                         }
1233                 }
1234         }
1235
1236         void Shader::analyzeDynamicBranching()
1237         {
1238                 dynamicBranching = false;
1239
1240                 for(int i = 0; i < length; i++)
1241                 {
1242                         switch(instruction[i]->getOpcode())
1243                         {
1244                         case ShaderOperation::OPCODE_CALLNZ:
1245                         case ShaderOperation::OPCODE_IF:
1246                         case ShaderOperation::OPCODE_IFC:
1247                         case ShaderOperation::OPCODE_BREAK:
1248                         case ShaderOperation::OPCODE_BREAKC:
1249                         case ShaderOperation::OPCODE_SETP:
1250                         case ShaderOperation::OPCODE_BREAKP:
1251                                 if(instruction[i]->sourceParameter[0].type != ShaderParameter::PARAMETER_CONSTBOOL)
1252                                 {
1253                                         dynamicBranching = true;
1254                                         break;
1255                                 }
1256                         }
1257                 }
1258         }
1259
1260         void Shader::analyzeSamplers()
1261         {
1262                 sampler = 0;
1263
1264                 for(int i = 0; i < length; i++)
1265                 {
1266                         switch(instruction[i]->getOpcode())
1267                         {
1268                         case ShaderOperation::OPCODE_TEX:
1269                         case ShaderOperation::OPCODE_TEXBEM:
1270                         case ShaderOperation::OPCODE_TEXBEML:
1271                         case ShaderOperation::OPCODE_TEXREG2AR:
1272                         case ShaderOperation::OPCODE_TEXREG2GB:
1273                         case ShaderOperation::OPCODE_TEXM3X2TEX:
1274                         case ShaderOperation::OPCODE_TEXM3X3TEX:
1275                         case ShaderOperation::OPCODE_TEXM3X3SPEC:
1276                         case ShaderOperation::OPCODE_TEXM3X3VSPEC:
1277                         case ShaderOperation::OPCODE_TEXREG2RGB:
1278                         case ShaderOperation::OPCODE_TEXDP3TEX:
1279                         case ShaderOperation::OPCODE_TEXM3X2DEPTH:
1280                         case ShaderOperation::OPCODE_TEXLDD:
1281                         case ShaderOperation::OPCODE_TEXLDL:
1282                                 {
1283                                         ShaderParameter &dst = instruction[i]->destinationParameter;
1284                                         ShaderParameter &src1 = instruction[i]->sourceParameter[1];
1285
1286                                         if(majorVersion >= 2)
1287                                         {
1288                                                 ASSERT(src1.type == ShaderParameter::PARAMETER_SAMPLER);
1289                                                 sampler |= 1 << src1.index;
1290                                         }
1291                                         else
1292                                         {
1293                                                 sampler |= 1 << dst.index;
1294                                         }
1295                                 }
1296                                 break;
1297                         }
1298                 }
1299         }
1300
1301         void Shader::removeComments(unsigned long *shaderToken, int tokenCount)
1302         {
1303                 for(int i = 0; i < tokenCount; )
1304                 {
1305                         int instructionSize = sw::Shader::size(shaderToken[i], (unsigned short)(shaderToken[0] & 0xFFFF)) + 1;
1306
1307                         if((shaderToken[i] & 0x0000FFFF) == ShaderOperation::OPCODE_COMMENT)
1308                         {
1309                                 for(int j = 0; j < instructionSize; j++)
1310                                 {
1311                                         shaderToken[i + j] = ShaderOperation::OPCODE_NOP;
1312                                 }
1313                         }
1314
1315                         i += instructionSize;
1316                 }
1317         }
1318 }