Commit 2bfe9f6b by Olli Etuaho Committed by Commit Bot

Use function id to group functions in ParseContext

This way we can do numeric comparisons instead of string comparisons. The effect on compiler perf test scores is fairly marginal, but this reduces binary size by a few kilobytes, and there may be a larger effect on shaders calling a lot of texture functions. BUG=angleproject:2267 TEST=angle_unittests Change-Id: I077db97b16b16b70b7e18ee037e06d7450d08dc9 Reviewed-on: https://chromium-review.googlesource.com/947952 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent fccebffe
......@@ -163,6 +163,7 @@ generators = {
],
'outputs': [
'src/compiler/translator/BuiltIn_autogen.h',
'src/compiler/translator/ParseContext_autogen.h',
'src/compiler/translator/SymbolTable_autogen.cpp',
'src/tests/compiler_tests/ImmutableString_test_autogen.cpp',
],
......
......@@ -105,6 +105,7 @@
'compiler/translator/ParamType.h',
'compiler/translator/ParseContext.cpp',
'compiler/translator/ParseContext.h',
'compiler/translator/ParseContext_autogen.h',
'compiler/translator/PoolAlloc.cpp',
'compiler/translator/PoolAlloc.h',
'compiler/translator/Pragma.h',
......
......@@ -11,8 +11,10 @@
#include "common/mathutil.h"
#include "compiler/preprocessor/SourceLocation.h"
#include "compiler/translator/BuiltIn_autogen.h"
#include "compiler/translator/Declarator.h"
#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/ParseContext_autogen.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/ValidateGlobalInitializer.h"
#include "compiler/translator/ValidateSwitch.h"
......@@ -33,33 +35,6 @@ namespace
const int kWebGLMaxStructNesting = 4;
constexpr const ImmutableString kTexelFetchOffsetName("texelFetchOffset");
constexpr const ImmutableString kTextureLodOffsetName("textureLodOffset");
constexpr const ImmutableString kTextureProjLodOffsetName("textureProjLodOffset");
constexpr const ImmutableString kTextureGradOffsetName("textureGradOffset");
constexpr const ImmutableString kTextureProjGradOffsetName("textureProjGradOffset");
constexpr const ImmutableString kTextureOffsetName("textureOffset");
constexpr const ImmutableString kTextureProjOffsetName("textureProjOffset");
constexpr const ImmutableString kTextureGatherName("textureGather");
constexpr const ImmutableString kTextureGatherOffsetName("textureGatherOffset");
constexpr const std::array<ImmutableString, 8> kAtomicBuiltin = {
{ImmutableString("atomicAdd"), ImmutableString("atomicMin"), ImmutableString("atomicMax"),
ImmutableString("atomicAnd"), ImmutableString("atomicOr"), ImmutableString("atomicXor"),
ImmutableString("atomicExchange"), ImmutableString("atomicCompSwap")}};
bool IsAtomicBuiltin(const ImmutableString &name)
{
for (size_t i = 0; i < kAtomicBuiltin.size(); ++i)
{
if (name == kAtomicBuiltin[i])
{
return true;
}
}
return false;
}
bool ContainsSampler(const TStructure *structType);
bool ContainsSampler(const TType &type)
......@@ -5499,11 +5474,10 @@ TIntermBranch *TParseContext::addBranch(TOperator op,
void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
{
ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
const ImmutableString &name = functionCall->getFunction()->name();
bool isTextureGather = name == kTextureGatherName;
bool isTextureGatherOffset = name == kTextureGatherOffsetName;
if (isTextureGather || isTextureGatherOffset)
const TFunction *func = functionCall->getFunction();
if (BuiltInGroup::isTextureGather(func))
{
bool isTextureGatherOffset = BuiltInGroup::isTextureGatherOffset(func);
TIntermNode *componentNode = nullptr;
TIntermSequence *arguments = functionCall->getSequence();
ASSERT(arguments->size() >= 2u && arguments->size() <= 4u);
......@@ -5517,7 +5491,7 @@ void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
case EbtSampler2DArray:
case EbtISampler2DArray:
case EbtUSampler2DArray:
if ((isTextureGather && arguments->size() == 3u) ||
if ((!isTextureGatherOffset && arguments->size() == 3u) ||
(isTextureGatherOffset && arguments->size() == 4u))
{
componentNode = arguments->back();
......@@ -5547,14 +5521,15 @@ void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
if (componentNode->getAsTyped()->getQualifier() != EvqConst || !componentConstantUnion)
{
error(functionCall->getLine(), "Texture component must be a constant expression",
name);
func->name());
}
else
{
int component = componentConstantUnion->getIConst(0);
if (component < 0 || component > 3)
{
error(functionCall->getLine(), "Component must be in the range [0;3]", name);
error(functionCall->getLine(), "Component must be in the range [0;3]",
func->name());
}
}
}
......@@ -5564,23 +5539,21 @@ void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
{
ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
const ImmutableString &name = functionCall->getFunction()->name();
const TFunction *func = functionCall->getFunction();
TIntermNode *offset = nullptr;
TIntermSequence *arguments = functionCall->getSequence();
bool useTextureGatherOffsetConstraints = false;
if (name == kTexelFetchOffsetName || name == kTextureLodOffsetName ||
name == kTextureProjLodOffsetName || name == kTextureGradOffsetName ||
name == kTextureProjGradOffsetName)
if (BuiltInGroup::isTextureOffsetNoBias(func))
{
offset = arguments->back();
}
else if (name == kTextureOffsetName || name == kTextureProjOffsetName)
else if (BuiltInGroup::isTextureOffsetBias(func))
{
// A bias parameter might follow the offset parameter.
// A bias parameter follows the offset parameter.
ASSERT(arguments->size() >= 3);
offset = (*arguments)[2];
}
else if (name == kTextureGatherOffsetName)
else if (BuiltInGroup::isTextureGatherOffset(func))
{
ASSERT(arguments->size() >= 3u);
const TIntermTyped *sampler = arguments->front()->getAsTyped();
......@@ -5610,7 +5583,8 @@ void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
{
error(functionCall->getLine(), "Texture offset must be a constant expression", name);
error(functionCall->getLine(), "Texture offset must be a constant expression",
func->name());
}
else
{
......@@ -5640,8 +5614,8 @@ void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall)
{
ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
const ImmutableString &functionName = functionCall->getFunction()->name();
if (IsAtomicBuiltin(functionName))
const TFunction *func = functionCall->getFunction();
if (BuiltInGroup::isAtomicMemory(func))
{
TIntermSequence *arguments = functionCall->getSequence();
TIntermTyped *memNode = (*arguments)[0]->getAsTyped();
......@@ -5663,7 +5637,7 @@ void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *function
error(memNode->getLine(),
"The value passed to the mem argument of an atomic memory function does not "
"correspond to a buffer or shared variable.",
functionName);
func->name());
}
}
......@@ -5672,15 +5646,16 @@ void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *
{
ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
if (functionCall->getFunction()->isImageFunction())
const TFunction *func = functionCall->getFunction();
if (BuiltInGroup::isImage(func))
{
const ImmutableString &name = functionCall->getFunction()->name();
TIntermSequence *arguments = functionCall->getSequence();
TIntermTyped *imageNode = (*arguments)[0]->getAsTyped();
const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
if (strcmp(name.data() + 5u, "Store") == 0)
if (BuiltInGroup::isImageStore(func))
{
if (memoryQualifier.readonly)
{
......@@ -5689,7 +5664,7 @@ void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *
GetImageArgumentToken(imageNode));
}
}
else if (strcmp(name.data() + 5u, "Load") == 0)
else if (BuiltInGroup::isImageLoad(func))
{
if (memoryQualifier.writeonly)
{
......
// GENERATED FILE - DO NOT EDIT.
// Generated by gen_builtin_symbols.py using data from builtin_variables.json and
// builtin_function_declarations.txt.
//
// 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.
//
// ParseContext_autogen.h:
// Helpers for built-in related checks.
#ifndef COMPILER_TRANSLATOR_PARSECONTEXT_AUTOGEN_H_
#define COMPILER_TRANSLATOR_PARSECONTEXT_AUTOGEN_H_
namespace sh
{
namespace BuiltInGroup
{
bool isTextureOffsetNoBias(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 605 && id <= 674;
}
bool isTextureOffsetBias(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 675 && id <= 694;
}
bool isTextureGatherOffset(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 764 && id <= 777;
}
bool isTextureGather(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 740 && id <= 777;
}
bool isAtomicMemory(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 793 && id <= 808;
}
bool isImageLoad(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 821 && id <= 832;
}
bool isImageStore(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 833 && id <= 844;
}
bool isImage(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 809 && id <= 844;
}
} // namespace BuiltInGroup
} // namespace sh
#endif // COMPILER_TRANSLATOR_PARSECONTEXT_AUTOGEN_H_
......@@ -377,7 +377,7 @@ GROUP BEGIN TextureESSL300
float textureProjGrad(sampler2DShadow, vec4, vec2, vec2);
GROUP END TextureESSL300
GROUP BEGIN TextureOffsetNoBias
GROUP BEGIN TextureOffsetNoBias {"queryFunction": true}
DEFAULT METADATA {"level": "ESSL3_BUILTINS", "op": "CallBuiltInFunction"}
gvec4 textureOffset(gsampler2D, vec2, ivec2);
gvec4 textureOffset(gsampler3D, vec3, ivec3);
......@@ -409,7 +409,7 @@ GROUP BEGIN TextureOffsetNoBias
float textureProjGradOffset(sampler2DShadow, vec4, vec2, vec2, ivec2);
GROUP END TextureOffsetNoBias
GROUP BEGIN TextureOffsetBias {"condition": "shaderType == GL_FRAGMENT_SHADER"}
GROUP BEGIN TextureOffsetBias {"queryFunction": true, "condition": "shaderType == GL_FRAGMENT_SHADER"}
DEFAULT METADATA {"level": "ESSL3_BUILTINS", "op": "CallBuiltInFunction"}
gvec4 textureOffset(gsampler2D, vec2, ivec2, float);
gvec4 textureOffset(gsampler3D, vec3, ivec3, float);
......@@ -468,7 +468,7 @@ GROUP BEGIN TexelFetchMS
gvec4 texelFetch(gsampler2DMS, ivec2, int);
GROUP END TexelFetchMS
GROUP BEGIN TextureGather
GROUP BEGIN TextureGather {"queryFunction": true}
DEFAULT METADATA {"level": "ESSL3_1_BUILTINS", "op": "CallBuiltInFunction"}
gvec4 textureGather(gsampler2D, vec2);
gvec4 textureGather(gsampler2D, vec2, int);
......@@ -483,7 +483,7 @@ GROUP BEGIN TextureGather
vec4 textureGather(samplerCubeShadow, vec3);
vec4 textureGather(samplerCubeShadow, vec3, float);
GROUP BEGIN Offset
GROUP BEGIN Offset {"queryFunction": true}
gvec4 textureGatherOffset(gsampler2D, vec2, ivec2);
gvec4 textureGatherOffset(gsampler2D, vec2, ivec2, int);
gvec4 textureGatherOffset(gsampler2DArray, vec3, ivec2);
......@@ -507,7 +507,7 @@ GROUP BEGIN AtomicCounter
uint atomicCounterDecrement(atomic_uint);
GROUP END AtomicCounter
GROUP BEGIN AtomicMemory
GROUP BEGIN AtomicMemory {"queryFunction": true}
DEFAULT METADATA {"level": "ESSL3_1_BUILTINS", "op": "CallBuiltInFunction"}
uint atomicAdd(inout uint, uint);
int atomicAdd(inout int, int);
......@@ -527,15 +527,15 @@ GROUP BEGIN AtomicMemory
int atomicCompSwap(inout int, int, int);
GROUP END AtomicMemory
GROUP BEGIN Image
GROUP BEGIN Image {"queryFunction": true}
DEFAULT METADATA {"level": "ESSL3_1_BUILTINS", "op": "CallBuiltInFunction"}
GROUP BEGIN Store
GROUP BEGIN Store {"queryFunction": true}
void imageStore(gimage2D, ivec2, gvec4);
void imageStore(gimage3D, ivec3, gvec4);
void imageStore(gimage2DArray, ivec3, gvec4);
void imageStore(gimageCube, ivec3, gvec4);
GROUP END Store
GROUP BEGIN Load
GROUP BEGIN Load {"queryFunction": true}
gvec4 imageLoad(gimage2D, ivec2);
gvec4 imageLoad(gimage3D, ivec3);
gvec4 imageLoad(gimage2DArray, ivec3);
......
......@@ -183,6 +183,36 @@ const UnmangledBuiltIn *TSymbolTable::getUnmangledBuiltInForShaderVersion(const
}} // namespace sh
"""
template_parsecontext_header = """// GENERATED FILE - DO NOT EDIT.
// Generated by {script_name} using data from {variable_data_source_name} and
// {function_data_source_name}.
//
// Copyright {copyright_year} 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.
//
// ParseContext_autogen.h:
// Helpers for built-in related checks.
#ifndef COMPILER_TRANSLATOR_PARSECONTEXT_AUTOGEN_H_
#define COMPILER_TRANSLATOR_PARSECONTEXT_AUTOGEN_H_
namespace sh
{{
namespace BuiltInGroup
{{
{is_in_group_definitions}
}} // namespace BuiltInGroup
}} // namespace sh
#endif // COMPILER_TRANSLATOR_PARSECONTEXT_AUTOGEN_H_
"""
parsed_variables = None
variables_json_filename = 'builtin_variables.json'
......@@ -539,6 +569,9 @@ unmangled_function_if_statements = GroupedList()
# Code for testing that script-generated hashes match with runtime computed hashes.
script_generated_hash_tests = OrderedDict()
# Functions for testing whether a builtin belongs in group.
is_in_group_definitions = []
id_counter = 0
def hash32(str):
......@@ -738,6 +771,9 @@ def process_single_function_group(condition, group_name, group):
id_counter += 1
def process_function_group(group_name, group):
global id_counter
first_id = id_counter
condition = 'NO_CONDITION'
if 'condition' in group:
condition = group['condition']
......@@ -748,7 +784,20 @@ def process_function_group(group_name, group):
if 'subgroups' in group:
for subgroup_name, subgroup in group['subgroups'].iteritems():
process_function_group(subgroup_name, subgroup)
process_function_group(group_name + subgroup_name, subgroup)
if 'queryFunction' in group:
template_args = {
'first_id': first_id,
'last_id': id_counter - 1,
'group_name': group_name
}
template_is_in_group_definition = """bool is{group_name}(const TFunction *func)
{{
int id = func->uniqueId().get();
return id >= {first_id} && id <= {last_id};
}}"""
is_in_group_definitions.append(template_is_in_group_definition.format(**template_args))
for group_name, group in parsed_functions.iteritems():
process_function_group(group_name, group)
......@@ -891,6 +940,8 @@ output_strings = {
'function_declarations': '\n'.join(function_declarations),
'parameter_declarations': '\n'.join(sorted(parameter_declarations)),
'is_in_group_definitions': '\n'.join(is_in_group_definitions),
'variable_data_source_name': variables_json_filename,
'variable_declarations': '\n'.join(sorted(variable_declarations)),
'get_variable_declarations': '\n'.join(sorted(get_variable_declarations)),
......@@ -972,3 +1023,6 @@ with open('SymbolTable_autogen.cpp', 'wt') as outfile_cpp:
output_cpp = template_symboltable_cpp.format(**output_strings)
outfile_cpp.write(output_cpp)
with open('ParseContext_autogen.h', 'wt') as outfile_header:
output_header = template_parsecontext_header.format(**output_strings)
outfile_header.write(output_header)
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