Shader.hpp revision c3d95f36258143af6cca041ede521995d8f890ea
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_COSH,
151			OPCODE_SINH,
152			OPCODE_TANH,
153			OPCODE_ACOSH,
154			OPCODE_ASINH,
155			OPCODE_ATANH,
156			OPCODE_DP1,
157			OPCODE_DP2,
158			OPCODE_TRUNC,
159			OPCODE_FLOOR,
160			OPCODE_ROUND,
161			OPCODE_ROUNDEVEN,
162			OPCODE_CEIL,
163			OPCODE_SQRT,
164			OPCODE_RSQ,
165			OPCODE_LEN2,
166			OPCODE_LEN3,
167			OPCODE_LEN4,
168			OPCODE_DIST1,
169			OPCODE_DIST2,
170			OPCODE_DIST3,
171			OPCODE_DIST4,
172			OPCODE_NRM2,
173			OPCODE_NRM4,
174			OPCODE_DIV,
175			OPCODE_MOD,
176			OPCODE_EXP2,
177			OPCODE_LOG2,
178			OPCODE_EXP,
179			OPCODE_LOG,
180			OPCODE_POW,
181			OPCODE_F2B,   // Float to bool
182			OPCODE_B2F,   // Bool to float
183			OPCODE_F2I,   // Float to int
184			OPCODE_I2F,   // Int to float
185			OPCODE_F2U,   // Float to uint
186			OPCODE_U2F,   // Uint to float
187			OPCODE_I2B,   // Int to bool
188			OPCODE_B2I,   // Bool to int
189			OPCODE_U2B,   // Uint to bool
190			OPCODE_B2U,   // Bool to uint
191			OPCODE_DET2,
192			OPCODE_DET3,
193			OPCODE_DET4,
194			OPCODE_ALL,
195			OPCODE_ANY,
196			OPCODE_NEG,
197			OPCODE_NOT,
198			OPCODE_OR,
199			OPCODE_XOR,
200			OPCODE_AND,
201			OPCODE_EQ,
202			OPCODE_NE,
203			OPCODE_STEP,
204			OPCODE_SMOOTH,
205			OPCODE_ISNAN,
206			OPCODE_ISINF,
207			OPCODE_FLOATBITSTOINT,
208			OPCODE_FLOATBITSTOUINT,
209			OPCODE_INTBITSTOFLOAT,
210			OPCODE_UINTBITSTOFLOAT,
211			OPCODE_PACKSNORM2x16,
212			OPCODE_PACKUNORM2x16,
213			OPCODE_PACKHALF2x16,
214			OPCODE_UNPACKSNORM2x16,
215			OPCODE_UNPACKUNORM2x16,
216			OPCODE_UNPACKHALF2x16,
217			OPCODE_FORWARD1,
218			OPCODE_FORWARD2,
219			OPCODE_FORWARD3,
220			OPCODE_FORWARD4,
221			OPCODE_REFLECT1,
222			OPCODE_REFLECT2,
223			OPCODE_REFLECT3,
224			OPCODE_REFLECT4,
225			OPCODE_REFRACT1,
226			OPCODE_REFRACT2,
227			OPCODE_REFRACT3,
228			OPCODE_REFRACT4,
229			OPCODE_ICMP,
230			OPCODE_UCMP,
231			OPCODE_SELECT,
232			OPCODE_EXTRACT,
233			OPCODE_INSERT,
234			OPCODE_DISCARD,
235			OPCODE_FWIDTH,
236			OPCODE_LEAVE,   // Return before the end of the function
237			OPCODE_CONTINUE,
238			OPCODE_TEST,   // Marks the end of the code that can be skipped by 'continue'
239
240			// Integer opcodes
241			OPCODE_INEG,
242			OPCODE_IADD,
243			OPCODE_ISUB,
244			OPCODE_IMUL,
245			OPCODE_IDIV,
246			OPCODE_IMAD,
247			OPCODE_IMOD,
248			OPCODE_SHL,
249			OPCODE_ISHR,
250			OPCODE_IMIN,
251			OPCODE_IMAX,
252
253			// Unsigned integer opcodes
254			OPCODE_UDIV,
255			OPCODE_UMOD,
256			OPCODE_USHR,
257			OPCODE_UMIN,
258			OPCODE_UMAX,
259		};
260
261		static Opcode OPCODE_DP(int);
262		static Opcode OPCODE_LEN(int);
263		static Opcode OPCODE_DIST(int);
264		static Opcode OPCODE_NRM(int);
265		static Opcode OPCODE_FORWARD(int);
266		static Opcode OPCODE_REFLECT(int);
267		static Opcode OPCODE_REFRACT(int);
268
269		enum Control
270		{
271			CONTROL_RESERVED0,
272			CONTROL_GT,
273			CONTROL_EQ,
274			CONTROL_GE,
275			CONTROL_LT,
276			CONTROL_NE,
277			CONTROL_LE,
278			CONTROL_RESERVED1
279		};
280
281		enum SamplerType
282		{
283			SAMPLER_UNKNOWN,
284			SAMPLER_1D,
285			SAMPLER_2D,
286			SAMPLER_CUBE,
287			SAMPLER_VOLUME
288		};
289
290		enum Usage   // For vertex input/output declarations
291		{
292			USAGE_POSITION = 0,
293			USAGE_BLENDWEIGHT = 1,
294			USAGE_BLENDINDICES = 2,
295			USAGE_NORMAL = 3,
296			USAGE_PSIZE = 4,
297			USAGE_TEXCOORD = 5,
298			USAGE_TANGENT = 6,
299			USAGE_BINORMAL = 7,
300			USAGE_TESSFACTOR = 8,
301			USAGE_POSITIONT = 9,
302			USAGE_COLOR = 10,
303			USAGE_FOG = 11,
304			USAGE_DEPTH = 12,
305			USAGE_SAMPLE = 13
306		};
307
308		enum ParameterType
309		{
310			PARAMETER_TEMP = 0,
311			PARAMETER_INPUT = 1,
312			PARAMETER_CONST = 2,
313			PARAMETER_TEXTURE = 3,
314			PARAMETER_ADDR = 3,
315			PARAMETER_RASTOUT = 4,
316			PARAMETER_ATTROUT = 5,
317			PARAMETER_TEXCRDOUT = 6,
318			PARAMETER_OUTPUT = 6,
319			PARAMETER_CONSTINT = 7,
320			PARAMETER_COLOROUT = 8,
321			PARAMETER_DEPTHOUT = 9,
322			PARAMETER_SAMPLER = 10,
323			PARAMETER_CONST2 = 11,
324			PARAMETER_CONST3 = 12,
325			PARAMETER_CONST4 = 13,
326			PARAMETER_CONSTBOOL = 14,
327			PARAMETER_LOOP = 15,
328			PARAMETER_TEMPFLOAT16 = 16,
329			PARAMETER_MISCTYPE = 17,
330			PARAMETER_LABEL = 18,
331			PARAMETER_PREDICATE = 19,
332
333		//	PARAMETER_FLOAT1LITERAL,
334		//	PARAMETER_FLOAT2LITERAL,
335		//	PARAMETER_FLOAT3LITERAL,
336			PARAMETER_FLOAT4LITERAL,
337			PARAMETER_BOOL1LITERAL,
338		//	PARAMETER_BOOL2LITERAL,
339		//	PARAMETER_BOOL3LITERAL,
340		//	PARAMETER_BOOL4LITERAL,
341		//	PARAMETER_INT1LITERAL,
342		//	PARAMETER_INT2LITERAL,
343		//	PARAMETER_INT3LITERAL,
344			PARAMETER_INT4LITERAL,
345
346			PARAMETER_VOID
347		};
348
349		enum Modifier
350		{
351			MODIFIER_NONE,
352			MODIFIER_NEGATE,
353			MODIFIER_BIAS,
354			MODIFIER_BIAS_NEGATE,
355			MODIFIER_SIGN,
356			MODIFIER_SIGN_NEGATE,
357			MODIFIER_COMPLEMENT,
358			MODIFIER_X2,
359			MODIFIER_X2_NEGATE,
360			MODIFIER_DZ,
361			MODIFIER_DW,
362			MODIFIER_ABS,
363			MODIFIER_ABS_NEGATE,
364			MODIFIER_NOT
365		};
366
367		enum Analysis
368		{
369			// Flags indicating whether an instruction is affected by an execution enable mask
370			ANALYSIS_BRANCH   = 0x00000001,
371			ANALYSIS_BREAK    = 0x00000002,
372			ANALYSIS_CONTINUE = 0x00000004,
373			ANALYSIS_LEAVE    = 0x00000008,
374		};
375
376		struct Parameter
377		{
378			union
379			{
380				struct
381				{
382					unsigned int index;   // For registers types
383
384					struct
385					{
386						ParameterType type : 8;
387						unsigned int index;
388						unsigned int swizzle : 8;
389						unsigned int scale;
390						bool deterministic;   // Equal accross shader instances run in lockstep (e.g. unrollable loop couters)
391					} rel;
392				};
393
394				float value[4];       // For float constants
395				int integer[4];       // For integer constants
396				int boolean[4];       // For boolean constants
397
398				struct
399				{
400					unsigned int label;      // Label index
401					unsigned int callSite;   // Call index (per label)
402				};
403			};
404
405			Parameter() : index(0), type(PARAMETER_VOID)
406			{
407				rel.type = PARAMETER_VOID;
408				rel.index = 0;
409				rel.swizzle = 0;
410				rel.scale = 1;
411				rel.deterministic = false;
412			}
413
414			std::string string(ShaderType shaderType, unsigned short version) const;
415			std::string typeString(ShaderType shaderType, unsigned short version) const;
416			std::string relativeString() const;
417
418			ParameterType type : 8;
419		};
420
421		struct DestinationParameter : Parameter
422		{
423			union
424			{
425				unsigned char mask;
426
427				struct
428				{
429					bool x : 1;
430					bool y : 1;
431					bool z : 1;
432					bool w : 1;
433				};
434			};
435
436			DestinationParameter() : mask(0xF), integer(false), saturate(false), partialPrecision(false), centroid(false), shift(0)
437			{
438			}
439
440			std::string modifierString() const;
441			std::string shiftString() const;
442			std::string maskString() const;
443
444			bool integer          : 1;
445			bool saturate         : 1;
446			bool partialPrecision : 1;
447			bool centroid         : 1;
448			signed char shift     : 4;
449		};
450
451		struct SourceParameter : Parameter
452		{
453			SourceParameter() : swizzle(0xE4), modifier(MODIFIER_NONE)
454			{
455			}
456
457			std::string swizzleString() const;
458			std::string preModifierString() const;
459			std::string postModifierString() const;
460
461			unsigned int swizzle : 8;
462			Modifier modifier : 8;
463		};
464
465		struct Instruction
466		{
467			explicit Instruction(Opcode opcode);
468			Instruction(const unsigned long *token, int size, unsigned char majorVersion);
469
470			virtual ~Instruction();
471
472			void parseOperationToken(unsigned long token, unsigned char majorVersion);
473			void parseDeclarationToken(unsigned long token);
474			void parseDestinationToken(const unsigned long *token, unsigned char majorVersion);
475			void parseSourceToken(int i, const unsigned long *token, unsigned char majorVersion);
476
477			std::string string(ShaderType shaderType, unsigned short version) const;
478			static std::string swizzleString(ParameterType type, unsigned char swizzle);
479			std::string operationString(unsigned short version) const;
480			std::string controlString() const;
481
482			bool isBranch() const;
483			bool isCall() const;
484			bool isBreak() const;
485			bool isLoop() const;
486			bool isEndLoop() const;
487
488			bool isPredicated() const;
489
490			Opcode opcode;
491
492			union
493			{
494				Control control;
495
496				struct
497				{
498					unsigned char project : 1;
499					unsigned char bias : 1;
500				};
501			};
502
503			bool predicate;
504			bool predicateNot;   // Negative predicate
505			unsigned char predicateSwizzle;
506
507			bool coissue;
508			SamplerType samplerType;
509			Usage usage;
510			unsigned char usageIndex;
511
512			DestinationParameter dst;
513			SourceParameter src[4];
514
515			union
516			{
517				unsigned int analysis;
518
519				struct
520				{
521					// Keep in sync with Shader::Analysis flags
522					unsigned int analysisBranch : 1;
523					unsigned int analysisBreak : 1;
524					unsigned int analysisContinue : 1;
525					unsigned int analysisLeave : 1;
526				};
527			};
528		};
529
530		Shader();
531
532		virtual ~Shader();
533
534		int getSerialID() const;
535		size_t getLength() const;
536		ShaderType getShaderType() const;
537		unsigned short getVersion() const;
538
539		void append(Instruction *instruction);
540		void declareSampler(int i);
541
542		const Instruction *getInstruction(unsigned int i) const;
543		int size(unsigned long opcode) const;
544		static int size(unsigned long opcode, unsigned short version);
545
546		void print(const char *fileName, ...) const;
547		void printInstruction(int index, const char *fileName) const;
548
549		static bool maskContainsComponent(int mask, int component);
550		static bool swizzleContainsComponent(int swizzle, int component);
551		static bool swizzleContainsComponentMasked(int swizzle, int component, int mask);
552
553		bool containsDynamicBranching() const;
554		bool containsBreakInstruction() const;
555		bool containsContinueInstruction() const;
556		bool containsLeaveInstruction() const;
557		bool containsDefineInstruction() const;
558		bool usesSampler(int i) const;
559
560		struct Semantic
561		{
562			Semantic(unsigned char usage = 0xFF, unsigned char index = 0xFF) : usage(usage), index(index), centroid(false)
563			{
564			}
565
566			bool operator==(const Semantic &semantic) const
567			{
568				return usage == semantic.usage && index == semantic.index;
569			}
570
571			bool active() const
572			{
573				return usage != 0xFF;
574			}
575
576			unsigned char usage;
577			unsigned char index;
578			bool centroid;
579		};
580
581		void optimize();
582		virtual void analyze() = 0;
583
584		// FIXME: Private
585		unsigned int dirtyConstantsF;
586		unsigned int dirtyConstantsI;
587		unsigned int dirtyConstantsB;
588
589		bool dynamicallyIndexedTemporaries;
590		bool dynamicallyIndexedInput;
591		bool dynamicallyIndexedOutput;
592
593	protected:
594		void parse(const unsigned long *token);
595
596		void optimizeLeave();
597		void optimizeCall();
598		void removeNull();
599
600		void analyzeDirtyConstants();
601		void analyzeDynamicBranching();
602		void analyzeSamplers();
603		void analyzeCallSites();
604		void analyzeDynamicIndexing();
605		void markFunctionAnalysis(int functionLabel, Analysis flag);
606
607		ShaderType shaderType;
608
609		union
610		{
611			unsigned short version;
612
613			struct
614			{
615				unsigned char minorVersion;
616				unsigned char majorVersion;
617			};
618		};
619
620		std::vector<Instruction*> instruction;
621
622		unsigned short usedSamplers;   // Bit flags
623
624	private:
625		const int serialID;
626		static volatile int serialCounter;
627
628		bool dynamicBranching;
629		bool containsBreak;
630		bool containsContinue;
631		bool containsLeave;
632		bool containsDefine;
633	};
634}
635
636#endif   // sw_Shader_hpp
637