Commit b3070102 by jchen10 Committed by Commit Bot

Add SH_REMOVE_DYNAMIC_INDEXING_OF_SWIZZLED_VECTOR

This is a workaround for the webgl2 conformance test case WebglConformance_conformance2_glsl3_vector_dynamic_indexing_swizzled_lvalue. Dynamic indexing of swizzled lvalue like "v.zyx[i] = 0.0" is problematic on various platforms. This removes the indexing by translating it this way: void dyn_index_write_vec3(inout vec3 base, in int index, in float value){ switch (index) { case (0): (base[0] = value); return ; case (1): (base[1] = value); return ; case (2): (base[2] = value); return ; default: break; } if ((index < 0)) { (base[0] = value); return ; } { (base[2] = value); } } ... dyn_index_write_vec3(v.zyx, i, 0.0); ... Bug: chromium:709351 Change-Id: I971b38eb404209b56e6764af1063878c078a7e88 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1869109 Commit-Queue: Jie A Chen <jie.a.chen@intel.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 0b779a7c
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
// Version number for shader translation API. // Version number for shader translation API.
// It is incremented every time the API changes. // It is incremented every time the API changes.
#define ANGLE_SH_VERSION 217 #define ANGLE_SH_VERSION 218
enum ShShaderSpec enum ShShaderSpec
{ {
...@@ -308,6 +308,9 @@ const ShCompileOptions SH_USE_OLD_REWRITE_STRUCT_SAMPLERS = UINT64_C(1) << 47; ...@@ -308,6 +308,9 @@ const ShCompileOptions SH_USE_OLD_REWRITE_STRUCT_SAMPLERS = UINT64_C(1) << 47;
// when angle_BaseVertex is available. // when angle_BaseVertex is available.
const ShCompileOptions SH_ADD_BASE_VERTEX_TO_VERTEX_ID = UINT64_C(1) << 48; const ShCompileOptions SH_ADD_BASE_VERTEX_TO_VERTEX_ID = UINT64_C(1) << 48;
// This works around the dynamic lvalue indexing of swizzled vectors on various platforms.
const ShCompileOptions SH_REMOVE_DYNAMIC_INDEXING_OF_SWIZZLED_VECTOR = UINT64_C(1) << 49;
// Defines alternate strategies for implementing array index clamping. // Defines alternate strategies for implementing array index clamping.
enum ShArrayIndexClampingStrategy enum ShArrayIndexClampingStrategy
{ {
......
...@@ -361,6 +361,12 @@ struct FeaturesGL : FeatureSetBase ...@@ -361,6 +361,12 @@ struct FeaturesGL : FeatureSetBase
"When GL_PRIMITIVE_RESTART_FIXED_INDEX is not available, emulate it with " "When GL_PRIMITIVE_RESTART_FIXED_INDEX is not available, emulate it with "
"GL_PRIMITIVE_RESTART and glPrimitiveRestartIndex.", "GL_PRIMITIVE_RESTART and glPrimitiveRestartIndex.",
&members, "http://anglebug.com/3997"}; &members, "http://anglebug.com/3997"};
// Dynamic indexing of swizzled l-values doesn't work correctly on various platforms.
Feature removeDynamicIndexingOfSwizzledVector = {
"remove_dynamic_indexing_of_swizzled_vector", FeatureCategory::OpenGLWorkarounds,
"Dynamic indexing of swizzled l-values doesn't work correctly on various platforms.",
&members, "http://crbug.com/709351"};
}; };
inline FeaturesGL::FeaturesGL() = default; inline FeaturesGL::FeaturesGL() = default;
......
...@@ -152,6 +152,8 @@ angle_translator_sources = [ ...@@ -152,6 +152,8 @@ angle_translator_sources = [
"src/compiler/translator/tree_ops/RegenerateStructNames.h", "src/compiler/translator/tree_ops/RegenerateStructNames.h",
"src/compiler/translator/tree_ops/RemoveArrayLengthMethod.cpp", "src/compiler/translator/tree_ops/RemoveArrayLengthMethod.cpp",
"src/compiler/translator/tree_ops/RemoveArrayLengthMethod.h", "src/compiler/translator/tree_ops/RemoveArrayLengthMethod.h",
"src/compiler/translator/tree_ops/RemoveDynamicIndexing.cpp",
"src/compiler/translator/tree_ops/RemoveDynamicIndexing.h",
"src/compiler/translator/tree_ops/RemoveInvariantDeclaration.cpp", "src/compiler/translator/tree_ops/RemoveInvariantDeclaration.cpp",
"src/compiler/translator/tree_ops/RemoveInvariantDeclaration.h", "src/compiler/translator/tree_ops/RemoveInvariantDeclaration.h",
"src/compiler/translator/tree_ops/RemovePow.cpp", "src/compiler/translator/tree_ops/RemovePow.cpp",
...@@ -276,8 +278,6 @@ angle_translator_hlsl_sources = [ ...@@ -276,8 +278,6 @@ angle_translator_hlsl_sources = [
"src/compiler/translator/tree_ops/AddDefaultReturnStatements.h", "src/compiler/translator/tree_ops/AddDefaultReturnStatements.h",
"src/compiler/translator/tree_ops/ArrayReturnValueToOutParameter.cpp", "src/compiler/translator/tree_ops/ArrayReturnValueToOutParameter.cpp",
"src/compiler/translator/tree_ops/ArrayReturnValueToOutParameter.h", "src/compiler/translator/tree_ops/ArrayReturnValueToOutParameter.h",
"src/compiler/translator/tree_ops/RemoveDynamicIndexing.cpp",
"src/compiler/translator/tree_ops/RemoveDynamicIndexing.h",
"src/compiler/translator/tree_ops/RemoveSwitchFallThrough.cpp", "src/compiler/translator/tree_ops/RemoveSwitchFallThrough.cpp",
"src/compiler/translator/tree_ops/RemoveSwitchFallThrough.h", "src/compiler/translator/tree_ops/RemoveSwitchFallThrough.h",
"src/compiler/translator/tree_ops/RewriteElseBlocks.cpp", "src/compiler/translator/tree_ops/RewriteElseBlocks.cpp",
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "compiler/translator/tree_ops/PruneNoOps.h" #include "compiler/translator/tree_ops/PruneNoOps.h"
#include "compiler/translator/tree_ops/RegenerateStructNames.h" #include "compiler/translator/tree_ops/RegenerateStructNames.h"
#include "compiler/translator/tree_ops/RemoveArrayLengthMethod.h" #include "compiler/translator/tree_ops/RemoveArrayLengthMethod.h"
#include "compiler/translator/tree_ops/RemoveDynamicIndexing.h"
#include "compiler/translator/tree_ops/RemoveInvariantDeclaration.h" #include "compiler/translator/tree_ops/RemoveInvariantDeclaration.h"
#include "compiler/translator/tree_ops/RemovePow.h" #include "compiler/translator/tree_ops/RemovePow.h"
#include "compiler/translator/tree_ops/RemoveUnreferencedVariables.h" #include "compiler/translator/tree_ops/RemoveUnreferencedVariables.h"
...@@ -893,6 +894,14 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, ...@@ -893,6 +894,14 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
} }
} }
if (compileOptions & SH_REMOVE_DYNAMIC_INDEXING_OF_SWIZZLED_VECTOR)
{
if (!sh::RemoveDynamicIndexingOfSwizzledVector(this, root, &getSymbolTable(), nullptr))
{
return false;
}
}
return true; return true;
} }
......
...@@ -105,7 +105,8 @@ bool TranslatorHLSL::translate(TIntermBlock *root, ...@@ -105,7 +105,8 @@ bool TranslatorHLSL::translate(TIntermBlock *root,
if (!shouldRunLoopAndIndexingValidation(compileOptions)) if (!shouldRunLoopAndIndexingValidation(compileOptions))
{ {
// HLSL doesn't support dynamic indexing of vectors and matrices. // HLSL doesn't support dynamic indexing of vectors and matrices.
if (!RemoveDynamicIndexing(this, root, &getSymbolTable(), perfDiagnostics)) if (!RemoveDynamicIndexingOfNonSSBOVectorOrMatrix(this, root, &getSymbolTable(),
perfDiagnostics))
{ {
return false; return false;
} }
......
...@@ -26,6 +26,8 @@ namespace sh ...@@ -26,6 +26,8 @@ namespace sh
namespace namespace
{ {
using DynamicIndexingNodeMatcher = std::function<bool(TIntermBinary *)>;
const TType *kIndexType = StaticType::Get<EbtInt, EbpHigh, EvqIn, 1, 1>(); const TType *kIndexType = StaticType::Get<EbtInt, EbpHigh, EvqIn, 1, 1>();
constexpr const ImmutableString kBaseName("base"); constexpr const ImmutableString kBaseName("base");
...@@ -261,7 +263,8 @@ TIntermFunctionDefinition *GetIndexFunctionDefinition(const TType &type, ...@@ -261,7 +263,8 @@ TIntermFunctionDefinition *GetIndexFunctionDefinition(const TType &type,
class RemoveDynamicIndexingTraverser : public TLValueTrackingTraverser class RemoveDynamicIndexingTraverser : public TLValueTrackingTraverser
{ {
public: public:
RemoveDynamicIndexingTraverser(TSymbolTable *symbolTable, RemoveDynamicIndexingTraverser(DynamicIndexingNodeMatcher &&matcher,
TSymbolTable *symbolTable,
PerformanceDiagnostics *perfDiagnostics); PerformanceDiagnostics *perfDiagnostics);
bool visitBinary(Visit visit, TIntermBinary *node) override; bool visitBinary(Visit visit, TIntermBinary *node) override;
...@@ -287,15 +290,18 @@ class RemoveDynamicIndexingTraverser : public TLValueTrackingTraverser ...@@ -287,15 +290,18 @@ class RemoveDynamicIndexingTraverser : public TLValueTrackingTraverser
// where V is an array of vectors, j++ will only be evaluated once. // where V is an array of vectors, j++ will only be evaluated once.
bool mRemoveIndexSideEffectsInSubtree; bool mRemoveIndexSideEffectsInSubtree;
DynamicIndexingNodeMatcher mMatcher;
PerformanceDiagnostics *mPerfDiagnostics; PerformanceDiagnostics *mPerfDiagnostics;
}; };
RemoveDynamicIndexingTraverser::RemoveDynamicIndexingTraverser( RemoveDynamicIndexingTraverser::RemoveDynamicIndexingTraverser(
DynamicIndexingNodeMatcher &&matcher,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
PerformanceDiagnostics *perfDiagnostics) PerformanceDiagnostics *perfDiagnostics)
: TLValueTrackingTraverser(true, false, false, symbolTable), : TLValueTrackingTraverser(true, false, false, symbolTable),
mUsedTreeInsertion(false), mUsedTreeInsertion(false),
mRemoveIndexSideEffectsInSubtree(false), mRemoveIndexSideEffectsInSubtree(false),
mMatcher(matcher),
mPerfDiagnostics(perfDiagnostics) mPerfDiagnostics(perfDiagnostics)
{} {}
...@@ -376,12 +382,15 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod ...@@ -376,12 +382,15 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod
TIntermSymbol *tempIndex = CreateTempSymbolNode(indexVariable); TIntermSymbol *tempIndex = CreateTempSymbolNode(indexVariable);
queueReplacementWithParent(node, node->getRight(), tempIndex, OriginalNode::IS_DROPPED); queueReplacementWithParent(node, node->getRight(), tempIndex, OriginalNode::IS_DROPPED);
} }
else if (IntermNodePatternMatcher::IsDynamicIndexingOfNonSSBOVectorOrMatrix(node)) else if (mMatcher(node))
{ {
mPerfDiagnostics->warning(node->getLine(), if (mPerfDiagnostics)
"Performance: dynamic indexing of vectors and " {
"matrices is emulated and can be slow.", mPerfDiagnostics->warning(node->getLine(),
"[]"); "Performance: dynamic indexing of vectors and "
"matrices is emulated and can be slow.",
"[]");
}
bool write = isLValueRequiredHere(); bool write = isLValueRequiredHere();
#if defined(ANGLE_ENABLE_ASSERTS) #if defined(ANGLE_ENABLE_ASSERTS)
...@@ -430,8 +439,7 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod ...@@ -430,8 +439,7 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod
} }
TIntermBinary *leftBinary = node->getLeft()->getAsBinaryNode(); TIntermBinary *leftBinary = node->getLeft()->getAsBinaryNode();
if (leftBinary != nullptr && if (leftBinary != nullptr && mMatcher(leftBinary))
IntermNodePatternMatcher::IsDynamicIndexingOfNonSSBOVectorOrMatrix(leftBinary))
{ {
// This is a case like: // This is a case like:
// mat2 m; // mat2 m;
...@@ -520,14 +528,13 @@ void RemoveDynamicIndexingTraverser::nextIteration() ...@@ -520,14 +528,13 @@ void RemoveDynamicIndexingTraverser::nextIteration()
mRemoveIndexSideEffectsInSubtree = false; mRemoveIndexSideEffectsInSubtree = false;
} }
} // namespace bool RemoveDynamicIndexingIf(DynamicIndexingNodeMatcher &&matcher,
TCompiler *compiler,
bool RemoveDynamicIndexing(TCompiler *compiler, TIntermNode *root,
TIntermNode *root, TSymbolTable *symbolTable,
TSymbolTable *symbolTable, PerformanceDiagnostics *perfDiagnostics)
PerformanceDiagnostics *perfDiagnostics)
{ {
RemoveDynamicIndexingTraverser traverser(symbolTable, perfDiagnostics); RemoveDynamicIndexingTraverser traverser(std::move(matcher), symbolTable, perfDiagnostics);
do do
{ {
traverser.nextIteration(); traverser.nextIteration();
...@@ -546,4 +553,31 @@ bool RemoveDynamicIndexing(TCompiler *compiler, ...@@ -546,4 +553,31 @@ bool RemoveDynamicIndexing(TCompiler *compiler,
return compiler->validateAST(root); return compiler->validateAST(root);
} }
} // namespace
ANGLE_NO_DISCARD bool RemoveDynamicIndexingOfNonSSBOVectorOrMatrix(
TCompiler *compiler,
TIntermNode *root,
TSymbolTable *symbolTable,
PerformanceDiagnostics *perfDiagnostics)
{
DynamicIndexingNodeMatcher matcher = [](TIntermBinary *node) {
return IntermNodePatternMatcher::IsDynamicIndexingOfNonSSBOVectorOrMatrix(node);
};
return RemoveDynamicIndexingIf(std::move(matcher), compiler, root, symbolTable,
perfDiagnostics);
}
ANGLE_NO_DISCARD bool RemoveDynamicIndexingOfSwizzledVector(TCompiler *compiler,
TIntermNode *root,
TSymbolTable *symbolTable,
PerformanceDiagnostics *perfDiagnostics)
{
DynamicIndexingNodeMatcher matcher = [](TIntermBinary *node) {
return IntermNodePatternMatcher::IsDynamicIndexingOfSwizzledVector(node);
};
return RemoveDynamicIndexingIf(std::move(matcher), compiler, root, symbolTable,
perfDiagnostics);
}
} // namespace sh } // namespace sh
...@@ -14,18 +14,28 @@ ...@@ -14,18 +14,28 @@
#include "common/angleutils.h" #include "common/angleutils.h"
#include <functional>
namespace sh namespace sh
{ {
class TCompiler; class TCompiler;
class TIntermNode; class TIntermNode;
class TIntermBinary;
class TSymbolTable; class TSymbolTable;
class PerformanceDiagnostics; class PerformanceDiagnostics;
ANGLE_NO_DISCARD bool RemoveDynamicIndexing(TCompiler *compiler, ANGLE_NO_DISCARD bool RemoveDynamicIndexingOfNonSSBOVectorOrMatrix(
TIntermNode *root, TCompiler *compiler,
TSymbolTable *symbolTable, TIntermNode *root,
PerformanceDiagnostics *perfDiagnostics); TSymbolTable *symbolTable,
PerformanceDiagnostics *perfDiagnostics);
ANGLE_NO_DISCARD bool RemoveDynamicIndexingOfSwizzledVector(
TCompiler *compiler,
TIntermNode *root,
TSymbolTable *symbolTable,
PerformanceDiagnostics *perfDiagnostics);
} // namespace sh } // namespace sh
......
...@@ -59,6 +59,12 @@ bool IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(TIntermBinary * ...@@ -59,6 +59,12 @@ bool IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *
node->getLeft()->getBasicType() != EbtStruct; node->getLeft()->getBasicType() != EbtStruct;
} }
// static
bool IntermNodePatternMatcher::IsDynamicIndexingOfSwizzledVector(TIntermBinary *node)
{
return IsDynamicIndexingOfVectorOrMatrix(node) && node->getLeft()->getAsSwizzleNode();
}
bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *parentNode) bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *parentNode)
{ {
if ((mMask & kExpressionReturningArray) != 0) if ((mMask & kExpressionReturningArray) != 0)
......
...@@ -26,6 +26,7 @@ class IntermNodePatternMatcher ...@@ -26,6 +26,7 @@ class IntermNodePatternMatcher
public: public:
static bool IsDynamicIndexingOfNonSSBOVectorOrMatrix(TIntermBinary *node); static bool IsDynamicIndexingOfNonSSBOVectorOrMatrix(TIntermBinary *node);
static bool IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node); static bool IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node);
static bool IsDynamicIndexingOfSwizzledVector(TIntermBinary *node);
enum PatternType enum PatternType
{ {
......
...@@ -343,6 +343,11 @@ std::shared_ptr<WaitableCompileEvent> ShaderGL::compile(const gl::Context *conte ...@@ -343,6 +343,11 @@ std::shared_ptr<WaitableCompileEvent> ShaderGL::compile(const gl::Context *conte
additionalOptions |= SH_UNFOLD_SHORT_CIRCUIT; additionalOptions |= SH_UNFOLD_SHORT_CIRCUIT;
} }
if (features.removeDynamicIndexingOfSwizzledVector.enabled)
{
additionalOptions |= SH_REMOVE_DYNAMIC_INDEXING_OF_SWIZZLED_VECTOR;
}
options |= additionalOptions; options |= additionalOptions;
auto workerThreadPool = context->getWorkerThreadPool(); auto workerThreadPool = context->getWorkerThreadPool();
......
...@@ -1578,6 +1578,9 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature ...@@ -1578,6 +1578,9 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature
ANGLE_FEATURE_CONDITION( ANGLE_FEATURE_CONDITION(
features, emulatePrimitiveRestartFixedIndex, features, emulatePrimitiveRestartFixedIndex,
!functions->isAtLeastGL(gl::Version(4, 3)) && !functions->isAtLeastGLES(gl::Version(3, 0))); !functions->isAtLeastGL(gl::Version(4, 3)) && !functions->isAtLeastGLES(gl::Version(3, 0)));
ANGLE_FEATURE_CONDITION(features, removeDynamicIndexingOfSwizzledVector,
IsApple() || IsAndroid() || IsWindows());
} }
void InitializeFrontendFeatures(const FunctionsGL *functions, angle::FrontendFeatures *features) void InitializeFrontendFeatures(const FunctionsGL *functions, angle::FrontendFeatures *features)
......
...@@ -7266,6 +7266,30 @@ void main() ...@@ -7266,6 +7266,30 @@ void main()
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
} }
// Test that dynamic indexing of swizzled l-values should work.
// A simple porting of sdk/tests/conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html
TEST_P(GLSLTest_ES3, DynamicIndexingOfSwizzledLValuesShouldWork)
{
// The shader first assigns v.x to v.z (1.0)
// Then v.y to v.y (2.0)
// Then v.z to v.x (1.0)
constexpr char kFS[] = R"(#version 300 es
precision highp float;
out vec4 my_FragColor;
void main() {
vec3 v = vec3(1.0, 2.0, 3.0);
for (int i = 0; i < 3; i++) {
v.zyx[i] = v[i];
}
my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
})";
ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
EXPECT_GL_NO_ERROR();
drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// Test that multiple nested assignments are handled correctly. // Test that multiple nested assignments are handled correctly.
TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteSideEffect) TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteSideEffect)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment