| // SwiftShader Software Renderer | |
| // | |
| // Copyright(c) 2005-2012 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. | |
| // | |
| #ifndef sw_Shader_hpp | |
| #define sw_Shader_hpp | |
| #include "Common/Types.hpp" | |
| #include <string> | |
| #include <vector> | |
| namespace sw | |
| { | |
| class Shader | |
| { | |
| public: | |
| enum ShaderType | |
| { | |
| SHADER_PIXEL = 0xFFFF, | |
| SHADER_VERTEX = 0xFFFE, | |
| SHADER_GEOMETRY = 0xFFFD | |
| }; | |
| enum Opcode | |
| { | |
| // Matches order in d3d9types.h | |
| OPCODE_NOP = 0, | |
| OPCODE_MOV, | |
| OPCODE_ADD, | |
| OPCODE_SUB, | |
| OPCODE_MAD, | |
| OPCODE_MUL, | |
| OPCODE_RCPX, | |
| OPCODE_RSQX, | |
| OPCODE_DP3, | |
| OPCODE_DP4, | |
| OPCODE_MIN, | |
| OPCODE_MAX, | |
| OPCODE_SLT, | |
| OPCODE_SGE, | |
| OPCODE_EXP2X, // D3DSIO_EXP | |
| OPCODE_LOG2X, // D3DSIO_LOG | |
| OPCODE_LIT, | |
| OPCODE_ATT, // D3DSIO_DST | |
| OPCODE_LRP, | |
| OPCODE_FRC, | |
| OPCODE_M4X4, | |
| OPCODE_M4X3, | |
| OPCODE_M3X4, | |
| OPCODE_M3X3, | |
| OPCODE_M3X2, | |
| OPCODE_CALL, | |
| OPCODE_CALLNZ, | |
| OPCODE_LOOP, | |
| OPCODE_RET, | |
| OPCODE_ENDLOOP, | |
| OPCODE_LABEL, | |
| OPCODE_DCL, | |
| OPCODE_POWX, | |
| OPCODE_CRS, | |
| OPCODE_SGN, | |
| OPCODE_ABS, | |
| OPCODE_NRM3, // D3DSIO_NRM | |
| OPCODE_SINCOS, | |
| OPCODE_REP, | |
| OPCODE_ENDREP, | |
| OPCODE_IF, | |
| OPCODE_IFC, | |
| OPCODE_ELSE, | |
| OPCODE_ENDIF, | |
| OPCODE_BREAK, | |
| OPCODE_BREAKC, | |
| OPCODE_MOVA, | |
| OPCODE_DEFB, | |
| OPCODE_DEFI, | |
| OPCODE_TEXCOORD = 64, | |
| OPCODE_TEXKILL, | |
| OPCODE_TEX, | |
| OPCODE_TEXBEM, | |
| OPCODE_TEXBEML, | |
| OPCODE_TEXREG2AR, | |
| OPCODE_TEXREG2GB, | |
| OPCODE_TEXM3X2PAD, | |
| OPCODE_TEXM3X2TEX, | |
| OPCODE_TEXM3X3PAD, | |
| OPCODE_TEXM3X3TEX, | |
| OPCODE_RESERVED0, | |
| OPCODE_TEXM3X3SPEC, | |
| OPCODE_TEXM3X3VSPEC, | |
| OPCODE_EXPP, | |
| OPCODE_LOGP, | |
| OPCODE_CND, | |
| OPCODE_DEF, | |
| OPCODE_TEXREG2RGB, | |
| OPCODE_TEXDP3TEX, | |
| OPCODE_TEXM3X2DEPTH, | |
| OPCODE_TEXDP3, | |
| OPCODE_TEXM3X3, | |
| OPCODE_TEXDEPTH, | |
| OPCODE_CMP0, // D3DSIO_CMP | |
| OPCODE_BEM, | |
| OPCODE_DP2ADD, | |
| OPCODE_DFDX, // D3DSIO_DSX | |
| OPCODE_DFDY, // D3DSIO_DSY | |
| OPCODE_TEXLDD, | |
| OPCODE_CMP, // D3DSIO_SETP | |
| OPCODE_TEXLDL, | |
| OPCODE_BREAKP, | |
| OPCODE_TEXSIZE, | |
| OPCODE_PHASE = 0xFFFD, | |
| OPCODE_COMMENT = 0xFFFE, | |
| OPCODE_END = 0xFFFF, | |
| OPCODE_PS_1_0 = 0xFFFF0100, | |
| OPCODE_PS_1_1 = 0xFFFF0101, | |
| OPCODE_PS_1_2 = 0xFFFF0102, | |
| OPCODE_PS_1_3 = 0xFFFF0103, | |
| OPCODE_PS_1_4 = 0xFFFF0104, | |
| OPCODE_PS_2_0 = 0xFFFF0200, | |
| OPCODE_PS_2_x = 0xFFFF0201, | |
| OPCODE_PS_3_0 = 0xFFFF0300, | |
| OPCODE_VS_1_0 = 0xFFFE0100, | |
| OPCODE_VS_1_1 = 0xFFFE0101, | |
| OPCODE_VS_2_0 = 0xFFFE0200, | |
| OPCODE_VS_2_x = 0xFFFE0201, | |
| OPCODE_VS_2_sw = 0xFFFE02FF, | |
| OPCODE_VS_3_0 = 0xFFFE0300, | |
| OPCODE_VS_3_sw = 0xFFFE03FF, | |
| OPCODE_NULL = 0x10000000, // Dead instruction, to be eliminated | |
| OPCODE_WHILE, | |
| OPCODE_ENDWHILE, | |
| OPCODE_COS, | |
| OPCODE_SIN, | |
| OPCODE_TAN, | |
| OPCODE_ACOS, | |
| OPCODE_ASIN, | |
| OPCODE_ATAN, | |
| OPCODE_ATAN2, | |
| OPCODE_COSH, | |
| OPCODE_SINH, | |
| OPCODE_TANH, | |
| OPCODE_ACOSH, | |
| OPCODE_ASINH, | |
| OPCODE_ATANH, | |
| OPCODE_DP1, | |
| OPCODE_DP2, | |
| OPCODE_TRUNC, | |
| OPCODE_FLOOR, | |
| OPCODE_ROUND, | |
| OPCODE_ROUNDEVEN, | |
| OPCODE_CEIL, | |
| OPCODE_SQRT, | |
| OPCODE_RSQ, | |
| OPCODE_LEN2, | |
| OPCODE_LEN3, | |
| OPCODE_LEN4, | |
| OPCODE_DIST1, | |
| OPCODE_DIST2, | |
| OPCODE_DIST3, | |
| OPCODE_DIST4, | |
| OPCODE_NRM2, | |
| OPCODE_NRM4, | |
| OPCODE_DIV, | |
| OPCODE_MOD, | |
| OPCODE_EXP2, | |
| OPCODE_LOG2, | |
| OPCODE_EXP, | |
| OPCODE_LOG, | |
| OPCODE_POW, | |
| OPCODE_F2B, // Float to bool | |
| OPCODE_B2F, // Bool to float | |
| OPCODE_F2I, // Float to int | |
| OPCODE_I2F, // Int to float | |
| OPCODE_F2U, // Float to uint | |
| OPCODE_U2F, // Uint to float | |
| OPCODE_I2B, // Int to bool | |
| OPCODE_B2I, // Bool to int | |
| OPCODE_U2B, // Uint to bool | |
| OPCODE_B2U, // Bool to uint | |
| OPCODE_DET2, | |
| OPCODE_DET3, | |
| OPCODE_DET4, | |
| OPCODE_ALL, | |
| OPCODE_ANY, | |
| OPCODE_NEG, | |
| OPCODE_NOT, | |
| OPCODE_OR, | |
| OPCODE_XOR, | |
| OPCODE_AND, | |
| OPCODE_EQ, | |
| OPCODE_NE, | |
| OPCODE_STEP, | |
| OPCODE_SMOOTH, | |
| OPCODE_ISNAN, | |
| OPCODE_ISINF, | |
| OPCODE_FLOATBITSTOINT, | |
| OPCODE_FLOATBITSTOUINT, | |
| OPCODE_INTBITSTOFLOAT, | |
| OPCODE_UINTBITSTOFLOAT, | |
| OPCODE_PACKSNORM2x16, | |
| OPCODE_PACKUNORM2x16, | |
| OPCODE_PACKHALF2x16, | |
| OPCODE_UNPACKSNORM2x16, | |
| OPCODE_UNPACKUNORM2x16, | |
| OPCODE_UNPACKHALF2x16, | |
| OPCODE_FORWARD1, | |
| OPCODE_FORWARD2, | |
| OPCODE_FORWARD3, | |
| OPCODE_FORWARD4, | |
| OPCODE_REFLECT1, | |
| OPCODE_REFLECT2, | |
| OPCODE_REFLECT3, | |
| OPCODE_REFLECT4, | |
| OPCODE_REFRACT1, | |
| OPCODE_REFRACT2, | |
| OPCODE_REFRACT3, | |
| OPCODE_REFRACT4, | |
| OPCODE_ICMP, | |
| OPCODE_UCMP, | |
| OPCODE_SELECT, | |
| OPCODE_EXTRACT, | |
| OPCODE_INSERT, | |
| OPCODE_DISCARD, | |
| OPCODE_FWIDTH, | |
| OPCODE_LEAVE, // Return before the end of the function | |
| OPCODE_CONTINUE, | |
| OPCODE_TEST, // Marks the end of the code that can be skipped by 'continue' | |
| // Integer opcodes | |
| OPCODE_INEG, | |
| OPCODE_IADD, | |
| OPCODE_ISUB, | |
| OPCODE_IMUL, | |
| OPCODE_IDIV, | |
| OPCODE_IMAD, | |
| OPCODE_IMOD, | |
| OPCODE_SHL, | |
| OPCODE_ISHR, | |
| OPCODE_IMIN, | |
| OPCODE_IMAX, | |
| // Unsigned integer opcodes | |
| OPCODE_UDIV, | |
| OPCODE_UMOD, | |
| OPCODE_USHR, | |
| OPCODE_UMIN, | |
| OPCODE_UMAX, | |
| }; | |
| static Opcode OPCODE_DP(int); | |
| static Opcode OPCODE_LEN(int); | |
| static Opcode OPCODE_DIST(int); | |
| static Opcode OPCODE_NRM(int); | |
| static Opcode OPCODE_FORWARD(int); | |
| static Opcode OPCODE_REFLECT(int); | |
| static Opcode OPCODE_REFRACT(int); | |
| enum Control | |
| { | |
| CONTROL_RESERVED0, | |
| CONTROL_GT, | |
| CONTROL_EQ, | |
| CONTROL_GE, | |
| CONTROL_LT, | |
| CONTROL_NE, | |
| CONTROL_LE, | |
| CONTROL_RESERVED1 | |
| }; | |
| enum SamplerType | |
| { | |
| SAMPLER_UNKNOWN, | |
| SAMPLER_1D, | |
| SAMPLER_2D, | |
| SAMPLER_CUBE, | |
| SAMPLER_VOLUME | |
| }; | |
| enum Usage // For vertex input/output declarations | |
| { | |
| USAGE_POSITION = 0, | |
| USAGE_BLENDWEIGHT = 1, | |
| USAGE_BLENDINDICES = 2, | |
| USAGE_NORMAL = 3, | |
| USAGE_PSIZE = 4, | |
| USAGE_TEXCOORD = 5, | |
| USAGE_TANGENT = 6, | |
| USAGE_BINORMAL = 7, | |
| USAGE_TESSFACTOR = 8, | |
| USAGE_POSITIONT = 9, | |
| USAGE_COLOR = 10, | |
| USAGE_FOG = 11, | |
| USAGE_DEPTH = 12, | |
| USAGE_SAMPLE = 13 | |
| }; | |
| enum ParameterType | |
| { | |
| PARAMETER_TEMP = 0, | |
| PARAMETER_INPUT = 1, | |
| PARAMETER_CONST = 2, | |
| PARAMETER_TEXTURE = 3, | |
| PARAMETER_ADDR = 3, | |
| PARAMETER_RASTOUT = 4, | |
| PARAMETER_ATTROUT = 5, | |
| PARAMETER_TEXCRDOUT = 6, | |
| PARAMETER_OUTPUT = 6, | |
| PARAMETER_CONSTINT = 7, | |
| PARAMETER_COLOROUT = 8, | |
| PARAMETER_DEPTHOUT = 9, | |
| PARAMETER_SAMPLER = 10, | |
| PARAMETER_CONST2 = 11, | |
| PARAMETER_CONST3 = 12, | |
| PARAMETER_CONST4 = 13, | |
| PARAMETER_CONSTBOOL = 14, | |
| PARAMETER_LOOP = 15, | |
| PARAMETER_TEMPFLOAT16 = 16, | |
| PARAMETER_MISCTYPE = 17, | |
| PARAMETER_LABEL = 18, | |
| PARAMETER_PREDICATE = 19, | |
| // PARAMETER_FLOAT1LITERAL, | |
| // PARAMETER_FLOAT2LITERAL, | |
| // PARAMETER_FLOAT3LITERAL, | |
| PARAMETER_FLOAT4LITERAL, | |
| PARAMETER_BOOL1LITERAL, | |
| // PARAMETER_BOOL2LITERAL, | |
| // PARAMETER_BOOL3LITERAL, | |
| // PARAMETER_BOOL4LITERAL, | |
| // PARAMETER_INT1LITERAL, | |
| // PARAMETER_INT2LITERAL, | |
| // PARAMETER_INT3LITERAL, | |
| PARAMETER_INT4LITERAL, | |
| PARAMETER_VOID | |
| }; | |
| enum Modifier | |
| { | |
| MODIFIER_NONE, | |
| MODIFIER_NEGATE, | |
| MODIFIER_BIAS, | |
| MODIFIER_BIAS_NEGATE, | |
| MODIFIER_SIGN, | |
| MODIFIER_SIGN_NEGATE, | |
| MODIFIER_COMPLEMENT, | |
| MODIFIER_X2, | |
| MODIFIER_X2_NEGATE, | |
| MODIFIER_DZ, | |
| MODIFIER_DW, | |
| MODIFIER_ABS, | |
| MODIFIER_ABS_NEGATE, | |
| MODIFIER_NOT | |
| }; | |
| enum Analysis | |
| { | |
| // Flags indicating whether an instruction is affected by an execution enable mask | |
| ANALYSIS_BRANCH = 0x00000001, | |
| ANALYSIS_BREAK = 0x00000002, | |
| ANALYSIS_CONTINUE = 0x00000004, | |
| ANALYSIS_LEAVE = 0x00000008, | |
| }; | |
| struct Parameter | |
| { | |
| union | |
| { | |
| struct | |
| { | |
| unsigned int index; // For registers types | |
| struct | |
| { | |
| ParameterType type : 8; | |
| unsigned int index; | |
| unsigned int swizzle : 8; | |
| unsigned int scale; | |
| bool deterministic; // Equal accross shader instances run in lockstep (e.g. unrollable loop couters) | |
| } rel; | |
| }; | |
| float value[4]; // For float constants | |
| int integer[4]; // For integer constants | |
| int boolean[4]; // For boolean constants | |
| struct | |
| { | |
| unsigned int label; // Label index | |
| unsigned int callSite; // Call index (per label) | |
| }; | |
| }; | |
| Parameter() : index(0), type(PARAMETER_VOID) | |
| { | |
| rel.type = PARAMETER_VOID; | |
| rel.index = 0; | |
| rel.swizzle = 0; | |
| rel.scale = 1; | |
| rel.deterministic = false; | |
| } | |
| std::string string(ShaderType shaderType, unsigned short version) const; | |
| std::string typeString(ShaderType shaderType, unsigned short version) const; | |
| std::string relativeString() const; | |
| ParameterType type : 8; | |
| }; | |
| struct DestinationParameter : Parameter | |
| { | |
| union | |
| { | |
| unsigned char mask; | |
| struct | |
| { | |
| bool x : 1; | |
| bool y : 1; | |
| bool z : 1; | |
| bool w : 1; | |
| }; | |
| }; | |
| DestinationParameter() : mask(0xF), integer(false), saturate(false), partialPrecision(false), centroid(false), shift(0) | |
| { | |
| } | |
| std::string modifierString() const; | |
| std::string shiftString() const; | |
| std::string maskString() const; | |
| bool integer : 1; | |
| bool saturate : 1; | |
| bool partialPrecision : 1; | |
| bool centroid : 1; | |
| signed char shift : 4; | |
| }; | |
| struct SourceParameter : Parameter | |
| { | |
| SourceParameter() : swizzle(0xE4), modifier(MODIFIER_NONE) | |
| { | |
| } | |
| std::string swizzleString() const; | |
| std::string preModifierString() const; | |
| std::string postModifierString() const; | |
| unsigned int swizzle : 8; | |
| Modifier modifier : 8; | |
| }; | |
| struct Instruction | |
| { | |
| explicit Instruction(Opcode opcode); | |
| Instruction(const unsigned long *token, int size, unsigned char majorVersion); | |
| virtual ~Instruction(); | |
| void parseOperationToken(unsigned long token, unsigned char majorVersion); | |
| void parseDeclarationToken(unsigned long token); | |
| void parseDestinationToken(const unsigned long *token, unsigned char majorVersion); | |
| void parseSourceToken(int i, const unsigned long *token, unsigned char majorVersion); | |
| std::string string(ShaderType shaderType, unsigned short version) const; | |
| static std::string swizzleString(ParameterType type, unsigned char swizzle); | |
| std::string operationString(unsigned short version) const; | |
| std::string controlString() const; | |
| bool isBranch() const; | |
| bool isCall() const; | |
| bool isBreak() const; | |
| bool isLoop() const; | |
| bool isEndLoop() const; | |
| bool isPredicated() const; | |
| Opcode opcode; | |
| union | |
| { | |
| Control control; | |
| struct | |
| { | |
| unsigned char project : 1; | |
| unsigned char bias : 1; | |
| }; | |
| }; | |
| bool predicate; | |
| bool predicateNot; // Negative predicate | |
| unsigned char predicateSwizzle; | |
| bool coissue; | |
| SamplerType samplerType; | |
| Usage usage; | |
| unsigned char usageIndex; | |
| DestinationParameter dst; | |
| SourceParameter src[4]; | |
| union | |
| { | |
| unsigned int analysis; | |
| struct | |
| { | |
| // Keep in sync with Shader::Analysis flags | |
| unsigned int analysisBranch : 1; | |
| unsigned int analysisBreak : 1; | |
| unsigned int analysisContinue : 1; | |
| unsigned int analysisLeave : 1; | |
| }; | |
| }; | |
| }; | |
| Shader(); | |
| virtual ~Shader(); | |
| int getSerialID() const; | |
| size_t getLength() const; | |
| ShaderType getShaderType() const; | |
| unsigned short getVersion() const; | |
| void append(Instruction *instruction); | |
| void declareSampler(int i); | |
| const Instruction *getInstruction(unsigned int i) const; | |
| int size(unsigned long opcode) const; | |
| static int size(unsigned long opcode, unsigned short version); | |
| void print(const char *fileName, ...) const; | |
| void printInstruction(int index, const char *fileName) const; | |
| static bool maskContainsComponent(int mask, int component); | |
| static bool swizzleContainsComponent(int swizzle, int component); | |
| static bool swizzleContainsComponentMasked(int swizzle, int component, int mask); | |
| bool containsDynamicBranching() const; | |
| bool containsBreakInstruction() const; | |
| bool containsContinueInstruction() const; | |
| bool containsLeaveInstruction() const; | |
| bool containsDefineInstruction() const; | |
| bool usesSampler(int i) const; | |
| struct Semantic | |
| { | |
| Semantic(unsigned char usage = 0xFF, unsigned char index = 0xFF) : usage(usage), index(index), centroid(false) | |
| { | |
| } | |
| bool operator==(const Semantic &semantic) const | |
| { | |
| return usage == semantic.usage && index == semantic.index; | |
| } | |
| bool active() const | |
| { | |
| return usage != 0xFF; | |
| } | |
| unsigned char usage; | |
| unsigned char index; | |
| bool centroid; | |
| }; | |
| void optimize(); | |
| virtual void analyze() = 0; | |
| // FIXME: Private | |
| unsigned int dirtyConstantsF; | |
| unsigned int dirtyConstantsI; | |
| unsigned int dirtyConstantsB; | |
| bool dynamicallyIndexedTemporaries; | |
| bool dynamicallyIndexedInput; | |
| bool dynamicallyIndexedOutput; | |
| protected: | |
| void parse(const unsigned long *token); | |
| void optimizeLeave(); | |
| void optimizeCall(); | |
| void removeNull(); | |
| void analyzeDirtyConstants(); | |
| void analyzeDynamicBranching(); | |
| void analyzeSamplers(); | |
| void analyzeCallSites(); | |
| void analyzeDynamicIndexing(); | |
| void markFunctionAnalysis(int functionLabel, Analysis flag); | |
| ShaderType shaderType; | |
| union | |
| { | |
| unsigned short version; | |
| struct | |
| { | |
| unsigned char minorVersion; | |
| unsigned char majorVersion; | |
| }; | |
| }; | |
| std::vector<Instruction*> instruction; | |
| unsigned short usedSamplers; // Bit flags | |
| private: | |
| const int serialID; | |
| static volatile int serialCounter; | |
| bool dynamicBranching; | |
| bool containsBreak; | |
| bool containsContinue; | |
| bool containsLeave; | |
| bool containsDefine; | |
| }; | |
| } | |
| #endif // sw_Shader_hpp |