Hash :
34130c2e
Author :
Date :
2020-11-07T15:11:14
Vulkan: Rewrite interpolateAtOffset to account for Y-flip
In order to fully suppot OES_shader_multisample_interpolation
rewrite interpolateAtOffset's offset parameter to account for
Y-coordinate flip.
Bug: angleproject:3589
Tests: dEQP-GLES31.functional.shaders.multisample_interpolation.
interpolate_at_offset.*.default_framebuffer
Change-Id: I6bf72ceb1c0466ff5d4a92b72d1ec9e2552d6f2a
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2524711
Commit-Queue: Mohan Maiya <m.maiya@samsung.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: 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 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
//
// Copyright 2020 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.
//
// Implementation of InterpolateAtOffset viewport transformation.
// See header for more info.
#include "compiler/translator/tree_ops/RewriteDfdy.h"
#include "common/angleutils.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
{
class Traverser : public TIntermTraverser
{
public:
ANGLE_NO_DISCARD static bool Apply(TCompiler *compiler,
TIntermNode *root,
const TSymbolTable &symbolTable,
TIntermBinary *flipXY,
TIntermTyped *fragRotation,
int ShaderVersion);
private:
Traverser(TIntermBinary *flipXY,
TIntermTyped *fragRotation,
TSymbolTable *symbolTable,
int shaderVersion);
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
TIntermBinary *mFlipXY = nullptr;
TIntermTyped *mFragRotation = nullptr;
const TSymbolTable *symbolTable = nullptr;
const int shaderVersion;
};
Traverser::Traverser(TIntermBinary *flipXY,
TIntermTyped *fragRotation,
TSymbolTable *symbolTable,
int shaderVersion)
: TIntermTraverser(true, false, false, symbolTable),
mFlipXY(flipXY),
mFragRotation(fragRotation),
symbolTable(symbolTable),
shaderVersion(shaderVersion)
{}
// static
bool Traverser::Apply(TCompiler *compiler,
TIntermNode *root,
const TSymbolTable &symbolTable,
TIntermBinary *flipXY,
TIntermTyped *fragRotation,
int shaderVersion)
{
TSymbolTable *pSymbolTable = const_cast<TSymbolTable *>(&symbolTable);
Traverser traverser(flipXY, fragRotation, pSymbolTable, shaderVersion);
root->traverse(&traverser);
return traverser.updateTree(compiler, root);
}
bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
{
// Decide if the node represents the call of texelFetchOffset.
if (node->getOp() != EOpCallBuiltInFunction)
{
return true;
}
ASSERT(node->getFunction()->symbolType() == SymbolType::BuiltIn);
if (node->getFunction()->name() != "interpolateAtOffset")
{
return true;
}
const TIntermSequence *sequence = node->getSequence();
ASSERT(sequence->size() == 2u);
TIntermSequence *interpolateAtOffsetArguments = new TIntermSequence();
// interpolant node
interpolateAtOffsetArguments->push_back(sequence->at(0));
// offset
TIntermTyped *offsetNode = sequence->at(1)->getAsTyped();
ASSERT(offsetNode->getType() == *(StaticType::GetBasic<EbtFloat, 2>()));
// If pre-rotation is enabled apply the transformation else just flip the Y-coordinate
TIntermTyped *rotatedXY;
if (mFragRotation)
{
rotatedXY =
new TIntermBinary(EOpMatrixTimesVector, mFragRotation->deepCopy(), mFlipXY->deepCopy());
}
else
{
rotatedXY = mFlipXY->deepCopy();
}
TIntermBinary *correctedOffset = new TIntermBinary(EOpMul, offsetNode, rotatedXY);
correctedOffset->setLine(offsetNode->getLine());
interpolateAtOffsetArguments->push_back(correctedOffset);
TIntermTyped *interpolateAtOffsetNode = CreateBuiltInFunctionCallNode(
"interpolateAtOffset", interpolateAtOffsetArguments, *symbolTable, shaderVersion);
interpolateAtOffsetNode->setLine(node->getLine());
// Replace the old node by this new node.
queueReplacement(interpolateAtOffsetNode, OriginalNode::IS_DROPPED);
return true;
}
} // anonymous namespace
bool RewriteInterpolateAtOffset(TCompiler *compiler,
TIntermNode *root,
const TSymbolTable &symbolTable,
int shaderVersion,
TIntermBinary *flipXY,
TIntermTyped *fragRotation)
{
// interpolateAtOffset is only valid in GLSL 3.0 and later.
if (shaderVersion < 300)
{
return true;
}
return Traverser::Apply(compiler, root, symbolTable, flipXY, fragRotation, shaderVersion);
}
} // namespace sh