Hash :
ca2b6e1f
Author :
Date :
2020-03-19T16:30:21
Vulkan: Implement EXT_shader_non_constant_global_initializers Enables the translator to handle non-constant global initializers in all essl versions iff the shader enables the extension to do so. Bug: angleproject:4468 Test: angle_end2end_tests --gtest_filter=ShaderNonConstGlobalInitializerTest.* Change-Id: I8f138c12fc83d2f38ff8f45ca9133222b01e4087 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2102959 Reviewed-by: Tobin Ehlis <tobine@google.com> 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
//
// Copyright 2002 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.
//
#include "compiler/translator/ValidateGlobalInitializer.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh
{
namespace
{
const int kMaxAllowedTraversalDepth = 256;
class ValidateGlobalInitializerTraverser : public TIntermTraverser
{
public:
ValidateGlobalInitializerTraverser(int shaderVersion,
bool isWebGL,
bool hasExtNonConstGlobalInitializers);
void visitSymbol(TIntermSymbol *node) override;
void visitConstantUnion(TIntermConstantUnion *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
bool visitBinary(Visit visit, TIntermBinary *node) override;
bool visitUnary(Visit visit, TIntermUnary *node) override;
bool isValid() const { return mIsValid && mMaxDepth < mMaxAllowedDepth; }
bool issueWarning() const { return mIssueWarning; }
private:
ANGLE_INLINE void onNonConstInitializerVisit(bool accept)
{
if (accept)
{
if (!mExtNonConstGlobalInitializers)
{
mIssueWarning = true;
}
}
else
{
mIsValid = false;
}
}
int mShaderVersion;
bool mIsWebGL;
bool mExtNonConstGlobalInitializers;
bool mIsValid;
bool mIssueWarning;
};
void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node)
{
// ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3):
// Global initializers must be constant expressions.
switch (node->getType().getQualifier())
{
case EvqConst:
break;
case EvqGlobal:
case EvqTemporary:
case EvqUniform:
// We allow these cases to be compatible with legacy ESSL 1.00 content.
// Implement stricter rules for ESSL 3.00 since there's no legacy content to deal
// with.
onNonConstInitializerVisit(mExtNonConstGlobalInitializers ||
((mShaderVersion < 300) && mIsWebGL));
break;
default:
mIsValid = false;
}
}
void ValidateGlobalInitializerTraverser::visitConstantUnion(TIntermConstantUnion *node)
{
// Constant unions that are not constant expressions may result from folding a ternary
// expression.
switch (node->getType().getQualifier())
{
case EvqConst:
break;
case EvqTemporary:
onNonConstInitializerVisit(mExtNonConstGlobalInitializers ||
((mShaderVersion < 300) && mIsWebGL));
break;
default:
UNREACHABLE();
}
}
bool ValidateGlobalInitializerTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
{
// Disallow calls to user-defined functions and texture lookup functions in global variable
// initializers.
// This is done simply by disabling all function calls - built-in math functions don't use
// the function call ops.
if (node->isFunctionCall())
{
onNonConstInitializerVisit(mExtNonConstGlobalInitializers);
}
return true;
}
bool ValidateGlobalInitializerTraverser::visitBinary(Visit visit, TIntermBinary *node)
{
if (node->isAssignment())
{
onNonConstInitializerVisit(mExtNonConstGlobalInitializers);
}
return true;
}
bool ValidateGlobalInitializerTraverser::visitUnary(Visit visit, TIntermUnary *node)
{
if (node->isAssignment())
{
onNonConstInitializerVisit(mExtNonConstGlobalInitializers);
}
return true;
}
ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(
int shaderVersion,
bool isWebGL,
bool hasExtNonConstGlobalInitializers)
: TIntermTraverser(true, false, false, nullptr),
mShaderVersion(shaderVersion),
mIsWebGL(isWebGL),
mExtNonConstGlobalInitializers(hasExtNonConstGlobalInitializers),
mIsValid(true),
mIssueWarning(false)
{
setMaxAllowedDepth(kMaxAllowedTraversalDepth);
}
} // namespace
bool ValidateGlobalInitializer(TIntermTyped *initializer,
int shaderVersion,
bool isWebGL,
bool hasExtNonConstGlobalInitializers,
bool *warning)
{
ValidateGlobalInitializerTraverser validate(shaderVersion, isWebGL,
hasExtNonConstGlobalInitializers);
initializer->traverse(&validate);
ASSERT(warning != nullptr);
*warning = validate.issueWarning();
return validate.isValid();
}
} // namespace sh