From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../translator/tree_ops/ClampIndirectIndices.cpp | 136 +++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_ops/ClampIndirectIndices.cpp (limited to 'gfx/angle/checkout/src/compiler/translator/tree_ops/ClampIndirectIndices.cpp') diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/ClampIndirectIndices.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/ClampIndirectIndices.cpp new file mode 100644 index 0000000000..bd1997a21d --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/ClampIndirectIndices.cpp @@ -0,0 +1,136 @@ +// +// Copyright 2021 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. +// +// ClampIndirectIndices.h: Add clamp to the indirect indices used on arrays. +// + +#include "compiler/translator/tree_ops/ClampIndirectIndices.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ +namespace +{ +// Traverser that finds EOpIndexIndirect nodes and applies a clamp to their right-hand side +// expression. +class ClampIndirectIndicesTraverser : public TIntermTraverser +{ + public: + ClampIndirectIndicesTraverser(TCompiler *compiler, TSymbolTable *symbolTable) + : TIntermTraverser(true, false, false, symbolTable), mCompiler(compiler) + {} + + bool visitBinary(Visit visit, TIntermBinary *node) override + { + ASSERT(visit == PreVisit); + + // Only interested in EOpIndexIndirect nodes. + if (node->getOp() != EOpIndexIndirect) + { + return true; + } + + // Apply the transformation to the left and right nodes + bool valid = ClampIndirectIndices(mCompiler, node->getLeft(), mSymbolTable); + ASSERT(valid); + valid = ClampIndirectIndices(mCompiler, node->getRight(), mSymbolTable); + ASSERT(valid); + + // Generate clamp(right, 0, N), where N is the size of the array being indexed minus 1. If + // the array is runtime-sized, the length() method is called on it. + const TType &leftType = node->getLeft()->getType(); + const TType &rightType = node->getRight()->getType(); + + // Don't clamp indirect indices on unsized arrays in buffer blocks. They are covered by the + // relevant robust access behavior of the backend. + if (leftType.isUnsizedArray()) + { + return true; + } + + // On GLSL es 100, clamp is only defined for float, so float arguments are used. + // + // However, float clamp is unconditionally emitted to workaround driver bugs with integer + // clamp on Qualcomm. http://crbug.com/1217167 + // + // const bool useFloatClamp = mCompiler->getShaderVersion() == 100; + const bool useFloatClamp = true; + + TIntermConstantUnion *zero = createClampValue(0, useFloatClamp); + TIntermTyped *max; + + if (leftType.isArray()) + { + max = createClampValue(static_cast(leftType.getOutermostArraySize()) - 1, + useFloatClamp); + } + else + { + ASSERT(leftType.isVector() || leftType.isMatrix()); + max = createClampValue(leftType.getNominalSize() - 1, useFloatClamp); + } + + TIntermTyped *index = node->getRight(); + // If the index node is not an int (i.e. it's a uint), or a float (if using float clamp), + // cast it. + const TBasicType requiredBasicType = useFloatClamp ? EbtFloat : EbtInt; + if (rightType.getBasicType() != requiredBasicType) + { + const TType *clampType = useFloatClamp ? StaticType::GetBasic() + : StaticType::GetBasic(); + TIntermSequence constructorArgs = {index}; + index = TIntermAggregate::CreateConstructor(*clampType, &constructorArgs); + } + + // min(gl_PointSize, maxPointSize) + TIntermSequence args; + args.push_back(index); + args.push_back(zero); + args.push_back(max); + TIntermTyped *clamped = + CreateBuiltInFunctionCallNode("clamp", &args, *mSymbolTable, useFloatClamp ? 100 : 300); + + // Cast back to int if float clamp was used. + if (useFloatClamp) + { + TIntermSequence constructorArgs = {clamped}; + clamped = TIntermAggregate::CreateConstructor(*StaticType::GetBasic(), + &constructorArgs); + } + + // Replace the right node (the index) with the clamped result. + queueReplacementWithParent(node, node->getRight(), clamped, OriginalNode::IS_DROPPED); + + // Don't recurse as left and right nodes are already processed. + return false; + } + + private: + TIntermConstantUnion *createClampValue(int value, bool useFloat) + { + if (useFloat) + { + return CreateFloatNode(static_cast(value), EbpHigh); + } + return CreateIndexNode(value); + } + + TCompiler *mCompiler; +}; +} // anonymous namespace + +bool ClampIndirectIndices(TCompiler *compiler, TIntermNode *root, TSymbolTable *symbolTable) +{ + ClampIndirectIndicesTraverser traverser(compiler, symbolTable); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +} // namespace sh -- cgit v1.2.3