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