1 /* 2 ----------------------------------------------------------------------------- 3 This source file is part of OGRE 4 (Object-oriented Graphics Rendering Engine) 5 For the latest info, see http://www.ogre3d.org/ 6 7 Copyright (c) 2000-2013 Torus Knot Software Ltd 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 THE SOFTWARE. 26 ----------------------------------------------------------------------------- 27 */ 28 29 30 /** 31 A number of invaluable references were used to put together this ps.1.x compiler for ATI_fragment_shader execution 32 33 References: 34 1. MSDN: DirectX 8.1 Reference 35 2. Wolfgang F. Engel "Fundamentals of Pixel Shaders - Introduction to Shader Programming Part III" on gamedev.net 36 3. Martin Ecker - XEngine 37 4. Shawn Kirst - ps14toATIfs 38 5. Jason L. Mitchell "Real-Time 3D Graphics With Pixel Shaders" 39 6. Jason L. Mitchell "1.4 Pixel Shaders" 40 7. Jason L. Mitchell and Evan Hart "Hardware Shading with EXT_vertex_shader and ATI_fragment_shader" 41 6. ATI 8500 SDK 42 7. GL_ATI_fragment_shader extension reference 43 44 */ 45 //--------------------------------------------------------------------------- 46 #ifndef ps_1_4H 47 #define ps_1_4H 48 49 #include <stdio.h> 50 #include <stdlib.h> 51 #include <string.h> 52 53 #include "OgreGLPrerequisites.h" 54 #include "Compiler2Pass.h" 55 56 57 //--------------------------------------------------------------------------- 58 // macro to get the size of a static array 59 #undef ARRAYSIZE 60 #define ARRAYSIZE(array) (sizeof(array)/sizeof(array[0])) 61 62 #define ALPHA_BIT 0x08 63 #define RGB_BITS 0x07 64 65 // Context key patterns 66 #define ckp_PS_BASE 0x1 67 #define ckp_PS_1_1 0x2 68 #define ckp_PS_1_2 0x4 69 #define ckp_PS_1_3 0x8 70 #define ckp_PS_1_4 0x10 71 72 #define ckp_PS_1_4_BASE (ckp_PS_BASE + ckp_PS_1_4) 73 74 75 76 77 /** Subclasses Compiler2Pass to provide a ps_1_x compiler that takes DirectX pixel shader assembly 78 and converts it to a form that can be used by ATI_fragment_shader OpenGL API 79 @remarks 80 all ps_1_1, ps_1_2, ps_1_3, ps_1_4 assembly instructions are recognized but not all are passed 81 on to ATI_fragment_shader. ATI_fragment_shader does not have an equivalent directive for 82 texkill or texdepth instructions. 83 84 The user must provide the GL binding interfaces. 85 86 A Test method is provided to verify the basic operation of the compiler which outputs the test 87 results to a file. 88 89 90 */ 91 class PS_1_4 : public Compiler2Pass{ 92 private: 93 enum RWAflags {rwa_NONE = 0, rwa_READ = 1, rwa_WRITE = 2}; 94 95 enum MachineInstID {mi_COLOROP1, mi_COLOROP2, mi_COLOROP3, mi_ALPHAOP1, mi_ALPHAOP2, 96 mi_ALPHAOP3, mi_SETCONSTANTS, mi_PASSTEXCOORD, mi_SAMPLEMAP, mi_TEX, 97 mi_TEXCOORD, mi_TEXREG2RGB, mi_NOP 98 }; 99 100 struct TokenInstType{ 101 char* Name; 102 GLuint ID; 103 104 }; 105 106 struct RegisterUsage { 107 bool Phase1Write; 108 bool Phase2Write; 109 }; 110 111 // Token ID enumeration 112 enum SymbolID { 113 // Terminal Tokens section 114 115 // DirectX pixel shader source formats 116 sid_PS_1_4, sid_PS_1_1, sid_PS_1_2, sid_PS_1_3, 117 118 // PS_BASE 119 sid_C0, sid_C1, sid_C2, sid_C3, sid_C4, sid_C5, sid_C6, sid_C7, 120 sid_V0, sid_V1, 121 sid_ADD, sid_SUB, sid_MUL, sid_MAD, sid_LRP, sid_MOV, sid_CMP, sid_CND, 122 sid_DP3, sid_DP4, sid_DEF, 123 sid_R, sid_RA, sid_G, sid_GA, sid_B, sid_BA, sid_A, sid_RGBA, sid_RGB, 124 sid_RG, sid_RGA, sid_RB, sid_RBA, sid_GB, sid_GBA, 125 sid_RRRR, sid_GGGG, sid_BBBB, sid_AAAA, 126 sid_X2, sid_X4, sid_D2, sid_SAT, 127 sid_BIAS, sid_INVERT, sid_NEGATE, sid_BX2, 128 sid_COMMA, sid_VALUE, 129 130 //PS_1_4 sid 131 sid_R0, sid_R1, sid_R2, sid_R3, sid_R4, sid_R5, 132 sid_T0, sid_T1, sid_T2, sid_T3, sid_T4, sid_T5, 133 sid_DP2ADD, 134 sid_X8, sid_D8, sid_D4, 135 sid_TEXCRD, sid_TEXLD, 136 sid_STR, sid_STQ, 137 sid_STRDR, sid_STQDQ, 138 sid_BEM, 139 sid_PHASE, 140 141 //PS_1_1 sid 142 sid_1R0, sid_1R1, sid_1T0, sid_1T1, sid_1T2, sid_1T3, 143 sid_TEX, sid_TEXCOORD, sid_TEXM3X2PAD, 144 sid_TEXM3X2TEX, sid_TEXM3X3PAD, sid_TEXM3X3TEX, sid_TEXM3X3SPEC, sid_TEXM3X3VSPEC, 145 sid_TEXREG2AR, sid_TEXREG2GB, 146 147 //PS_1_2 side 148 sid_TEXREG2RGB, sid_TEXDP3, sid_TEXDP3TEX, 149 150 // common 151 sid_SKIP, sid_PLUS, 152 153 // non-terminal tokens section 154 sid_PROGRAM, sid_PROGRAMTYPE, sid_DECLCONSTS, sid_DEFCONST, 155 sid_CONSTANT, sid_COLOR, 156 sid_TEXSWIZZLE, sid_UNARYOP, 157 sid_NUMVAL, sid_SEPERATOR, sid_ALUOPS, sid_TEXMASK, sid_TEXOP_PS1_1_3, 158 sid_TEXOP_PS1_4, 159 sid_ALU_STATEMENT, sid_DSTMODSAT, sid_UNARYOP_ARGS, sid_REG_PS1_4, 160 sid_TEX_PS1_4, sid_REG_PS1_1_3, sid_TEX_PS1_1_3, sid_DSTINFO, 161 sid_SRCINFO, sid_BINARYOP_ARGS, sid_TERNARYOP_ARGS, sid_TEMPREG, 162 sid_DSTMASK, sid_PRESRCMOD, sid_SRCNAME, sid_SRCREP, sid_POSTSRCMOD, 163 sid_DSTMOD, sid_DSTSAT, sid_BINARYOP, sid_TERNARYOP, 164 sid_TEXOPS_PHASE1, sid_COISSUE, sid_PHASEMARKER, sid_TEXOPS_PHASE2, 165 sid_TEXREG_PS1_4, sid_TEXOPS_PS1_4, sid_TEXOPS_PS1_1_3, sid_TEXCISCOP_PS1_1_3, 166 167 168 // last token 169 sid_INVALID = BAD_TOKEN // must be last in enumeration 170 }; 171 172 /// structure used to keep track of arguments and instruction parameters 173 struct OpParram { 174 GLuint Arg; // type of argument 175 bool Filled; // has it been filled yet 176 GLuint MaskRep; // Mask/Replicator flags 177 GLuint Mod; // argument modifier 178 }; 179 180 typedef std::vector<uint> MachineInstContainer; 181 //typedef MachineInstContainer::iterator MachineInstIterator; 182 183 184 // there are 2 phases with 2 subphases each 185 enum PhaseType {ptPHASE1TEX, ptPHASE1ALU, ptPHASE2TEX, ptPHASE2ALU }; 186 187 struct RegModOffset { 188 uint MacroOffset; 189 uint RegisterBase; 190 uint OpParramsIndex; 191 }; 192 193 struct MacroRegModify { 194 TokenInst * Macro; 195 uint MacroSize; 196 RegModOffset * RegMods; 197 uint RegModSize; 198 199 }; 200 201 #define R_BASE static_cast<unsigned int>((sid_R0 - GL_REG_0_ATI)) 202 #define C_BASE static_cast<unsigned int>((sid_C0 - GL_CON_0_ATI)) 203 #define T_BASE static_cast<unsigned int>((sid_1T0 - GL_REG_0_ATI)) 204 205 // static library database for tokens and BNF rules 206 static SymbolDef PS_1_4_SymbolTypeLib[]; 207 static TokenRule PS_1_x_RulePath[]; 208 static bool LibInitialized; 209 210 // Static Macro database for ps.1.1 ps.1.2 ps.1.3 instructions 211 212 static TokenInst texreg2ar[]; 213 static RegModOffset texreg2xx_RegMods[]; 214 static MacroRegModify texreg2ar_MacroMods; 215 216 static TokenInst texreg2gb[]; 217 static MacroRegModify texreg2gb_MacroMods; 218 219 static TokenInst texdp3[]; 220 static RegModOffset texdp3_RegMods[]; 221 static MacroRegModify texdp3_MacroMods; 222 223 static TokenInst texdp3tex[]; 224 static RegModOffset texdp3tex_RegMods[]; 225 static MacroRegModify texdp3tex_MacroMods; 226 227 static TokenInst texm3x2pad[]; 228 static RegModOffset texm3xxpad_RegMods[]; 229 static MacroRegModify texm3x2pad_MacroMods; 230 231 static TokenInst texm3x2tex[]; 232 static RegModOffset texm3xxtex_RegMods[]; 233 static MacroRegModify texm3x2tex_MacroMods; 234 235 static TokenInst texm3x3pad[]; 236 static MacroRegModify texm3x3pad_MacroMods; 237 238 static TokenInst texm3x3tex[]; 239 static MacroRegModify texm3x3tex_MacroMods; 240 241 static TokenInst texm3x3spec[]; 242 static RegModOffset texm3x3spec_RegMods[]; 243 static MacroRegModify texm3x3spec_MacroMods; 244 245 static TokenInst texm3x3vspec[]; 246 static RegModOffset texm3x3vspec_RegMods[]; 247 static MacroRegModify texm3x3vspec_MacroMods; 248 249 250 MachineInstContainer mPhase1TEX_mi; /// machine instructions for phase one texture section 251 MachineInstContainer mPhase1ALU_mi; /// machine instructions for phase one ALU section 252 MachineInstContainer mPhase2TEX_mi; /// machine instructions for phase two texture section 253 MachineInstContainer mPhase2ALU_mi; /// machine instructions for phase two ALU section 254 255 // vars used during pass 2 256 MachineInstID mOpType; 257 uint mOpInst; 258 bool mDo_Alpha; 259 PhaseType mInstructionPhase; 260 int mArgCnt; 261 int mConstantsPos; 262 263 #define MAXOPPARRAMS 5 // max number of parrams bound to an instruction 264 265 OpParram mOpParrams[MAXOPPARRAMS]; 266 267 /// keeps track of which registers are written to in each phase 268 /// if a register is read from but has not been written to in phase 2 269 /// then if it was written to in phase 1 perform a register pass function 270 /// at the beginning of phase2 so that the register has something worthwhile in it 271 /// NB: check ALU and TEX section of phase 1 and phase 2 272 /// there are 6 temp registers r0 to r5 to keep track off 273 /// checks are performed in pass 2 when building machine instructions 274 RegisterUsage Phase_RegisterUsage[6]; 275 276 bool mMacroOn; // if true then put all ALU instructions in phase 1 277 278 uint mTexm3x3padCount; // keep track of how many texm3x3pad instructions are used so know which mask to use 279 280 size_t mLastInstructionPos; // keep track of last phase 2 ALU instruction to check for R0 setting 281 size_t mSecondLastInstructionPos; 282 283 // keep track if phase marker found: determines which phase the ALU instructions go into 284 bool mPhaseMarkerFound; 285 286 #ifdef _DEBUG 287 FILE* fp; 288 // full compiler test with output results going to a text file 289 void testCompile(char* testname, char* teststr, SymbolID* testresult, 290 uint testresultsize, GLuint* MachinInstResults = NULL, uint MachinInstResultsSize = 0); 291 #endif // _DEBUG 292 293 294 /** attempt to build a machine instruction using current tokens 295 determines what phase machine insturction should be in and if an Alpha Op is required 296 calls expandMachineInstruction() to expand the token into machine instructions 297 */ 298 bool BuildMachineInst(); 299 300 void clearMachineInstState(); 301 302 bool setOpParram(const SymbolDef* symboldef); 303 304 /** optimizes machine instructions depending on pixel shader context 305 only applies to ps.1.1 ps.1.2 and ps.1.3 since they use CISC instructions 306 that must be transformed into RISC instructions 307 */ 308 void optimize(); 309 310 // the method is expected to be recursive to allow for inline expansion of instructions if required 311 bool Pass2scan(const TokenInst * Tokens, const size_t size); 312 313 // supply virtual functions for Compiler2Pass 314 /// Pass 1 is completed so now take tokens generated and build machine instructions 315 bool doPass2(); 316 317 /** Build a machine instruction from token and ready it for expansion 318 will expand CISC tokens using macro database 319 320 */ 321 bool bindMachineInstInPassToFragmentShader(const MachineInstContainer & PassMachineInstructions); 322 323 /** Expand CISC tokens into PS1_4 token equivalents 324 325 */ 326 bool expandMacro(const MacroRegModify & MacroMod); 327 328 /** Expand Machine instruction into operation type and arguments and put into proper machine 329 instruction container 330 also expands scaler alpha machine instructions if required 331 332 */ 333 bool expandMachineInstruction(); 334 335 // mainly used by tests - too slow for use in binding 336 size_t getMachineInst(size_t Idx); 337 338 size_t getMachineInstCount(); 339 340 void addMachineInst(PhaseType phase, const uint inst); 341 342 void clearAllMachineInst(); 343 344 void updateRegisterWriteState(const PhaseType phase); 345 346 bool isRegisterReadValid(const PhaseType phase, const int param); 347 348 public: 349 350 /// constructor 351 PS_1_4(); 352 353 /// binds machine instructions generated in Pass 2 to the ATI GL fragment shader 354 bool bindAllMachineInstToFragmentShader(); 355 356 #ifdef _DEBUG 357 /// perform compiler tests - only available in _DEBUG mode 358 void test(); 359 void testbinder(); 360 361 #endif 362 }; 363 364 365 #endif 366 367