Add SwiftShader source to repo
Oct 6 code drop from Transgaming
Review URL: https://chromereviews.googleplex.com/3846015
diff --git a/src/Shader/PixelShader.cpp b/src/Shader/PixelShader.cpp
new file mode 100644
index 0000000..7bf072a
--- /dev/null
+++ b/src/Shader/PixelShader.cpp
@@ -0,0 +1,728 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2011 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+#include "PixelShader.hpp"
+
+#include "Debug.hpp"
+
+namespace sw
+{
+ PixelShader::PixelShader(const unsigned long *token) : Shader(token)
+ {
+ parse(token);
+ }
+
+ PixelShader::~PixelShader()
+ {
+ }
+
+ void PixelShader::parse(const unsigned long *token)
+ {
+ minorVersion = (unsigned char)(token[0] & 0x000000FF);
+ majorVersion = (unsigned char)((token[0] & 0x0000FF00) >> 8);
+ shaderType = (ShaderType)((token[0] & 0xFFFF0000) >> 16);
+
+ length = validate(token);
+ ASSERT(length != 0);
+
+ instruction = new Shader::Instruction*[length];
+
+ for(int i = 0; i < length; i++)
+ {
+ while((*token & 0x0000FFFF) == 0x0000FFFE) // Comment token
+ {
+ int length = (*token & 0x7FFF0000) >> 16;
+
+ token += length + 1;
+ }
+
+ int length = size(*token);
+
+ instruction[i] = new Instruction(token, length, majorVersion);
+
+ token += length + 1;
+ }
+
+ analyzeZOverride();
+ analyzeTexkill();
+ analyzeInterpolants();
+ analyzeDirtyConstants();
+ analyzeDynamicBranching();
+ analyzeSamplers();
+ }
+
+ int PixelShader::validate(const unsigned long *const token)
+ {
+ if(!token)
+ {
+ return 0;
+ }
+
+ unsigned short version = (unsigned short)(token[0] & 0x0000FFFF);
+ unsigned char minorVersion = (unsigned char)(token[0] & 0x000000FF);
+ unsigned char majorVersion = (unsigned char)((token[0] & 0x0000FF00) >> 8);
+ ShaderType shaderType = (ShaderType)((token[0] & 0xFFFF0000) >> 16);
+
+ if(shaderType != SHADER_PIXEL || majorVersion > 3)
+ {
+ return 0;
+ }
+
+ int instructionCount = 1;
+
+ for(int i = 0; token[i] != 0x0000FFFF; i++)
+ {
+ if((token[i] & 0x0000FFFF) == 0x0000FFFE) // Comment token
+ {
+ int length = (token[i] & 0x7FFF0000) >> 16;
+
+ i += length;
+ }
+ else
+ {
+ ShaderOpcode opcode = (ShaderOpcode)(token[i] & 0x0000FFFF);
+
+ switch(opcode)
+ {
+ case ShaderOperation::OPCODE_RESERVED0:
+ case ShaderOperation::OPCODE_MOVA:
+ return 0; // Unsupported operation
+ default:
+ instructionCount++;
+ break;
+ }
+
+ i += size(token[i], version);
+ }
+ }
+
+ return instructionCount;
+ }
+
+ bool PixelShader::depthOverride() const
+ {
+ return zOverride;
+ }
+
+ bool PixelShader::containsTexkill() const
+ {
+ return texkill;
+ }
+
+ bool PixelShader::containsCentroid() const
+ {
+ return centroid;
+ }
+
+ bool PixelShader::usesDiffuse(int component) const
+ {
+ return semantic[0][component].active();
+ }
+
+ bool PixelShader::usesSpecular(int component) const
+ {
+ return semantic[1][component].active();
+ }
+
+ bool PixelShader::usesTexture(int coordinate, int component) const
+ {
+ return semantic[2 + coordinate][component].active();
+ }
+
+ void PixelShader::analyzeZOverride()
+ {
+ zOverride = false;
+
+ for(int i = 0; i < length; i++)
+ {
+ if(instruction[i]->getOpcode() == Instruction::Operation::OPCODE_TEXM3X2DEPTH ||
+ instruction[i]->getOpcode() == Instruction::Operation::OPCODE_TEXDEPTH ||
+ instruction[i]->getDestinationParameter().type == Instruction::DestinationParameter::PARAMETER_DEPTHOUT)
+ {
+ zOverride = true;
+
+ break;
+ }
+ }
+ }
+
+ void PixelShader::analyzeTexkill()
+ {
+ texkill = false;
+
+ for(int i = 0; i < length; i++)
+ {
+ if(instruction[i]->getOpcode() == Instruction::Operation::OPCODE_TEXKILL)
+ {
+ texkill = true;
+
+ break;
+ }
+ }
+ }
+
+ void PixelShader::analyzeInterpolants()
+ {
+ vPosDeclared = false;
+ vFaceDeclared = false;
+ centroid = false;
+
+ if(version < 0x0300)
+ {
+ // Set default mapping; disable unused interpolants below
+ semantic[0][0] = Semantic(ShaderOperation::USAGE_COLOR, 0);
+ semantic[0][1] = Semantic(ShaderOperation::USAGE_COLOR, 0);
+ semantic[0][2] = Semantic(ShaderOperation::USAGE_COLOR, 0);
+ semantic[0][3] = Semantic(ShaderOperation::USAGE_COLOR, 0);
+
+ semantic[1][0] = Semantic(ShaderOperation::USAGE_COLOR, 1);
+ semantic[1][1] = Semantic(ShaderOperation::USAGE_COLOR, 1);
+ semantic[1][2] = Semantic(ShaderOperation::USAGE_COLOR, 1);
+ semantic[1][3] = Semantic(ShaderOperation::USAGE_COLOR, 1);
+
+ for(int i = 0; i < 8; i++)
+ {
+ semantic[2 + i][0] = Semantic(ShaderOperation::USAGE_TEXCOORD, i);
+ semantic[2 + i][1] = Semantic(ShaderOperation::USAGE_TEXCOORD, i);
+ semantic[2 + i][2] = Semantic(ShaderOperation::USAGE_TEXCOORD, i);
+ semantic[2 + i][3] = Semantic(ShaderOperation::USAGE_TEXCOORD, i);
+ }
+
+ Instruction::Operation::SamplerType samplerType[16];
+
+ for(int i = 0; i < 16; i++)
+ {
+ samplerType[i] = Instruction::Operation::SAMPLER_UNKNOWN;
+ }
+
+ for(int i = 0; i < length; i++)
+ {
+ if(instruction[i]->getDestinationParameter().type == Instruction::SourceParameter::PARAMETER_SAMPLER)
+ {
+ int sampler = instruction[i]->getDestinationParameter().index;
+
+ samplerType[sampler] = instruction[i]->getSamplerType();
+ }
+ }
+
+ bool interpolant[10][4] = {false}; // Interpolants in use
+
+ for(int i = 0; i < length; i++)
+ {
+ if(instruction[i]->getDestinationParameter().type == Instruction::SourceParameter::PARAMETER_TEXTURE)
+ {
+ int index = instruction[i]->getDestinationParameter().index + 2;
+ int mask = instruction[i]->getDestinationParameter().mask;
+
+ switch(instruction[i]->getOpcode())
+ {
+ case Instruction::Operation::OPCODE_TEX:
+ case Instruction::Operation::OPCODE_TEXBEM:
+ case Instruction::Operation::OPCODE_TEXBEML:
+ case Instruction::Operation::OPCODE_TEXCOORD:
+ case Instruction::Operation::OPCODE_TEXDP3:
+ case Instruction::Operation::OPCODE_TEXDP3TEX:
+ case Instruction::Operation::OPCODE_TEXM3X2DEPTH:
+ case Instruction::Operation::OPCODE_TEXM3X2PAD:
+ case Instruction::Operation::OPCODE_TEXM3X2TEX:
+ case Instruction::Operation::OPCODE_TEXM3X3:
+ case Instruction::Operation::OPCODE_TEXM3X3PAD:
+ case Instruction::Operation::OPCODE_TEXM3X3TEX:
+ interpolant[index][0] = true;
+ interpolant[index][1] = true;
+ interpolant[index][2] = true;
+ break;
+ case Instruction::Operation::OPCODE_TEXKILL:
+ if(majorVersion < 2)
+ {
+ interpolant[index][0] = true;
+ interpolant[index][1] = true;
+ interpolant[index][2] = true;
+ }
+ else
+ {
+ interpolant[index][0] = true;
+ interpolant[index][1] = true;
+ interpolant[index][2] = true;
+ interpolant[index][3] = true;
+ }
+ break;
+ case Instruction::Operation::OPCODE_TEXM3X3VSPEC:
+ interpolant[index][0] = true;
+ interpolant[index][1] = true;
+ interpolant[index][2] = true;
+ interpolant[index - 2][3] = true;
+ interpolant[index - 1][3] = true;
+ interpolant[index - 0][3] = true;
+ break;
+ case Instruction::Operation::OPCODE_DCL:
+ break; // Ignore
+ default: // Arithmetic instruction
+ if(version >= 0x0104)
+ {
+ ASSERT(false);
+ }
+ }
+ }
+
+ for(int argument = 0; argument < 4; argument++)
+ {
+ if(instruction[i]->getSourceParameter(argument).type == Instruction::SourceParameter::PARAMETER_INPUT ||
+ instruction[i]->getSourceParameter(argument).type == Instruction::SourceParameter::PARAMETER_TEXTURE)
+ {
+ int index = instruction[i]->getSourceParameter(argument).index;
+ int swizzle = instruction[i]->getSourceParameter(argument).swizzle;
+ int mask = instruction[i]->getDestinationParameter().mask;
+
+ if(instruction[i]->getSourceParameter(argument).type == Instruction::SourceParameter::PARAMETER_TEXTURE)
+ {
+ index += 2;
+ }
+
+ switch(instruction[i]->getOpcode())
+ {
+ case Instruction::Operation::OPCODE_TEX:
+ case Instruction::Operation::OPCODE_TEXLDD:
+ case Instruction::Operation::OPCODE_TEXLDL:
+ {
+ int sampler = instruction[i]->getSourceParameter(1).index;
+
+ switch(samplerType[sampler])
+ {
+ case Instruction::Operation::SAMPLER_UNKNOWN:
+ if(version == 0x0104)
+ {
+ if((instruction[i]->getSourceParameter(0).swizzle & 0x30) == 0x20) // .xyz
+ {
+ interpolant[index][0] = true;
+ interpolant[index][1] = true;
+ interpolant[index][2] = true;
+ }
+ else // .xyw
+ {
+ interpolant[index][0] = true;
+ interpolant[index][1] = true;
+ interpolant[index][3] = true;
+ }
+ }
+ else
+ {
+ ASSERT(false);
+ }
+ break;
+ case Instruction::Operation::SAMPLER_1D:
+ interpolant[index][0] = true;
+ break;
+ case Instruction::Operation::SAMPLER_2D:
+ interpolant[index][0] = true;
+ interpolant[index][1] = true;
+ break;
+ case Instruction::Operation::SAMPLER_CUBE:
+ interpolant[index][0] = true;
+ interpolant[index][1] = true;
+ interpolant[index][2] = true;
+ break;
+ case Instruction::Operation::SAMPLER_VOLUME:
+ interpolant[index][0] = true;
+ interpolant[index][1] = true;
+ interpolant[index][2] = true;
+ break;
+ default:
+ ASSERT(false);
+ }
+
+ if(instruction[i]->isBias())
+ {
+ interpolant[index][3] = true;
+ }
+
+ if(instruction[i]->isProject())
+ {
+ interpolant[index][3] = true;
+ }
+
+ if(version == 0x0104 && instruction[i]->getOpcode() == Instruction::Operation::OPCODE_TEX)
+ {
+ if(instruction[i]->getSourceParameter(0).modifier == Instruction::SourceParameter::MODIFIER_DZ)
+ {
+ interpolant[index][2] = true;
+ }
+
+ if(instruction[i]->getSourceParameter(0).modifier == Instruction::SourceParameter::MODIFIER_DW)
+ {
+ interpolant[index][3] = true;
+ }
+ }
+ }
+ break;
+ case Instruction::Operation::OPCODE_M3X2:
+ if(mask & 0x1)
+ {
+ interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
+ interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
+ interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
+ interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
+ }
+
+ if(argument == 1)
+ {
+ if(mask & 0x2)
+ {
+ interpolant[index + 1][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
+ interpolant[index + 1][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
+ interpolant[index + 1][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
+ interpolant[index + 1][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
+ }
+ }
+ break;
+ case Instruction::Operation::OPCODE_M3X3:
+ if(mask & 0x1)
+ {
+ interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
+ interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
+ interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
+ interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
+ }
+
+ if(argument == 1)
+ {
+ if(mask & 0x2)
+ {
+ interpolant[index + 1][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
+ interpolant[index + 1][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
+ interpolant[index + 1][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
+ interpolant[index + 1][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
+ }
+
+ if(mask & 0x4)
+ {
+ interpolant[index + 2][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
+ interpolant[index + 2][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
+ interpolant[index + 2][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
+ interpolant[index + 2][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
+ }
+ }
+ break;
+ case Instruction::Operation::OPCODE_M3X4:
+ if(mask & 0x1)
+ {
+ interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
+ interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
+ interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
+ interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
+ }
+
+ if(argument == 1)
+ {
+ if(mask & 0x2)
+ {
+ interpolant[index + 1][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
+ interpolant[index + 1][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
+ interpolant[index + 1][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
+ interpolant[index + 1][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
+ }
+
+ if(mask & 0x4)
+ {
+ interpolant[index + 2][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
+ interpolant[index + 2][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
+ interpolant[index + 2][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
+ interpolant[index + 2][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
+ }
+
+ if(mask & 0x8)
+ {
+ interpolant[index + 3][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
+ interpolant[index + 3][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
+ interpolant[index + 3][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
+ interpolant[index + 3][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
+ }
+ }
+ break;
+ case Instruction::Operation::OPCODE_M4X3:
+ if(mask & 0x1)
+ {
+ interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
+ interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
+ interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
+ interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
+ }
+
+ if(argument == 1)
+ {
+ if(mask & 0x2)
+ {
+ interpolant[index + 1][0] |= swizzleContainsComponent(swizzle, 0);
+ interpolant[index + 1][1] |= swizzleContainsComponent(swizzle, 1);
+ interpolant[index + 1][2] |= swizzleContainsComponent(swizzle, 2);
+ interpolant[index + 1][3] |= swizzleContainsComponent(swizzle, 3);
+ }
+
+ if(mask & 0x4)
+ {
+ interpolant[index + 2][0] |= swizzleContainsComponent(swizzle, 0);
+ interpolant[index + 2][1] |= swizzleContainsComponent(swizzle, 1);
+ interpolant[index + 2][2] |= swizzleContainsComponent(swizzle, 2);
+ interpolant[index + 2][3] |= swizzleContainsComponent(swizzle, 3);
+ }
+ }
+ break;
+ case Instruction::Operation::OPCODE_M4X4:
+ if(mask & 0x1)
+ {
+ interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
+ interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
+ interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
+ interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
+ }
+
+ if(argument == 1)
+ {
+ if(mask & 0x2)
+ {
+ interpolant[index + 1][0] |= swizzleContainsComponent(swizzle, 0);
+ interpolant[index + 1][1] |= swizzleContainsComponent(swizzle, 1);
+ interpolant[index + 1][2] |= swizzleContainsComponent(swizzle, 2);
+ interpolant[index + 1][3] |= swizzleContainsComponent(swizzle, 3);
+ }
+
+ if(mask & 0x4)
+ {
+ interpolant[index + 2][0] |= swizzleContainsComponent(swizzle, 0);
+ interpolant[index + 2][1] |= swizzleContainsComponent(swizzle, 1);
+ interpolant[index + 2][2] |= swizzleContainsComponent(swizzle, 2);
+ interpolant[index + 2][3] |= swizzleContainsComponent(swizzle, 3);
+ }
+
+ if(mask & 0x8)
+ {
+ interpolant[index + 3][0] |= swizzleContainsComponent(swizzle, 0);
+ interpolant[index + 3][1] |= swizzleContainsComponent(swizzle, 1);
+ interpolant[index + 3][2] |= swizzleContainsComponent(swizzle, 2);
+ interpolant[index + 3][3] |= swizzleContainsComponent(swizzle, 3);
+ }
+ }
+ break;
+ case Instruction::Operation::OPCODE_CRS:
+ if(mask & 0x1)
+ {
+ interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x6);
+ interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x6);
+ interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x6);
+ interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x6);
+ }
+
+ if(mask & 0x2)
+ {
+ interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x5);
+ interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x5);
+ interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x5);
+ interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x5);
+ }
+
+ if(mask & 0x4)
+ {
+ interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x3);
+ interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x3);
+ interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x3);
+ interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x3);
+ }
+ break;
+ case Instruction::Operation::OPCODE_DP2ADD:
+ if(argument == 0 || argument == 1)
+ {
+ interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x3);
+ interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x3);
+ interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x3);
+ interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x3);
+ }
+ else // argument == 2
+ {
+ interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
+ interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
+ interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
+ interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
+ }
+ break;
+ case Instruction::Operation::OPCODE_DP3:
+ interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
+ interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
+ interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
+ interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
+ break;
+ case Instruction::Operation::OPCODE_DP4:
+ interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
+ interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
+ interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
+ interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
+ break;
+ case Instruction::Operation::OPCODE_SINCOS:
+ case Instruction::Operation::OPCODE_EXP:
+ case Instruction::Operation::OPCODE_LOG:
+ case Instruction::Operation::OPCODE_POW:
+ case Instruction::Operation::OPCODE_RCP:
+ case Instruction::Operation::OPCODE_RSQ:
+ interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
+ interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
+ interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
+ interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
+ break;
+ case Instruction::Operation::OPCODE_NRM:
+ interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7 | mask);
+ interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7 | mask);
+ interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7 | mask);
+ interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7 | mask);
+ break;
+ case Instruction::Operation::OPCODE_MOV:
+ case Instruction::Operation::OPCODE_ADD:
+ case Instruction::Operation::OPCODE_SUB:
+ case Instruction::Operation::OPCODE_MUL:
+ case Instruction::Operation::OPCODE_MAD:
+ case Instruction::Operation::OPCODE_ABS:
+ case Instruction::Operation::OPCODE_CMP:
+ case Instruction::Operation::OPCODE_CND:
+ case Instruction::Operation::OPCODE_FRC:
+ case Instruction::Operation::OPCODE_LRP:
+ case Instruction::Operation::OPCODE_MAX:
+ case Instruction::Operation::OPCODE_MIN:
+ case Instruction::Operation::OPCODE_SETP:
+ case Instruction::Operation::OPCODE_BREAKC:
+ case Instruction::Operation::OPCODE_DSX:
+ case Instruction::Operation::OPCODE_DSY:
+ interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, mask);
+ interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, mask);
+ interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, mask);
+ interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, mask);
+ break;
+ case Instruction::Operation::OPCODE_TEXCOORD:
+ interpolant[index][0] = true;
+ interpolant[index][1] = true;
+ interpolant[index][2] = true;
+ interpolant[index][3] = true;
+ break;
+ case Instruction::Operation::OPCODE_TEXDP3:
+ case Instruction::Operation::OPCODE_TEXDP3TEX:
+ case Instruction::Operation::OPCODE_TEXM3X2PAD:
+ case Instruction::Operation::OPCODE_TEXM3X3PAD:
+ case Instruction::Operation::OPCODE_TEXM3X2TEX:
+ case Instruction::Operation::OPCODE_TEXM3X3SPEC:
+ case Instruction::Operation::OPCODE_TEXM3X3VSPEC:
+ case Instruction::Operation::OPCODE_TEXBEM:
+ case Instruction::Operation::OPCODE_TEXBEML:
+ case Instruction::Operation::OPCODE_TEXM3X2DEPTH:
+ case Instruction::Operation::OPCODE_TEXM3X3:
+ case Instruction::Operation::OPCODE_TEXM3X3TEX:
+ interpolant[index][0] = true;
+ interpolant[index][1] = true;
+ interpolant[index][2] = true;
+ break;
+ case Instruction::Operation::OPCODE_TEXREG2AR:
+ case Instruction::Operation::OPCODE_TEXREG2GB:
+ case Instruction::Operation::OPCODE_TEXREG2RGB:
+ break;
+ default:
+ // ASSERT(false); // Refine component usage
+ interpolant[index][0] = true;
+ interpolant[index][1] = true;
+ interpolant[index][2] = true;
+ interpolant[index][3] = true;
+ }
+ }
+ }
+ }
+
+ for(int index = 0; index < 10; index++)
+ {
+ for(int component = 0; component < 4; component++)
+ {
+ if(!interpolant[index][component])
+ {
+ semantic[index][component] = Semantic();
+ }
+ }
+ }
+ }
+ else // Shader Model 3.0 input declaration; v# indexable
+ {
+ for(int i = 0; i < length; i++)
+ {
+ if(instruction[i]->getOpcode() == ShaderOperation::OPCODE_DCL)
+ {
+ if(instruction[i]->getDestinationParameter().type == ShaderParameter::PARAMETER_INPUT)
+ {
+ unsigned char usage = instruction[i]->getUsage();
+ unsigned char index = instruction[i]->getUsageIndex();
+ unsigned char mask = instruction[i]->getDestinationParameter().mask;
+ unsigned char reg = instruction[i]->getDestinationParameter().index;
+
+ if(mask & 0x01)
+ {
+ semantic[reg][0] = Semantic(usage, index);
+ }
+
+ if(mask & 0x02)
+ {
+ semantic[reg][1] = Semantic(usage, index);
+ }
+
+ if(mask & 0x04)
+ {
+ semantic[reg][2] = Semantic(usage, index);
+ }
+
+ if(mask & 0x08)
+ {
+ semantic[reg][3] = Semantic(usage, index);
+ }
+ }
+ else if(instruction[i]->getDestinationParameter().type == ShaderParameter::PARAMETER_MISCTYPE)
+ {
+ unsigned char index = instruction[i]->getDestinationParameter().index;
+
+ if(index == 0)
+ {
+ vPosDeclared = true;
+ }
+ else if(index == 1)
+ {
+ vFaceDeclared = true;
+ }
+ else ASSERT(false);
+ }
+ }
+ }
+ }
+
+ if(version >= 0x0200)
+ {
+ for(int i = 0; i < length; i++)
+ {
+ if(instruction[i]->getOpcode() == ShaderOperation::OPCODE_DCL)
+ {
+ bool centroid = instruction[i]->getDestinationParameter().centroid;
+ unsigned char reg = instruction[i]->getDestinationParameter().index;
+
+ switch(instruction[i]->getDestinationParameter().type)
+ {
+ case ShaderParameter::PARAMETER_INPUT:
+ semantic[reg][0].centroid = centroid;
+ break;
+ case ShaderParameter::PARAMETER_TEXTURE:
+ semantic[2 + reg][0].centroid = centroid;
+ break;
+ }
+
+ this->centroid = this->centroid || centroid;
+ }
+ }
+ }
+ }
+}