Commit 233b3342 by Geoff Lang

Enable needed extensions in generated GLSL shaders and call them when possible.

BUG=angleproject:1044 Change-Id: Ife94d2258fb912974aa97484a0e30f289dd96734 Reviewed-on: https://chromium-review.googlesource.com/278324Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 5b58cae2
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
'compiler/translator/EmulatePrecision.cpp', 'compiler/translator/EmulatePrecision.cpp',
'compiler/translator/EmulatePrecision.h', 'compiler/translator/EmulatePrecision.h',
'compiler/translator/ExtensionBehavior.h', 'compiler/translator/ExtensionBehavior.h',
'compiler/translator/ExtensionGLSL.cpp',
'compiler/translator/ExtensionGLSL.h',
'compiler/translator/FlagStd140Structs.cpp', 'compiler/translator/FlagStd140Structs.cpp',
'compiler/translator/FlagStd140Structs.h', 'compiler/translator/FlagStd140Structs.h',
'compiler/translator/ForLoopUnroll.cpp', 'compiler/translator/ForLoopUnroll.cpp',
......
...@@ -49,117 +49,141 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator ...@@ -49,117 +49,141 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
const TType *float2 = TCache::getType(EbtFloat, 2); const TType *float2 = TCache::getType(EbtFloat, 2);
const TType *uint1 = TCache::getType(EbtUInt); const TType *uint1 = TCache::getType(EbtUInt);
// clang-format off
emu->addEmulatedFunction(EOpPackSnorm2x16, float2, emu->addEmulatedFunction(EOpPackSnorm2x16, float2,
"uint webgl_packSnorm2x16_emu(vec2 v)\n" "uint webgl_packSnorm2x16_emu(vec2 v)\n"
"{\n" "{\n"
" int x = int(round(clamp(v.x, -1.0, 1.0) * 32767.0));\n" " #if GL_ARB_shading_language_packing\n"
" int y = int(round(clamp(v.y, -1.0, 1.0) * 32767.0));\n" " return packSnorm2x16(v);\n"
" return uint((y << 16) | (x & 0xFFFF));\n" " #else\n"
" int x = int(round(clamp(v.x, -1.0, 1.0) * 32767.0));\n"
" int y = int(round(clamp(v.y, -1.0, 1.0) * 32767.0));\n"
" return uint((y << 16) | (x & 0xFFFF));\n"
" #endif\n"
"}\n"); "}\n");
emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1, emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
"float webgl_fromSnorm(uint x)\n" "#if !GL_ARB_shading_language_packing\n"
"{\n" " float webgl_fromSnorm(uint x)\n"
" int xi = (int(x) & 0x7FFF) - (int(x) & 0x8000);\n" " {\n"
" return clamp(float(xi) / 32767.0, -1.0, 1.0);\n" " int xi = (int(x) & 0x7FFF) - (int(x) & 0x8000);\n"
"}\n" " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
" }\n"
"#endif\n"
"\n" "\n"
"vec2 webgl_unpackSnorm2x16_emu(uint u)\n" "vec2 webgl_unpackSnorm2x16_emu(uint u)\n"
"{\n" "{\n"
" uint y = (u >> 16);\n" " #if GL_ARB_shading_language_packing\n"
" uint x = u;\n" " return unpackSnorm2x16(u);\n"
" return vec2(webgl_fromSnorm(x), webgl_fromSnorm(y));\n" " #else\n"
" uint y = (u >> 16);\n"
" uint x = u;\n"
" return vec2(webgl_fromSnorm(x), webgl_fromSnorm(y));\n"
" #endif\n"
"}\n"); "}\n");
// Functions uint webgl_f32tof16(float val) and float webgl_f16tof32(uint val) are // Functions uint webgl_f32tof16(float val) and float webgl_f16tof32(uint val) are
// based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL". // based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL".
emu->addEmulatedFunction(EOpPackHalf2x16, float2, emu->addEmulatedFunction(EOpPackHalf2x16, float2,
"uint webgl_f32tof16(float val)\n" "#if !GL_ARB_shading_language_packing\n"
"{\n" " uint webgl_f32tof16(float val)\n"
" uint f32 = floatBitsToUint(val);\n"
" uint f16 = 0u;\n"
" uint sign = (f32 >> 16) & 0x8000u;\n"
" int exponent = int((f32 >> 23) & 0xFFu) - 127;\n"
" uint mantissa = f32 & 0x007FFFFFu;\n"
" if (exponent == 128)\n"
" {\n" " {\n"
" // Infinity or NaN\n" " uint f32 = floatBitsToUint(val);\n"
" // NaN bits that are masked out by 0x3FF get discarded.\n" " uint f16 = 0u;\n"
" // This can turn some NaNs to infinity, but this is allowed by the spec.\n" " uint sign = (f32 >> 16) & 0x8000u;\n"
" f16 = sign | (0x1Fu << 10);\n" " int exponent = int((f32 >> 23) & 0xFFu) - 127;\n"
" f16 |= (mantissa & 0x3FFu);\n" " uint mantissa = f32 & 0x007FFFFFu;\n"
" }\n" " if (exponent == 128)\n"
" else if (exponent > 15)\n" " {\n"
" {\n" " // Infinity or NaN\n"
" // Overflow - flush to Infinity\n" " // NaN bits that are masked out by 0x3FF get discarded.\n"
" f16 = sign | (0x1Fu << 10);\n" " // This can turn some NaNs to infinity, but this is allowed by the spec.\n"
" }\n" " f16 = sign | (0x1Fu << 10);\n"
" else if (exponent > -15)\n" " f16 |= (mantissa & 0x3FFu);\n"
" {\n" " }\n"
" // Representable value\n" " else if (exponent > 15)\n"
" exponent += 15;\n" " {\n"
" mantissa >>= 13;\n" " // Overflow - flush to Infinity\n"
" f16 = sign | uint(exponent << 10) | mantissa;\n" " f16 = sign | (0x1Fu << 10);\n"
" }\n" " }\n"
" else\n" " else if (exponent > -15)\n"
" {\n" " {\n"
" f16 = sign;\n" " // Representable value\n"
" exponent += 15;\n"
" mantissa >>= 13;\n"
" f16 = sign | uint(exponent << 10) | mantissa;\n"
" }\n"
" else\n"
" {\n"
" f16 = sign;\n"
" }\n"
" return f16;\n"
" }\n" " }\n"
" return f16;\n" "#endif\n"
"}\n"
"\n" "\n"
"uint webgl_packHalf2x16_emu(vec2 v)\n" "uint webgl_packHalf2x16_emu(vec2 v)\n"
"{\n" "{\n"
" uint x = webgl_f32tof16(v.x);\n" " #if GL_ARB_shading_language_packing\n"
" uint y = webgl_f32tof16(v.y);\n" " return packHalf2x16(v);\n"
" return (y << 16) | x;\n" " #else\n"
" uint x = webgl_f32tof16(v.x);\n"
" uint y = webgl_f32tof16(v.y);\n"
" return (y << 16) | x;\n"
" #endif\n"
"}\n"); "}\n");
emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1, emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1,
"float webgl_f16tof32(uint val)\n" "#if !GL_ARB_shading_language_packing\n"
"{\n" " float webgl_f16tof32(uint val)\n"
" uint sign = (val & 0x8000u) << 16;\n"
" int exponent = int((val & 0x7C00u) >> 10);\n"
" uint mantissa = val & 0x03FFu;\n"
" float f32 = 0.0;\n"
" if(exponent == 0)\n"
" {\n" " {\n"
" if (mantissa != 0u)\n" " uint sign = (val & 0x8000u) << 16;\n"
" int exponent = int((val & 0x7C00u) >> 10);\n"
" uint mantissa = val & 0x03FFu;\n"
" float f32 = 0.0;\n"
" if(exponent == 0)\n"
" {\n" " {\n"
" const float scale = 1.0 / (1 << 24);\n" " if (mantissa != 0u)\n"
" f32 = scale * mantissa;\n" " {\n"
" const float scale = 1.0 / (1 << 24);\n"
" f32 = scale * mantissa;\n"
" }\n"
" }\n"
" else if (exponent == 31)\n"
" {\n"
" return uintBitsToFloat(sign | 0x7F800000u | mantissa);\n"
" }\n"
" else\n"
" {\n"
" exponent -= 15;\n"
" float scale;\n"
" if(exponent < 0)\n"
" {\n"
" scale = 1.0 / (1 << -exponent);\n"
" }\n"
" else\n"
" {\n"
" scale = 1 << exponent;\n"
" }\n"
" float decimal = 1.0 + float(mantissa) / float(1 << 10);\n"
" f32 = scale * decimal;\n"
" }\n" " }\n"
" }\n"
" else if (exponent == 31)\n"
" {\n"
" return uintBitsToFloat(sign | 0x7F800000u | mantissa);\n"
" }\n"
" else\n"
" {\n"
" exponent -= 15;\n"
" float scale;\n"
" if(exponent < 0)\n"
" {\n"
" scale = 1.0 / (1 << -exponent);\n"
" }\n"
" else\n"
" {\n"
" scale = 1 << exponent;\n"
" }\n"
" float decimal = 1.0 + float(mantissa) / float(1 << 10);\n"
" f32 = scale * decimal;\n"
" }\n"
"\n" "\n"
" if (sign != 0u)\n" " if (sign != 0u)\n"
" {\n" " {\n"
" f32 = -f32;\n" " f32 = -f32;\n"
" }\n" " }\n"
"\n" "\n"
" return f32;\n" " return f32;\n"
"}\n" " }\n"
"#endif\n"
"\n" "\n"
"vec2 webgl_unpackHalf2x16_emu(uint u)\n" "vec2 webgl_unpackHalf2x16_emu(uint u)\n"
"{\n" "{\n"
" uint y = (u >> 16);\n" " #if GL_ARB_shading_language_packing\n"
" uint x = u & 0xFFFFu;\n" " return unpackHalf2x16(u);\n"
" return vec2(webgl_f16tof32(x), webgl_f16tof32(y));\n" " #else\n"
" uint y = (u >> 16);\n"
" uint x = u & 0xFFFFu;\n"
" return vec2(webgl_f16tof32(x), webgl_f16tof32(y));\n"
" #endif\n"
"}\n"); "}\n");
// clang-format on
} }
} }
//
// Copyright (c) 2015 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.
//
// ExtensionGLSL.cpp: Implements the TExtensionGLSL class that tracks GLSL extension requirements
// of shaders.
#include "compiler/translator/ExtensionGLSL.h"
#include "compiler/translator/VersionGLSL.h"
TExtensionGLSL::TExtensionGLSL(ShShaderOutput output)
: TIntermTraverser(true, false, false), mTargetVersion(ShaderOutputTypeToGLSLVersion(output))
{
}
const std::set<std::string> &TExtensionGLSL::getEnabledExtensions() const
{
return mEnabledExtensions;
}
const std::set<std::string> &TExtensionGLSL::getRequiredExtensions() const
{
return mRequiredExtensions;
}
bool TExtensionGLSL::visitUnary(Visit, TIntermUnary *node)
{
checkOperator(node);
return true;
}
bool TExtensionGLSL::visitAggregate(Visit, TIntermAggregate *node)
{
checkOperator(node);
return true;
}
void TExtensionGLSL::checkOperator(TIntermOperator *node)
{
if (mTargetVersion < GLSL_VERSION_130)
{
return;
}
switch (node->getOp())
{
case EOpAbs:
break;
case EOpSign:
break;
case EOpMix:
break;
case EOpFloatBitsToInt:
case EOpFloatBitsToUint:
case EOpIntBitsToFloat:
case EOpUintBitsToFloat:
if (mTargetVersion < GLSL_VERSION_330)
{
// Bit conversion functions cannot be emulated.
mRequiredExtensions.insert("GL_ARB_shader_bit_encoding");
}
break;
case EOpPackSnorm2x16:
case EOpPackHalf2x16:
case EOpUnpackSnorm2x16:
case EOpUnpackHalf2x16:
if (mTargetVersion < GLSL_VERSION_420)
{
mEnabledExtensions.insert("GL_ARB_shading_language_packing");
if (mTargetVersion < GLSL_VERSION_330)
{
// floatBitsToUint and uintBitsToFloat are needed to emulate
// packHalf2x16 and unpackHalf2x16 respectively and cannot be
// emulated themselves.
mRequiredExtensions.insert("GL_ARB_shader_bit_encoding");
}
}
break;
case EOpPackUnorm2x16:
case EOpUnpackUnorm2x16:
if (mTargetVersion < GLSL_VERSION_410)
{
mEnabledExtensions.insert("GL_ARB_shading_language_packing");
}
break;
default:
break;
}
}
//
// Copyright (c) 2015 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.
//
// ExtensionGLSL.h: Defines the TExtensionGLSL class that tracks GLSL extension requirements of
// shaders.
#ifndef COMPILER_TRANSLATOR_EXTENSIONGLSL_H_
#define COMPILER_TRANSLATOR_EXTENSIONGLSL_H_
#include <set>
#include <string>
#include "compiler/translator/IntermNode.h"
// Traverses the intermediate tree to determine which GLSL extensions are required
// to support the shader.
class TExtensionGLSL : public TIntermTraverser
{
public:
TExtensionGLSL(ShShaderOutput output);
const std::set<std::string> &getEnabledExtensions() const;
const std::set<std::string> &getRequiredExtensions() const;
bool visitUnary(Visit visit, TIntermUnary *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
private:
void checkOperator(TIntermOperator *node);
int mTargetVersion;
std::set<std::string> mEnabledExtensions;
std::set<std::string> mRequiredExtensions;
};
#endif // COMPILER_TRANSLATOR_EXTENSIONGLSL_H_
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "angle_gl.h" #include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" #include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
#include "compiler/translator/EmulatePrecision.h" #include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/ExtensionGLSL.h"
#include "compiler/translator/OutputGLSL.h" #include "compiler/translator/OutputGLSL.h"
#include "compiler/translator/VersionGLSL.h" #include "compiler/translator/VersionGLSL.h"
...@@ -39,7 +40,7 @@ void TranslatorGLSL::translate(TIntermNode *root, int compileOptions) ...@@ -39,7 +40,7 @@ void TranslatorGLSL::translate(TIntermNode *root, int compileOptions)
writePragma(); writePragma();
// Write extension behaviour as needed // Write extension behaviour as needed
writeExtensionBehavior(); writeExtensionBehavior(root);
bool precisionEmulation = getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision; bool precisionEmulation = getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
...@@ -156,19 +157,35 @@ void TranslatorGLSL::writeVersion(TIntermNode *root) ...@@ -156,19 +157,35 @@ void TranslatorGLSL::writeVersion(TIntermNode *root)
} }
} }
void TranslatorGLSL::writeExtensionBehavior() { void TranslatorGLSL::writeExtensionBehavior(TIntermNode *root)
{
TInfoSinkBase& sink = getInfoSink().obj; TInfoSinkBase& sink = getInfoSink().obj;
const TExtensionBehavior& extBehavior = getExtensionBehavior(); const TExtensionBehavior& extBehavior = getExtensionBehavior();
for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); for (const auto &iter : extBehavior)
iter != extBehavior.end(); ++iter) { {
if (iter->second == EBhUndefined) if (iter.second == EBhUndefined)
{
continue; continue;
}
// For GLSL output, we don't need to emit most extensions explicitly, // For GLSL output, we don't need to emit most extensions explicitly,
// but some we need to translate. // but some we need to translate.
if (iter->first == "GL_EXT_shader_texture_lod") { if (iter.first == "GL_EXT_shader_texture_lod")
sink << "#extension GL_ARB_shader_texture_lod : " {
<< getBehaviorString(iter->second) << "\n"; sink << "#extension GL_ARB_shader_texture_lod : " << getBehaviorString(iter.second)
<< "\n";
} }
} }
TExtensionGLSL extensionGLSL(getOutputType());
root->traverse(&extensionGLSL);
for (const auto &ext : extensionGLSL.getEnabledExtensions())
{
sink << "#extension " << ext << " : enable\n";
}
for (const auto &ext : extensionGLSL.getRequiredExtensions())
{
sink << "#extension " << ext << " : require\n";
}
} }
...@@ -21,7 +21,7 @@ class TranslatorGLSL : public TCompiler ...@@ -21,7 +21,7 @@ class TranslatorGLSL : public TCompiler
private: private:
void writeVersion(TIntermNode *root); void writeVersion(TIntermNode *root);
void writeExtensionBehavior(); void writeExtensionBehavior(TIntermNode *root);
}; };
#endif // COMPILER_TRANSLATOR_TRANSLATORGLSL_H_ #endif // COMPILER_TRANSLATOR_TRANSLATORGLSL_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment