Add flags to shader translator to emulate gl_BaseVertex and gl_BaseInstance

Adds support for translating gl_BaseVertex and gl_BaseInstance for implementation of
GL_ANGLE_base_vertex_base_instance.

They will only be available in WebGL 2. Since there's no gl_VertexID and
gl_InstanceID in WebGL 1. It won't be very useful to add them to WebGL
1.

Mostly follow pattern of gl_DrawID of GL_multi_draw

BUG=angleproject:3402,chromium:891861

Change-Id: Ifcd990c52d12f6814127b904e61a779b8d382e0c
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1666361
Commit-Queue: Shrek Shao <shrekshao@google.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
shrekshao 2019-06-18 17:24:54 -07:00 коммит произвёл Commit Bot
Родитель cbdf8616f9
Коммит cdab03aa93
26 изменённых файлов: 683 добавлений и 159 удалений

Просмотреть файл

@ -26,7 +26,7 @@
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 208
#define ANGLE_SH_VERSION 209
enum ShShaderSpec
{
@ -281,6 +281,9 @@ const ShCompileOptions SH_INIT_SHARED_VARIABLES = UINT64_C(1) << 41;
// http://anglebug.com/3246
const ShCompileOptions SH_FORCE_ATOMIC_VALUE_RESOLUTION = UINT64_C(1) << 42;
// Rewrite gl_BaseVertex and gl_BaseInstance as uniform int
const ShCompileOptions SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE = UINT64_C(1) << 43;
// Defines alternate strategies for implementing array index clamping.
enum ShArrayIndexClampingStrategy
{
@ -334,6 +337,7 @@ struct ShBuiltInResources
int OES_texture_3D;
int ANGLE_texture_multisample;
int ANGLE_multi_draw;
int ANGLE_base_vertex_base_instance;
// Set to 1 to enable replacing GL_EXT_draw_buffers #extension directives
// with GL_NV_draw_buffers in ESSL output. This flag can be used to emulate

Просмотреть файл

@ -52,21 +52,21 @@
"ESSL static builtins:src/compiler/translator/ParseContext_autogen.h":
"58786d2f352ee1a58d529fb7572c86a4",
"ESSL static builtins:src/compiler/translator/SymbolTable_autogen.cpp":
"a33c88c3e99fd32b914daa9991262810",
"9a0b524e9254116e1a38e3ef1b57b669",
"ESSL static builtins:src/compiler/translator/SymbolTable_autogen.h":
"bdb3c8eab0d48267a2f264e3af635e1a",
"ESSL static builtins:src/compiler/translator/builtin_function_declarations.txt":
"d0c15cb9f2ef6c0ba5cd6612470db000",
"ESSL static builtins:src/compiler/translator/builtin_symbols_hash_autogen.txt":
"03ea75bbf5fe670041c9ccd60ab4d9c3",
"e2fb536afe6669e60e45f6b5d0730631",
"ESSL static builtins:src/compiler/translator/builtin_variables.json":
"13e7c79b2c2baaf7dab12730a0509982",
"04f763459cfbd47831bec22299287e82",
"ESSL static builtins:src/compiler/translator/gen_builtin_symbols.py":
"5d5467e17ca5ed5bf9938df9a3391e6f",
"ESSL static builtins:src/compiler/translator/tree_util/BuiltIn_autogen.h":
"150682db27fba7f4d2d0d67272d67768",
"69268b2f3bda048ba8aaabe60c9b9912",
"ESSL static builtins:src/tests/compiler_tests/ImmutableString_test_autogen.cpp":
"db56dc37c3369f5c5e7c6b0ee5439ba9",
"e23f23bbd011ab29c4bb37ea69cfb3bd",
"Emulated HLSL functions:src/compiler/translator/emulated_builtin_function_data_hlsl.json":
"002ad46d144c51fe98d73478aa554ba7",
"Emulated HLSL functions:src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp":

Просмотреть файл

@ -122,10 +122,10 @@ angle_translator_sources = [
"src/compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.cpp",
"src/compiler/translator/tree_ops/DeferGlobalInitializers.cpp",
"src/compiler/translator/tree_ops/DeferGlobalInitializers.h",
"src/compiler/translator/tree_ops/EmulateGLDrawID.cpp",
"src/compiler/translator/tree_ops/EmulateGLDrawID.h",
"src/compiler/translator/tree_ops/EmulateGLFragColorBroadcast.cpp",
"src/compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h",
"src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.cpp",
"src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h",
"src/compiler/translator/tree_ops/EmulatePrecision.cpp",
"src/compiler/translator/tree_ops/EmulatePrecision.h",
"src/compiler/translator/tree_ops/ExpandIntegerPowExpressions.cpp",

Просмотреть файл

@ -622,6 +622,9 @@ enum TQualifier
EvqDrawID, // ANGLE_multi_draw
EvqBaseVertex, // ANGLE_base_vertex_base_instance
EvqBaseInstance, // ANGLE_base_vertex_base_instance
// built-ins read by fragment shader
EvqFragCoord,
EvqFrontFacing,
@ -907,6 +910,8 @@ inline const char *getQualifierString(TQualifier q)
case EvqPosition: return "Position";
case EvqPointSize: return "PointSize";
case EvqDrawID: return "DrawID";
case EvqBaseVertex: return "BaseVertex";
case EvqBaseInstance: return "BaseInstance";
case EvqFragCoord: return "FragCoord";
case EvqFrontFacing: return "FrontFacing";
case EvqPointCoord: return "PointCoord";

Просмотреть файл

@ -175,6 +175,8 @@ class CollectVariablesTraverser : public TIntermTraverser
bool mVertexIDAdded;
bool mPointSizeAdded;
bool mDrawIDAdded;
bool mBaseVertexAdded;
bool mBaseInstanceAdded;
// Vertex Shader and Geometry Shader builtins
bool mPositionAdded;
@ -233,6 +235,8 @@ CollectVariablesTraverser::CollectVariablesTraverser(
mVertexIDAdded(false),
mPointSizeAdded(false),
mDrawIDAdded(false),
mBaseVertexAdded(false),
mBaseInstanceAdded(false),
mPositionAdded(false),
mPointCoordAdded(false),
mFrontFacingAdded(false),
@ -489,6 +493,12 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
case EvqDrawID:
recordBuiltInAttributeUsed(symbol->variable(), &mDrawIDAdded);
return;
case EvqBaseVertex:
recordBuiltInAttributeUsed(symbol->variable(), &mBaseVertexAdded);
return;
case EvqBaseInstance:
recordBuiltInAttributeUsed(symbol->variable(), &mBaseInstanceAdded);
return;
case EvqLastFragData:
recordBuiltInVaryingUsed(symbol->variable(), &mLastFragDataAdded, mInputVaryings);
return;

Просмотреть файл

@ -26,8 +26,8 @@
#include "compiler/translator/tree_ops/ClampPointSize.h"
#include "compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h"
#include "compiler/translator/tree_ops/DeferGlobalInitializers.h"
#include "compiler/translator/tree_ops/EmulateGLDrawID.h"
#include "compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h"
#include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h"
#include "compiler/translator/tree_ops/EmulatePrecision.h"
#include "compiler/translator/tree_ops/FoldExpressions.h"
#include "compiler/translator/tree_ops/InitializeVariables.h"
@ -356,6 +356,17 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
}
}
const bool glBaseVertexBaseInstanceSupported =
(compileOptions & SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE) != 0u;
if (!glBaseVertexBaseInstanceSupported)
{
auto it = mExtensionBehavior.find(TExtension::ANGLE_base_vertex_base_instance);
if (it != mExtensionBehavior.end())
{
mExtensionBehavior.erase(it);
}
}
// First string is path of source file if flag is set. The actual source follows.
size_t firstSource = 0;
if (compileOptions & SH_SOURCE_PATH)
@ -631,7 +642,7 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
if (mShaderType == GL_VERTEX_SHADER &&
IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_multi_draw))
{
if ((compileOptions & SH_EMULATE_GL_DRAW_ID) != 0)
if ((compileOptions & SH_EMULATE_GL_DRAW_ID) != 0u)
{
EmulateGLDrawID(root, &mSymbolTable, &mUniforms,
shouldCollectVariables(compileOptions));
@ -642,6 +653,22 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
}
}
if (mShaderType == GL_VERTEX_SHADER &&
IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_base_vertex_base_instance))
{
if ((compileOptions & SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE) != 0u)
{
EmulateGLBaseVertex(root, &mSymbolTable, &mUniforms,
shouldCollectVariables(compileOptions));
EmulateGLBaseInstance(root, &mSymbolTable, &mUniforms,
shouldCollectVariables(compileOptions));
if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
{
return false;
}
}
}
if (mShaderType == GL_FRAGMENT_SHADER && mShaderVersion == 100 && mResources.EXT_draw_buffers &&
mResources.MaxDrawBuffers > 1 &&
IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
@ -904,17 +931,35 @@ bool TCompiler::compile(const char *const shaderStrings[],
translate(root, compileOptions, &perfDiagnostics);
}
if (mShaderType == GL_VERTEX_SHADER &&
IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_multi_draw))
if (mShaderType == GL_VERTEX_SHADER)
{
if ((compileOptions & SH_EMULATE_GL_DRAW_ID) != 0)
bool lookForDrawID =
IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_multi_draw) &&
((compileOptions & SH_EMULATE_GL_DRAW_ID) != 0u);
bool lookForBaseVertexBaseInstance =
IsExtensionEnabled(mExtensionBehavior,
TExtension::ANGLE_base_vertex_base_instance) &&
((compileOptions & SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE) != 0u);
if (lookForDrawID || lookForBaseVertexBaseInstance)
{
for (auto &uniform : mUniforms)
{
if (uniform.name == "angle_DrawID" && uniform.mappedName == "angle_DrawID")
if (lookForDrawID && uniform.name == "angle_DrawID" &&
uniform.mappedName == "angle_DrawID")
{
uniform.name = "gl_DrawID";
break;
}
else if (lookForBaseVertexBaseInstance && uniform.name == "angle_BaseVertex" &&
uniform.mappedName == "angle_BaseVertex")
{
uniform.name = "gl_BaseVertex";
}
else if (lookForBaseVertexBaseInstance &&
uniform.name == "angle_BaseInstance" &&
uniform.mappedName == "angle_BaseInstance")
{
uniform.name = "gl_BaseInstance";
}
}
}
@ -986,6 +1031,7 @@ void TCompiler::setResourceString()
<< ":NV_draw_buffers:" << mResources.NV_draw_buffers
<< ":WEBGL_debug_shader_precision:" << mResources.WEBGL_debug_shader_precision
<< ":ANGLE_multi_draw:" << mResources.ANGLE_multi_draw
<< ":ANGLE_base_vertex_base_instance:" << mResources.ANGLE_base_vertex_base_instance
<< ":MinProgramTextureGatherOffset:" << mResources.MinProgramTextureGatherOffset
<< ":MaxProgramTextureGatherOffset:" << mResources.MaxProgramTextureGatherOffset
<< ":MaxImageUnits:" << mResources.MaxImageUnits

Просмотреть файл

@ -32,7 +32,8 @@
OP(OES_texture_3D) \
OP(OVR_multiview) \
OP(OVR_multiview2) \
OP(ANGLE_multi_draw)
OP(ANGLE_multi_draw) \
OP(ANGLE_base_vertex_base_instance)
namespace sh
{

Просмотреть файл

@ -38,6 +38,7 @@ enum class TExtension
OVR_multiview,
OVR_multiview2,
ANGLE_multi_draw,
ANGLE_base_vertex_base_instance
};
enum TBehavior

Просмотреть файл

@ -93,6 +93,10 @@ void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavi
{
extBehavior[TExtension::ANGLE_multi_draw] = EBhUndefined;
}
if (resources.ANGLE_base_vertex_base_instance)
{
extBehavior[TExtension::ANGLE_base_vertex_base_instance] = EBhUndefined;
}
}
void ResetExtensionBehavior(TExtensionBehavior &extBehavior)

Просмотреть файл

@ -207,6 +207,7 @@ void InitBuiltInResources(ShBuiltInResources *resources)
resources->OES_texture_3D = 0;
resources->ANGLE_texture_multisample = 0;
resources->ANGLE_multi_draw = 0;
resources->ANGLE_base_vertex_base_instance = 0;
resources->NV_draw_buffers = 0;

Просмотреть файл

@ -978,6 +978,8 @@ constexpr const TSymbolUniqueId BuiltInId::gl_ViewportIndex;
constexpr const TSymbolUniqueId BuiltInId::gl_LayerVS;
constexpr const TSymbolUniqueId BuiltInId::gl_DrawID;
constexpr const TSymbolUniqueId BuiltInId::gl_DrawIDESSL1;
constexpr const TSymbolUniqueId BuiltInId::gl_BaseVertex;
constexpr const TSymbolUniqueId BuiltInId::gl_BaseInstance;
constexpr const TSymbolUniqueId BuiltInId::gl_NumWorkGroups;
constexpr const TSymbolUniqueId BuiltInId::gl_WorkGroupSize;
constexpr const TSymbolUniqueId BuiltInId::gl_WorkGroupID;
@ -995,7 +997,7 @@ constexpr const TSymbolUniqueId BuiltInId::gl_PositionGS;
constexpr const TSymbolUniqueId BuiltInId::gl_ViewID_OVR;
constexpr const TSymbolUniqueId BuiltInId::gl_ViewID_OVRESSL1;
const int TSymbolTable::kLastBuiltInId = 1031;
const int TSymbolTable::kLastBuiltInId = 1033;
namespace BuiltInName
{
@ -1082,6 +1084,8 @@ constexpr const ImmutableString frexp("frexp");
constexpr const ImmutableString frexp_3B3C("frexp(3B3C");
constexpr const ImmutableString fwidth("fwidth");
constexpr const ImmutableString fwidthExt("fwidth");
constexpr const ImmutableString gl_BaseInstance("gl_BaseInstance");
constexpr const ImmutableString gl_BaseVertex("gl_BaseVertex");
constexpr const ImmutableString gl_DepthRange("gl_DepthRange");
constexpr const ImmutableString gl_DepthRangeParameters("gl_DepthRangeParameters");
constexpr const ImmutableString gl_DrawID("gl_DrawID");
@ -1468,6 +1472,18 @@ constexpr const ImmutableString yuv_2_rgb("yuv_2_rgb");
namespace BuiltInVariable
{
constexpr const TVariable kVar_gl_BaseInstance(
BuiltInId::gl_BaseInstance,
BuiltInName::gl_BaseInstance,
SymbolType::BuiltIn,
TExtension::ANGLE_base_vertex_base_instance,
StaticType::Get<EbtInt, EbpHigh, EvqBaseInstance, 1, 1>());
constexpr const TVariable kVar_gl_BaseVertex(
BuiltInId::gl_BaseVertex,
BuiltInName::gl_BaseVertex,
SymbolType::BuiltIn,
TExtension::ANGLE_base_vertex_base_instance,
StaticType::Get<EbtInt, EbpHigh, EvqBaseVertex, 1, 1>());
constexpr const TVariable kVar_gl_DrawID(BuiltInId::gl_DrawID,
BuiltInName::gl_DrawID,
SymbolType::BuiltIn,
@ -2056,6 +2072,16 @@ constexpr const TVariable kVar_pt_o_3D(BuiltInId::pt_o_3D,
TExtension::UNDEFINED,
StaticType::Get<EbtUInt, EbpUndefined, EvqOut, 4, 1>());
const TVariable *gl_BaseInstance()
{
return &kVar_gl_BaseInstance;
}
const TVariable *gl_BaseVertex()
{
return &kVar_gl_BaseVertex;
}
const TVariable *gl_DrawID()
{
return &kVar_gl_DrawID;
@ -16873,6 +16899,28 @@ const TSymbol *TSymbolTable::findBuiltIn(const ImmutableString &name, int shader
}
}
}
if ((mShaderType == GL_VERTEX_SHADER) && (mResources.ANGLE_base_vertex_base_instance))
{
switch (nameHash)
{
case 0x7e695e00u:
{
if (name == BuiltInName::gl_BaseVertex)
{
return &BuiltInVariable::kVar_gl_BaseVertex;
}
break;
}
case 0x7e785b75u:
{
if (name == BuiltInName::gl_BaseInstance)
{
return &BuiltInVariable::kVar_gl_BaseInstance;
}
break;
}
}
}
if ((mResources.OVR_multiview || mResources.OVR_multiview2) &&
mShaderType != GL_COMPUTE_SHADER)
{

Просмотреть файл

@ -168,6 +168,12 @@ void TranslatorESSL::writeExtensionBehavior(ShCompileOptions compileOptions)
ASSERT((compileOptions & SH_EMULATE_GL_DRAW_ID) != 0);
continue;
}
else if (iter->first == TExtension::ANGLE_base_vertex_base_instance)
{
// Don't emit anything. This extension is emulated
ASSERT((compileOptions & SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE) != 0);
continue;
}
else
{
sink << "#extension " << GetExtensionNameString(iter->first) << " : "

Просмотреть файл

@ -1 +1 @@
81fe24b242a39d4996a5d91bf7227b6d
571dbbc401f64a7bd3d3dca5d9002ba1

Просмотреть файл

@ -704,7 +704,33 @@
}
}
}
},
"ANGLEBaseVertexBaseInstance":{
"condition": "mResources.ANGLE_base_vertex_base_instance",
"subgroups":{
"ESSL3":{
"variables":{
"gl_BaseVertex":{
"level":"ESSL3_BUILTINS",
"extension":"ANGLE_base_vertex_base_instance",
"type":{
"basic":"Int",
"precision":"High",
"qualifier":"BaseVertex"
}
},
"gl_BaseInstance":{
"level":"ESSL3_BUILTINS",
"extension":"ANGLE_base_vertex_base_instance",
"type":{
"basic":"Int",
"precision":"High",
"qualifier":"BaseInstance"
}
}
}
}
}
}
}
},

