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