Hash :
800e82c6
Author :
Date :
2021-08-23T11:05:23
Translator: Validate precisions
When declaring a variable, a struct field, function parameter etc,
there's a precision necessarily applied to the entity being declared.
AST Validation is added to enforce this. Intermediate nodes derive
their precision from these entities automatically.
Consistency of intermediate nodes is not validated. This is because AST
transformations replace a node with a transformed one, and that may not
have the same precision. Take the following code:
mediump float x = ...;
mediump float y = ...;
... x + y ...
and assume is transformed as such:
highp float driver_uniform;
... (x * driver_uniform) + y ...
The addition was originally done in mediump, but would seemingly need to
be done in highp after transformation. There are a number of options
here:
- Make sure that when nodes are replaced, the precision is unaffected.
This can be intrusive, requiring temp variables.
- Bubble up the new precision
- Accept the discrepancy
ANGLE opts for the last option, which actually respects the original
shader's intended precision for operations, even if some transformation
needs to temporarily evaluate an expression at a higher precision.
Bug: angleproject:4889
Bug: angleproject:6132
Change-Id: Ibcde3a230de159157783b1c6d5ef1cd63ceb4d8f
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3114027
Reviewed-by: Tim Van Patten <timvp@google.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
//
// Copyright 2017 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.
//
// IntermNode_util.h: High-level utilities for creating AST nodes and node hierarchies. Mostly meant
// to be used in AST transforms.
#ifndef COMPILER_TRANSLATOR_INTERMNODEUTIL_H_
#define COMPILER_TRANSLATOR_INTERMNODEUTIL_H_
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/tree_util/FindFunction.h"
namespace sh
{
class TSymbolTable;
class TVariable;
TIntermFunctionPrototype *CreateInternalFunctionPrototypeNode(const TFunction &func);
TIntermFunctionDefinition *CreateInternalFunctionDefinitionNode(const TFunction &func,
TIntermBlock *functionBody);
TIntermTyped *CreateZeroNode(const TType &type);
TIntermConstantUnion *CreateFloatNode(float value, TPrecision precision);
TIntermConstantUnion *CreateIndexNode(int index);
TIntermConstantUnion *CreateUIntNode(unsigned int value);
TIntermConstantUnion *CreateBoolNode(bool value);
TVariable *CreateTempVariable(TSymbolTable *symbolTable, const TType *type);
TVariable *CreateTempVariable(TSymbolTable *symbolTable, const TType *type, TQualifier qualifier);
TIntermSymbol *CreateTempSymbolNode(const TVariable *tempVariable);
TIntermDeclaration *CreateTempDeclarationNode(const TVariable *tempVariable);
TIntermDeclaration *CreateTempInitDeclarationNode(const TVariable *tempVariable,
TIntermTyped *initializer);
TIntermBinary *CreateTempAssignmentNode(const TVariable *tempVariable, TIntermTyped *rightNode);
TVariable *DeclareTempVariable(TSymbolTable *symbolTable,
const TType *type,
TQualifier qualifier,
TIntermDeclaration **declarationOut);
TVariable *DeclareTempVariable(TSymbolTable *symbolTable,
TIntermTyped *initializer,
TQualifier qualifier,
TIntermDeclaration **declarationOut);
std::pair<const TVariable *, const TVariable *> DeclareStructure(
TIntermBlock *root,
TSymbolTable *symbolTable,
TFieldList *fieldList,
TQualifier qualifier,
const TMemoryQualifier &memoryQualifier,
uint32_t arraySize,
const ImmutableString &structTypeName,
const ImmutableString *structInstanceName);
const TVariable *DeclareInterfaceBlock(TIntermBlock *root,
TSymbolTable *symbolTable,
TFieldList *fieldList,
TQualifier qualifier,
const TLayoutQualifier &layoutQualifier,
const TMemoryQualifier &memoryQualifier,
uint32_t arraySize,
const ImmutableString &blockTypeName,
const ImmutableString &blockVariableName);
// If the input node is nullptr, return nullptr.
// If the input node is a block node, return it.
// If the input node is not a block node, put it inside a block node and return that.
TIntermBlock *EnsureBlock(TIntermNode *node);
// Should be called from inside Compiler::compileTreeImpl() where the global level is in scope.
TIntermSymbol *ReferenceGlobalVariable(const ImmutableString &name,
const TSymbolTable &symbolTable);
// Note: this can't access desktop GLSL built-ins. Those can only be accessed directly through
// BuiltIn.h.
TIntermSymbol *ReferenceBuiltInVariable(const ImmutableString &name,
const TSymbolTable &symbolTable,
int shaderVersion);
TIntermTyped *CreateBuiltInFunctionCallNode(const char *name,
TIntermSequence *arguments,
const TSymbolTable &symbolTable,
int shaderVersion);
TIntermTyped *CreateBuiltInUnaryFunctionCallNode(const char *name,
TIntermTyped *argument,
const TSymbolTable &symbolTable,
int shaderVersion);
inline void GetSwizzleIndex(TVector<int> *indexOut) {}
template <typename T, typename... ArgsT>
void GetSwizzleIndex(TVector<int> *indexOut, T arg, ArgsT... args)
{
indexOut->push_back(arg);
GetSwizzleIndex(indexOut, args...);
}
template <typename... ArgsT>
TIntermSwizzle *CreateSwizzle(TIntermTyped *reference, ArgsT... args)
{
TVector<int> swizzleIndex;
GetSwizzleIndex(&swizzleIndex, args...);
return new TIntermSwizzle(reference, swizzleIndex);
}
} // namespace sh
#endif // COMPILER_TRANSLATOR_INTERMNODEUTIL_H_