Просмотреть файл

@ -1,89 +0,0 @@
//
// Copyright 2018 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.
//
// EmulateGLDrawID is an AST traverser to convert the gl_DrawID builtin
// to a uniform int
//
#include "compiler/translator/tree_ops/EmulateGLDrawID.h"
#include "angle_gl.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/Symbol.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
#include "compiler/translator/tree_util/ReplaceVariable.h"
#include "compiler/translator/util.h"
namespace sh
{
namespace
{
constexpr const ImmutableString kEmulatedGLDrawIDName("angle_DrawID");
class FindGLDrawIDTraverser : public TIntermTraverser
{
public:
FindGLDrawIDTraverser() : TIntermTraverser(true, false, false), mVariable(nullptr) {}
const TVariable *getGLDrawIDBuiltinVariable() { return mVariable; }
protected:
void visitSymbol(TIntermSymbol *node) override
{
if (&node->variable() == BuiltInVariable::gl_DrawID() ||
&node->variable() == BuiltInVariable::gl_DrawIDESSL1())
{
mVariable = &node->variable();
}
}
private:
const TVariable *mVariable;
};
} // namespace
void EmulateGLDrawID(TIntermBlock *root,
TSymbolTable *symbolTable,
std::vector<sh::Uniform> *uniforms,
bool shouldCollect)
{
FindGLDrawIDTraverser traverser;
root->traverse(&traverser);
const TVariable *builtInVariable = traverser.getGLDrawIDBuiltinVariable();
if (builtInVariable)
{
const TType *type = StaticType::Get<EbtInt, EbpHigh, EvqUniform, 1, 1>();
const TVariable *drawID =
new TVariable(symbolTable, kEmulatedGLDrawIDName, type, SymbolType::AngleInternal);
// AngleInternal variables don't get collected
if (shouldCollect)
{
Uniform uniform;
uniform.name = kEmulatedGLDrawIDName.data();
uniform.mappedName = kEmulatedGLDrawIDName.data();
uniform.type = GLVariableType(*type);
uniform.precision = GLVariablePrecision(*type);
uniform.staticUse = symbolTable->isStaticallyUsed(*builtInVariable);
uniform.active = true;
uniform.binding = type->getLayoutQualifier().binding;
uniform.location = type->getLayoutQualifier().location;
uniform.offset = type->getLayoutQualifier().offset;
uniform.readonly = type->getMemoryQualifier().readonly;
uniform.writeonly = type->getMemoryQualifier().writeonly;
uniforms->push_back(uniform);
}
DeclareGlobalVariable(root, drawID);
ReplaceVariable(root, builtInVariable, drawID);
}
}
} // namespace sh

Просмотреть файл

@ -1,31 +0,0 @@
//
// Copyright 2018 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.
//
// EmulateGLDrawID is an AST traverser to convert the gl_DrawID builtin
// to a uniform int
//
#ifndef COMPILER_TRANSLATOR_TREEOPS_EMULATEGLDRAWID_H_
#define COMPILER_TRANSLATOR_TREEOPS_EMULATEGLDRAWID_H_
#include <GLSLANG/ShaderLang.h>
#include <vector>
#include "compiler/translator/HashNames.h"
namespace sh
{
struct Uniform;
class TIntermBlock;
class TSymbolTable;
void EmulateGLDrawID(TIntermBlock *root,
TSymbolTable *symbolTable,
std::vector<sh::Uniform> *uniforms,
bool shouldCollect);
} // namespace sh
#endif // COMPILER_TRANSLATOR_TREEOPS_EMULATEGLDRAWID_H_

Просмотреть файл

