Add SwiftShader source to repo
Oct 6 code drop from Transgaming
Review URL: https://chromereviews.googleplex.com/3846015
diff --git a/src/Shader/VertexShader.cpp b/src/Shader/VertexShader.cpp
new file mode 100644
index 0000000..c958820
--- /dev/null
+++ b/src/Shader/VertexShader.cpp
@@ -0,0 +1,266 @@
+// 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 "VertexShader.hpp"
+
+#include "Vertex.hpp"
+#include "Debug.hpp"
+
+namespace sw
+{
+ VertexShader::VertexShader(const unsigned long *token) : Shader(token)
+ {
+ parse(token);
+ }
+
+ VertexShader::~VertexShader()
+ {
+ }
+
+ void VertexShader::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 tokenCount = size(*token);
+
+ instruction[i] = new Instruction(token, tokenCount, majorVersion);
+
+ token += 1 + tokenCount;
+ }
+
+ analyzeInput();
+ analyzeOutput();
+ analyzeDirtyConstants();
+ analyzeTexldl();
+ analyzeDynamicBranching();
+ analyzeSamplers();
+ }
+
+ int VertexShader::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_VERTEX || 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_TEXCOORD:
+ case ShaderOperation::OPCODE_TEXKILL:
+ case ShaderOperation::OPCODE_TEX:
+ case ShaderOperation::OPCODE_TEXBEM:
+ case ShaderOperation::OPCODE_TEXBEML:
+ case ShaderOperation::OPCODE_TEXREG2AR:
+ case ShaderOperation::OPCODE_TEXREG2GB:
+ case ShaderOperation::OPCODE_TEXM3X2PAD:
+ case ShaderOperation::OPCODE_TEXM3X2TEX:
+ case ShaderOperation::OPCODE_TEXM3X3PAD:
+ case ShaderOperation::OPCODE_TEXM3X3TEX:
+ case ShaderOperation::OPCODE_RESERVED0:
+ case ShaderOperation::OPCODE_TEXM3X3SPEC:
+ case ShaderOperation::OPCODE_TEXM3X3VSPEC:
+ case ShaderOperation::OPCODE_TEXREG2RGB:
+ case ShaderOperation::OPCODE_TEXDP3TEX:
+ case ShaderOperation::OPCODE_TEXM3X2DEPTH:
+ case ShaderOperation::OPCODE_TEXDP3:
+ case ShaderOperation::OPCODE_TEXM3X3:
+ case ShaderOperation::OPCODE_TEXDEPTH:
+ case ShaderOperation::OPCODE_CMP:
+ case ShaderOperation::OPCODE_BEM:
+ case ShaderOperation::OPCODE_DP2ADD:
+ case ShaderOperation::OPCODE_DSX:
+ case ShaderOperation::OPCODE_DSY:
+ case ShaderOperation::OPCODE_TEXLDD:
+ return 0; // Unsupported operation
+ default:
+ instructionCount++;
+ break;
+ }
+
+ i += size(token[i], version);
+ }
+ }
+
+ return instructionCount;
+ }
+
+ bool VertexShader::containsTexldl() const
+ {
+ return texldl;
+ }
+
+ void VertexShader::analyzeInput()
+ {
+ for(int i = 0; i < 16; i++)
+ {
+ input[i] = Semantic(-1, -1);
+ }
+
+ for(int i = 0; i < length; i++)
+ {
+ if(instruction[i]->getOpcode() == ShaderOperation::OPCODE_DCL &&
+ instruction[i]->getDestinationParameter().type == ShaderParameter::PARAMETER_INPUT)
+ {
+ int index = instruction[i]->getDestinationParameter().index;
+
+ input[index] = Semantic(instruction[i]->getUsage(), instruction[i]->getUsageIndex());
+ }
+ }
+ }
+
+ void VertexShader::analyzeOutput()
+ {
+ positionRegister = Pos;
+ pointSizeRegister = -1; // No vertex point size
+
+ if(version < 0x0300)
+ {
+ output[Pos][0] = Semantic(ShaderOperation::USAGE_POSITION, 0);
+ output[Pos][1] = Semantic(ShaderOperation::USAGE_POSITION, 0);
+ output[Pos][2] = Semantic(ShaderOperation::USAGE_POSITION, 0);
+ output[Pos][3] = Semantic(ShaderOperation::USAGE_POSITION, 0);
+
+ for(int i = 0; i < length; i++)
+ {
+ const Instruction::DestinationParameter &dst = instruction[i]->getDestinationParameter();
+
+ switch(dst.type)
+ {
+ case ShaderParameter::PARAMETER_RASTOUT:
+ switch(dst.index)
+ {
+ case 0:
+ // Position already assumed written
+ break;
+ case 1:
+ output[Fog][0] = Semantic(ShaderOperation::USAGE_FOG, 0);
+ break;
+ case 2:
+ output[Pts][1] = Semantic(ShaderOperation::USAGE_PSIZE, 0);
+ pointSizeRegister = Pts;
+ break;
+ default: ASSERT(false);
+ }
+ break;
+ case ShaderParameter::PARAMETER_ATTROUT:
+ if(dst.index == 0)
+ {
+ if(dst.x) output[D0][0] = Semantic(ShaderOperation::USAGE_COLOR, 0);
+ if(dst.y) output[D0][1] = Semantic(ShaderOperation::USAGE_COLOR, 0);
+ if(dst.z) output[D0][2] = Semantic(ShaderOperation::USAGE_COLOR, 0);
+ if(dst.w) output[D0][3] = Semantic(ShaderOperation::USAGE_COLOR, 0);
+ }
+ else if(dst.index == 1)
+ {
+ if(dst.x) output[D1][0] = Semantic(ShaderOperation::USAGE_COLOR, 1);
+ if(dst.y) output[D1][1] = Semantic(ShaderOperation::USAGE_COLOR, 1);
+ if(dst.z) output[D1][2] = Semantic(ShaderOperation::USAGE_COLOR, 1);
+ if(dst.w) output[D1][3] = Semantic(ShaderOperation::USAGE_COLOR, 1);
+ }
+ else ASSERT(false);
+ break;
+ case ShaderParameter::PARAMETER_TEXCRDOUT:
+ if(dst.x) output[T0 + dst.index][0] = Semantic(ShaderOperation::USAGE_TEXCOORD, dst.index);
+ if(dst.y) output[T0 + dst.index][1] = Semantic(ShaderOperation::USAGE_TEXCOORD, dst.index);
+ if(dst.z) output[T0 + dst.index][2] = Semantic(ShaderOperation::USAGE_TEXCOORD, dst.index);
+ if(dst.w) output[T0 + dst.index][3] = Semantic(ShaderOperation::USAGE_TEXCOORD, dst.index);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else // Shader Model 3.0 input declaration
+ {
+ for(int i = 0; i < length; i++)
+ {
+ if(instruction[i]->getOpcode() == ShaderOperation::OPCODE_DCL &&
+ instruction[i]->getDestinationParameter().type == ShaderParameter::PARAMETER_OUTPUT)
+ {
+ unsigned char usage = instruction[i]->getUsage();
+ unsigned char usageIndex = instruction[i]->getUsageIndex();
+
+ const Instruction::DestinationParameter &dst = instruction[i]->getDestinationParameter();
+
+ if(dst.x) output[dst.index][0] = Semantic(usage, usageIndex);
+ if(dst.y) output[dst.index][1] = Semantic(usage, usageIndex);
+ if(dst.z) output[dst.index][2] = Semantic(usage, usageIndex);
+ if(dst.w) output[dst.index][3] = Semantic(usage, usageIndex);
+
+ if(usage == ShaderOperation::USAGE_POSITION && usageIndex == 0)
+ {
+ positionRegister = dst.index;
+ }
+
+ if(usage == ShaderOperation::USAGE_PSIZE && usageIndex == 0)
+ {
+ pointSizeRegister = dst.index;
+ }
+ }
+ }
+ }
+ }
+
+ void VertexShader::analyzeTexldl()
+ {
+ texldl = false;
+
+ for(int i = 0; i < length; i++)
+ {
+ if(instruction[i]->getOpcode() == Instruction::Operation::OPCODE_TEXLDL)
+ {
+ texldl = true;
+
+ break;
+ }
+ }
+ }
+}