1 // 2 // Copyright (c) 2002-2013 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 "common/angleutils.h" 10 #include "compiler/debug.h" 11 #include "compiler/DetectDiscontinuity.h" 12 #include "compiler/InfoSink.h" 13 #include "compiler/SearchSymbol.h" 14 #include "compiler/UnfoldShortCircuit.h" 15 #include "compiler/NodeSearch.h" 16 17 #include <algorithm> 18 #include <cfloat> 19 #include <stdio.h> 20 21 namespace sh 22 { 23 // Integer to TString conversion 24 TString str(int i) 25 { 26 char buffer[20]; 27 snprintf(buffer, sizeof(buffer), "%d", i); 28 return buffer; 29 } 30 31 OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType) 32 : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType) 33 { 34 mUnfoldShortCircuit = new UnfoldShortCircuit(context, this); 35 mInsideFunction = false; 36 37 mUsesTexture2D = false; 38 mUsesTexture2D_bias = false; 39 mUsesTexture2DProj = false; 40 mUsesTexture2DProj_bias = false; 41 mUsesTexture2DProjLod = false; 42 mUsesTexture2DLod = false; 43 mUsesTextureCube = false; 44 mUsesTextureCube_bias = false; 45 mUsesTextureCubeLod = false; 46 mUsesTexture2DLod0 = false; 47 mUsesTexture2DLod0_bias = false; 48 mUsesTexture2DProjLod0 = false; 49 mUsesTexture2DProjLod0_bias = false; 50 mUsesTextureCubeLod0 = false; 51 mUsesTextureCubeLod0_bias = false; 52 mUsesFragColor = false; 53 mUsesFragData = false; 54 mUsesDepthRange = false; 55 mUsesFragCoord = false; 56 mUsesPointCoord = false; 57 mUsesFrontFacing = false; 58 mUsesPointSize = false; 59 mUsesFragDepth = false; 60 mUsesXor = false; 61 mUsesMod1 = false; 62 mUsesMod2v = false; 63 mUsesMod2f = false; 64 mUsesMod3v = false; 65 mUsesMod3f = false; 66 mUsesMod4v = false; 67 mUsesMod4f = false; 68 mUsesFaceforward1 = false; 69 mUsesFaceforward2 = false; 70 mUsesFaceforward3 = false; 71 mUsesFaceforward4 = false; 72 mUsesAtan2_1 = false; 73 mUsesAtan2_2 = false; 74 mUsesAtan2_3 = false; 75 mUsesAtan2_4 = false; 76 mUsesDiscardRewriting = false; 77 78 mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; 79 80 mScopeDepth = 0; 81 82 mUniqueIndex = 0; 83 84 mContainsLoopDiscontinuity = false; 85 mOutputLod0Function = false; 86 mInsideDiscontinuousLoop = false; 87 88 mExcessiveLoopIndex = NULL; 89 90 if (mOutputType == SH_HLSL9_OUTPUT) 91 { 92 if (mContext.shaderType == SH_FRAGMENT_SHADER) 93 { 94 mUniformRegister = 3; // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront 95 } 96 else 97 { 98 mUniformRegister = 2; // Reserve registers for dx_DepthRange and dx_ViewAdjust 99 } 100 } 101 else 102 { 103 mUniformRegister = 0; 104 } 105 106 mSamplerRegister = 0; 107 } 108 109 OutputHLSL::~OutputHLSL() 110 { 111 delete mUnfoldShortCircuit; 112 } 113 114 void OutputHLSL::output() 115 { 116 mContainsLoopDiscontinuity = mContext.shaderType == SH_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot); 117 118 mContext.treeRoot->traverse(this); // Output the body first to determine what has to go in the header 119 header(); 120 121 mContext.infoSink().obj << mHeader.c_str(); 122 mContext.infoSink().obj << mBody.c_str(); 123 } 124 125 TInfoSinkBase &OutputHLSL::getBodyStream() 126 { 127 return mBody; 128 } 129 130 const ActiveUniforms &OutputHLSL::getUniforms() 131 { 132 return mActiveUniforms; 133 } 134 135 int OutputHLSL::vectorSize(const TType &type) const 136 { 137 int elementSize = type.isMatrix() ? type.getNominalSize() : 1; 138 int arraySize = type.isArray() ? type.getArraySize() : 1; 139 140 return elementSize * arraySize; 141 } 142 143 void OutputHLSL::header() 144 { 145 ShShaderType shaderType = mContext.shaderType; 146 TInfoSinkBase &out = mHeader; 147 148 for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++) 149 { 150 out << *structDeclaration; 151 } 152 153 for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++) 154 { 155 out << *constructor; 156 } 157 158 TString uniforms; 159 TString varyings; 160 TString attributes; 161 162 for (ReferencedSymbols::const_iterator uniform = mReferencedUniforms.begin(); uniform != mReferencedUniforms.end(); uniform++) 163 { 164 const TType &type = uniform->second->getType(); 165 const TString &name = uniform->second->getSymbol(); 166 167 if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) // Also declare the texture 168 { 169 int index = samplerRegister(mReferencedUniforms[name]); 170 171 uniforms += "uniform SamplerState sampler_" + decorateUniform(name, type) + arrayString(type) + 172 " : register(s" + str(index) + ");\n"; 173 174 uniforms += "uniform " + textureString(type) + " texture_" + decorateUniform(name, type) + arrayString(type) + 175 " : register(t" + str(index) + ");\n"; 176 } 177 else 178 { 179 uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) + 180 " : register(" + registerString(mReferencedUniforms[name]) + ");\n"; 181 } 182 } 183 184 for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); varying != mReferencedVaryings.end(); varying++) 185 { 186 const TType &type = varying->second->getType(); 187 const TString &name = varying->second->getSymbol(); 188 189 // Program linking depends on this exact format 190 varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; 191 } 192 193 for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); attribute != mReferencedAttributes.end(); attribute++) 194 { 195 const TType &type = attribute->second->getType(); 196 const TString &name = attribute->second->getSymbol(); 197 198 attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; 199 } 200 201 if (mUsesDiscardRewriting) 202 { 203 out << "#define ANGLE_USES_DISCARD_REWRITING" << "\n"; 204 } 205 206 if (shaderType == SH_FRAGMENT_SHADER) 207 { 208 TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers"); 209 const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire)); 210 211 const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1; 212 213 out << "// Varyings\n"; 214 out << varyings; 215 out << "\n" 216 "static float4 gl_Color[" << numColorValues << "] =\n" 217 "{\n"; 218 for (unsigned int i = 0; i < numColorValues; i++) 219 { 220 out << " float4(0, 0, 0, 0)"; 221 if (i + 1 != numColorValues) 222 { 223 out << ","; 224 } 225 out << "\n"; 226 } 227 out << "};\n"; 228 229 if (mUsesFragDepth) 230 { 231 out << "static float gl_Depth = 0.0;\n"; 232 } 233 234 if (mUsesFragCoord) 235 { 236 out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n"; 237 } 238 239 if (mUsesPointCoord) 240 { 241 out << "static float2 gl_PointCoord = float2(0.5, 0.5);\n"; 242 } 243 244 if (mUsesFrontFacing) 245 { 246 out << "static bool gl_FrontFacing = false;\n"; 247 } 248 249 out << "\n"; 250 251 if (mUsesDepthRange) 252 { 253 out << "struct gl_DepthRangeParameters\n" 254 "{\n" 255 " float near;\n" 256 " float far;\n" 257 " float diff;\n" 258 "};\n" 259 "\n"; 260 } 261 262 if (mOutputType == SH_HLSL11_OUTPUT) 263 { 264 out << "cbuffer DriverConstants : register(b1)\n" 265 "{\n"; 266 267 if (mUsesDepthRange) 268 { 269 out << " float3 dx_DepthRange : packoffset(c0);\n"; 270 } 271 272 if (mUsesFragCoord) 273 { 274 out << " float4 dx_ViewCoords : packoffset(c1);\n"; 275 } 276 277 if (mUsesFragCoord || mUsesFrontFacing) 278 { 279 out << " float3 dx_DepthFront : packoffset(c2);\n"; 280 } 281 282 out << "};\n"; 283 } 284 else 285 { 286 if (mUsesDepthRange) 287 { 288 out << "uniform float3 dx_DepthRange : register(c0);"; 289 } 290 291 if (mUsesFragCoord) 292 { 293 out << "uniform float4 dx_ViewCoords : register(c1);\n"; 294 } 295 296 if (mUsesFragCoord || mUsesFrontFacing) 297 { 298 out << "uniform float3 dx_DepthFront : register(c2);\n"; 299 } 300 } 301 302 out << "\n"; 303 304 if (mUsesDepthRange) 305 { 306 out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" 307 "\n"; 308 } 309 310 out << uniforms; 311 out << "\n"; 312 313 if (mUsesTexture2D) 314 { 315 if (mOutputType == SH_HLSL9_OUTPUT) 316 { 317 out << "float4 gl_texture2D(sampler2D s, float2 t)\n" 318 "{\n" 319 " return tex2D(s, t);\n" 320 "}\n" 321 "\n"; 322 } 323 else if (mOutputType == SH_HLSL11_OUTPUT) 324 { 325 out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n" 326 "{\n" 327 " return t.Sample(s, uv);\n" 328 "}\n" 329 "\n"; 330 } 331 else UNREACHABLE(); 332 } 333 334 if (mUsesTexture2D_bias) 335 { 336 if (mOutputType == SH_HLSL9_OUTPUT) 337 { 338 out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n" 339 "{\n" 340 " return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n" 341 "}\n" 342 "\n"; 343 } 344 else if (mOutputType == SH_HLSL11_OUTPUT) 345 { 346 out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv, float bias)\n" 347 "{\n" 348 " return t.SampleBias(s, uv, bias);\n" 349 "}\n" 350 "\n"; 351 } 352 else UNREACHABLE(); 353 } 354 355 if (mUsesTexture2DProj) 356 { 357 if (mOutputType == SH_HLSL9_OUTPUT) 358 { 359 out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n" 360 "{\n" 361 " return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n" 362 "}\n" 363 "\n" 364 "float4 gl_texture2DProj(sampler2D s, float4 t)\n" 365 "{\n" 366 " return tex2Dproj(s, t);\n" 367 "}\n" 368 "\n"; 369 } 370 else if (mOutputType == SH_HLSL11_OUTPUT) 371 { 372 out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n" 373 "{\n" 374 " return t.Sample(s, float2(uvw.x / uvw.z, uvw.y / uvw.z));\n" 375 "}\n" 376 "\n" 377 "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n" 378 "{\n" 379 " return t.Sample(s, float2(uvw.x / uvw.w, uvw.y / uvw.w));\n" 380 "}\n" 381 "\n"; 382 } 383 else UNREACHABLE(); 384 } 385 386 if (mUsesTexture2DProj_bias) 387 { 388 if (mOutputType == SH_HLSL9_OUTPUT) 389 { 390 out << "float4 gl_texture2DProj(sampler2D s, float3 t, float bias)\n" 391 "{\n" 392 " return tex2Dbias(s, float4(t.x / t.z, t.y / t.z, 0, bias));\n" 393 "}\n" 394 "\n" 395 "float4 gl_texture2DProj(sampler2D s, float4 t, float bias)\n" 396 "{\n" 397 " return tex2Dbias(s, float4(t.x / t.w, t.y / t.w, 0, bias));\n" 398 "}\n" 399 "\n"; 400 } 401 else if (mOutputType == SH_HLSL11_OUTPUT) 402 { 403 out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw, float bias)\n" 404 "{\n" 405 " return t.SampleBias(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), bias);\n" 406 "}\n" 407 "\n" 408 "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw, float bias)\n" 409 "{\n" 410 " return t.SampleBias(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), bias);\n" 411 "}\n" 412 "\n"; 413 } 414 else UNREACHABLE(); 415 } 416 417 if (mUsesTextureCube) 418 { 419 if (mOutputType == SH_HLSL9_OUTPUT) 420 { 421 out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" 422 "{\n" 423 " return texCUBE(s, t);\n" 424 "}\n" 425 "\n"; 426 } 427 else if (mOutputType == SH_HLSL11_OUTPUT) 428 { 429 out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n" 430 "{\n" 431 " return t.Sample(s, uvw);\n" 432 "}\n" 433 "\n"; 434 } 435 else UNREACHABLE(); 436 } 437 438 if (mUsesTextureCube_bias) 439 { 440 if (mOutputType == SH_HLSL9_OUTPUT) 441 { 442 out << "float4 gl_textureCube(samplerCUBE s, float3 t, float bias)\n" 443 "{\n" 444 " return texCUBEbias(s, float4(t.x, t.y, t.z, bias));\n" 445 "}\n" 446 "\n"; 447 } 448 else if (mOutputType == SH_HLSL11_OUTPUT) 449 { 450 out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw, float bias)\n" 451 "{\n" 452 " return t.SampleBias(s, uvw, bias);\n" 453 "}\n" 454 "\n"; 455 } 456 else UNREACHABLE(); 457 } 458 459 // These *Lod0 intrinsics are not available in GL fragment shaders. 460 // They are used to sample using discontinuous texture coordinates. 461 if (mUsesTexture2DLod0) 462 { 463 if (mOutputType == SH_HLSL9_OUTPUT) 464 { 465 out << "float4 gl_texture2DLod0(sampler2D s, float2 t)\n" 466 "{\n" 467 " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" 468 "}\n" 469 "\n"; 470 } 471 else if (mOutputType == SH_HLSL11_OUTPUT) 472 { 473 out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv)\n" 474 "{\n" 475 " return t.SampleLevel(s, uv, 0);\n" 476 "}\n" 477 "\n"; 478 } 479 else UNREACHABLE(); 480 } 481 482 if (mUsesTexture2DLod0_bias) 483 { 484 if (mOutputType == SH_HLSL9_OUTPUT) 485 { 486 out << "float4 gl_texture2DLod0(sampler2D s, float2 t, float bias)\n" 487 "{\n" 488 " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" 489 "}\n" 490 "\n"; 491 } 492 else if (mOutputType == SH_HLSL11_OUTPUT) 493 { 494 out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv, float bias)\n" 495 "{\n" 496 " return t.SampleLevel(s, uv, 0);\n" 497 "}\n" 498 "\n"; 499 } 500 else UNREACHABLE(); 501 } 502 503 if (mUsesTexture2DProjLod0) 504 { 505 if (mOutputType == SH_HLSL9_OUTPUT) 506 { 507 out << "float4 gl_texture2DProjLod0(sampler2D s, float3 t)\n" 508 "{\n" 509 " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" 510 "}\n" 511 "\n" 512 "float4 gl_texture2DProjLod(sampler2D s, float4 t)\n" 513 "{\n" 514 " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" 515 "}\n" 516 "\n"; 517 } 518 else if (mOutputType == SH_HLSL11_OUTPUT) 519 { 520 out << "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float3 uvw)\n" 521 "{\n" 522 " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n" 523 "}\n" 524 "\n" 525 "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float4 uvw)\n" 526 "{\n" 527 " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n" 528 "}\n" 529 "\n"; 530 } 531 else UNREACHABLE(); 532 } 533 534 if (mUsesTexture2DProjLod0_bias) 535 { 536 if (mOutputType == SH_HLSL9_OUTPUT) 537 { 538 out << "float4 gl_texture2DProjLod0_bias(sampler2D s, float3 t, float bias)\n" 539 "{\n" 540 " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" 541 "}\n" 542 "\n" 543 "float4 gl_texture2DProjLod_bias(sampler2D s, float4 t, float bias)\n" 544 "{\n" 545 " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" 546 "}\n" 547 "\n"; 548 } 549 else if (mOutputType == SH_HLSL11_OUTPUT) 550 { 551 out << "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float3 uvw, float bias)\n" 552 "{\n" 553 " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n" 554 "}\n" 555 "\n" 556 "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float4 uvw, float bias)\n" 557 "{\n" 558 " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n" 559 "}\n" 560 "\n"; 561 } 562 else UNREACHABLE(); 563 } 564 565 if (mUsesTextureCubeLod0) 566 { 567 if (mOutputType == SH_HLSL9_OUTPUT) 568 { 569 out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t)\n" 570 "{\n" 571 " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" 572 "}\n" 573 "\n"; 574 } 575 else if (mOutputType == SH_HLSL11_OUTPUT) 576 { 577 out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw)\n" 578 "{\n" 579 " return t.SampleLevel(s, uvw, 0);\n" 580 "}\n" 581 "\n"; 582 } 583 else UNREACHABLE(); 584 } 585 586 if (mUsesTextureCubeLod0_bias) 587 { 588 if (mOutputType == SH_HLSL9_OUTPUT) 589 { 590 out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t, float bias)\n" 591 "{\n" 592 " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" 593 "}\n" 594 "\n"; 595 } 596 else if (mOutputType == SH_HLSL11_OUTPUT) 597 { 598 out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw, float bias)\n" 599 "{\n" 600 " return t.SampleLevel(s, uvw, 0);\n" 601 "}\n" 602 "\n"; 603 } 604 else UNREACHABLE(); 605 } 606 607 if (usingMRTExtension && mNumRenderTargets > 1) 608 { 609 out << "#define GL_USES_MRT\n"; 610 } 611 612 if (mUsesFragColor) 613 { 614 out << "#define GL_USES_FRAG_COLOR\n"; 615 } 616 617 if (mUsesFragData) 618 { 619 out << "#define GL_USES_FRAG_DATA\n"; 620 } 621 } 622 else // Vertex shader 623 { 624 out << "// Attributes\n"; 625 out << attributes; 626 out << "\n" 627 "static float4 gl_Position = float4(0, 0, 0, 0);\n"; 628 629 if (mUsesPointSize) 630 { 631 out << "static float gl_PointSize = float(1);\n"; 632 } 633 634 out << "\n" 635 "// Varyings\n"; 636 out << varyings; 637 out << "\n"; 638 639 if (mUsesDepthRange) 640 { 641 out << "struct gl_DepthRangeParameters\n" 642 "{\n" 643 " float near;\n" 644 " float far;\n" 645 " float diff;\n" 646 "};\n" 647 "\n"; 648 } 649 650 if (mOutputType == SH_HLSL11_OUTPUT) 651 { 652 if (mUsesDepthRange) 653 { 654 out << "cbuffer DriverConstants : register(b1)\n" 655 "{\n" 656 " float3 dx_DepthRange : packoffset(c0);\n" 657 "};\n" 658 "\n"; 659 } 660 } 661 else 662 { 663 if (mUsesDepthRange) 664 { 665 out << "uniform float3 dx_DepthRange : register(c0);\n"; 666 } 667 668 out << "uniform float4 dx_ViewAdjust : register(c1);\n" 669 "\n"; 670 } 671 672 if (mUsesDepthRange) 673 { 674 out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" 675 "\n"; 676 } 677 678 out << uniforms; 679 out << "\n"; 680 681 if (mUsesTexture2D) 682 { 683 if (mOutputType == SH_HLSL9_OUTPUT) 684 { 685 out << "float4 gl_texture2D(sampler2D s, float2 t)\n" 686 "{\n" 687 " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" 688 "}\n" 689 "\n"; 690 } 691 else if (mOutputType == SH_HLSL11_OUTPUT) 692 { 693 out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n" 694 "{\n" 695 " return t.SampleLevel(s, uv, 0);\n" 696 "}\n" 697 "\n"; 698 } 699 else UNREACHABLE(); 700 } 701 702 if (mUsesTexture2DLod) 703 { 704 if (mOutputType == SH_HLSL9_OUTPUT) 705 { 706 out << "float4 gl_texture2DLod(sampler2D s, float2 t, float lod)\n" 707 "{\n" 708 " return tex2Dlod(s, float4(t.x, t.y, 0, lod));\n" 709 "}\n" 710 "\n"; 711 } 712 else if (mOutputType == SH_HLSL11_OUTPUT) 713 { 714 out << "float4 gl_texture2DLod(Texture2D t, SamplerState s, float2 uv, float lod)\n" 715 "{\n" 716 " return t.SampleLevel(s, uv, lod);\n" 717 "}\n" 718 "\n"; 719 } 720 else UNREACHABLE(); 721 } 722 723 if (mUsesTexture2DProj) 724 { 725 if (mOutputType == SH_HLSL9_OUTPUT) 726 { 727 out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n" 728 "{\n" 729 " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" 730 "}\n" 731 "\n" 732 "float4 gl_texture2DProj(sampler2D s, float4 t)\n" 733 "{\n" 734 " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" 735 "}\n" 736 "\n"; 737 } 738 else if (mOutputType == SH_HLSL11_OUTPUT) 739 { 740 out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n" 741 "{\n" 742 " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n" 743 "}\n" 744 "\n" 745 "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n" 746 "{\n" 747 " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n" 748 "}\n" 749 "\n"; 750 } 751 else UNREACHABLE(); 752 } 753 754 if (mUsesTexture2DProjLod) 755 { 756 if (mOutputType == SH_HLSL9_OUTPUT) 757 { 758 out << "float4 gl_texture2DProjLod(sampler2D s, float3 t, float lod)\n" 759 "{\n" 760 " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, lod));\n" 761 "}\n" 762 "\n" 763 "float4 gl_texture2DProjLod(sampler2D s, float4 t, float lod)\n" 764 "{\n" 765 " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, lod));\n" 766 "}\n" 767 "\n"; 768 } 769 else if (mOutputType == SH_HLSL11_OUTPUT) 770 { 771 out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw, float lod)\n" 772 "{\n" 773 " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), lod);\n" 774 "}\n" 775 "\n" 776 "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n" 777 "{\n" 778 " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), lod);\n" 779 "}\n" 780 "\n"; 781 } 782 else UNREACHABLE(); 783 } 784 785 if (mUsesTextureCube) 786 { 787 if (mOutputType == SH_HLSL9_OUTPUT) 788 { 789 out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" 790 "{\n" 791 " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" 792 "}\n" 793 "\n"; 794 } 795 else if (mOutputType == SH_HLSL11_OUTPUT) 796 { 797 out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n" 798 "{\n" 799 " return t.SampleLevel(s, uvw, 0);\n" 800 "}\n" 801 "\n"; 802 } 803 else UNREACHABLE(); 804 } 805 806 if (mUsesTextureCubeLod) 807 { 808 if (mOutputType == SH_HLSL9_OUTPUT) 809 { 810 out << "float4 gl_textureCubeLod(samplerCUBE s, float3 t, float lod)\n" 811 "{\n" 812 " return texCUBElod(s, float4(t.x, t.y, t.z, lod));\n" 813 "}\n" 814 "\n"; 815 } 816 else if (mOutputType == SH_HLSL11_OUTPUT) 817 { 818 out << "float4 gl_textureCubeLod(TextureCube t, SamplerState s, float3 uvw, float lod)\n" 819 "{\n" 820 " return t.SampleLevel(s, uvw, lod);\n" 821 "}\n" 822 "\n"; 823 } 824 else UNREACHABLE(); 825 } 826 } 827 828 if (mUsesFragCoord) 829 { 830 out << "#define GL_USES_FRAG_COORD\n"; 831 } 832 833 if (mUsesPointCoord) 834 { 835 out << "#define GL_USES_POINT_COORD\n"; 836 } 837 838 if (mUsesFrontFacing) 839 { 840 out << "#define GL_USES_FRONT_FACING\n"; 841 } 842 843 if (mUsesPointSize) 844 { 845 out << "#define GL_USES_POINT_SIZE\n"; 846 } 847 848 if (mUsesFragDepth) 849 { 850 out << "#define GL_USES_FRAG_DEPTH\n"; 851 } 852 853 if (mUsesDepthRange) 854 { 855 out << "#define GL_USES_DEPTH_RANGE\n"; 856 } 857 858 if (mUsesXor) 859 { 860 out << "bool xor(bool p, bool q)\n" 861 "{\n" 862 " return (p || q) && !(p && q);\n" 863 "}\n" 864 "\n"; 865 } 866 867 if (mUsesMod1) 868 { 869 out << "float mod(float x, float y)\n" 870 "{\n" 871 " return x - y * floor(x / y);\n" 872 "}\n" 873 "\n"; 874 } 875 876 if (mUsesMod2v) 877 { 878 out << "float2 mod(float2 x, float2 y)\n" 879 "{\n" 880 " return x - y * floor(x / y);\n" 881 "}\n" 882 "\n"; 883 } 884 885 if (mUsesMod2f) 886 { 887 out << "float2 mod(float2 x, float y)\n" 888 "{\n" 889 " return x - y * floor(x / y);\n" 890 "}\n" 891 "\n"; 892 } 893 894 if (mUsesMod3v) 895 { 896 out << "float3 mod(float3 x, float3 y)\n" 897 "{\n" 898 " return x - y * floor(x / y);\n" 899 "}\n" 900 "\n"; 901 } 902 903 if (mUsesMod3f) 904 { 905 out << "float3 mod(float3 x, float y)\n" 906 "{\n" 907 " return x - y * floor(x / y);\n" 908 "}\n" 909 "\n"; 910 } 911 912 if (mUsesMod4v) 913 { 914 out << "float4 mod(float4 x, float4 y)\n" 915 "{\n" 916 " return x - y * floor(x / y);\n" 917 "}\n" 918 "\n"; 919 } 920 921 if (mUsesMod4f) 922 { 923 out << "float4 mod(float4 x, float y)\n" 924 "{\n" 925 " return x - y * floor(x / y);\n" 926 "}\n" 927 "\n"; 928 } 929 930 if (mUsesFaceforward1) 931 { 932 out << "float faceforward(float N, float I, float Nref)\n" 933 "{\n" 934 " if(dot(Nref, I) >= 0)\n" 935 " {\n" 936 " return -N;\n" 937 " }\n" 938 " else\n" 939 " {\n" 940 " return N;\n" 941 " }\n" 942 "}\n" 943 "\n"; 944 } 945 946 if (mUsesFaceforward2) 947 { 948 out << "float2 faceforward(float2 N, float2 I, float2 Nref)\n" 949 "{\n" 950 " if(dot(Nref, I) >= 0)\n" 951 " {\n" 952 " return -N;\n" 953 " }\n" 954 " else\n" 955 " {\n" 956 " return N;\n" 957 " }\n" 958 "}\n" 959 "\n"; 960 } 961 962 if (mUsesFaceforward3) 963 { 964 out << "float3 faceforward(float3 N, float3 I, float3 Nref)\n" 965 "{\n" 966 " if(dot(Nref, I) >= 0)\n" 967 " {\n" 968 " return -N;\n" 969 " }\n" 970 " else\n" 971 " {\n" 972 " return N;\n" 973 " }\n" 974 "}\n" 975 "\n"; 976 } 977 978 if (mUsesFaceforward4) 979 { 980 out << "float4 faceforward(float4 N, float4 I, float4 Nref)\n" 981 "{\n" 982 " if(dot(Nref, I) >= 0)\n" 983 " {\n" 984 " return -N;\n" 985 " }\n" 986 " else\n" 987 " {\n" 988 " return N;\n" 989 " }\n" 990 "}\n" 991 "\n"; 992 } 993 994 if (mUsesAtan2_1) 995 { 996 out << "float atanyx(float y, float x)\n" 997 "{\n" 998 " if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN 999 " return atan2(y, x);\n" 1000 "}\n"; 1001 } 1002 1003 if (mUsesAtan2_2) 1004 { 1005 out << "float2 atanyx(float2 y, float2 x)\n" 1006 "{\n" 1007 " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" 1008 " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" 1009 " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n" 1010 "}\n"; 1011 } 1012 1013 if (mUsesAtan2_3) 1014 { 1015 out << "float3 atanyx(float3 y, float3 x)\n" 1016 "{\n" 1017 " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" 1018 " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" 1019 " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" 1020 " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n" 1021 "}\n"; 1022 } 1023 1024 if (mUsesAtan2_4) 1025 { 1026 out << "float4 atanyx(float4 y, float4 x)\n" 1027 "{\n" 1028 " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" 1029 " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" 1030 " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" 1031 " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n" 1032 " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n" 1033 "}\n"; 1034 } 1035 } 1036 1037 void OutputHLSL::visitSymbol(TIntermSymbol *node) 1038 { 1039 TInfoSinkBase &out = mBody; 1040 1041 TString name = node->getSymbol(); 1042 1043 if (name == "gl_FragColor") 1044 { 1045 out << "gl_Color[0]"; 1046 mUsesFragColor = true; 1047 } 1048 else if (name == "gl_FragData") 1049 { 1050 out << "gl_Color"; 1051 mUsesFragData = true; 1052 } 1053 else if (name == "gl_DepthRange") 1054 { 1055 mUsesDepthRange = true; 1056 out << name; 1057 } 1058 else if (name == "gl_FragCoord") 1059 { 1060 mUsesFragCoord = true; 1061 out << name; 1062 } 1063 else if (name == "gl_PointCoord") 1064 { 1065 mUsesPointCoord = true; 1066 out << name; 1067 } 1068 else if (name == "gl_FrontFacing") 1069 { 1070 mUsesFrontFacing = true; 1071 out << name; 1072 } 1073 else if (name == "gl_PointSize") 1074 { 1075 mUsesPointSize = true; 1076 out << name; 1077 } 1078 else if (name == "gl_FragDepthEXT") 1079 { 1080 mUsesFragDepth = true; 1081 out << "gl_Depth"; 1082 } 1083 else 1084 { 1085 TQualifier qualifier = node->getQualifier(); 1086 1087 if (qualifier == EvqUniform) 1088 { 1089 mReferencedUniforms[name] = node; 1090 out << decorateUniform(name, node->getType()); 1091 } 1092 else if (qualifier == EvqAttribute) 1093 { 1094 mReferencedAttributes[name] = node; 1095 out << decorate(name); 1096 } 1097 else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut || qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn) 1098 { 1099 mReferencedVaryings[name] = node; 1100 out << decorate(name); 1101 } 1102 else 1103 { 1104 out << decorate(name); 1105 } 1106 } 1107 } 1108 1109 bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) 1110 { 1111 TInfoSinkBase &out = mBody; 1112 1113 switch (node->getOp()) 1114 { 1115 case EOpAssign: outputTriplet(visit, "(", " = ", ")"); break; 1116 case EOpInitialize: 1117 if (visit == PreVisit) 1118 { 1119 // GLSL allows to write things like "float x = x;" where a new variable x is defined 1120 // and the value of an existing variable x is assigned. HLSL uses C semantics (the 1121 // new variable is created before the assignment is evaluated), so we need to convert 1122 // this to "float t = x, x = t;". 1123 1124 TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode(); 1125 TIntermTyped *expression = node->getRight(); 1126 1127 sh::SearchSymbol searchSymbol(symbolNode->getSymbol()); 1128 expression->traverse(&searchSymbol); 1129 bool sameSymbol = searchSymbol.foundMatch(); 1130 1131 if (sameSymbol) 1132 { 1133 // Type already printed 1134 out << "t" + str(mUniqueIndex) + " = "; 1135 expression->traverse(this); 1136 out << ", "; 1137 symbolNode->traverse(this); 1138 out << " = t" + str(mUniqueIndex); 1139 1140 mUniqueIndex++; 1141 return false; 1142 } 1143 } 1144 else if (visit == InVisit) 1145 { 1146 out << " = "; 1147 } 1148 break; 1149 case EOpAddAssign: outputTriplet(visit, "(", " += ", ")"); break; 1150 case EOpSubAssign: outputTriplet(visit, "(", " -= ", ")"); break; 1151 case EOpMulAssign: outputTriplet(visit, "(", " *= ", ")"); break; 1152 case EOpVectorTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break; 1153 case EOpMatrixTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break; 1154 case EOpVectorTimesMatrixAssign: 1155 if (visit == PreVisit) 1156 { 1157 out << "("; 1158 } 1159 else if (visit == InVisit) 1160 { 1161 out << " = mul("; 1162 node->getLeft()->traverse(this); 1163 out << ", transpose("; 1164 } 1165 else 1166 { 1167 out << ")))"; 1168 } 1169 break; 1170 case EOpMatrixTimesMatrixAssign: 1171 if (visit == PreVisit) 1172 { 1173 out << "("; 1174 } 1175 else if (visit == InVisit) 1176 { 1177 out << " = mul("; 1178 node->getLeft()->traverse(this); 1179 out << ", "; 1180 } 1181 else 1182 { 1183 out << "))"; 1184 } 1185 break; 1186 case EOpDivAssign: outputTriplet(visit, "(", " /= ", ")"); break; 1187 case EOpIndexDirect: outputTriplet(visit, "", "[", "]"); break; 1188 case EOpIndexIndirect: outputTriplet(visit, "", "[", "]"); break; 1189 case EOpIndexDirectStruct: 1190 if (visit == InVisit) 1191 { 1192 const TStructure* structure = node->getLeft()->getType().getStruct(); 1193 const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion(); 1194 const TField* field = structure->fields()[index->getIConst(0)]; 1195 out << "." + decorateField(field->name(), node->getLeft()->getType()); 1196 1197 return false; 1198 } 1199 break; 1200 case EOpVectorSwizzle: 1201 if (visit == InVisit) 1202 { 1203 out << "."; 1204 1205 TIntermAggregate *swizzle = node->getRight()->getAsAggregate(); 1206 1207 if (swizzle) 1208 { 1209 TIntermSequence &sequence = swizzle->getSequence(); 1210 1211 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) 1212 { 1213 TIntermConstantUnion *element = (*sit)->getAsConstantUnion(); 1214 1215 if (element) 1216 { 1217 int i = element->getIConst(0); 1218 1219 switch (i) 1220 { 1221 case 0: out << "x"; break; 1222 case 1: out << "y"; break; 1223 case 2: out << "z"; break; 1224 case 3: out << "w"; break; 1225 default: UNREACHABLE(); 1226 } 1227 } 1228 else UNREACHABLE(); 1229 } 1230 } 1231 else UNREACHABLE(); 1232 1233 return false; // Fully processed 1234 } 1235 break; 1236 case EOpAdd: outputTriplet(visit, "(", " + ", ")"); break; 1237 case EOpSub: outputTriplet(visit, "(", " - ", ")"); break; 1238 case EOpMul: outputTriplet(visit, "(", " * ", ")"); break; 1239 case EOpDiv: outputTriplet(visit, "(", " / ", ")"); break; 1240 case EOpEqual: 1241 case EOpNotEqual: 1242 if (node->getLeft()->isScalar()) 1243 { 1244 if (node->getOp() == EOpEqual) 1245 { 1246 outputTriplet(visit, "(", " == ", ")"); 1247 } 1248 else 1249 { 1250 outputTriplet(visit, "(", " != ", ")"); 1251 } 1252 } 1253 else if (node->getLeft()->getBasicType() == EbtStruct) 1254 { 1255 if (node->getOp() == EOpEqual) 1256 { 1257 out << "("; 1258 } 1259 else 1260 { 1261 out << "!("; 1262 } 1263 1264 const TFieldList &fields = node->getLeft()->getType().getStruct()->fields(); 1265 1266 for (size_t i = 0; i < fields.size(); i++) 1267 { 1268 const TField *field = fields[i]; 1269 1270 node->getLeft()->traverse(this); 1271 out << "." + decorateField(field->name(), node->getLeft()->getType()) + " == "; 1272 node->getRight()->traverse(this); 1273 out << "." + decorateField(field->name(), node->getLeft()->getType()); 1274 1275 if (i < fields.size() - 1) 1276 { 1277 out << " && "; 1278 } 1279 } 1280 1281 out << ")"; 1282 1283 return false; 1284 } 1285 else 1286 { 1287 ASSERT(node->getLeft()->isMatrix() || node->getLeft()->isVector()); 1288 1289 if (node->getOp() == EOpEqual) 1290 { 1291 outputTriplet(visit, "all(", " == ", ")"); 1292 } 1293 else 1294 { 1295 outputTriplet(visit, "!all(", " == ", ")"); 1296 } 1297 } 1298 break; 1299 case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; 1300 case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break; 1301 case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break; 1302 case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break; 1303 case EOpVectorTimesScalar: outputTriplet(visit, "(", " * ", ")"); break; 1304 case EOpMatrixTimesScalar: outputTriplet(visit, "(", " * ", ")"); break; 1305 case EOpVectorTimesMatrix: outputTriplet(visit, "mul(", ", transpose(", "))"); break; 1306 case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break; 1307 case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break; 1308 case EOpLogicalOr: 1309 if (node->getRight()->hasSideEffects()) 1310 { 1311 out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex(); 1312 return false; 1313 } 1314 else 1315 { 1316 outputTriplet(visit, "(", " || ", ")"); 1317 return true; 1318 } 1319 case EOpLogicalXor: 1320 mUsesXor = true; 1321 outputTriplet(visit, "xor(", ", ", ")"); 1322 break; 1323 case EOpLogicalAnd: 1324 if (node->getRight()->hasSideEffects()) 1325 { 1326 out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex(); 1327 return false; 1328 } 1329 else 1330 { 1331 outputTriplet(visit, "(", " && ", ")"); 1332 return true; 1333 } 1334 default: UNREACHABLE(); 1335 } 1336 1337 return true; 1338 } 1339 1340 bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) 1341 { 1342 switch (node->getOp()) 1343 { 1344 case EOpNegative: outputTriplet(visit, "(-", "", ")"); break; 1345 case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break; 1346 case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break; 1347 case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break; 1348 case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break; 1349 case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break; 1350 case EOpPreDecrement: outputTriplet(visit, "(--", "", ")"); break; 1351 case EOpConvIntToBool: 1352 case EOpConvFloatToBool: 1353 switch (node->getOperand()->getType().getNominalSize()) 1354 { 1355 case 1: outputTriplet(visit, "bool(", "", ")"); break; 1356 case 2: outputTriplet(visit, "bool2(", "", ")"); break; 1357 case 3: outputTriplet(visit, "bool3(", "", ")"); break; 1358 case 4: outputTriplet(visit, "bool4(", "", ")"); break; 1359 default: UNREACHABLE(); 1360 } 1361 break; 1362 case EOpConvBoolToFloat: 1363 case EOpConvIntToFloat: 1364 switch (node->getOperand()->getType().getNominalSize()) 1365 { 1366 case 1: outputTriplet(visit, "float(", "", ")"); break; 1367 case 2: outputTriplet(visit, "float2(", "", ")"); break; 1368 case 3: outputTriplet(visit, "float3(", "", ")"); break; 1369 case 4: outputTriplet(visit, "float4(", "", ")"); break; 1370 default: UNREACHABLE(); 1371 } 1372 break; 1373 case EOpConvFloatToInt: 1374 case EOpConvBoolToInt: 1375 switch (node->getOperand()->getType().getNominalSize()) 1376 { 1377 case 1: outputTriplet(visit, "int(", "", ")"); break; 1378 case 2: outputTriplet(visit, "int2(", "", ")"); break; 1379 case 3: outputTriplet(visit, "int3(", "", ")"); break; 1380 case 4: outputTriplet(visit, "int4(", "", ")"); break; 1381 default: UNREACHABLE(); 1382 } 1383 break; 1384 case EOpRadians: outputTriplet(visit, "radians(", "", ")"); break; 1385 case EOpDegrees: outputTriplet(visit, "degrees(", "", ")"); break; 1386 case EOpSin: outputTriplet(visit, "sin(", "", ")"); break; 1387 case EOpCos: outputTriplet(visit, "cos(", "", ")"); break; 1388 case EOpTan: outputTriplet(visit, "tan(", "", ")"); break; 1389 case EOpAsin: outputTriplet(visit, "asin(", "", ")"); break; 1390 case EOpAcos: outputTriplet(visit, "acos(", "", ")"); break; 1391 case EOpAtan: outputTriplet(visit, "atan(", "", ")"); break; 1392 case EOpExp: outputTriplet(visit, "exp(", "", ")"); break; 1393 case EOpLog: outputTriplet(visit, "log(", "", ")"); break; 1394 case EOpExp2: outputTriplet(visit, "exp2(", "", ")"); break; 1395 case EOpLog2: outputTriplet(visit, "log2(", "", ")"); break; 1396 case EOpSqrt: outputTriplet(visit, "sqrt(", "", ")"); break; 1397 case EOpInverseSqrt: outputTriplet(visit, "rsqrt(", "", ")"); break; 1398 case EOpAbs: outputTriplet(visit, "abs(", "", ")"); break; 1399 case EOpSign: outputTriplet(visit, "sign(", "", ")"); break; 1400 case EOpFloor: outputTriplet(visit, "floor(", "", ")"); break; 1401 case EOpCeil: outputTriplet(visit, "ceil(", "", ")"); break; 1402 case EOpFract: outputTriplet(visit, "frac(", "", ")"); break; 1403 case EOpLength: outputTriplet(visit, "length(", "", ")"); break; 1404 case EOpNormalize: outputTriplet(visit, "normalize(", "", ")"); break; 1405 case EOpDFdx: 1406 if(mInsideDiscontinuousLoop || mOutputLod0Function) 1407 { 1408 outputTriplet(visit, "(", "", ", 0.0)"); 1409 } 1410 else 1411 { 1412 outputTriplet(visit, "ddx(", "", ")"); 1413 } 1414 break; 1415 case EOpDFdy: 1416 if(mInsideDiscontinuousLoop || mOutputLod0Function) 1417 { 1418 outputTriplet(visit, "(", "", ", 0.0)"); 1419 } 1420 else 1421 { 1422 outputTriplet(visit, "ddy(", "", ")"); 1423 } 1424 break; 1425 case EOpFwidth: 1426 if(mInsideDiscontinuousLoop || mOutputLod0Function) 1427 { 1428 outputTriplet(visit, "(", "", ", 0.0)"); 1429 } 1430 else 1431 { 1432 outputTriplet(visit, "fwidth(", "", ")"); 1433 } 1434 break; 1435 case EOpAny: outputTriplet(visit, "any(", "", ")"); break; 1436 case EOpAll: outputTriplet(visit, "all(", "", ")"); break; 1437 default: UNREACHABLE(); 1438 } 1439 1440 return true; 1441 } 1442 1443 bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) 1444 { 1445 TInfoSinkBase &out = mBody; 1446 1447 switch (node->getOp()) 1448 { 1449 case EOpSequence: 1450 { 1451 if (mInsideFunction) 1452 { 1453 outputLineDirective(node->getLine().first_line); 1454 out << "{\n"; 1455 1456 mScopeDepth++; 1457 1458 if (mScopeBracket.size() < mScopeDepth) 1459 { 1460 mScopeBracket.push_back(0); // New scope level 1461 } 1462 else 1463 { 1464 mScopeBracket[mScopeDepth - 1]++; // New scope at existing level 1465 } 1466 } 1467 1468 for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++) 1469 { 1470 outputLineDirective((*sit)->getLine().first_line); 1471 1472 traverseStatements(*sit); 1473 1474 out << ";\n"; 1475 } 1476 1477 if (mInsideFunction) 1478 { 1479 outputLineDirective(node->getLine().last_line); 1480 out << "}\n"; 1481 1482 mScopeDepth--; 1483 } 1484 1485 return false; 1486 } 1487 case EOpDeclaration: 1488 if (visit == PreVisit) 1489 { 1490 TIntermSequence &sequence = node->getSequence(); 1491 TIntermTyped *variable = sequence[0]->getAsTyped(); 1492 1493 if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal)) 1494 { 1495 if (variable->getType().getStruct()) 1496 { 1497 addConstructor(variable->getType(), scopedStruct(variable->getType().getStruct()->name()), NULL); 1498 } 1499 1500 if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration 1501 { 1502 if (!mInsideFunction) 1503 { 1504 out << "static "; 1505 } 1506 1507 out << typeString(variable->getType()) + " "; 1508 1509 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) 1510 { 1511 TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); 1512 1513 if (symbol) 1514 { 1515 symbol->traverse(this); 1516 out << arrayString(symbol->getType()); 1517 out << " = " + initializer(variable->getType()); 1518 } 1519 else 1520 { 1521 (*sit)->traverse(this); 1522 } 1523 1524 if (*sit != sequence.back()) 1525 { 1526 out << ", "; 1527 } 1528 } 1529 } 1530 else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration 1531 { 1532 // Already added to constructor map 1533 } 1534 else UNREACHABLE(); 1535 } 1536 else if (variable && (variable->getQualifier() == EvqVaryingOut || variable->getQualifier() == EvqInvariantVaryingOut)) 1537 { 1538 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) 1539 { 1540 TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); 1541 1542 if (symbol) 1543 { 1544 // Vertex (output) varyings which are declared but not written to should still be declared to allow successful linking 1545 mReferencedVaryings[symbol->getSymbol()] = symbol; 1546 } 1547 else 1548 { 1549 (*sit)->traverse(this); 1550 } 1551 } 1552 } 1553 1554 return false; 1555 } 1556 else if (visit == InVisit) 1557 { 1558 out << ", "; 1559 } 1560 break; 1561 case EOpPrototype: 1562 if (visit == PreVisit) 1563 { 1564 out << typeString(node->getType()) << " " << decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "("); 1565 1566 TIntermSequence &arguments = node->getSequence(); 1567 1568 for (unsigned int i = 0; i < arguments.size(); i++) 1569 { 1570 TIntermSymbol *symbol = arguments[i]->getAsSymbolNode(); 1571 1572 if (symbol) 1573 { 1574 out << argumentString(symbol); 1575 1576 if (i < arguments.size() - 1) 1577 { 1578 out << ", "; 1579 } 1580 } 1581 else UNREACHABLE(); 1582 } 1583 1584 out << ");\n"; 1585 1586 // Also prototype the Lod0 variant if needed 1587 if (mContainsLoopDiscontinuity && !mOutputLod0Function) 1588 { 1589 mOutputLod0Function = true; 1590 node->traverse(this); 1591 mOutputLod0Function = false; 1592 } 1593 1594 return false; 1595 } 1596 break; 1597 case EOpComma: outputTriplet(visit, "(", ", ", ")"); break; 1598 case EOpFunction: 1599 { 1600 TString name = TFunction::unmangleName(node->getName()); 1601 1602 out << typeString(node->getType()) << " "; 1603 1604 if (name == "main") 1605 { 1606 out << "gl_main("; 1607 } 1608 else 1609 { 1610 out << decorate(name) << (mOutputLod0Function ? "Lod0(" : "("); 1611 } 1612 1613 TIntermSequence &sequence = node->getSequence(); 1614 TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence(); 1615 1616 for (unsigned int i = 0; i < arguments.size(); i++) 1617 { 1618 TIntermSymbol *symbol = arguments[i]->getAsSymbolNode(); 1619 1620 if (symbol) 1621 { 1622 if (symbol->getType().getStruct()) 1623 { 1624 addConstructor(symbol->getType(), scopedStruct(symbol->getType().getStruct()->name()), NULL); 1625 } 1626 1627 out << argumentString(symbol); 1628 1629 if (i < arguments.size() - 1) 1630 { 1631 out << ", "; 1632 } 1633 } 1634 else UNREACHABLE(); 1635 } 1636 1637 out << ")\n" 1638 "{\n"; 1639 1640 if (sequence.size() > 1) 1641 { 1642 mInsideFunction = true; 1643 sequence[1]->traverse(this); 1644 mInsideFunction = false; 1645 } 1646 1647 out << "}\n"; 1648 1649 if (mContainsLoopDiscontinuity && !mOutputLod0Function) 1650 { 1651 if (name != "main") 1652 { 1653 mOutputLod0Function = true; 1654 node->traverse(this); 1655 mOutputLod0Function = false; 1656 } 1657 } 1658 1659 return false; 1660 } 1661 break; 1662 case EOpFunctionCall: 1663 { 1664 TString name = TFunction::unmangleName(node->getName()); 1665 bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function; 1666 1667 if (node->isUserDefined()) 1668 { 1669 out << decorate(name) << (lod0 ? "Lod0(" : "("); 1670 } 1671 else 1672 { 1673 if (name == "texture2D") 1674 { 1675 if (!lod0) 1676 { 1677 if (node->getSequence().size() == 2) 1678 { 1679 mUsesTexture2D = true; 1680 } 1681 else if (node->getSequence().size() == 3) 1682 { 1683 mUsesTexture2D_bias = true; 1684 } 1685 else UNREACHABLE(); 1686 1687 out << "gl_texture2D("; 1688 } 1689 else 1690 { 1691 if (node->getSequence().size() == 2) 1692 { 1693 mUsesTexture2DLod0 = true; 1694 } 1695 else if (node->getSequence().size() == 3) 1696 { 1697 mUsesTexture2DLod0_bias = true; 1698 } 1699 else UNREACHABLE(); 1700 1701 out << "gl_texture2DLod0("; 1702 } 1703 } 1704 else if (name == "texture2DProj") 1705 { 1706 if (!lod0) 1707 { 1708 if (node->getSequence().size() == 2) 1709 { 1710 mUsesTexture2DProj = true; 1711 } 1712 else if (node->getSequence().size() == 3) 1713 { 1714 mUsesTexture2DProj_bias = true; 1715 } 1716 else UNREACHABLE(); 1717 1718 out << "gl_texture2DProj("; 1719 } 1720 else 1721 { 1722 if (node->getSequence().size() == 2) 1723 { 1724 mUsesTexture2DProjLod0 = true; 1725 } 1726 else if (node->getSequence().size() == 3) 1727 { 1728 mUsesTexture2DProjLod0_bias = true; 1729 } 1730 else UNREACHABLE(); 1731 1732 out << "gl_texture2DProjLod0("; 1733 } 1734 } 1735 else if (name == "textureCube") 1736 { 1737 if (!lod0) 1738 { 1739 if (node->getSequence().size() == 2) 1740 { 1741 mUsesTextureCube = true; 1742 } 1743 else if (node->getSequence().size() == 3) 1744 { 1745 mUsesTextureCube_bias = true; 1746 } 1747 else UNREACHABLE(); 1748 1749 out << "gl_textureCube("; 1750 } 1751 else 1752 { 1753 if (node->getSequence().size() == 2) 1754 { 1755 mUsesTextureCubeLod0 = true; 1756 } 1757 else if (node->getSequence().size() == 3) 1758 { 1759 mUsesTextureCubeLod0_bias = true; 1760 } 1761 else UNREACHABLE(); 1762 1763 out << "gl_textureCubeLod0("; 1764 } 1765 } 1766 else if (name == "texture2DLod") 1767 { 1768 if (node->getSequence().size() == 3) 1769 { 1770 mUsesTexture2DLod = true; 1771 } 1772 else UNREACHABLE(); 1773 1774 out << "gl_texture2DLod("; 1775 } 1776 else if (name == "texture2DProjLod") 1777 { 1778 if (node->getSequence().size() == 3) 1779 { 1780 mUsesTexture2DProjLod = true; 1781 } 1782 else UNREACHABLE(); 1783 1784 out << "gl_texture2DProjLod("; 1785 } 1786 else if (name == "textureCubeLod") 1787 { 1788 if (node->getSequence().size() == 3) 1789 { 1790 mUsesTextureCubeLod = true; 1791 } 1792 else UNREACHABLE(); 1793 1794 out << "gl_textureCubeLod("; 1795 } 1796 else UNREACHABLE(); 1797 } 1798 1799 TIntermSequence &arguments = node->getSequence(); 1800 1801 for (TIntermSequence::iterator arg = arguments.begin(); arg != arguments.end(); arg++) 1802 { 1803 if (mOutputType == SH_HLSL11_OUTPUT && IsSampler((*arg)->getAsTyped()->getBasicType())) 1804 { 1805 out << "texture_"; 1806 (*arg)->traverse(this); 1807 out << ", sampler_"; 1808 } 1809 1810 (*arg)->traverse(this); 1811 1812 if (arg < arguments.end() - 1) 1813 { 1814 out << ", "; 1815 } 1816 } 1817 1818 out << ")"; 1819 1820 return false; 1821 } 1822 break; 1823 case EOpParameters: outputTriplet(visit, "(", ", ", ")\n{\n"); break; 1824 case EOpConstructFloat: 1825 addConstructor(node->getType(), "vec1", &node->getSequence()); 1826 outputTriplet(visit, "vec1(", "", ")"); 1827 break; 1828 case EOpConstructVec2: 1829 addConstructor(node->getType(), "vec2", &node->getSequence()); 1830 outputTriplet(visit, "vec2(", ", ", ")"); 1831 break; 1832 case EOpConstructVec3: 1833 addConstructor(node->getType(), "vec3", &node->getSequence()); 1834 outputTriplet(visit, "vec3(", ", ", ")"); 1835 break; 1836 case EOpConstructVec4: 1837 addConstructor(node->getType(), "vec4", &node->getSequence()); 1838 outputTriplet(visit, "vec4(", ", ", ")"); 1839 break; 1840 case EOpConstructBool: 1841 addConstructor(node->getType(), "bvec1", &node->getSequence()); 1842 outputTriplet(visit, "bvec1(", "", ")"); 1843 break; 1844 case EOpConstructBVec2: 1845 addConstructor(node->getType(), "bvec2", &node->getSequence()); 1846 outputTriplet(visit, "bvec2(", ", ", ")"); 1847 break; 1848 case EOpConstructBVec3: 1849 addConstructor(node->getType(), "bvec3", &node->getSequence()); 1850 outputTriplet(visit, "bvec3(", ", ", ")"); 1851 break; 1852 case EOpConstructBVec4: 1853 addConstructor(node->getType(), "bvec4", &node->getSequence()); 1854 outputTriplet(visit, "bvec4(", ", ", ")"); 1855 break; 1856 case EOpConstructInt: 1857 addConstructor(node->getType(), "ivec1", &node->getSequence()); 1858 outputTriplet(visit, "ivec1(", "", ")"); 1859 break; 1860 case EOpConstructIVec2: 1861 addConstructor(node->getType(), "ivec2", &node->getSequence()); 1862 outputTriplet(visit, "ivec2(", ", ", ")"); 1863 break; 1864 case EOpConstructIVec3: 1865 addConstructor(node->getType(), "ivec3", &node->getSequence()); 1866 outputTriplet(visit, "ivec3(", ", ", ")"); 1867 break; 1868 case EOpConstructIVec4: 1869 addConstructor(node->getType(), "ivec4", &node->getSequence()); 1870 outputTriplet(visit, "ivec4(", ", ", ")"); 1871 break; 1872 case EOpConstructMat2: 1873 addConstructor(node->getType(), "mat2", &node->getSequence()); 1874 outputTriplet(visit, "mat2(", ", ", ")"); 1875 break; 1876 case EOpConstructMat3: 1877 addConstructor(node->getType(), "mat3", &node->getSequence()); 1878 outputTriplet(visit, "mat3(", ", ", ")"); 1879 break; 1880 case EOpConstructMat4: 1881 addConstructor(node->getType(), "mat4", &node->getSequence()); 1882 outputTriplet(visit, "mat4(", ", ", ")"); 1883 break; 1884 case EOpConstructStruct: 1885 addConstructor(node->getType(), scopedStruct(node->getType().getStruct()->name()), &node->getSequence()); 1886 outputTriplet(visit, structLookup(node->getType().getStruct()->name()) + "_ctor(", ", ", ")"); 1887 break; 1888 case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; 1889 case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break; 1890 case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break; 1891 case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break; 1892 case EOpVectorEqual: outputTriplet(visit, "(", " == ", ")"); break; 1893 case EOpVectorNotEqual: outputTriplet(visit, "(", " != ", ")"); break; 1894 case EOpMod: 1895 { 1896 // We need to look at the number of components in both arguments 1897 switch (node->getSequence()[0]->getAsTyped()->getNominalSize() * 10 1898 + node->getSequence()[1]->getAsTyped()->getNominalSize()) 1899 { 1900 case 11: mUsesMod1 = true; break; 1901 case 22: mUsesMod2v = true; break; 1902 case 21: mUsesMod2f = true; break; 1903 case 33: mUsesMod3v = true; break; 1904 case 31: mUsesMod3f = true; break; 1905 case 44: mUsesMod4v = true; break; 1906 case 41: mUsesMod4f = true; break; 1907 default: UNREACHABLE(); 1908 } 1909 1910 outputTriplet(visit, "mod(", ", ", ")"); 1911 } 1912 break; 1913 case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break; 1914 case EOpAtan: 1915 ASSERT(node->getSequence().size() == 2); // atan(x) is a unary operator 1916 switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) 1917 { 1918 case 1: mUsesAtan2_1 = true; break; 1919 case 2: mUsesAtan2_2 = true; break; 1920 case 3: mUsesAtan2_3 = true; break; 1921 case 4: mUsesAtan2_4 = true; break; 1922 default: UNREACHABLE(); 1923 } 1924 outputTriplet(visit, "atanyx(", ", ", ")"); 1925 break; 1926 case EOpMin: outputTriplet(visit, "min(", ", ", ")"); break; 1927 case EOpMax: outputTriplet(visit, "max(", ", ", ")"); break; 1928 case EOpClamp: outputTriplet(visit, "clamp(", ", ", ")"); break; 1929 case EOpMix: outputTriplet(visit, "lerp(", ", ", ")"); break; 1930 case EOpStep: outputTriplet(visit, "step(", ", ", ")"); break; 1931 case EOpSmoothStep: outputTriplet(visit, "smoothstep(", ", ", ")"); break; 1932 case EOpDistance: outputTriplet(visit, "distance(", ", ", ")"); break; 1933 case EOpDot: outputTriplet(visit, "dot(", ", ", ")"); break; 1934 case EOpCross: outputTriplet(visit, "cross(", ", ", ")"); break; 1935 case EOpFaceForward: 1936 { 1937 switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) // Number of components in the first argument 1938 { 1939 case 1: mUsesFaceforward1 = true; break; 1940 case 2: mUsesFaceforward2 = true; break; 1941 case 3: mUsesFaceforward3 = true; break; 1942 case 4: mUsesFaceforward4 = true; break; 1943 default: UNREACHABLE(); 1944 } 1945 1946 outputTriplet(visit, "faceforward(", ", ", ")"); 1947 } 1948 break; 1949 case EOpReflect: outputTriplet(visit, "reflect(", ", ", ")"); break; 1950 case EOpRefract: outputTriplet(visit, "refract(", ", ", ")"); break; 1951 case EOpMul: outputTriplet(visit, "(", " * ", ")"); break; 1952 default: UNREACHABLE(); 1953 } 1954 1955 return true; 1956 } 1957 1958 bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) 1959 { 1960 TInfoSinkBase &out = mBody; 1961 1962 if (node->usesTernaryOperator()) 1963 { 1964 out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex(); 1965 } 1966 else // if/else statement 1967 { 1968 mUnfoldShortCircuit->traverse(node->getCondition()); 1969 1970 out << "if ("; 1971 1972 node->getCondition()->traverse(this); 1973 1974 out << ")\n"; 1975 1976 outputLineDirective(node->getLine().first_line); 1977 out << "{\n"; 1978 1979 bool discard = false; 1980 1981 if (node->getTrueBlock()) 1982 { 1983 traverseStatements(node->getTrueBlock()); 1984 1985 // Detect true discard 1986 discard = (discard || FindDiscard::search(node->getTrueBlock())); 1987 } 1988 1989 outputLineDirective(node->getLine().first_line); 1990 out << ";\n}\n"; 1991 1992 if (node->getFalseBlock()) 1993 { 1994 out << "else\n"; 1995 1996 outputLineDirective(node->getFalseBlock()->getLine().first_line); 1997 out << "{\n"; 1998 1999 outputLineDirective(node->getFalseBlock()->getLine().first_line); 2000 traverseStatements(node->getFalseBlock()); 2001 2002 outputLineDirective(node->getFalseBlock()->getLine().first_line); 2003 out << ";\n}\n"; 2004 2005 // Detect false discard 2006 discard = (discard || FindDiscard::search(node->getFalseBlock())); 2007 } 2008 2009 // ANGLE issue 486: Detect problematic conditional discard 2010 if (discard && FindSideEffectRewriting::search(node)) 2011 { 2012 mUsesDiscardRewriting = true; 2013 } 2014 } 2015 2016 return false; 2017 } 2018 2019 void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node) 2020 { 2021 writeConstantUnion(node->getType(), node->getUnionArrayPointer()); 2022 } 2023 2024 bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) 2025 { 2026 bool wasDiscontinuous = mInsideDiscontinuousLoop; 2027 2028 if (mContainsLoopDiscontinuity && !mInsideDiscontinuousLoop) 2029 { 2030 mInsideDiscontinuousLoop = containsLoopDiscontinuity(node); 2031 } 2032 2033 if (mOutputType == SH_HLSL9_OUTPUT) 2034 { 2035 if (handleExcessiveLoop(node)) 2036 { 2037 return false; 2038 } 2039 } 2040 2041 TInfoSinkBase &out = mBody; 2042 2043 if (node->getType() == ELoopDoWhile) 2044 { 2045 out << "{do\n"; 2046 2047 outputLineDirective(node->getLine().first_line); 2048 out << "{\n"; 2049 } 2050 else 2051 { 2052 out << "{for("; 2053 2054 if (node->getInit()) 2055 { 2056 node->getInit()->traverse(this); 2057 } 2058 2059 out << "; "; 2060 2061 if (node->getCondition()) 2062 { 2063 node->getCondition()->traverse(this); 2064 } 2065 2066 out << "; "; 2067 2068 if (node->getExpression()) 2069 { 2070 node->getExpression()->traverse(this); 2071 } 2072 2073 out << ")\n"; 2074 2075 outputLineDirective(node->getLine().first_line); 2076 out << "{\n"; 2077 } 2078 2079 if (node->getBody()) 2080 { 2081 traverseStatements(node->getBody()); 2082 } 2083 2084 outputLineDirective(node->getLine().first_line); 2085 out << ";}\n"; 2086 2087 if (node->getType() == ELoopDoWhile) 2088 { 2089 outputLineDirective(node->getCondition()->getLine().first_line); 2090 out << "while(\n"; 2091 2092 node->getCondition()->traverse(this); 2093 2094 out << ");"; 2095 } 2096 2097 out << "}\n"; 2098 2099 mInsideDiscontinuousLoop = wasDiscontinuous; 2100 2101 return false; 2102 } 2103 2104 bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node) 2105 { 2106 TInfoSinkBase &out = mBody; 2107 2108 switch (node->getFlowOp()) 2109 { 2110 case EOpKill: 2111 outputTriplet(visit, "discard;\n", "", ""); 2112 break; 2113 case EOpBreak: 2114 if (visit == PreVisit) 2115 { 2116 if (mExcessiveLoopIndex) 2117 { 2118 out << "{Break"; 2119 mExcessiveLoopIndex->traverse(this); 2120 out << " = true; break;}\n"; 2121 } 2122 else 2123 { 2124 out << "break;\n"; 2125 } 2126 } 2127 break; 2128 case EOpContinue: outputTriplet(visit, "continue;\n", "", ""); break; 2129 case EOpReturn: 2130 if (visit == PreVisit) 2131 { 2132 if (node->getExpression()) 2133 { 2134 out << "return "; 2135 } 2136 else 2137 { 2138 out << "return;\n"; 2139 } 2140 } 2141 else if (visit == PostVisit) 2142 { 2143 if (node->getExpression()) 2144 { 2145 out << ";\n"; 2146 } 2147 } 2148 break; 2149 default: UNREACHABLE(); 2150 } 2151 2152 return true; 2153 } 2154 2155 void OutputHLSL::traverseStatements(TIntermNode *node) 2156 { 2157 if (isSingleStatement(node)) 2158 { 2159 mUnfoldShortCircuit->traverse(node); 2160 } 2161 2162 node->traverse(this); 2163 } 2164 2165 bool OutputHLSL::isSingleStatement(TIntermNode *node) 2166 { 2167 TIntermAggregate *aggregate = node->getAsAggregate(); 2168 2169 if (aggregate) 2170 { 2171 if (aggregate->getOp() == EOpSequence) 2172 { 2173 return false; 2174 } 2175 else 2176 { 2177 for (TIntermSequence::iterator sit = aggregate->getSequence().begin(); sit != aggregate->getSequence().end(); sit++) 2178 { 2179 if (!isSingleStatement(*sit)) 2180 { 2181 return false; 2182 } 2183 } 2184 2185 return true; 2186 } 2187 } 2188 2189 return true; 2190 } 2191 2192 // Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them 2193 // (The D3D documentation says 255 iterations, but the compiler complains at anything more than 254). 2194 bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) 2195 { 2196 const int MAX_LOOP_ITERATIONS = 254; 2197 TInfoSinkBase &out = mBody; 2198 2199 // Parse loops of the form: 2200 // for(int index = initial; index [comparator] limit; index += increment) 2201 TIntermSymbol *index = NULL; 2202 TOperator comparator = EOpNull; 2203 int initial = 0; 2204 int limit = 0; 2205 int increment = 0; 2206 2207 // Parse index name and intial value 2208 if (node->getInit()) 2209 { 2210 TIntermAggregate *init = node->getInit()->getAsAggregate(); 2211 2212 if (init) 2213 { 2214 TIntermSequence &sequence = init->getSequence(); 2215 TIntermTyped *variable = sequence[0]->getAsTyped(); 2216 2217 if (variable && variable->getQualifier() == EvqTemporary) 2218 { 2219 TIntermBinary *assign = variable->getAsBinaryNode(); 2220 2221 if (assign->getOp() == EOpInitialize) 2222 { 2223 TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode(); 2224 TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion(); 2225 2226 if (symbol && constant) 2227 { 2228 if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) 2229 { 2230 index = symbol; 2231 initial = constant->getIConst(0); 2232 } 2233 } 2234 } 2235 } 2236 } 2237 } 2238 2239 // Parse comparator and limit value 2240 if (index != NULL && node->getCondition()) 2241 { 2242 TIntermBinary *test = node->getCondition()->getAsBinaryNode(); 2243 2244 if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId()) 2245 { 2246 TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion(); 2247 2248 if (constant) 2249 { 2250 if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) 2251 { 2252 comparator = test->getOp(); 2253 limit = constant->getIConst(0); 2254 } 2255 } 2256 } 2257 } 2258 2259 // Parse increment 2260 if (index != NULL && comparator != EOpNull && node->getExpression()) 2261 { 2262 TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode(); 2263 TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode(); 2264 2265 if (binaryTerminal) 2266 { 2267 TOperator op = binaryTerminal->getOp(); 2268 TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion(); 2269 2270 if (constant) 2271 { 2272 if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) 2273 { 2274 int value = constant->getIConst(0); 2275 2276 switch (op) 2277 { 2278 case EOpAddAssign: increment = value; break; 2279 case EOpSubAssign: increment = -value; break; 2280 default: UNIMPLEMENTED(); 2281 } 2282 } 2283 } 2284 } 2285 else if (unaryTerminal) 2286 { 2287 TOperator op = unaryTerminal->getOp(); 2288 2289 switch (op) 2290 { 2291 case EOpPostIncrement: increment = 1; break; 2292 case EOpPostDecrement: increment = -1; break; 2293 case EOpPreIncrement: increment = 1; break; 2294 case EOpPreDecrement: increment = -1; break; 2295 default: UNIMPLEMENTED(); 2296 } 2297 } 2298 } 2299 2300 if (index != NULL && comparator != EOpNull && increment != 0) 2301 { 2302 if (comparator == EOpLessThanEqual) 2303 { 2304 comparator = EOpLessThan; 2305 limit += 1; 2306 } 2307 2308 if (comparator == EOpLessThan) 2309 { 2310 int iterations = (limit - initial) / increment; 2311 2312 if (iterations <= MAX_LOOP_ITERATIONS) 2313 { 2314 return false; // Not an excessive loop 2315 } 2316 2317 TIntermSymbol *restoreIndex = mExcessiveLoopIndex; 2318 mExcessiveLoopIndex = index; 2319 2320 out << "{int "; 2321 index->traverse(this); 2322 out << ";\n" 2323 "bool Break"; 2324 index->traverse(this); 2325 out << " = false;\n"; 2326 2327 bool firstLoopFragment = true; 2328 2329 while (iterations > 0) 2330 { 2331 int clampedLimit = initial + increment * std::min(MAX_LOOP_ITERATIONS, iterations); 2332 2333 if (!firstLoopFragment) 2334 { 2335 out << "if (!Break"; 2336 index->traverse(this); 2337 out << ") {\n"; 2338 } 2339 2340 if (iterations <= MAX_LOOP_ITERATIONS) // Last loop fragment 2341 { 2342 mExcessiveLoopIndex = NULL; // Stops setting the Break flag 2343 } 2344 2345 // for(int index = initial; index < clampedLimit; index += increment) 2346 2347 out << "for("; 2348 index->traverse(this); 2349 out << " = "; 2350 out << initial; 2351 2352 out << "; "; 2353 index->traverse(this); 2354 out << " < "; 2355 out << clampedLimit; 2356 2357 out << "; "; 2358 index->traverse(this); 2359 out << " += "; 2360 out << increment; 2361 out << ")\n"; 2362 2363 outputLineDirective(node->getLine().first_line); 2364 out << "{\n"; 2365 2366 if (node->getBody()) 2367 { 2368 node->getBody()->traverse(this); 2369 } 2370 2371 outputLineDirective(node->getLine().first_line); 2372 out << ";}\n"; 2373 2374 if (!firstLoopFragment) 2375 { 2376 out << "}\n"; 2377 } 2378 2379 firstLoopFragment = false; 2380 2381 initial += MAX_LOOP_ITERATIONS * increment; 2382 iterations -= MAX_LOOP_ITERATIONS; 2383 } 2384 2385 out << "}"; 2386 2387 mExcessiveLoopIndex = restoreIndex; 2388 2389 return true; 2390 } 2391 else UNIMPLEMENTED(); 2392 } 2393 2394 return false; // Not handled as an excessive loop 2395 } 2396 2397 void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString) 2398 { 2399 TInfoSinkBase &out = mBody; 2400 2401 if (visit == PreVisit) 2402 { 2403 out << preString; 2404 } 2405 else if (visit == InVisit) 2406 { 2407 out << inString; 2408 } 2409 else if (visit == PostVisit) 2410 { 2411 out << postString; 2412 } 2413 } 2414 2415 void OutputHLSL::outputLineDirective(int line) 2416 { 2417 if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0)) 2418 { 2419 mBody << "\n"; 2420 mBody << "#line " << line; 2421 2422 if (mContext.sourcePath) 2423 { 2424 mBody << " \"" << mContext.sourcePath << "\""; 2425 } 2426 2427 mBody << "\n"; 2428 } 2429 } 2430 2431 TString OutputHLSL::argumentString(const TIntermSymbol *symbol) 2432 { 2433 TQualifier qualifier = symbol->getQualifier(); 2434 const TType &type = symbol->getType(); 2435 TString name = symbol->getSymbol(); 2436 2437 if (name.empty()) // HLSL demands named arguments, also for prototypes 2438 { 2439 name = "x" + str(mUniqueIndex++); 2440 } 2441 else 2442 { 2443 name = decorate(name); 2444 } 2445 2446 if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) 2447 { 2448 return qualifierString(qualifier) + " " + textureString(type) + " texture_" + name + arrayString(type) + ", " + 2449 qualifierString(qualifier) + " SamplerState sampler_" + name + arrayString(type); 2450 } 2451 2452 return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type); 2453 } 2454 2455 TString OutputHLSL::qualifierString(TQualifier qualifier) 2456 { 2457 switch(qualifier) 2458 { 2459 case EvqIn: return "in"; 2460 case EvqOut: return "out"; 2461 case EvqInOut: return "inout"; 2462 case EvqConstReadOnly: return "const"; 2463 default: UNREACHABLE(); 2464 } 2465 2466 return ""; 2467 } 2468 2469 TString OutputHLSL::typeString(const TType &type) 2470 { 2471 if (type.getBasicType() == EbtStruct) 2472 { 2473 const TString& typeName = type.getStruct()->name(); 2474 if (typeName != "") 2475 { 2476 return structLookup(typeName); 2477 } 2478 else // Nameless structure, define in place 2479 { 2480 const TFieldList &fields = type.getStruct()->fields(); 2481 2482 TString string = "struct\n" 2483 "{\n"; 2484 2485 for (unsigned int i = 0; i < fields.size(); i++) 2486 { 2487 const TField *field = fields[i]; 2488 2489 string += " " + typeString(*field->type()) + " " + decorate(field->name()) + arrayString(*field->type()) + ";\n"; 2490 } 2491 2492 string += "} "; 2493 2494 return string; 2495 } 2496 } 2497 else if (type.isMatrix()) 2498 { 2499 switch (type.getNominalSize()) 2500 { 2501 case 2: return "float2x2"; 2502 case 3: return "float3x3"; 2503 case 4: return "float4x4"; 2504 } 2505 } 2506 else 2507 { 2508 switch (type.getBasicType()) 2509 { 2510 case EbtFloat: 2511 switch (type.getNominalSize()) 2512 { 2513 case 1: return "float"; 2514 case 2: return "float2"; 2515 case 3: return "float3"; 2516 case 4: return "float4"; 2517 } 2518 case EbtInt: 2519 switch (type.getNominalSize()) 2520 { 2521 case 1: return "int"; 2522 case 2: return "int2"; 2523 case 3: return "int3"; 2524 case 4: return "int4"; 2525 } 2526 case EbtBool: 2527 switch (type.getNominalSize()) 2528 { 2529 case 1: return "bool"; 2530 case 2: return "bool2"; 2531 case 3: return "bool3"; 2532 case 4: return "bool4"; 2533 } 2534 case EbtVoid: 2535 return "void"; 2536 case EbtSampler2D: 2537 return "sampler2D"; 2538 case EbtSamplerCube: 2539 return "samplerCUBE"; 2540 case EbtSamplerExternalOES: 2541 return "sampler2D"; 2542 default: 2543 break; 2544 } 2545 } 2546 2547 UNREACHABLE(); 2548 return "<unknown type>"; 2549 } 2550 2551 TString OutputHLSL::textureString(const TType &type) 2552 { 2553 switch (type.getBasicType()) 2554 { 2555 case EbtSampler2D: 2556 return "Texture2D"; 2557 case EbtSamplerCube: 2558 return "TextureCube"; 2559 case EbtSamplerExternalOES: 2560 return "Texture2D"; 2561 default: 2562 break; 2563 } 2564 2565 UNREACHABLE(); 2566 return "<unknown texture type>"; 2567 } 2568 2569 TString OutputHLSL::arrayString(const TType &type) 2570 { 2571 if (!type.isArray()) 2572 { 2573 return ""; 2574 } 2575 2576 return "[" + str(type.getArraySize()) + "]"; 2577 } 2578 2579 TString OutputHLSL::initializer(const TType &type) 2580 { 2581 TString string; 2582 2583 size_t size = type.getObjectSize(); 2584 for (size_t component = 0; component < size; component++) 2585 { 2586 string += "0"; 2587 2588 if (component + 1 < size) 2589 { 2590 string += ", "; 2591 } 2592 } 2593 2594 return "{" + string + "}"; 2595 } 2596 2597 void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters) 2598 { 2599 if (name == "") 2600 { 2601 return; // Nameless structures don't have constructors 2602 } 2603 2604 if (type.getStruct() && mStructNames.find(decorate(name)) != mStructNames.end()) 2605 { 2606 return; // Already added 2607 } 2608 2609 TType ctorType = type; 2610 ctorType.clearArrayness(); 2611 ctorType.setPrecision(EbpHigh); 2612 ctorType.setQualifier(EvqTemporary); 2613 2614 TString ctorName = type.getStruct() ? decorate(name) : name; 2615 2616 typedef std::vector<TType> ParameterArray; 2617 ParameterArray ctorParameters; 2618 2619 if (type.getStruct()) 2620 { 2621 mStructNames.insert(decorate(name)); 2622 2623 TString structure; 2624 structure += "struct " + decorate(name) + "\n" 2625 "{\n"; 2626 2627 const TFieldList &fields = type.getStruct()->fields(); 2628 2629 for (unsigned int i = 0; i < fields.size(); i++) 2630 { 2631 const TField *field = fields[i]; 2632 2633 structure += " " + typeString(*field->type()) + " " + decorateField(field->name(), type) + arrayString(*field->type()) + ";\n"; 2634 } 2635 2636 structure += "};\n"; 2637 2638 if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structure) == mStructDeclarations.end()) 2639 { 2640 mStructDeclarations.push_back(structure); 2641 } 2642 2643 for (unsigned int i = 0; i < fields.size(); i++) 2644 { 2645 ctorParameters.push_back(*fields[i]->type()); 2646 } 2647 } 2648 else if (parameters) 2649 { 2650 for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++) 2651 { 2652 ctorParameters.push_back((*parameter)->getAsTyped()->getType()); 2653 } 2654 } 2655 else UNREACHABLE(); 2656 2657 TString constructor; 2658 2659 if (ctorType.getStruct()) 2660 { 2661 constructor += ctorName + " " + ctorName + "_ctor("; 2662 } 2663 else // Built-in type 2664 { 2665 constructor += typeString(ctorType) + " " + ctorName + "("; 2666 } 2667 2668 for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++) 2669 { 2670 const TType &type = ctorParameters[parameter]; 2671 2672 constructor += typeString(type) + " x" + str(parameter) + arrayString(type); 2673 2674 if (parameter < ctorParameters.size() - 1) 2675 { 2676 constructor += ", "; 2677 } 2678 } 2679 2680 constructor += ")\n" 2681 "{\n"; 2682 2683 if (ctorType.getStruct()) 2684 { 2685 constructor += " " + ctorName + " structure = {"; 2686 } 2687 else 2688 { 2689 constructor += " return " + typeString(ctorType) + "("; 2690 } 2691 2692 if (ctorType.isMatrix() && ctorParameters.size() == 1) 2693 { 2694 int dim = ctorType.getNominalSize(); 2695 const TType ¶meter = ctorParameters[0]; 2696 2697 if (parameter.isScalar()) 2698 { 2699 for (int row = 0; row < dim; row++) 2700 { 2701 for (int col = 0; col < dim; col++) 2702 { 2703 constructor += TString((row == col) ? "x0" : "0.0"); 2704 2705 if (row < dim - 1 || col < dim - 1) 2706 { 2707 constructor += ", "; 2708 } 2709 } 2710 } 2711 } 2712 else if (parameter.isMatrix()) 2713 { 2714 for (int row = 0; row < dim; row++) 2715 { 2716 for (int col = 0; col < dim; col++) 2717 { 2718 if (row < parameter.getNominalSize() && col < parameter.getNominalSize()) 2719 { 2720 constructor += TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]"; 2721 } 2722 else 2723 { 2724 constructor += TString((row == col) ? "1.0" : "0.0"); 2725 } 2726 2727 if (row < dim - 1 || col < dim - 1) 2728 { 2729 constructor += ", "; 2730 } 2731 } 2732 } 2733 } 2734 else UNREACHABLE(); 2735 } 2736 else 2737 { 2738 size_t remainingComponents = ctorType.getObjectSize(); 2739 size_t parameterIndex = 0; 2740 2741 while (remainingComponents > 0) 2742 { 2743 const TType ¶meter = ctorParameters[parameterIndex]; 2744 const size_t parameterSize = parameter.getObjectSize(); 2745 bool moreParameters = parameterIndex + 1 < ctorParameters.size(); 2746 2747 constructor += "x" + str(parameterIndex); 2748 2749 if (parameter.isScalar()) 2750 { 2751 ASSERT(parameterSize <= remainingComponents); 2752 remainingComponents -= parameterSize; 2753 } 2754 else if (parameter.isVector()) 2755 { 2756 if (remainingComponents == parameterSize || moreParameters) 2757 { 2758 ASSERT(parameterSize <= remainingComponents); 2759 remainingComponents -= parameterSize; 2760 } 2761 else if (remainingComponents < static_cast<size_t>(parameter.getNominalSize())) 2762 { 2763 switch (remainingComponents) 2764 { 2765 case 1: constructor += ".x"; break; 2766 case 2: constructor += ".xy"; break; 2767 case 3: constructor += ".xyz"; break; 2768 case 4: constructor += ".xyzw"; break; 2769 default: UNREACHABLE(); 2770 } 2771 2772 remainingComponents = 0; 2773 } 2774 else UNREACHABLE(); 2775 } 2776 else if (parameter.isMatrix() || parameter.getStruct()) 2777 { 2778 ASSERT(remainingComponents == parameterSize || moreParameters); 2779 ASSERT(parameterSize <= remainingComponents); 2780 2781 remainingComponents -= parameterSize; 2782 } 2783 else UNREACHABLE(); 2784 2785 if (moreParameters) 2786 { 2787 parameterIndex++; 2788 } 2789 2790 if (remainingComponents) 2791 { 2792 constructor += ", "; 2793 } 2794 } 2795 } 2796 2797 if (ctorType.getStruct()) 2798 { 2799 constructor += "};\n" 2800 " return structure;\n" 2801 "}\n"; 2802 } 2803 else 2804 { 2805 constructor += ");\n" 2806 "}\n"; 2807 } 2808 2809 mConstructors.insert(constructor); 2810 } 2811 2812 const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion) 2813 { 2814 TInfoSinkBase &out = mBody; 2815 2816 if (type.getBasicType() == EbtStruct) 2817 { 2818 out << structLookup(type.getStruct()->name()) + "_ctor("; 2819 2820 const TFieldList &fields = type.getStruct()->fields(); 2821 2822 for (size_t i = 0; i < fields.size(); i++) 2823 { 2824 const TType *fieldType = fields[i]->type(); 2825 2826 constUnion = writeConstantUnion(*fieldType, constUnion); 2827 2828 if (i != fields.size() - 1) 2829 { 2830 out << ", "; 2831 } 2832 } 2833 2834 out << ")"; 2835 } 2836 else 2837 { 2838 size_t size = type.getObjectSize(); 2839 bool writeType = size > 1; 2840 2841 if (writeType) 2842 { 2843 out << typeString(type) << "("; 2844 } 2845 2846 for (size_t i = 0; i < size; i++, constUnion++) 2847 { 2848 switch (constUnion->getType()) 2849 { 2850 case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, constUnion->getFConst())); break; 2851 case EbtInt: out << constUnion->getIConst(); break; 2852 case EbtBool: out << constUnion->getBConst(); break; 2853 default: UNREACHABLE(); 2854 } 2855 2856 if (i != size - 1) 2857 { 2858 out << ", "; 2859 } 2860 } 2861 2862 if (writeType) 2863 { 2864 out << ")"; 2865 } 2866 } 2867 2868 return constUnion; 2869 } 2870 2871 TString OutputHLSL::scopeString(unsigned int depthLimit) 2872 { 2873 TString string; 2874 2875 for (unsigned int i = 0; i < mScopeBracket.size() && i < depthLimit; i++) 2876 { 2877 string += "_" + str(i); 2878 } 2879 2880 return string; 2881 } 2882 2883 TString OutputHLSL::scopedStruct(const TString &typeName) 2884 { 2885 if (typeName == "") 2886 { 2887 return typeName; 2888 } 2889 2890 return typeName + scopeString(mScopeDepth); 2891 } 2892 2893 TString OutputHLSL::structLookup(const TString &typeName) 2894 { 2895 for (int depth = mScopeDepth; depth >= 0; depth--) 2896 { 2897 TString scopedName = decorate(typeName + scopeString(depth)); 2898 2899 for (StructNames::iterator structName = mStructNames.begin(); structName != mStructNames.end(); structName++) 2900 { 2901 if (*structName == scopedName) 2902 { 2903 return scopedName; 2904 } 2905 } 2906 } 2907 2908 UNREACHABLE(); // Should have found a matching constructor 2909 2910 return typeName; 2911 } 2912 2913 TString OutputHLSL::decorate(const TString &string) 2914 { 2915 if (string.compare(0, 3, "gl_") != 0 && string.compare(0, 3, "dx_") != 0) 2916 { 2917 return "_" + string; 2918 } 2919 2920 return string; 2921 } 2922 2923 TString OutputHLSL::decorateUniform(const TString &string, const TType &type) 2924 { 2925 if (type.getBasicType() == EbtSamplerExternalOES) 2926 { 2927 return "ex_" + string; 2928 } 2929 2930 return decorate(string); 2931 } 2932 2933 TString OutputHLSL::decorateField(const TString &string, const TType &structure) 2934 { 2935 if (structure.getStruct()->name().compare(0, 3, "gl_") != 0) 2936 { 2937 return decorate(string); 2938 } 2939 2940 return string; 2941 } 2942 2943 TString OutputHLSL::registerString(TIntermSymbol *operand) 2944 { 2945 ASSERT(operand->getQualifier() == EvqUniform); 2946 2947 if (IsSampler(operand->getBasicType())) 2948 { 2949 return "s" + str(samplerRegister(operand)); 2950 } 2951 2952 return "c" + str(uniformRegister(operand)); 2953 } 2954 2955 int OutputHLSL::samplerRegister(TIntermSymbol *sampler) 2956 { 2957 const TType &type = sampler->getType(); 2958 ASSERT(IsSampler(type.getBasicType())); 2959 2960 int index = mSamplerRegister; 2961 mSamplerRegister += sampler->totalRegisterCount(); 2962 2963 declareUniform(type, sampler->getSymbol(), index); 2964 2965 return index; 2966 } 2967 2968 int OutputHLSL::uniformRegister(TIntermSymbol *uniform) 2969 { 2970 const TType &type = uniform->getType(); 2971 ASSERT(!IsSampler(type.getBasicType())); 2972 2973 int index = mUniformRegister; 2974 mUniformRegister += uniform->totalRegisterCount(); 2975 2976 declareUniform(type, uniform->getSymbol(), index); 2977 2978 return index; 2979 } 2980 2981 void OutputHLSL::declareUniform(const TType &type, const TString &name, int index) 2982 { 2983 TStructure *structure = type.getStruct(); 2984 2985 if (!structure) 2986 { 2987 mActiveUniforms.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), type.getArraySize(), index)); 2988 } 2989 else 2990 { 2991 const TFieldList &fields = structure->fields(); 2992 2993 if (type.isArray()) 2994 { 2995 int elementIndex = index; 2996 2997 for (int i = 0; i < type.getArraySize(); i++) 2998 { 2999 for (size_t j = 0; j < fields.size(); j++) 3000 { 3001 const TType &fieldType = *fields[j]->type(); 3002 const TString uniformName = name + "[" + str(i) + "]." + fields[j]->name(); 3003 declareUniform(fieldType, uniformName, elementIndex); 3004 elementIndex += fieldType.totalRegisterCount(); 3005 } 3006 } 3007 } 3008 else 3009 { 3010 int fieldIndex = index; 3011 3012 for (size_t i = 0; i < fields.size(); i++) 3013 { 3014 const TType &fieldType = *fields[i]->type(); 3015 const TString uniformName = name + "." + fields[i]->name(); 3016 declareUniform(fieldType, uniformName, fieldIndex); 3017 fieldIndex += fieldType.totalRegisterCount(); 3018 } 3019 } 3020 } 3021 } 3022 3023 GLenum OutputHLSL::glVariableType(const TType &type) 3024 { 3025 if (type.getBasicType() == EbtFloat) 3026 { 3027 if (type.isScalar()) 3028 { 3029 return GL_FLOAT; 3030 } 3031 else if (type.isVector()) 3032 { 3033 switch(type.getNominalSize()) 3034 { 3035 case 2: return GL_FLOAT_VEC2; 3036 case 3: return GL_FLOAT_VEC3; 3037 case 4: return GL_FLOAT_VEC4; 3038 default: UNREACHABLE(); 3039 } 3040 } 3041 else if (type.isMatrix()) 3042 { 3043 switch(type.getNominalSize()) 3044 { 3045 case 2: return GL_FLOAT_MAT2; 3046 case 3: return GL_FLOAT_MAT3; 3047 case 4: return GL_FLOAT_MAT4; 3048 default: UNREACHABLE(); 3049 } 3050 } 3051 else UNREACHABLE(); 3052 } 3053 else if (type.getBasicType() == EbtInt) 3054 { 3055 if (type.isScalar()) 3056 { 3057 return GL_INT; 3058 } 3059 else if (type.isVector()) 3060 { 3061 switch(type.getNominalSize()) 3062 { 3063 case 2: return GL_INT_VEC2; 3064 case 3: return GL_INT_VEC3; 3065 case 4: return GL_INT_VEC4; 3066 default: UNREACHABLE(); 3067 } 3068 } 3069 else UNREACHABLE(); 3070 } 3071 else if (type.getBasicType() == EbtBool) 3072 { 3073 if (type.isScalar()) 3074 { 3075 return GL_BOOL; 3076 } 3077 else if (type.isVector()) 3078 { 3079 switch(type.getNominalSize()) 3080 { 3081 case 2: return GL_BOOL_VEC2; 3082 case 3: return GL_BOOL_VEC3; 3083 case 4: return GL_BOOL_VEC4; 3084 default: UNREACHABLE(); 3085 } 3086 } 3087 else UNREACHABLE(); 3088 } 3089 else if (type.getBasicType() == EbtSampler2D) 3090 { 3091 return GL_SAMPLER_2D; 3092 } 3093 else if (type.getBasicType() == EbtSamplerCube) 3094 { 3095 return GL_SAMPLER_CUBE; 3096 } 3097 else UNREACHABLE(); 3098 3099 return GL_NONE; 3100 } 3101 3102 GLenum OutputHLSL::glVariablePrecision(const TType &type) 3103 { 3104 if (type.getBasicType() == EbtFloat) 3105 { 3106 switch (type.getPrecision()) 3107 { 3108 case EbpHigh: return GL_HIGH_FLOAT; 3109 case EbpMedium: return GL_MEDIUM_FLOAT; 3110 case EbpLow: return GL_LOW_FLOAT; 3111 case EbpUndefined: 3112 // Should be defined as the default precision by the parser 3113 default: UNREACHABLE(); 3114 } 3115 } 3116 else if (type.getBasicType() == EbtInt) 3117 { 3118 switch (type.getPrecision()) 3119 { 3120 case EbpHigh: return GL_HIGH_INT; 3121 case EbpMedium: return GL_MEDIUM_INT; 3122 case EbpLow: return GL_LOW_INT; 3123 case EbpUndefined: 3124 // Should be defined as the default precision by the parser 3125 default: UNREACHABLE(); 3126 } 3127 } 3128 3129 // Other types (boolean, sampler) don't have a precision 3130 return GL_NONE; 3131 } 3132 3133 } 3134