summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp')
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp214
1 files changed, 178 insertions, 36 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp
index 05e9eb310b..a14e69e5d5 100644
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp
@@ -11,53 +11,116 @@
#include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/ExtensionGLSL.h"
#include "compiler/translator/OutputGLSL.h"
+#include "compiler/translator/RewriteTexelFetchOffset.h"
+#include "compiler/translator/RewriteUnaryMinusOperatorFloat.h"
#include "compiler/translator/VersionGLSL.h"
-TranslatorGLSL::TranslatorGLSL(sh::GLenum type,
- ShShaderSpec spec,
- ShShaderOutput output)
- : TCompiler(type, spec, output) {
+namespace sh
+{
+
+TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
+ : TCompiler(type, spec, output)
+{
}
-void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions)
+void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
+ ShCompileOptions compileOptions)
{
- if (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS)
+ if (compileOptions & SH_EMULATE_ABS_INT_FUNCTION)
+ {
+ InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(emu, getShaderType());
+ }
+
+ if (compileOptions & SH_EMULATE_ISNAN_FLOAT_FUNCTION)
{
- InitBuiltInFunctionEmulatorForGLSLWorkarounds(emu, getShaderType());
+ InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(emu, getShaderVersion());
+ }
+
+ if (compileOptions & SH_EMULATE_ATAN2_FLOAT_FUNCTION)
+ {
+ InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu);
}
int targetGLSLVersion = ShaderOutputTypeToGLSLVersion(getOutputType());
InitBuiltInFunctionEmulatorForGLSLMissingFunctions(emu, getShaderType(), targetGLSLVersion);
}
-void TranslatorGLSL::translate(TIntermNode *root, int compileOptions)
+void TranslatorGLSL::translate(TIntermBlock *root,
+ ShCompileOptions compileOptions,
+ PerformanceDiagnostics * /*perfDiagnostics*/)
{
- TInfoSinkBase& sink = getInfoSink().obj;
+ TInfoSinkBase &sink = getInfoSink().obj;
// Write GLSL version.
writeVersion(root);
- writePragma();
-
// Write extension behaviour as needed
- writeExtensionBehavior(root);
+ writeExtensionBehavior(root, compileOptions);
+
+ // Write pragmas after extensions because some drivers consider pragmas
+ // like non-preprocessor tokens.
+ writePragma(compileOptions);
+
+ // If flattening the global invariant pragma, write invariant declarations for built-in
+ // variables. It should be harmless to do this twice in the case that the shader also explicitly
+ // did this. However, it's important to emit invariant qualifiers only for those built-in
+ // variables that are actually used, to avoid affecting the behavior of the shader.
+ if ((compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) != 0 &&
+ getPragma().stdgl.invariantAll &&
+ !sh::RemoveInvariant(getShaderType(), getShaderVersion(), getOutputType(), compileOptions))
+ {
+ ASSERT(wereVariablesCollected());
+
+ switch (getShaderType())
+ {
+ case GL_VERTEX_SHADER:
+ sink << "invariant gl_Position;\n";
- bool precisionEmulation = getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
+ // gl_PointSize should be declared invariant in both ESSL 1.00 and 3.00 fragment
+ // shaders if it's statically referenced.
+ conditionallyOutputInvariantDeclaration("gl_PointSize");
+ break;
+ case GL_FRAGMENT_SHADER:
+ // The preprocessor will reject this pragma if it's used in ESSL 3.00 fragment
+ // shaders, so we can use simple logic to determine whether to declare these
+ // variables invariant.
+ conditionallyOutputInvariantDeclaration("gl_FragCoord");
+ conditionallyOutputInvariantDeclaration("gl_PointCoord");
+ break;
+ default:
+ // Currently not reached, but leave this in for future expansion.
+ ASSERT(false);
+ break;
+ }
+ }
+
+ if ((compileOptions & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0)
+ {
+ sh::RewriteTexelFetchOffset(root, getSymbolTable(), getShaderVersion());
+ }
+
+ if ((compileOptions & SH_REWRITE_FLOAT_UNARY_MINUS_OPERATOR) != 0)
+ {
+ sh::RewriteUnaryMinusOperatorFloat(root);
+ }
+
+ bool precisionEmulation =
+ getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
if (precisionEmulation)
{
- EmulatePrecision emulatePrecision(getSymbolTable(), getShaderVersion());
+ EmulatePrecision emulatePrecision(&getSymbolTable(), getShaderVersion());
root->traverse(&emulatePrecision);
emulatePrecision.updateTree();
- emulatePrecision.writeEmulationHelpers(sink, getOutputType());
+ emulatePrecision.writeEmulationHelpers(sink, getShaderVersion(), getOutputType());
}
// Write emulated built-in functions if needed.
- if (!getBuiltInFunctionEmulator().IsOutputEmpty())
+ if (!getBuiltInFunctionEmulator().isOutputEmpty())
{
sink << "// BEGIN: Generated code for built-in function emulation\n\n";
- sink << "#define webgl_emu_precision\n\n";
- getBuiltInFunctionEmulator().OutputEmulatedFunctions(sink);
+ sink << "#define emu_precision\n\n";
+ getBuiltInFunctionEmulator().outputEmulatedFunctions(sink);
sink << "// END: Generated code for built-in function emulation\n\n";
}
@@ -69,7 +132,7 @@ void TranslatorGLSL::translate(TIntermNode *root, int compileOptions)
if (getShaderType() == GL_FRAGMENT_SHADER)
{
const bool mayHaveESSL1SecondaryOutputs =
- IsExtensionEnabled(getExtensionBehavior(), "GL_EXT_blend_func_extended") &&
+ IsExtensionEnabled(getExtensionBehavior(), TExtension::EXT_blend_func_extended) &&
getShaderVersion() == 100;
const bool declareGLFragmentOutputs = IsGLSL130OrNewer(getOutputType());
@@ -132,17 +195,48 @@ void TranslatorGLSL::translate(TIntermNode *root, int compileOptions)
}
}
+ if (getShaderType() == GL_COMPUTE_SHADER && isComputeShaderLocalSizeDeclared())
+ {
+ const sh::WorkGroupSize &localSize = getComputeShaderLocalSize();
+ sink << "layout (local_size_x=" << localSize[0] << ", local_size_y=" << localSize[1]
+ << ", local_size_z=" << localSize[2] << ") in;\n";
+ }
+
+ if (getShaderType() == GL_GEOMETRY_SHADER_OES)
+ {
+ WriteGeometryShaderLayoutQualifiers(
+ sink, getGeometryShaderInputPrimitiveType(), getGeometryShaderInvocations(),
+ getGeometryShaderOutputPrimitiveType(), getGeometryShaderMaxVertices());
+ }
+
// Write translated shader.
- TOutputGLSL outputGLSL(sink,
- getArrayIndexClampingStrategy(),
- getHashFunction(),
- getNameMap(),
- getSymbolTable(),
- getShaderVersion(),
- getOutputType());
+ TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(),
+ &getSymbolTable(), getShaderType(), getShaderVersion(), getOutputType(),
+ compileOptions);
+
+ if (compileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM)
+ {
+ TName uniformName(TString("ViewID_OVR"));
+ uniformName.setInternal(true);
+ sink << "uniform int " << outputGLSL.hashName(uniformName) << ";\n";
+ }
+
root->traverse(&outputGLSL);
}
+bool TranslatorGLSL::shouldFlattenPragmaStdglInvariantAll()
+{
+ // Required when outputting to any GLSL version greater than 1.20, but since ANGLE doesn't
+ // translate to that version, return true for the next higher version.
+ return IsGLSL130OrNewer(getOutputType());
+}
+
+bool TranslatorGLSL::shouldCollectVariables(ShCompileOptions compileOptions)
+{
+ return (compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) ||
+ TCompiler::shouldCollectVariables(compileOptions);
+}
+
void TranslatorGLSL::writeVersion(TIntermNode *root)
{
TVersionGLSL versionGLSL(getShaderType(), getPragma(), getOutputType());
@@ -152,15 +246,15 @@ void TranslatorGLSL::writeVersion(TIntermNode *root)
// If there is no version directive in the shader, 110 is implied.
if (version > 110)
{
- TInfoSinkBase& sink = getInfoSink().obj;
+ TInfoSinkBase &sink = getInfoSink().obj;
sink << "#version " << version << "\n";
}
}
-void TranslatorGLSL::writeExtensionBehavior(TIntermNode *root)
+void TranslatorGLSL::writeExtensionBehavior(TIntermNode *root, ShCompileOptions compileOptions)
{
- TInfoSinkBase& sink = getInfoSink().obj;
- const TExtensionBehavior& extBehavior = getExtensionBehavior();
+ TInfoSinkBase &sink = getInfoSink().obj;
+ const TExtensionBehavior &extBehavior = getExtensionBehavior();
for (const auto &iter : extBehavior)
{
if (iter.second == EBhUndefined)
@@ -168,21 +262,58 @@ void TranslatorGLSL::writeExtensionBehavior(TIntermNode *root)
continue;
}
- // For GLSL output, we don't need to emit most extensions explicitly,
- // but some we need to translate.
- if (iter.first == "GL_EXT_shader_texture_lod")
+ if (getOutputType() == SH_GLSL_COMPATIBILITY_OUTPUT)
+ {
+ // For GLSL output, we don't need to emit most extensions explicitly,
+ // but some we need to translate in GL compatibility profile.
+ if (iter.first == TExtension::EXT_shader_texture_lod)
+ {
+ sink << "#extension GL_ARB_shader_texture_lod : " << GetBehaviorString(iter.second)
+ << "\n";
+ }
+
+ if (iter.first == TExtension::EXT_draw_buffers)
+ {
+ sink << "#extension GL_ARB_draw_buffers : " << GetBehaviorString(iter.second)
+ << "\n";
+ }
+
+ if (iter.first == TExtension::OES_geometry_shader)
+ {
+ sink << "#extension GL_ARB_geometry_shader4 : " << GetBehaviorString(iter.second)
+ << "\n";
+ }
+ }
+
+ const bool isMultiview = (iter.first == TExtension::OVR_multiview);
+ if (isMultiview && getShaderType() == GL_VERTEX_SHADER &&
+ (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u)
{
- sink << "#extension GL_ARB_shader_texture_lod : " << getBehaviorString(iter.second)
- << "\n";
+ // Emit the NV_viewport_array2 extension in a vertex shader if the
+ // SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set and the OVR_multiview(2)
+ // extension is requested.
+ sink << "#extension GL_NV_viewport_array2 : require\n";
}
}
// GLSL ES 3 explicit location qualifiers need to use an extension before GLSL 330
- if (getShaderVersion() >= 300 && getOutputType() < SH_GLSL_330_CORE_OUTPUT)
+ if (getShaderVersion() >= 300 && getOutputType() < SH_GLSL_330_CORE_OUTPUT &&
+ getShaderType() != GL_COMPUTE_SHADER)
{
sink << "#extension GL_ARB_explicit_attrib_location : require\n";
}
+ // Need to enable gpu_shader5 to have index constant sampler array indexing
+ if (getOutputType() != SH_ESSL_OUTPUT && getOutputType() < SH_GLSL_400_CORE_OUTPUT &&
+ getShaderVersion() == 100)
+ {
+ // Don't use "require" on to avoid breaking WebGL 1 on drivers that silently
+ // support index constant sampler array indexing, but don't have the extension or
+ // on drivers that don't have the extension at all as it would break WebGL 1 for
+ // some users.
+ sink << "#extension GL_ARB_gpu_shader5 : enable\n";
+ }
+
TExtensionGLSL extensionGLSL(getOutputType());
root->traverse(&extensionGLSL);
@@ -195,3 +326,14 @@ void TranslatorGLSL::writeExtensionBehavior(TIntermNode *root)
sink << "#extension " << ext << " : require\n";
}
}
+
+void TranslatorGLSL::conditionallyOutputInvariantDeclaration(const char *builtinVaryingName)
+{
+ if (isVaryingDefined(builtinVaryingName))
+ {
+ TInfoSinkBase &sink = getInfoSink().obj;
+ sink << "invariant " << builtinVaryingName << ";\n";
+ }
+}
+
+} // namespace sh