@ -0,0 +1,213 @@
//
// Copyright 2019 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.
//
// EmulateGLDrawID is an AST traverser to convert the gl_DrawID builtin
// to a uniform int
//
// EmulateGLBaseVertex is an AST traverser to convert the gl_BaseVertex builtin
// to a uniform int
//
// EmulateGLBaseInstance is an AST traverser to convert the gl_BaseInstance builtin
// to a uniform int
//
#include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h"
#include "angle_gl.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/Symbol.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
#include "compiler/translator/tree_util/ReplaceVariable.h"
#include "compiler/translator/util.h"
namespace sh
{
namespace
{
constexpr const ImmutableString kEmulatedGLDrawIDName("angle_DrawID");
class FindGLDrawIDTraverser : public TIntermTraverser
{
public:
FindGLDrawIDTraverser() : TIntermTraverser(true, false, false), mVariable(nullptr) {}
const TVariable *getGLDrawIDBuiltinVariable() { return mVariable; }
protected:
void visitSymbol(TIntermSymbol *node) override
{
if (&node->variable() == BuiltInVariable::gl_DrawID() ||
&node->variable() == BuiltInVariable::gl_DrawIDESSL1())
{
mVariable = &node->variable();
}
}
private:
const TVariable *mVariable;
};
constexpr const ImmutableString kEmulatedGLBaseVertexName("angle_BaseVertex");
class FindGLBaseVertexTraverser : public TIntermTraverser
{
public:
FindGLBaseVertexTraverser() : TIntermTraverser(true, false, false), mVariable(nullptr) {}
const TVariable *getGLBaseVertexBuiltinVariable() { return mVariable; }
protected:
void visitSymbol(TIntermSymbol *node) override
{
if (&node->variable() == BuiltInVariable::gl_BaseVertex())
{
mVariable = &node->variable();
}
}
private:
const TVariable *mVariable;
};
constexpr const ImmutableString kEmulatedGLBaseInstanceName("angle_BaseInstance");
class FindGLBaseInstanceTraverser : public TIntermTraverser
{
public:
FindGLBaseInstanceTraverser() : TIntermTraverser(true, false, false), mVariable(nullptr) {}
const TVariable *getGLBaseInstanceBuiltinVariable() { return mVariable; }
protected:
void visitSymbol(TIntermSymbol *node) override
{
if (&node->variable() == BuiltInVariable::gl_BaseInstance())
{
mVariable = &node->variable();
}
}
private:
const TVariable *mVariable;
};
} // namespace
void EmulateGLDrawID(TIntermBlock *root,
TSymbolTable *symbolTable,
std::vector<sh::Uniform> *uniforms,
bool shouldCollect)
{
FindGLDrawIDTraverser traverser;
root->traverse(&traverser);
const TVariable *builtInVariable = traverser.getGLDrawIDBuiltinVariable();
if (builtInVariable)
{
const TType *type = StaticType::Get<EbtInt, EbpHigh, EvqUniform, 1, 1>();
const TVariable *drawID =
new TVariable(symbolTable, kEmulatedGLDrawIDName, type, SymbolType::AngleInternal);
// AngleInternal variables don't get collected
if (shouldCollect)
{
Uniform uniform;
uniform.name = kEmulatedGLDrawIDName.data();
uniform.mappedName = kEmulatedGLDrawIDName.data();
uniform.type = GLVariableType(*type);
uniform.precision = GLVariablePrecision(*type);
uniform.staticUse = symbolTable->isStaticallyUsed(*builtInVariable);
uniform.active = true;
uniform.binding = type->getLayoutQualifier().binding;
uniform.location = type->getLayoutQualifier().location;
uniform.offset = type->getLayoutQualifier().offset;
uniform.readonly = type->getMemoryQualifier().readonly;
uniform.writeonly = type->getMemoryQualifier().writeonly;
uniforms->push_back(uniform);
}
DeclareGlobalVariable(root, drawID);
ReplaceVariable(root, builtInVariable, drawID);
}
}
void EmulateGLBaseVertex(TIntermBlock *root,
TSymbolTable *symbolTable,
std::vector<sh::Uniform> *uniforms,
bool shouldCollect)
{
FindGLBaseVertexTraverser traverser;
root->traverse(&traverser);
const TVariable *builtInVariable = traverser.getGLBaseVertexBuiltinVariable();
if (builtInVariable)
{
const TType *type = StaticType::Get<EbtInt, EbpHigh, EvqUniform, 1, 1>();
const TVariable *baseVertex =
new TVariable(symbolTable, kEmulatedGLBaseVertexName, type, SymbolType::AngleInternal);
// AngleInternal variables don't get collected
if (shouldCollect)
{
Uniform uniform;
uniform.name = kEmulatedGLBaseVertexName.data();
uniform.mappedName = kEmulatedGLBaseVertexName.data();
uniform.type = GLVariableType(*type);
uniform.precision = GLVariablePrecision(*type);
uniform.staticUse = symbolTable->isStaticallyUsed(*builtInVariable);
uniform.active = true;
uniform.binding = type->getLayoutQualifier().binding;
uniform.location = type->getLayoutQualifier().location;
uniform.offset = type->getLayoutQualifier().offset;
uniform.readonly = type->getMemoryQualifier().readonly;
uniform.writeonly = type->getMemoryQualifier().writeonly;
uniforms->push_back(uniform);
}
DeclareGlobalVariable(root, baseVertex);
ReplaceVariable(root, builtInVariable, baseVertex);
}
}
void EmulateGLBaseInstance(TIntermBlock *root,
TSymbolTable *symbolTable,
std::vector<sh::Uniform> *uniforms,
bool shouldCollect)
{
FindGLBaseInstanceTraverser traverser;
root->traverse(&traverser);
const TVariable *builtInVariable = traverser.getGLBaseInstanceBuiltinVariable();
if (builtInVariable)
{
const TType *type = StaticType::Get<EbtInt, EbpHigh, EvqUniform, 1, 1>();
const TVariable *baseInstance = new TVariable(symbolTable, kEmulatedGLBaseInstanceName,
type, SymbolType::AngleInternal);
// AngleInternal variables don't get collected
if (shouldCollect)
{
Uniform uniform;
uniform.name = kEmulatedGLBaseInstanceName.data();
uniform.mappedName = kEmulatedGLBaseInstanceName.data();
uniform.type = GLVariableType(*type);
uniform.precision = GLVariablePrecision(*type);
uniform.staticUse = symbolTable->isStaticallyUsed(*builtInVariable);
uniform.active = true;
uniform.binding = type->getLayoutQualifier().binding;
uniform.location = type->getLayoutQualifier().location;
uniform.offset = type->getLayoutQualifier().offset;
uniform.readonly = type->getMemoryQualifier().readonly;
uniform.writeonly = type->getMemoryQualifier().writeonly;
uniforms->push_back(uniform);
}
DeclareGlobalVariable(root, baseInstance);
ReplaceVariable(root, builtInVariable, baseInstance);
}
}
} // namespace sh

Просмотреть файл

@ -0,0 +1,47 @@
//
// Copyright 2019 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.
//
// EmulateGLDrawID is an AST traverser to convert the gl_DrawID builtin
// to a uniform int
//
// EmulateGLBaseVertex is an AST traverser to convert the gl_BaseVertex builtin
// to a uniform int
//
// EmulateGLBaseInstance is an AST traverser to convert the gl_BaseInstance builtin
// to a uniform int
//
#ifndef COMPILER_TRANSLATOR_TREEOPS_EMULATEMULTIDRAWSHADERBUILTINS_H_
#define COMPILER_TRANSLATOR_TREEOPS_EMULATEMULTIDRAWSHADERBUILTINS_H_
#include <GLSLANG/ShaderLang.h>
#include <vector>
#include "compiler/translator/HashNames.h"
namespace sh
{
struct Uniform;
class TIntermBlock;
class TSymbolTable;
void EmulateGLDrawID(TIntermBlock *root,
TSymbolTable *symbolTable,
std::vector<sh::Uniform> *uniforms,
bool shouldCollect);
void EmulateGLBaseVertex(TIntermBlock *root,
TSymbolTable *symbolTable,
std::vector<sh::Uniform> *uniforms,
bool shouldCollect);
void EmulateGLBaseInstance(TIntermBlock *root,
TSymbolTable *symbolTable,
std::vector<sh::Uniform> *uniforms,
bool shouldCollect);
} // namespace sh
#endif // COMPILER_TRANSLATOR_TREEOPS_EMULATEMULTIDRAWSHADERBUILTINS_H_

Просмотреть файл

@ -1309,28 +1309,32 @@ class BuiltInId
static constexpr const TSymbolUniqueId gl_LayerVS = TSymbolUniqueId(1013);
static constexpr const TSymbolUniqueId gl_DrawID = TSymbolUniqueId(1014);
static constexpr const TSymbolUniqueId gl_DrawIDESSL1 = TSymbolUniqueId(1015);
static constexpr const TSymbolUniqueId gl_NumWorkGroups = TSymbolUniqueId(1016);
static constexpr const TSymbolUniqueId gl_WorkGroupSize = TSymbolUniqueId(1017);
static constexpr const TSymbolUniqueId gl_WorkGroupID = TSymbolUniqueId(1018);
static constexpr const TSymbolUniqueId gl_LocalInvocationID = TSymbolUniqueId(1019);
static constexpr const TSymbolUniqueId gl_GlobalInvocationID = TSymbolUniqueId(1020);
static constexpr const TSymbolUniqueId gl_LocalInvocationIndex = TSymbolUniqueId(1021);
static constexpr const TSymbolUniqueId gl_PrimitiveIDIn = TSymbolUniqueId(1022);
static constexpr const TSymbolUniqueId gl_InvocationID = TSymbolUniqueId(1023);
static constexpr const TSymbolUniqueId gl_PrimitiveIDGS = TSymbolUniqueId(1024);
static constexpr const TSymbolUniqueId gl_LayerGS = TSymbolUniqueId(1025);
static constexpr const TSymbolUniqueId gl_PerVertex = TSymbolUniqueId(1026);
static constexpr const TSymbolUniqueId gl_in = TSymbolUniqueId(1027);
static constexpr const TSymbolUniqueId gl_PerVertexOutBlock = TSymbolUniqueId(1028);
static constexpr const TSymbolUniqueId gl_PositionGS = TSymbolUniqueId(1029);
static constexpr const TSymbolUniqueId gl_ViewID_OVR = TSymbolUniqueId(1030);
static constexpr const TSymbolUniqueId gl_ViewID_OVRESSL1 = TSymbolUniqueId(1031);
static constexpr const TSymbolUniqueId gl_BaseVertex = TSymbolUniqueId(1016);
static constexpr const TSymbolUniqueId gl_BaseInstance = TSymbolUniqueId(1017);
static constexpr const TSymbolUniqueId gl_NumWorkGroups = TSymbolUniqueId(1018);
static constexpr const TSymbolUniqueId gl_WorkGroupSize = TSymbolUniqueId(1019);
static constexpr const TSymbolUniqueId gl_WorkGroupID = TSymbolUniqueId(1020);
static constexpr const TSymbolUniqueId gl_LocalInvocationID = TSymbolUniqueId(1021);
static constexpr const TSymbolUniqueId gl_GlobalInvocationID = TSymbolUniqueId(1022);
static constexpr const TSymbolUniqueId gl_LocalInvocationIndex = TSymbolUniqueId(1023);
static constexpr const TSymbolUniqueId gl_PrimitiveIDIn = TSymbolUniqueId(1024);
static constexpr const TSymbolUniqueId gl_InvocationID = TSymbolUniqueId(1025);
static constexpr const TSymbolUniqueId gl_PrimitiveIDGS = TSymbolUniqueId(1026);
static constexpr const TSymbolUniqueId gl_LayerGS = TSymbolUniqueId(1027);
static constexpr const TSymbolUniqueId gl_PerVertex = TSymbolUniqueId(1028);
static constexpr const TSymbolUniqueId gl_in = TSymbolUniqueId(1029);
static constexpr const TSymbolUniqueId gl_PerVertexOutBlock = TSymbolUniqueId(1030);
static constexpr const TSymbolUniqueId gl_PositionGS = TSymbolUniqueId(1031);
static constexpr const TSymbolUniqueId gl_ViewID_OVR = TSymbolUniqueId(1032);
static constexpr const TSymbolUniqueId gl_ViewID_OVRESSL1 = TSymbolUniqueId(1033);
}; // class BuiltInId
namespace BuiltInVariable
{
const TVariable *gl_BaseInstance();
const TVariable *gl_BaseVertex();
const TVariable *gl_DrawID();
const TVariable *gl_DrawIDESSL1();
const TVariable *gl_FragColor();

Просмотреть файл

@ -811,6 +811,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_ANGLE_provoking_vertex"] = enableableExtension(&Extensions::provokingVertex);
map["GL_CHROMIUM_lose_context"] = enableableExtension(&Extensions::loseContextCHROMIUM);
map["GL_ANGLE_texture_external_update"] = enableableExtension(&Extensions::textureExternalUpdateANGLE);
map["GL_ANGLE_base_vertex_base_instance"] = enableableExtension(&Extensions::baseVertexBaseInstance);
// GLES1 extensinos
map["GL_OES_point_size_array"] = enableableExtension(&Extensions::pointSizeArray);
map["GL_OES_texture_cube_map"] = enableableExtension(&Extensions::textureCubeMap);

Просмотреть файл

@ -515,6 +515,9 @@ struct Extensions
// GL_ANGLE_texture_external_update
bool textureExternalUpdateANGLE = false;
// GL_ANGLE_base_vertex_base_instance
bool baseVertexBaseInstance = false;
};
struct ExtensionInfo

