Hash :
c4ca12e3
Author :
Date :
2020-11-20T09:02:54
Vulkan: Support the single-sampled targets
Add support for gl_SampleMask for single-sampled targets.
When dealing with a single-sampled target, gl_SampleMask
is always be set to 0xFFFFFFFF. And when the target is
single-sampled, sample shading is disabled to enable
Bresenham line rasterization.
Bug: angleproject:3588
Tests: dEQP-GLES31.functional.shaders.sample_variables.
sample_mask.discard_half_per_pixel.*
sample_mask.discard_half_per_sample.*
sample_pos.correctness.*
sample_mask_in.bit*_per_two_samples.*
sample_mask.discard_half_per_two_samples.*
sample_mask.inverse_per_*
Change-Id: Ibb471261b8451ff01fab3dc43f2e965ae2999610
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2477909
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Mohan Maiya <m.maiya@samsung.com>
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 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
//
// 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.
//
// RewriteSampleMaskVariable.cpp: Find any references to gl_SampleMask and gl_SampleMaskIn, and
// rewrite it with ANGLESampleMask or ANGLESampleMaskIn.
//
#include "compiler/translator/tree_util/RewriteSampleMaskVariable.h"
#include "common/bitset_utils.h"
#include "common/debug.h"
#include "common/utilities.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/BuiltIn.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
#include "compiler/translator/tree_util/RunAtTheBeginningOfShader.h"
#include "compiler/translator/tree_util/RunAtTheEndOfShader.h"
namespace sh
{
namespace
{
constexpr int kMaxIndexForSampleMaskVar = 0;
constexpr int kFullSampleMask = 0xFFFFFFFF;
// Traverse the tree and collect the redeclaration and replace all non constant index references of
// gl_SampleMask or gl_SampleMaskIn with constant index references
class GLSampleMaskRelatedReferenceTraverser : public TIntermTraverser
{
public:
GLSampleMaskRelatedReferenceTraverser(const TIntermSymbol **redeclaredSymOut,
const ImmutableString &targetStr)
: TIntermTraverser(true, false, false),
mRedeclaredSym(redeclaredSymOut),
mTargetStr(targetStr)
{
*mRedeclaredSym = nullptr;
}
bool visitDeclaration(Visit visit, TIntermDeclaration *node) override
{
// If gl_SampleMask is redeclared, we need to collect its information
const TIntermSequence &sequence = *(node->getSequence());
if (sequence.size() != 1)
{
return true;
}
TIntermTyped *variable = sequence.front()->getAsTyped();
TIntermSymbol *symbol = variable->getAsSymbolNode();
if (symbol == nullptr || symbol->getName() != mTargetStr)
{
return true;
}
*mRedeclaredSym = symbol;
return true;
}
bool visitBinary(Visit visit, TIntermBinary *node) override
{
TOperator op = node->getOp();
if (op != EOpIndexDirect && op != EOpIndexIndirect)
{
return true;
}
TIntermSymbol *left = node->getLeft()->getAsSymbolNode();
if (!left)
{
return true;
}
if (left->getName() != mTargetStr)
{
return true;
}
const TConstantUnion *constIdx = node->getRight()->getConstantValue();
if (!constIdx)
{
if (node->getRight()->hasSideEffects())
{
insertStatementInParentBlock(node->getRight());
}
queueReplacementWithParent(node, node->getRight(),
CreateIndexNode(kMaxIndexForSampleMaskVar),
OriginalNode::IS_DROPPED);
}
return true;
}
private:
const TIntermSymbol **mRedeclaredSym;
const ImmutableString mTargetStr;
};
} // anonymous namespace
ANGLE_NO_DISCARD bool RewriteSampleMask(TCompiler *compiler,
TIntermBlock *root,
TSymbolTable *symbolTable,
const TIntermTyped *numSamplesUniform)
{
const TIntermSymbol *redeclaredGLSampleMask = nullptr;
GLSampleMaskRelatedReferenceTraverser indexTraverser(&redeclaredGLSampleMask,
ImmutableString("gl_SampleMask"));
root->traverse(&indexTraverser);
if (!indexTraverser.updateTree(compiler, root))
{
return false;
}
// Retrieve gl_SampleMask variable reference
// Search user redeclared it first
const TVariable *glSampleMaskVar = nullptr;
if (redeclaredGLSampleMask)
{
glSampleMaskVar = &redeclaredGLSampleMask->variable();
}
else
{
// User defined not found, find in built-in table
glSampleMaskVar = static_cast<const TVariable *>(
symbolTable->findBuiltIn(ImmutableString("gl_SampleMask"), 320));
}
if (!glSampleMaskVar)
{
return false;
}
// Current ANGLE assumes that the maximum number of samples is less than or equal to
// VK_SAMPLE_COUNT_32_BIT. So, the size of gl_SampleMask array is always one.
const unsigned int arraySizeOfSampleMask = glSampleMaskVar->getType().getOutermostArraySize();
ASSERT(arraySizeOfSampleMask == 1);
TIntermSymbol *glSampleMaskSymbol = new TIntermSymbol(glSampleMaskVar);
// if (ANGLEUniforms.numSamples == 1)
// {
// gl_SampleMask[0] = int(0xFFFFFFFF);
// }
TIntermConstantUnion *singleSampleCount = CreateUIntNode(1);
TIntermBinary *equalTo =
new TIntermBinary(EOpEqual, numSamplesUniform->deepCopy(), singleSampleCount);
TIntermBlock *trueBlock = new TIntermBlock();
TIntermBinary *sampleMaskVar = new TIntermBinary(EOpIndexDirect, glSampleMaskSymbol->deepCopy(),
CreateIndexNode(kMaxIndexForSampleMaskVar));
TIntermConstantUnion *fullSampleMask = CreateIndexNode(kFullSampleMask);
TIntermBinary *assignment = new TIntermBinary(EOpAssign, sampleMaskVar, fullSampleMask);
trueBlock->appendStatement(assignment);
TIntermIfElse *multiSampleOrNot = new TIntermIfElse(equalTo, trueBlock, nullptr);
return RunAtTheEndOfShader(compiler, root, multiSampleOrNot, symbolTable);
}
ANGLE_NO_DISCARD bool RewriteSampleMaskIn(TCompiler *compiler,
TIntermBlock *root,
TSymbolTable *symbolTable)
{
const TIntermSymbol *redeclaredGLSampleMaskIn = nullptr;
GLSampleMaskRelatedReferenceTraverser indexTraverser(&redeclaredGLSampleMaskIn,
ImmutableString("gl_SampleMaskIn"));
root->traverse(&indexTraverser);
if (!indexTraverser.updateTree(compiler, root))
{
return false;
}
// Retrieve gl_SampleMaskIn variable reference
const TVariable *glSampleMaskInVar = nullptr;
glSampleMaskInVar = static_cast<const TVariable *>(
symbolTable->findBuiltIn(ImmutableString("gl_SampleMaskIn"), 320));
if (!glSampleMaskInVar)
{
return false;
}
// Current ANGLE assumes that the maximum number of samples is less than or equal to
// VK_SAMPLE_COUNT_32_BIT. So, the size of gl_SampleMask array is always one.
const unsigned int arraySizeOfSampleMaskIn =
glSampleMaskInVar->getType().getOutermostArraySize();
ASSERT(arraySizeOfSampleMaskIn == 1);
return true;
}
} // namespace sh