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