Shader.hpp revision 6dbd5fef7ee0e118c421a6b4db9c452528d98bd7
1// SwiftShader Software Renderer
2//
3// Copyright(c) 2005-2012 TransGaming Inc.
4//
5// All rights reserved. No part of this software may be copied, distributed, transmitted,
6// transcribed, stored in a retrieval system, translated into any human or computer
7// language by any means, or disclosed to third parties without the explicit written
8// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9// or implied, including but not limited to any patent rights, are granted to you.
10//
11
12#ifndef sw_Shader_hpp
13#define sw_Shader_hpp
14
15#include "Common/Types.hpp"
16
17#include <string>
18#include <vector>
19
20namespace sw
21{
22	class Shader
23	{
24	public:
25		enum ShaderType
26		{
27			SHADER_PIXEL = 0xFFFF,
28			SHADER_VERTEX = 0xFFFE,
29			SHADER_GEOMETRY = 0xFFFD
30		};
31
32		enum Opcode
33		{
34			// Matches order in d3d9types.h
35			OPCODE_NOP = 0,
36			OPCODE_MOV,
37			OPCODE_ADD,
38			OPCODE_SUB,
39			OPCODE_MAD,
40			OPCODE_MUL,
41			OPCODE_RCPX,
42			OPCODE_RSQX,
43			OPCODE_DP3,
44			OPCODE_DP4,
45			OPCODE_MIN,
46			OPCODE_MAX,
47			OPCODE_SLT,
48			OPCODE_SGE,
49			OPCODE_EXP2X,   // D3DSIO_EXP
50			OPCODE_LOG2X,   // D3DSIO_LOG
51			OPCODE_LIT,
52			OPCODE_ATT,   // D3DSIO_DST
53			OPCODE_LRP,
54			OPCODE_FRC,
55			OPCODE_M4X4,
56			OPCODE_M4X3,
57			OPCODE_M3X4,
58			OPCODE_M3X3,
59			OPCODE_M3X2,
60			OPCODE_CALL,
61			OPCODE_CALLNZ,
62			OPCODE_LOOP,
63			OPCODE_RET,
64			OPCODE_ENDLOOP,
65			OPCODE_LABEL,
66			OPCODE_DCL,
67			OPCODE_POWX,
68			OPCODE_CRS,
69			OPCODE_SGN,
70			OPCODE_ABS,
71			OPCODE_NRM3,   // D3DSIO_NRM
72			OPCODE_SINCOS,
73			OPCODE_REP,
74			OPCODE_ENDREP,
75			OPCODE_IF,
76			OPCODE_IFC,
77			OPCODE_ELSE,
78			OPCODE_ENDIF,
79			OPCODE_BREAK,
80			OPCODE_BREAKC,
81			OPCODE_MOVA,
82			OPCODE_DEFB,
83			OPCODE_DEFI,
84
85			OPCODE_TEXCOORD = 64,
86			OPCODE_TEXKILL,
87			OPCODE_TEX,
88			OPCODE_TEXBEM,
89			OPCODE_TEXBEML,
90			OPCODE_TEXREG2AR,
91			OPCODE_TEXREG2GB,
92			OPCODE_TEXM3X2PAD,
93			OPCODE_TEXM3X2TEX,
94			OPCODE_TEXM3X3PAD,
95			OPCODE_TEXM3X3TEX,
96			OPCODE_RESERVED0,
97			OPCODE_TEXM3X3SPEC,
98			OPCODE_TEXM3X3VSPEC,
99			OPCODE_EXPP,
100			OPCODE_LOGP,
101			OPCODE_CND,
102			OPCODE_DEF,
103			OPCODE_TEXREG2RGB,
104			OPCODE_TEXDP3TEX,
105			OPCODE_TEXM3X2DEPTH,
106			OPCODE_TEXDP3,
107			OPCODE_TEXM3X3,
108			OPCODE_TEXDEPTH,
109			OPCODE_CMP0,   // D3DSIO_CMP
110			OPCODE_BEM,
111			OPCODE_DP2ADD,
112			OPCODE_DFDX,   // D3DSIO_DSX
113			OPCODE_DFDY,   // D3DSIO_DSY
114			OPCODE_TEXLDD,
115			OPCODE_CMP,   // D3DSIO_SETP
116			OPCODE_TEXLDL,
117			OPCODE_BREAKP,
118
119			OPCODE_PHASE = 0xFFFD,
120			OPCODE_COMMENT = 0xFFFE,
121			OPCODE_END = 0xFFFF,
122
123			OPCODE_PS_1_0 = 0xFFFF0100,
124			OPCODE_PS_1_1 = 0xFFFF0101,
125			OPCODE_PS_1_2 = 0xFFFF0102,
126			OPCODE_PS_1_3 = 0xFFFF0103,
127			OPCODE_PS_1_4 = 0xFFFF0104,
128			OPCODE_PS_2_0 = 0xFFFF0200,
129			OPCODE_PS_2_x = 0xFFFF0201,
130			OPCODE_PS_3_0 = 0xFFFF0300,
131
132			OPCODE_VS_1_0 = 0xFFFE0100,
133			OPCODE_VS_1_1 = 0xFFFE0101,
134			OPCODE_VS_2_0 = 0xFFFE0200,
135			OPCODE_VS_2_x = 0xFFFE0201,
136			OPCODE_VS_2_sw = 0xFFFE02FF,
137			OPCODE_VS_3_0 = 0xFFFE0300,
138			OPCODE_VS_3_sw = 0xFFFE03FF,
139
140			OPCODE_NULL = 0x10000000,   // Dead instruction, to be eliminated
141			OPCODE_WHILE,
142			OPCODE_ENDWHILE,
143			OPCODE_COS,
144			OPCODE_SIN,
145			OPCODE_TAN,
146			OPCODE_ACOS,
147			OPCODE_ASIN,
148			OPCODE_ATAN,
149			OPCODE_ATAN2,
150			OPCODE_DP1,
151			OPCODE_DP2,
152			OPCODE_TRUNC,
153			OPCODE_FLOOR,
154			OPCODE_CEIL,
155			OPCODE_SQRT,
156			OPCODE_RSQ,
157			OPCODE_LEN2,
158			OPCODE_LEN3,
159			OPCODE_LEN4,
160			OPCODE_DIST1,
161			OPCODE_DIST2,
162			OPCODE_DIST3,
163			OPCODE_DIST4,
164			OPCODE_NRM2,
165			OPCODE_NRM4,
166			OPCODE_DIV,
167			OPCODE_MOD,
168			OPCODE_EXP2,
169			OPCODE_LOG2,
170			OPCODE_EXP,
171			OPCODE_LOG,
172			OPCODE_POW,
173			OPCODE_F2B,   // Float to bool
174			OPCODE_B2F,   // Bool to float
175			OPCODE_ALL,
176			OPCODE_ANY,
177			OPCODE_NOT,
178			OPCODE_OR,
179			OPCODE_XOR,
180			OPCODE_AND,
181			OPCODE_STEP,
182			OPCODE_SMOOTH,
183			OPCODE_FORWARD1,
184			OPCODE_FORWARD2,
185			OPCODE_FORWARD3,
186			OPCODE_FORWARD4,
187			OPCODE_REFLECT1,
188			OPCODE_REFLECT2,
189			OPCODE_REFLECT3,
190			OPCODE_REFLECT4,
191			OPCODE_REFRACT1,
192			OPCODE_REFRACT2,
193			OPCODE_REFRACT3,
194			OPCODE_REFRACT4,
195			OPCODE_ICMP,
196			OPCODE_SELECT,
197			OPCODE_EXTRACT,
198			OPCODE_INSERT,
199			OPCODE_DISCARD,
200			OPCODE_FWIDTH,
201			OPCODE_LEAVE,   // Return before the end of the function
202			OPCODE_CONTINUE,
203			OPCODE_TEST,   // Marks the end of the code that can be skipped by 'continue'
204		};
205
206		static Opcode OPCODE_DP(int);
207		static Opcode OPCODE_LEN(int);
208		static Opcode OPCODE_DIST(int);
209		static Opcode OPCODE_NRM(int);
210		static Opcode OPCODE_FORWARD(int);
211		static Opcode OPCODE_REFLECT(int);
212		static Opcode OPCODE_REFRACT(int);
213
214		enum Control
215		{
216			CONTROL_RESERVED0,
217			CONTROL_GT,
218			CONTROL_EQ,
219			CONTROL_GE,
220			CONTROL_LT,
221			CONTROL_NE,
222			CONTROL_LE,
223			CONTROL_RESERVED1
224		};
225
226		enum SamplerType
227		{
228			SAMPLER_UNKNOWN,
229			SAMPLER_1D,
230			SAMPLER_2D,
231			SAMPLER_CUBE,
232			SAMPLER_VOLUME
233		};
234
235		enum Usage   // For vertex input/output declarations
236		{
237			USAGE_POSITION = 0,
238			USAGE_BLENDWEIGHT = 1,
239			USAGE_BLENDINDICES = 2,
240			USAGE_NORMAL = 3,
241			USAGE_PSIZE = 4,
242			USAGE_TEXCOORD = 5,
243			USAGE_TANGENT = 6,
244			USAGE_BINORMAL = 7,
245			USAGE_TESSFACTOR = 8,
246			USAGE_POSITIONT = 9,
247			USAGE_COLOR = 10,
248			USAGE_FOG = 11,
249			USAGE_DEPTH = 12,
250			USAGE_SAMPLE = 13
251		};
252
253		enum ParameterType
254		{
255			PARAMETER_TEMP = 0,
256			PARAMETER_INPUT = 1,
257			PARAMETER_CONST = 2,
258			PARAMETER_TEXTURE = 3,
259			PARAMETER_ADDR = 3,
260			PARAMETER_RASTOUT = 4,
261			PARAMETER_ATTROUT = 5,
262			PARAMETER_TEXCRDOUT = 6,
263			PARAMETER_OUTPUT = 6,
264			PARAMETER_CONSTINT = 7,
265			PARAMETER_COLOROUT = 8,
266			PARAMETER_DEPTHOUT = 9,
267			PARAMETER_SAMPLER = 10,
268			PARAMETER_CONST2 = 11,
269			PARAMETER_CONST3 = 12,
270			PARAMETER_CONST4 = 13,
271			PARAMETER_CONSTBOOL = 14,
272			PARAMETER_LOOP = 15,
273			PARAMETER_TEMPFLOAT16 = 16,
274			PARAMETER_MISCTYPE = 17,
275			PARAMETER_LABEL = 18,
276			PARAMETER_PREDICATE = 19,
277
278		//	PARAMETER_FLOAT1LITERAL,
279		//	PARAMETER_FLOAT2LITERAL,
280		//	PARAMETER_FLOAT3LITERAL,
281			PARAMETER_FLOAT4LITERAL,
282			PARAMETER_BOOL1LITERAL,
283		//	PARAMETER_BOOL2LITERAL,
284		//	PARAMETER_BOOL3LITERAL,
285		//	PARAMETER_BOOL4LITERAL,
286		//	PARAMETER_INT1LITERAL,
287		//	PARAMETER_INT2LITERAL,
288		//	PARAMETER_INT3LITERAL,
289			PARAMETER_INT4LITERAL,
290
291			PARAMETER_VOID
292		};
293
294		enum Modifier
295		{
296			MODIFIER_NONE,
297			MODIFIER_NEGATE,
298			MODIFIER_BIAS,
299			MODIFIER_BIAS_NEGATE,
300			MODIFIER_SIGN,
301			MODIFIER_SIGN_NEGATE,
302			MODIFIER_COMPLEMENT,
303			MODIFIER_X2,
304			MODIFIER_X2_NEGATE,
305			MODIFIER_DZ,
306			MODIFIER_DW,
307			MODIFIER_ABS,
308			MODIFIER_ABS_NEGATE,
309			MODIFIER_NOT
310		};
311
312		enum Analysis
313		{
314			// Flags indicating whether an instruction is affected by an execution enable mask
315			ANALYSIS_BRANCH   = 0x00000001,
316			ANALYSIS_BREAK    = 0x00000002,
317			ANALYSIS_CONTINUE = 0x00000004,
318			ANALYSIS_LEAVE    = 0x00000008,
319		};
320
321		struct Parameter
322		{
323			union
324			{
325				struct
326				{
327					unsigned int index;   // For registers types
328
329					struct
330					{
331						ParameterType type : 8;
332						unsigned int index;
333						unsigned int swizzle : 8;
334						unsigned int scale;
335						bool deterministic;   // Equal accross shader instances run in lockstep (e.g. unrollable loop couters)
336					} rel;
337				};
338
339				float value[4];       // For float constants
340				int integer[4];       // For integer constants
341				int boolean[4];       // For boolean constants
342
343				struct
344				{
345					unsigned int label;      // Label index
346					unsigned int callSite;   // Call index (per label)
347				};
348			};
349
350			Parameter() : type(PARAMETER_VOID), index(0)
351			{
352				rel.type = PARAMETER_VOID;
353				rel.index = 0;
354				rel.swizzle = 0;
355				rel.scale = 1;
356				rel.deterministic = false;
357			}
358
359			std::string string(ShaderType shaderType, unsigned short version) const;
360			std::string typeString(ShaderType shaderType, unsigned short version) const;
361			std::string relativeString() const;
362
363			ParameterType type : 8;
364		};
365
366		struct DestinationParameter : Parameter
367		{
368			union
369			{
370				unsigned char mask;
371
372				struct
373				{
374					bool x : 1;
375					bool y : 1;
376					bool z : 1;
377					bool w : 1;
378				};
379			};
380
381			DestinationParameter() : mask(0xF), integer(false), saturate(false), partialPrecision(false), centroid(false), shift(0)
382			{
383			}
384
385			std::string modifierString() const;
386			std::string shiftString() const;
387			std::string maskString() const;
388
389			bool integer          : 1;
390			bool saturate         : 1;
391			bool partialPrecision : 1;
392			bool centroid         : 1;
393			signed char shift     : 4;
394		};
395
396		struct SourceParameter : Parameter
397		{
398			SourceParameter() : swizzle(0xE4), modifier(MODIFIER_NONE)
399			{
400			}
401
402			std::string swizzleString() const;
403			std::string preModifierString() const;
404			std::string postModifierString() const;
405
406			unsigned int swizzle : 8;
407			Modifier modifier : 8;
408		};
409
410		struct Instruction
411		{
412			explicit Instruction(Opcode opcode);
413			Instruction(const unsigned long *token, int size, unsigned char majorVersion);
414
415			virtual ~Instruction();
416
417			void parseOperationToken(unsigned long token, unsigned char majorVersion);
418			void parseDeclarationToken(unsigned long token);
419			void parseDestinationToken(const unsigned long *token, unsigned char majorVersion);
420			void parseSourceToken(int i, const unsigned long *token, unsigned char majorVersion);
421
422			std::string string(ShaderType shaderType, unsigned short version) const;
423			static std::string swizzleString(ParameterType type, unsigned char swizzle);
424			std::string operationString(unsigned short version) const;
425			std::string controlString() const;
426
427			bool isBranch() const;
428			bool isCall() const;
429			bool isBreak() const;
430			bool isLoop() const;
431			bool isEndLoop() const;
432
433			bool isPredicated() const;
434
435			Opcode opcode;
436
437			union
438			{
439				Control control;
440
441				struct
442				{
443					unsigned char project : 1;
444					unsigned char bias : 1;
445				};
446			};
447
448			bool predicate;
449			bool predicateNot;   // Negative predicate
450			unsigned char predicateSwizzle;
451
452			bool coissue;
453			SamplerType samplerType;
454			Usage usage;
455			unsigned char usageIndex;
456
457			DestinationParameter dst;
458			SourceParameter src[4];
459
460			union
461			{
462				unsigned int analysis;
463
464				struct
465				{
466					// Keep in sync with Shader::Analysis flags
467					unsigned int analysisBranch : 1;
468					unsigned int analysisBreak : 1;
469					unsigned int analysisContinue : 1;
470					unsigned int analysisLeave : 1;
471				};
472			};
473		};
474
475		Shader();
476
477		virtual ~Shader();
478
479		int getSerialID() const;
480		size_t getLength() const;
481		ShaderType getShaderType() const;
482		unsigned short getVersion() const;
483
484		void append(Instruction *instruction);
485		void declareSampler(int i);
486
487		const Instruction *getInstruction(unsigned int i) const;
488		int size(unsigned long opcode) const;
489		static int size(unsigned long opcode, unsigned short version);
490
491		void print(const char *fileName, ...) const;
492		void printInstruction(int index, const char *fileName) const;
493
494		static bool maskContainsComponent(int mask, int component);
495		static bool swizzleContainsComponent(int swizzle, int component);
496		static bool swizzleContainsComponentMasked(int swizzle, int component, int mask);
497
498		bool containsDynamicBranching() const;
499		bool containsBreakInstruction() const;
500		bool containsContinueInstruction() const;
501		bool containsLeaveInstruction() const;
502		bool usesSampler(int i) const;
503
504		struct Semantic
505		{
506			Semantic(unsigned char usage = 0xFF, unsigned char index = 0xFF) : usage(usage), index(index), centroid(false)
507			{
508			}
509
510			bool operator==(const Semantic &semantic) const
511			{
512				return usage == semantic.usage && index == semantic.index;
513			}
514
515			bool active() const
516			{
517				return usage != 0xFF;
518			}
519
520			unsigned char usage;
521			unsigned char index;
522			bool centroid;
523		};
524
525		void optimize();
526		virtual void analyze() = 0;
527
528		// FIXME: Private
529		unsigned int dirtyConstantsF;
530		unsigned int dirtyConstantsI;
531		unsigned int dirtyConstantsB;
532
533		bool dynamicallyIndexedTemporaries;
534		bool dynamicallyIndexedInput;
535		bool dynamicallyIndexedOutput;
536
537	protected:
538		void parse(const unsigned long *token);
539
540		void optimizeLeave();
541		void optimizeCall();
542		void removeNull();
543
544		void analyzeDirtyConstants();
545		void analyzeDynamicBranching();
546		void analyzeSamplers();
547		void analyzeCallSites();
548		void analyzeDynamicIndexing();
549		void markFunctionAnalysis(int functionLabel, Analysis flag);
550
551		ShaderType shaderType;
552
553		union
554		{
555			unsigned short version;
556
557			struct
558			{
559				unsigned char minorVersion;
560				unsigned char majorVersion;
561			};
562		};
563
564		std::vector<Instruction*> instruction;
565
566		unsigned short usedSamplers;   // Bit flags
567
568	private:
569		const int serialID;
570		static volatile int serialCounter;
571
572		bool dynamicBranching;
573		bool containsBreak;
574		bool containsContinue;
575		bool containsLeave;
576	};
577}
578
579#endif   // sw_Shader_hpp
580