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