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