Просмотреть файл

@ -85,9 +85,10 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state)
mResources.ARB_texture_rectangle = extensions.textureRectangle;
mResources.OES_texture_storage_multisample_2d_array =
extensions.textureStorageMultisample2DArray;
mResources.OES_texture_3D = extensions.texture3DOES;
mResources.ANGLE_texture_multisample = extensions.textureMultisample;
mResources.ANGLE_multi_draw = extensions.multiDraw;
mResources.OES_texture_3D = extensions.texture3DOES;
mResources.ANGLE_texture_multisample = extensions.textureMultisample;
mResources.ANGLE_multi_draw = extensions.multiDraw;
mResources.ANGLE_base_vertex_base_instance = extensions.baseVertexBaseInstance;
// TODO: use shader precision caps to determine if high precision is supported?
mResources.FragmentPrecisionHigh = 1;

Просмотреть файл

@ -57,6 +57,7 @@ angle_unittests_sources = [
"../tests/compiler_tests/ConstantFoldingOverflow_test.cpp",
"../tests/compiler_tests/ConstructCompiler_test.cpp",
"../tests/compiler_tests/DebugShaderPrecision_test.cpp",
"../tests/compiler_tests/EmulateGLBaseVertexBaseInstance_test.cpp",
"../tests/compiler_tests/EmulateGLDrawID_test.cpp",
"../tests/compiler_tests/EmulateGLFragColorBroadcast_test.cpp",
"../tests/compiler_tests/ExpressionLimit_test.cpp",

Просмотреть файл

@ -0,0 +1,220 @@
//
// Copyright 2019 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.
//
// ANGLE_base_vertex_base_instance.cpp:
// Test for ANGLE_base_vertex_base_instance extension
//
#include "GLSLANG/ShaderLang.h"
#include "angle_gl.h"
#include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h"
#include "gtest/gtest.h"
#include "tests/test_utils/compiler_test.h"
using namespace sh;
class EmulateGLBaseVertexBaseInstanceTest : public MatchOutputCodeTest
{
public:
EmulateGLBaseVertexBaseInstanceTest()
: MatchOutputCodeTest(GL_VERTEX_SHADER, SH_VARIABLES, SH_GLSL_COMPATIBILITY_OUTPUT)
{
getResources()->ANGLE_base_vertex_base_instance = 1;
}
protected:
void CheckCompileFailure(const std::string &shaderString, const char *expectedError = nullptr)
{
std::string translatedCode;
std::string infoLog;
bool success = compileTestShader(GL_VERTEX_SHADER, SH_GLES2_SPEC,
SH_GLSL_COMPATIBILITY_OUTPUT, shaderString, getResources(),
SH_VARIABLES, &translatedCode, &infoLog);
EXPECT_FALSE(success);
if (expectedError)
{
EXPECT_TRUE(infoLog.find(expectedError) != std::string::npos);
}
}
};
// Check that compilation fails if the compile option to emulate gl_BaseVertex and gl_BaseInstance
// is not set
TEST_F(EmulateGLBaseVertexBaseInstanceTest, RequiresEmulation)
{
CheckCompileFailure(
"#extension GL_ANGLE_base_vertex_base_instance : require\n"
"void main() {\n"
" gl_Position = vec4(float(gl_BaseVertex), float(gl_BaseInstance), 0.0, 1.0);\n"
"}\n",
"extension is not supported");
}
// Check that compiling with emulation with gl_BaseVertex and gl_BaseInstance works with different
// shader versions
TEST_F(EmulateGLBaseVertexBaseInstanceTest, CheckCompile)
{
const std::string shaderString =
"#extension GL_ANGLE_base_vertex_base_instance : require\n"
"void main() {\n"
" gl_Position = vec4(float(gl_BaseVertex), float(gl_BaseInstance), 0.0, 1.0);\n"
"}\n";
compile("#version 300 es\n" + shaderString,
SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE);
}
// Check that gl_BaseVertex and gl_BaseInstance is properly emulated
TEST_F(EmulateGLBaseVertexBaseInstanceTest, EmulatesUniform)
{
addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT);
addOutputType(SH_ESSL_OUTPUT);
#ifdef ANGLE_ENABLE_VULKAN
addOutputType(SH_GLSL_VULKAN_OUTPUT);
#endif
#ifdef ANGLE_ENABLE_HLSL
addOutputType(SH_HLSL_3_0_OUTPUT);
addOutputType(SH_HLSL_3_0_OUTPUT);
#endif
const std::string &shaderString =
"#version 300 es\n"
"#extension GL_ANGLE_base_vertex_base_instance : require\n"
"void main() {\n"
" gl_Position = vec4(float(gl_BaseVertex), float(gl_BaseInstance), 0.0, 1.0);\n"
"}\n";
compile(shaderString, SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE);
EXPECT_TRUE(notFoundInCode("gl_BaseVertex"));
EXPECT_TRUE(foundInCode("angle_BaseVertex"));
EXPECT_TRUE(notFoundInCode("gl_BaseInstance"));
EXPECT_TRUE(foundInCode("angle_BaseInstance"));
EXPECT_TRUE(notFoundInCode("GL_ANGLE_base_vertex_base_instance"));
EXPECT_TRUE(foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, "uniform int angle_BaseVertex"));
EXPECT_TRUE(foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, "uniform int angle_BaseInstance"));
EXPECT_TRUE(foundInCode(SH_ESSL_OUTPUT, "uniform highp int angle_BaseVertex"));
EXPECT_TRUE(foundInCode(SH_ESSL_OUTPUT, "uniform highp int angle_BaseInstance"));
#ifdef ANGLE_ENABLE_VULKAN
EXPECT_TRUE(foundInCode(
SH_GLSL_VULKAN_OUTPUT,
"uniform defaultUniforms\n{\n int angle_BaseInstance;\n int angle_BaseVertex;"));
#endif
#ifdef ANGLE_ENABLE_HLSL
EXPECT_TRUE(foundInCode(SH_HLSL_3_0_OUTPUT, "uniform int angle_BaseVertex : register"));
EXPECT_TRUE(foundInCode(SH_HLSL_3_0_OUTPUT, "uniform int angle_BaseInstance : register"));
#endif
}
// Check that a user-defined "gl_BaseVertex" or "gl_BaseInstance" is not permitted
TEST_F(EmulateGLBaseVertexBaseInstanceTest, DisallowsUserDefinedGLDrawID)
{
// Check that it is not permitted without the extension
CheckCompileFailure(
"#version 300 es\n"
"uniform int gl_BaseVertex;\n"
"void main() {\n"
" gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0);\n"
"}\n",
"reserved built-in name");
CheckCompileFailure(
"#version 300 es\n"
"uniform int gl_BaseInstance;\n"
"void main() {\n"
" gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0);\n"
"}\n",
"reserved built-in name");
CheckCompileFailure(
"#version 300 es\n"
"void main() {\n"
" int gl_BaseVertex = 0;\n"
" gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0);\n"
"}\n",
"reserved built-in name");
CheckCompileFailure(
"#version 300 es\n"
"void main() {\n"
" int gl_BaseInstance = 0;\n"
" gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0);\n"
"}\n",
"reserved built-in name");
// Check that it is not permitted with the extension
CheckCompileFailure(
"#version 300 es\n"
"#extension GL_ANGLE_base_vertex_base_instance : require\n"
"uniform int gl_BaseVertex;\n"
"void main() {\n"
" gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0);\n"
"}\n",
"reserved built-in name");
CheckCompileFailure(
"#version 300 es\n"
"#extension GL_ANGLE_base_vertex_base_instance : require\n"
"uniform int gl_BaseInstance;\n"
"void main() {\n"
" gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0);\n"
"}\n",
"reserved built-in name");
CheckCompileFailure(
"#version 300 es\n"
"#extension GL_ANGLE_base_vertex_base_instance : require\n"
"void main() {\n"
" int gl_BaseVertex = 0;\n"
" gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0);\n"
"}\n",
"reserved built-in name");
CheckCompileFailure(
"#version 300 es\n"
"#extension GL_ANGLE_base_vertex_base_instance : require\n"
"void main() {\n"
" int gl_BaseInstance = 0;\n"
" gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0);\n"
"}\n",
"reserved built-in name");
}
// gl_BaseVertex and gl_BaseInstance are translated to angle_BaseVertex and angle_BaseInstance
// internally. Check that a user-defined angle_BaseVertex or angle_BaseInstance is permitted
TEST_F(EmulateGLBaseVertexBaseInstanceTest, AllowsUserDefinedANGLEDrawID)
{
addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT);
addOutputType(SH_ESSL_OUTPUT);
#ifdef ANGLE_ENABLE_VULKAN
addOutputType(SH_GLSL_VULKAN_OUTPUT);
#endif
#ifdef ANGLE_ENABLE_HLSL
addOutputType(SH_HLSL_3_0_OUTPUT);
addOutputType(SH_HLSL_3_0_OUTPUT);
#endif
const std::string &shaderString =
"#version 300 es\n"
"#extension GL_ANGLE_base_vertex_base_instance : require\n"
"uniform int angle_BaseVertex;\n"
"uniform int angle_BaseInstance;\n"
"void main() {\n"
" gl_Position = vec4(\n"
" float(angle_BaseVertex + gl_BaseVertex),\n"
" float(angle_BaseInstance + gl_BaseInstance),\n"
" 0.0, 1.0);\n"
"}\n";
compile(shaderString, SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE);
// " angle_BaseVertex" (note the space) should appear exactly twice:
// once in the declaration and once in the body.
// The user-defined angle_BaseVertex should be decorated
EXPECT_TRUE(foundInCode(" angle_BaseVertex", 2));
EXPECT_TRUE(foundInCode(" angle_BaseInstance", 2));
}

