gfx/angle/src/compiler/OutputHLSL.cpp

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

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

mercurial