1 // 2 // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 #include "compiler/OutputHLSL.h" 8 9 #include "compiler/debug.h" 10 #include "compiler/InfoSink.h" 11 #include "compiler/UnfoldSelect.h" 12 #include "compiler/SearchSymbol.h" 13 14 #include <stdio.h> 15 #include <algorithm> 16 17 namespace sh 18 { 19 // Integer to TString conversion 20 TString str(int i) 21 { 22 char buffer[20]; 23 sprintf(buffer, "%d", i); 24 return buffer; 25 } 26 27 OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, true), mContext(context) 28 { 29 mUnfoldSelect = new UnfoldSelect(context, this); 30 mInsideFunction = false; 31 32 mUsesTexture2D = false; 33 mUsesTexture2D_bias = false; 34 mUsesTexture2DProj = false; 35 mUsesTexture2DProj_bias = false; 36 mUsesTextureCube = false; 37 mUsesTextureCube_bias = false; 38 mUsesDepthRange = false; 39 mUsesFragCoord = false; 40 mUsesPointCoord = false; 41 mUsesFrontFacing = false; 42 mUsesPointSize = false; 43 mUsesXor = false; 44 mUsesMod1 = false; 45 mUsesMod2 = false; 46 mUsesMod3 = false; 47 mUsesMod4 = false; 48 mUsesFaceforward1 = false; 49 mUsesFaceforward2 = false; 50 mUsesFaceforward3 = false; 51 mUsesFaceforward4 = false; 52 mUsesEqualMat2 = false; 53 mUsesEqualMat3 = false; 54 mUsesEqualMat4 = false; 55 mUsesEqualVec2 = false; 56 mUsesEqualVec3 = false; 57 mUsesEqualVec4 = false; 58 mUsesEqualIVec2 = false; 59 mUsesEqualIVec3 = false; 60 mUsesEqualIVec4 = false; 61 mUsesEqualBVec2 = false; 62 mUsesEqualBVec3 = false; 63 mUsesEqualBVec4 = false; 64 mUsesAtan2 = false; 65 66 mScopeDepth = 0; 67 68 mUniqueIndex = 0; 69 } 70 71 OutputHLSL::~OutputHLSL() 72 { 73 delete mUnfoldSelect; 74 } 75 76 void OutputHLSL::output() 77 { 78 mContext.treeRoot->traverse(this); // Output the body first to determine what has to go in the header 79 header(); 80 81 mContext.infoSink.obj << mHeader.c_str(); 82 mContext.infoSink.obj << mBody.c_str(); 83 } 84 85 TInfoSinkBase &OutputHLSL::getBodyStream() 86 { 87 return mBody; 88 } 89 90 int OutputHLSL::vectorSize(const TType &type) const 91 { 92 int elementSize = type.isMatrix() ? type.getNominalSize() : 1; 93 int arraySize = type.isArray() ? type.getArraySize() : 1; 94 95 return elementSize * arraySize; 96 } 97 98 void OutputHLSL::header() 99 { 100 ShShaderType shaderType = mContext.shaderType; 101 TInfoSinkBase &out = mHeader; 102 103 for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++) 104 { 105 out << *structDeclaration; 106 } 107 108 for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++) 109 { 110 out << *constructor; 111 } 112 113 if (shaderType == SH_FRAGMENT_SHADER) 114 { 115 TString uniforms; 116 TString varyings; 117 118 TSymbolTableLevel *symbols = mContext.symbolTable.getGlobalLevel(); 119 int semanticIndex = 0; 120 121 for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++) 122 { 123 const TSymbol *symbol = (*namedSymbol).second; 124 const TString &name = symbol->getName(); 125 126 if (symbol->isVariable()) 127 { 128 const TVariable *variable = static_cast<const TVariable*>(symbol); 129 const TType &type = variable->getType(); 130 TQualifier qualifier = type.getQualifier(); 131 132 if (qualifier == EvqUniform) 133 { 134 if (mReferencedUniforms.find(name.c_str()) != mReferencedUniforms.end()) 135 { 136 uniforms += "uniform " + typeString(type) + " " + decorate(name) + arrayString(type) + ";\n"; 137 } 138 } 139 else if (qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn) 140 { 141 if (mReferencedVaryings.find(name.c_str()) != mReferencedVaryings.end()) 142 { 143 // Program linking depends on this exact format 144 varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; 145 146 semanticIndex += type.isArray() ? type.getArraySize() : 1; 147 } 148 } 149 else if (qualifier == EvqGlobal || qualifier == EvqTemporary) 150 { 151 // Globals are declared and intialized as an aggregate node 152 } 153 else if (qualifier == EvqConst) 154 { 155 // Constants are repeated as literals where used 156 } 157 else UNREACHABLE(); 158 } 159 } 160 161 out << "// Varyings\n"; 162 out << varyings; 163 out << "\n" 164 "static float4 gl_Color[1] = {float4(0, 0, 0, 0)};\n"; 165 166 if (mUsesFragCoord) 167 { 168 out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n"; 169 } 170 171 if (mUsesPointCoord) 172 { 173 out << "static float2 gl_PointCoord = float2(0.5, 0.5);\n"; 174 } 175 176 if (mUsesFrontFacing) 177 { 178 out << "static bool gl_FrontFacing = false;\n"; 179 } 180 181 out << "\n"; 182 183 if (mUsesFragCoord) 184 { 185 out << "uniform float4 dx_Viewport;\n" 186 "uniform float2 dx_Depth;\n"; 187 } 188 189 if (mUsesFrontFacing) 190 { 191 out << "uniform bool dx_PointsOrLines;\n" 192 "uniform bool dx_FrontCCW;\n"; 193 } 194 195 out << "\n"; 196 out << uniforms; 197 out << "\n"; 198 199 if (mUsesTexture2D) 200 { 201 out << "float4 gl_texture2D(sampler2D s, float2 t)\n" 202 "{\n" 203 " return tex2D(s, t);\n" 204 "}\n" 205 "\n"; 206 } 207 208 if (mUsesTexture2D_bias) 209 { 210 out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n" 211 "{\n" 212 " return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n" 213 "}\n" 214 "\n"; 215 } 216 217 if (mUsesTexture2DProj) 218 { 219 out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n" 220 "{\n" 221 " return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n" 222 "}\n" 223 "\n" 224 "float4 gl_texture2DProj(sampler2D s, float4 t)\n" 225 "{\n" 226 " return tex2Dproj(s, t);\n" 227 "}\n" 228 "\n"; 229 } 230 231 if (mUsesTexture2DProj_bias) 232 { 233 out << "float4 gl_texture2DProj(sampler2D s, float3 t, float bias)\n" 234 "{\n" 235 " return tex2Dbias(s, float4(t.x / t.z, t.y / t.z, 0, bias));\n" 236 "}\n" 237 "\n" 238 "float4 gl_texture2DProj(sampler2D s, float4 t, float bias)\n" 239 "{\n" 240 " return tex2Dbias(s, float4(t.x / t.w, t.y / t.w, 0, bias));\n" 241 "}\n" 242 "\n"; 243 } 244 245 if (mUsesTextureCube) 246 { 247 out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" 248 "{\n" 249 " return texCUBE(s, t);\n" 250 "}\n" 251 "\n"; 252 } 253 254 if (mUsesTextureCube_bias) 255 { 256 out << "float4 gl_textureCube(samplerCUBE s, float3 t, float bias)\n" 257 "{\n" 258 " return texCUBEbias(s, float4(t.x, t.y, t.z, bias));\n" 259 "}\n" 260 "\n"; 261 } 262 } 263 else // Vertex shader 264 { 265 TString uniforms; 266 TString attributes; 267 TString varyings; 268 269 TSymbolTableLevel *symbols = mContext.symbolTable.getGlobalLevel(); 270 271 for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++) 272 { 273 const TSymbol *symbol = (*namedSymbol).second; 274 const TString &name = symbol->getName(); 275 276 if (symbol->isVariable()) 277 { 278 const TVariable *variable = static_cast<const TVariable*>(symbol); 279 const TType &type = variable->getType(); 280 TQualifier qualifier = type.getQualifier(); 281 282 if (qualifier == EvqUniform) 283 { 284 if (mReferencedUniforms.find(name.c_str()) != mReferencedUniforms.end()) 285 { 286 uniforms += "uniform " + typeString(type) + " " + decorate(name) + arrayString(type) + ";\n"; 287 } 288 } 289 else if (qualifier == EvqAttribute) 290 { 291 if (mReferencedAttributes.find(name.c_str()) != mReferencedAttributes.end()) 292 { 293 attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; 294 } 295 } 296 else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut) 297 { 298 if (mReferencedVaryings.find(name.c_str()) != mReferencedVaryings.end()) 299 { 300 // Program linking depends on this exact format 301 varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; 302 } 303 } 304 else if (qualifier == EvqGlobal || qualifier == EvqTemporary) 305 { 306 // Globals are declared and intialized as an aggregate node 307 } 308 else if (qualifier == EvqConst) 309 { 310 // Constants are repeated as literals where used 311 } 312 else UNREACHABLE(); 313 } 314 } 315 316 out << "// Attributes\n"; 317 out << attributes; 318 out << "\n" 319 "static float4 gl_Position = float4(0, 0, 0, 0);\n"; 320 321 if (mUsesPointSize) 322 { 323 out << "static float gl_PointSize = float(1);\n"; 324 } 325 326 out << "\n" 327 "// Varyings\n"; 328 out << varyings; 329 out << "\n" 330 "uniform float2 dx_HalfPixelSize;\n" 331 "\n"; 332 out << uniforms; 333 out << "\n"; 334 } 335 336 if (mUsesFragCoord) 337 { 338 out << "#define GL_USES_FRAG_COORD\n"; 339 } 340 341 if (mUsesPointCoord) 342 { 343 out << "#define GL_USES_POINT_COORD\n"; 344 } 345 346 if (mUsesFrontFacing) 347 { 348 out << "#define GL_USES_FRONT_FACING\n"; 349 } 350 351 if (mUsesPointSize) 352 { 353 out << "#define GL_USES_POINT_SIZE\n"; 354 } 355 356 if (mUsesDepthRange) 357 { 358 out << "struct gl_DepthRangeParameters\n" 359 "{\n" 360 " float near;\n" 361 " float far;\n" 362 " float diff;\n" 363 "};\n" 364 "\n" 365 "uniform float3 dx_DepthRange;" 366 "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" 367 "\n"; 368 } 369 370 if (mUsesXor) 371 { 372 out << "bool xor(bool p, bool q)\n" 373 "{\n" 374 " return (p || q) && !(p && q);\n" 375 "}\n" 376 "\n"; 377 } 378 379 if (mUsesMod1) 380 { 381 out << "float mod(float x, float y)\n" 382 "{\n" 383 " return x - y * floor(x / y);\n" 384 "}\n" 385 "\n"; 386 } 387 388 if (mUsesMod2) 389 { 390 out << "float2 mod(float2 x, float y)\n" 391 "{\n" 392 " return x - y * floor(x / y);\n" 393 "}\n" 394 "\n"; 395 } 396 397 if (mUsesMod3) 398 { 399 out << "float3 mod(float3 x, float y)\n" 400 "{\n" 401 " return x - y * floor(x / y);\n" 402 "}\n" 403 "\n"; 404 } 405 406 if (mUsesMod4) 407 { 408 out << "float4 mod(float4 x, float y)\n" 409 "{\n" 410 " return x - y * floor(x / y);\n" 411 "}\n" 412 "\n"; 413 } 414 415 if (mUsesFaceforward1) 416 { 417 out << "float faceforward(float N, float I, float Nref)\n" 418 "{\n" 419 " if(dot(Nref, I) >= 0)\n" 420 " {\n" 421 " return -N;\n" 422 " }\n" 423 " else\n" 424 " {\n" 425 " return N;\n" 426 " }\n" 427 "}\n" 428 "\n"; 429 } 430 431 if (mUsesFaceforward2) 432 { 433 out << "float2 faceforward(float2 N, float2 I, float2 Nref)\n" 434 "{\n" 435 " if(dot(Nref, I) >= 0)\n" 436 " {\n" 437 " return -N;\n" 438 " }\n" 439 " else\n" 440 " {\n" 441 " return N;\n" 442 " }\n" 443 "}\n" 444 "\n"; 445 } 446 447 if (mUsesFaceforward3) 448 { 449 out << "float3 faceforward(float3 N, float3 I, float3 Nref)\n" 450 "{\n" 451 " if(dot(Nref, I) >= 0)\n" 452 " {\n" 453 " return -N;\n" 454 " }\n" 455 " else\n" 456 " {\n" 457 " return N;\n" 458 " }\n" 459 "}\n" 460 "\n"; 461 } 462 463 if (mUsesFaceforward4) 464 { 465 out << "float4 faceforward(float4 N, float4 I, float4 Nref)\n" 466 "{\n" 467 " if(dot(Nref, I) >= 0)\n" 468 " {\n" 469 " return -N;\n" 470 " }\n" 471 " else\n" 472 " {\n" 473 " return N;\n" 474 " }\n" 475 "}\n" 476 "\n"; 477 } 478 479 if (mUsesEqualMat2) 480 { 481 out << "bool equal(float2x2 m, float2x2 n)\n" 482 "{\n" 483 " return m[0][0] == n[0][0] && m[0][1] == n[0][1] &&\n" 484 " m[1][0] == n[1][0] && m[1][1] == n[1][1];\n" 485 "}\n"; 486 } 487 488 if (mUsesEqualMat3) 489 { 490 out << "bool equal(float3x3 m, float3x3 n)\n" 491 "{\n" 492 " return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] &&\n" 493 " m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] &&\n" 494 " m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2];\n" 495 "}\n"; 496 } 497 498 if (mUsesEqualMat4) 499 { 500 out << "bool equal(float4x4 m, float4x4 n)\n" 501 "{\n" 502 " return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] && m[0][3] == n[0][3] &&\n" 503 " m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] && m[1][3] == n[1][3] &&\n" 504 " m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2] && m[2][3] == n[2][3] &&\n" 505 " m[3][0] == n[3][0] && m[3][1] == n[3][1] && m[3][2] == n[3][2] && m[3][3] == n[3][3];\n" 506 "}\n"; 507 } 508 509 if (mUsesEqualVec2) 510 { 511 out << "bool equal(float2 v, float2 u)\n" 512 "{\n" 513 " return v.x == u.x && v.y == u.y;\n" 514 "}\n"; 515 } 516 517 if (mUsesEqualVec3) 518 { 519 out << "bool equal(float3 v, float3 u)\n" 520 "{\n" 521 " return v.x == u.x && v.y == u.y && v.z == u.z;\n" 522 "}\n"; 523 } 524 525 if (mUsesEqualVec4) 526 { 527 out << "bool equal(float4 v, float4 u)\n" 528 "{\n" 529 " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n" 530 "}\n"; 531 } 532 533 if (mUsesEqualIVec2) 534 { 535 out << "bool equal(int2 v, int2 u)\n" 536 "{\n" 537 " return v.x == u.x && v.y == u.y;\n" 538 "}\n"; 539 } 540 541 if (mUsesEqualIVec3) 542 { 543 out << "bool equal(int3 v, int3 u)\n" 544 "{\n" 545 " return v.x == u.x && v.y == u.y && v.z == u.z;\n" 546 "}\n"; 547 } 548 549 if (mUsesEqualIVec4) 550 { 551 out << "bool equal(int4 v, int4 u)\n" 552 "{\n" 553 " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n" 554 "}\n"; 555 } 556 557 if (mUsesEqualBVec2) 558 { 559 out << "bool equal(bool2 v, bool2 u)\n" 560 "{\n" 561 " return v.x == u.x && v.y == u.y;\n" 562 "}\n"; 563 } 564 565 if (mUsesEqualBVec3) 566 { 567 out << "bool equal(bool3 v, bool3 u)\n" 568 "{\n" 569 " return v.x == u.x && v.y == u.y && v.z == u.z;\n" 570 "}\n"; 571 } 572 573 if (mUsesEqualBVec4) 574 { 575 out << "bool equal(bool4 v, bool4 u)\n" 576 "{\n" 577 " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n" 578 "}\n"; 579 } 580 581 if (mUsesAtan2) 582 { 583 out << "float atanyx(float y, float x)\n" 584 "{\n" 585 " if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN 586 " return atan2(y, x);\n" 587 "}\n"; 588 } 589 } 590 591 void OutputHLSL::visitSymbol(TIntermSymbol *node) 592 { 593 TInfoSinkBase &out = mBody; 594 595 TString name = node->getSymbol(); 596 597 if (name == "gl_FragColor") 598 { 599 out << "gl_Color[0]"; 600 } 601 else if (name == "gl_FragData") 602 { 603 out << "gl_Color"; 604 } 605 else if (name == "gl_DepthRange") 606 { 607 mUsesDepthRange = true; 608 out << name; 609 } 610 else if (name == "gl_FragCoord") 611 { 612 mUsesFragCoord = true; 613 out << name; 614 } 615 else if (name == "gl_PointCoord") 616 { 617 mUsesPointCoord = true; 618 out << name; 619 } 620 else if (name == "gl_FrontFacing") 621 { 622 mUsesFrontFacing = true; 623 out << name; 624 } 625 else if (name == "gl_PointSize") 626 { 627 mUsesPointSize = true; 628 out << name; 629 } 630 else 631 { 632 TQualifier qualifier = node->getQualifier(); 633 634 if (qualifier == EvqUniform) 635 { 636 mReferencedUniforms.insert(name.c_str()); 637 } 638 else if (qualifier == EvqAttribute) 639 { 640 mReferencedAttributes.insert(name.c_str()); 641 } 642 else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut || qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn) 643 { 644 mReferencedVaryings.insert(name.c_str()); 645 } 646 647 out << decorate(name); 648 } 649 } 650 651 bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) 652 { 653 TInfoSinkBase &out = mBody; 654 655 switch (node->getOp()) 656 { 657 case EOpAssign: outputTriplet(visit, "(", " = ", ")"); break; 658 case EOpInitialize: 659 if (visit == PreVisit) 660 { 661 // GLSL allows to write things like "float x = x;" where a new variable x is defined 662 // and the value of an existing variable x is assigned. HLSL uses C semantics (the 663 // new variable is created before the assignment is evaluated), so we need to convert 664 // this to "float t = x, x = t;". 665 666 TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode(); 667 TIntermTyped *expression = node->getRight(); 668 669 sh::SearchSymbol searchSymbol(symbolNode->getSymbol()); 670 expression->traverse(&searchSymbol); 671 bool sameSymbol = searchSymbol.foundMatch(); 672 673 if (sameSymbol) 674 { 675 // Type already printed 676 out << "t" + str(mUniqueIndex) + " = "; 677 expression->traverse(this); 678 out << ", "; 679 symbolNode->traverse(this); 680 out << " = t" + str(mUniqueIndex); 681 682 mUniqueIndex++; 683 return false; 684 } 685 } 686 else if (visit == InVisit) 687 { 688 out << " = "; 689 } 690 break; 691 case EOpAddAssign: outputTriplet(visit, "(", " += ", ")"); break; 692 case EOpSubAssign: outputTriplet(visit, "(", " -= ", ")"); break; 693 case EOpMulAssign: outputTriplet(visit, "(", " *= ", ")"); break; 694 case EOpVectorTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break; 695 case EOpMatrixTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break; 696 case EOpVectorTimesMatrixAssign: 697 if (visit == PreVisit) 698 { 699 out << "("; 700 } 701 else if (visit == InVisit) 702 { 703 out << " = mul("; 704 node->getLeft()->traverse(this); 705 out << ", transpose("; 706 } 707 else 708 { 709 out << ")))"; 710 } 711 break; 712 case EOpMatrixTimesMatrixAssign: 713 if (visit == PreVisit) 714 { 715 out << "("; 716 } 717 else if (visit == InVisit) 718 { 719 out << " = mul("; 720 node->getLeft()->traverse(this); 721 out << ", "; 722 } 723 else 724 { 725 out << "))"; 726 } 727 break; 728 case EOpDivAssign: outputTriplet(visit, "(", " /= ", ")"); break; 729 case EOpIndexDirect: outputTriplet(visit, "", "[", "]"); break; 730 case EOpIndexIndirect: outputTriplet(visit, "", "[", "]"); break; 731 case EOpIndexDirectStruct: 732 if (visit == InVisit) 733 { 734 out << "." + node->getType().getFieldName(); 735 736 return false; 737 } 738 break; 739 case EOpVectorSwizzle: 740 if (visit == InVisit) 741 { 742 out << "."; 743 744 TIntermAggregate *swizzle = node->getRight()->getAsAggregate(); 745 746 if (swizzle) 747 { 748 TIntermSequence &sequence = swizzle->getSequence(); 749 750 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) 751 { 752 TIntermConstantUnion *element = (*sit)->getAsConstantUnion(); 753 754 if (element) 755 { 756 int i = element->getUnionArrayPointer()[0].getIConst(); 757 758 switch (i) 759 { 760 case 0: out << "x"; break; 761 case 1: out << "y"; break; 762 case 2: out << "z"; break; 763 case 3: out << "w"; break; 764 default: UNREACHABLE(); 765 } 766 } 767 else UNREACHABLE(); 768 } 769 } 770 else UNREACHABLE(); 771 772 return false; // Fully processed 773 } 774 break; 775 case EOpAdd: outputTriplet(visit, "(", " + ", ")"); break; 776 case EOpSub: outputTriplet(visit, "(", " - ", ")"); break; 777 case EOpMul: outputTriplet(visit, "(", " * ", ")"); break; 778 case EOpDiv: outputTriplet(visit, "(", " / ", ")"); break; 779 case EOpEqual: 780 case EOpNotEqual: 781 if (node->getLeft()->isScalar()) 782 { 783 if (node->getOp() == EOpEqual) 784 { 785 outputTriplet(visit, "(", " == ", ")"); 786 } 787 else 788 { 789 outputTriplet(visit, "(", " != ", ")"); 790 } 791 } 792 else if (node->getLeft()->getBasicType() == EbtStruct) 793 { 794 if (node->getOp() == EOpEqual) 795 { 796 out << "("; 797 } 798 else 799 { 800 out << "!("; 801 } 802 803 const TTypeList *fields = node->getLeft()->getType().getStruct(); 804 805 for (size_t i = 0; i < fields->size(); i++) 806 { 807 const TType *fieldType = (*fields)[i].type; 808 809 node->getLeft()->traverse(this); 810 out << "." + fieldType->getFieldName() + " == "; 811 node->getRight()->traverse(this); 812 out << "." + fieldType->getFieldName(); 813 814 if (i < fields->size() - 1) 815 { 816 out << " && "; 817 } 818 } 819 820 out << ")"; 821 822 return false; 823 } 824 else 825 { 826 if (node->getLeft()->isMatrix()) 827 { 828 switch (node->getLeft()->getNominalSize()) 829 { 830 case 2: mUsesEqualMat2 = true; break; 831 case 3: mUsesEqualMat3 = true; break; 832 case 4: mUsesEqualMat4 = true; break; 833 default: UNREACHABLE(); 834 } 835 } 836 else if (node->getLeft()->isVector()) 837 { 838 switch (node->getLeft()->getBasicType()) 839 { 840 case EbtFloat: 841 switch (node->getLeft()->getNominalSize()) 842 { 843 case 2: mUsesEqualVec2 = true; break; 844 case 3: mUsesEqualVec3 = true; break; 845 case 4: mUsesEqualVec4 = true; break; 846 default: UNREACHABLE(); 847 } 848 break; 849 case EbtInt: 850 switch (node->getLeft()->getNominalSize()) 851 { 852 case 2: mUsesEqualIVec2 = true; break; 853 case 3: mUsesEqualIVec3 = true; break; 854 case 4: mUsesEqualIVec4 = true; break; 855 default: UNREACHABLE(); 856 } 857 break; 858 case EbtBool: 859 switch (node->getLeft()->getNominalSize()) 860 { 861 case 2: mUsesEqualBVec2 = true; break; 862 case 3: mUsesEqualBVec3 = true; break; 863 case 4: mUsesEqualBVec4 = true; break; 864 default: UNREACHABLE(); 865 } 866 break; 867 default: UNREACHABLE(); 868 } 869 } 870 else UNREACHABLE(); 871 872 if (node->getOp() == EOpEqual) 873 { 874 outputTriplet(visit, "equal(", ", ", ")"); 875 } 876 else 877 { 878 outputTriplet(visit, "!equal(", ", ", ")"); 879 } 880 } 881 break; 882 case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; 883 case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break; 884 case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break; 885 case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break; 886 case EOpVectorTimesScalar: outputTriplet(visit, "(", " * ", ")"); break; 887 case EOpMatrixTimesScalar: outputTriplet(visit, "(", " * ", ")"); break; 888 case EOpVectorTimesMatrix: outputTriplet(visit, "mul(", ", transpose(", "))"); break; 889 case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break; 890 case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break; 891 case EOpLogicalOr: outputTriplet(visit, "(", " || ", ")"); break; 892 case EOpLogicalXor: 893 mUsesXor = true; 894 outputTriplet(visit, "xor(", ", ", ")"); 895 break; 896 case EOpLogicalAnd: outputTriplet(visit, "(", " && ", ")"); break; 897 default: UNREACHABLE(); 898 } 899 900 return true; 901 } 902 903 bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) 904 { 905 TInfoSinkBase &out = mBody; 906 907 switch (node->getOp()) 908 { 909 case EOpNegative: outputTriplet(visit, "(-", "", ")"); break; 910 case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break; 911 case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break; 912 case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break; 913 case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break; 914 case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break; 915 case EOpPreDecrement: outputTriplet(visit, "(--", "", ")"); break; 916 case EOpConvIntToBool: 917 case EOpConvFloatToBool: 918 switch (node->getOperand()->getType().getNominalSize()) 919 { 920 case 1: outputTriplet(visit, "bool(", "", ")"); break; 921 case 2: outputTriplet(visit, "bool2(", "", ")"); break; 922 case 3: outputTriplet(visit, "bool3(", "", ")"); break; 923 case 4: outputTriplet(visit, "bool4(", "", ")"); break; 924 default: UNREACHABLE(); 925 } 926 break; 927 case EOpConvBoolToFloat: 928 case EOpConvIntToFloat: 929 switch (node->getOperand()->getType().getNominalSize()) 930 { 931 case 1: outputTriplet(visit, "float(", "", ")"); break; 932 case 2: outputTriplet(visit, "float2(", "", ")"); break; 933 case 3: outputTriplet(visit, "float3(", "", ")"); break; 934 case 4: outputTriplet(visit, "float4(", "", ")"); break; 935 default: UNREACHABLE(); 936 } 937 break; 938 case EOpConvFloatToInt: 939 case EOpConvBoolToInt: 940 switch (node->getOperand()->getType().getNominalSize()) 941 { 942 case 1: outputTriplet(visit, "int(", "", ")"); break; 943 case 2: outputTriplet(visit, "int2(", "", ")"); break; 944 case 3: outputTriplet(visit, "int3(", "", ")"); break; 945 case 4: outputTriplet(visit, "int4(", "", ")"); break; 946 default: UNREACHABLE(); 947 } 948 break; 949 case EOpRadians: outputTriplet(visit, "radians(", "", ")"); break; 950 case EOpDegrees: outputTriplet(visit, "degrees(", "", ")"); break; 951 case EOpSin: outputTriplet(visit, "sin(", "", ")"); break; 952 case EOpCos: outputTriplet(visit, "cos(", "", ")"); break; 953 case EOpTan: outputTriplet(visit, "tan(", "", ")"); break; 954 case EOpAsin: outputTriplet(visit, "asin(", "", ")"); break; 955 case EOpAcos: outputTriplet(visit, "acos(", "", ")"); break; 956 case EOpAtan: outputTriplet(visit, "atan(", "", ")"); break; 957 case EOpExp: outputTriplet(visit, "exp(", "", ")"); break; 958 case EOpLog: outputTriplet(visit, "log(", "", ")"); break; 959 case EOpExp2: outputTriplet(visit, "exp2(", "", ")"); break; 960 case EOpLog2: outputTriplet(visit, "log2(", "", ")"); break; 961 case EOpSqrt: outputTriplet(visit, "sqrt(", "", ")"); break; 962 case EOpInverseSqrt: outputTriplet(visit, "rsqrt(", "", ")"); break; 963 case EOpAbs: outputTriplet(visit, "abs(", "", ")"); break; 964 case EOpSign: outputTriplet(visit, "sign(", "", ")"); break; 965 case EOpFloor: outputTriplet(visit, "floor(", "", ")"); break; 966 case EOpCeil: outputTriplet(visit, "ceil(", "", ")"); break; 967 case EOpFract: outputTriplet(visit, "frac(", "", ")"); break; 968 case EOpLength: outputTriplet(visit, "length(", "", ")"); break; 969 case EOpNormalize: outputTriplet(visit, "normalize(", "", ")"); break; 970 case EOpDFdx: outputTriplet(visit, "ddx(", "", ")"); break; 971 case EOpDFdy: outputTriplet(visit, "ddy(", "", ")"); break; 972 case EOpFwidth: outputTriplet(visit, "fwidth(", "", ")"); break; 973 case EOpAny: outputTriplet(visit, "any(", "", ")"); break; 974 case EOpAll: outputTriplet(visit, "all(", "", ")"); break; 975 default: UNREACHABLE(); 976 } 977 978 return true; 979 } 980 981 bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) 982 { 983 ShShaderType shaderType = mContext.shaderType; 984 TInfoSinkBase &out = mBody; 985 986 switch (node->getOp()) 987 { 988 case EOpSequence: 989 { 990 if (mInsideFunction) 991 { 992 out << "{\n"; 993 994 mScopeDepth++; 995 996 if (mScopeBracket.size() < mScopeDepth) 997 { 998 mScopeBracket.push_back(0); // New scope level 999 } 1000 else 1001 { 1002 mScopeBracket[mScopeDepth - 1]++; // New scope at existing level 1003 } 1004 } 1005 1006 for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++) 1007 { 1008 if (isSingleStatement(*sit)) 1009 { 1010 mUnfoldSelect->traverse(*sit); 1011 } 1012 1013 (*sit)->traverse(this); 1014 1015 out << ";\n"; 1016 } 1017 1018 if (mInsideFunction) 1019 { 1020 out << "}\n"; 1021 1022 mScopeDepth--; 1023 } 1024 1025 return false; 1026 } 1027 case EOpDeclaration: 1028 if (visit == PreVisit) 1029 { 1030 TIntermSequence &sequence = node->getSequence(); 1031 TIntermTyped *variable = sequence[0]->getAsTyped(); 1032 bool visit = true; 1033 1034 if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal)) 1035 { 1036 if (variable->getType().getStruct()) 1037 { 1038 addConstructor(variable->getType(), scopedStruct(variable->getType().getTypeName()), NULL); 1039 } 1040 1041 if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration 1042 { 1043 if (!mInsideFunction) 1044 { 1045 out << "static "; 1046 } 1047 1048 out << typeString(variable->getType()) + " "; 1049 1050 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) 1051 { 1052 TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); 1053 1054 if (symbol) 1055 { 1056 symbol->traverse(this); 1057 out << arrayString(symbol->getType()); 1058 out << " = " + initializer(variable->getType()); 1059 } 1060 else 1061 { 1062 (*sit)->traverse(this); 1063 } 1064 1065 if (visit && this->inVisit) 1066 { 1067 if (*sit != sequence.back()) 1068 { 1069 visit = this->visitAggregate(InVisit, node); 1070 } 1071 } 1072 } 1073 1074 if (visit && this->postVisit) 1075 { 1076 this->visitAggregate(PostVisit, node); 1077 } 1078 } 1079 else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration 1080 { 1081 // Already added to constructor map 1082 } 1083 else UNREACHABLE(); 1084 } 1085 1086 return false; 1087 } 1088 else if (visit == InVisit) 1089 { 1090 out << ", "; 1091 } 1092 break; 1093 case EOpPrototype: 1094 if (visit == PreVisit) 1095 { 1096 out << typeString(node->getType()) << " " << decorate(node->getName()) << "("; 1097 1098 TIntermSequence &arguments = node->getSequence(); 1099 1100 for (unsigned int i = 0; i < arguments.size(); i++) 1101 { 1102 TIntermSymbol *symbol = arguments[i]->getAsSymbolNode(); 1103 1104 if (symbol) 1105 { 1106 out << argumentString(symbol); 1107 1108 if (i < arguments.size() - 1) 1109 { 1110 out << ", "; 1111 } 1112 } 1113 else UNREACHABLE(); 1114 } 1115 1116 out << ");\n"; 1117 1118 return false; 1119 } 1120 break; 1121 case EOpComma: outputTriplet(visit, "", ", ", ""); break; 1122 case EOpFunction: 1123 { 1124 TString name = TFunction::unmangleName(node->getName()); 1125 1126 if (visit == PreVisit) 1127 { 1128 out << typeString(node->getType()) << " "; 1129 1130 if (name == "main") 1131 { 1132 out << "gl_main("; 1133 } 1134 else 1135 { 1136 out << decorate(name) << "("; 1137 } 1138 1139 TIntermSequence &sequence = node->getSequence(); 1140 TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence(); 1141 1142 for (unsigned int i = 0; i < arguments.size(); i++) 1143 { 1144 TIntermSymbol *symbol = arguments[i]->getAsSymbolNode(); 1145 1146 if (symbol) 1147 { 1148 out << argumentString(symbol); 1149 1150 if (i < arguments.size() - 1) 1151 { 1152 out << ", "; 1153 } 1154 } 1155 else UNREACHABLE(); 1156 } 1157 1158 sequence.erase(sequence.begin()); 1159 1160 out << ")\n" 1161 "{\n"; 1162 1163 mInsideFunction = true; 1164 } 1165 else if (visit == PostVisit) 1166 { 1167 out << "}\n"; 1168 1169 mInsideFunction = false; 1170 } 1171 } 1172 break; 1173 case EOpFunctionCall: 1174 { 1175 if (visit == PreVisit) 1176 { 1177 TString name = TFunction::unmangleName(node->getName()); 1178 1179 if (node->isUserDefined()) 1180 { 1181 out << decorate(name) << "("; 1182 } 1183 else 1184 { 1185 if (name == "texture2D") 1186 { 1187 if (node->getSequence().size() == 2) 1188 { 1189 mUsesTexture2D = true; 1190 } 1191 else if (node->getSequence().size() == 3) 1192 { 1193 mUsesTexture2D_bias = true; 1194 } 1195 else UNREACHABLE(); 1196 1197 out << "gl_texture2D("; 1198 } 1199 else if (name == "texture2DProj") 1200 { 1201 if (node->getSequence().size() == 2) 1202 { 1203 mUsesTexture2DProj = true; 1204 } 1205 else if (node->getSequence().size() == 3) 1206 { 1207 mUsesTexture2DProj_bias = true; 1208 } 1209 else UNREACHABLE(); 1210 1211 out << "gl_texture2DProj("; 1212 } 1213 else if (name == "textureCube") 1214 { 1215 if (node->getSequence().size() == 2) 1216 { 1217 mUsesTextureCube = true; 1218 } 1219 else if (node->getSequence().size() == 3) 1220 { 1221 mUsesTextureCube_bias = true; 1222 } 1223 else UNREACHABLE(); 1224 1225 out << "gl_textureCube("; 1226 } 1227 else if (name == "texture2DLod") 1228 { 1229 UNIMPLEMENTED(); // Requires the vertex shader texture sampling extension 1230 } 1231 else if (name == "texture2DProjLod") 1232 { 1233 UNIMPLEMENTED(); // Requires the vertex shader texture sampling extension 1234 } 1235 else if (name == "textureCubeLod") 1236 { 1237 UNIMPLEMENTED(); // Requires the vertex shader texture sampling extension 1238 } 1239 else UNREACHABLE(); 1240 } 1241 } 1242 else if (visit == InVisit) 1243 { 1244 out << ", "; 1245 } 1246 else 1247 { 1248 out << ")"; 1249 } 1250 } 1251 break; 1252 case EOpParameters: outputTriplet(visit, "(", ", ", ")\n{\n"); break; 1253 case EOpConstructFloat: 1254 addConstructor(node->getType(), "vec1", &node->getSequence()); 1255 outputTriplet(visit, "vec1(", "", ")"); 1256 break; 1257 case EOpConstructVec2: 1258 addConstructor(node->getType(), "vec2", &node->getSequence()); 1259 outputTriplet(visit, "vec2(", ", ", ")"); 1260 break; 1261 case EOpConstructVec3: 1262 addConstructor(node->getType(), "vec3", &node->getSequence()); 1263 outputTriplet(visit, "vec3(", ", ", ")"); 1264 break; 1265 case EOpConstructVec4: 1266 addConstructor(node->getType(), "vec4", &node->getSequence()); 1267 outputTriplet(visit, "vec4(", ", ", ")"); 1268 break; 1269 case EOpConstructBool: 1270 addConstructor(node->getType(), "bvec1", &node->getSequence()); 1271 outputTriplet(visit, "bvec1(", "", ")"); 1272 break; 1273 case EOpConstructBVec2: 1274 addConstructor(node->getType(), "bvec2", &node->getSequence()); 1275 outputTriplet(visit, "bvec2(", ", ", ")"); 1276 break; 1277 case EOpConstructBVec3: 1278 addConstructor(node->getType(), "bvec3", &node->getSequence()); 1279 outputTriplet(visit, "bvec3(", ", ", ")"); 1280 break; 1281 case EOpConstructBVec4: 1282 addConstructor(node->getType(), "bvec4", &node->getSequence()); 1283 outputTriplet(visit, "bvec4(", ", ", ")"); 1284 break; 1285 case EOpConstructInt: 1286 addConstructor(node->getType(), "ivec1", &node->getSequence()); 1287 outputTriplet(visit, "ivec1(", "", ")"); 1288 break; 1289 case EOpConstructIVec2: 1290 addConstructor(node->getType(), "ivec2", &node->getSequence()); 1291 outputTriplet(visit, "ivec2(", ", ", ")"); 1292 break; 1293 case EOpConstructIVec3: 1294 addConstructor(node->getType(), "ivec3", &node->getSequence()); 1295 outputTriplet(visit, "ivec3(", ", ", ")"); 1296 break; 1297 case EOpConstructIVec4: 1298 addConstructor(node->getType(), "ivec4", &node->getSequence()); 1299 outputTriplet(visit, "ivec4(", ", ", ")"); 1300 break; 1301 case EOpConstructMat2: 1302 addConstructor(node->getType(), "mat2", &node->getSequence()); 1303 outputTriplet(visit, "mat2(", ", ", ")"); 1304 break; 1305 case EOpConstructMat3: 1306 addConstructor(node->getType(), "mat3", &node->getSequence()); 1307 outputTriplet(visit, "mat3(", ", ", ")"); 1308 break; 1309 case EOpConstructMat4: 1310 addConstructor(node->getType(), "mat4", &node->getSequence()); 1311 outputTriplet(visit, "mat4(", ", ", ")"); 1312 break; 1313 case EOpConstructStruct: 1314 addConstructor(node->getType(), scopedStruct(node->getType().getTypeName()), &node->getSequence()); 1315 outputTriplet(visit, structLookup(node->getType().getTypeName()) + "_ctor(", ", ", ")"); 1316 break; 1317 case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; 1318 case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break; 1319 case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break; 1320 case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break; 1321 case EOpVectorEqual: outputTriplet(visit, "(", " == ", ")"); break; 1322 case EOpVectorNotEqual: outputTriplet(visit, "(", " != ", ")"); break; 1323 case EOpMod: 1324 { 1325 switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) // Number of components in the first argument 1326 { 1327 case 1: mUsesMod1 = true; break; 1328 case 2: mUsesMod2 = true; break; 1329 case 3: mUsesMod3 = true; break; 1330 case 4: mUsesMod4 = true; break; 1331 default: UNREACHABLE(); 1332 } 1333 1334 outputTriplet(visit, "mod(", ", ", ")"); 1335 } 1336 break; 1337 case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break; 1338 case EOpAtan: 1339 ASSERT(node->getSequence().size() == 2); // atan(x) is a unary operator 1340 mUsesAtan2 = true; 1341 outputTriplet(visit, "atanyx(", ", ", ")"); 1342 break; 1343 case EOpMin: outputTriplet(visit, "min(", ", ", ")"); break; 1344 case EOpMax: outputTriplet(visit, "max(", ", ", ")"); break; 1345 case EOpClamp: outputTriplet(visit, "clamp(", ", ", ")"); break; 1346 case EOpMix: outputTriplet(visit, "lerp(", ", ", ")"); break; 1347 case EOpStep: outputTriplet(visit, "step(", ", ", ")"); break; 1348 case EOpSmoothStep: outputTriplet(visit, "smoothstep(", ", ", ")"); break; 1349 case EOpDistance: outputTriplet(visit, "distance(", ", ", ")"); break; 1350 case EOpDot: outputTriplet(visit, "dot(", ", ", ")"); break; 1351 case EOpCross: outputTriplet(visit, "cross(", ", ", ")"); break; 1352 case EOpFaceForward: 1353 { 1354 switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) // Number of components in the first argument 1355 { 1356 case 1: mUsesFaceforward1 = true; break; 1357 case 2: mUsesFaceforward2 = true; break; 1358 case 3: mUsesFaceforward3 = true; break; 1359 case 4: mUsesFaceforward4 = true; break; 1360 default: UNREACHABLE(); 1361 } 1362 1363 outputTriplet(visit, "faceforward(", ", ", ")"); 1364 } 1365 break; 1366 case EOpReflect: outputTriplet(visit, "reflect(", ", ", ")"); break; 1367 case EOpRefract: outputTriplet(visit, "refract(", ", ", ")"); break; 1368 case EOpMul: outputTriplet(visit, "(", " * ", ")"); break; 1369 default: UNREACHABLE(); 1370 } 1371 1372 return true; 1373 } 1374 1375 bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) 1376 { 1377 TInfoSinkBase &out = mBody; 1378 1379 if (node->usesTernaryOperator()) 1380 { 1381 out << "t" << mUnfoldSelect->getTemporaryIndex(); 1382 } 1383 else // if/else statement 1384 { 1385 mUnfoldSelect->traverse(node->getCondition()); 1386 1387 out << "if("; 1388 1389 node->getCondition()->traverse(this); 1390 1391 out << ")\n" 1392 "{\n"; 1393 1394 if (node->getTrueBlock()) 1395 { 1396 node->getTrueBlock()->traverse(this); 1397 } 1398 1399 out << ";}\n"; 1400 1401 if (node->getFalseBlock()) 1402 { 1403 out << "else\n" 1404 "{\n"; 1405 1406 node->getFalseBlock()->traverse(this); 1407 1408 out << ";}\n"; 1409 } 1410 } 1411 1412 return false; 1413 } 1414 1415 void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node) 1416 { 1417 writeConstantUnion(node->getType(), node->getUnionArrayPointer()); 1418 } 1419 1420 bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) 1421 { 1422 if (handleExcessiveLoop(node)) 1423 { 1424 return false; 1425 } 1426 1427 TInfoSinkBase &out = mBody; 1428 1429 if (node->getType() == ELoopDoWhile) 1430 { 1431 out << "do\n" 1432 "{\n"; 1433 } 1434 else 1435 { 1436 if (node->getInit()) 1437 { 1438 mUnfoldSelect->traverse(node->getInit()); 1439 } 1440 1441 if (node->getCondition()) 1442 { 1443 mUnfoldSelect->traverse(node->getCondition()); 1444 } 1445 1446 if (node->getExpression()) 1447 { 1448 mUnfoldSelect->traverse(node->getExpression()); 1449 } 1450 1451 out << "for("; 1452 1453 if (node->getInit()) 1454 { 1455 node->getInit()->traverse(this); 1456 } 1457 1458 out << "; "; 1459 1460 if (node->getCondition()) 1461 { 1462 node->getCondition()->traverse(this); 1463 } 1464 1465 out << "; "; 1466 1467 if (node->getExpression()) 1468 { 1469 node->getExpression()->traverse(this); 1470 } 1471 1472 out << ")\n" 1473 "{\n"; 1474 } 1475 1476 if (node->getBody()) 1477 { 1478 node->getBody()->traverse(this); 1479 } 1480 1481 out << "}\n"; 1482 1483 if (node->getType() == ELoopDoWhile) 1484 { 1485 out << "while(\n"; 1486 1487 node->getCondition()->traverse(this); 1488 1489 out << ")"; 1490 } 1491 1492 out << ";\n"; 1493 1494 return false; 1495 } 1496 1497 bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node) 1498 { 1499 TInfoSinkBase &out = mBody; 1500 1501 switch (node->getFlowOp()) 1502 { 1503 case EOpKill: outputTriplet(visit, "discard", "", ""); break; 1504 case EOpBreak: outputTriplet(visit, "break", "", ""); break; 1505 case EOpContinue: outputTriplet(visit, "continue", "", ""); break; 1506 case EOpReturn: 1507 if (visit == PreVisit) 1508 { 1509 if (node->getExpression()) 1510 { 1511 out << "return "; 1512 } 1513 else 1514 { 1515 out << "return;\n"; 1516 } 1517 } 1518 else if (visit == PostVisit) 1519 { 1520 out << ";\n"; 1521 } 1522 break; 1523 default: UNREACHABLE(); 1524 } 1525 1526 return true; 1527 } 1528 1529 bool OutputHLSL::isSingleStatement(TIntermNode *node) 1530 { 1531 TIntermAggregate *aggregate = node->getAsAggregate(); 1532 1533 if (aggregate) 1534 { 1535 if (aggregate->getOp() == EOpSequence) 1536 { 1537 return false; 1538 } 1539 else 1540 { 1541 for (TIntermSequence::iterator sit = aggregate->getSequence().begin(); sit != aggregate->getSequence().end(); sit++) 1542 { 1543 if (!isSingleStatement(*sit)) 1544 { 1545 return false; 1546 } 1547 } 1548 1549 return true; 1550 } 1551 } 1552 1553 return true; 1554 } 1555 1556 // Handle loops with more than 255 iterations (unsupported by D3D9) by splitting them 1557 bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) 1558 { 1559 TInfoSinkBase &out = mBody; 1560 1561 // Parse loops of the form: 1562 // for(int index = initial; index [comparator] limit; index += increment) 1563 TIntermSymbol *index = NULL; 1564 TOperator comparator = EOpNull; 1565 int initial = 0; 1566 int limit = 0; 1567 int increment = 0; 1568 1569 // Parse index name and intial value 1570 if (node->getInit()) 1571 { 1572 TIntermAggregate *init = node->getInit()->getAsAggregate(); 1573 1574 if (init) 1575 { 1576 TIntermSequence &sequence = init->getSequence(); 1577 TIntermTyped *variable = sequence[0]->getAsTyped(); 1578 1579 if (variable && variable->getQualifier() == EvqTemporary) 1580 { 1581 TIntermBinary *assign = variable->getAsBinaryNode(); 1582 1583 if (assign->getOp() == EOpInitialize) 1584 { 1585 TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode(); 1586 TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion(); 1587 1588 if (symbol && constant) 1589 { 1590 if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) 1591 { 1592 index = symbol; 1593 initial = constant->getUnionArrayPointer()[0].getIConst(); 1594 } 1595 } 1596 } 1597 } 1598 } 1599 } 1600 1601 // Parse comparator and limit value 1602 if (index != NULL && node->getCondition()) 1603 { 1604 TIntermBinary *test = node->getCondition()->getAsBinaryNode(); 1605 1606 if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId()) 1607 { 1608 TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion(); 1609 1610 if (constant) 1611 { 1612 if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) 1613 { 1614 comparator = test->getOp(); 1615 limit = constant->getUnionArrayPointer()[0].getIConst(); 1616 } 1617 } 1618 } 1619 } 1620 1621 // Parse increment 1622 if (index != NULL && comparator != EOpNull && node->getExpression()) 1623 { 1624 TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode(); 1625 TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode(); 1626 1627 if (binaryTerminal) 1628 { 1629 TOperator op = binaryTerminal->getOp(); 1630 TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion(); 1631 1632 if (constant) 1633 { 1634 if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) 1635 { 1636 int value = constant->getUnionArrayPointer()[0].getIConst(); 1637 1638 switch (op) 1639 { 1640 case EOpAddAssign: increment = value; break; 1641 case EOpSubAssign: increment = -value; break; 1642 default: UNIMPLEMENTED(); 1643 } 1644 } 1645 } 1646 } 1647 else if (unaryTerminal) 1648 { 1649 TOperator op = unaryTerminal->getOp(); 1650 1651 switch (op) 1652 { 1653 case EOpPostIncrement: increment = 1; break; 1654 case EOpPostDecrement: increment = -1; break; 1655 case EOpPreIncrement: increment = 1; break; 1656 case EOpPreDecrement: increment = -1; break; 1657 default: UNIMPLEMENTED(); 1658 } 1659 } 1660 } 1661 1662 if (index != NULL && comparator != EOpNull && increment != 0) 1663 { 1664 if (comparator == EOpLessThanEqual) 1665 { 1666 comparator = EOpLessThan; 1667 limit += 1; 1668 } 1669 1670 if (comparator == EOpLessThan) 1671 { 1672 int iterations = (limit - initial + 1) / increment; 1673 1674 if (iterations <= 255) 1675 { 1676 return false; // Not an excessive loop 1677 } 1678 1679 while (iterations > 0) 1680 { 1681 int remainder = (limit - initial + 1) % increment; 1682 int clampedLimit = initial + increment * std::min(255, iterations) - 1 - remainder; 1683 1684 // for(int index = initial; index < clampedLimit; index += increment) 1685 1686 out << "for(int "; 1687 index->traverse(this); 1688 out << " = "; 1689 out << initial; 1690 1691 out << "; "; 1692 index->traverse(this); 1693 out << " < "; 1694 out << clampedLimit; 1695 1696 out << "; "; 1697 index->traverse(this); 1698 out << " += "; 1699 out << increment; 1700 out << ")\n" 1701 "{\n"; 1702 1703 if (node->getBody()) 1704 { 1705 node->getBody()->traverse(this); 1706 } 1707 1708 out << "}\n"; 1709 1710 initial += 255 * increment; 1711 iterations -= 255; 1712 } 1713 1714 return true; 1715 } 1716 else UNIMPLEMENTED(); 1717 } 1718 1719 return false; // Not handled as an excessive loop 1720 } 1721 1722 void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString) 1723 { 1724 TInfoSinkBase &out = mBody; 1725 1726 if (visit == PreVisit) 1727 { 1728 out << preString; 1729 } 1730 else if (visit == InVisit) 1731 { 1732 out << inString; 1733 } 1734 else if (visit == PostVisit) 1735 { 1736 out << postString; 1737 } 1738 } 1739 1740 TString OutputHLSL::argumentString(const TIntermSymbol *symbol) 1741 { 1742 TQualifier qualifier = symbol->getQualifier(); 1743 const TType &type = symbol->getType(); 1744 TString name = symbol->getSymbol(); 1745 1746 if (name.empty()) // HLSL demands named arguments, also for prototypes 1747 { 1748 name = "x" + str(mUniqueIndex++); 1749 } 1750 else 1751 { 1752 name = decorate(name); 1753 } 1754 1755 return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type); 1756 } 1757 1758 TString OutputHLSL::qualifierString(TQualifier qualifier) 1759 { 1760 switch(qualifier) 1761 { 1762 case EvqIn: return "in"; 1763 case EvqOut: return "out"; 1764 case EvqInOut: return "inout"; 1765 case EvqConstReadOnly: return "const"; 1766 default: UNREACHABLE(); 1767 } 1768 1769 return ""; 1770 } 1771 1772 TString OutputHLSL::typeString(const TType &type) 1773 { 1774 if (type.getBasicType() == EbtStruct) 1775 { 1776 if (type.getTypeName() != "") 1777 { 1778 return structLookup(type.getTypeName()); 1779 } 1780 else // Nameless structure, define in place 1781 { 1782 const TTypeList &fields = *type.getStruct(); 1783 1784 TString string = "struct\n" 1785 "{\n"; 1786 1787 for (unsigned int i = 0; i < fields.size(); i++) 1788 { 1789 const TType &field = *fields[i].type; 1790 1791 string += " " + typeString(field) + " " + field.getFieldName() + arrayString(field) + ";\n"; 1792 } 1793 1794 string += "} "; 1795 1796 return string; 1797 } 1798 } 1799 else if (type.isMatrix()) 1800 { 1801 switch (type.getNominalSize()) 1802 { 1803 case 2: return "float2x2"; 1804 case 3: return "float3x3"; 1805 case 4: return "float4x4"; 1806 } 1807 } 1808 else 1809 { 1810 switch (type.getBasicType()) 1811 { 1812 case EbtFloat: 1813 switch (type.getNominalSize()) 1814 { 1815 case 1: return "float"; 1816 case 2: return "float2"; 1817 case 3: return "float3"; 1818 case 4: return "float4"; 1819 } 1820 case EbtInt: 1821 switch (type.getNominalSize()) 1822 { 1823 case 1: return "int"; 1824 case 2: return "int2"; 1825 case 3: return "int3"; 1826 case 4: return "int4"; 1827 } 1828 case EbtBool: 1829 switch (type.getNominalSize()) 1830 { 1831 case 1: return "bool"; 1832 case 2: return "bool2"; 1833 case 3: return "bool3"; 1834 case 4: return "bool4"; 1835 } 1836 case EbtVoid: 1837 return "void"; 1838 case EbtSampler2D: 1839 return "sampler2D"; 1840 case EbtSamplerCube: 1841 return "samplerCUBE"; 1842 } 1843 } 1844 1845 UNIMPLEMENTED(); // FIXME 1846 return "<unknown type>"; 1847 } 1848 1849 TString OutputHLSL::arrayString(const TType &type) 1850 { 1851 if (!type.isArray()) 1852 { 1853 return ""; 1854 } 1855 1856 return "[" + str(type.getArraySize()) + "]"; 1857 } 1858 1859 TString OutputHLSL::initializer(const TType &type) 1860 { 1861 TString string; 1862 1863 for (int component = 0; component < type.getObjectSize(); component++) 1864 { 1865 string += "0"; 1866 1867 if (component < type.getObjectSize() - 1) 1868 { 1869 string += ", "; 1870 } 1871 } 1872 1873 return "{" + string + "}"; 1874 } 1875 1876 void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters) 1877 { 1878 if (name == "") 1879 { 1880 return; // Nameless structures don't have constructors 1881 } 1882 1883 TType ctorType = type; 1884 ctorType.clearArrayness(); 1885 ctorType.setPrecision(EbpHigh); 1886 ctorType.setQualifier(EvqTemporary); 1887 1888 TString ctorName = type.getStruct() ? decorate(name) : name; 1889 1890 typedef std::vector<TType> ParameterArray; 1891 ParameterArray ctorParameters; 1892 1893 if (parameters) 1894 { 1895 for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++) 1896 { 1897 ctorParameters.push_back((*parameter)->getAsTyped()->getType()); 1898 } 1899 } 1900 else if (type.getStruct()) 1901 { 1902 mStructNames.insert(decorate(name)); 1903 1904 TString structure; 1905 structure += "struct " + decorate(name) + "\n" 1906 "{\n"; 1907 1908 const TTypeList &fields = *type.getStruct(); 1909 1910 for (unsigned int i = 0; i < fields.size(); i++) 1911 { 1912 const TType &field = *fields[i].type; 1913 1914 structure += " " + typeString(field) + " " + field.getFieldName() + arrayString(field) + ";\n"; 1915 } 1916 1917 structure += "};\n"; 1918 1919 if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structure) == mStructDeclarations.end()) 1920 { 1921 mStructDeclarations.push_back(structure); 1922 } 1923 1924 for (unsigned int i = 0; i < fields.size(); i++) 1925 { 1926 ctorParameters.push_back(*fields[i].type); 1927 } 1928 } 1929 else UNREACHABLE(); 1930 1931 TString constructor; 1932 1933 if (ctorType.getStruct()) 1934 { 1935 constructor += ctorName + " " + ctorName + "_ctor("; 1936 } 1937 else // Built-in type 1938 { 1939 constructor += typeString(ctorType) + " " + ctorName + "("; 1940 } 1941 1942 for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++) 1943 { 1944 const TType &type = ctorParameters[parameter]; 1945 1946 constructor += typeString(type) + " x" + str(parameter) + arrayString(type); 1947 1948 if (parameter < ctorParameters.size() - 1) 1949 { 1950 constructor += ", "; 1951 } 1952 } 1953 1954 constructor += ")\n" 1955 "{\n"; 1956 1957 if (ctorType.getStruct()) 1958 { 1959 constructor += " " + ctorName + " structure = {"; 1960 } 1961 else 1962 { 1963 constructor += " return " + typeString(ctorType) + "("; 1964 } 1965 1966 if (ctorType.isMatrix() && ctorParameters.size() == 1) 1967 { 1968 int dim = ctorType.getNominalSize(); 1969 const TType ¶meter = ctorParameters[0]; 1970 1971 if (parameter.isScalar()) 1972 { 1973 for (int row = 0; row < dim; row++) 1974 { 1975 for (int col = 0; col < dim; col++) 1976 { 1977 constructor += TString((row == col) ? "x0" : "0.0"); 1978 1979 if (row < dim - 1 || col < dim - 1) 1980 { 1981 constructor += ", "; 1982 } 1983 } 1984 } 1985 } 1986 else if (parameter.isMatrix()) 1987 { 1988 for (int row = 0; row < dim; row++) 1989 { 1990 for (int col = 0; col < dim; col++) 1991 { 1992 if (row < parameter.getNominalSize() && col < parameter.getNominalSize()) 1993 { 1994 constructor += TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]"; 1995 } 1996 else 1997 { 1998 constructor += TString((row == col) ? "1.0" : "0.0"); 1999 } 2000 2001 if (row < dim - 1 || col < dim - 1) 2002 { 2003 constructor += ", "; 2004 } 2005 } 2006 } 2007 } 2008 else UNREACHABLE(); 2009 } 2010 else 2011 { 2012 int remainingComponents = ctorType.getObjectSize(); 2013 int parameterIndex = 0; 2014 2015 while (remainingComponents > 0) 2016 { 2017 const TType ¶meter = ctorParameters[parameterIndex]; 2018 bool moreParameters = parameterIndex < (int)ctorParameters.size() - 1; 2019 2020 constructor += "x" + str(parameterIndex); 2021 2022 if (parameter.isScalar()) 2023 { 2024 remainingComponents -= parameter.getObjectSize(); 2025 } 2026 else if (parameter.isVector()) 2027 { 2028 if (remainingComponents == parameter.getObjectSize() || moreParameters) 2029 { 2030 remainingComponents -= parameter.getObjectSize(); 2031 } 2032 else if (remainingComponents < parameter.getNominalSize()) 2033 { 2034 switch (remainingComponents) 2035 { 2036 case 1: constructor += ".x"; break; 2037 case 2: constructor += ".xy"; break; 2038 case 3: constructor += ".xyz"; break; 2039 case 4: constructor += ".xyzw"; break; 2040 default: UNREACHABLE(); 2041 } 2042 2043 remainingComponents = 0; 2044 } 2045 else UNREACHABLE(); 2046 } 2047 else if (parameter.isMatrix() || parameter.getStruct()) 2048 { 2049 ASSERT(remainingComponents == parameter.getObjectSize() || moreParameters); 2050 2051 remainingComponents -= parameter.getObjectSize(); 2052 } 2053 else UNREACHABLE(); 2054 2055 if (moreParameters) 2056 { 2057 parameterIndex++; 2058 } 2059 2060 if (remainingComponents) 2061 { 2062 constructor += ", "; 2063 } 2064 } 2065 } 2066 2067 if (ctorType.getStruct()) 2068 { 2069 constructor += "};\n" 2070 " return structure;\n" 2071 "}\n"; 2072 } 2073 else 2074 { 2075 constructor += ");\n" 2076 "}\n"; 2077 } 2078 2079 mConstructors.insert(constructor); 2080 } 2081 2082 const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion) 2083 { 2084 TInfoSinkBase &out = mBody; 2085 2086 if (type.getBasicType() == EbtStruct) 2087 { 2088 out << structLookup(type.getTypeName()) + "_ctor("; 2089 2090 const TTypeList *structure = type.getStruct(); 2091 2092 for (size_t i = 0; i < structure->size(); i++) 2093 { 2094 const TType *fieldType = (*structure)[i].type; 2095 2096 constUnion = writeConstantUnion(*fieldType, constUnion); 2097 2098 if (i != structure->size() - 1) 2099 { 2100 out << ", "; 2101 } 2102 } 2103 2104 out << ")"; 2105 } 2106 else 2107 { 2108 int size = type.getObjectSize(); 2109 bool writeType = size > 1; 2110 2111 if (writeType) 2112 { 2113 out << typeString(type) << "("; 2114 } 2115 2116 for (int i = 0; i < size; i++, constUnion++) 2117 { 2118 switch (constUnion->getType()) 2119 { 2120 case EbtFloat: out << constUnion->getFConst(); break; 2121 case EbtInt: out << constUnion->getIConst(); break; 2122 case EbtBool: out << constUnion->getBConst(); break; 2123 default: UNREACHABLE(); 2124 } 2125 2126 if (i != size - 1) 2127 { 2128 out << ", "; 2129 } 2130 } 2131 2132 if (writeType) 2133 { 2134 out << ")"; 2135 } 2136 } 2137 2138 return constUnion; 2139 } 2140 2141 TString OutputHLSL::scopeString(unsigned int depthLimit) 2142 { 2143 TString string; 2144 2145 for (unsigned int i = 0; i < mScopeBracket.size() && i < depthLimit; i++) 2146 { 2147 string += "_" + str(i); 2148 } 2149 2150 return string; 2151 } 2152 2153 TString OutputHLSL::scopedStruct(const TString &typeName) 2154 { 2155 if (typeName == "") 2156 { 2157 return typeName; 2158 } 2159 2160 return typeName + scopeString(mScopeDepth); 2161 } 2162 2163 TString OutputHLSL::structLookup(const TString &typeName) 2164 { 2165 for (int depth = mScopeDepth; depth >= 0; depth--) 2166 { 2167 TString scopedName = decorate(typeName + scopeString(depth)); 2168 2169 for (StructNames::iterator structName = mStructNames.begin(); structName != mStructNames.end(); structName++) 2170 { 2171 if (*structName == scopedName) 2172 { 2173 return scopedName; 2174 } 2175 } 2176 } 2177 2178 UNREACHABLE(); // Should have found a matching constructor 2179 2180 return typeName; 2181 } 2182 2183 TString OutputHLSL::decorate(const TString &string) 2184 { 2185 if (string.substr(0, 3) != "gl_" && string.substr(0, 3) != "dx_") 2186 { 2187 return "_" + string; 2188 } 2189 else 2190 { 2191 return string; 2192 } 2193 } 2194 } 2195