1 // SwiftShader Software Renderer
3 // Copyright(c) 2005-2011 TransGaming Inc.
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.
23 Shader::Instruction::Instruction()
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;
33 Shader::Instruction::Instruction(const unsigned long *token, int size, unsigned char majorVersion)
35 parseOperationToken(*token++, majorVersion);
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
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);
49 else if(operation.opcode == Operation::OPCODE_DCL)
51 parseDeclarationToken(*token++);
52 parseDestinationToken(token++, majorVersion);
58 parseDestinationToken(token, majorVersion);
60 if(destinationParameter.relative && majorVersion >= 3)
70 if(operation.predicate)
74 operation.predicateNot = (SourceParameter::Modifier)((*token & 0x0F000000) >> 24) == SourceParameter::MODIFIER_NOT;
75 operation.predicateSwizzle = (unsigned char)((*token & 0x00FF0000) >> 16);
81 for(int i = 0; size > 0; i++)
83 parseSourceToken(i, token, majorVersion);
88 if(sourceParameter[i].relative && majorVersion >= 2)
97 Shader::Instruction::~Instruction()
101 Shader::Instruction::Operation::Opcode Shader::Instruction::getOpcode() const
103 return operation.opcode;
106 const Shader::Instruction::DestinationParameter &Shader::Instruction::getDestinationParameter() const
108 return destinationParameter;
111 const Shader::Instruction::SourceParameter &Shader::Instruction::getSourceParameter(int i) const
113 return sourceParameter[i];
116 bool Shader::Instruction::isCoissue() const
118 return operation.coissue;
121 bool Shader::Instruction::isProject() const
123 return operation.project;
126 bool Shader::Instruction::isBias() const
128 return operation.bias;
131 bool Shader::Instruction::isPredicate() const
133 return operation.predicate;
136 bool Shader::Instruction::isPredicateNot() const
138 return operation.predicateNot;
141 unsigned char Shader::Instruction::getPredicateSwizzle() const
143 return operation.predicateSwizzle;
146 Shader::Instruction::Operation::Control Shader::Instruction::getControl() const
148 return operation.control;
151 Shader::Instruction::Operation::Usage Shader::Instruction::getUsage() const
153 return operation.usage;
156 unsigned char Shader::Instruction::getUsageIndex() const
158 return operation.usageIndex;
161 Shader::Instruction::Operation::SamplerType Shader::Instruction::getSamplerType() const
163 return operation.samplerType;
166 std::string Shader::Instruction::string(ShaderType shaderType, unsigned short version) const
168 std::string instructionString;
170 if(operation.opcode != Operation::OPCODE_DCL)
172 instructionString += operation.coissue ? "+ " : "";
174 if(operation.predicate)
176 instructionString += operation.predicateNot ? "(!p0" : "(p0";
177 instructionString += swizzleString(Parameter::PARAMETER_PREDICATE, operation.predicateSwizzle);
178 instructionString += ") ";
181 instructionString += operation.string(version) + operation.controlString() + destinationParameter.shiftString() + destinationParameter.modifierString();
183 if(destinationParameter.type != Parameter::PARAMETER_VOID)
185 instructionString += " " + destinationParameter.string(shaderType, version) +
186 destinationParameter.relativeString() +
187 destinationParameter.maskString();
190 for(int i = 0; i < 4; i++)
192 if(sourceParameter[i].type != Parameter::PARAMETER_VOID)
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();
205 instructionString += "dcl";
207 if(destinationParameter.type == Parameter::PARAMETER_SAMPLER)
209 switch(operation.samplerType)
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;
220 instructionString += destinationParameter.string(shaderType, version);
222 else if(destinationParameter.type == Parameter::PARAMETER_INPUT ||
223 destinationParameter.type == Parameter::PARAMETER_OUTPUT ||
224 destinationParameter.type == Parameter::PARAMETER_TEXTURE)
226 if(version >= 0x0300)
228 switch(operation.usage)
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;
248 if(operation.usageIndex > 0)
250 std::ostringstream buffer;
252 buffer << (int)operation.usageIndex;
254 instructionString += buffer.str();
257 else ASSERT(destinationParameter.type != Parameter::PARAMETER_OUTPUT);
259 instructionString += " ";
261 instructionString += destinationParameter.string(shaderType, version);
262 instructionString += destinationParameter.maskString();
264 else if(destinationParameter.type == Parameter::PARAMETER_MISCTYPE) // vPos and vFace
266 instructionString += " ";
268 instructionString += destinationParameter.string(shaderType, version);
273 return instructionString;
276 std::string Shader::Instruction::Operation::string(unsigned short version) const
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";
332 if(version < 0x0104) return "tex";
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";
389 std::string Shader::Instruction::Operation::controlString() const
391 if(opcode != OPCODE_LOOP && opcode != OPCODE_BREAKC && opcode != OPCODE_IFC && opcode != OPCODE_SETP)
393 if(project) return "p";
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";
410 // ASSERT(false); // FIXME
414 std::string Shader::Instruction::DestinationParameter::modifierString() const
416 if(type == PARAMETER_VOID || type == PARAMETER_LABEL)
421 std::string modifierString;
425 modifierString += "_sat";
430 modifierString += "_pp";
435 modifierString += "_centroid";
438 return modifierString;
441 std::string Shader::Instruction::DestinationParameter::shiftString() const
443 if(type == PARAMETER_VOID || type == PARAMETER_LABEL)
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";
459 // ASSERT(false); // FIXME
463 std::string Shader::Instruction::DestinationParameter::maskString() const
465 if(type == PARAMETER_VOID || type == PARAMETER_LABEL)
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";
495 std::string Shader::Instruction::SourceParameter::preModifierString() const
497 if(type == PARAMETER_VOID)
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 "!";
525 std::string Shader::Instruction::Parameter::relativeString() const
527 if(!relative) return "";
529 if(relativeType == Parameter::PARAMETER_ADDR)
531 switch(relativeSwizzle & 0x03)
533 case 0: return "[a0.x]";
534 case 1: return "[a0.y]";
535 case 2: return "[a0.z]";
536 case 3: return "[a0.w]";
539 else if(relativeType == Parameter::PARAMETER_LOOP)
548 std::string Shader::Instruction::SourceParameter::postModifierString() const
550 if(type == PARAMETER_VOID)
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 "";
578 std::string Shader::Instruction::SourceParameter::swizzleString() const
580 return Instruction::swizzleString(type, swizzle);
583 void Shader::Instruction::parseOperationToken(unsigned long token, unsigned char majorVersion)
585 if((token & 0xFFFF0000) == 0xFFFF0000 || (token & 0xFFFF0000) == 0xFFFE0000) // Version token
587 operation.opcode = (Operation::Opcode)token;
588 operation.predicate = false;
589 operation.coissue = false;
593 operation.opcode = (Operation::Opcode)(token & 0x0000FFFF);
594 operation.control = (Operation::Control)((token & 0x00FF0000) >> 16);
596 int size = (token & 0x0F000000) >> 24;
598 operation.predicate = (token & 0x10000000) != 0x00000000;
599 operation.coissue = (token & 0x40000000) != 0x00000000;
605 ASSERT(false); // Reserved
611 if(operation.predicate)
617 if((token & 0x20000000) != 0x00000000)
619 ASSERT(false); // Reserved
622 if(majorVersion >= 2)
624 if(operation.coissue)
626 ASSERT(false); // Reserved
630 if((token & 0x80000000) != 0x00000000)
637 void Shader::Instruction::parseDeclarationToken(unsigned long token)
639 operation.samplerType = (Operation::SamplerType)((token & 0x78000000) >> 27);
640 operation.usage = (Operation::Usage)(token & 0x0000001F);
641 operation.usageIndex = (unsigned char)((token & 0x000F0000) >> 16);
644 void Shader::Instruction::parseDestinationToken(const unsigned long *token, unsigned char majorVersion)
646 destinationParameter.index = (unsigned short)(token[0] & 0x000007FF);
647 destinationParameter.type = (Parameter::Type)(((token[0] & 0x00001800) >> 8) | ((token[0] & 0x70000000) >> 28));
649 // TODO: Check type and index range
651 destinationParameter.relative = (token[0] & 0x00002000) != 0x00000000;
652 destinationParameter.relativeType = Parameter::PARAMETER_ADDR;
653 destinationParameter.relativeSwizzle = 0x00;
655 if(destinationParameter.relative && majorVersion >= 3)
657 destinationParameter.relativeType = (Parameter::Type)(((token[1] & 0x00001800) >> 8) | ((token[1] & 0x70000000) >> 28));
658 destinationParameter.relativeSwizzle = (unsigned char)((token[1] & 0x00FF0000) >> 16);
660 else if(destinationParameter.relative) ASSERT(false); // Reserved
662 if((token[0] & 0x0000C000) != 0x00000000)
664 ASSERT(false); // Reserved
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;
673 if(majorVersion >= 2)
675 if(destinationParameter.shift)
677 ASSERT(false); // Reserved
681 if((token[0] & 0x80000000) != 0x80000000)
687 void Shader::Instruction::parseSourceToken(int i, const unsigned long *token, unsigned char majorVersion)
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;
698 switch(operation.opcode)
700 case Instruction::Operation::OPCODE_DEF:
701 sourceParameter[i].type = Parameter::PARAMETER_FLOATLITERAL;
703 case Instruction::Operation::OPCODE_DEFB:
704 sourceParameter[i].type = Parameter::PARAMETER_BOOLLITERAL;
706 case Instruction::Operation::OPCODE_DEFI:
707 sourceParameter[i].type = Parameter::PARAMETER_INTLITERAL;
710 sourceParameter[i].index = (unsigned short)(token[0] & 0x000007FF);
711 sourceParameter[i].type = (Parameter::Type)(((token[0] & 0x00001800) >> 8) | ((token[0] & 0x70000000) >> 28));
713 // FIXME: Check type and index range
715 sourceParameter[i].relative = (token[0] & 0x00002000) != 0x00000000;
717 if((token[0] & 0x0000C000) != 0x00000000)
719 if(operation.opcode != Operation::OPCODE_DEF &&
720 operation.opcode != Operation::OPCODE_DEFI &&
721 operation.opcode != Operation::OPCODE_DEFB)
727 sourceParameter[i].swizzle = (unsigned char)((token[0] & 0x00FF0000) >> 16);
728 sourceParameter[i].modifier = (SourceParameter::Modifier)((token[0] & 0x0F000000) >> 24);
730 if((token[0] & 0x80000000) != 0x80000000)
732 if(operation.opcode != Operation::OPCODE_DEF &&
733 operation.opcode != Operation::OPCODE_DEFI &&
734 operation.opcode != Operation::OPCODE_DEFB)
740 if(sourceParameter[i].relative && majorVersion >= 2)
742 sourceParameter[i].relativeType = (Parameter::Type)(((token[1] & 0x00001800) >> 8) | ((token[1] & 0x70000000) >> 28));
743 sourceParameter[i].relativeSwizzle = (unsigned char)((token[1] & 0x00FF0000) >> 16);
748 std::string Shader::Instruction::swizzleString(Parameter::Type type, unsigned char swizzle)
750 if(type == Parameter::PARAMETER_VOID || type == Parameter::PARAMETER_LABEL || swizzle == 0xE4)
755 int x = (swizzle & 0x03) >> 0;
756 int y = (swizzle & 0x0C) >> 2;
757 int z = (swizzle & 0x30) >> 4;
758 int w = (swizzle & 0xC0) >> 6;
760 std::string swizzleString = ".";
764 case 0: swizzleString += "x"; break;
765 case 1: swizzleString += "y"; break;
766 case 2: swizzleString += "z"; break;
767 case 3: swizzleString += "w"; break;
770 if(!(x == y && y == z && z == w))
774 case 0: swizzleString += "x"; break;
775 case 1: swizzleString += "y"; break;
776 case 2: swizzleString += "z"; break;
777 case 3: swizzleString += "w"; break;
780 if(!(y == z && z == w))
784 case 0: swizzleString += "x"; break;
785 case 1: swizzleString += "y"; break;
786 case 2: swizzleString += "z"; break;
787 case 3: swizzleString += "w"; break;
794 case 0: swizzleString += "x"; break;
795 case 1: swizzleString += "y"; break;
796 case 2: swizzleString += "z"; break;
797 case 3: swizzleString += "w"; break;
803 return swizzleString;
806 std::string Shader::Instruction::Parameter::string(ShaderType shaderType, unsigned short version) const
808 std::ostringstream buffer;
810 if(type == PARAMETER_FLOATLITERAL)
818 if(type != PARAMETER_RASTOUT && !(type == PARAMETER_ADDR && shaderType == SHADER_VERTEX) && type != PARAMETER_LOOP && type != PARAMETER_PREDICATE && type != PARAMETER_MISCTYPE)
822 return typeString(shaderType, version) + buffer.str();
826 return typeString(shaderType, version);
831 std::string Shader::Instruction::Parameter::typeString(ShaderType shaderType, unsigned short version) const
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";
842 case PARAMETER_RASTOUT:
843 if(index == 0) return "oPos";
844 else if(index == 1) return "oFog";
845 else if(index == 2) return "oPts";
847 case PARAMETER_ATTROUT: return "oD";
848 case PARAMETER_TEXCRDOUT:
849 // case PARAMETER_OUTPUT: return "";
850 if(version < 0x0300) return "oT";
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";
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 "";
879 Shader::Shader(const unsigned long *shaderToken)
886 while(shaderToken[tokenCount] != 0x0000FFFF)
888 tokenCount += sw::Shader::size(shaderToken[tokenCount], (unsigned short)(shaderToken[0] & 0xFFFF)) + 1;
893 this->shaderToken = new unsigned long[tokenCount];
894 memcpy(this->shaderToken, shaderToken, tokenCount * sizeof(unsigned long));
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));
905 delete[] shaderToken;
908 for(int i = 0; i < length; i++)
910 delete instruction[i];
914 delete[] instruction;
918 void Shader::getFunction(void *data, unsigned int *size)
922 memcpy(data, shaderToken, tokenCount * 4);
925 *size = tokenCount * 4;
928 int Shader::size(unsigned long opcode) const
930 return size(opcode, version);
933 int Shader::size(unsigned long opcode, unsigned short version)
940 static const char size[] =
1059 if((opcode & 0x0000FFFF) == ShaderOperation::OPCODE_COMMENT)
1061 return (opcode & 0x7FFF0000) >> 16;
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)
1082 if(version >= 0x0200)
1084 length = (opcode & 0x0F000000) >> 24;
1088 length = size[opcode & 0x0000FFFF];
1097 if(version == 0x0104)
1099 switch(opcode & 0x0000FFFF)
1101 case ShaderOperation::OPCODE_TEX:
1104 case ShaderOperation::OPCODE_TEXCOORD:
1115 bool Shader::maskContainsComponent(int mask, int component)
1117 return (mask & (1 << component)) != 0;
1120 bool Shader::swizzleContainsComponent(int swizzle, int component)
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;
1130 bool Shader::swizzleContainsComponentMasked(int swizzle, int component, int mask)
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;
1140 bool Shader::containsDynamicBranching() const
1142 return dynamicBranching;
1145 bool Shader::usesSampler(int index) const
1147 return (sampler & (1 << index)) != 0;
1150 int64_t Shader::getHash() const
1155 int Shader::getLength() const
1160 Shader::ShaderType Shader::getShaderType() const
1165 unsigned short Shader::getVersion() const
1170 void Shader::print(const char *fileName, ...) const
1172 char fullName[1024 + 1];
1175 va_start(vararg, fileName);
1176 vsnprintf(fullName, 1024, fileName, vararg);
1179 std::ofstream file(fullName, std::ofstream::out | std::ofstream::app);
1181 for(int i = 0; i < length; i++)
1183 file << instruction[i]->string(shaderType, version) << std::endl;
1187 void Shader::printInstruction(int index, const char *fileName) const
1189 std::ofstream file(fileName, std::ofstream::out | std::ofstream::app);
1191 file << instruction[index]->string(shaderType, version) << std::endl;
1194 const ShaderInstruction *Shader::getInstruction(int i) const
1196 if(i < 0 || i >= length)
1201 return instruction[i];
1204 void Shader::analyzeDirtyConstants()
1206 dirtyConstantsF = 0;
1207 dirtyConstantsI = 0;
1208 dirtyConstantsB = 0;
1210 for(int i = 0; i < length; i++)
1212 switch(instruction[i]->operation.opcode)
1214 case ShaderOperation::OPCODE_DEF:
1215 if(instruction[i]->destinationParameter.index + 1 > dirtyConstantsF)
1217 dirtyConstantsF = instruction[i]->destinationParameter.index + 1;
1220 case ShaderOperation::OPCODE_DEFI:
1221 if(instruction[i]->destinationParameter.index + 1 > dirtyConstantsI)
1223 dirtyConstantsI = instruction[i]->destinationParameter.index + 1;
1226 case ShaderOperation::OPCODE_DEFB:
1227 if(instruction[i]->destinationParameter.index + 1 > dirtyConstantsB)
1229 dirtyConstantsB = instruction[i]->destinationParameter.index + 1;
1236 void Shader::analyzeDynamicBranching()
1238 dynamicBranching = false;
1240 for(int i = 0; i < length; i++)
1242 switch(instruction[i]->getOpcode())
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)
1253 dynamicBranching = true;
1260 void Shader::analyzeSamplers()
1264 for(int i = 0; i < length; i++)
1266 switch(instruction[i]->getOpcode())
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:
1283 ShaderParameter &dst = instruction[i]->destinationParameter;
1284 ShaderParameter &src1 = instruction[i]->sourceParameter[1];
1286 if(majorVersion >= 2)
1288 ASSERT(src1.type == ShaderParameter::PARAMETER_SAMPLER);
1289 sampler |= 1 << src1.index;
1293 sampler |= 1 << dst.index;
1301 void Shader::removeComments(unsigned long *shaderToken, int tokenCount)
1303 for(int i = 0; i < tokenCount; )
1305 int instructionSize = sw::Shader::size(shaderToken[i], (unsigned short)(shaderToken[0] & 0xFFFF)) + 1;
1307 if((shaderToken[i] & 0x0000FFFF) == ShaderOperation::OPCODE_COMMENT)
1309 for(int j = 0; j < instructionSize; j++)
1311 shaderToken[i + j] = ShaderOperation::OPCODE_NOP;
1315 i += instructionSize;