blob: 7bf072a27e6e68b1742a10f109a415e46591a9c5 [file] [log] [blame]
// 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;
}
}
}
}
}