diff options
Diffstat (limited to 'Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp')
-rw-r--r-- | Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp | 421 |
1 files changed, 332 insertions, 89 deletions
diff --git a/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp index 57e99d2..69b8c26 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -33,8 +33,11 @@ OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, tr mUsesTexture2D_bias = false; mUsesTexture2DProj = false; mUsesTexture2DProj_bias = false; + mUsesTexture2DProjLod = false; + mUsesTexture2DLod = false; mUsesTextureCube = false; mUsesTextureCube_bias = false; + mUsesTextureCubeLod = false; mUsesDepthRange = false; mUsesFragCoord = false; mUsesPointCoord = false; @@ -42,9 +45,12 @@ OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, tr mUsesPointSize = false; mUsesXor = false; mUsesMod1 = false; - mUsesMod2 = false; - mUsesMod3 = false; - mUsesMod4 = false; + mUsesMod2v = false; + mUsesMod2f = false; + mUsesMod3v = false; + mUsesMod3f = false; + mUsesMod4v = false; + mUsesMod4f = false; mUsesFaceforward1 = false; mUsesFaceforward2 = false; mUsesFaceforward3 = false; @@ -61,7 +67,10 @@ OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, tr mUsesEqualBVec2 = false; mUsesEqualBVec3 = false; mUsesEqualBVec4 = false; - mUsesAtan2 = false; + mUsesAtan2_1 = false; + mUsesAtan2_2 = false; + mUsesAtan2_3 = false; + mUsesAtan2_4 = false; mScopeDepth = 0; @@ -133,7 +142,7 @@ void OutputHLSL::header() { if (mReferencedUniforms.find(name.c_str()) != mReferencedUniforms.end()) { - uniforms += "uniform " + typeString(type) + " " + decorate(name) + arrayString(type) + ";\n"; + uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) + ";\n"; } } else if (qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn) @@ -182,7 +191,7 @@ void OutputHLSL::header() if (mUsesFragCoord) { - out << "uniform float4 dx_Viewport;\n" + out << "uniform float4 dx_Coord;\n" "uniform float2 dx_Depth;\n"; } @@ -196,11 +205,25 @@ void OutputHLSL::header() out << uniforms; out << "\n"; + // The texture fetch functions "flip" the Y coordinate in one way or another. This is because textures are stored + // according to the OpenGL convention, i.e. (0, 0) is "bottom left", rather than the D3D convention where (0, 0) + // is "top left". Since the HLSL texture fetch functions expect textures to be stored according to the D3D + // convention, the Y coordinate passed to these functions is adjusted to compensate. + // + // The simplest case is texture2D where the mapping is Y -> 1-Y, which maps [0, 1] -> [1, 0]. + // + // The texture2DProj functions are more complicated because the projection divides by either Z or W. For the vec3 + // case, the mapping is Y -> Z-Y or Y/Z -> 1-Y/Z, which again maps [0, 1] -> [1, 0]. + // + // For cube textures the mapping is Y -> -Y, which maps [-1, 1] -> [1, -1]. This is not sufficient on its own for the + // +Y and -Y faces, which are now on the "wrong sides" of the cube. This is compensated for by exchanging the + // +Y and -Y faces everywhere else throughout the code. + if (mUsesTexture2D) { out << "float4 gl_texture2D(sampler2D s, float2 t)\n" "{\n" - " return tex2D(s, t);\n" + " return tex2D(s, float2(t.x, 1 - t.y));\n" "}\n" "\n"; } @@ -209,7 +232,7 @@ void OutputHLSL::header() { out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n" "{\n" - " return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n" + " return tex2Dbias(s, float4(t.x, 1 - t.y, 0, bias));\n" "}\n" "\n"; } @@ -218,12 +241,12 @@ void OutputHLSL::header() { out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n" "{\n" - " return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n" + " return tex2Dproj(s, float4(t.x, t.z - t.y, 0, t.z));\n" "}\n" "\n" "float4 gl_texture2DProj(sampler2D s, float4 t)\n" "{\n" - " return tex2Dproj(s, t);\n" + " return tex2Dproj(s, float4(t.x, t.w - t.y, t.z, t.w));\n" "}\n" "\n"; } @@ -232,12 +255,12 @@ void OutputHLSL::header() { out << "float4 gl_texture2DProj(sampler2D s, float3 t, float bias)\n" "{\n" - " return tex2Dbias(s, float4(t.x / t.z, t.y / t.z, 0, bias));\n" + " return tex2Dbias(s, float4(t.x / t.z, 1 - (t.y / t.z), 0, bias));\n" "}\n" "\n" "float4 gl_texture2DProj(sampler2D s, float4 t, float bias)\n" "{\n" - " return tex2Dbias(s, float4(t.x / t.w, t.y / t.w, 0, bias));\n" + " return tex2Dbias(s, float4(t.x / t.w, 1 - (t.y / t.w), 0, bias));\n" "}\n" "\n"; } @@ -246,7 +269,7 @@ void OutputHLSL::header() { out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" "{\n" - " return texCUBE(s, t);\n" + " return texCUBE(s, float3(t.x, -t.y, t.z));\n" "}\n" "\n"; } @@ -255,7 +278,7 @@ void OutputHLSL::header() { out << "float4 gl_textureCube(samplerCUBE s, float3 t, float bias)\n" "{\n" - " return texCUBEbias(s, float4(t.x, t.y, t.z, bias));\n" + " return texCUBEbias(s, float4(t.x, -t.y, t.z, bias));\n" "}\n" "\n"; } @@ -283,7 +306,7 @@ void OutputHLSL::header() { if (mReferencedUniforms.find(name.c_str()) != mReferencedUniforms.end()) { - uniforms += "uniform " + typeString(type) + " " + decorate(name) + arrayString(type) + ";\n"; + uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) + ";\n"; } } else if (qualifier == EvqAttribute) @@ -331,6 +354,84 @@ void OutputHLSL::header() "\n"; out << uniforms; out << "\n"; + + // The texture fetch functions "flip" the Y coordinate in one way or another. This is because textures are stored + // according to the OpenGL convention, i.e. (0, 0) is "bottom left", rather than the D3D convention where (0, 0) + // is "top left". Since the HLSL texture fetch functions expect textures to be stored according to the D3D + // convention, the Y coordinate passed to these functions is adjusted to compensate. + // + // The simplest case is texture2D where the mapping is Y -> 1-Y, which maps [0, 1] -> [1, 0]. + // + // The texture2DProj functions are more complicated because the projection divides by either Z or W. For the vec3 + // case, the mapping is Y -> Z-Y or Y/Z -> 1-Y/Z, which again maps [0, 1] -> [1, 0]. + // + // For cube textures the mapping is Y -> -Y, which maps [-1, 1] -> [1, -1]. This is not sufficient on its own for the + // +Y and -Y faces, which are now on the "wrong sides" of the cube. This is compensated for by exchanging the + // +Y and -Y faces everywhere else throughout the code. + + if (mUsesTexture2D) + { + out << "float4 gl_texture2D(sampler2D s, float2 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x, 1 - t.y, 0, 0));\n" + "}\n" + "\n"; + } + + if (mUsesTexture2DLod) + { + out << "float4 gl_texture2DLod(sampler2D s, float2 t, float lod)\n" + "{\n" + " return tex2Dlod(s, float4(t.x, 1 - t.y, 0, lod));\n" + "}\n" + "\n"; + } + + if (mUsesTexture2DProj) + { + out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.z, 1 - t.y / t.z, 0, 0));\n" + "}\n" + "\n" + "float4 gl_texture2DProj(sampler2D s, float4 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.w, 1 - t.y / t.w, 0, 0));\n" + "}\n" + "\n"; + } + + if (mUsesTexture2DProjLod) + { + out << "float4 gl_texture2DProjLod(sampler2D s, float3 t, float lod)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.z, 1 - t.y / t.z, 0, lod));\n" + "}\n" + "\n" + "float4 gl_texture2DProjLod(sampler2D s, float4 t, float lod)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.w, 1 - t.y / t.w, 0, lod));\n" + "}\n" + "\n"; + } + + if (mUsesTextureCube) + { + out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" + "{\n" + " return texCUBElod(s, float4(t.x, -t.y, t.z, 0));\n" + "}\n" + "\n"; + } + + if (mUsesTextureCubeLod) + { + out << "float4 gl_textureCubeLod(samplerCUBE s, float3 t, float lod)\n" + "{\n" + " return texCUBElod(s, float4(t.x, -t.y, t.z, lod));\n" + "}\n" + "\n"; + } } if (mUsesFragCoord) @@ -384,8 +485,17 @@ void OutputHLSL::header() "}\n" "\n"; } - - if (mUsesMod2) + + if (mUsesMod2v) + { + out << "float2 mod(float2 x, float2 y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"; + } + + if (mUsesMod2f) { out << "float2 mod(float2 x, float y)\n" "{\n" @@ -394,7 +504,16 @@ void OutputHLSL::header() "\n"; } - if (mUsesMod3) + if (mUsesMod3v) + { + out << "float3 mod(float3 x, float3 y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"; + } + + if (mUsesMod3f) { out << "float3 mod(float3 x, float y)\n" "{\n" @@ -403,7 +522,16 @@ void OutputHLSL::header() "\n"; } - if (mUsesMod4) + if (mUsesMod4v) + { + out << "float4 mod(float4 x, float4 y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"; + } + + if (mUsesMod4f) { out << "float4 mod(float4 x, float y)\n" "{\n" @@ -578,7 +706,7 @@ void OutputHLSL::header() "}\n"; } - if (mUsesAtan2) + if (mUsesAtan2_1) { out << "float atanyx(float y, float x)\n" "{\n" @@ -586,6 +714,39 @@ void OutputHLSL::header() " return atan2(y, x);\n" "}\n"; } + + if (mUsesAtan2_2) + { + out << "float2 atanyx(float2 y, float2 x)\n" + "{\n" + " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" + " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" + " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n" + "}\n"; + } + + if (mUsesAtan2_3) + { + out << "float3 atanyx(float3 y, float3 x)\n" + "{\n" + " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" + " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" + " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" + " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n" + "}\n"; + } + + if (mUsesAtan2_4) + { + out << "float4 atanyx(float4 y, float4 x)\n" + "{\n" + " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" + " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" + " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" + " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n" + " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n" + "}\n"; + } } void OutputHLSL::visitSymbol(TIntermSymbol *node) @@ -634,17 +795,22 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) if (qualifier == EvqUniform) { mReferencedUniforms.insert(name.c_str()); + out << decorateUniform(name, node->getType()); } else if (qualifier == EvqAttribute) { mReferencedAttributes.insert(name.c_str()); + out << decorate(name); } else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut || qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn) { mReferencedVaryings.insert(name.c_str()); + out << decorate(name); + } + else + { + out << decorate(name); } - - out << decorate(name); } } @@ -902,8 +1068,6 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) { - TInfoSinkBase &out = mBody; - switch (node->getOp()) { case EOpNegative: outputTriplet(visit, "(-", "", ")"); break; @@ -968,7 +1132,7 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) case EOpLength: outputTriplet(visit, "length(", "", ")"); break; case EOpNormalize: outputTriplet(visit, "normalize(", "", ")"); break; case EOpDFdx: outputTriplet(visit, "ddx(", "", ")"); break; - case EOpDFdy: outputTriplet(visit, "ddy(", "", ")"); break; + case EOpDFdy: outputTriplet(visit, "(-ddy(", "", "))"); break; case EOpFwidth: outputTriplet(visit, "fwidth(", "", ")"); break; case EOpAny: outputTriplet(visit, "any(", "", ")"); break; case EOpAll: outputTriplet(visit, "all(", "", ")"); break; @@ -980,7 +1144,6 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { - ShShaderType shaderType = mContext.shaderType; TInfoSinkBase &out = mBody; switch (node->getOp()) @@ -989,6 +1152,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { if (mInsideFunction) { + outputLineDirective(node->getLine()); out << "{\n"; mScopeDepth++; @@ -1005,6 +1169,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++) { + outputLineDirective((*sit)->getLine()); + if (isSingleStatement(*sit)) { mUnfoldSelect->traverse(*sit); @@ -1017,6 +1183,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) if (mInsideFunction) { + outputLineDirective(node->getEndLine()); out << "}\n"; mScopeDepth--; @@ -1118,7 +1285,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) return false; } break; - case EOpComma: outputTriplet(visit, "", ", ", ""); break; + case EOpComma: outputTriplet(visit, "(", ", ", ")"); break; case EOpFunction: { TString name = TFunction::unmangleName(node->getName()); @@ -1145,6 +1312,11 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) if (symbol) { + if (symbol->getType().getStruct()) + { + addConstructor(symbol->getType(), scopedStruct(symbol->getType().getTypeName()), NULL); + } + out << argumentString(symbol); if (i < arguments.size() - 1) @@ -1157,13 +1329,16 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) sequence.erase(sequence.begin()); - out << ")\n" - "{\n"; - + out << ")\n"; + + outputLineDirective(node->getLine()); + out << "{\n"; + mInsideFunction = true; } else if (visit == PostVisit) { + outputLineDirective(node->getEndLine()); out << "}\n"; mInsideFunction = false; @@ -1226,15 +1401,33 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) } else if (name == "texture2DLod") { - UNIMPLEMENTED(); // Requires the vertex shader texture sampling extension + if (node->getSequence().size() == 3) + { + mUsesTexture2DLod = true; + } + else UNREACHABLE(); + + out << "gl_texture2DLod("; } else if (name == "texture2DProjLod") { - UNIMPLEMENTED(); // Requires the vertex shader texture sampling extension + if (node->getSequence().size() == 3) + { + mUsesTexture2DProjLod = true; + } + else UNREACHABLE(); + + out << "gl_texture2DProjLod("; } else if (name == "textureCubeLod") { - UNIMPLEMENTED(); // Requires the vertex shader texture sampling extension + if (node->getSequence().size() == 3) + { + mUsesTextureCubeLod = true; + } + else UNREACHABLE(); + + out << "gl_textureCubeLod("; } else UNREACHABLE(); } @@ -1322,12 +1515,17 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpVectorNotEqual: outputTriplet(visit, "(", " != ", ")"); break; case EOpMod: { - switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) // Number of components in the first argument + // We need to look at the number of components in both arguments + switch (node->getSequence()[0]->getAsTyped()->getNominalSize() * 10 + + node->getSequence()[1]->getAsTyped()->getNominalSize()) { - case 1: mUsesMod1 = true; break; - case 2: mUsesMod2 = true; break; - case 3: mUsesMod3 = true; break; - case 4: mUsesMod4 = true; break; + case 11: mUsesMod1 = true; break; + case 22: mUsesMod2v = true; break; + case 21: mUsesMod2f = true; break; + case 33: mUsesMod3v = true; break; + case 31: mUsesMod3f = true; break; + case 44: mUsesMod4v = true; break; + case 41: mUsesMod4f = true; break; default: UNREACHABLE(); } @@ -1337,7 +1535,14 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break; case EOpAtan: ASSERT(node->getSequence().size() == 2); // atan(x) is a unary operator - mUsesAtan2 = true; + switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) + { + case 1: mUsesAtan2_1 = true; break; + case 2: mUsesAtan2_2 = true; break; + case 3: mUsesAtan2_3 = true; break; + case 4: mUsesAtan2_4 = true; break; + default: UNREACHABLE(); + } outputTriplet(visit, "atanyx(", ", ", ")"); break; case EOpMin: outputTriplet(visit, "min(", ", ", ")"); break; @@ -1378,7 +1583,7 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) if (node->usesTernaryOperator()) { - out << "t" << mUnfoldSelect->getTemporaryIndex(); + out << "s" << mUnfoldSelect->getNextTemporaryIndex(); } else // if/else statement { @@ -1388,23 +1593,30 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) node->getCondition()->traverse(this); - out << ")\n" - "{\n"; + out << ")\n"; + + outputLineDirective(node->getLine()); + out << "{\n"; if (node->getTrueBlock()) { node->getTrueBlock()->traverse(this); } + outputLineDirective(node->getLine()); out << ";}\n"; if (node->getFalseBlock()) { - out << "else\n" - "{\n"; + out << "else\n"; + + outputLineDirective(node->getFalseBlock()->getLine()); + out << "{\n"; + outputLineDirective(node->getFalseBlock()->getLine()); node->getFalseBlock()->traverse(this); + outputLineDirective(node->getFalseBlock()->getLine()); out << ";}\n"; } } @@ -1428,27 +1640,14 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) if (node->getType() == ELoopDoWhile) { - out << "do\n" - "{\n"; + out << "{do\n"; + + outputLineDirective(node->getLine()); + out << "{\n"; } else { - if (node->getInit()) - { - mUnfoldSelect->traverse(node->getInit()); - } - - if (node->getCondition()) - { - mUnfoldSelect->traverse(node->getCondition()); - } - - if (node->getExpression()) - { - mUnfoldSelect->traverse(node->getExpression()); - } - - out << "for("; + out << "{for("; if (node->getInit()) { @@ -1469,8 +1668,10 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) node->getExpression()->traverse(this); } - out << ")\n" - "{\n"; + out << ")\n"; + + outputLineDirective(node->getLine()); + out << "{\n"; } if (node->getBody()) @@ -1478,18 +1679,20 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) node->getBody()->traverse(this); } - out << "}\n"; + outputLineDirective(node->getLine()); + out << ";}\n"; if (node->getType() == ELoopDoWhile) { + outputLineDirective(node->getCondition()->getLine()); out << "while(\n"; node->getCondition()->traverse(this); - out << ")"; + out << ");"; } - out << ";\n"; + out << "}\n"; return false; } @@ -1500,9 +1703,9 @@ bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node) switch (node->getFlowOp()) { - case EOpKill: outputTriplet(visit, "discard", "", ""); break; - case EOpBreak: outputTriplet(visit, "break", "", ""); break; - case EOpContinue: outputTriplet(visit, "continue", "", ""); break; + case EOpKill: outputTriplet(visit, "discard;\n", "", ""); break; + case EOpBreak: outputTriplet(visit, "break;\n", "", ""); break; + case EOpContinue: outputTriplet(visit, "continue;\n", "", ""); break; case EOpReturn: if (visit == PreVisit) { @@ -1517,7 +1720,10 @@ bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node) } else if (visit == PostVisit) { - out << ";\n"; + if (node->getExpression()) + { + out << ";\n"; + } } break; default: UNREACHABLE(); @@ -1669,7 +1875,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) if (comparator == EOpLessThan) { - int iterations = (limit - initial + 1) / increment; + int iterations = (limit - initial) / increment; if (iterations <= 255) { @@ -1678,8 +1884,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) while (iterations > 0) { - int remainder = (limit - initial + 1) % increment; - int clampedLimit = initial + increment * std::min(255, iterations) - 1 - remainder; + int clampedLimit = initial + increment * std::min(255, iterations); // for(int index = initial; index < clampedLimit; index += increment) @@ -1697,15 +1902,18 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) index->traverse(this); out << " += "; out << increment; - out << ")\n" - "{\n"; + out << ")\n"; + + outputLineDirective(node->getLine()); + out << "{\n"; if (node->getBody()) { node->getBody()->traverse(this); } - out << "}\n"; + outputLineDirective(node->getLine()); + out << ";}\n"; initial += 255 * increment; iterations -= 255; @@ -1737,6 +1945,22 @@ void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TStr } } +void OutputHLSL::outputLineDirective(int line) +{ + if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0)) + { + mBody << "\n"; + mBody << "#line " << line; + + if (mContext.sourcePath) + { + mBody << " \"" << mContext.sourcePath << "\""; + } + + mBody << "\n"; + } +} + TString OutputHLSL::argumentString(const TIntermSymbol *symbol) { TQualifier qualifier = symbol->getQualifier(); @@ -1839,6 +2063,8 @@ TString OutputHLSL::typeString(const TType &type) return "sampler2D"; case EbtSamplerCube: return "samplerCUBE"; + case EbtSamplerExternalOES: + return "sampler2D"; } } @@ -1880,6 +2106,11 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI return; // Nameless structures don't have constructors } + if (type.getStruct() && mStructNames.find(decorate(name)) != mStructNames.end()) + { + return; // Already added + } + TType ctorType = type; ctorType.clearArrayness(); ctorType.setPrecision(EbpHigh); @@ -1890,14 +2121,7 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI typedef std::vector<TType> ParameterArray; ParameterArray ctorParameters; - if (parameters) - { - for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++) - { - ctorParameters.push_back((*parameter)->getAsTyped()->getType()); - } - } - else if (type.getStruct()) + if (type.getStruct()) { mStructNames.insert(decorate(name)); @@ -1926,6 +2150,13 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI ctorParameters.push_back(*fields[i].type); } } + else if (parameters) + { + for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++) + { + ctorParameters.push_back((*parameter)->getAsTyped()->getType()); + } + } else UNREACHABLE(); TString constructor; @@ -2182,13 +2413,25 @@ TString OutputHLSL::structLookup(const TString &typeName) TString OutputHLSL::decorate(const TString &string) { - if (string.substr(0, 3) != "gl_" && string.substr(0, 3) != "dx_") + if (string.compare(0, 3, "gl_") != 0 && string.compare(0, 3, "dx_") != 0) { return "_" + string; } - else + + return string; +} + +TString OutputHLSL::decorateUniform(const TString &string, const TType &type) +{ + if (type.isArray()) { - return string; + return "ar_" + string; // Allows identifying arrays of size 1 } + else if (type.getBasicType() == EbtSamplerExternalOES) + { + return "ex_" + string; + } + + return decorate(string); } } |