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 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 Parametersw::Shader::Parameter417 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 DestinationParametersw::Shader::DestinationParameter448 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 { SourceParametersw::Shader::SourceParameter465 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 { Semanticsw::Shader::Semantic575 Semantic(unsigned char usage = 0xFF, unsigned char index = 0xFF) : usage(usage), index(index), centroid(false) 576 { 577 } 578 operator ==sw::Shader::Semantic579 bool operator==(const Semantic &semantic) const 580 { 581 return usage == semantic.usage && index == semantic.index; 582 } 583 activesw::Shader::Semantic584 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