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_SCALAR, // Marks the start of code not subject to SIMD lane masking. Ends at WHILE and ENDWHILE. 251 OPCODE_SWITCH, 252 OPCODE_ENDSWITCH, 253 254 // Integer opcodes 255 OPCODE_INEG, 256 OPCODE_IABS, 257 OPCODE_ISGN, 258 OPCODE_IADD, 259 OPCODE_ISUB, 260 OPCODE_IMUL, 261 OPCODE_IDIV, 262 OPCODE_IMAD, 263 OPCODE_IMOD, 264 OPCODE_SHL, 265 OPCODE_ISHR, 266 OPCODE_IMIN, 267 OPCODE_IMAX, 268 269 // Unsigned integer opcodes 270 OPCODE_UDIV, 271 OPCODE_UMOD, 272 OPCODE_USHR, 273 OPCODE_UMIN, 274 OPCODE_UMAX, 275 }; 276 277 static Opcode OPCODE_DP(int); 278 static Opcode OPCODE_LEN(int); 279 static Opcode OPCODE_DIST(int); 280 static Opcode OPCODE_NRM(int); 281 static Opcode OPCODE_FORWARD(int); 282 static Opcode OPCODE_REFLECT(int); 283 static Opcode OPCODE_REFRACT(int); 284 285 enum Control 286 { 287 CONTROL_RESERVED0, 288 CONTROL_GT, 289 CONTROL_EQ, 290 CONTROL_GE, 291 CONTROL_LT, 292 CONTROL_NE, 293 CONTROL_LE, 294 CONTROL_RESERVED1 295 }; 296 297 enum SamplerType 298 { 299 SAMPLER_UNKNOWN, 300 SAMPLER_1D, 301 SAMPLER_2D, 302 SAMPLER_CUBE, 303 SAMPLER_VOLUME 304 }; 305 306 enum Usage // For vertex input/output declarations 307 { 308 USAGE_POSITION = 0, 309 USAGE_BLENDWEIGHT = 1, 310 USAGE_BLENDINDICES = 2, 311 USAGE_NORMAL = 3, 312 USAGE_PSIZE = 4, 313 USAGE_TEXCOORD = 5, 314 USAGE_TANGENT = 6, 315 USAGE_BINORMAL = 7, 316 USAGE_TESSFACTOR = 8, 317 USAGE_POSITIONT = 9, 318 USAGE_COLOR = 10, 319 USAGE_FOG = 11, 320 USAGE_DEPTH = 12, 321 USAGE_SAMPLE = 13 322 }; 323 324 enum ParameterType 325 { 326 PARAMETER_TEMP = 0, 327 PARAMETER_INPUT = 1, 328 PARAMETER_CONST = 2, 329 PARAMETER_TEXTURE = 3, 330 PARAMETER_ADDR = 3, 331 PARAMETER_RASTOUT = 4, 332 PARAMETER_ATTROUT = 5, 333 PARAMETER_TEXCRDOUT = 6, 334 PARAMETER_OUTPUT = 6, 335 PARAMETER_CONSTINT = 7, 336 PARAMETER_COLOROUT = 8, 337 PARAMETER_DEPTHOUT = 9, 338 PARAMETER_SAMPLER = 10, 339 PARAMETER_CONST2 = 11, 340 PARAMETER_CONST3 = 12, 341 PARAMETER_CONST4 = 13, 342 PARAMETER_CONSTBOOL = 14, 343 PARAMETER_LOOP = 15, 344 PARAMETER_TEMPFLOAT16 = 16, 345 PARAMETER_MISCTYPE = 17, 346 PARAMETER_LABEL = 18, 347 PARAMETER_PREDICATE = 19, 348 349 // PARAMETER_FLOAT1LITERAL, 350 // PARAMETER_FLOAT2LITERAL, 351 // PARAMETER_FLOAT3LITERAL, 352 PARAMETER_FLOAT4LITERAL, 353 PARAMETER_BOOL1LITERAL, 354 // PARAMETER_BOOL2LITERAL, 355 // PARAMETER_BOOL3LITERAL, 356 // PARAMETER_BOOL4LITERAL, 357 // PARAMETER_INT1LITERAL, 358 // PARAMETER_INT2LITERAL, 359 // PARAMETER_INT3LITERAL, 360 PARAMETER_INT4LITERAL, 361 362 PARAMETER_VOID 363 }; 364 365 enum MiscParameterIndex 366 { 367 VPosIndex = 0, 368 VFaceIndex = 1, 369 InstanceIDIndex = 2, 370 VertexIDIndex = 3, 371 }; 372 373 enum Modifier 374 { 375 MODIFIER_NONE, 376 MODIFIER_NEGATE, 377 MODIFIER_BIAS, 378 MODIFIER_BIAS_NEGATE, 379 MODIFIER_SIGN, 380 MODIFIER_SIGN_NEGATE, 381 MODIFIER_COMPLEMENT, 382 MODIFIER_X2, 383 MODIFIER_X2_NEGATE, 384 MODIFIER_DZ, 385 MODIFIER_DW, 386 MODIFIER_ABS, 387 MODIFIER_ABS_NEGATE, 388 MODIFIER_NOT 389 }; 390 391 enum Analysis 392 { 393 // Flags indicating whether an instruction is affected by an execution enable mask 394 ANALYSIS_BRANCH = 0x00000001, 395 ANALYSIS_BREAK = 0x00000002, 396 ANALYSIS_CONTINUE = 0x00000004, 397 ANALYSIS_LEAVE = 0x00000008, 398 }; 399 400 struct Relative 401 { 402 ParameterType type : 8; 403 unsigned int index; 404 unsigned int swizzle : 8; 405 unsigned int scale; 406 bool dynamic; // Varies between concurrent shader instances 407 }; 408 409 struct Parameter 410 { 411 union 412 { 413 struct 414 { 415 unsigned int index; // For registers types 416 417 Relative rel; 418 }; 419 420 float value[4]; // For float constants 421 int integer[4]; // For integer constants 422 int boolean[4]; // For boolean constants 423 424 struct 425 { 426 unsigned int label; // Label index 427 unsigned int callSite; // Call index (per label) 428 }; 429 }; 430 Parametersw::Shader::Parameter431 Parameter() : index(0), type(PARAMETER_VOID) 432 { 433 rel.type = PARAMETER_VOID; 434 rel.index = 0; 435 rel.swizzle = 0; 436 rel.scale = 1; 437 rel.dynamic = true; 438 } 439 440 std::string string(ShaderType shaderType, unsigned short version) const; 441 std::string typeString(ShaderType shaderType, unsigned short version) const; 442 std::string relativeString() const; 443 444 ParameterType type : 8; 445 }; 446 447 struct DestinationParameter : Parameter 448 { 449 union 450 { 451 unsigned char mask; 452 453 struct 454 { 455 bool x : 1; 456 bool y : 1; 457 bool z : 1; 458 bool w : 1; 459 }; 460 }; 461 DestinationParametersw::Shader::DestinationParameter462 DestinationParameter() : mask(0xF), saturate(false), partialPrecision(false), centroid(false), shift(0) 463 { 464 } 465 466 std::string modifierString() const; 467 std::string shiftString() const; 468 std::string maskString() const; 469 470 bool saturate : 1; 471 bool partialPrecision : 1; 472 bool centroid : 1; 473 signed char shift : 4; 474 }; 475 476 struct SourceParameter : Parameter 477 { SourceParametersw::Shader::SourceParameter478 SourceParameter() : swizzle(0xE4), modifier(MODIFIER_NONE), bufferIndex(-1) 479 { 480 } 481 482 std::string string(ShaderType shaderType, unsigned short version) const; 483 std::string swizzleString() const; 484 std::string preModifierString() const; 485 std::string postModifierString() const; 486 487 unsigned int swizzle : 8; 488 Modifier modifier : 8; 489 int bufferIndex : 8; 490 }; 491 492 struct Instruction 493 { 494 explicit Instruction(Opcode opcode); 495 Instruction(const unsigned long *token, int size, unsigned char majorVersion); 496 497 virtual ~Instruction(); 498 499 void parseOperationToken(unsigned long token, unsigned char majorVersion); 500 void parseDeclarationToken(unsigned long token); 501 void parseDestinationToken(const unsigned long *token, unsigned char majorVersion); 502 void parseSourceToken(int i, const unsigned long *token, unsigned char majorVersion); 503 504 std::string string(ShaderType shaderType, unsigned short version) const; 505 static std::string swizzleString(ParameterType type, unsigned char swizzle); 506 std::string operationString(unsigned short version) const; 507 std::string controlString() const; 508 509 bool isBranch() const; 510 bool isCall() const; 511 bool isBreak() const; 512 bool isLoop() const; 513 bool isEndLoop() const; 514 515 bool isPredicated() const; 516 517 Opcode opcode; 518 519 union 520 { 521 Control control; 522 523 struct 524 { 525 unsigned char project : 1; // D3DSI_TEXLD_PROJECT 526 unsigned char bias : 1; // D3DSI_TEXLD_BIAS 527 }; 528 }; 529 530 bool predicate; 531 bool predicateNot; // Negative predicate 532 unsigned char predicateSwizzle; 533 534 bool coissue; 535 SamplerType samplerType; 536 Usage usage; 537 unsigned char usageIndex; 538 539 DestinationParameter dst; 540 SourceParameter src[5]; 541 542 union 543 { 544 unsigned int analysis; 545 546 struct 547 { 548 // Keep in sync with Shader::Analysis flags 549 unsigned int analysisBranch : 1; 550 unsigned int analysisBreak : 1; 551 unsigned int analysisContinue : 1; 552 unsigned int analysisLeave : 1; 553 }; 554 }; 555 }; 556 557 Shader(); 558 559 virtual ~Shader(); 560 561 int getSerialID() const; 562 size_t getLength() const; 563 ShaderType getShaderType() const; 564 unsigned short getShaderModel() const; 565 566 void append(Instruction *instruction); 567 void declareSampler(int i); 568 569 const Instruction *getInstruction(size_t i) const; 570 int size(unsigned long opcode) const; 571 static int size(unsigned long opcode, unsigned short shaderModel); 572 573 void print(const char *fileName, ...) const; 574 void printInstruction(int index, const char *fileName) const; 575 576 static bool maskContainsComponent(int mask, int component); 577 static bool swizzleContainsComponent(int swizzle, int component); 578 static bool swizzleContainsComponentMasked(int swizzle, int component, int mask); 579 580 bool containsDynamicBranching() const; 581 bool containsBreakInstruction() const; 582 bool containsContinueInstruction() const; 583 bool containsLeaveInstruction() const; 584 bool containsDefineInstruction() const; 585 bool usesSampler(int i) const; 586 587 struct Semantic 588 { Semanticsw::Shader::Semantic589 Semantic(unsigned char usage = 0xFF, unsigned char index = 0xFF, bool flat = false) : usage(usage), index(index), centroid(false), flat(flat) 590 { 591 } 592 operator ==sw::Shader::Semantic593 bool operator==(const Semantic &semantic) const 594 { 595 return usage == semantic.usage && index == semantic.index; 596 } 597 activesw::Shader::Semantic598 bool active() const 599 { 600 return usage != 0xFF; 601 } 602 603 unsigned char usage; 604 unsigned char index; 605 bool centroid; 606 bool flat; 607 }; 608 609 void optimize(); 610 611 // FIXME: Private 612 unsigned int dirtyConstantsF; 613 unsigned int dirtyConstantsI; 614 unsigned int dirtyConstantsB; 615 616 bool indirectAddressableTemporaries; 617 bool indirectAddressableInput; 618 bool indirectAddressableOutput; 619 620 protected: 621 void parse(const unsigned long *token); 622 623 void optimizeLeave(); 624 void optimizeCall(); 625 void removeNull(); 626 627 void analyzeDirtyConstants(); 628 void analyzeDynamicBranching(); 629 void analyzeSamplers(); 630 void analyzeCallSites(); 631 void analyzeIndirectAddressing(); 632 void markFunctionAnalysis(unsigned int functionLabel, Analysis flag); 633 634 ShaderType shaderType; 635 636 union 637 { 638 unsigned short shaderModel; 639 640 struct 641 { 642 unsigned char minorVersion; 643 unsigned char majorVersion; 644 }; 645 }; 646 647 std::vector<Instruction*> instruction; 648 649 unsigned short usedSamplers; // Bit flags 650 651 private: 652 const int serialID; 653 static volatile int serialCounter; 654 655 bool dynamicBranching; 656 bool containsBreak; 657 bool containsContinue; 658 bool containsLeave; 659 bool containsDefine; 660 }; 661 } 662 663 #endif // sw_Shader_hpp 664