Просмотреть файл

@ -7,9 +7,9 @@
// Test for ANGLE_draw_id extension
//
#include "compiler/translator/tree_ops/EmulateGLDrawID.h"
#include "GLSLANG/ShaderLang.h"
#include "angle_gl.h"
#include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h"
#include "gtest/gtest.h"
#include "tests/test_utils/compiler_test.h"

Просмотреть файл

@ -1073,6 +1073,8 @@ TEST(ImmutableStringTest, ScriptGeneratedHashesMatch)
ASSERT_EQ(0x7e6be47fu, ImmutableString("gl_InstanceID").mangledNameHash());
ASSERT_EQ(0x7e5f8987u, ImmutableString("gl_VertexID").mangledNameHash());
ASSERT_EQ(0x7e4c3c42u, ImmutableString("gl_DrawID").mangledNameHash());
ASSERT_EQ(0x7e695e00u, ImmutableString("gl_BaseVertex").mangledNameHash());
ASSERT_EQ(0x7e785b75u, ImmutableString("gl_BaseInstance").mangledNameHash());
ASSERT_EQ(0x7e6f6de9u, ImmutableString("gl_ViewID_OVR").mangledNameHash());
ASSERT_EQ(0x7ea6cdf6u, ImmutableString("gl_MaxVaryingVectors").mangledNameHash());
ASSERT_EQ(0x7e5a0c08u, ImmutableString("gl_FragData").mangledNameHash());